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