1use libav_sys_ng::{
2 self, av_frame_alloc, av_frame_free, av_frame_get_buffer, av_get_bits_per_pixel,
3 av_pix_fmt_desc_get, AVFrame,
4};
5
6pub struct Frame {
7 _frame: *mut libav_sys_ng::AVFrame,
8 is_frame_allocated: bool,
9}
10
11impl Frame {
12 pub fn empty() -> Option<Self> {
13 let _frame = unsafe { av_frame_alloc() };
14
15 if _frame.is_null() {
16 return None;
17 }
18
19 Some(Self {
20 _frame,
21 is_frame_allocated: false,
22 })
23 }
24
25 pub fn from_size_and_pixfmt(width: i32, height: i32, pixfmt: i32) -> Option<Self> {
26 unsafe {
27 let mut _frame = av_frame_alloc();
28
29 if _frame.is_null() {
30 None
31 } else {
32 (*_frame).width = width;
33 (*_frame).height = height;
34 (*_frame).format = pixfmt;
35
36 let mut this = Frame {
37 _frame,
38 is_frame_allocated: false,
39 };
40
41 this.allocate_buffer();
42
43 Some(this)
44 }
45 }
46 }
47
48 pub fn data_plane(&self, plane_nr: usize) -> Result<&[u8], &str> {
49 if plane_nr >= 8 {
50 return Err("Out of bounds.");
51 }
52
53 let size = self.frame_size()?;
54
55 unsafe {
56 Ok(core::slice::from_raw_parts(
57 (*self._frame).data[plane_nr],
58 size,
59 ))
60 }
61 }
62
63 pub fn frame_size(&self) -> Result<usize, &str> {
64 let data = unsafe { av_pix_fmt_desc_get((*self._frame).format) };
65 let depth = if data.is_null() {
66 Err("Failed to get pixel format info")
67 } else {
68 Ok(unsafe { av_get_bits_per_pixel(data) } as usize)
69 };
70
71 if depth.is_err() {
72 return Err(depth.err().unwrap());
73 }
74
75 let size = (unsafe { *self._frame }).width as usize
76 * (unsafe { *self._frame }).height as usize
77 * depth.ok().unwrap()
78 / 8;
79
80 Ok(size)
81 }
82
83 pub fn data_plane_mut(&mut self, plane_nr: usize) -> Result<&mut [u8], &str> {
84 if plane_nr >= 8 {
85 return Err("Out of bounds.");
86 }
87
88 let size = self.frame_size()?;
89
90 unsafe {
91 Ok(core::slice::from_raw_parts_mut(
92 (*self._frame).data[plane_nr],
93 size,
94 ))
95 }
96 }
97
98 fn allocate_buffer(&mut self) {
99 if self.is_frame_allocated {
100 return;
101 }
102
103 unsafe {
104 av_frame_get_buffer(self._frame, 0);
105 }
106
107 self.is_frame_allocated = true;
108 }
109
110 pub fn format(&self) -> i32 {
111 unsafe { (*self._frame).format }
112 }
113
114 pub fn linesize(&self) -> [i32; 8] {
115 unsafe { (*self._frame).linesize }
116 }
117
118 pub unsafe fn raw(&self) -> &AVFrame {
119 &*self._frame.cast()
120 }
121
122 pub unsafe fn raw_mut(&mut self) -> &mut AVFrame {
123 &mut *self._frame
124 }
125}
126
127impl Drop for Frame {
128 fn drop(&mut self) {
129 unsafe {
130 av_frame_free(&mut self._frame);
131 }
132 }
133}