1use std::{fmt, marker::PhantomData, mem, ops, ptr, slice};
4
5use crate::ffi;
6use glib::translate::{from_glib, from_glib_none, Borrowed, ToGlibPtr};
7
8pub enum Readable {}
9pub enum Writable {}
10
11pub unsafe trait IsVideoFrame {
12 fn as_raw(&self) -> &ffi::GstVideoFrame;
13}
14
15unsafe impl<T> IsVideoFrame for VideoFrame<T> {
16 #[inline]
17 fn as_raw(&self) -> &ffi::GstVideoFrame {
18 &self.frame
19 }
20}
21
22fn plane_buffer_info<T: IsVideoFrame>(
23 frame: &T,
24 plane: u32,
25) -> Result<(usize, usize), glib::BoolError> {
26 skip_assert_initialized!();
27
28 if plane >= frame.n_planes() {
29 return Err(glib::bool_error!(
30 "Plane index higher than number of planes"
31 ));
32 }
33
34 let format_info = frame.format_info();
35
36 if format_info.has_palette() && plane == 1 {
38 return Ok((1, 256 * 4));
39 }
40
41 let w = frame.plane_stride()[plane as usize] as u32;
42 let h = frame.plane_height(plane);
43
44 if w == 0 || h == 0 {
45 return Ok((0, 0));
46 }
47
48 Ok((plane as usize, (w * h) as usize))
49}
50
51pub struct VideoFrame<T> {
52 frame: ffi::GstVideoFrame,
53 phantom: PhantomData<T>,
54}
55
56unsafe impl<T> Send for VideoFrame<T> {}
57unsafe impl<T> Sync for VideoFrame<T> {}
58
59impl<T> fmt::Debug for VideoFrame<T> {
60 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
61 f.debug_struct("VideoFrame")
62 .field("flags", &self.flags())
63 .field("id", &self.id())
64 .field("buffer", &self.buffer())
65 .field("info", &self.info())
66 .finish()
67 }
68}
69
70pub trait VideoFrameExt: IsVideoFrame {
71 #[inline]
72 fn as_ptr(&self) -> *const ffi::GstVideoFrame {
73 self.as_raw() as _
74 }
75
76 #[inline]
77 fn info(&self) -> &crate::VideoInfo {
78 unsafe {
79 let frame = self.as_raw();
80 let info = &frame.info as *const ffi::GstVideoInfo as *const crate::VideoInfo;
81 &*info
82 }
83 }
84
85 #[inline]
86 fn flags(&self) -> crate::VideoFrameFlags {
87 unsafe { from_glib(self.as_raw().flags) }
88 }
89
90 #[inline]
91 fn id(&self) -> i32 {
92 self.as_raw().id
93 }
94
95 #[inline]
96 fn buffer(&self) -> &gst::BufferRef {
97 unsafe { gst::BufferRef::from_ptr(self.as_raw().buffer) }
98 }
99
100 #[inline]
101 fn format(&self) -> crate::VideoFormat {
102 self.info().format()
103 }
104
105 #[inline]
106 fn format_info(&self) -> crate::VideoFormatInfo {
107 self.info().format_info()
108 }
109
110 #[inline]
111 fn width(&self) -> u32 {
112 self.info().width()
113 }
114
115 #[inline]
116 fn height(&self) -> u32 {
117 self.info().height()
118 }
119
120 #[inline]
121 fn size(&self) -> usize {
122 self.info().size()
123 }
124
125 #[inline]
126 fn is_interlaced(&self) -> bool {
127 self.flags().contains(crate::VideoFrameFlags::INTERLACED)
128 }
129
130 #[inline]
131 fn is_tff(&self) -> bool {
132 self.flags().contains(crate::VideoFrameFlags::TFF)
133 }
134
135 #[inline]
136 fn is_rff(&self) -> bool {
137 self.flags().contains(crate::VideoFrameFlags::RFF)
138 }
139
140 #[inline]
141 fn is_onefield(&self) -> bool {
142 self.flags().contains(crate::VideoFrameFlags::ONEFIELD)
143 }
144
145 #[inline]
146 fn is_bottom_field(&self) -> bool {
147 self.flags().contains(crate::VideoFrameFlags::ONEFIELD)
148 && !self.flags().contains(crate::VideoFrameFlags::TFF)
149 }
150
151 #[inline]
152 fn is_top_field(&self) -> bool {
153 self.flags().contains(crate::VideoFrameFlags::ONEFIELD)
154 && self.flags().contains(crate::VideoFrameFlags::TFF)
155 }
156
157 #[inline]
158 fn n_planes(&self) -> u32 {
159 self.info().n_planes()
160 }
161
162 #[inline]
163 fn n_components(&self) -> u32 {
164 self.info().n_components()
165 }
166
167 #[inline]
168 fn plane_stride(&self) -> &[i32] {
169 self.info().stride()
170 }
171
172 #[inline]
173 fn plane_offset(&self) -> &[usize] {
174 self.info().offset()
175 }
176
177 #[inline]
178 fn plane_height(&self, plane: u32) -> u32 {
179 cfg_if::cfg_if! {
180 if #[cfg(feature = "v1_18")] {
181 let comp = self.format_info().component(plane)[0];
182 if comp == -1 {
183 0
184 } else {
185 self.comp_height(comp as u32)
186 }
187 } else {
188 self.format_info().scale_height(plane as u8, self.height())
195 }
196 }
197 }
198
199 #[inline]
200 fn comp_depth(&self, component: u32) -> u32 {
201 self.info().comp_depth(component as u8)
202 }
203
204 #[inline]
205 fn comp_height(&self, component: u32) -> u32 {
206 self.info().comp_height(component as u8)
207 }
208
209 #[inline]
210 fn comp_width(&self, component: u32) -> u32 {
211 self.info().comp_width(component as u8)
212 }
213
214 #[inline]
215 fn comp_offset(&self, component: u32) -> usize {
216 self.info().comp_offset(component as u8)
217 }
218
219 #[inline]
220 fn comp_poffset(&self, component: u32) -> u32 {
221 self.info().comp_poffset(component as u8)
222 }
223
224 #[inline]
225 fn comp_pstride(&self, component: u32) -> i32 {
226 self.info().comp_pstride(component as u8)
227 }
228
229 #[inline]
230 fn comp_stride(&self, component: u32) -> i32 {
231 self.info().comp_stride(component as u8)
232 }
233
234 #[inline]
235 fn comp_plane(&self, component: u32) -> u32 {
236 self.info().comp_plane(component as u8)
237 }
238}
239
240impl<O: IsVideoFrame> VideoFrameExt for O {}
241
242impl<T> VideoFrame<T> {
243 #[inline]
244 pub fn into_buffer(self) -> gst::Buffer {
245 unsafe {
246 let mut s = mem::ManuallyDrop::new(self);
247 let buffer = from_glib_none(s.frame.buffer);
248 ffi::gst_video_frame_unmap(&mut s.frame);
249 buffer
250 }
251 }
252
253 #[doc(alias = "gst_video_frame_copy")]
254 pub fn copy(&self, dest: &mut VideoFrame<Writable>) -> Result<(), glib::BoolError> {
255 unsafe {
256 let res: bool = from_glib(ffi::gst_video_frame_copy(&mut dest.frame, &self.frame));
257 if res {
258 Ok(())
259 } else {
260 Err(glib::bool_error!("Failed to copy video frame"))
261 }
262 }
263 }
264
265 #[doc(alias = "gst_video_frame_copy_plane")]
266 pub fn copy_plane(
267 &self,
268 dest: &mut VideoFrame<Writable>,
269 plane: u32,
270 ) -> Result<(), glib::BoolError> {
271 skip_assert_initialized!();
272
273 unsafe {
274 let res: bool = from_glib(ffi::gst_video_frame_copy_plane(
275 &mut dest.frame,
276 &self.frame,
277 plane,
278 ));
279 if res {
280 Ok(())
281 } else {
282 Err(glib::bool_error!("Failed to copy video frame plane"))
283 }
284 }
285 }
286
287 #[inline]
288 pub fn comp_data(&self, component: u32) -> Result<&[u8], glib::BoolError> {
289 let poffset = self.info().comp_poffset(component as u8) as usize;
290 Ok(&self.plane_data(self.format_info().plane()[component as usize])?[poffset..])
291 }
292
293 #[inline]
294 pub fn buffer(&self) -> &gst::BufferRef {
295 unsafe { gst::BufferRef::from_ptr(self.frame.buffer) }
296 }
297
298 pub fn plane_data(&self, plane: u32) -> Result<&[u8], glib::BoolError> {
299 match plane_buffer_info(self, plane) {
300 Ok((plane, size)) => {
301 if size == 0 {
302 return Ok(&[]);
303 }
304
305 unsafe {
306 Ok(slice::from_raw_parts(
307 self.frame.data[plane] as *const u8,
308 size,
309 ))
310 }
311 }
312 Err(err) => Err(err),
313 }
314 }
315
316 pub fn planes_data(&self) -> [&[u8]; 4] {
317 let mut planes = [[].as_slice(); 4];
318
319 for plane in 0..self.n_planes() {
320 planes[plane as usize] = self.plane_data(plane).unwrap();
321 }
322
323 planes
324 }
325
326 #[inline]
327 pub unsafe fn from_glib_full(frame: ffi::GstVideoFrame) -> Self {
328 Self {
329 frame,
330 phantom: PhantomData,
331 }
332 }
333
334 #[inline]
335 pub fn as_video_frame_ref(&self) -> VideoFrameRef<&gst::BufferRef> {
336 let frame = unsafe { ptr::read(&self.frame) };
337 VideoFrameRef {
338 frame,
339 unmap: false,
340 phantom: PhantomData,
341 }
342 }
343
344 #[inline]
345 pub fn into_raw(self) -> ffi::GstVideoFrame {
346 let s = mem::ManuallyDrop::new(self);
347 s.frame
348 }
349}
350
351impl<T> Drop for VideoFrame<T> {
352 #[inline]
353 fn drop(&mut self) {
354 unsafe {
355 ffi::gst_video_frame_unmap(&mut self.frame);
356 }
357 }
358}
359
360impl VideoFrame<Readable> {
361 #[inline]
362 pub fn from_buffer_readable(
363 buffer: gst::Buffer,
364 info: &crate::VideoInfo,
365 ) -> Result<Self, gst::Buffer> {
366 skip_assert_initialized!();
367
368 assert!(info.is_valid());
369
370 unsafe {
371 let mut frame = mem::MaybeUninit::uninit();
372 let res: bool = from_glib(ffi::gst_video_frame_map(
377 frame.as_mut_ptr(),
378 info.to_glib_none().0 as *mut _,
379 buffer.to_glib_none().0,
380 gst::ffi::GST_MAP_READ,
381 ));
382
383 if !res {
384 Err(buffer)
385 } else {
386 let frame = frame.assume_init();
387 Ok(Self {
388 frame,
389 phantom: PhantomData,
390 })
391 }
392 }
393 }
394
395 #[inline]
396 pub fn from_buffer_id_readable(
397 buffer: gst::Buffer,
398 id: i32,
399 info: &crate::VideoInfo,
400 ) -> Result<Self, gst::Buffer> {
401 skip_assert_initialized!();
402
403 assert!(info.is_valid());
404
405 unsafe {
406 let mut frame = mem::MaybeUninit::uninit();
407 let res: bool = from_glib(ffi::gst_video_frame_map_id(
412 frame.as_mut_ptr(),
413 info.to_glib_none().0 as *mut _,
414 buffer.to_glib_none().0,
415 id,
416 gst::ffi::GST_MAP_READ,
417 ));
418
419 if !res {
420 Err(buffer)
421 } else {
422 let frame = frame.assume_init();
423 Ok(Self {
424 frame,
425 phantom: PhantomData,
426 })
427 }
428 }
429 }
430
431 #[inline]
432 pub fn buffer_owned(&self) -> gst::Buffer {
433 unsafe { from_glib_none(self.frame.buffer) }
434 }
435}
436
437impl VideoFrame<Writable> {
438 #[inline]
439 pub fn from_buffer_writable(
440 buffer: gst::Buffer,
441 info: &crate::VideoInfo,
442 ) -> Result<Self, gst::Buffer> {
443 skip_assert_initialized!();
444
445 assert!(info.is_valid());
446
447 unsafe {
448 let mut frame = mem::MaybeUninit::uninit();
449 let res: bool = from_glib(ffi::gst_video_frame_map(
454 frame.as_mut_ptr(),
455 info.to_glib_none().0 as *mut _,
456 buffer.to_glib_none().0,
457 gst::ffi::GST_MAP_READ | gst::ffi::GST_MAP_WRITE,
458 ));
459
460 if !res {
461 Err(buffer)
462 } else {
463 let frame = frame.assume_init();
464 Ok(Self {
465 frame,
466 phantom: PhantomData,
467 })
468 }
469 }
470 }
471
472 #[inline]
473 pub fn from_buffer_id_writable(
474 buffer: gst::Buffer,
475 id: i32,
476 info: &crate::VideoInfo,
477 ) -> Result<Self, gst::Buffer> {
478 skip_assert_initialized!();
479
480 assert!(info.is_valid());
481
482 unsafe {
483 let mut frame = mem::MaybeUninit::uninit();
484 let res: bool = from_glib(ffi::gst_video_frame_map_id(
489 frame.as_mut_ptr(),
490 info.to_glib_none().0 as *mut _,
491 buffer.to_glib_none().0,
492 id,
493 gst::ffi::GST_MAP_READ | gst::ffi::GST_MAP_WRITE,
494 ));
495
496 if !res {
497 Err(buffer)
498 } else {
499 let frame = frame.assume_init();
500 Ok(Self {
501 frame,
502 phantom: PhantomData,
503 })
504 }
505 }
506 }
507
508 pub fn comp_data_mut(&mut self, component: u32) -> Result<&mut [u8], glib::BoolError> {
509 let poffset = self.info().comp_poffset(component as u8) as usize;
510 Ok(&mut self.plane_data_mut(self.format_info().plane()[component as usize])?[poffset..])
511 }
512
513 pub fn plane_data_mut(&mut self, plane: u32) -> Result<&mut [u8], glib::BoolError> {
514 match plane_buffer_info(self, plane) {
515 Ok((plane, size)) => {
516 if size == 0 {
517 return Ok(&mut []);
518 }
519
520 unsafe {
521 Ok(slice::from_raw_parts_mut(
522 self.frame.data[plane] as *mut u8,
523 size,
524 ))
525 }
526 }
527 Err(err) => Err(err),
528 }
529 }
530
531 pub fn planes_data_mut(&mut self) -> [&mut [u8]; 4] {
532 unsafe {
533 let mut planes = [
534 [].as_mut_slice(),
535 [].as_mut_slice(),
536 [].as_mut_slice(),
537 [].as_mut_slice(),
538 ];
539
540 for plane in 0..self.n_planes() {
541 let slice = self.plane_data_mut(plane).unwrap();
542 planes[plane as usize] = slice::from_raw_parts_mut(slice.as_mut_ptr(), slice.len());
543 }
544
545 planes
546 }
547 }
548
549 #[inline]
550 pub fn as_mut_video_frame_ref(&mut self) -> VideoFrameRef<&mut gst::BufferRef> {
551 let frame = unsafe { ptr::read(&self.frame) };
552 VideoFrameRef {
553 frame,
554 unmap: false,
555 phantom: PhantomData,
556 }
557 }
558
559 #[inline]
560 pub fn as_mut_ptr(&mut self) -> *mut ffi::GstVideoFrame {
561 &mut self.frame
562 }
563}
564
565pub struct VideoFrameRef<T> {
566 frame: ffi::GstVideoFrame,
567 unmap: bool,
568 phantom: PhantomData<T>,
569}
570
571unsafe impl<T> IsVideoFrame for VideoFrameRef<T> {
572 #[inline]
573 fn as_raw(&self) -> &ffi::GstVideoFrame {
574 &self.frame
575 }
576}
577
578impl<T> fmt::Debug for VideoFrameRef<T> {
579 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
580 f.debug_struct("VideoFrameRef")
581 .field("flags", &self.flags())
582 .field("id", &self.id())
583 .field("buffer", &unsafe {
584 gst::BufferRef::from_ptr(self.frame.buffer)
585 })
586 .field("info", &self.info())
587 .finish()
588 }
589}
590
591impl<T> VideoFrameRef<T> {
592 #[doc(alias = "gst_video_frame_copy")]
593 pub fn copy(
594 &self,
595 dest: &mut VideoFrameRef<&mut gst::BufferRef>,
596 ) -> Result<(), glib::BoolError> {
597 unsafe {
598 let res: bool = from_glib(ffi::gst_video_frame_copy(&mut dest.frame, &self.frame));
599 if res {
600 Ok(())
601 } else {
602 Err(glib::bool_error!("Failed to copy video frame"))
603 }
604 }
605 }
606
607 #[doc(alias = "gst_video_frame_copy_plane")]
608 pub fn copy_plane(
609 &self,
610 dest: &mut VideoFrameRef<&mut gst::BufferRef>,
611 plane: u32,
612 ) -> Result<(), glib::BoolError> {
613 skip_assert_initialized!();
614
615 unsafe {
616 let res: bool = from_glib(ffi::gst_video_frame_copy_plane(
617 &mut dest.frame,
618 &self.frame,
619 plane,
620 ));
621 if res {
622 Ok(())
623 } else {
624 Err(glib::bool_error!("Failed to copy video frame plane"))
625 }
626 }
627 }
628
629 pub fn comp_data(&self, component: u32) -> Result<&[u8], glib::BoolError> {
630 let poffset = self.info().comp_poffset(component as u8) as usize;
631 Ok(&self.plane_data(self.format_info().plane()[component as usize])?[poffset..])
632 }
633
634 pub fn plane_data(&self, plane: u32) -> Result<&[u8], glib::BoolError> {
635 match plane_buffer_info(self, plane) {
636 Ok((plane, size)) => {
637 if size == 0 {
638 return Ok(&[]);
639 }
640
641 unsafe {
642 Ok(slice::from_raw_parts(
643 self.frame.data[plane] as *const u8,
644 size,
645 ))
646 }
647 }
648 Err(err) => Err(err),
649 }
650 }
651
652 pub fn planes_data(&self) -> [&[u8]; 4] {
653 let mut planes = [[].as_slice(); 4];
654
655 for plane in 0..self.n_planes() {
656 planes[plane as usize] = self.plane_data(plane).unwrap();
657 }
658
659 planes
660 }
661}
662
663impl<'a> VideoFrameRef<&'a gst::BufferRef> {
664 #[inline]
665 pub unsafe fn from_glib_borrow(frame: *const ffi::GstVideoFrame) -> Borrowed<Self> {
666 debug_assert!(!frame.is_null());
667
668 let frame = ptr::read(frame);
669 Borrowed::new(Self {
670 frame,
671 unmap: false,
672 phantom: PhantomData,
673 })
674 }
675
676 #[inline]
677 pub unsafe fn from_glib_full(frame: ffi::GstVideoFrame) -> Self {
678 Self {
679 frame,
680 unmap: true,
681 phantom: PhantomData,
682 }
683 }
684
685 #[inline]
686 pub fn from_buffer_ref_readable<'b>(
687 buffer: &'a gst::BufferRef,
688 info: &'b crate::VideoInfo,
689 ) -> Result<Self, glib::BoolError> {
690 skip_assert_initialized!();
691
692 assert!(info.is_valid());
693
694 unsafe {
695 let mut frame = mem::MaybeUninit::uninit();
696 let res: bool = from_glib(ffi::gst_video_frame_map(
697 frame.as_mut_ptr(),
698 info.to_glib_none().0 as *mut _,
699 buffer.as_mut_ptr(),
700 ffi::GST_VIDEO_FRAME_MAP_FLAG_NO_REF | gst::ffi::GST_MAP_READ,
701 ));
702
703 if !res {
704 Err(glib::bool_error!("Failed to map VideoFrame"))
705 } else {
706 let frame = frame.assume_init();
707 Ok(Self {
708 frame,
709 unmap: true,
710 phantom: PhantomData,
711 })
712 }
713 }
714 }
715
716 #[inline]
717 pub fn from_buffer_ref_id_readable<'b>(
718 buffer: &'a gst::BufferRef,
719 id: i32,
720 info: &'b crate::VideoInfo,
721 ) -> Result<Self, glib::BoolError> {
722 skip_assert_initialized!();
723
724 assert!(info.is_valid());
725
726 unsafe {
727 let mut frame = mem::MaybeUninit::uninit();
728 let res: bool = from_glib(ffi::gst_video_frame_map_id(
729 frame.as_mut_ptr(),
730 info.to_glib_none().0 as *mut _,
731 buffer.as_mut_ptr(),
732 id,
733 ffi::GST_VIDEO_FRAME_MAP_FLAG_NO_REF | gst::ffi::GST_MAP_READ,
734 ));
735
736 if !res {
737 Err(glib::bool_error!("Failed to map VideoFrame"))
738 } else {
739 let frame = frame.assume_init();
740 Ok(Self {
741 frame,
742 unmap: true,
743 phantom: PhantomData,
744 })
745 }
746 }
747 }
748}
749
750impl<'a> VideoFrameRef<&'a mut gst::BufferRef> {
751 #[inline]
752 pub unsafe fn from_glib_borrow_mut(frame: *mut ffi::GstVideoFrame) -> Self {
753 debug_assert!(!frame.is_null());
754
755 let frame = ptr::read(frame);
756 Self {
757 frame,
758 unmap: false,
759 phantom: PhantomData,
760 }
761 }
762
763 #[inline]
764 pub unsafe fn from_glib_full_mut(frame: ffi::GstVideoFrame) -> Self {
765 Self {
766 frame,
767 unmap: true,
768 phantom: PhantomData,
769 }
770 }
771
772 #[inline]
773 pub fn from_buffer_ref_writable<'b>(
774 buffer: &'a mut gst::BufferRef,
775 info: &'b crate::VideoInfo,
776 ) -> Result<Self, glib::BoolError> {
777 skip_assert_initialized!();
778
779 assert!(info.is_valid());
780
781 unsafe {
782 let mut frame = mem::MaybeUninit::uninit();
783 let res: bool = from_glib(ffi::gst_video_frame_map(
784 frame.as_mut_ptr(),
785 info.to_glib_none().0 as *mut _,
786 buffer.as_mut_ptr(),
787 ffi::GST_VIDEO_FRAME_MAP_FLAG_NO_REF
788 | gst::ffi::GST_MAP_READ
789 | gst::ffi::GST_MAP_WRITE,
790 ));
791
792 if !res {
793 Err(glib::bool_error!("Failed to map VideoFrame"))
794 } else {
795 let frame = frame.assume_init();
796 Ok(Self {
797 frame,
798 unmap: true,
799 phantom: PhantomData,
800 })
801 }
802 }
803 }
804
805 #[inline]
806 pub fn from_buffer_ref_id_writable<'b>(
807 buffer: &'a mut gst::BufferRef,
808 id: i32,
809 info: &'b crate::VideoInfo,
810 ) -> Result<Self, glib::BoolError> {
811 skip_assert_initialized!();
812
813 assert!(info.is_valid());
814
815 unsafe {
816 let mut frame = mem::MaybeUninit::uninit();
817 let res: bool = from_glib(ffi::gst_video_frame_map_id(
818 frame.as_mut_ptr(),
819 info.to_glib_none().0 as *mut _,
820 buffer.as_mut_ptr(),
821 id,
822 ffi::GST_VIDEO_FRAME_MAP_FLAG_NO_REF
823 | gst::ffi::GST_MAP_READ
824 | gst::ffi::GST_MAP_WRITE,
825 ));
826
827 if !res {
828 Err(glib::bool_error!("Failed to map VideoFrame"))
829 } else {
830 let frame = frame.assume_init();
831 Ok(Self {
832 frame,
833 unmap: true,
834 phantom: PhantomData,
835 })
836 }
837 }
838 }
839
840 pub fn comp_data_mut(&mut self, component: u32) -> Result<&mut [u8], glib::BoolError> {
841 let poffset = self.info().comp_poffset(component as u8) as usize;
842 Ok(&mut self.plane_data_mut(self.format_info().plane()[component as usize])?[poffset..])
843 }
844
845 pub fn plane_data_mut(&mut self, plane: u32) -> Result<&mut [u8], glib::BoolError> {
846 match plane_buffer_info(self, plane) {
847 Ok((plane, size)) => {
848 if size == 0 {
849 return Ok(&mut []);
850 }
851
852 unsafe {
853 Ok(slice::from_raw_parts_mut(
854 self.frame.data[plane] as *mut u8,
855 size,
856 ))
857 }
858 }
859 Err(err) => Err(err),
860 }
861 }
862
863 pub fn planes_data_mut(&mut self) -> [&mut [u8]; 4] {
864 unsafe {
865 let mut planes = [
866 [].as_mut_slice(),
867 [].as_mut_slice(),
868 [].as_mut_slice(),
869 [].as_mut_slice(),
870 ];
871
872 for plane in 0..self.n_planes() {
873 let slice = self.plane_data_mut(plane).unwrap();
874 planes[plane as usize] = slice::from_raw_parts_mut(slice.as_mut_ptr(), slice.len());
875 }
876
877 planes
878 }
879 }
880
881 #[inline]
882 pub fn as_mut_ptr(&mut self) -> *mut ffi::GstVideoFrame {
883 &mut self.frame
884 }
885}
886
887impl<'a> ops::Deref for VideoFrameRef<&'a mut gst::BufferRef> {
888 type Target = VideoFrameRef<&'a gst::BufferRef>;
889
890 #[inline]
891 fn deref(&self) -> &Self::Target {
892 unsafe { &*(self as *const Self as *const Self::Target) }
893 }
894}
895
896unsafe impl<T> Send for VideoFrameRef<T> {}
897unsafe impl<T> Sync for VideoFrameRef<T> {}
898
899impl<T> Drop for VideoFrameRef<T> {
900 #[inline]
901 fn drop(&mut self) {
902 unsafe {
903 if self.unmap {
904 ffi::gst_video_frame_unmap(&mut self.frame);
905 }
906 }
907 }
908}
909
910pub trait VideoBufferExt {
911 #[doc(alias = "get_video_flags")]
912 fn video_flags(&self) -> crate::VideoBufferFlags;
913 fn set_video_flags(&mut self, flags: crate::VideoBufferFlags);
914 fn unset_video_flags(&mut self, flags: crate::VideoBufferFlags);
915}
916
917impl VideoBufferExt for gst::BufferRef {
918 #[inline]
919 fn video_flags(&self) -> crate::VideoBufferFlags {
920 unsafe {
921 let ptr = self.as_mut_ptr();
922 crate::VideoBufferFlags::from_bits_truncate((*ptr).mini_object.flags)
923 }
924 }
925
926 #[inline]
927 fn set_video_flags(&mut self, flags: crate::VideoBufferFlags) {
928 unsafe {
929 let ptr = self.as_mut_ptr();
930 (*ptr).mini_object.flags |= flags.bits();
931 }
932 }
933
934 #[inline]
935 fn unset_video_flags(&mut self, flags: crate::VideoBufferFlags) {
936 unsafe {
937 let ptr = self.as_mut_ptr();
938 (*ptr).mini_object.flags &= !flags.bits();
939 }
940 }
941}
942
943#[cfg(test)]
944mod tests {
945 use super::*;
946
947 #[test]
948 fn test_map_read() {
949 gst::init().unwrap();
950
951 let info = crate::VideoInfo::builder(crate::VideoFormat::Gray8, 320, 240)
952 .build()
953 .unwrap();
954 let buffer = gst::Buffer::with_size(info.size()).unwrap();
955 let frame = VideoFrame::from_buffer_readable(buffer, &info).unwrap();
956
957 assert!(frame.plane_data(0).is_ok());
958 assert_eq!(frame.plane_data(0).unwrap().len(), 320 * 240);
959 assert!(frame.plane_data(1).is_err());
960 assert!(frame.info() == &info);
961
962 {
963 let frame = frame.as_video_frame_ref();
964
965 assert!(frame.plane_data(0).is_ok());
966 assert_eq!(frame.plane_data(0).unwrap().len(), 320 * 240);
967 assert!(frame.plane_data(1).is_err());
968 assert!(frame.info() == &info);
969 }
970
971 assert!(frame.plane_data(0).is_ok());
972 assert_eq!(frame.plane_data(0).unwrap().len(), 320 * 240);
973 assert!(frame.plane_data(1).is_err());
974 assert!(frame.info() == &info);
975 }
976
977 #[test]
978 fn test_map_write() {
979 gst::init().unwrap();
980
981 let info = crate::VideoInfo::builder(crate::VideoFormat::Gray8, 320, 240)
982 .build()
983 .unwrap();
984 let buffer = gst::Buffer::with_size(info.size()).unwrap();
985 let mut frame = VideoFrame::from_buffer_writable(buffer, &info).unwrap();
986
987 assert!(frame.plane_data_mut(0).is_ok());
988 assert_eq!(frame.plane_data_mut(0).unwrap().len(), 320 * 240);
989 assert!(frame.plane_data_mut(1).is_err());
990 assert!(frame.info() == &info);
991
992 {
993 let mut frame = frame.as_mut_video_frame_ref();
994
995 assert!(frame.plane_data_mut(0).is_ok());
996 assert_eq!(frame.plane_data_mut(0).unwrap().len(), 320 * 240);
997 assert!(frame.plane_data_mut(1).is_err());
998 assert!(frame.info() == &info);
999 }
1000
1001 assert!(frame.plane_data_mut(0).is_ok());
1002 assert_eq!(frame.plane_data_mut(0).unwrap().len(), 320 * 240);
1003 assert!(frame.plane_data_mut(1).is_err());
1004 assert!(frame.info() == &info);
1005 }
1006
1007 #[test]
1008 fn test_map_ref_read() {
1009 gst::init().unwrap();
1010
1011 let info = crate::VideoInfo::builder(crate::VideoFormat::Gray8, 320, 240)
1012 .build()
1013 .unwrap();
1014 let buffer = gst::Buffer::with_size(info.size()).unwrap();
1015 let frame = VideoFrameRef::from_buffer_ref_readable(&buffer, &info).unwrap();
1016
1017 assert!(frame.plane_data(0).is_ok());
1018 assert_eq!(frame.plane_data(0).unwrap().len(), 320 * 240);
1019 assert!(frame.plane_data(1).is_err());
1020 assert!(frame.info() == &info);
1021 }
1022
1023 #[test]
1024 fn test_map_ref_write() {
1025 gst::init().unwrap();
1026
1027 let info = crate::VideoInfo::builder(crate::VideoFormat::Gray8, 320, 240)
1028 .build()
1029 .unwrap();
1030 let mut buffer = gst::Buffer::with_size(info.size()).unwrap();
1031 {
1032 let buffer = buffer.get_mut().unwrap();
1033 let mut frame = VideoFrameRef::from_buffer_ref_writable(buffer, &info).unwrap();
1034
1035 assert!(frame.plane_data_mut(0).is_ok());
1036 assert_eq!(frame.plane_data_mut(0).unwrap().len(), 320 * 240);
1037 assert!(frame.plane_data_mut(1).is_err());
1038 assert!(frame.info() == &info);
1039 }
1040 }
1041
1042 #[cfg(feature = "v1_20")]
1043 #[test]
1044 fn test_plane_data() {
1045 gst::init().unwrap();
1046
1047 let info = crate::VideoInfo::builder(crate::VideoFormat::Av12, 320, 240)
1048 .build()
1049 .unwrap();
1050 let buffer = gst::Buffer::with_size(info.size()).unwrap();
1051 let mut frame = VideoFrame::from_buffer_writable(buffer, &info).unwrap();
1052
1053 {
1055 let mut frame = frame.as_mut_video_frame_ref();
1056 let data = frame.plane_data_mut(2).unwrap();
1057 assert_eq!(data.len(), 320 * 240);
1058 data[0] = 42;
1059 }
1060
1061 {
1063 let mut frame = frame.as_mut_video_frame_ref();
1064 let data = frame.plane_data_mut(1).unwrap();
1065 assert_eq!(data.len(), 320 * 120);
1066 data[0] = 42;
1067 }
1068
1069 let frame = frame.into_buffer();
1070 let frame = VideoFrame::from_buffer_readable(frame, &info).unwrap();
1071
1072 let alpha_data = frame.plane_data(2).unwrap();
1073 assert_eq!(alpha_data.len(), 320 * 240);
1074 assert_eq!(alpha_data[0], 42);
1075
1076 let uv_data = frame.plane_data(1).unwrap();
1077 assert_eq!(uv_data.len(), 320 * 120);
1078 assert_eq!(uv_data[0], 42);
1079 }
1080}