gstreamer_video/
video_encoder.rs1use std::{mem, ptr};
4
5use glib::{prelude::*, translate::*};
6
7use crate::{
8 ffi,
9 utils::HasStreamLock,
10 video_codec_state::{InNegotiation, Readable, VideoCodecState, VideoCodecStateContext},
11 VideoCodecFrame, VideoEncoder,
12};
13
14pub trait VideoEncoderExtManual: IsA<VideoEncoder> + 'static {
15 #[doc(alias = "gst_video_encoder_allocate_output_frame")]
16 fn allocate_output_frame(
17 &self,
18 frame: &mut VideoCodecFrame,
19 size: usize,
20 ) -> Result<gst::FlowSuccess, gst::FlowError> {
21 unsafe {
22 try_from_glib(ffi::gst_video_encoder_allocate_output_frame(
23 self.as_ref().to_glib_none().0,
24 frame.to_glib_none().0,
25 size,
26 ))
27 }
28 }
29
30 #[doc(alias = "get_frame")]
31 #[doc(alias = "gst_video_encoder_get_frame")]
32 fn frame(&self, frame_number: i32) -> Option<VideoCodecFrame<'_>> {
33 let frame = unsafe {
34 ffi::gst_video_encoder_get_frame(self.as_ref().to_glib_none().0, frame_number)
35 };
36
37 if frame.is_null() {
38 None
39 } else {
40 unsafe { Some(VideoCodecFrame::new(frame, self.as_ref())) }
41 }
42 }
43
44 #[doc(alias = "get_frames")]
45 #[doc(alias = "gst_video_encoder_get_frames")]
46 fn frames(&self) -> Vec<VideoCodecFrame<'_>> {
47 unsafe {
48 let frames = ffi::gst_video_encoder_get_frames(self.as_ref().to_glib_none().0);
49 let mut iter: *const glib::ffi::GList = frames;
50 let mut vec = Vec::new();
51
52 while !iter.is_null() {
53 let frame_ptr = Ptr::from((*iter).data);
54 let frame = VideoCodecFrame::new(frame_ptr, self.as_ref());
56 vec.push(frame);
57 iter = (*iter).next;
58 }
59
60 glib::ffi::g_list_free(frames);
61 vec
62 }
63 }
64
65 #[doc(alias = "get_oldest_frame")]
66 #[doc(alias = "gst_video_encoder_get_oldest_frame")]
67 fn oldest_frame(&self) -> Option<VideoCodecFrame<'_>> {
68 let frame =
69 unsafe { ffi::gst_video_encoder_get_oldest_frame(self.as_ref().to_glib_none().0) };
70
71 if frame.is_null() {
72 None
73 } else {
74 unsafe { Some(VideoCodecFrame::new(frame, self.as_ref())) }
75 }
76 }
77
78 #[doc(alias = "get_allocator")]
79 #[doc(alias = "gst_video_encoder_get_allocator")]
80 fn allocator(&self) -> (Option<gst::Allocator>, gst::AllocationParams) {
81 unsafe {
82 let mut allocator = ptr::null_mut();
83 let mut params = mem::MaybeUninit::uninit();
84 ffi::gst_video_encoder_get_allocator(
85 self.as_ref().to_glib_none().0,
86 &mut allocator,
87 params.as_mut_ptr(),
88 );
89 (from_glib_full(allocator), params.assume_init().into())
90 }
91 }
92
93 #[cfg(feature = "v1_18")]
94 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
95 #[doc(alias = "gst_video_encoder_finish_subframe")]
96 fn finish_subframe(&self, frame: &VideoCodecFrame) -> Result<gst::FlowSuccess, gst::FlowError> {
97 unsafe {
98 try_from_glib(ffi::gst_video_encoder_finish_subframe(
99 self.as_ref().to_glib_none().0,
100 frame.to_glib_none().0,
101 ))
102 }
103 }
104
105 #[doc(alias = "get_latency")]
106 #[doc(alias = "gst_video_encoder_get_latency")]
107 fn latency(&self) -> (gst::ClockTime, Option<gst::ClockTime>) {
108 let mut min_latency = gst::ffi::GST_CLOCK_TIME_NONE;
109 let mut max_latency = gst::ffi::GST_CLOCK_TIME_NONE;
110
111 unsafe {
112 ffi::gst_video_encoder_get_latency(
113 self.as_ref().to_glib_none().0,
114 &mut min_latency,
115 &mut max_latency,
116 );
117
118 (
119 try_from_glib(min_latency).expect("undefined min_latency"),
120 from_glib(max_latency),
121 )
122 }
123 }
124
125 #[doc(alias = "gst_video_encoder_set_latency")]
126 fn set_latency(
127 &self,
128 min_latency: gst::ClockTime,
129 max_latency: impl Into<Option<gst::ClockTime>>,
130 ) {
131 unsafe {
132 ffi::gst_video_encoder_set_latency(
133 self.as_ref().to_glib_none().0,
134 min_latency.into_glib(),
135 max_latency.into().into_glib(),
136 );
137 }
138 }
139 #[doc(alias = "get_output_state")]
140 #[doc(alias = "gst_video_encoder_get_output_state")]
141 fn output_state(&self) -> Option<VideoCodecState<'static, Readable>> {
142 let state =
143 unsafe { ffi::gst_video_encoder_get_output_state(self.as_ref().to_glib_none().0) };
144
145 if state.is_null() {
146 None
147 } else {
148 unsafe { Some(VideoCodecState::<Readable>::new(state)) }
149 }
150 }
151
152 #[doc(alias = "gst_video_encoder_set_output_state")]
153 fn set_output_state(
154 &self,
155 caps: gst::Caps,
156 reference: Option<&VideoCodecState<Readable>>,
157 ) -> Result<VideoCodecState<'_, InNegotiation<'_>>, gst::FlowError> {
158 let state = unsafe {
159 let reference = match reference {
160 Some(reference) => reference.as_mut_ptr(),
161 None => ptr::null_mut(),
162 };
163 ffi::gst_video_encoder_set_output_state(
164 self.as_ref().to_glib_none().0,
165 caps.into_glib_ptr(),
166 reference,
167 )
168 };
169
170 if state.is_null() {
171 Err(gst::FlowError::NotNegotiated)
172 } else {
173 unsafe { Ok(VideoCodecState::<InNegotiation>::new(state, self.as_ref())) }
174 }
175 }
176
177 #[doc(alias = "gst_video_encoder_negotiate")]
178 fn negotiate<'a>(
179 &'a self,
180 output_state: VideoCodecState<'a, InNegotiation<'a>>,
181 ) -> Result<(), gst::FlowError> {
182 let self_ptr = self.to_glib_none().0 as *const gst::ffi::GstElement;
184 assert_eq!(output_state.context.element_as_ptr(), self_ptr);
185
186 let ret = unsafe {
187 from_glib(ffi::gst_video_encoder_negotiate(
188 self.as_ref().to_glib_none().0,
189 ))
190 };
191 if ret {
192 Ok(())
193 } else {
194 Err(gst::FlowError::NotNegotiated)
195 }
196 }
197
198 #[doc(alias = "gst_video_encoder_set_headers")]
199 fn set_headers(&self, headers: impl IntoIterator<Item = gst::Buffer>) {
200 unsafe {
201 ffi::gst_video_encoder_set_headers(
202 self.as_ref().to_glib_none().0,
203 headers
204 .into_iter()
205 .collect::<glib::List<_>>()
206 .into_glib_ptr(),
207 );
208 }
209 }
210
211 fn sink_pad(&self) -> &gst::Pad {
212 unsafe {
213 let elt = &*(self.as_ptr() as *const ffi::GstVideoEncoder);
214 &*(&elt.sinkpad as *const *mut gst::ffi::GstPad as *const gst::Pad)
215 }
216 }
217
218 fn src_pad(&self) -> &gst::Pad {
219 unsafe {
220 let elt = &*(self.as_ptr() as *const ffi::GstVideoEncoder);
221 &*(&elt.srcpad as *const *mut gst::ffi::GstPad as *const gst::Pad)
222 }
223 }
224
225 fn input_segment(&self) -> gst::Segment {
226 unsafe {
227 let ptr: &ffi::GstVideoDecoder = &*(self.as_ptr() as *const _);
228 glib::ffi::g_rec_mutex_lock(mut_override(&ptr.stream_lock));
229 let segment = ptr.input_segment;
230 glib::ffi::g_rec_mutex_unlock(mut_override(&ptr.stream_lock));
231 from_glib_none(&segment as *const gst::ffi::GstSegment)
232 }
233 }
234
235 fn output_segment(&self) -> gst::Segment {
236 unsafe {
237 let ptr: &ffi::GstVideoDecoder = &*(self.as_ptr() as *const _);
238 glib::ffi::g_rec_mutex_lock(mut_override(&ptr.stream_lock));
239 let segment = ptr.output_segment;
240 glib::ffi::g_rec_mutex_unlock(mut_override(&ptr.stream_lock));
241 from_glib_none(&segment as *const gst::ffi::GstSegment)
242 }
243 }
244}
245
246impl<O: IsA<VideoEncoder>> VideoEncoderExtManual for O {}
247
248impl HasStreamLock for VideoEncoder {
249 fn stream_lock(&self) -> *mut glib::ffi::GRecMutex {
250 let encoder_sys: *const ffi::GstVideoEncoder = self.to_glib_none().0;
251 unsafe { mut_override(&(*encoder_sys).stream_lock) }
252 }
253
254 fn element_as_ptr(&self) -> *const gst::ffi::GstElement {
255 self.as_ptr() as *const gst::ffi::GstElement
256 }
257}