re_rav1d/
lib.rs

1#![allow(non_upper_case_globals)]
2#![cfg_attr(target_arch = "arm", feature(stdarch_arm_feature_detection))]
3#![cfg_attr(
4    any(target_arch = "riscv32", target_arch = "riscv64"),
5    feature(stdarch_riscv_feature_detection)
6)]
7#![deny(unsafe_op_in_unsafe_fn)]
8#![allow(clippy::all)]
9#![deny(clippy::undocumented_unsafe_blocks)]
10#![deny(clippy::missing_safety_doc)]
11
12#[cfg(not(any(feature = "bitdepth_8", feature = "bitdepth_16")))]
13compile_error!("No bitdepths enabled. Enable one or more of the following features: `bitdepth_8`, `bitdepth_16`");
14
15pub mod include {
16    pub mod common {
17        pub(crate) mod attributes;
18        pub(crate) mod bitdepth;
19        pub(crate) mod dump;
20        pub(crate) mod intops;
21        pub(crate) mod validate;
22    } // mod common
23    pub mod dav1d {
24        pub mod common;
25        pub mod data;
26        pub mod dav1d;
27        pub mod headers;
28        pub mod picture;
29    } // mod dav1d
30} // mod include
31pub mod src {
32    pub mod align;
33    pub(crate) mod assume;
34    pub(crate) mod c_arc;
35    pub(crate) mod c_box;
36    mod cdef;
37    mod cdef_apply;
38    mod cdf;
39    mod const_fn;
40    pub mod cpu;
41    mod ctx;
42    mod cursor;
43    mod data;
44    mod decode;
45    mod dequant_tables;
46    pub(crate) mod disjoint_mut;
47    pub(crate) mod enum_map;
48    mod env;
49    pub(crate) mod error;
50    mod ffi_safe;
51    mod fg_apply;
52    mod filmgrain;
53    mod getbits;
54    pub(crate) mod pic_or_buf;
55    pub(crate) mod pixels;
56    pub(crate) mod relaxed_atomic;
57    pub mod send_sync_non_null;
58    pub(crate) mod strided;
59    pub(crate) mod with_offset;
60    pub(crate) mod wrap_fn_ptr;
61    // TODO(kkysen) Temporarily `pub(crate)` due to a `pub use` until TAIT.
62    mod extensions;
63    mod in_range;
64    pub(super) mod internal;
65    mod intra_edge;
66    mod ipred;
67    mod ipred_prepare;
68    mod iter;
69    mod itx;
70    mod itx_1d;
71    pub(crate) mod levels;
72    mod lf_apply;
73    mod lf_mask;
74    pub mod lib;
75    pub(crate) mod log;
76    mod loopfilter;
77    mod looprestoration;
78    mod lr_apply;
79    mod mc;
80    mod mem;
81    mod msac;
82    mod obu;
83    mod pal;
84    mod picture;
85    mod qm;
86    mod recon;
87    mod refmvs;
88    mod scan;
89    mod tables;
90    mod thread_task;
91    mod warpmv;
92    mod wedge;
93} // mod src
94
95pub use src::error::Dav1dResult;
96
97// ---------------------------------------------------------------------------------------
98
99/// Public Rust API.
100///
101/// This is more or less the same API as <https://crates.io/crates/dav1d>,
102/// and is indeed a fork of that work.
103pub mod dav1d {
104    // This whole module was originally copied from https://github.com/rust-av/dav1d-rs/
105    // (specifically https://github.com/rust-av/dav1d-rs/blob/94b1deaa1e25bf29c77bb5cc8a08ddaf7663eede/src/lib.rs)
106    // with some modifications.
107    // `dav1d-rs` is under the MIT license, replicated here:
108
109    // MIT License
110    //
111    // Copyright (c) 2018 Luca Barbato
112    //
113    // Permission is hereby granted, free of charge, to any person obtaining a copy
114    // of this software and associated documentation files (the "Software"), to deal
115    // in the Software without restriction, including without limitation the rights
116    // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
117    // copies of the Software, and to permit persons to whom the Software is
118    // furnished to do so, subject to the following conditions:
119    //
120    // The above copyright notice and this permission notice shall be included in all
121    // copies or substantial portions of the Software.
122    //
123    // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
124    // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
125    // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
126    // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
127    // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
128    // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
129    // SOFTWARE.
130
131    // The code below provides a safe API around the rav1d C FFI layer.
132
133    use crate as rav1d;
134
135    pub use av_data::pixel;
136    use std::ffi::c_void;
137    use std::fmt;
138    use std::mem;
139    use std::ptr::NonNull;
140    use std::sync::Arc;
141
142    use rav1d::include::dav1d::data::*;
143    use rav1d::include::dav1d::dav1d::*;
144    use rav1d::include::dav1d::headers::*;
145    use rav1d::include::dav1d::picture::*;
146    use rav1d::src::error::{Rav1dError, Rav1dResult};
147    use rav1d::src::lib::*;
148    use rav1d::src::send_sync_non_null::SendSyncNonNull;
149    use rav1d::Dav1dResult;
150
151    fn option_nonnull<T>(ptr: *mut T) -> Option<NonNull<T>> {
152        if ptr.is_null() {
153            None
154        } else {
155            Some(NonNull::new(ptr).unwrap())
156        }
157    }
158
159    fn option_send_sync_non_null<T: Send + Sync>(r#box: Box<T>) -> Option<SendSyncNonNull<T>> {
160        Some(SendSyncNonNull::from_box(r#box))
161    }
162
163    fn rav1d_result(ret: Dav1dResult) -> Rav1dResult {
164        Rav1dResult::try_from(ret).unwrap()
165    }
166
167    /// Error enum return by various `dav1d` operations.
168    #[derive(Debug, Copy, Clone, PartialEq, Eq)]
169    #[non_exhaustive]
170    pub enum Error {
171        /// Try again.
172        ///
173        /// If this is returned by [`Decoder::send_data`] or [`Decoder::send_pending_data`] then there
174        /// are decoded frames pending that first have to be retrieved via [`Decoder::get_picture`]
175        /// before processing any further pending data.
176        ///
177        /// If this is returned by [`Decoder::get_picture`] then no decoded frames are pending
178        /// currently and more data needs to be sent to the decoder.
179        Again,
180        /// Invalid argument.
181        ///
182        /// One of the arguments passed to the function was invalid.
183        InvalidArgument,
184        /// Not enough memory.
185        ///
186        /// Not enough memory is currently available for performing this operation.
187        NotEnoughMemory,
188        /// Unsupported bitstream.
189        ///
190        /// The provided bitstream is not supported by `dav1d`.
191        UnsupportedBitstream,
192        /// Unknown error.
193        UnknownError(Rav1dError),
194    }
195
196    impl From<Rav1dError> for Error {
197        fn from(err: Rav1dError) -> Self {
198            match err {
199                Rav1dError::EAGAIN => Error::Again,
200                Rav1dError::ENOMEM => Error::NotEnoughMemory,
201                Rav1dError::EINVAL => Error::InvalidArgument,
202                Rav1dError::ENOPROTOOPT => Error::UnsupportedBitstream,
203                _ => Error::UnknownError(err),
204            }
205        }
206    }
207
208    impl Error {
209        pub const fn is_again(&self) -> bool {
210            matches!(self, Error::Again)
211        }
212    }
213
214    impl fmt::Display for Error {
215        fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
216            match self {
217                Error::Again => write!(fmt, "Try again"),
218                Error::InvalidArgument => write!(fmt, "Invalid argument"),
219                Error::NotEnoughMemory => write!(fmt, "Not enough memory available"),
220                Error::UnsupportedBitstream => write!(fmt, "Unsupported bitstream"),
221                Error::UnknownError(err) => write!(fmt, "Unknown error {err:?}"),
222            }
223        }
224    }
225
226    impl std::error::Error for Error {}
227
228    /// Settings for creating a new [`Decoder`] instance.
229    /// See documentation for native `Dav1dSettings` struct.
230    pub struct Settings {
231        dav1d_settings: Dav1dSettings,
232    }
233
234    unsafe impl Send for Settings {}
235    unsafe impl Sync for Settings {}
236
237    impl Default for Settings {
238        fn default() -> Self {
239            Self::new()
240        }
241    }
242
243    impl Settings {
244        /// Creates a new [`Settings`] instance with default settings.
245        pub fn new() -> Self {
246            unsafe {
247                let mut dav1d_settings = mem::MaybeUninit::uninit();
248
249                dav1d_default_settings(NonNull::new(dav1d_settings.as_mut_ptr()).unwrap());
250
251                Self {
252                    dav1d_settings: dav1d_settings.assume_init(),
253                }
254            }
255        }
256
257        pub fn set_n_threads(&mut self, n_threads: u32) {
258            self.dav1d_settings.n_threads = n_threads as i32;
259        }
260
261        pub fn get_n_threads(&self) -> u32 {
262            self.dav1d_settings.n_threads as u32
263        }
264
265        pub fn set_max_frame_delay(&mut self, max_frame_delay: u32) {
266            self.dav1d_settings.max_frame_delay = max_frame_delay as i32;
267        }
268
269        pub fn get_max_frame_delay(&self) -> u32 {
270            self.dav1d_settings.max_frame_delay as u32
271        }
272
273        pub fn set_apply_grain(&mut self, apply_grain: bool) {
274            self.dav1d_settings.apply_grain = i32::from(apply_grain);
275        }
276
277        pub fn get_apply_grain(&self) -> bool {
278            self.dav1d_settings.apply_grain != 0
279        }
280
281        pub fn set_operating_point(&mut self, operating_point: u32) {
282            self.dav1d_settings.operating_point = operating_point as i32;
283        }
284
285        pub fn get_operating_point(&self) -> u32 {
286            self.dav1d_settings.operating_point as u32
287        }
288
289        pub fn set_all_layers(&mut self, all_layers: bool) {
290            self.dav1d_settings.all_layers = i32::from(all_layers);
291        }
292
293        pub fn get_all_layers(&self) -> bool {
294            self.dav1d_settings.all_layers != 0
295        }
296
297        pub fn set_frame_size_limit(&mut self, frame_size_limit: u32) {
298            self.dav1d_settings.frame_size_limit = frame_size_limit;
299        }
300
301        pub fn get_frame_size_limit(&self) -> u32 {
302            self.dav1d_settings.frame_size_limit
303        }
304
305        pub fn set_strict_std_compliance(&mut self, strict_std_compliance: bool) {
306            self.dav1d_settings.strict_std_compliance = i32::from(strict_std_compliance);
307        }
308
309        pub fn get_strict_std_compliance(&self) -> bool {
310            self.dav1d_settings.strict_std_compliance != 0
311        }
312
313        pub fn set_output_invisible_frames(&mut self, output_invisible_frames: bool) {
314            self.dav1d_settings.output_invisible_frames = i32::from(output_invisible_frames);
315        }
316
317        pub fn get_output_invisible_frames(&self) -> bool {
318            self.dav1d_settings.output_invisible_frames != 0
319        }
320
321        pub fn set_inloop_filters(&mut self, inloop_filters: InloopFilterType) {
322            self.dav1d_settings.inloop_filters = inloop_filters.bits();
323        }
324
325        pub fn get_inloop_filters(&self) -> InloopFilterType {
326            InloopFilterType::from_bits_truncate(self.dav1d_settings.inloop_filters)
327        }
328
329        pub fn set_decode_frame_type(&mut self, decode_frame_type: DecodeFrameType) {
330            self.dav1d_settings.decode_frame_type = decode_frame_type.into();
331        }
332
333        pub fn get_decode_frame_type(&self) -> DecodeFrameType {
334            DecodeFrameType::try_from(self.dav1d_settings.decode_frame_type)
335                .expect("Invalid Dav1dDecodeFrameType")
336        }
337    }
338
339    bitflags::bitflags! {
340        #[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
341        pub struct InloopFilterType: u32 {
342            const DEBLOCK = DAV1D_INLOOPFILTER_DEBLOCK;
343            const CDEF = DAV1D_INLOOPFILTER_CDEF;
344            const RESTORATION = DAV1D_INLOOPFILTER_RESTORATION;
345        }
346    }
347
348    #[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
349    pub enum DecodeFrameType {
350        #[default]
351        All,
352        Reference,
353        Intra,
354        Key,
355    }
356
357    impl TryFrom<u32> for DecodeFrameType {
358        type Error = TryFromEnumError;
359
360        fn try_from(value: u32) -> Result<Self, Self::Error> {
361            match value {
362                DAV1D_DECODEFRAMETYPE_ALL => Ok(DecodeFrameType::All),
363                DAV1D_DECODEFRAMETYPE_REFERENCE => Ok(DecodeFrameType::Reference),
364                DAV1D_DECODEFRAMETYPE_INTRA => Ok(DecodeFrameType::Intra),
365                DAV1D_DECODEFRAMETYPE_KEY => Ok(DecodeFrameType::Key),
366                _ => Err(TryFromEnumError(())),
367            }
368        }
369    }
370
371    impl From<DecodeFrameType> for u32 {
372        fn from(v: DecodeFrameType) -> u32 {
373            match v {
374                DecodeFrameType::All => DAV1D_DECODEFRAMETYPE_ALL,
375                DecodeFrameType::Reference => DAV1D_DECODEFRAMETYPE_REFERENCE,
376                DecodeFrameType::Intra => DAV1D_DECODEFRAMETYPE_INTRA,
377                DecodeFrameType::Key => DAV1D_DECODEFRAMETYPE_KEY,
378            }
379        }
380    }
381
382    /// The error type returned when a conversion from a C enum fails.
383    #[derive(Debug, Copy, Clone, PartialEq, Eq)]
384    pub struct TryFromEnumError(());
385
386    impl std::fmt::Display for TryFromEnumError {
387        fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
388            fmt.write_str("Invalid enum value")
389        }
390    }
391
392    impl From<std::convert::Infallible> for TryFromEnumError {
393        fn from(x: std::convert::Infallible) -> TryFromEnumError {
394            match x {}
395        }
396    }
397
398    impl std::error::Error for TryFromEnumError {}
399
400    /// A `dav1d` decoder instance.
401    pub struct Decoder {
402        dec: Dav1dContext,
403        pending_data: Option<Dav1dData>,
404    }
405
406    unsafe extern "C" fn release_wrapped_data<T: AsRef<[u8]>>(
407        _data: *const u8,
408        cookie: Option<SendSyncNonNull<std::ffi::c_void>>,
409    ) {
410        let cookie = cookie.unwrap().as_ptr().as_ptr();
411        let buf = unsafe { Box::from_raw(cookie as *mut T) };
412        drop(buf);
413    }
414
415    impl Decoder {
416        /// Creates a new [`Decoder`] instance with given [`Settings`].
417        pub fn with_settings(settings: &Settings) -> Result<Self, Error> {
418            unsafe {
419                let mut dec = mem::MaybeUninit::uninit();
420
421                let ret = dav1d_open(
422                    Some(NonNull::new(dec.as_mut_ptr()).unwrap()),
423                    Some(NonNull::new(&settings.dav1d_settings as *const _ as *mut _).unwrap()),
424                );
425
426                match rav1d_result(ret) {
427                    Ok(_) => Ok(Decoder {
428                        dec: dec.assume_init().unwrap(),
429                        pending_data: None,
430                    }),
431                    Err(err) => Err(Error::from(err)),
432                }
433            }
434        }
435
436        /// Creates a new [`Decoder`] instance with the default settings.
437        pub fn new() -> Result<Self, Error> {
438            Self::with_settings(&Settings::default())
439        }
440
441        /// Flush the decoder.
442        ///
443        /// This flushes all delayed frames in the decoder and clears the internal decoder state.
444        ///
445        /// All currently pending frames are available afterwards via [`Decoder::get_picture`].
446        pub fn flush(&mut self) {
447            unsafe {
448                dav1d_flush(self.dec);
449                if let Some(mut pending_data) = self.pending_data.take() {
450                    dav1d_data_unref(Some(NonNull::new(&mut pending_data).unwrap()));
451                }
452            }
453        }
454
455        /// Send new AV1 data to the decoder.
456        ///
457        /// After this returned `Ok(())` or `Err([Error::Again])` there might be decoded frames
458        /// available via [`Decoder::get_picture`].
459        ///
460        /// # Panics
461        ///
462        /// If a previous call returned [`Error::Again`] then this must not be called again until
463        /// [`Decoder::send_pending_data`] has returned `Ok(())`.
464        pub fn send_data<T: AsRef<[u8]> + Send + Sync + 'static>(
465            &mut self,
466            buf: T,
467            offset: Option<i64>,
468            timestamp: Option<i64>,
469            duration: Option<i64>,
470        ) -> Result<(), Error> {
471            assert!(
472                self.pending_data.is_none(),
473                "Have pending data that needs to be handled first"
474            );
475
476            let buf = Box::new(buf);
477            let slice = (*buf).as_ref();
478            let len = slice.len();
479
480            unsafe {
481                let mut data: Dav1dData = mem::zeroed();
482                let _ret = dav1d_data_wrap(
483                    option_nonnull(&mut data),
484                    option_nonnull(slice.as_ptr() as *mut _),
485                    len,
486                    Some(release_wrapped_data::<T>),
487                    option_send_sync_non_null(buf).map(|v| v.cast()),
488                );
489                if let Some(offset) = offset {
490                    data.m.offset = offset as libc::off_t;
491                }
492                if let Some(timestamp) = timestamp {
493                    data.m.timestamp = timestamp;
494                }
495                if let Some(duration) = duration {
496                    data.m.duration = duration;
497                }
498
499                let ret = dav1d_send_data(Some(self.dec), option_nonnull(&mut data));
500                if let Err(err) = rav1d_result(ret) {
501                    let ret = Error::from(err);
502
503                    if ret.is_again() {
504                        self.pending_data = Some(data);
505                    } else {
506                        dav1d_data_unref(option_nonnull(&mut data));
507                    }
508
509                    return Err(ret);
510                }
511
512                if data.sz > 0 {
513                    self.pending_data = Some(data);
514                    return Err(Error::Again);
515                }
516
517                Ok(())
518            }
519        }
520
521        /// Sends any pending data to the decoder.
522        ///
523        /// This has to be called after [`Decoder::send_data`] has returned `Err([Error::Again])` to
524        /// consume any futher pending data.
525        ///
526        /// After this returned `Ok(())` or `Err([Error::Again])` there might be decoded frames
527        /// available via [`Decoder::get_picture`].
528        pub fn send_pending_data(&mut self) -> Result<(), Error> {
529            let mut data = match self.pending_data.take() {
530                None => {
531                    return Ok(());
532                }
533                Some(data) => data,
534            };
535
536            unsafe {
537                let ret = dav1d_send_data(Some(self.dec), option_nonnull(&mut data));
538                if let Err(err) = rav1d_result(ret) {
539                    let ret = Error::from(err);
540
541                    if ret.is_again() {
542                        self.pending_data = Some(data);
543                    } else {
544                        dav1d_data_unref(option_nonnull(&mut data));
545                    }
546
547                    return Err(ret);
548                }
549
550                if data.sz > 0 {
551                    self.pending_data = Some(data);
552                    return Err(Error::Again);
553                }
554
555                Ok(())
556            }
557        }
558
559        /// Get the next decoded frame from the decoder.
560        ///
561        /// If this returns `Err([Error::Again])` then further data has to be sent to the decoder
562        /// before further decoded frames become available.
563        ///
564        /// To make most use of frame threading this function should only be called once per submitted
565        /// input frame and not until it returns `Err([Error::Again])`. Calling it in a loop should
566        /// only be done to drain all pending frames at the end.
567        pub fn get_picture(&mut self) -> Result<Picture, Error> {
568            unsafe {
569                let mut pic: Dav1dPicture = mem::zeroed();
570                let ret = dav1d_get_picture(Some(self.dec), option_nonnull(&mut pic));
571
572                if let Err(err) = rav1d_result(ret) {
573                    Err(Error::from(err))
574                } else {
575                    let inner = InnerPicture { pic };
576                    Ok(Picture {
577                        inner: Arc::new(inner),
578                    })
579                }
580            }
581        }
582
583        /// Get the decoder delay.
584        pub fn get_frame_delay(&self) -> u32 {
585            unsafe {
586                dav1d_get_frame_delay(option_nonnull(&self.dec as *const _ as *mut _)).0 as u32
587            }
588        }
589    }
590
591    impl Drop for Decoder {
592        fn drop(&mut self) {
593            unsafe {
594                if let Some(mut pending_data) = self.pending_data.take() {
595                    dav1d_data_unref(option_nonnull(&mut pending_data));
596                }
597                let mut dec = Some(self.dec);
598                dav1d_close(option_nonnull(&mut dec));
599            };
600        }
601    }
602
603    unsafe impl Send for Decoder {}
604    unsafe impl Sync for Decoder {}
605
606    struct InnerPicture {
607        pub pic: Dav1dPicture,
608    }
609
610    /// A decoded frame.
611    #[derive(Clone)]
612    pub struct Picture {
613        inner: Arc<InnerPicture>,
614    }
615
616    /// Pixel layout of a frame.
617    #[derive(Debug, Eq, PartialEq, Copy, Clone)]
618    pub enum PixelLayout {
619        /// Monochrome.
620        I400,
621        /// 4:2:0 planar.
622        I420,
623        /// 4:2:2 planar.
624        I422,
625        /// 4:4:4 planar.
626        I444,
627    }
628
629    /// Frame component.
630    #[derive(Eq, PartialEq, Copy, Clone, Debug)]
631    pub enum PlanarImageComponent {
632        /// Y component.
633        Y,
634        /// U component.
635        U,
636        /// V component.
637        V,
638    }
639
640    impl From<usize> for PlanarImageComponent {
641        fn from(index: usize) -> Self {
642            match index {
643                0 => PlanarImageComponent::Y,
644                1 => PlanarImageComponent::U,
645                2 => PlanarImageComponent::V,
646                _ => panic!("Invalid YUV index: {}", index),
647            }
648        }
649    }
650
651    impl From<PlanarImageComponent> for usize {
652        fn from(component: PlanarImageComponent) -> Self {
653            match component {
654                PlanarImageComponent::Y => 0,
655                PlanarImageComponent::U => 1,
656                PlanarImageComponent::V => 2,
657            }
658        }
659    }
660
661    /// A single plane of a decoded frame.
662    ///
663    /// This can be used like a `&[u8]`.
664    #[derive(Clone)]
665    pub struct Plane(Picture, PlanarImageComponent);
666
667    impl AsRef<[u8]> for Plane {
668        fn as_ref(&self) -> &[u8] {
669            let (stride, height) = self.0.plane_data_geometry(self.1);
670            unsafe {
671                std::slice::from_raw_parts(
672                    self.0.plane_data_ptr(self.1) as *const u8,
673                    (stride * height) as usize,
674                )
675            }
676        }
677    }
678
679    impl std::ops::Deref for Plane {
680        type Target = [u8];
681
682        fn deref(&self) -> &Self::Target {
683            self.as_ref()
684        }
685    }
686
687    static_assertions::assert_impl_all!(Plane: Send, Sync);
688
689    /// Number of bits per component.
690    #[derive(Copy, Clone, Debug, PartialEq, Eq)]
691    pub struct BitsPerComponent(pub usize);
692
693    impl Picture {
694        /// Stride in pixels of the `component` for the decoded frame.
695        pub fn stride(&self, component: PlanarImageComponent) -> u32 {
696            let s = match component {
697                PlanarImageComponent::Y => 0,
698                _ => 1,
699            };
700            self.inner.pic.stride[s] as u32
701        }
702
703        /// Raw pointer to the data of the `component` for the decoded frame.
704        pub fn plane_data_ptr(&self, component: PlanarImageComponent) -> *mut c_void {
705            let index: usize = component.into();
706            self.inner.pic.data[index].unwrap().as_ptr()
707        }
708
709        /// Plane geometry of the `component` for the decoded frame.
710        ///
711        /// This returns the stride and height.
712        pub fn plane_data_geometry(&self, component: PlanarImageComponent) -> (u32, u32) {
713            let height = match component {
714                PlanarImageComponent::Y => self.height(),
715                _ => match self.pixel_layout() {
716                    PixelLayout::I420 => (self.height() + 1) / 2,
717                    PixelLayout::I400 | PixelLayout::I422 | PixelLayout::I444 => self.height(),
718                },
719            };
720            (self.stride(component), height)
721        }
722
723        /// Plane data of the `component` for the decoded frame.
724        pub fn plane(&self, component: PlanarImageComponent) -> Plane {
725            Plane(self.clone(), component)
726        }
727
728        /// Bit depth of the plane data.
729        ///
730        /// This returns 8 or 16 for the underlying integer type used for the plane data.
731        ///
732        /// Check [`Picture::bits_per_component`] for the number of bits that are used.
733        pub fn bit_depth(&self) -> usize {
734            self.inner.pic.p.bpc as usize
735        }
736
737        /// Bits used per component of the plane data.
738        ///
739        /// Check [`Picture::bit_depth`] for the number of storage bits.
740        pub fn bits_per_component(&self) -> Option<BitsPerComponent> {
741            unsafe {
742                match (*self.inner.pic.seq_hdr.unwrap().as_ptr()).hbd {
743                    0 => Some(BitsPerComponent(8)),
744                    1 => Some(BitsPerComponent(10)),
745                    2 => Some(BitsPerComponent(12)),
746                    _ => None,
747                }
748            }
749        }
750
751        /// Width of the frame.
752        pub fn width(&self) -> u32 {
753            self.inner.pic.p.w as u32
754        }
755
756        /// Height of the frame.
757        pub fn height(&self) -> u32 {
758            self.inner.pic.p.h as u32
759        }
760
761        /// Pixel layout of the frame.
762        pub fn pixel_layout(&self) -> PixelLayout {
763            #[allow(non_upper_case_globals)]
764            match self.inner.pic.p.layout {
765                DAV1D_PIXEL_LAYOUT_I400 => PixelLayout::I400,
766                DAV1D_PIXEL_LAYOUT_I420 => PixelLayout::I420,
767                DAV1D_PIXEL_LAYOUT_I422 => PixelLayout::I422,
768                DAV1D_PIXEL_LAYOUT_I444 => PixelLayout::I444,
769                _ => unreachable!(),
770            }
771        }
772
773        /// Timestamp of the frame.
774        ///
775        /// This is the same timestamp as the one provided to [`Decoder::send_data`].
776        pub fn timestamp(&self) -> Option<i64> {
777            let ts = self.inner.pic.m.timestamp;
778            if ts == i64::MIN {
779                None
780            } else {
781                Some(ts)
782            }
783        }
784
785        /// Duration of the frame.
786        ///
787        /// This is the same duration as the one provided to [`Decoder::send_data`] or `0` if none was
788        /// provided.
789        pub fn duration(&self) -> i64 {
790            self.inner.pic.m.duration
791        }
792
793        /// Offset of the frame.
794        ///
795        /// This is the same offset as the one provided to [`Decoder::send_data`] or `-1` if none was
796        /// provided.
797        pub fn offset(&self) -> i64 {
798            self.inner.pic.m.offset as i64
799        }
800
801        /// Chromaticity coordinates of the source colour primaries.
802        pub fn color_primaries(&self) -> pixel::ColorPrimaries {
803            unsafe {
804                #[allow(non_upper_case_globals)]
805                match (*self.inner.pic.seq_hdr.unwrap().as_ptr()).pri {
806                    DAV1D_COLOR_PRI_BT709 => pixel::ColorPrimaries::BT709,
807                    DAV1D_COLOR_PRI_UNKNOWN => pixel::ColorPrimaries::Unspecified,
808                    DAV1D_COLOR_PRI_BT470M => pixel::ColorPrimaries::BT470M,
809                    DAV1D_COLOR_PRI_BT470BG => pixel::ColorPrimaries::BT470BG,
810                    DAV1D_COLOR_PRI_BT601 => pixel::ColorPrimaries::BT470BG,
811                    DAV1D_COLOR_PRI_SMPTE240 => pixel::ColorPrimaries::ST240M,
812                    DAV1D_COLOR_PRI_FILM => pixel::ColorPrimaries::Film,
813                    DAV1D_COLOR_PRI_BT2020 => pixel::ColorPrimaries::BT2020,
814                    DAV1D_COLOR_PRI_XYZ => pixel::ColorPrimaries::ST428,
815                    DAV1D_COLOR_PRI_SMPTE431 => pixel::ColorPrimaries::P3DCI,
816                    DAV1D_COLOR_PRI_SMPTE432 => pixel::ColorPrimaries::P3Display,
817                    DAV1D_COLOR_PRI_EBU3213 => pixel::ColorPrimaries::Tech3213,
818                    23..=DAV1D_COLOR_PRI_RESERVED => pixel::ColorPrimaries::Unspecified,
819                    _ => unreachable!(),
820                }
821            }
822        }
823
824        /// Transfer characteristics function.
825        pub fn transfer_characteristic(&self) -> pixel::TransferCharacteristic {
826            unsafe {
827                #[allow(non_upper_case_globals)]
828                match (*self.inner.pic.seq_hdr.unwrap().as_ptr()).trc {
829                    DAV1D_TRC_BT709 => pixel::TransferCharacteristic::BT1886,
830                    DAV1D_TRC_UNKNOWN => pixel::TransferCharacteristic::Unspecified,
831                    DAV1D_TRC_BT470M => pixel::TransferCharacteristic::BT470M,
832                    DAV1D_TRC_BT470BG => pixel::TransferCharacteristic::BT470BG,
833                    DAV1D_TRC_BT601 => pixel::TransferCharacteristic::ST170M,
834                    DAV1D_TRC_SMPTE240 => pixel::TransferCharacteristic::ST240M,
835                    DAV1D_TRC_LINEAR => pixel::TransferCharacteristic::Linear,
836                    DAV1D_TRC_LOG100 => pixel::TransferCharacteristic::Logarithmic100,
837                    DAV1D_TRC_LOG100_SQRT10 => pixel::TransferCharacteristic::Logarithmic316,
838                    DAV1D_TRC_IEC61966 => pixel::TransferCharacteristic::SRGB,
839                    DAV1D_TRC_BT1361 => pixel::TransferCharacteristic::BT1886,
840                    DAV1D_TRC_SRGB => pixel::TransferCharacteristic::SRGB,
841                    DAV1D_TRC_BT2020_10BIT => pixel::TransferCharacteristic::BT2020Ten,
842                    DAV1D_TRC_BT2020_12BIT => pixel::TransferCharacteristic::BT2020Twelve,
843                    DAV1D_TRC_SMPTE2084 => pixel::TransferCharacteristic::PerceptualQuantizer,
844                    DAV1D_TRC_SMPTE428 => pixel::TransferCharacteristic::ST428,
845                    DAV1D_TRC_HLG => pixel::TransferCharacteristic::HybridLogGamma,
846                    19..=DAV1D_TRC_RESERVED => pixel::TransferCharacteristic::Unspecified,
847                    _ => unreachable!(),
848                }
849            }
850        }
851
852        /// Matrix coefficients used in deriving luma and chroma signals from the
853        /// green, blue and red or X, Y and Z primaries.
854        pub fn matrix_coefficients(&self) -> pixel::MatrixCoefficients {
855            unsafe {
856                #[allow(non_upper_case_globals)]
857                match (*self.inner.pic.seq_hdr.unwrap().as_ptr()).mtrx {
858                    DAV1D_MC_IDENTITY => pixel::MatrixCoefficients::Identity,
859                    DAV1D_MC_BT709 => pixel::MatrixCoefficients::BT709,
860                    DAV1D_MC_UNKNOWN => pixel::MatrixCoefficients::Unspecified,
861                    DAV1D_MC_FCC => pixel::MatrixCoefficients::BT470M,
862                    DAV1D_MC_BT470BG => pixel::MatrixCoefficients::BT470BG,
863                    DAV1D_MC_BT601 => pixel::MatrixCoefficients::BT470BG,
864                    DAV1D_MC_SMPTE240 => pixel::MatrixCoefficients::ST240M,
865                    DAV1D_MC_SMPTE_YCGCO => pixel::MatrixCoefficients::YCgCo,
866                    DAV1D_MC_BT2020_NCL => pixel::MatrixCoefficients::BT2020NonConstantLuminance,
867                    DAV1D_MC_BT2020_CL => pixel::MatrixCoefficients::BT2020ConstantLuminance,
868                    DAV1D_MC_SMPTE2085 => pixel::MatrixCoefficients::ST2085,
869                    DAV1D_MC_CHROMAT_NCL => {
870                        pixel::MatrixCoefficients::ChromaticityDerivedNonConstantLuminance
871                    }
872                    DAV1D_MC_CHROMAT_CL => {
873                        pixel::MatrixCoefficients::ChromaticityDerivedConstantLuminance
874                    }
875                    DAV1D_MC_ICTCP => pixel::MatrixCoefficients::ICtCp,
876                    15..=DAV1D_MC_RESERVED => pixel::MatrixCoefficients::Unspecified,
877                    _ => unreachable!(),
878                }
879            }
880        }
881
882        /// YUV color range.
883        pub fn color_range(&self) -> pixel::YUVRange {
884            unsafe {
885                match (*self.inner.pic.seq_hdr.unwrap().as_ptr()).color_range {
886                    0 => pixel::YUVRange::Limited,
887                    _ => pixel::YUVRange::Full,
888                }
889            }
890        }
891
892        /// Sample position for subsampled chroma.
893        pub fn chroma_location(&self) -> pixel::ChromaLocation {
894            // According to y4m mapping declared in dav1d's output/y4m2.c and applied from FFmpeg's yuv4mpegdec.c
895            unsafe {
896                match (*self.inner.pic.seq_hdr.unwrap().as_ptr()).chr {
897                    DAV1D_CHR_UNKNOWN | DAV1D_CHR_COLOCATED => pixel::ChromaLocation::Center,
898                    DAV1D_CHR_VERTICAL => pixel::ChromaLocation::Left,
899                    _ => unreachable!(),
900                }
901            }
902        }
903    }
904
905    static_assertions::assert_impl_all!(Picture: Send, Sync);
906
907    unsafe impl Send for InnerPicture {}
908    unsafe impl Sync for InnerPicture {}
909
910    impl Drop for InnerPicture {
911        fn drop(&mut self) {
912            unsafe {
913                dav1d_picture_unref(option_nonnull(&mut self.pic));
914            }
915        }
916    }
917
918    impl std::fmt::Debug for Picture {
919        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
920            f.debug_struct("Picture")
921                .field("width", &self.width())
922                .field("height", &self.height())
923                .field("bit_depth", &self.bit_depth())
924                .field("pixel_layout", &self.pixel_layout())
925                .field("timestamp", &self.timestamp())
926                .field("duration", &self.duration())
927                .field("offset", &self.offset())
928                .field("color_primaries", &self.color_primaries())
929                .field("transfer_characteristic", &self.transfer_characteristic())
930                .field("matrix_coefficients", &self.matrix_coefficients())
931                .field("color_range", &self.color_range())
932                .field("chroma_location", &self.chroma_location())
933                .finish()
934        }
935    }
936}
937
938pub use dav1d::*;