dav1d/
lib.rs

1use dav1d_sys::*;
2
3pub use av_data::pixel;
4use std::ffi::c_void;
5use std::fmt;
6use std::i64;
7use std::mem;
8use std::ptr;
9use std::sync::Arc;
10
11/// Error enum return by various `dav1d` operations.
12#[derive(Debug, Copy, Clone, PartialEq, Eq)]
13#[non_exhaustive]
14pub enum Error {
15    /// Try again.
16    ///
17    /// If this is returned by [`Decoder::send_data`] or [`Decoder::send_pending_data`] then there
18    /// are decoded frames pending that first have to be retrieved via [`Decoder::get_picture`]
19    /// before processing any further pending data.
20    ///
21    /// If this is returned by [`Decoder::get_picture`] then no decoded frames are pending
22    /// currently and more data needs to be sent to the decoder.
23    Again,
24    /// Invalid argument.
25    ///
26    /// One of the arguments passed to the function was invalid.
27    InvalidArgument,
28    /// Not enough memory.
29    ///
30    /// Not enough memory is currently available for performing this operation.
31    NotEnoughMemory,
32    /// Unsupported bitstream.
33    ///
34    /// The provided bitstream is not supported by `dav1d`.
35    UnsupportedBitstream,
36    /// Unknown error.
37    UnknownError(i32),
38}
39
40impl From<i32> for Error {
41    fn from(err: i32) -> Self {
42        assert!(err < 0);
43
44        match err {
45            DAV1D_ERR_AGAIN => Error::Again,
46            DAV1D_ERR_INVAL => Error::InvalidArgument,
47            DAV1D_ERR_NOMEM => Error::NotEnoughMemory,
48            DAV1D_ERR_NOPROTOOPT => Error::UnsupportedBitstream,
49            _ => Error::UnknownError(err),
50        }
51    }
52}
53
54impl Error {
55    pub const fn is_again(&self) -> bool {
56        matches!(self, Error::Again)
57    }
58}
59
60impl fmt::Display for Error {
61    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
62        match self {
63            Error::Again => write!(fmt, "Try again"),
64            Error::InvalidArgument => write!(fmt, "Invalid argument"),
65            Error::NotEnoughMemory => write!(fmt, "Not enough memory available"),
66            Error::UnsupportedBitstream => write!(fmt, "Unsupported bitstream"),
67            Error::UnknownError(err) => write!(fmt, "Unknown error {}", err),
68        }
69    }
70}
71
72impl std::error::Error for Error {}
73
74/// Settings for creating a new [`Decoder`] instance.
75/// See documentation for native `Dav1dSettings` struct.
76#[derive(Debug)]
77pub struct Settings {
78    dav1d_settings: Dav1dSettings,
79}
80
81unsafe impl Send for Settings {}
82unsafe impl Sync for Settings {}
83
84impl Default for Settings {
85    fn default() -> Self {
86        Self::new()
87    }
88}
89
90impl Settings {
91    /// Creates a new [`Settings`] instance with default settings.
92    pub fn new() -> Self {
93        unsafe {
94            let mut dav1d_settings = mem::MaybeUninit::uninit();
95
96            dav1d_default_settings(dav1d_settings.as_mut_ptr());
97
98            Self {
99                dav1d_settings: dav1d_settings.assume_init(),
100            }
101        }
102    }
103
104    pub fn set_n_threads(&mut self, n_threads: u32) {
105        self.dav1d_settings.n_threads = n_threads as i32;
106    }
107
108    pub fn get_n_threads(&self) -> u32 {
109        self.dav1d_settings.n_threads as u32
110    }
111
112    pub fn set_max_frame_delay(&mut self, max_frame_delay: u32) {
113        self.dav1d_settings.max_frame_delay = max_frame_delay as i32;
114    }
115
116    pub fn get_max_frame_delay(&self) -> u32 {
117        self.dav1d_settings.max_frame_delay as u32
118    }
119
120    pub fn set_apply_grain(&mut self, apply_grain: bool) {
121        self.dav1d_settings.apply_grain = i32::from(apply_grain);
122    }
123
124    pub fn get_apply_grain(&self) -> bool {
125        self.dav1d_settings.apply_grain != 0
126    }
127
128    pub fn set_operating_point(&mut self, operating_point: u32) {
129        self.dav1d_settings.operating_point = operating_point as i32;
130    }
131
132    pub fn get_operating_point(&self) -> u32 {
133        self.dav1d_settings.operating_point as u32
134    }
135
136    pub fn set_all_layers(&mut self, all_layers: bool) {
137        self.dav1d_settings.all_layers = i32::from(all_layers);
138    }
139
140    pub fn get_all_layers(&self) -> bool {
141        self.dav1d_settings.all_layers != 0
142    }
143
144    pub fn set_frame_size_limit(&mut self, frame_size_limit: u32) {
145        self.dav1d_settings.frame_size_limit = frame_size_limit;
146    }
147
148    pub fn get_frame_size_limit(&self) -> u32 {
149        self.dav1d_settings.frame_size_limit
150    }
151
152    pub fn set_strict_std_compliance(&mut self, strict_std_compliance: bool) {
153        self.dav1d_settings.strict_std_compliance = i32::from(strict_std_compliance);
154    }
155
156    pub fn get_strict_std_compliance(&self) -> bool {
157        self.dav1d_settings.strict_std_compliance != 0
158    }
159
160    pub fn set_output_invisible_frames(&mut self, output_invisible_frames: bool) {
161        self.dav1d_settings.output_invisible_frames = i32::from(output_invisible_frames);
162    }
163
164    pub fn get_output_invisible_frames(&self) -> bool {
165        self.dav1d_settings.output_invisible_frames != 0
166    }
167
168    pub fn set_inloop_filters(&mut self, inloop_filters: InloopFilterType) {
169        self.dav1d_settings.inloop_filters = inloop_filters.bits();
170    }
171
172    pub fn get_inloop_filters(&self) -> InloopFilterType {
173        InloopFilterType::from_bits_truncate(self.dav1d_settings.inloop_filters)
174    }
175
176    pub fn set_decode_frame_type(&mut self, decode_frame_type: DecodeFrameType) {
177        self.dav1d_settings.decode_frame_type = decode_frame_type.into();
178    }
179
180    pub fn get_decode_frame_type(&self) -> DecodeFrameType {
181        DecodeFrameType::try_from(self.dav1d_settings.decode_frame_type)
182            .expect("Invalid Dav1dDecodeFrameType")
183    }
184}
185
186bitflags::bitflags! {
187    #[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
188    pub struct InloopFilterType: u32 {
189        const DEBLOCK = DAV1D_INLOOPFILTER_DEBLOCK;
190        const CDEF = DAV1D_INLOOPFILTER_CDEF;
191        const RESTORATION = DAV1D_INLOOPFILTER_RESTORATION;
192    }
193}
194
195#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
196pub enum DecodeFrameType {
197    #[default]
198    All,
199    Reference,
200    Intra,
201    Key,
202}
203
204impl TryFrom<u32> for DecodeFrameType {
205    type Error = TryFromEnumError;
206
207    fn try_from(value: u32) -> Result<Self, Self::Error> {
208        match value {
209            DAV1D_DECODEFRAMETYPE_ALL => Ok(DecodeFrameType::All),
210            DAV1D_DECODEFRAMETYPE_REFERENCE => Ok(DecodeFrameType::Reference),
211            DAV1D_DECODEFRAMETYPE_INTRA => Ok(DecodeFrameType::Intra),
212            DAV1D_DECODEFRAMETYPE_KEY => Ok(DecodeFrameType::Key),
213            _ => Err(TryFromEnumError(())),
214        }
215    }
216}
217
218impl From<DecodeFrameType> for u32 {
219    fn from(v: DecodeFrameType) -> u32 {
220        match v {
221            DecodeFrameType::All => DAV1D_DECODEFRAMETYPE_ALL,
222            DecodeFrameType::Reference => DAV1D_DECODEFRAMETYPE_REFERENCE,
223            DecodeFrameType::Intra => DAV1D_DECODEFRAMETYPE_INTRA,
224            DecodeFrameType::Key => DAV1D_DECODEFRAMETYPE_KEY,
225        }
226    }
227}
228
229/// The error type returned when a conversion from a C enum fails.
230#[derive(Debug, Copy, Clone, PartialEq, Eq)]
231pub struct TryFromEnumError(());
232
233impl std::fmt::Display for TryFromEnumError {
234    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
235        fmt.write_str("Invalid enum value")
236    }
237}
238
239impl From<std::convert::Infallible> for TryFromEnumError {
240    fn from(x: std::convert::Infallible) -> TryFromEnumError {
241        match x {}
242    }
243}
244
245impl std::error::Error for TryFromEnumError {}
246
247/// A `dav1d` decoder instance.
248#[derive(Debug)]
249pub struct Decoder {
250    dec: ptr::NonNull<Dav1dContext>,
251    pending_data: Option<Dav1dData>,
252}
253
254unsafe extern "C" fn release_wrapped_data<T: AsRef<[u8]>>(_data: *const u8, cookie: *mut c_void) {
255    let buf = Box::from_raw(cookie as *mut T);
256    drop(buf);
257}
258
259impl Decoder {
260    /// Creates a new [`Decoder`] instance with given [`Settings`].
261    pub fn with_settings(settings: &Settings) -> Result<Self, Error> {
262        unsafe {
263            let mut dec = mem::MaybeUninit::uninit();
264
265            let ret = dav1d_open(dec.as_mut_ptr(), &settings.dav1d_settings);
266
267            if ret < 0 {
268                return Err(Error::from(ret));
269            }
270
271            Ok(Decoder {
272                dec: ptr::NonNull::new(dec.assume_init()).unwrap(),
273                pending_data: None,
274            })
275        }
276    }
277
278    /// Creates a new [`Decoder`] instance with the default settings.
279    pub fn new() -> Result<Self, Error> {
280        Self::with_settings(&Settings::default())
281    }
282
283    /// Flush the decoder.
284    ///
285    /// This flushes all delayed frames in the decoder and clears the internal decoder state.
286    ///
287    /// All currently pending frames are available afterwards via [`Decoder::get_picture`].
288    pub fn flush(&mut self) {
289        unsafe {
290            dav1d_flush(self.dec.as_ptr());
291            if let Some(mut pending_data) = self.pending_data.take() {
292                dav1d_data_unref(&mut pending_data);
293            }
294        }
295    }
296
297    /// Send new AV1 data to the decoder.
298    ///
299    /// After this returned `Ok(())` or `Err([Error::Again])` there might be decoded frames
300    /// available via [`Decoder::get_picture`].
301    ///
302    /// # Panics
303    ///
304    /// If a previous call returned [`Error::Again`] then this must not be called again until
305    /// [`Decoder::send_pending_data`] has returned `Ok(())`.
306    pub fn send_data<T: AsRef<[u8]> + Send + 'static>(
307        &mut self,
308        buf: T,
309        offset: Option<i64>,
310        timestamp: Option<i64>,
311        duration: Option<i64>,
312    ) -> Result<(), Error> {
313        assert!(
314            self.pending_data.is_none(),
315            "Have pending data that needs to be handled first"
316        );
317
318        let buf = Box::new(buf);
319        let slice = (*buf).as_ref();
320        let len = slice.len();
321
322        unsafe {
323            let mut data: Dav1dData = mem::zeroed();
324            let _ret = dav1d_data_wrap(
325                &mut data,
326                slice.as_ptr(),
327                len,
328                Some(release_wrapped_data::<T>),
329                Box::into_raw(buf) as *mut c_void,
330            );
331            if let Some(offset) = offset {
332                data.m.offset = offset;
333            }
334            if let Some(timestamp) = timestamp {
335                data.m.timestamp = timestamp;
336            }
337            if let Some(duration) = duration {
338                data.m.duration = duration;
339            }
340
341            let ret = dav1d_send_data(self.dec.as_ptr(), &mut data);
342            if ret < 0 {
343                let ret = Error::from(ret);
344
345                if ret.is_again() {
346                    self.pending_data = Some(data);
347                } else {
348                    dav1d_data_unref(&mut data);
349                }
350
351                return Err(ret);
352            }
353
354            if data.sz > 0 {
355                self.pending_data = Some(data);
356                return Err(Error::Again);
357            }
358
359            Ok(())
360        }
361    }
362
363    /// Sends any pending data to the decoder.
364    ///
365    /// This has to be called after [`Decoder::send_data`] has returned `Err([Error::Again])` to
366    /// consume any futher pending data.
367    ///
368    /// After this returned `Ok(())` or `Err([Error::Again])` there might be decoded frames
369    /// available via [`Decoder::get_picture`].
370    pub fn send_pending_data(&mut self) -> Result<(), Error> {
371        let mut data = match self.pending_data.take() {
372            None => {
373                return Ok(());
374            }
375            Some(data) => data,
376        };
377
378        unsafe {
379            let ret = dav1d_send_data(self.dec.as_ptr(), &mut data);
380            if ret < 0 {
381                let ret = Error::from(ret);
382
383                if ret.is_again() {
384                    self.pending_data = Some(data);
385                } else {
386                    dav1d_data_unref(&mut data);
387                }
388
389                return Err(ret);
390            }
391
392            if data.sz > 0 {
393                self.pending_data = Some(data);
394                return Err(Error::Again);
395            }
396
397            Ok(())
398        }
399    }
400
401    /// Get the next decoded frame from the decoder.
402    ///
403    /// If this returns `Err([Error::Again])` then further data has to be sent to the decoder
404    /// before further decoded frames become available.
405    ///
406    /// To make most use of frame threading this function should only be called once per submitted
407    /// input frame and not until it returns `Err([Error::Again])`. Calling it in a loop should
408    /// only be done to drain all pending frames at the end.
409    pub fn get_picture(&mut self) -> Result<Picture, Error> {
410        unsafe {
411            let mut pic: Dav1dPicture = mem::zeroed();
412            let ret = dav1d_get_picture(self.dec.as_ptr(), &mut pic);
413
414            if ret < 0 {
415                Err(Error::from(ret))
416            } else {
417                let inner = InnerPicture { pic };
418                Ok(Picture {
419                    inner: Arc::new(inner),
420                })
421            }
422        }
423    }
424
425    /// Get the decoder delay.
426    pub fn get_frame_delay(&self) -> u32 {
427        unsafe { dav1d_get_frame_delay(self.dec.as_ptr()) as u32 }
428    }
429}
430
431impl Drop for Decoder {
432    fn drop(&mut self) {
433        unsafe {
434            if let Some(mut pending_data) = self.pending_data.take() {
435                dav1d_data_unref(&mut pending_data);
436            }
437            let mut dec = self.dec.as_ptr();
438            dav1d_close(&mut dec);
439        };
440    }
441}
442
443unsafe impl Send for Decoder {}
444unsafe impl Sync for Decoder {}
445
446#[derive(Debug)]
447struct InnerPicture {
448    pub pic: Dav1dPicture,
449}
450
451/// A decoded frame.
452#[derive(Debug, Clone)]
453pub struct Picture {
454    inner: Arc<InnerPicture>,
455}
456
457/// Pixel layout of a frame.
458#[derive(Debug, Eq, PartialEq, Copy, Clone)]
459pub enum PixelLayout {
460    /// Monochrome.
461    I400,
462    /// 4:2:0 planar.
463    I420,
464    /// 4:2:2 planar.
465    I422,
466    /// 4:4:4 planar.
467    I444,
468}
469
470/// Frame component.
471#[derive(Eq, PartialEq, Copy, Clone, Debug)]
472pub enum PlanarImageComponent {
473    /// Y component.
474    Y,
475    /// U component.
476    U,
477    /// V component.
478    V,
479}
480
481impl From<usize> for PlanarImageComponent {
482    fn from(index: usize) -> Self {
483        match index {
484            0 => PlanarImageComponent::Y,
485            1 => PlanarImageComponent::U,
486            2 => PlanarImageComponent::V,
487            _ => panic!("Invalid YUV index: {}", index),
488        }
489    }
490}
491
492impl From<PlanarImageComponent> for usize {
493    fn from(component: PlanarImageComponent) -> Self {
494        match component {
495            PlanarImageComponent::Y => 0,
496            PlanarImageComponent::U => 1,
497            PlanarImageComponent::V => 2,
498        }
499    }
500}
501
502/// A single plane of a decoded frame.
503///
504/// This can be used like a `&[u8]`.
505#[derive(Clone, Debug)]
506pub struct Plane(Picture, PlanarImageComponent);
507
508impl AsRef<[u8]> for Plane {
509    fn as_ref(&self) -> &[u8] {
510        let (stride, height) = self.0.plane_data_geometry(self.1);
511        unsafe {
512            std::slice::from_raw_parts(
513                self.0.plane_data_ptr(self.1) as *const u8,
514                (stride * height) as usize,
515            )
516        }
517    }
518}
519
520impl std::ops::Deref for Plane {
521    type Target = [u8];
522
523    fn deref(&self) -> &Self::Target {
524        self.as_ref()
525    }
526}
527
528static_assertions::assert_impl_all!(Plane: Send, Sync);
529
530/// Number of bits per component.
531#[derive(Copy, Clone, Debug, PartialEq, Eq)]
532pub struct BitsPerComponent(pub usize);
533
534impl Picture {
535    /// Stride in pixels of the `component` for the decoded frame.
536    pub fn stride(&self, component: PlanarImageComponent) -> u32 {
537        let s = match component {
538            PlanarImageComponent::Y => 0,
539            _ => 1,
540        };
541        self.inner.pic.stride[s] as u32
542    }
543
544    /// Raw pointer to the data of the `component` for the decoded frame.
545    pub fn plane_data_ptr(&self, component: PlanarImageComponent) -> *mut c_void {
546        let index: usize = component.into();
547        self.inner.pic.data[index]
548    }
549
550    /// Plane geometry of the `component` for the decoded frame.
551    ///
552    /// This returns the stride and height.
553    pub fn plane_data_geometry(&self, component: PlanarImageComponent) -> (u32, u32) {
554        let height = match component {
555            PlanarImageComponent::Y => self.height(),
556            _ => match self.pixel_layout() {
557                PixelLayout::I420 => (self.height() + 1) / 2,
558                PixelLayout::I400 | PixelLayout::I422 | PixelLayout::I444 => self.height(),
559            },
560        };
561        (self.stride(component), height)
562    }
563
564    /// Plane data of the `component` for the decoded frame.
565    pub fn plane(&self, component: PlanarImageComponent) -> Plane {
566        Plane(self.clone(), component)
567    }
568
569    /// Bit depth of the plane data.
570    ///
571    /// This returns 8 or 16 for the underlying integer type used for the plane data.
572    ///
573    /// Check [`Picture::bits_per_component`] for the number of bits that are used.
574    pub fn bit_depth(&self) -> usize {
575        self.inner.pic.p.bpc as usize
576    }
577
578    /// Bits used per component of the plane data.
579    ///
580    /// Check [`Picture::bit_depth`] for the number of storage bits.
581    pub fn bits_per_component(&self) -> Option<BitsPerComponent> {
582        unsafe {
583            match (*self.inner.pic.seq_hdr).hbd {
584                0 => Some(BitsPerComponent(8)),
585                1 => Some(BitsPerComponent(10)),
586                2 => Some(BitsPerComponent(12)),
587                _ => None,
588            }
589        }
590    }
591
592    /// Width of the frame.
593    pub fn width(&self) -> u32 {
594        self.inner.pic.p.w as u32
595    }
596
597    /// Height of the frame.
598    pub fn height(&self) -> u32 {
599        self.inner.pic.p.h as u32
600    }
601
602    /// Pixel layout of the frame.
603    pub fn pixel_layout(&self) -> PixelLayout {
604        #[allow(non_upper_case_globals)]
605        match self.inner.pic.p.layout {
606            DAV1D_PIXEL_LAYOUT_I400 => PixelLayout::I400,
607            DAV1D_PIXEL_LAYOUT_I420 => PixelLayout::I420,
608            DAV1D_PIXEL_LAYOUT_I422 => PixelLayout::I422,
609            DAV1D_PIXEL_LAYOUT_I444 => PixelLayout::I444,
610            _ => unreachable!(),
611        }
612    }
613
614    /// Timestamp of the frame.
615    ///
616    /// This is the same timestamp as the one provided to [`Decoder::send_data`].
617    pub fn timestamp(&self) -> Option<i64> {
618        let ts = self.inner.pic.m.timestamp;
619        if ts == i64::MIN {
620            None
621        } else {
622            Some(ts)
623        }
624    }
625
626    /// Duration of the frame.
627    ///
628    /// This is the same duration as the one provided to [`Decoder::send_data`] or `0` if none was
629    /// provided.
630    pub fn duration(&self) -> i64 {
631        self.inner.pic.m.duration
632    }
633
634    /// Offset of the frame.
635    ///
636    /// This is the same offset as the one provided to [`Decoder::send_data`] or `-1` if none was
637    /// provided.
638    pub fn offset(&self) -> i64 {
639        self.inner.pic.m.offset
640    }
641
642    /// Chromaticity coordinates of the source colour primaries.
643    pub fn color_primaries(&self) -> pixel::ColorPrimaries {
644        unsafe {
645            #[allow(non_upper_case_globals)]
646            match (*self.inner.pic.seq_hdr).pri {
647                DAV1D_COLOR_PRI_BT709 => pixel::ColorPrimaries::BT709,
648                DAV1D_COLOR_PRI_UNKNOWN => pixel::ColorPrimaries::Unspecified,
649                DAV1D_COLOR_PRI_BT470M => pixel::ColorPrimaries::BT470M,
650                DAV1D_COLOR_PRI_BT470BG => pixel::ColorPrimaries::BT470BG,
651                DAV1D_COLOR_PRI_BT601 => pixel::ColorPrimaries::BT470BG,
652                DAV1D_COLOR_PRI_SMPTE240 => pixel::ColorPrimaries::ST240M,
653                DAV1D_COLOR_PRI_FILM => pixel::ColorPrimaries::Film,
654                DAV1D_COLOR_PRI_BT2020 => pixel::ColorPrimaries::BT2020,
655                DAV1D_COLOR_PRI_XYZ => pixel::ColorPrimaries::ST428,
656                DAV1D_COLOR_PRI_SMPTE431 => pixel::ColorPrimaries::P3DCI,
657                DAV1D_COLOR_PRI_SMPTE432 => pixel::ColorPrimaries::P3Display,
658                DAV1D_COLOR_PRI_EBU3213 => pixel::ColorPrimaries::Tech3213,
659                23..=DAV1D_COLOR_PRI_RESERVED => pixel::ColorPrimaries::Unspecified,
660                _ => unreachable!(),
661            }
662        }
663    }
664
665    /// Transfer characteristics function.
666    pub fn transfer_characteristic(&self) -> pixel::TransferCharacteristic {
667        unsafe {
668            #[allow(non_upper_case_globals)]
669            match (*self.inner.pic.seq_hdr).trc {
670                DAV1D_TRC_BT709 => pixel::TransferCharacteristic::BT1886,
671                DAV1D_TRC_UNKNOWN => pixel::TransferCharacteristic::Unspecified,
672                DAV1D_TRC_BT470M => pixel::TransferCharacteristic::BT470M,
673                DAV1D_TRC_BT470BG => pixel::TransferCharacteristic::BT470BG,
674                DAV1D_TRC_BT601 => pixel::TransferCharacteristic::ST170M,
675                DAV1D_TRC_SMPTE240 => pixel::TransferCharacteristic::ST240M,
676                DAV1D_TRC_LINEAR => pixel::TransferCharacteristic::Linear,
677                DAV1D_TRC_LOG100 => pixel::TransferCharacteristic::Logarithmic100,
678                DAV1D_TRC_LOG100_SQRT10 => pixel::TransferCharacteristic::Logarithmic316,
679                DAV1D_TRC_IEC61966 => pixel::TransferCharacteristic::SRGB,
680                DAV1D_TRC_BT1361 => pixel::TransferCharacteristic::BT1886,
681                DAV1D_TRC_SRGB => pixel::TransferCharacteristic::SRGB,
682                DAV1D_TRC_BT2020_10BIT => pixel::TransferCharacteristic::BT2020Ten,
683                DAV1D_TRC_BT2020_12BIT => pixel::TransferCharacteristic::BT2020Twelve,
684                DAV1D_TRC_SMPTE2084 => pixel::TransferCharacteristic::PerceptualQuantizer,
685                DAV1D_TRC_SMPTE428 => pixel::TransferCharacteristic::ST428,
686                DAV1D_TRC_HLG => pixel::TransferCharacteristic::HybridLogGamma,
687                19..=DAV1D_TRC_RESERVED => pixel::TransferCharacteristic::Unspecified,
688                _ => unreachable!(),
689            }
690        }
691    }
692
693    /// Matrix coefficients used in deriving luma and chroma signals from the
694    /// green, blue and red or X, Y and Z primaries.
695    pub fn matrix_coefficients(&self) -> pixel::MatrixCoefficients {
696        unsafe {
697            #[allow(non_upper_case_globals)]
698            match (*self.inner.pic.seq_hdr).mtrx {
699                DAV1D_MC_IDENTITY => pixel::MatrixCoefficients::Identity,
700                DAV1D_MC_BT709 => pixel::MatrixCoefficients::BT709,
701                DAV1D_MC_UNKNOWN => pixel::MatrixCoefficients::Unspecified,
702                DAV1D_MC_FCC => pixel::MatrixCoefficients::BT470M,
703                DAV1D_MC_BT470BG => pixel::MatrixCoefficients::BT470BG,
704                DAV1D_MC_BT601 => pixel::MatrixCoefficients::BT470BG,
705                DAV1D_MC_SMPTE240 => pixel::MatrixCoefficients::ST240M,
706                DAV1D_MC_SMPTE_YCGCO => pixel::MatrixCoefficients::YCgCo,
707                DAV1D_MC_BT2020_NCL => pixel::MatrixCoefficients::BT2020NonConstantLuminance,
708                DAV1D_MC_BT2020_CL => pixel::MatrixCoefficients::BT2020ConstantLuminance,
709                DAV1D_MC_SMPTE2085 => pixel::MatrixCoefficients::ST2085,
710                DAV1D_MC_CHROMAT_NCL => {
711                    pixel::MatrixCoefficients::ChromaticityDerivedNonConstantLuminance
712                }
713                DAV1D_MC_CHROMAT_CL => {
714                    pixel::MatrixCoefficients::ChromaticityDerivedConstantLuminance
715                }
716                DAV1D_MC_ICTCP => pixel::MatrixCoefficients::ICtCp,
717                15..=DAV1D_MC_RESERVED => pixel::MatrixCoefficients::Unspecified,
718                _ => unreachable!(),
719            }
720        }
721    }
722
723    /// YUV color range.
724    pub fn color_range(&self) -> pixel::YUVRange {
725        unsafe {
726            match (*self.inner.pic.seq_hdr).color_range {
727                0 => pixel::YUVRange::Limited,
728                _ => pixel::YUVRange::Full,
729            }
730        }
731    }
732
733    /// Sample position for subsampled chroma.
734    pub fn chroma_location(&self) -> pixel::ChromaLocation {
735        // According to y4m mapping declared in dav1d's output/y4m2.c and applied from FFmpeg's yuv4mpegdec.c
736        unsafe {
737            match (*self.inner.pic.seq_hdr).chr {
738                DAV1D_CHR_UNKNOWN | DAV1D_CHR_COLOCATED => pixel::ChromaLocation::Center,
739                DAV1D_CHR_VERTICAL => pixel::ChromaLocation::Left,
740                _ => unreachable!(),
741            }
742        }
743    }
744}
745
746static_assertions::assert_impl_all!(Picture: Send, Sync);
747
748unsafe impl Send for InnerPicture {}
749unsafe impl Sync for InnerPicture {}
750
751impl Drop for InnerPicture {
752    fn drop(&mut self) {
753        unsafe {
754            dav1d_picture_unref(&mut self.pic);
755        }
756    }
757}