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