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#[derive(Debug, Copy, Clone, PartialEq, Eq)]
13#[non_exhaustive]
14pub enum Error {
15 Again,
24 InvalidArgument,
28 NotEnoughMemory,
32 UnsupportedBitstream,
36 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#[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 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#[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#[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 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 pub fn new() -> Result<Self, Error> {
280 Self::with_settings(&Settings::default())
281 }
282
283 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 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 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 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 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#[derive(Debug, Clone)]
453pub struct Picture {
454 inner: Arc<InnerPicture>,
455}
456
457#[derive(Debug, Eq, PartialEq, Copy, Clone)]
459pub enum PixelLayout {
460 I400,
462 I420,
464 I422,
466 I444,
468}
469
470#[derive(Eq, PartialEq, Copy, Clone, Debug)]
472pub enum PlanarImageComponent {
473 Y,
475 U,
477 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#[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#[derive(Copy, Clone, Debug, PartialEq, Eq)]
532pub struct BitsPerComponent(pub usize);
533
534impl Picture {
535 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 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 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 pub fn plane(&self, component: PlanarImageComponent) -> Plane {
566 Plane(self.clone(), component)
567 }
568
569 pub fn bit_depth(&self) -> usize {
575 self.inner.pic.p.bpc as usize
576 }
577
578 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 pub fn width(&self) -> u32 {
594 self.inner.pic.p.w as u32
595 }
596
597 pub fn height(&self) -> u32 {
599 self.inner.pic.p.h as u32
600 }
601
602 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 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 pub fn duration(&self) -> i64 {
631 self.inner.pic.m.duration
632 }
633
634 pub fn offset(&self) -> i64 {
639 self.inner.pic.m.offset
640 }
641
642 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 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 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 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 pub fn chroma_location(&self) -> pixel::ChromaLocation {
735 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}