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