gstreamer_video/subclass/
video_aggregator_pad.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{mem, ptr};
4
5use glib::translate::*;
6use gst_base::{prelude::*, subclass::prelude::*};
7
8use crate::{ffi, subclass::AggregateFramesToken, VideoAggregator, VideoAggregatorPad};
9
10pub trait VideoAggregatorPadImpl: VideoAggregatorPadImplExt + AggregatorPadImpl {
11    fn update_conversion_info(&self) {
12        self.parent_update_conversion_info()
13    }
14
15    fn prepare_frame(
16        &self,
17        aggregator: &crate::VideoAggregator,
18        token: &AggregateFramesToken,
19        buffer: &gst::Buffer,
20    ) -> Option<crate::VideoFrame<crate::video_frame::Readable>> {
21        self.parent_prepare_frame(aggregator, token, buffer)
22    }
23
24    fn clean_frame(
25        &self,
26        aggregator: &crate::VideoAggregator,
27        token: &AggregateFramesToken,
28        frame: Option<crate::VideoFrame<crate::video_frame::Readable>>,
29    ) {
30        self.parent_clean_frame(aggregator, token, frame)
31    }
32}
33
34mod sealed {
35    pub trait Sealed {}
36    impl<T: super::VideoAggregatorPadImplExt> Sealed for T {}
37}
38
39pub trait VideoAggregatorPadImplExt: ObjectSubclass + sealed::Sealed {
40    fn parent_update_conversion_info(&self) {
41        unsafe {
42            let data = Self::type_data();
43            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoAggregatorPadClass;
44            if let Some(f) = (*parent_class).update_conversion_info {
45                f(self
46                    .obj()
47                    .unsafe_cast_ref::<VideoAggregatorPad>()
48                    .to_glib_none()
49                    .0);
50            }
51        }
52    }
53
54    fn parent_prepare_frame(
55        &self,
56        aggregator: &crate::VideoAggregator,
57        token: &AggregateFramesToken,
58        buffer: &gst::Buffer,
59    ) -> Option<crate::VideoFrame<crate::video_frame::Readable>> {
60        assert_eq!(aggregator.as_ptr(), token.0.as_ptr());
61
62        unsafe {
63            let data = Self::type_data();
64            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoAggregatorPadClass;
65            if let Some(f) = (*parent_class).prepare_frame {
66                let mut prepared_frame = mem::MaybeUninit::zeroed();
67
68                f(
69                    self.obj()
70                        .unsafe_cast_ref::<VideoAggregatorPad>()
71                        .to_glib_none()
72                        .0,
73                    aggregator.to_glib_none().0,
74                    buffer.as_mut_ptr(),
75                    prepared_frame.as_mut_ptr(),
76                );
77
78                let prepared_frame = prepared_frame.assume_init();
79                if prepared_frame.buffer.is_null() {
80                    None
81                } else {
82                    Some(crate::VideoFrame::from_glib_full(prepared_frame))
83                }
84            } else {
85                None
86            }
87        }
88    }
89
90    fn parent_clean_frame(
91        &self,
92        aggregator: &crate::VideoAggregator,
93        token: &AggregateFramesToken,
94        frame: Option<crate::VideoFrame<crate::video_frame::Readable>>,
95    ) {
96        assert_eq!(aggregator.as_ptr(), token.0.as_ptr());
97
98        unsafe {
99            let data = Self::type_data();
100            let parent_class = data.as_ref().parent_class() as *mut ffi::GstVideoAggregatorPadClass;
101            if let Some(f) = (*parent_class).clean_frame {
102                let mut prepared_frame = if let Some(frame) = frame {
103                    frame.into_raw()
104                } else {
105                    mem::zeroed()
106                };
107
108                f(
109                    self.obj()
110                        .unsafe_cast_ref::<VideoAggregatorPad>()
111                        .to_glib_none()
112                        .0,
113                    aggregator.to_glib_none().0,
114                    &mut prepared_frame,
115                );
116            }
117        }
118    }
119}
120
121impl<T: VideoAggregatorPadImpl> VideoAggregatorPadImplExt for T {}
122
123unsafe impl<T: VideoAggregatorPadImpl> IsSubclassable<T> for VideoAggregatorPad {
124    fn class_init(klass: &mut glib::Class<Self>) {
125        Self::parent_class_init::<T>(klass);
126
127        let klass = klass.as_mut();
128        klass.update_conversion_info = Some(video_aggregator_pad_update_conversion_info::<T>);
129        klass.prepare_frame = Some(video_aggregator_pad_prepare_frame::<T>);
130        klass.clean_frame = Some(video_aggregator_pad_clean_frame::<T>);
131    }
132}
133
134unsafe extern "C" fn video_aggregator_pad_update_conversion_info<T: VideoAggregatorPadImpl>(
135    ptr: *mut ffi::GstVideoAggregatorPad,
136) {
137    let instance = &*(ptr as *mut T::Instance);
138    let imp = instance.imp();
139
140    imp.update_conversion_info();
141}
142
143unsafe extern "C" fn video_aggregator_pad_prepare_frame<T: VideoAggregatorPadImpl>(
144    ptr: *mut ffi::GstVideoAggregatorPad,
145    aggregator: *mut ffi::GstVideoAggregator,
146    buffer: *mut gst::ffi::GstBuffer,
147    prepared_frame: *mut ffi::GstVideoFrame,
148) -> glib::ffi::gboolean {
149    let instance = &*(ptr as *mut T::Instance);
150    let imp = instance.imp();
151    let aggregator: Borrowed<VideoAggregator> = from_glib_borrow(aggregator);
152
153    let token = AggregateFramesToken(&aggregator);
154
155    match imp.prepare_frame(&aggregator, &token, &from_glib_borrow(buffer)) {
156        Some(frame) => {
157            *prepared_frame = frame.into_raw();
158        }
159        None => {
160            ptr::write(prepared_frame, mem::zeroed());
161        }
162    }
163
164    glib::ffi::GTRUE
165}
166
167unsafe extern "C" fn video_aggregator_pad_clean_frame<T: VideoAggregatorPadImpl>(
168    ptr: *mut ffi::GstVideoAggregatorPad,
169    aggregator: *mut ffi::GstVideoAggregator,
170    prepared_frame: *mut ffi::GstVideoFrame,
171) {
172    let instance = &*(ptr as *mut T::Instance);
173    let imp = instance.imp();
174    let aggregator: Borrowed<VideoAggregator> = from_glib_borrow(aggregator);
175
176    let token = AggregateFramesToken(&aggregator);
177
178    let frame = if (*prepared_frame).buffer.is_null() {
179        None
180    } else {
181        let frame = crate::VideoFrame::from_glib_full(*prepared_frame);
182        ptr::write(prepared_frame, mem::zeroed());
183        Some(frame)
184    };
185
186    imp.clean_frame(&aggregator, &token, frame);
187}