1use std::{fmt, mem};
4
5use crate::ffi;
6use glib::translate::*;
7
8gst::mini_object_wrapper!(
9 VideoOverlayRectangle,
10 VideoOverlayRectangleRef,
11 ffi::GstVideoOverlayRectangle,
12 || ffi::gst_video_overlay_rectangle_get_type()
13);
14
15impl fmt::Debug for VideoOverlayRectangle {
16 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
17 VideoOverlayRectangleRef::fmt(self, f)
18 }
19}
20
21impl fmt::Debug for VideoOverlayRectangleRef {
22 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
23 f.debug_struct("VideoOverlayRectangle")
24 .field("flags", &self.flags())
25 .field("global_alpha", &self.global_alpha())
26 .field("render_rectangle", &self.render_rectangle())
27 .finish()
28 }
29}
30
31impl VideoOverlayRectangle {
32 #[doc(alias = "gst_video_overlay_rectangle_new_raw")]
33 pub fn new_raw(
34 buffer: &gst::Buffer,
35 render_x: i32,
36 render_y: i32,
37 render_width: u32,
38 render_height: u32,
39 flags: crate::VideoOverlayFormatFlags,
40 ) -> Self {
41 skip_assert_initialized!();
42 assert!(buffer.meta::<crate::VideoMeta>().is_some());
43 unsafe {
44 from_glib_full(ffi::gst_video_overlay_rectangle_new_raw(
45 buffer.to_glib_none().0,
46 render_x,
47 render_y,
48 render_width,
49 render_height,
50 flags.into_glib(),
51 ))
52 }
53 }
54}
55
56impl VideoOverlayRectangleRef {
57 #[doc(alias = "get_flags")]
58 #[doc(alias = "gst_video_overlay_rectangle_get_flags")]
59 pub fn flags(&self) -> crate::VideoOverlayFormatFlags {
60 unsafe {
61 from_glib(ffi::gst_video_overlay_rectangle_get_flags(
62 self.as_mut_ptr(),
63 ))
64 }
65 }
66
67 #[doc(alias = "get_global_alpha")]
68 #[doc(alias = "gst_video_overlay_rectangle_get_global_alpha")]
69 pub fn global_alpha(&self) -> f32 {
70 unsafe { ffi::gst_video_overlay_rectangle_get_global_alpha(self.as_mut_ptr()) }
71 }
72
73 #[doc(alias = "gst_video_overlay_rectangle_set_global_alpha")]
74 pub fn set_global_alpha(&mut self, alpha: f32) {
75 unsafe { ffi::gst_video_overlay_rectangle_set_global_alpha(self.as_mut_ptr(), alpha) }
76 }
77
78 #[doc(alias = "get_seqnum")]
79 #[doc(alias = "gst_video_overlay_rectangle_get_seqnum")]
80 pub fn seqnum(&self) -> u32 {
81 unsafe { ffi::gst_video_overlay_rectangle_get_seqnum(self.as_mut_ptr()) }
82 }
83
84 #[doc(alias = "get_render_rectangle")]
85 #[doc(alias = "gst_video_overlay_rectangle_get_render_rectangle")]
86 pub fn render_rectangle(&self) -> (i32, i32, u32, u32) {
87 unsafe {
88 let mut render_x = mem::MaybeUninit::uninit();
89 let mut render_y = mem::MaybeUninit::uninit();
90 let mut render_width = mem::MaybeUninit::uninit();
91 let mut render_height = mem::MaybeUninit::uninit();
92
93 ffi::gst_video_overlay_rectangle_get_render_rectangle(
94 self.as_mut_ptr(),
95 render_x.as_mut_ptr(),
96 render_y.as_mut_ptr(),
97 render_width.as_mut_ptr(),
98 render_height.as_mut_ptr(),
99 );
100
101 (
102 render_x.assume_init(),
103 render_y.assume_init(),
104 render_width.assume_init(),
105 render_height.assume_init(),
106 )
107 }
108 }
109
110 #[doc(alias = "gst_video_overlay_rectangle_set_render_rectangle")]
111 pub fn set_render_rectangle(
112 &mut self,
113 render_x: i32,
114 render_y: i32,
115 render_width: u32,
116 render_height: u32,
117 ) {
118 unsafe {
119 ffi::gst_video_overlay_rectangle_set_render_rectangle(
120 self.as_mut_ptr(),
121 render_x,
122 render_y,
123 render_width,
124 render_height,
125 )
126 }
127 }
128
129 #[doc(alias = "get_pixels_unscaled_raw")]
130 #[doc(alias = "gst_video_overlay_rectangle_get_pixels_unscaled_raw")]
131 pub fn pixels_unscaled_raw(&self, flags: crate::VideoOverlayFormatFlags) -> gst::Buffer {
132 unsafe {
133 from_glib_none(ffi::gst_video_overlay_rectangle_get_pixels_unscaled_raw(
134 self.as_mut_ptr(),
135 flags.into_glib(),
136 ))
137 }
138 }
139
140 #[doc(alias = "get_pixels_unscaled_ayuv")]
141 #[doc(alias = "gst_video_overlay_rectangle_get_pixels_unscaled_ayuv")]
142 pub fn pixels_unscaled_ayuv(&self, flags: crate::VideoOverlayFormatFlags) -> gst::Buffer {
143 unsafe {
144 from_glib_none(ffi::gst_video_overlay_rectangle_get_pixels_unscaled_ayuv(
145 self.as_mut_ptr(),
146 flags.into_glib(),
147 ))
148 }
149 }
150
151 #[doc(alias = "get_pixels_unscaled_argb")]
152 #[doc(alias = "gst_video_overlay_rectangle_get_pixels_unscaled_argb")]
153 pub fn pixels_unscaled_argb(&self, flags: crate::VideoOverlayFormatFlags) -> gst::Buffer {
154 unsafe {
155 from_glib_none(ffi::gst_video_overlay_rectangle_get_pixels_unscaled_argb(
156 self.as_mut_ptr(),
157 flags.into_glib(),
158 ))
159 }
160 }
161
162 #[doc(alias = "get_pixels_raw")]
163 #[doc(alias = "gst_video_overlay_rectangle_get_pixels_raw")]
164 pub fn pixels_raw(&self, flags: crate::VideoOverlayFormatFlags) -> gst::Buffer {
165 unsafe {
166 from_glib_none(ffi::gst_video_overlay_rectangle_get_pixels_raw(
167 self.as_mut_ptr(),
168 flags.into_glib(),
169 ))
170 }
171 }
172
173 #[doc(alias = "get_pixels_ayuv")]
174 #[doc(alias = "gst_video_overlay_rectangle_get_pixels_ayuv")]
175 pub fn pixels_ayuv(&self, flags: crate::VideoOverlayFormatFlags) -> gst::Buffer {
176 unsafe {
177 from_glib_none(ffi::gst_video_overlay_rectangle_get_pixels_ayuv(
178 self.as_mut_ptr(),
179 flags.into_glib(),
180 ))
181 }
182 }
183
184 #[doc(alias = "get_pixels_argb")]
185 #[doc(alias = "gst_video_overlay_rectangle_get_pixels_argb")]
186 pub fn pixels_argb(&self, flags: crate::VideoOverlayFormatFlags) -> gst::Buffer {
187 unsafe {
188 from_glib_none(ffi::gst_video_overlay_rectangle_get_pixels_argb(
189 self.as_mut_ptr(),
190 flags.into_glib(),
191 ))
192 }
193 }
194}
195
196gst::mini_object_wrapper!(
197 VideoOverlayComposition,
198 VideoOverlayCompositionRef,
199 ffi::GstVideoOverlayComposition,
200 || ffi::gst_video_overlay_composition_get_type()
201);
202
203impl fmt::Debug for VideoOverlayComposition {
204 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
205 VideoOverlayCompositionRef::fmt(self, f)
206 }
207}
208
209impl fmt::Debug for VideoOverlayCompositionRef {
210 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
211 f.debug_struct("VideoOverlayComposition").finish()
212 }
213}
214
215impl VideoOverlayComposition {
216 #[doc(alias = "gst_video_overlay_composition_new")]
217 pub fn new<'a>(
218 rects: impl IntoIterator<Item = &'a VideoOverlayRectangle>,
219 ) -> Result<Self, glib::error::BoolError> {
220 assert_initialized_main_thread!();
221
222 #[cfg(feature = "v1_20")]
223 unsafe {
224 use std::ptr;
225
226 let composition =
227 Self::from_glib_full(ffi::gst_video_overlay_composition_new(ptr::null_mut()));
228
229 rects.into_iter().for_each(|rect| {
230 ffi::gst_video_overlay_composition_add_rectangle(
231 composition.as_mut_ptr(),
232 rect.as_mut_ptr(),
233 );
234 });
235
236 Ok(composition)
237 }
238 #[cfg(not(feature = "v1_20"))]
239 unsafe {
240 let mut iter = rects.into_iter();
241
242 let first = match iter.next() {
243 None => {
244 return Err(glib::bool_error!(
245 "Failed to create VideoOverlayComposition"
246 ))
247 }
248 Some(first) => first,
249 };
250
251 let composition =
252 Self::from_glib_full(ffi::gst_video_overlay_composition_new(first.as_mut_ptr()));
253
254 for rect in iter {
255 ffi::gst_video_overlay_composition_add_rectangle(
256 composition.as_mut_ptr(),
257 rect.as_mut_ptr(),
258 );
259 }
260
261 Ok(composition)
262 }
263 }
264}
265
266#[cfg(feature = "v1_20")]
267impl Default for VideoOverlayComposition {
268 fn default() -> Self {
269 assert_initialized_main_thread!();
270
271 use std::ptr;
272
273 unsafe { from_glib_full(ffi::gst_video_overlay_composition_new(ptr::null_mut())) }
274 }
275}
276
277impl VideoOverlayCompositionRef {
278 #[doc(alias = "gst_video_overlay_composition_n_rectangles")]
279 pub fn n_rectangles(&self) -> u32 {
280 unsafe { ffi::gst_video_overlay_composition_n_rectangles(self.as_mut_ptr()) }
281 }
282
283 #[doc(alias = "get_rectangle")]
284 #[doc(alias = "gst_video_overlay_composition_get_rectangle")]
285 pub fn rectangle(&self, idx: u32) -> Result<VideoOverlayRectangle, glib::error::BoolError> {
286 if idx >= self.n_rectangles() {
287 return Err(glib::bool_error!("Invalid index"));
288 }
289
290 unsafe {
291 match from_glib_none(ffi::gst_video_overlay_composition_get_rectangle(
292 self.as_mut_ptr(),
293 idx,
294 )) {
295 Some(r) => Ok(r),
296 None => Err(glib::bool_error!("Failed to get rectangle")),
297 }
298 }
299 }
300
301 #[doc(alias = "gst_video_overlay_composition_add_rectangle")]
302 pub fn add_rectangle(&mut self, rect: &VideoOverlayRectangleRef) {
303 unsafe {
304 ffi::gst_video_overlay_composition_add_rectangle(self.as_mut_ptr(), rect.as_mut_ptr());
305 }
306 }
307
308 #[doc(alias = "get_seqnum")]
309 #[doc(alias = "gst_video_overlay_composition_get_seqnum")]
310 pub fn seqnum(&self) -> u32 {
311 unsafe { ffi::gst_video_overlay_composition_get_seqnum(self.as_mut_ptr()) }
312 }
313
314 #[doc(alias = "gst_video_overlay_composition_blend")]
315 pub fn blend(
316 &self,
317 frame: &mut crate::VideoFrameRef<&mut gst::BufferRef>,
318 ) -> Result<(), glib::BoolError> {
319 unsafe {
320 glib::result_from_gboolean!(
321 ffi::gst_video_overlay_composition_blend(self.as_mut_ptr(), frame.as_mut_ptr()),
322 "Failed to blend overlay composition",
323 )
324 }
325 }
326
327 pub fn iter(&self) -> Iter {
328 Iter {
329 composition: self,
330 idx: 0,
331 len: self.n_rectangles() as usize,
332 }
333 }
334}
335
336impl<'a> IntoIterator for &'a VideoOverlayComposition {
337 type IntoIter = Iter<'a>;
338 type Item = VideoOverlayRectangle;
339
340 fn into_iter(self) -> Self::IntoIter {
341 self.iter()
342 }
343}
344
345impl From<VideoOverlayRectangle> for VideoOverlayComposition {
346 fn from(value: VideoOverlayRectangle) -> Self {
347 skip_assert_initialized!();
348
349 unsafe {
350 Self::from_glib_full(ffi::gst_video_overlay_composition_new(
351 value.into_glib_ptr(),
352 ))
353 }
354 }
355}
356
357impl<'a> From<&'a VideoOverlayRectangle> for VideoOverlayComposition {
358 fn from(value: &'a VideoOverlayRectangle) -> Self {
359 skip_assert_initialized!();
360
361 unsafe { Self::from_glib_full(ffi::gst_video_overlay_composition_new(value.as_mut_ptr())) }
362 }
363}
364
365#[cfg(feature = "v1_20")]
366impl<const N: usize> From<[VideoOverlayRectangle; N]> for VideoOverlayComposition {
367 fn from(value: [VideoOverlayRectangle; N]) -> Self {
368 assert_initialized_main_thread!();
369
370 unsafe {
371 use std::ptr;
372
373 let composition =
374 Self::from_glib_full(ffi::gst_video_overlay_composition_new(ptr::null_mut()));
375
376 value.into_iter().for_each(|rect| {
377 ffi::gst_video_overlay_composition_add_rectangle(
378 composition.as_mut_ptr(),
379 rect.into_glib_ptr(),
380 );
381 });
382
383 composition
384 }
385 }
386}
387
388#[cfg(feature = "v1_20")]
389impl<'a, const N: usize> From<[&'a VideoOverlayRectangle; N]> for VideoOverlayComposition {
390 fn from(value: [&'a VideoOverlayRectangle; N]) -> Self {
391 assert_initialized_main_thread!();
392
393 unsafe {
394 use std::ptr;
395
396 let composition =
397 Self::from_glib_full(ffi::gst_video_overlay_composition_new(ptr::null_mut()));
398
399 value.into_iter().for_each(|rect| {
400 ffi::gst_video_overlay_composition_add_rectangle(
401 composition.as_mut_ptr(),
402 rect.as_mut_ptr(),
403 );
404 });
405
406 composition
407 }
408 }
409}
410
411#[cfg(feature = "v1_20")]
412impl std::iter::FromIterator<VideoOverlayRectangle> for VideoOverlayComposition {
413 fn from_iter<T: IntoIterator<Item = VideoOverlayRectangle>>(iter: T) -> Self {
414 assert_initialized_main_thread!();
415
416 unsafe {
417 use std::ptr;
418
419 let composition =
420 Self::from_glib_full(ffi::gst_video_overlay_composition_new(ptr::null_mut()));
421
422 iter.into_iter().for_each(|rect| {
423 ffi::gst_video_overlay_composition_add_rectangle(
424 composition.as_mut_ptr(),
425 rect.into_glib_ptr(),
426 );
427 });
428
429 composition
430 }
431 }
432}
433
434#[cfg(feature = "v1_20")]
435impl<'a> std::iter::FromIterator<&'a VideoOverlayRectangle> for VideoOverlayComposition {
436 fn from_iter<T: IntoIterator<Item = &'a VideoOverlayRectangle>>(iter: T) -> Self {
437 assert_initialized_main_thread!();
438
439 unsafe {
440 use std::ptr;
441
442 let composition =
443 Self::from_glib_full(ffi::gst_video_overlay_composition_new(ptr::null_mut()));
444
445 iter.into_iter().for_each(|rect| {
446 ffi::gst_video_overlay_composition_add_rectangle(
447 composition.as_mut_ptr(),
448 rect.as_mut_ptr(),
449 );
450 });
451
452 composition
453 }
454 }
455}
456
457#[must_use = "iterators are lazy and do nothing unless consumed"]
458pub struct Iter<'a> {
459 composition: &'a VideoOverlayCompositionRef,
460 idx: usize,
461 len: usize,
462}
463
464impl Iterator for Iter<'_> {
465 type Item = VideoOverlayRectangle;
466
467 fn next(&mut self) -> Option<Self::Item> {
468 if self.idx >= self.len {
469 return None;
470 }
471
472 let rect = self.composition.rectangle(self.idx as u32).unwrap();
473 self.idx += 1;
474
475 Some(rect)
476 }
477
478 fn size_hint(&self) -> (usize, Option<usize>) {
479 let remaining = self.len - self.idx;
480
481 (remaining, Some(remaining))
482 }
483
484 fn count(self) -> usize {
485 self.len - self.idx
486 }
487
488 fn nth(&mut self, n: usize) -> Option<Self::Item> {
489 let (end, overflow) = self.idx.overflowing_add(n);
490 if end >= self.len || overflow {
491 self.idx = self.len;
492 None
493 } else {
494 self.idx = end + 1;
495 Some(self.composition.rectangle(end as u32).unwrap())
496 }
497 }
498
499 fn last(self) -> Option<Self::Item> {
500 if self.idx == self.len {
501 None
502 } else {
503 Some(self.composition.rectangle(self.len as u32 - 1).unwrap())
504 }
505 }
506}
507
508impl DoubleEndedIterator for Iter<'_> {
509 fn next_back(&mut self) -> Option<Self::Item> {
510 if self.idx == self.len {
511 return None;
512 }
513
514 self.len -= 1;
515
516 Some(self.composition.rectangle(self.len as u32).unwrap())
517 }
518
519 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
520 let (end, overflow) = self.len.overflowing_sub(n);
521 if end <= self.idx || overflow {
522 self.idx = self.len;
523 None
524 } else {
525 self.len = end - 1;
526 Some(self.composition.rectangle(self.len as u32).unwrap())
527 }
528 }
529}
530
531impl ExactSizeIterator for Iter<'_> {}
532
533impl std::iter::FusedIterator for Iter<'_> {}