1use std::{fmt, marker::PhantomData, mem, ops, ptr, slice};
4
5use crate::ffi;
6use glib::translate::{Borrowed, ToGlibPtr, from_glib, from_glib_none};
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 unsafe {
668 debug_assert!(!frame.is_null());
669
670 let frame = ptr::read(frame);
671 Borrowed::new(Self {
672 frame,
673 unmap: false,
674 phantom: PhantomData,
675 })
676 }
677 }
678
679 #[inline]
680 pub unsafe fn from_glib_full(frame: ffi::GstVideoFrame) -> Self {
681 Self {
682 frame,
683 unmap: true,
684 phantom: PhantomData,
685 }
686 }
687
688 #[inline]
689 pub fn from_buffer_ref_readable<'b>(
690 buffer: &'a gst::BufferRef,
691 info: &'b crate::VideoInfo,
692 ) -> Result<Self, glib::BoolError> {
693 skip_assert_initialized!();
694
695 assert!(info.is_valid());
696
697 unsafe {
698 let mut frame = mem::MaybeUninit::uninit();
699 let res: bool = from_glib(ffi::gst_video_frame_map(
700 frame.as_mut_ptr(),
701 info.to_glib_none().0 as *mut _,
702 buffer.as_mut_ptr(),
703 ffi::GST_VIDEO_FRAME_MAP_FLAG_NO_REF | gst::ffi::GST_MAP_READ,
704 ));
705
706 if !res {
707 Err(glib::bool_error!("Failed to map VideoFrame"))
708 } else {
709 let frame = frame.assume_init();
710 Ok(Self {
711 frame,
712 unmap: true,
713 phantom: PhantomData,
714 })
715 }
716 }
717 }
718
719 #[inline]
720 pub fn from_buffer_ref_id_readable<'b>(
721 buffer: &'a gst::BufferRef,
722 id: i32,
723 info: &'b crate::VideoInfo,
724 ) -> Result<Self, glib::BoolError> {
725 skip_assert_initialized!();
726
727 assert!(info.is_valid());
728
729 unsafe {
730 let mut frame = mem::MaybeUninit::uninit();
731 let res: bool = from_glib(ffi::gst_video_frame_map_id(
732 frame.as_mut_ptr(),
733 info.to_glib_none().0 as *mut _,
734 buffer.as_mut_ptr(),
735 id,
736 ffi::GST_VIDEO_FRAME_MAP_FLAG_NO_REF | gst::ffi::GST_MAP_READ,
737 ));
738
739 if !res {
740 Err(glib::bool_error!("Failed to map VideoFrame"))
741 } else {
742 let frame = frame.assume_init();
743 Ok(Self {
744 frame,
745 unmap: true,
746 phantom: PhantomData,
747 })
748 }
749 }
750 }
751}
752
753impl<'a> VideoFrameRef<&'a mut gst::BufferRef> {
754 #[inline]
755 pub unsafe fn from_glib_borrow_mut(frame: *mut ffi::GstVideoFrame) -> Self {
756 unsafe {
757 debug_assert!(!frame.is_null());
758
759 let frame = ptr::read(frame);
760 Self {
761 frame,
762 unmap: false,
763 phantom: PhantomData,
764 }
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}