1use std::mem;
2use std::ops::{Deref, DerefMut};
3use std::slice;
4
5use super::Frame;
6use color;
7use ffi::*;
8use libc::c_int;
9use picture;
10use util::chroma;
11use util::format;
12use Rational;
13
14#[derive(PartialEq, Eq)]
15pub struct Video(Frame);
16
17impl Video {
18 #[inline(always)]
19 pub unsafe fn wrap(ptr: *mut AVFrame) -> Self {
20 Video(Frame::wrap(ptr))
21 }
22
23 #[inline]
24 pub unsafe fn alloc(&mut self, format: format::Pixel, width: u32, height: u32) {
25 self.set_format(format);
26 self.set_width(width);
27 self.set_height(height);
28
29 av_frame_get_buffer(self.as_mut_ptr(), 32);
30 }
31}
32
33impl Video {
34 #[inline(always)]
35 pub fn empty() -> Self {
36 unsafe { Video(Frame::empty()) }
37 }
38
39 #[inline]
40 pub fn new(format: format::Pixel, width: u32, height: u32) -> Self {
41 unsafe {
42 let mut frame = Video::empty();
43 frame.alloc(format, width, height);
44
45 frame
46 }
47 }
48
49 #[inline]
50 pub fn format(&self) -> format::Pixel {
51 unsafe {
52 if (*self.as_ptr()).format == -1 {
53 format::Pixel::None
54 } else {
55 format::Pixel::from(mem::transmute::<_, AVPixelFormat>((*self.as_ptr()).format))
56 }
57 }
58 }
59
60 #[inline]
61 pub fn set_format(&mut self, value: format::Pixel) {
62 unsafe {
63 (*self.as_mut_ptr()).format = mem::transmute::<AVPixelFormat, c_int>(value.into());
64 }
65 }
66
67 #[inline]
68 pub fn kind(&self) -> picture::Type {
69 unsafe { picture::Type::from((*self.as_ptr()).pict_type) }
70 }
71
72 #[inline]
73 pub fn set_kind(&mut self, value: picture::Type) {
74 unsafe {
75 (*self.as_mut_ptr()).pict_type = value.into();
76 }
77 }
78
79 #[inline]
80 pub fn is_interlaced(&self) -> bool {
81 unsafe { (*self.as_ptr()).interlaced_frame != 0 }
82 }
83
84 #[inline]
85 pub fn is_top_first(&self) -> bool {
86 unsafe { (*self.as_ptr()).top_field_first != 0 }
87 }
88
89 #[inline]
90 pub fn has_palette_changed(&self) -> bool {
91 unsafe { (*self.as_ptr()).palette_has_changed != 0 }
92 }
93
94 #[inline]
95 pub fn width(&self) -> u32 {
96 unsafe { (*self.as_ptr()).width as u32 }
97 }
98
99 #[inline]
100 pub fn set_width(&mut self, value: u32) {
101 unsafe {
102 (*self.as_mut_ptr()).width = value as c_int;
103 }
104 }
105
106 #[inline]
107 pub fn height(&self) -> u32 {
108 unsafe { (*self.as_ptr()).height as u32 }
109 }
110
111 #[inline]
112 pub fn set_height(&mut self, value: u32) {
113 unsafe {
114 (*self.as_mut_ptr()).height = value as c_int;
115 }
116 }
117
118 #[inline]
119 pub fn color_space(&self) -> color::Space {
120 unsafe { color::Space::from((*self.as_ptr()).colorspace) }
121 }
122
123 #[inline]
124 pub fn set_color_space(&mut self, value: color::Space) {
125 unsafe {
126 (*self.as_mut_ptr()).colorspace = value.into();
127 }
128 }
129
130 #[inline]
131 pub fn color_range(&self) -> color::Range {
132 unsafe { color::Range::from((*self.as_ptr()).color_range) }
133 }
134
135 #[inline]
136 pub fn set_color_range(&mut self, value: color::Range) {
137 unsafe {
138 (*self.as_mut_ptr()).color_range = value.into();
139 }
140 }
141
142 #[inline]
143 pub fn color_primaries(&self) -> color::Primaries {
144 unsafe { color::Primaries::from((*self.as_ptr()).color_primaries) }
145 }
146
147 #[inline]
148 pub fn set_color_primaries(&mut self, value: color::Primaries) {
149 unsafe {
150 (*self.as_mut_ptr()).color_primaries = value.into();
151 }
152 }
153
154 #[inline]
155 pub fn color_transfer_characteristic(&self) -> color::TransferCharacteristic {
156 unsafe { color::TransferCharacteristic::from((*self.as_ptr()).color_trc) }
157 }
158
159 #[inline]
160 pub fn set_color_transfer_characteristic(&mut self, value: color::TransferCharacteristic) {
161 unsafe {
162 (*self.as_mut_ptr()).color_trc = value.into();
163 }
164 }
165
166 #[inline]
167 pub fn chroma_location(&self) -> chroma::Location {
168 unsafe { chroma::Location::from((*self.as_ptr()).chroma_location) }
169 }
170
171 #[inline]
172 pub fn aspect_ratio(&self) -> Rational {
173 unsafe { Rational::from((*self.as_ptr()).sample_aspect_ratio) }
174 }
175
176 #[inline]
177 pub fn coded_number(&self) -> usize {
178 unsafe { (*self.as_ptr()).coded_picture_number as usize }
179 }
180
181 #[inline]
182 pub fn display_number(&self) -> usize {
183 unsafe { (*self.as_ptr()).display_picture_number as usize }
184 }
185
186 #[inline]
187 pub fn repeat(&self) -> f64 {
188 unsafe { f64::from((*self.as_ptr()).repeat_pict) }
189 }
190
191 #[inline]
192 pub fn stride(&self, index: usize) -> usize {
193 if index >= self.planes() {
194 panic!("out of bounds");
195 }
196
197 unsafe { (*self.as_ptr()).linesize[index] as usize }
198 }
199
200 #[inline]
201 pub fn planes(&self) -> usize {
202 for i in 0..8 {
203 unsafe {
204 if (*self.as_ptr()).linesize[i] == 0 {
205 return i;
206 }
207 }
208 }
209
210 8
211 }
212
213 #[inline]
214 pub fn plane_width(&self, index: usize) -> u32 {
215 if index >= self.planes() {
216 panic!("out of bounds");
217 }
218
219 // Logic taken from image_get_linesize().
220 if index != 1 && index != 2 {
221 return self.width();
222 }
223
224 if let Some(desc) = self.format().descriptor() {
225 let s = desc.log2_chroma_w();
226 (self.width() + (1 << s) - 1) >> s
227 } else {
228 self.width()
229 }
230 }
231
232 #[inline]
233 pub fn plane_height(&self, index: usize) -> u32 {
234 if index >= self.planes() {
235 panic!("out of bounds");
236 }
237
238 // Logic taken from av_image_fill_pointers().
239 if index != 1 && index != 2 {
240 return self.height();
241 }
242
243 if let Some(desc) = self.format().descriptor() {
244 let s = desc.log2_chroma_h();
245 (self.height() + (1 << s) - 1) >> s
246 } else {
247 self.height()
248 }
249 }
250
251 #[inline]
252 pub fn plane<T: Component>(&self, index: usize) -> &[T] {
253 if index >= self.planes() {
254 panic!("out of bounds");
255 }
256
257 if !<T as Component>::is_valid(self.format()) {
258 panic!("unsupported type");
259 }
260
261 unsafe {
262 slice::from_raw_parts(
263 (*self.as_ptr()).data[index] as *const T,
264 self.stride(index) * self.plane_height(index) as usize / mem::size_of::<T>(),
265 )
266 }
267 }
268
269 #[inline]
270 pub fn plane_mut<T: Component>(&mut self, index: usize) -> &mut [T] {
271 if index >= self.planes() {
272 panic!("out of bounds");
273 }
274
275 if !<T as Component>::is_valid(self.format()) {
276 panic!("unsupported type");
277 }
278
279 unsafe {
280 slice::from_raw_parts_mut(
281 (*self.as_mut_ptr()).data[index] as *mut T,
282 self.stride(index) * self.plane_height(index) as usize / mem::size_of::<T>(),
283 )
284 }
285 }
286
287 #[inline]
288 pub fn data(&self, index: usize) -> &[u8] {
289 if index >= self.planes() {
290 panic!("out of bounds");
291 }
292
293 unsafe {
294 slice::from_raw_parts(
295 (*self.as_ptr()).data[index],
296 self.stride(index) * self.plane_height(index) as usize,
297 )
298 }
299 }
300
301 #[inline]
302 pub fn data_mut(&mut self, index: usize) -> &mut [u8] {
303 if index >= self.planes() {
304 panic!("out of bounds");
305 }
306
307 unsafe {
308 slice::from_raw_parts_mut(
309 (*self.as_mut_ptr()).data[index],
310 self.stride(index) * self.plane_height(index) as usize,
311 )
312 }
313 }
314}
315
316impl Deref for Video {
317 type Target = Frame;
318
319 #[inline]
320 fn deref(&self) -> &Frame {
321 &self.0
322 }
323}
324
325impl DerefMut for Video {
326 #[inline]
327 fn deref_mut(&mut self) -> &mut Frame {
328 &mut self.0
329 }
330}
331
332impl Clone for Video {
333 #[inline]
334 fn clone(&self) -> Self {
335 let mut cloned: Video = Video::new(self.format(), self.width(), self.height());
336 cloned.clone_from(self);
337
338 cloned
339 }
340
341 #[inline]
342 fn clone_from(&mut self, source: &Self) {
343 unsafe {
344 av_frame_copy(self.as_mut_ptr(), source.as_ptr());
345 av_frame_copy_props(self.as_mut_ptr(), source.as_ptr());
346 }
347 }
348}
349
350impl From<Frame> for Video {
351 #[inline]
352 fn from(frame: Frame) -> Self {
353 Video(frame)
354 }
355}
356
357pub unsafe trait Component {
358 fn is_valid(format: format::Pixel) -> bool;
359}
360
361#[cfg(feature = "image")]
362unsafe impl Component for ::image::Luma<u8> {
363 #[inline(always)]
364 fn is_valid(format: format::Pixel) -> bool {
365 format == format::Pixel::GRAY8
366 }
367}
368
369#[cfg(feature = "image")]
370unsafe impl Component for ::image::Rgb<u8> {
371 #[inline(always)]
372 fn is_valid(format: format::Pixel) -> bool {
373 format == format::Pixel::RGB24
374 }
375}
376
377#[cfg(feature = "image")]
378unsafe impl Component for ::image::Rgba<u8> {
379 #[inline(always)]
380 fn is_valid(format: format::Pixel) -> bool {
381 format == format::Pixel::RGBA
382 }
383}
384
385unsafe impl Component for [u8; 3] {
386 #[inline(always)]
387 fn is_valid(format: format::Pixel) -> bool {
388 format == format::Pixel::RGB24 || format == format::Pixel::BGR24
389 }
390}
391
392unsafe impl Component for (u8, u8, u8) {
393 #[inline(always)]
394 fn is_valid(format: format::Pixel) -> bool {
395 format == format::Pixel::RGB24 || format == format::Pixel::BGR24
396 }
397}
398
399unsafe impl Component for [u8; 4] {
400 #[inline(always)]
401 fn is_valid(format: format::Pixel) -> bool {
402 format == format::Pixel::RGBA
403 || format == format::Pixel::BGRA
404 || format == format::Pixel::ARGB
405 || format == format::Pixel::ABGR
406 || format == format::Pixel::RGBZ
407 || format == format::Pixel::BGRZ
408 || format == format::Pixel::ZRGB
409 || format == format::Pixel::ZBGR
410 }
411}
412
413unsafe impl Component for (u8, u8, u8, u8) {
414 #[inline(always)]
415 fn is_valid(format: format::Pixel) -> bool {
416 format == format::Pixel::RGBA
417 || format == format::Pixel::BGRA
418 || format == format::Pixel::ARGB
419 || format == format::Pixel::ABGR
420 || format == format::Pixel::RGBZ
421 || format == format::Pixel::BGRZ
422 || format == format::Pixel::ZRGB
423 || format == format::Pixel::ZBGR
424 }
425}
426