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 {}