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