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 } pub mod dav1d {
24 pub mod common;
25 pub mod data;
26 pub mod dav1d;
27 pub mod headers;
28 pub mod picture;
29 } } pub 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 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} pub use src::error::Dav1dResult;
96
97pub mod dav1d {
104 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 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
169 #[non_exhaustive]
170 pub enum Error {
171 Again,
180 InvalidArgument,
184 NotEnoughMemory,
188 UnsupportedBitstream,
192 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 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 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 #[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 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 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 pub fn new() -> Result<Self, Error> {
438 Self::with_settings(&Settings::default())
439 }
440
441 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 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 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 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 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 #[derive(Clone)]
612 pub struct Picture {
613 inner: Arc<InnerPicture>,
614 }
615
616 #[derive(Debug, Eq, PartialEq, Copy, Clone)]
618 pub enum PixelLayout {
619 I400,
621 I420,
623 I422,
625 I444,
627 }
628
629 #[derive(Eq, PartialEq, Copy, Clone, Debug)]
631 pub enum PlanarImageComponent {
632 Y,
634 U,
636 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 #[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 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
691 pub struct BitsPerComponent(pub usize);
692
693 impl Picture {
694 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 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 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 pub fn plane(&self, component: PlanarImageComponent) -> Plane {
725 Plane(self.clone(), component)
726 }
727
728 pub fn bit_depth(&self) -> usize {
734 self.inner.pic.p.bpc as usize
735 }
736
737 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 pub fn width(&self) -> u32 {
753 self.inner.pic.p.w as u32
754 }
755
756 pub fn height(&self) -> u32 {
758 self.inner.pic.p.h as u32
759 }
760
761 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 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 pub fn duration(&self) -> i64 {
790 self.inner.pic.m.duration
791 }
792
793 pub fn offset(&self) -> i64 {
798 self.inner.pic.m.offset as i64
799 }
800
801 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 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 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 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 pub fn chroma_location(&self) -> pixel::ChromaLocation {
894 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::*;