Skip to main content

libav_ng/
avframe.rs

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}