ffmpeg_next_crossfix/util/frame/
video.rs

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(av_frame_get_colorspace(self.as_ptr())) }
121    }
122
123    #[inline]
124    pub fn set_color_space(&mut self, value: color::Space) {
125        unsafe {
126            av_frame_set_colorspace(self.as_mut_ptr(), value.into());
127        }
128    }
129
130    #[inline]
131    pub fn color_range(&self) -> color::Range {
132        unsafe { color::Range::from(av_frame_get_color_range(self.as_ptr())) }
133    }
134
135    #[inline]
136    pub fn set_color_range(&mut self, value: color::Range) {
137        unsafe {
138            av_frame_set_color_range(self.as_mut_ptr(), 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::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}