gstreamer_video/
video_encoder.rs1use std::{mem, ptr};
4
5use glib::{prelude::*, translate::*};
6
7use crate::{
8 VideoCodecFrame, VideoEncoder, ffi,
9 utils::HasStreamLock,
10 video_codec_state::{InNegotiation, Readable, VideoCodecState, VideoCodecStateContext},
11};
12
13pub trait VideoEncoderExtManual: IsA<VideoEncoder> + 'static {
14 #[doc(alias = "gst_video_encoder_allocate_output_frame")]
29 fn allocate_output_frame(
30 &self,
31 frame: &mut VideoCodecFrame,
32 size: usize,
33 ) -> Result<gst::FlowSuccess, gst::FlowError> {
34 unsafe {
35 try_from_glib(ffi::gst_video_encoder_allocate_output_frame(
36 self.as_ref().to_glib_none().0,
37 frame.to_glib_none().0,
38 size,
39 ))
40 }
41 }
42
43 #[doc(alias = "get_frame")]
51 #[doc(alias = "gst_video_encoder_get_frame")]
52 fn frame(&self, frame_number: i32) -> Option<VideoCodecFrame<'_>> {
53 let frame = unsafe {
54 ffi::gst_video_encoder_get_frame(self.as_ref().to_glib_none().0, frame_number)
55 };
56
57 if frame.is_null() {
58 None
59 } else {
60 unsafe { Some(VideoCodecFrame::new(frame, self.as_ref())) }
61 }
62 }
63
64 #[doc(alias = "get_frames")]
70 #[doc(alias = "gst_video_encoder_get_frames")]
71 fn frames(&self) -> Vec<VideoCodecFrame<'_>> {
72 unsafe {
73 let frames = ffi::gst_video_encoder_get_frames(self.as_ref().to_glib_none().0);
74 let mut iter: *const glib::ffi::GList = frames;
75 let mut vec = Vec::new();
76
77 while !iter.is_null() {
78 let frame_ptr = Ptr::from((*iter).data);
79 let frame = VideoCodecFrame::new(frame_ptr, self.as_ref());
81 vec.push(frame);
82 iter = (*iter).next;
83 }
84
85 glib::ffi::g_list_free(frames);
86 vec
87 }
88 }
89
90 #[doc(alias = "get_oldest_frame")]
96 #[doc(alias = "gst_video_encoder_get_oldest_frame")]
97 fn oldest_frame(&self) -> Option<VideoCodecFrame<'_>> {
98 let frame =
99 unsafe { ffi::gst_video_encoder_get_oldest_frame(self.as_ref().to_glib_none().0) };
100
101 if frame.is_null() {
102 None
103 } else {
104 unsafe { Some(VideoCodecFrame::new(frame, self.as_ref())) }
105 }
106 }
107
108 #[doc(alias = "get_allocator")]
124 #[doc(alias = "gst_video_encoder_get_allocator")]
125 fn allocator(&self) -> (Option<gst::Allocator>, gst::AllocationParams) {
126 unsafe {
127 let mut allocator = ptr::null_mut();
128 let mut params = mem::MaybeUninit::uninit();
129 ffi::gst_video_encoder_get_allocator(
130 self.as_ref().to_glib_none().0,
131 &mut allocator,
132 params.as_mut_ptr(),
133 );
134 (from_glib_full(allocator), params.assume_init().into())
135 }
136 }
137
138 #[cfg(feature = "v1_18")]
147 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
148 #[doc(alias = "gst_video_encoder_finish_subframe")]
149 fn finish_subframe(&self, frame: &VideoCodecFrame) -> Result<gst::FlowSuccess, gst::FlowError> {
150 unsafe {
151 try_from_glib(ffi::gst_video_encoder_finish_subframe(
152 self.as_ref().to_glib_none().0,
153 frame.to_glib_none().0,
154 ))
155 }
156 }
157
158 #[doc(alias = "get_latency")]
172 #[doc(alias = "gst_video_encoder_get_latency")]
173 fn latency(&self) -> (gst::ClockTime, Option<gst::ClockTime>) {
174 let mut min_latency = gst::ffi::GST_CLOCK_TIME_NONE;
175 let mut max_latency = gst::ffi::GST_CLOCK_TIME_NONE;
176
177 unsafe {
178 ffi::gst_video_encoder_get_latency(
179 self.as_ref().to_glib_none().0,
180 &mut min_latency,
181 &mut max_latency,
182 );
183
184 (
185 try_from_glib(min_latency).expect("undefined min_latency"),
186 from_glib(max_latency),
187 )
188 }
189 }
190
191 #[doc(alias = "gst_video_encoder_set_latency")]
199 fn set_latency(
200 &self,
201 min_latency: gst::ClockTime,
202 max_latency: impl Into<Option<gst::ClockTime>>,
203 ) {
204 unsafe {
205 ffi::gst_video_encoder_set_latency(
206 self.as_ref().to_glib_none().0,
207 min_latency.into_glib(),
208 max_latency.into().into_glib(),
209 );
210 }
211 }
212 #[doc(alias = "get_output_state")]
218 #[doc(alias = "gst_video_encoder_get_output_state")]
219 fn output_state(&self) -> Option<VideoCodecState<'static, Readable>> {
220 let state =
221 unsafe { ffi::gst_video_encoder_get_output_state(self.as_ref().to_glib_none().0) };
222
223 if state.is_null() {
224 None
225 } else {
226 unsafe { Some(VideoCodecState::<Readable>::new(state)) }
227 }
228 }
229
230 #[doc(alias = "gst_video_encoder_set_output_state")]
257 fn set_output_state(
258 &self,
259 caps: gst::Caps,
260 reference: Option<&VideoCodecState<Readable>>,
261 ) -> Result<VideoCodecState<'_, InNegotiation<'_>>, gst::FlowError> {
262 let state = unsafe {
263 let reference = match reference {
264 Some(reference) => reference.as_mut_ptr(),
265 None => ptr::null_mut(),
266 };
267 ffi::gst_video_encoder_set_output_state(
268 self.as_ref().to_glib_none().0,
269 caps.into_glib_ptr(),
270 reference,
271 )
272 };
273
274 if state.is_null() {
275 Err(gst::FlowError::NotNegotiated)
276 } else {
277 unsafe { Ok(VideoCodecState::<InNegotiation>::new(state, self.as_ref())) }
278 }
279 }
280
281 #[doc(alias = "gst_video_encoder_negotiate")]
289 fn negotiate<'a>(
290 &'a self,
291 output_state: VideoCodecState<'a, InNegotiation<'a>>,
292 ) -> Result<(), gst::FlowError> {
293 let self_ptr = self.to_glib_none().0 as *const gst::ffi::GstElement;
295 assert_eq!(output_state.context.element_as_ptr(), self_ptr);
296
297 let ret = unsafe {
298 from_glib(ffi::gst_video_encoder_negotiate(
299 self.as_ref().to_glib_none().0,
300 ))
301 };
302 if ret {
303 Ok(())
304 } else {
305 Err(gst::FlowError::NotNegotiated)
306 }
307 }
308
309 #[doc(alias = "gst_video_encoder_set_headers")]
313 fn set_headers(&self, headers: impl IntoIterator<Item = gst::Buffer>) {
314 unsafe {
315 ffi::gst_video_encoder_set_headers(
316 self.as_ref().to_glib_none().0,
317 headers
318 .into_iter()
319 .collect::<glib::List<_>>()
320 .into_glib_ptr(),
321 );
322 }
323 }
324
325 fn sink_pad(&self) -> &gst::Pad {
326 unsafe {
327 let elt = &*(self.as_ptr() as *const ffi::GstVideoEncoder);
328 &*(&elt.sinkpad as *const *mut gst::ffi::GstPad as *const gst::Pad)
329 }
330 }
331
332 fn src_pad(&self) -> &gst::Pad {
333 unsafe {
334 let elt = &*(self.as_ptr() as *const ffi::GstVideoEncoder);
335 &*(&elt.srcpad as *const *mut gst::ffi::GstPad as *const gst::Pad)
336 }
337 }
338
339 fn input_segment(&self) -> gst::Segment {
340 unsafe {
341 let ptr: &ffi::GstVideoDecoder = &*(self.as_ptr() as *const _);
342 glib::ffi::g_rec_mutex_lock(mut_override(&ptr.stream_lock));
343 let segment = ptr.input_segment;
344 glib::ffi::g_rec_mutex_unlock(mut_override(&ptr.stream_lock));
345 from_glib_none(&segment as *const gst::ffi::GstSegment)
346 }
347 }
348
349 fn output_segment(&self) -> gst::Segment {
350 unsafe {
351 let ptr: &ffi::GstVideoDecoder = &*(self.as_ptr() as *const _);
352 glib::ffi::g_rec_mutex_lock(mut_override(&ptr.stream_lock));
353 let segment = ptr.output_segment;
354 glib::ffi::g_rec_mutex_unlock(mut_override(&ptr.stream_lock));
355 from_glib_none(&segment as *const gst::ffi::GstSegment)
356 }
357 }
358}
359
360impl<O: IsA<VideoEncoder>> VideoEncoderExtManual for O {}
361
362impl HasStreamLock for VideoEncoder {
363 fn stream_lock(&self) -> *mut glib::ffi::GRecMutex {
364 let encoder_sys: *const ffi::GstVideoEncoder = self.to_glib_none().0;
365 unsafe { mut_override(&(*encoder_sys).stream_lock) }
366 }
367
368 fn element_as_ptr(&self) -> *const gst::ffi::GstElement {
369 self.as_ptr() as *const gst::ffi::GstElement
370 }
371}