1 | use std::marker::PhantomData; |
2 | use std::mem; |
3 | use std::slice; |
4 | |
5 | use ffi::*; |
6 | use format; |
7 | use libc::{c_int, size_t}; |
8 | use Error; |
9 | |
10 | pub struct Picture<'a> { |
11 | ptr: *mut AVPicture, |
12 | |
13 | format: format::Pixel, |
14 | width: u32, |
15 | height: u32, |
16 | |
17 | _own: bool, |
18 | _marker: PhantomData<&'a ()>, |
19 | } |
20 | |
21 | impl<'a> Picture<'a> { |
22 | pub unsafe fn wrap( |
23 | ptr: *mut AVPicture, |
24 | format: format::Pixel, |
25 | width: u32, |
26 | height: u32, |
27 | ) -> Self { |
28 | Picture { |
29 | ptr, |
30 | |
31 | format, |
32 | width, |
33 | height, |
34 | |
35 | _own: false, |
36 | _marker: PhantomData, |
37 | } |
38 | } |
39 | |
40 | pub unsafe fn as_ptr(&self) -> *const AVPicture { |
41 | self.ptr as *const _ |
42 | } |
43 | |
44 | pub unsafe fn as_mut_ptr(&mut self) -> *mut AVPicture { |
45 | self.ptr |
46 | } |
47 | } |
48 | |
49 | impl<'a> Picture<'a> { |
50 | pub fn size(format: format::Pixel, width: u32, height: u32) -> Result<usize, Error> { |
51 | unsafe { |
52 | match avpicture_get_size(format.into(), width as c_int, height as c_int) { |
53 | v if v >= 0 => Ok(v as usize), |
54 | e => Err(Error::from(e)), |
55 | } |
56 | } |
57 | } |
58 | |
59 | pub fn new(format: format::Pixel, width: u32, height: u32) -> Result<Self, Error> { |
60 | unsafe { |
61 | let ptr = av_malloc(mem::size_of::<AVPicture>() as size_t) as *mut AVPicture; |
62 | |
63 | match avpicture_alloc(ptr, format.into(), width as c_int, height as c_int) { |
64 | 0 => Ok(Picture { |
65 | ptr, |
66 | |
67 | format, |
68 | width, |
69 | height, |
70 | |
71 | _own: true, |
72 | _marker: PhantomData, |
73 | }), |
74 | |
75 | e => Err(Error::from(e)), |
76 | } |
77 | } |
78 | } |
79 | |
80 | pub fn format(&self) -> format::Pixel { |
81 | self.format |
82 | } |
83 | |
84 | pub fn width(&self) -> u32 { |
85 | self.width |
86 | } |
87 | |
88 | pub fn height(&self) -> u32 { |
89 | self.height |
90 | } |
91 | |
92 | pub fn layout(&self, out: &mut [u8]) -> Result<usize, Error> { |
93 | unsafe { |
94 | match avpicture_layout( |
95 | self.ptr, |
96 | self.format.into(), |
97 | self.width as c_int, |
98 | self.height as c_int, |
99 | out.as_mut_ptr(), |
100 | out.len() as c_int, |
101 | ) { |
102 | s if s >= 0 => Ok(s as usize), |
103 | e => Err(Error::from(e)), |
104 | } |
105 | } |
106 | } |
107 | |
108 | pub fn layout_as( |
109 | &self, |
110 | format: format::Pixel, |
111 | width: u32, |
112 | height: u32, |
113 | out: &mut [u8], |
114 | ) -> Result<usize, Error> { |
115 | unsafe { |
116 | match avpicture_layout( |
117 | self.as_ptr(), |
118 | format.into(), |
119 | width as c_int, |
120 | height as c_int, |
121 | out.as_mut_ptr(), |
122 | out.len() as c_int, |
123 | ) { |
124 | s if s >= 0 => Ok(s as usize), |
125 | e => Err(Error::from(e)), |
126 | } |
127 | } |
128 | } |
129 | |
130 | pub fn crop(&self, source: &mut Picture, top: u32, left: u32) -> Result<(), Error> { |
131 | if self.format != source.format { |
132 | return Err(Error::Bug); |
133 | } |
134 | |
135 | unsafe { |
136 | match av_picture_crop( |
137 | source.as_mut_ptr(), |
138 | self.as_ptr(), |
139 | self.format.into(), |
140 | top as c_int, |
141 | left as c_int, |
142 | ) { |
143 | 0 => Ok(()), |
144 | e => Err(Error::from(e)), |
145 | } |
146 | } |
147 | } |
148 | |
149 | pub fn data(&self) -> Vec<&[u8]> { |
150 | let mut result = Vec::new(); |
151 | |
152 | unsafe { |
153 | for (i, length) in (*self.as_ptr()) |
154 | .linesize |
155 | .iter() |
156 | .take_while(|l| **l > 0) |
157 | .enumerate() |
158 | { |
159 | result.push(slice::from_raw_parts( |
160 | (*self.as_ptr()).data[i], |
161 | (*length as usize) * (self.height as usize), |
162 | )) |
163 | } |
164 | } |
165 | |
166 | result |
167 | } |
168 | |
169 | pub fn data_mut(&mut self) -> Vec<&mut [u8]> { |
170 | let mut result = Vec::new(); |
171 | |
172 | unsafe { |
173 | for (i, length) in (*self.as_ptr()) |
174 | .linesize |
175 | .iter() |
176 | .take_while(|l| **l > 0) |
177 | .enumerate() |
178 | { |
179 | result.push(slice::from_raw_parts_mut( |
180 | (*self.as_ptr()).data[i], |
181 | (*length as usize) * (self.height as usize), |
182 | )) |
183 | } |
184 | } |
185 | |
186 | result |
187 | } |
188 | } |
189 | |
190 | impl<'a> Clone for Picture<'a> { |
191 | fn clone(&self) -> Self { |
192 | let mut pic: Picture<'_> = Picture::new(self.format, self.width, self.height).unwrap(); |
193 | pic.clone_from(self); |
194 | |
195 | pic |
196 | } |
197 | |
198 | fn clone_from(&mut self, source: &Self) { |
199 | unsafe { |
200 | av_picture_copy( |
201 | self.as_mut_ptr(), |
202 | source.as_ptr(), |
203 | source.format.into(), |
204 | source.width as c_int, |
205 | source.height as c_int, |
206 | ); |
207 | } |
208 | } |
209 | } |
210 | |
211 | impl<'a> Drop for Picture<'a> { |
212 | fn drop(&mut self) { |
213 | if self._own { |
214 | unsafe { |
215 | av_free(self.as_mut_ptr() as *mut _); |
216 | } |
217 | } |
218 | } |
219 | } |
220 | |