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::{ffi, BaseParse, BaseParseFrame};
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    /// Sets the duration of the currently playing media. Subclass can use this
58    /// when it is able to determine duration and/or notices a change in the media
59    /// duration. Alternatively, if `interval` is non-zero (default), then stream
60    /// duration is determined based on estimated bitrate, and updated every `interval`
61    /// frames.
62    /// ## `fmt`
63    /// [`gst::Format`][crate::gst::Format].
64    /// ## `duration`
65    /// duration value.
66    /// ## `interval`
67    /// how often to update the duration estimate based on bitrate, or 0.
68    #[doc(alias = "gst_base_parse_set_duration")]
69    fn set_duration(&self, duration: impl FormattedValue, interval: u32) {
70        unsafe {
71            ffi::gst_base_parse_set_duration(
72                self.as_ref().to_glib_none().0,
73                duration.format().into_glib(),
74                duration.into_raw_value(),
75                interval as i32,
76            );
77        }
78    }
79
80    /// If frames per second is configured, parser can take care of buffer duration
81    /// and timestamping. When performing segment clipping, or seeking to a specific
82    /// location, a corresponding decoder might need an initial `lead_in` and a
83    /// following `lead_out` number of frames to ensure the desired segment is
84    /// entirely filled upon decoding.
85    /// ## `fps_num`
86    /// frames per second (numerator).
87    /// ## `fps_den`
88    /// frames per second (denominator).
89    /// ## `lead_in`
90    /// frames needed before a segment for subsequent decode
91    /// ## `lead_out`
92    /// frames needed after a segment
93    #[doc(alias = "gst_base_parse_set_frame_rate")]
94    fn set_frame_rate(&self, fps: gst::Fraction, lead_in: u32, lead_out: u32) {
95        let (fps_num, fps_den) = fps.into();
96        unsafe {
97            ffi::gst_base_parse_set_frame_rate(
98                self.as_ref().to_glib_none().0,
99                fps_num as u32,
100                fps_den as u32,
101                lead_in,
102                lead_out,
103            );
104        }
105    }
106
107    /// Default implementation of `GstBaseParseClass::convert`.
108    /// ## `src_format`
109    /// [`gst::Format`][crate::gst::Format] describing the source format.
110    /// ## `src_value`
111    /// Source value to be converted.
112    /// ## `dest_format`
113    /// [`gst::Format`][crate::gst::Format] defining the converted format.
114    ///
115    /// # Returns
116    ///
117    /// [`true`] if conversion was successful.
118    ///
119    /// ## `dest_value`
120    /// Pointer where the conversion result will be put.
121    #[doc(alias = "gst_base_parse_convert_default")]
122    fn convert_default<U: SpecificFormattedValueFullRange>(
123        &self,
124        src_val: impl FormattedValue,
125    ) -> Option<U> {
126        unsafe {
127            let mut dest_val = mem::MaybeUninit::uninit();
128            let ret = from_glib(ffi::gst_base_parse_convert_default(
129                self.as_ref().to_glib_none().0,
130                src_val.format().into_glib(),
131                src_val.into_raw_value(),
132                U::default_format().into_glib(),
133                dest_val.as_mut_ptr(),
134            ));
135            if ret {
136                Some(U::from_raw(U::default_format(), dest_val.assume_init()))
137            } else {
138                None
139            }
140        }
141    }
142
143    fn convert_default_generic(
144        &self,
145        src_val: impl FormattedValue,
146        dest_format: gst::Format,
147    ) -> Option<gst::GenericFormattedValue> {
148        unsafe {
149            let mut dest_val = mem::MaybeUninit::uninit();
150            let ret = from_glib(ffi::gst_base_parse_convert_default(
151                self.as_ref().to_glib_none().0,
152                src_val.format().into_glib(),
153                src_val.into_raw_value(),
154                dest_format.into_glib(),
155                dest_val.as_mut_ptr(),
156            ));
157            if ret {
158                Some(gst::GenericFormattedValue::new(
159                    dest_format,
160                    dest_val.assume_init(),
161                ))
162            } else {
163                None
164            }
165        }
166    }
167
168    /// Collects parsed data and pushes it downstream.
169    /// Source pad caps must be set when this is called.
170    ///
171    /// If `frame`'s out_buffer is set, that will be used as subsequent frame data,
172    /// and `size` amount will be flushed from the input data. The output_buffer size
173    /// can differ from the consumed size indicated by `size`.
174    ///
175    /// Otherwise, `size` samples will be taken from the input and used for output,
176    /// and the output's metadata (timestamps etc) will be taken as (optionally)
177    /// set by the subclass on `frame`'s (input) buffer (which is otherwise
178    /// ignored for any but the above purpose/information).
179    ///
180    /// Note that the latter buffer is invalidated by this call, whereas the
181    /// caller retains ownership of `frame`.
182    /// ## `frame`
183    /// a [`BaseParseFrame`][crate::BaseParseFrame]
184    /// ## `size`
185    /// consumed input data represented by frame
186    ///
187    /// # Returns
188    ///
189    /// a [`gst::FlowReturn`][crate::gst::FlowReturn] that should be escalated to caller (of caller)
190    #[doc(alias = "gst_base_parse_finish_frame")]
191    fn finish_frame(
192        &self,
193        frame: BaseParseFrame,
194        size: u32,
195    ) -> Result<gst::FlowSuccess, gst::FlowError> {
196        unsafe {
197            try_from_glib(ffi::gst_base_parse_finish_frame(
198                self.as_ref().to_glib_none().0,
199                frame.to_glib_none().0,
200                i32::try_from(size).expect("size higher than i32::MAX"),
201            ))
202        }
203    }
204}
205
206impl<O: IsA<BaseParse>> BaseParseExtManual for O {}