Skip to main content

gstreamer_base/
base_parse.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::mem;
4
5use glib::{prelude::*, translate::*};
6use gst::{
7    format::{FormattedValue, SpecificFormattedValueFullRange},
8    prelude::*,
9};
10
11use crate::{BaseParse, BaseParseFrame, ffi};
12
13pub trait BaseParseExtManual: IsA<BaseParse> + 'static {
14    #[doc(alias = "get_sink_pad")]
15    fn sink_pad(&self) -> &gst::Pad {
16        unsafe {
17            let elt = &*(self.as_ptr() as *const ffi::GstBaseParse);
18            &*(&elt.sinkpad as *const *mut gst::ffi::GstPad as *const gst::Pad)
19        }
20    }
21
22    #[doc(alias = "get_src_pad")]
23    fn src_pad(&self) -> &gst::Pad {
24        unsafe {
25            let elt = &*(self.as_ptr() as *const ffi::GstBaseParse);
26            &*(&elt.srcpad as *const *mut gst::ffi::GstPad as *const gst::Pad)
27        }
28    }
29
30    fn segment(&self) -> gst::Segment {
31        unsafe {
32            let ptr: &ffi::GstBaseParse = &*(self.as_ptr() as *const _);
33            let sinkpad = self.sink_pad();
34            let _guard = sinkpad.stream_lock();
35            from_glib_none(&ptr.segment as *const gst::ffi::GstSegment)
36        }
37    }
38
39    fn lost_sync(&self) -> bool {
40        unsafe {
41            let ptr: &ffi::GstBaseParse = &*(self.as_ptr() as *const _);
42            let sinkpad = self.sink_pad();
43            let _guard = sinkpad.stream_lock();
44            ptr.flags & ffi::GST_BASE_PARSE_FLAG_LOST_SYNC as u32 != 0
45        }
46    }
47
48    fn is_draining(&self) -> bool {
49        unsafe {
50            let ptr: &ffi::GstBaseParse = &*(self.as_ptr() as *const _);
51            let sinkpad = self.sink_pad();
52            let _guard = sinkpad.stream_lock();
53            ptr.flags & ffi::GST_BASE_PARSE_FLAG_DRAINING as u32 != 0
54        }
55    }
56
57    /// READY state changes. Subclasses must
58    /// call this function from `GstBaseParseClass::start` if they want to set a static value.
59    /// ## `fmt`
60    /// [`gst::Format`][crate::gst::Format].
61    /// ## `duration`
62    /// duration value.
63    /// ## `interval`
64    /// how often to update the duration estimate based on bitrate, or 0.
65    #[doc(alias = "gst_base_parse_set_duration")]
66    fn set_duration(&self, duration: impl FormattedValue, interval: u32) {
67        unsafe {
68            ffi::gst_base_parse_set_duration(
69                self.as_ref().to_glib_none().0,
70                duration.format().into_glib(),
71                duration.into_raw_value(),
72                interval as i32,
73            );
74        }
75    }
76
77    /// READY state changes. Subclasses must
78    /// call this function from `GstBaseParseClass::start` if they want to set a static value.
79    /// ## `fps_num`
80    /// frames per second (numerator).
81    /// ## `fps_den`
82    /// frames per second (denominator).
83    /// ## `lead_in`
84    /// frames needed before a segment for subsequent decode
85    /// ## `lead_out`
86    /// frames needed after a segment
87    #[doc(alias = "gst_base_parse_set_frame_rate")]
88    fn set_frame_rate(&self, fps: gst::Fraction, lead_in: u32, lead_out: u32) {
89        let (fps_num, fps_den) = fps.into();
90        unsafe {
91            ffi::gst_base_parse_set_frame_rate(
92                self.as_ref().to_glib_none().0,
93                fps_num as u32,
94                fps_den as u32,
95                lead_in,
96                lead_out,
97            );
98        }
99    }
100
101    /// Default implementation of `GstBaseParseClass::convert`.
102    /// ## `src_format`
103    /// [`gst::Format`][crate::gst::Format] describing the source format.
104    /// ## `src_value`
105    /// Source value to be converted.
106    /// ## `dest_format`
107    /// [`gst::Format`][crate::gst::Format] defining the converted format.
108    ///
109    /// # Returns
110    ///
111    /// [`true`] if conversion was successful.
112    ///
113    /// ## `dest_value`
114    /// Pointer where the conversion result will be put.
115    #[doc(alias = "gst_base_parse_convert_default")]
116    fn convert_default<U: SpecificFormattedValueFullRange>(
117        &self,
118        src_val: impl FormattedValue,
119    ) -> Option<U> {
120        unsafe {
121            let mut dest_val = mem::MaybeUninit::uninit();
122            let ret = from_glib(ffi::gst_base_parse_convert_default(
123                self.as_ref().to_glib_none().0,
124                src_val.format().into_glib(),
125                src_val.into_raw_value(),
126                U::default_format().into_glib(),
127                dest_val.as_mut_ptr(),
128            ));
129            if ret {
130                Some(U::from_raw(U::default_format(), dest_val.assume_init()))
131            } else {
132                None
133            }
134        }
135    }
136
137    fn convert_default_generic(
138        &self,
139        src_val: impl FormattedValue,
140        dest_format: gst::Format,
141    ) -> Option<gst::GenericFormattedValue> {
142        unsafe {
143            let mut dest_val = mem::MaybeUninit::uninit();
144            let ret = from_glib(ffi::gst_base_parse_convert_default(
145                self.as_ref().to_glib_none().0,
146                src_val.format().into_glib(),
147                src_val.into_raw_value(),
148                dest_format.into_glib(),
149                dest_val.as_mut_ptr(),
150            ));
151            if ret {
152                Some(gst::GenericFormattedValue::new(
153                    dest_format,
154                    dest_val.assume_init(),
155                ))
156            } else {
157                None
158            }
159        }
160    }
161
162    /// Collects parsed data and pushes it downstream.
163    /// Source pad caps must be set when this is called.
164    ///
165    /// If `frame`'s out_buffer is set, that will be used as subsequent frame data,
166    /// and `size` amount will be flushed from the input data. The output_buffer size
167    /// can differ from the consumed size indicated by `size`.
168    ///
169    /// Otherwise, `size` samples will be taken from the input and used for output,
170    /// and the output's metadata (timestamps etc) will be taken as (optionally)
171    /// set by the subclass on `frame`'s (input) buffer (which is otherwise
172    /// ignored for any but the above purpose/information).
173    ///
174    /// Note that the latter buffer is invalidated by this call, whereas the
175    /// caller retains ownership of `frame`.
176    /// ## `frame`
177    /// a [`BaseParseFrame`][crate::BaseParseFrame]
178    /// ## `size`
179    /// consumed input data represented by frame
180    ///
181    /// # Returns
182    ///
183    /// a [`gst::FlowReturn`][crate::gst::FlowReturn] that should be escalated to caller (of caller)
184    #[doc(alias = "gst_base_parse_finish_frame")]
185    fn finish_frame(
186        &self,
187        frame: BaseParseFrame,
188        size: u32,
189    ) -> Result<gst::FlowSuccess, gst::FlowError> {
190        unsafe {
191            try_from_glib(ffi::gst_base_parse_finish_frame(
192                self.as_ref().to_glib_none().0,
193                frame.to_glib_none().0,
194                i32::try_from(size).expect("size higher than i32::MAX"),
195            ))
196        }
197    }
198}
199
200impl<O: IsA<BaseParse>> BaseParseExtManual for O {}