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