1 // Copyright 2024 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 use crate::codecs::Decoder;
16 use crate::codecs::DecoderConfig;
17 use crate::decoder::Category;
18 use crate::image::Image;
19 use crate::image::YuvRange;
20 use crate::internal_utils::pixels::*;
21 use crate::*;
22 
23 use dav1d_sys::bindings::*;
24 
25 use std::mem::MaybeUninit;
26 
27 #[derive(Debug, Default)]
28 pub struct Dav1d {
29     context: Option<*mut Dav1dContext>,
30     picture: Option<Dav1dPicture>,
31 }
32 
avif_dav1d_free_callback( _buf: *const u8, _cookie: *mut ::std::os::raw::c_void, )33 unsafe extern "C" fn avif_dav1d_free_callback(
34     _buf: *const u8,
35     _cookie: *mut ::std::os::raw::c_void,
36 ) {
37     // Do nothing. The buffers are owned by the decoder.
38 }
39 
40 // See https://code.videolan.org/videolan/dav1d/-/blob/9849ede1304da1443cfb4a86f197765081034205/include/dav1d/common.h#L55-59
41 const DAV1D_EAGAIN: i32 = if libc::EPERM > 0 { -libc::EAGAIN } else { libc::EAGAIN };
42 
43 // The type of the fields from dav1d_sys::bindings::* are dependent on the
44 // compiler that is used to generate the bindings, version of dav1d, etc.
45 // So allow clippy to ignore unnecessary cast warnings.
46 #[allow(clippy::unnecessary_cast)]
47 impl Decoder for Dav1d {
initialize(&mut self, config: &DecoderConfig) -> AvifResult<()>48     fn initialize(&mut self, config: &DecoderConfig) -> AvifResult<()> {
49         if self.context.is_some() {
50             return Ok(());
51         }
52         let mut settings_uninit: MaybeUninit<Dav1dSettings> = MaybeUninit::uninit();
53         unsafe { dav1d_default_settings(settings_uninit.as_mut_ptr()) };
54         let mut settings = unsafe { settings_uninit.assume_init() };
55         settings.max_frame_delay = 1;
56         settings.n_threads = i32::try_from(config.max_threads).unwrap_or(1);
57         settings.operating_point = config.operating_point as i32;
58         settings.all_layers = if config.all_layers { 1 } else { 0 };
59 
60         let mut dec = MaybeUninit::uninit();
61         let ret = unsafe { dav1d_open(dec.as_mut_ptr(), (&settings) as *const _) };
62         if ret != 0 {
63             return Err(AvifError::UnknownError(format!(
64                 "dav1d_open returned {ret}"
65             )));
66         }
67         self.context = Some(unsafe { dec.assume_init() });
68 
69         Ok(())
70     }
71 
get_next_image( &mut self, av1_payload: &[u8], spatial_id: u8, image: &mut Image, category: Category, ) -> AvifResult<()>72     fn get_next_image(
73         &mut self,
74         av1_payload: &[u8],
75         spatial_id: u8,
76         image: &mut Image,
77         category: Category,
78     ) -> AvifResult<()> {
79         if self.context.is_none() {
80             self.initialize(&DecoderConfig::default())?;
81         }
82         unsafe {
83             let mut data: Dav1dData = std::mem::zeroed();
84             let res = dav1d_data_wrap(
85                 (&mut data) as *mut _,
86                 av1_payload.as_ptr(),
87                 av1_payload.len(),
88                 Some(avif_dav1d_free_callback),
89                 /*cookie=*/ std::ptr::null_mut(),
90             );
91             if res != 0 {
92                 return Err(AvifError::UnknownError(format!(
93                     "dav1d_data_wrap returned {res}"
94                 )));
95             }
96             let mut next_frame: Dav1dPicture = std::mem::zeroed();
97             let got_picture;
98             loop {
99                 if !data.data.is_null() {
100                     let res = dav1d_send_data(self.context.unwrap(), (&mut data) as *mut _);
101                     if res < 0 && res != DAV1D_EAGAIN {
102                         dav1d_data_unref((&mut data) as *mut _);
103                         return Err(AvifError::UnknownError(format!(
104                             "dav1d_send_data returned {res}"
105                         )));
106                     }
107                 }
108 
109                 let res = dav1d_get_picture(self.context.unwrap(), (&mut next_frame) as *mut _);
110                 if res == DAV1D_EAGAIN {
111                     // send more data.
112                     if !data.data.is_null() {
113                         continue;
114                     }
115                     return Err(AvifError::UnknownError("".into()));
116                 } else if res < 0 {
117                     if !data.data.is_null() {
118                         dav1d_data_unref((&mut data) as *mut _);
119                     }
120                     return Err(AvifError::UnknownError(format!(
121                         "dav1d_send_picture returned {res}"
122                     )));
123                 } else {
124                     // Got a picture.
125                     let frame_spatial_id = (*next_frame.frame_hdr).spatial_id as u8;
126                     if spatial_id != 0xFF && spatial_id != frame_spatial_id {
127                         // layer selection: skip this unwanted layer.
128                         dav1d_picture_unref((&mut next_frame) as *mut _);
129                     } else {
130                         got_picture = true;
131                         break;
132                     }
133                 }
134             }
135             if !data.data.is_null() {
136                 dav1d_data_unref((&mut data) as *mut _);
137             }
138 
139             // Drain all buffered frames in the decoder.
140             //
141             // The sample should have only one frame of the desired layer. If there are more frames
142             // after that frame, we need to discard them so that they won't be mistakenly output
143             // when the decoder is used to decode another sample.
144             let mut buffered_frame: Dav1dPicture = std::mem::zeroed();
145             loop {
146                 let res = dav1d_get_picture(self.context.unwrap(), (&mut buffered_frame) as *mut _);
147                 if res < 0 {
148                     if res != DAV1D_EAGAIN {
149                         if got_picture {
150                             dav1d_picture_unref((&mut next_frame) as *mut _);
151                         }
152                         return Err(AvifError::UnknownError(format!(
153                             "error draining buffered frames {res}"
154                         )));
155                     }
156                 } else {
157                     dav1d_picture_unref((&mut buffered_frame) as *mut _);
158                 }
159                 if res != 0 {
160                     break;
161                 }
162             }
163 
164             if got_picture {
165                 // unref previous frame.
166                 if self.picture.is_some() {
167                     let mut previous_picture = self.picture.unwrap();
168                     dav1d_picture_unref((&mut previous_picture) as *mut _);
169                 }
170                 self.picture = Some(next_frame);
171             } else if category == Category::Alpha && self.picture.is_some() {
172                 // Special case for alpha, re-use last frame.
173             } else {
174                 return Err(AvifError::UnknownError("".into()));
175             }
176         }
177 
178         let dav1d_picture = self.picture.unwrap_ref();
179         match category {
180             Category::Alpha => {
181                 if image.width > 0
182                     && image.height > 0
183                     && (image.width != (dav1d_picture.p.w as u32)
184                         || image.height != (dav1d_picture.p.h as u32)
185                         || image.depth != (dav1d_picture.p.bpc as u8))
186                 {
187                     // Alpha plane does not match the previous alpha plane.
188                     return Err(AvifError::UnknownError("".into()));
189                 }
190                 image.width = dav1d_picture.p.w as u32;
191                 image.height = dav1d_picture.p.h as u32;
192                 image.depth = dav1d_picture.p.bpc as u8;
193                 image.row_bytes[3] = dav1d_picture.stride[0] as u32;
194                 image.planes[3] = Some(Pixels::from_raw_pointer(
195                     dav1d_picture.data[0] as *mut u8,
196                     image.depth as u32,
197                     image.height,
198                     image.row_bytes[3],
199                 )?);
200                 image.image_owns_planes[3] = false;
201                 let seq_hdr = unsafe { &(*dav1d_picture.seq_hdr) };
202                 image.yuv_range =
203                     if seq_hdr.color_range == 0 { YuvRange::Limited } else { YuvRange::Full };
204             }
205             _ => {
206                 image.width = dav1d_picture.p.w as u32;
207                 image.height = dav1d_picture.p.h as u32;
208                 image.depth = dav1d_picture.p.bpc as u8;
209 
210                 image.yuv_format = match dav1d_picture.p.layout {
211                     0 => PixelFormat::Yuv400,
212                     1 => PixelFormat::Yuv420,
213                     2 => PixelFormat::Yuv422,
214                     3 => PixelFormat::Yuv444,
215                     _ => return Err(AvifError::UnknownError("".into())), // not reached.
216                 };
217                 let seq_hdr = unsafe { &(*dav1d_picture.seq_hdr) };
218                 image.yuv_range =
219                     if seq_hdr.color_range == 0 { YuvRange::Limited } else { YuvRange::Full };
220                 image.chroma_sample_position = (seq_hdr.chr as u32).into();
221 
222                 image.color_primaries = (seq_hdr.pri as u16).into();
223                 image.transfer_characteristics = (seq_hdr.trc as u16).into();
224                 image.matrix_coefficients = (seq_hdr.mtrx as u16).into();
225 
226                 for plane in 0usize..image.yuv_format.plane_count() {
227                     let stride_index = if plane == 0 { 0 } else { 1 };
228                     image.row_bytes[plane] = dav1d_picture.stride[stride_index] as u32;
229                     image.planes[plane] = Some(Pixels::from_raw_pointer(
230                         dav1d_picture.data[plane] as *mut u8,
231                         image.depth as u32,
232                         image.height,
233                         image.row_bytes[plane],
234                     )?);
235                     image.image_owns_planes[plane] = false;
236                 }
237                 if image.yuv_format == PixelFormat::Yuv400 {
238                     // Clear left over chroma planes from previous frames.
239                     image.clear_chroma_planes();
240                 }
241             }
242         }
243         Ok(())
244     }
245 }
246 
247 impl Drop for Dav1d {
drop(&mut self)248     fn drop(&mut self) {
249         if self.picture.is_some() {
250             unsafe { dav1d_picture_unref(self.picture.unwrap_mut() as *mut _) };
251         }
252         if self.context.is_some() {
253             unsafe { dav1d_close(&mut self.context.unwrap()) };
254         }
255     }
256 }
257