ac_ffmpeg/codec/video/
frame.rs

1//! Video frame.
2
3use std::{
4    ffi::{CStr, CString},
5    fmt::{self, Display, Formatter},
6    marker::PhantomData,
7    ops::{Deref, DerefMut},
8    os::raw::{c_char, c_int, c_void},
9    ptr,
10    slice::{self, Chunks, ChunksMut},
11    str::FromStr,
12};
13
14use crate::time::{TimeBase, Timestamp};
15
16extern "C" {
17    fn ffw_get_pixel_format_by_name(name: *const c_char) -> c_int;
18    fn ffw_pixel_format_is_none(format: c_int) -> c_int;
19    fn ffw_get_pixel_format_name(format: c_int) -> *const c_char;
20
21    fn ffw_frame_new_black(pixel_format: c_int, width: c_int, height: c_int) -> *mut c_void;
22    fn ffw_frame_get_format(frame: *const c_void) -> c_int;
23    fn ffw_frame_get_width(frame: *const c_void) -> c_int;
24    fn ffw_frame_get_height(frame: *const c_void) -> c_int;
25    fn ffw_frame_get_best_effort_timestamp(frame: *const c_void) -> i64;
26    fn ffw_frame_get_pts(frame: *const c_void) -> i64;
27    fn ffw_frame_set_pts(frame: *mut c_void, pts: i64);
28    fn ffw_frame_get_plane_data(frame: *mut c_void, index: usize) -> *mut u8;
29    fn ffw_frame_get_line_size(frame: *const c_void, plane: usize) -> usize;
30    fn ffw_frame_get_line_count(frame: *const c_void, plane: usize) -> usize;
31    fn ffw_frame_clone(frame: *const c_void) -> *mut c_void;
32    fn ffw_frame_free(frame: *mut c_void);
33    fn ffw_frame_is_writable(frame: *const c_void) -> c_int;
34    fn ffw_frame_make_writable(frame: *mut c_void) -> c_int;
35    fn ffw_frame_get_picture_type(frame: *const c_void) -> c_int;
36    fn ffw_frame_set_picture_type(frame: *mut c_void, picture_type: c_int);
37}
38
39#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
40pub enum PictureType {
41    None = 0,
42    /// Intra.
43    I = 1,
44    /// Predicted.
45    P = 2,
46    /// Bi-dir predicted.
47    B = 3,
48    /// S(GMC)-VOP MPEG4.
49    S = 4,
50    /// Switching Intra.
51    Si = 5,
52    /// Switching Predicted.
53    Sp = 6,
54    /// BI type.
55    Bi = 7,
56}
57
58impl PictureType {
59    pub(crate) fn from_raw(value: c_int) -> Self {
60        match value {
61            1 => PictureType::I,
62            2 => PictureType::P,
63            3 => PictureType::B,
64            4 => PictureType::S,
65            5 => PictureType::Si,
66            6 => PictureType::Sp,
67            7 => PictureType::Bi,
68            _ => PictureType::None,
69        }
70    }
71}
72
73/// An error indicating an unknown pixel format.
74#[derive(Debug, Copy, Clone)]
75pub struct UnknownPixelFormat;
76
77impl Display for UnknownPixelFormat {
78    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
79        f.write_str("unknown pixel format")
80    }
81}
82
83impl std::error::Error for UnknownPixelFormat {}
84
85/// Pixel format.
86#[derive(Copy, Clone, Eq, PartialEq)]
87pub struct PixelFormat(c_int);
88
89impl PixelFormat {
90    /// Create a pixel format value from a given raw representation.
91    pub(crate) fn from_raw(v: c_int) -> Self {
92        Self(v)
93    }
94
95    /// Get the raw value.
96    pub(crate) fn into_raw(self) -> c_int {
97        let Self(format) = self;
98
99        format
100    }
101
102    /// Get name of the pixel format.
103    pub fn name(self) -> &'static str {
104        unsafe {
105            let ptr = ffw_get_pixel_format_name(self.into_raw());
106
107            if ptr.is_null() {
108                panic!("invalid pixel format");
109            }
110
111            let name = CStr::from_ptr(ptr as _);
112
113            name.to_str().unwrap()
114        }
115    }
116}
117
118impl FromStr for PixelFormat {
119    type Err = UnknownPixelFormat;
120
121    fn from_str(s: &str) -> Result<Self, Self::Err> {
122        let name = CString::new(s).expect("invalid pixel format name");
123
124        unsafe {
125            let format = ffw_get_pixel_format_by_name(name.as_ptr() as _);
126
127            if ffw_pixel_format_is_none(format) == 0 {
128                Ok(Self(format))
129            } else {
130                Err(UnknownPixelFormat)
131            }
132        }
133    }
134}
135
136/// Get a pixel format with a given name.
137pub fn get_pixel_format(name: &str) -> PixelFormat {
138    PixelFormat::from_str(name).unwrap()
139}
140
141/// Picture plane (i.e. a planar array of pixel components).
142pub struct Plane<'a> {
143    frame: *mut c_void,
144    index: usize,
145    phantom: PhantomData<&'a ()>,
146}
147
148impl Plane<'_> {
149    /// Create a new plane.
150    fn new(frame: *mut c_void, index: usize) -> Self {
151        Self {
152            frame,
153            index,
154            phantom: PhantomData,
155        }
156    }
157
158    /// Get plane data.
159    pub fn data(&self) -> &[u8] {
160        let line_size = self.line_size();
161        let line_count = self.line_count();
162
163        unsafe {
164            let data = ffw_frame_get_plane_data(self.frame, self.index as _);
165
166            slice::from_raw_parts(data, line_size * line_count)
167        }
168    }
169
170    /// Get mutable plane data.
171    pub fn data_mut(&mut self) -> &mut [u8] {
172        let line_size = self.line_size();
173        let line_count = self.line_count();
174
175        unsafe {
176            let data = ffw_frame_get_plane_data(self.frame, self.index as _);
177
178            slice::from_raw_parts_mut(data, line_size * line_count)
179        }
180    }
181
182    /// Get a single line.
183    pub fn line(&self, index: usize) -> Option<&[u8]> {
184        if index < self.line_count() {
185            let line_size = self.line_size();
186            let data = self.data();
187            let offset = index * line_size;
188
189            Some(&data[offset..offset + line_size])
190        } else {
191            None
192        }
193    }
194
195    /// Get a single mutable line.
196    pub fn line_mut(&mut self, index: usize) -> Option<&mut [u8]> {
197        if index < self.line_count() {
198            let line_size = self.line_size();
199            let data = self.data_mut();
200            let offset = index * line_size;
201
202            Some(&mut data[offset..offset + line_size])
203        } else {
204            None
205        }
206    }
207
208    /// Get an iterator over all lines.
209    pub fn lines(&self) -> LinesIter {
210        let line_size = self.line_size();
211        let data = self.data();
212
213        LinesIter::new(data.chunks(line_size))
214    }
215
216    /// Get an iterator over all mutable lines.
217    pub fn lines_mut(&mut self) -> LinesIterMut {
218        let line_size = self.line_size();
219        let data = self.data_mut();
220
221        LinesIterMut::new(data.chunks_mut(line_size))
222    }
223
224    /// Get line size (note: the line size doesn't necessarily need to be equal to picture width).
225    pub fn line_size(&self) -> usize {
226        unsafe { ffw_frame_get_line_size(self.frame, self.index as _) as _ }
227    }
228
229    /// Get number of lines (note: the number of lines doesn't necessarily need to be equal to
230    /// to picture height).
231    pub fn line_count(&self) -> usize {
232        unsafe { ffw_frame_get_line_count(self.frame, self.index as _) as _ }
233    }
234}
235
236/// Iterator over plane lines.
237pub struct LinesIter<'a> {
238    inner: Chunks<'a, u8>,
239}
240
241impl<'a> LinesIter<'a> {
242    /// Create a new iterator.
243    fn new(chunks: Chunks<'a, u8>) -> Self {
244        Self { inner: chunks }
245    }
246}
247
248impl<'a> Iterator for LinesIter<'a> {
249    type Item = &'a [u8];
250
251    fn next(&mut self) -> Option<Self::Item> {
252        self.inner.next()
253    }
254}
255
256/// Iterator over plane lines.
257pub struct LinesIterMut<'a> {
258    inner: ChunksMut<'a, u8>,
259}
260
261impl<'a> LinesIterMut<'a> {
262    /// Create a new iterator.
263    fn new(chunks: ChunksMut<'a, u8>) -> Self {
264        Self { inner: chunks }
265    }
266}
267
268impl<'a> Iterator for LinesIterMut<'a> {
269    type Item = &'a mut [u8];
270
271    fn next(&mut self) -> Option<Self::Item> {
272        self.inner.next()
273    }
274}
275
276/// A collection of picture planes.
277pub struct Planes<'a> {
278    inner: [Plane<'a>; 4],
279}
280
281impl<'a> From<&'a VideoFrame> for Planes<'a> {
282    fn from(frame: &'a VideoFrame) -> Self {
283        let inner = [
284            Plane::new(frame.ptr, 0),
285            Plane::new(frame.ptr, 1),
286            Plane::new(frame.ptr, 2),
287            Plane::new(frame.ptr, 3),
288        ];
289
290        Self { inner }
291    }
292}
293
294impl<'a> From<&'a VideoFrameMut> for Planes<'a> {
295    fn from(frame: &'a VideoFrameMut) -> Self {
296        let inner = [
297            Plane::new(frame.ptr, 0),
298            Plane::new(frame.ptr, 1),
299            Plane::new(frame.ptr, 2),
300            Plane::new(frame.ptr, 3),
301        ];
302
303        Self { inner }
304    }
305}
306
307impl<'a> Deref for Planes<'a> {
308    type Target = [Plane<'a>];
309
310    #[inline]
311    fn deref(&self) -> &Self::Target {
312        &self.inner
313    }
314}
315
316/// A collection of mutable picture planes.
317pub struct PlanesMut<'a> {
318    inner: [Plane<'a>; 4],
319}
320
321impl<'a> From<&'a mut VideoFrameMut> for PlanesMut<'a> {
322    fn from(frame: &'a mut VideoFrameMut) -> Self {
323        // NOTE: creating multiple mutable references to the frame is safe here because the planes
324        // are distinct
325        let inner = [
326            Plane::new(frame.ptr, 0),
327            Plane::new(frame.ptr, 1),
328            Plane::new(frame.ptr, 2),
329            Plane::new(frame.ptr, 3),
330        ];
331
332        Self { inner }
333    }
334}
335
336impl<'a> Deref for PlanesMut<'a> {
337    type Target = [Plane<'a>];
338
339    #[inline]
340    fn deref(&self) -> &Self::Target {
341        &self.inner
342    }
343}
344
345impl DerefMut for PlanesMut<'_> {
346    #[inline]
347    fn deref_mut(&mut self) -> &mut Self::Target {
348        &mut self.inner
349    }
350}
351
352/// A video frame with mutable data.
353pub struct VideoFrameMut {
354    ptr: *mut c_void,
355    time_base: TimeBase,
356}
357
358impl VideoFrameMut {
359    /// Create a black video frame. The time base of the frame will be in
360    /// microseconds.
361    pub fn black(pixel_format: PixelFormat, width: usize, height: usize) -> Self {
362        let ptr = unsafe { ffw_frame_new_black(pixel_format.into_raw(), width as _, height as _) };
363
364        if ptr.is_null() {
365            panic!("unable to allocate a video frame");
366        }
367
368        VideoFrameMut {
369            ptr,
370            time_base: TimeBase::MICROSECONDS,
371        }
372    }
373
374    /// Get frame pixel format.
375    pub fn pixel_format(&self) -> PixelFormat {
376        unsafe { PixelFormat::from_raw(ffw_frame_get_format(self.ptr)) }
377    }
378
379    /// Get frame width.
380    pub fn width(&self) -> usize {
381        unsafe { ffw_frame_get_width(self.ptr) as _ }
382    }
383
384    /// Get frame height.
385    pub fn height(&self) -> usize {
386        unsafe { ffw_frame_get_height(self.ptr) as _ }
387    }
388
389    /// Get frame time base.
390    #[inline]
391    pub fn time_base(&self) -> TimeBase {
392        self.time_base
393    }
394
395    /// Set frame time base. (This will rescale the current timestamp into a
396    /// given time base.)
397    pub fn with_time_base(mut self, time_base: TimeBase) -> Self {
398        let new_pts = self.pts().with_time_base(time_base);
399
400        unsafe {
401            ffw_frame_set_pts(self.ptr, new_pts.timestamp());
402        }
403
404        self.time_base = time_base;
405
406        self
407    }
408
409    /// Get presentation timestamp.
410    pub fn pts(&self) -> Timestamp {
411        let pts = unsafe { ffw_frame_get_pts(self.ptr) };
412
413        Timestamp::new(pts, self.time_base)
414    }
415
416    /// Set presentation timestamp.
417    pub fn with_pts(self, pts: Timestamp) -> Self {
418        let pts = pts.with_time_base(self.time_base);
419
420        unsafe { ffw_frame_set_pts(self.ptr, pts.timestamp()) }
421
422        self
423    }
424
425    /// Get picture type
426    pub fn picture_type(&self) -> PictureType {
427        unsafe { PictureType::from_raw(ffw_frame_get_picture_type(self.ptr)) }
428    }
429
430    /// Set picture type
431    pub fn with_picture_type(self, picture_type: PictureType) -> Self {
432        unsafe { ffw_frame_set_picture_type(self.ptr, picture_type as c_int) };
433        self
434    }
435
436    /// Get picture planes.
437    pub fn planes(&self) -> Planes {
438        Planes::from(self)
439    }
440
441    /// Get mutable picture planes.
442    pub fn planes_mut(&mut self) -> PlanesMut {
443        PlanesMut::from(self)
444    }
445
446    /// Make the frame immutable.
447    pub fn freeze(mut self) -> VideoFrame {
448        let ptr = self.ptr;
449
450        self.ptr = ptr::null_mut();
451
452        VideoFrame {
453            ptr,
454            time_base: self.time_base,
455        }
456    }
457}
458
459impl Drop for VideoFrameMut {
460    fn drop(&mut self) {
461        unsafe { ffw_frame_free(self.ptr) }
462    }
463}
464
465unsafe impl Send for VideoFrameMut {}
466unsafe impl Sync for VideoFrameMut {}
467
468/// A video frame with immutable data.
469pub struct VideoFrame {
470    ptr: *mut c_void,
471    time_base: TimeBase,
472}
473
474impl VideoFrame {
475    /// Create a new video frame from its raw representation.
476    pub(crate) unsafe fn from_raw_ptr(ptr: *mut c_void, time_base: TimeBase) -> Self {
477        Self { ptr, time_base }
478    }
479
480    /// Get frame pixel format.
481    pub fn pixel_format(&self) -> PixelFormat {
482        unsafe { PixelFormat::from_raw(ffw_frame_get_format(self.ptr)) }
483    }
484
485    /// Get frame width.
486    pub fn width(&self) -> usize {
487        unsafe { ffw_frame_get_width(self.ptr) as _ }
488    }
489
490    /// Get frame height.
491    pub fn height(&self) -> usize {
492        unsafe { ffw_frame_get_height(self.ptr) as _ }
493    }
494
495    /// Get picture planes.
496    pub fn planes(&self) -> Planes {
497        Planes::from(self)
498    }
499
500    /// Get frame time base.
501    #[inline]
502    pub fn time_base(&self) -> TimeBase {
503        self.time_base
504    }
505
506    /// Set frame time base. (This will rescale the current timestamp into a
507    /// given time base.)
508    pub fn with_time_base(mut self, time_base: TimeBase) -> Self {
509        let new_pts = self.pts().with_time_base(time_base);
510
511        unsafe {
512            ffw_frame_set_pts(self.ptr, new_pts.timestamp());
513        }
514
515        self.time_base = time_base;
516
517        self
518    }
519
520    /// Get timestamp estimated using various heuristics.
521    pub fn best_effort_timestamp(&self) -> Timestamp {
522        let pts = unsafe { ffw_frame_get_best_effort_timestamp(self.ptr) };
523
524        Timestamp::new(pts, self.time_base)
525    }
526
527    /// Get presentation timestamp.
528    pub fn pts(&self) -> Timestamp {
529        let pts = unsafe { ffw_frame_get_pts(self.ptr) };
530
531        Timestamp::new(pts, self.time_base)
532    }
533
534    /// Set presentation timestamp.
535    pub fn with_pts(self, pts: Timestamp) -> Self {
536        let pts = pts.with_time_base(self.time_base);
537
538        unsafe { ffw_frame_set_pts(self.ptr, pts.timestamp()) }
539
540        self
541    }
542
543    /// Get picture type
544    pub fn picture_type(&self) -> PictureType {
545        unsafe { PictureType::from_raw(ffw_frame_get_picture_type(self.ptr)) }
546    }
547
548    /// Get raw pointer.
549    pub(crate) fn as_ptr(&self) -> *const c_void {
550        self.ptr
551    }
552
553    /// Try to make this frame mutable. Returns VideoFrameMut if it can be made
554    /// into mutable without copying the data, otherwise returns VideoFrame.
555    pub fn try_into_mut(self) -> Result<VideoFrameMut, VideoFrame> {
556        let res = unsafe { ffw_frame_is_writable(self.ptr) };
557        if res > 0 {
558            Ok(self.into_mut())
559        } else {
560            Err(self)
561        }
562    }
563
564    /// Make this frame mutable. This will copy the data if it is not already
565    /// mutable.
566    pub fn into_mut(mut self) -> VideoFrameMut {
567        let res = unsafe { ffw_frame_make_writable(self.ptr) };
568
569        if res < 0 {
570            panic!("unable to make the frame mutable");
571        }
572
573        let ptr = self.ptr;
574
575        self.ptr = ptr::null_mut();
576
577        VideoFrameMut {
578            ptr,
579            time_base: self.time_base,
580        }
581    }
582}
583
584impl Clone for VideoFrame {
585    fn clone(&self) -> Self {
586        let ptr = unsafe { ffw_frame_clone(self.ptr) };
587
588        if ptr.is_null() {
589            panic!("unable to clone a frame");
590        }
591
592        Self {
593            ptr,
594            time_base: self.time_base,
595        }
596    }
597}
598
599impl Drop for VideoFrame {
600    fn drop(&mut self) {
601        unsafe { ffw_frame_free(self.ptr) }
602    }
603}
604
605unsafe impl Send for VideoFrame {}
606unsafe impl Sync for VideoFrame {}