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