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