1use dav1d_sys::*;
2use dav1d_sys::Dav1dInloopFilterType::*;
3use dav1d_sys::Dav1dPixelLayout::*;
4
5use std::ffi::c_void;
6use std::fmt;
7use std::i64;
8use std::mem;
9use std::ptr;
10use std::sync::Arc;
11
12#[derive(Debug, Copy, Clone, PartialEq, Eq)]
14#[non_exhaustive]
15pub enum Error {
16 Again,
25 InvalidArgument,
29 NotEnoughMemory,
33 UnsupportedBitstream,
37 UnknownError(i32),
39}
40
41impl From<i32> for Error {
42 fn from(err: i32) -> Self {
43 assert!(err < 0);
44
45 match err {
46 DAV1D_ERR_AGAIN => Error::Again,
47 DAV1D_ERR_INVAL => Error::InvalidArgument,
48 DAV1D_ERR_NOMEM => Error::NotEnoughMemory,
49 DAV1D_ERR_NOPROTOOPT => Error::UnsupportedBitstream,
50 _ => Error::UnknownError(err),
51 }
52 }
53}
54
55impl Error {
56 pub const fn is_again(&self) -> bool {
57 matches!(self, Error::Again)
58 }
59}
60
61impl fmt::Display for Error {
62 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
63 match self {
64 Error::Again => write!(fmt, "Try again"),
65 Error::InvalidArgument => write!(fmt, "Invalid argument"),
66 Error::NotEnoughMemory => write!(fmt, "Not enough memory available"),
67 Error::UnsupportedBitstream => write!(fmt, "Unsupported bitstream"),
68 Error::UnknownError(err) => write!(fmt, "Unknown error {}", err),
69 }
70 }
71}
72
73impl std::error::Error for Error {}
74
75#[derive(Debug)]
78pub struct Settings {
79 dav1d_settings: Dav1dSettings,
80}
81
82impl Default for Settings {
83 fn default() -> Self {
84 Self::new()
85 }
86}
87
88impl Settings {
89 pub fn new() -> Self {
91 unsafe {
92 let mut dav1d_settings = mem::MaybeUninit::uninit();
93
94 dav1d_default_settings(dav1d_settings.as_mut_ptr());
95
96 Self {
97 dav1d_settings: dav1d_settings.assume_init(),
98 }
99 }
100 }
101
102 pub fn set_n_threads(&mut self, n_threads: u32) {
103 self.dav1d_settings.n_threads = n_threads as i32;
104 }
105
106 pub fn get_n_threads(&self) -> u32 {
107 self.dav1d_settings.n_threads as u32
108 }
109
110 pub fn set_max_frame_delay(&mut self, max_frame_delay: u32) {
111 self.dav1d_settings.max_frame_delay = max_frame_delay as i32;
112 }
113
114 pub fn get_max_frame_delay(&self) -> u32 {
115 self.dav1d_settings.max_frame_delay as u32
116 }
117
118 pub fn set_apply_grain(&mut self, apply_grain: bool) {
119 self.dav1d_settings.apply_grain = i32::from(apply_grain);
120 }
121
122 pub fn get_apply_grain(&self) -> bool {
123 self.dav1d_settings.apply_grain != 0
124 }
125
126 pub fn set_operating_point(&mut self, operating_point: u32) {
127 self.dav1d_settings.operating_point = operating_point as i32;
128 }
129
130 pub fn get_operating_point(&self) -> u32 {
131 self.dav1d_settings.operating_point as u32
132 }
133
134 pub fn set_all_layers(&mut self, all_layers: bool) {
135 self.dav1d_settings.all_layers = i32::from(all_layers);
136 }
137
138 pub fn get_all_layers(&self) -> bool {
139 self.dav1d_settings.all_layers != 0
140 }
141
142 pub fn set_frame_size_limit(&mut self, frame_size_limit: u32) {
143 self.dav1d_settings.frame_size_limit = frame_size_limit;
144 }
145
146 pub fn get_frame_size_limit(&self) -> u32 {
147 self.dav1d_settings.frame_size_limit
148 }
149
150 pub fn set_strict_std_compliance(&mut self, strict_std_compliance: bool) {
151 self.dav1d_settings.strict_std_compliance = i32::from(strict_std_compliance);
152 }
153
154 pub fn get_strict_std_compliance(&self) -> bool {
155 self.dav1d_settings.strict_std_compliance != 0
156 }
157
158 pub fn set_output_invisible_frames(&mut self, output_invisible_frames: bool) {
159 self.dav1d_settings.output_invisible_frames = i32::from(output_invisible_frames);
160 }
161
162 pub fn get_output_invisible_frames(&self) -> bool {
163 self.dav1d_settings.output_invisible_frames != 0
164 }
165
166 pub fn set_inloop_filters(&mut self, inloop_filters: InloopFilterType) {
167 self.dav1d_settings.inloop_filters = inloop_filters.bits();
168 }
169
170 pub fn get_inloop_filters(&self) -> InloopFilterType {
171 InloopFilterType::from_bits_truncate(self.dav1d_settings.inloop_filters)
172 }
173
174 pub fn set_decode_frame_type(&mut self, decode_frame_type: DecodeFrameType) {
175 use dav1d_sys::Dav1dDecodeFrameType::*;
176 self.dav1d_settings.decode_frame_type = match decode_frame_type {
177 DecodeFrameType::All => DAV1D_DECODEFRAMETYPE_ALL,
178 DecodeFrameType::Reference => DAV1D_DECODEFRAMETYPE_REFERENCE,
179 DecodeFrameType::Intra => DAV1D_DECODEFRAMETYPE_INTRA,
180 DecodeFrameType::Key => DAV1D_DECODEFRAMETYPE_KEY,
181 }
182 }
183
184 pub fn get_decode_frame_type(&self) -> DecodeFrameType {
185 DecodeFrameType::try_from(self.dav1d_settings.decode_frame_type as u32)
186 .expect("Invalid Dav1dDecodeFrameType")
187 }
188}
189
190bitflags::bitflags! {
191 #[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
192 pub struct InloopFilterType: u32 {
193 const DEBLOCK = DAV1D_INLOOPFILTER_DEBLOCK as u32;
194 const CDEF = DAV1D_INLOOPFILTER_CDEF as u32;
195 const RESTORATION = DAV1D_INLOOPFILTER_RESTORATION as u32;
196 }
197}
198
199#[derive(Debug, Copy, Clone, PartialEq, Eq)]
200pub enum DecodeFrameType {
201 All,
202 Reference,
203 Intra,
204 Key,
205}
206
207impl Default for DecodeFrameType {
208 fn default() -> Self {
209 DecodeFrameType::All
210 }
211}
212
213impl TryFrom<u32> for DecodeFrameType {
214 type Error = TryFromEnumError;
215
216 fn try_from(value: u32) -> Result<Self, Self::Error> {
217 use dav1d_sys::Dav1dDecodeFrameType::*;
218 match value {
219 x if x == DAV1D_DECODEFRAMETYPE_ALL as _ => Ok(DecodeFrameType::All),
220 x if x == DAV1D_DECODEFRAMETYPE_REFERENCE as _ => Ok(DecodeFrameType::Reference),
221 x if x == DAV1D_DECODEFRAMETYPE_INTRA as _ => Ok(DecodeFrameType::Intra),
222 x if x == DAV1D_DECODEFRAMETYPE_KEY as _ => Ok(DecodeFrameType::Key),
223 _ => Err(TryFromEnumError(())),
224 }
225 }
226}
227
228impl From<DecodeFrameType> for u32 {
229 fn from(v: DecodeFrameType) -> u32 {
230 use dav1d_sys::Dav1dDecodeFrameType::*;
231 match v {
232 DecodeFrameType::All => DAV1D_DECODEFRAMETYPE_ALL as _,
233 DecodeFrameType::Reference => DAV1D_DECODEFRAMETYPE_REFERENCE as _,
234 DecodeFrameType::Intra => DAV1D_DECODEFRAMETYPE_INTRA as _,
235 DecodeFrameType::Key => DAV1D_DECODEFRAMETYPE_KEY as _,
236 }
237 }
238}
239
240#[derive(Debug, Copy, Clone, PartialEq, Eq)]
242pub struct TryFromEnumError(());
243
244impl std::fmt::Display for TryFromEnumError {
245 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
246 fmt.write_str("Invalid enum value")
247 }
248}
249
250impl From<std::convert::Infallible> for TryFromEnumError {
251 fn from(x: std::convert::Infallible) -> TryFromEnumError {
252 match x {}
253 }
254}
255
256impl std::error::Error for TryFromEnumError {}
257
258#[derive(Debug)]
260pub struct Decoder {
261 dec: ptr::NonNull<Dav1dContext>,
262 pending_data: Option<Dav1dData>,
263}
264
265unsafe extern "C" fn release_wrapped_data<T: AsRef<[u8]>>(_data: *const u8, cookie: *mut c_void) {
266 let buf = Box::from_raw(cookie as *mut T);
267 drop(buf);
268}
269
270impl Decoder {
271 pub fn with_settings(settings: &Settings) -> Result<Self, Error> {
273 unsafe {
274 let mut dec = mem::MaybeUninit::uninit();
275
276 let ret = dav1d_open(dec.as_mut_ptr(), &settings.dav1d_settings);
277
278 if ret < 0 {
279 return Err(Error::from(ret));
280 }
281
282 Ok(Decoder {
283 dec: ptr::NonNull::new(dec.assume_init()).unwrap(),
284 pending_data: None,
285 })
286 }
287 }
288
289 pub fn new() -> Result<Self, Error> {
291 Self::with_settings(&Settings::default())
292 }
293
294 pub fn flush(&mut self) {
300 unsafe {
301 dav1d_flush(self.dec.as_ptr());
302 if let Some(mut pending_data) = self.pending_data.take() {
303 dav1d_data_unref(&mut pending_data);
304 }
305 }
306 }
307
308 pub fn send_data<T: AsRef<[u8]> + Send + 'static>(
318 &mut self,
319 buf: T,
320 offset: Option<i64>,
321 timestamp: Option<i64>,
322 duration: Option<i64>,
323 ) -> Result<(), Error> {
324 assert!(
325 self.pending_data.is_none(),
326 "Have pending data that needs to be handled first"
327 );
328
329 let buf = Box::new(buf);
330 let slice = (*buf).as_ref();
331 let len = slice.len();
332
333 unsafe {
334 let mut data: Dav1dData = mem::zeroed();
335 let _ret = dav1d_data_wrap(
336 &mut data,
337 slice.as_ptr(),
338 len,
339 Some(release_wrapped_data::<T>),
340 Box::into_raw(buf) as *mut c_void,
341 );
342 if let Some(offset) = offset {
343 data.m.offset = offset;
344 }
345 if let Some(timestamp) = timestamp {
346 data.m.timestamp = timestamp;
347 }
348 if let Some(duration) = duration {
349 data.m.duration = duration;
350 }
351
352 let ret = dav1d_send_data(self.dec.as_ptr(), &mut data);
353 if ret < 0 {
354 let ret = Error::from(ret);
355
356 if ret.is_again() {
357 self.pending_data = Some(data);
358 } else {
359 dav1d_data_unref(&mut data);
360 }
361
362 return Err(ret);
363 }
364
365 if data.sz > 0 {
366 self.pending_data = Some(data);
367 return Err(Error::Again);
368 }
369
370 Ok(())
371 }
372 }
373
374 pub fn send_pending_data(&mut self) -> Result<(), Error> {
382 let mut data = match self.pending_data.take() {
383 None => {
384 return Ok(());
385 }
386 Some(data) => data,
387 };
388
389 unsafe {
390 let ret = dav1d_send_data(self.dec.as_ptr(), &mut data);
391 if ret < 0 {
392 let ret = Error::from(ret);
393
394 if ret.is_again() {
395 self.pending_data = Some(data);
396 } else {
397 dav1d_data_unref(&mut data);
398 }
399
400 return Err(ret);
401 }
402
403 if data.sz > 0 {
404 self.pending_data = Some(data);
405 return Err(Error::Again);
406 }
407
408 Ok(())
409 }
410 }
411
412 pub fn get_picture(&mut self) -> Result<Picture, Error> {
421 unsafe {
422 let mut pic: Dav1dPicture = mem::zeroed();
423 let ret = dav1d_get_picture(self.dec.as_ptr(), &mut pic);
424
425 if ret < 0 {
426 Err(Error::from(ret))
427 } else {
428 let inner = InnerPicture { pic };
429 Ok(Picture {
430 inner: Arc::new(inner),
431 })
432 }
433 }
434 }
435
436 pub fn get_frame_delay(&self) -> u32 {
438 unsafe { dav1d_get_frame_delay(self.dec.as_ptr() as *const _) as u32 }
439 }
440}
441
442impl Drop for Decoder {
443 fn drop(&mut self) {
444 unsafe {
445 if let Some(mut pending_data) = self.pending_data.take() {
446 dav1d_data_unref(&mut pending_data);
447 }
448 let mut dec = self.dec.as_ptr();
449 dav1d_close(&mut dec);
450 };
451 }
452}
453
454unsafe impl Send for Decoder {}
455unsafe impl Sync for Decoder {}
456
457#[derive(Debug)]
458struct InnerPicture {
459 pub pic: Dav1dPicture,
460}
461
462#[derive(Debug, Clone)]
464pub struct Picture {
465 inner: Arc<InnerPicture>,
466}
467
468#[derive(Debug, Eq, PartialEq, Copy, Clone)]
470pub enum PixelLayout {
471 I400,
473 I420,
475 I422,
477 I444,
479}
480
481#[derive(Eq, PartialEq, Copy, Clone, Debug)]
483pub enum PlanarImageComponent {
484 Y,
486 U,
488 V,
490}
491
492impl From<usize> for PlanarImageComponent {
493 fn from(index: usize) -> Self {
494 match index {
495 0 => PlanarImageComponent::Y,
496 1 => PlanarImageComponent::U,
497 2 => PlanarImageComponent::V,
498 _ => panic!("Invalid YUV index: {}", index),
499 }
500 }
501}
502
503impl From<PlanarImageComponent> for usize {
504 fn from(component: PlanarImageComponent) -> Self {
505 match component {
506 PlanarImageComponent::Y => 0,
507 PlanarImageComponent::U => 1,
508 PlanarImageComponent::V => 2,
509 }
510 }
511}
512
513#[derive(Clone, Debug)]
517pub struct Plane(Picture, PlanarImageComponent);
518
519impl AsRef<[u8]> for Plane {
520 fn as_ref(&self) -> &[u8] {
521 let (stride, height) = self.0.plane_data_geometry(self.1);
522 unsafe {
523 std::slice::from_raw_parts(
524 self.0.plane_data_ptr(self.1) as *const u8,
525 (stride * height) as usize,
526 )
527 }
528 }
529}
530
531impl std::ops::Deref for Plane {
532 type Target = [u8];
533
534 fn deref(&self) -> &Self::Target {
535 self.as_ref()
536 }
537}
538
539unsafe impl Send for Plane {}
540unsafe impl Sync for Plane {}
541
542#[derive(Copy, Clone, Debug, PartialEq, Eq)]
544pub struct BitsPerComponent(pub usize);
545
546impl Picture {
547 pub fn stride(&self, component: PlanarImageComponent) -> u32 {
549 let s = match component {
550 PlanarImageComponent::Y => 0,
551 _ => 1,
552 };
553 self.inner.pic.stride[s] as u32
554 }
555
556 pub fn plane_data_ptr(&self, component: PlanarImageComponent) -> *mut c_void {
558 let index: usize = component.into();
559 self.inner.pic.data[index]
560 }
561
562 pub fn plane_data_geometry(&self, component: PlanarImageComponent) -> (u32, u32) {
566 let height = match component {
567 PlanarImageComponent::Y => self.height(),
568 _ => match self.pixel_layout() {
569 PixelLayout::I420 => (self.height() + 1) / 2,
570 PixelLayout::I400 | PixelLayout::I422 | PixelLayout::I444 => self.height(),
571 },
572 };
573 (self.stride(component) as u32, height)
574 }
575
576 pub fn plane(&self, component: PlanarImageComponent) -> Plane {
578 Plane(self.clone(), component)
579 }
580
581 pub fn bit_depth(&self) -> usize {
587 self.inner.pic.p.bpc as usize
588 }
589
590 pub fn bits_per_component(&self) -> Option<BitsPerComponent> {
594 unsafe {
595 match (*self.inner.pic.seq_hdr).hbd {
596 0 => Some(BitsPerComponent(8)),
597 1 => Some(BitsPerComponent(10)),
598 2 => Some(BitsPerComponent(12)),
599 _ => None,
600 }
601 }
602 }
603
604 pub fn width(&self) -> u32 {
606 self.inner.pic.p.w as u32
607 }
608
609 pub fn height(&self) -> u32 {
611 self.inner.pic.p.h as u32
612 }
613
614 pub fn pixel_layout(&self) -> PixelLayout {
616 #[allow(non_upper_case_globals)]
617 match self.inner.pic.p.layout {
618 DAV1D_PIXEL_LAYOUT_I400 => PixelLayout::I400,
619 DAV1D_PIXEL_LAYOUT_I420 => PixelLayout::I420,
620 DAV1D_PIXEL_LAYOUT_I422 => PixelLayout::I422,
621 DAV1D_PIXEL_LAYOUT_I444 => PixelLayout::I444,
622 #[allow(unreachable_patterns)]
623 _ => unreachable!(),
624 }
625 }
626
627 pub fn timestamp(&self) -> Option<i64> {
631 let ts = self.inner.pic.m.timestamp;
632 if ts == i64::MIN {
633 None
634 } else {
635 Some(ts)
636 }
637 }
638
639 pub fn duration(&self) -> i64 {
644 self.inner.pic.m.duration as i64
645 }
646
647 pub fn offset(&self) -> i64 {
652 self.inner.pic.m.offset
653 }
654}
655
656unsafe impl Send for Picture {}
657unsafe impl Sync for Picture {}
658
659impl Drop for InnerPicture {
660 fn drop(&mut self) {
661 unsafe {
662 dav1d_picture_unref(&mut self.pic);
663 }
664 }
665}