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::CodecChoice;
18 use crate::decoder::GridImageHelper;
19 use crate::image::Image;
20 use crate::image::YuvRange;
21 use crate::internal_utils::pixels::*;
22 use crate::*;
23
24 use dav1d_sys::bindings::*;
25
26 use std::mem::MaybeUninit;
27
28 #[derive(Default)]
29 pub struct Dav1d {
30 context: Option<*mut Dav1dContext>,
31 picture: Option<Dav1dPicture>,
32 config: Option<DecoderConfig>,
33 }
34
avif_dav1d_free_callback( _buf: *const u8, _cookie: *mut ::std::os::raw::c_void, )35 unsafe extern "C" fn avif_dav1d_free_callback(
36 _buf: *const u8,
37 _cookie: *mut ::std::os::raw::c_void,
38 ) {
39 // Do nothing. The buffers are owned by the decoder.
40 }
41
42 // See https://code.videolan.org/videolan/dav1d/-/blob/9849ede1304da1443cfb4a86f197765081034205/include/dav1d/common.h#L55-59
43 const DAV1D_EAGAIN: i32 = if libc::EPERM > 0 { -libc::EAGAIN } else { libc::EAGAIN };
44
45 impl Dav1d {
initialize_impl(&mut self, low_latency: bool) -> AvifResult<()>46 fn initialize_impl(&mut self, low_latency: bool) -> AvifResult<()> {
47 if self.context.is_some() {
48 return Ok(());
49 }
50 let config = self.config.unwrap_ref();
51 let mut settings_uninit: MaybeUninit<Dav1dSettings> = MaybeUninit::uninit();
52 unsafe { dav1d_default_settings(settings_uninit.as_mut_ptr()) };
53 let mut settings = unsafe { settings_uninit.assume_init() };
54 if low_latency {
55 settings.max_frame_delay = 1;
56 }
57 settings.n_threads = i32::try_from(config.max_threads).unwrap_or(1);
58 settings.operating_point = config.operating_point as i32;
59 settings.all_layers = if config.all_layers { 1 } else { 0 };
60 let frame_size_limit = match config.image_size_limit {
61 Some(value) => value.get(),
62 None => 0,
63 };
64 // Set a maximum frame size limit to avoid OOM'ing fuzzers. In 32-bit builds, if
65 // frame_size_limit > 8192 * 8192, dav1d reduces frame_size_limit to 8192 * 8192 and logs
66 // a message, so we set frame_size_limit to at most 8192 * 8192 to avoid the dav1d_log
67 // message.
68 settings.frame_size_limit = if cfg!(target_pointer_width = "32") {
69 std::cmp::min(frame_size_limit, 8192 * 8192)
70 } else {
71 frame_size_limit
72 };
73
74 let mut dec = MaybeUninit::uninit();
75 let ret = unsafe { dav1d_open(dec.as_mut_ptr(), (&settings) as *const _) };
76 if ret != 0 {
77 return Err(AvifError::UnknownError(format!(
78 "dav1d_open returned {ret}"
79 )));
80 }
81 self.context = Some(unsafe { dec.assume_init() });
82 Ok(())
83 }
84
picture_to_image( &self, dav1d_picture: &Dav1dPicture, image: &mut Image, category: Category, ) -> AvifResult<()>85 fn picture_to_image(
86 &self,
87 dav1d_picture: &Dav1dPicture,
88 image: &mut Image,
89 category: Category,
90 ) -> AvifResult<()> {
91 match category {
92 Category::Alpha => {
93 if image.width > 0
94 && image.height > 0
95 && (image.width != (dav1d_picture.p.w as u32)
96 || image.height != (dav1d_picture.p.h as u32)
97 || image.depth != (dav1d_picture.p.bpc as u8))
98 {
99 // Alpha plane does not match the previous alpha plane.
100 return Err(AvifError::UnknownError("".into()));
101 }
102 image.width = dav1d_picture.p.w as u32;
103 image.height = dav1d_picture.p.h as u32;
104 image.depth = dav1d_picture.p.bpc as u8;
105 image.row_bytes[3] = dav1d_picture.stride[0] as u32;
106 image.planes[3] = Some(Pixels::from_raw_pointer(
107 dav1d_picture.data[0] as *mut u8,
108 image.depth as u32,
109 image.height,
110 image.row_bytes[3],
111 )?);
112 image.image_owns_planes[3] = false;
113 let seq_hdr = unsafe { &(*dav1d_picture.seq_hdr) };
114 image.yuv_range =
115 if seq_hdr.color_range == 0 { YuvRange::Limited } else { YuvRange::Full };
116 }
117 _ => {
118 image.width = dav1d_picture.p.w as u32;
119 image.height = dav1d_picture.p.h as u32;
120 image.depth = dav1d_picture.p.bpc as u8;
121
122 image.yuv_format = match dav1d_picture.p.layout {
123 0 => PixelFormat::Yuv400,
124 1 => PixelFormat::Yuv420,
125 2 => PixelFormat::Yuv422,
126 3 => PixelFormat::Yuv444,
127 _ => return Err(AvifError::UnknownError("".into())), // not reached.
128 };
129 let seq_hdr = unsafe { &(*dav1d_picture.seq_hdr) };
130 image.yuv_range =
131 if seq_hdr.color_range == 0 { YuvRange::Limited } else { YuvRange::Full };
132 image.chroma_sample_position = (seq_hdr.chr as u32).into();
133
134 image.color_primaries = (seq_hdr.pri as u16).into();
135 image.transfer_characteristics = (seq_hdr.trc as u16).into();
136 image.matrix_coefficients = (seq_hdr.mtrx as u16).into();
137
138 for plane in 0usize..image.yuv_format.plane_count() {
139 let stride_index = if plane == 0 { 0 } else { 1 };
140 image.row_bytes[plane] = dav1d_picture.stride[stride_index] as u32;
141 image.planes[plane] = Some(Pixels::from_raw_pointer(
142 dav1d_picture.data[plane] as *mut u8,
143 image.depth as u32,
144 image.height,
145 image.row_bytes[plane],
146 )?);
147 image.image_owns_planes[plane] = false;
148 }
149 if image.yuv_format == PixelFormat::Yuv400 {
150 // Clear left over chroma planes from previous frames.
151 image.clear_chroma_planes();
152 }
153 }
154 }
155 Ok(())
156 }
157 }
158
159 // The type of the fields from dav1d_sys::bindings::* are dependent on the
160 // compiler that is used to generate the bindings, version of dav1d, etc.
161 // So allow clippy to ignore unnecessary cast warnings.
162 #[allow(clippy::unnecessary_cast)]
163 impl Decoder for Dav1d {
codec(&self) -> CodecChoice164 fn codec(&self) -> CodecChoice {
165 CodecChoice::Dav1d
166 }
167
initialize(&mut self, config: &DecoderConfig) -> AvifResult<()>168 fn initialize(&mut self, config: &DecoderConfig) -> AvifResult<()> {
169 self.config = Some(config.clone());
170 Ok(())
171 }
172
get_next_image( &mut self, av1_payload: &[u8], spatial_id: u8, image: &mut Image, category: Category, ) -> AvifResult<()>173 fn get_next_image(
174 &mut self,
175 av1_payload: &[u8],
176 spatial_id: u8,
177 image: &mut Image,
178 category: Category,
179 ) -> AvifResult<()> {
180 if self.context.is_none() {
181 self.initialize_impl(true)?;
182 }
183 unsafe {
184 let mut data: Dav1dData = std::mem::zeroed();
185 let res = dav1d_data_wrap(
186 (&mut data) as *mut _,
187 av1_payload.as_ptr(),
188 av1_payload.len(),
189 Some(avif_dav1d_free_callback),
190 /*cookie=*/ std::ptr::null_mut(),
191 );
192 if res != 0 {
193 return Err(AvifError::UnknownError(format!(
194 "dav1d_data_wrap returned {res}"
195 )));
196 }
197 let mut next_frame: Dav1dPicture = std::mem::zeroed();
198 let got_picture;
199 loop {
200 if !data.data.is_null() {
201 let res = dav1d_send_data(self.context.unwrap(), (&mut data) as *mut _);
202 if res < 0 && res != DAV1D_EAGAIN {
203 dav1d_data_unref((&mut data) as *mut _);
204 return Err(AvifError::UnknownError(format!(
205 "dav1d_send_data returned {res}"
206 )));
207 }
208 }
209
210 let res = dav1d_get_picture(self.context.unwrap(), (&mut next_frame) as *mut _);
211 if res == DAV1D_EAGAIN {
212 // send more data.
213 if !data.data.is_null() {
214 continue;
215 }
216 return Err(AvifError::UnknownError("".into()));
217 } else if res < 0 {
218 if !data.data.is_null() {
219 dav1d_data_unref((&mut data) as *mut _);
220 }
221 return Err(AvifError::UnknownError(format!(
222 "dav1d_send_picture returned {res}"
223 )));
224 } else {
225 // Got a picture.
226 let frame_spatial_id = (*next_frame.frame_hdr).spatial_id as u8;
227 if spatial_id != 0xFF && spatial_id != frame_spatial_id {
228 // layer selection: skip this unwanted layer.
229 dav1d_picture_unref((&mut next_frame) as *mut _);
230 } else {
231 got_picture = true;
232 break;
233 }
234 }
235 }
236 if !data.data.is_null() {
237 dav1d_data_unref((&mut data) as *mut _);
238 }
239
240 // Drain all buffered frames in the decoder.
241 //
242 // The sample should have only one frame of the desired layer. If there are more frames
243 // after that frame, we need to discard them so that they won't be mistakenly output
244 // when the decoder is used to decode another sample.
245 let mut buffered_frame: Dav1dPicture = std::mem::zeroed();
246 loop {
247 let res = dav1d_get_picture(self.context.unwrap(), (&mut buffered_frame) as *mut _);
248 if res < 0 {
249 if res != DAV1D_EAGAIN {
250 if got_picture {
251 dav1d_picture_unref((&mut next_frame) as *mut _);
252 }
253 return Err(AvifError::UnknownError(format!(
254 "error draining buffered frames {res}"
255 )));
256 }
257 } else {
258 dav1d_picture_unref((&mut buffered_frame) as *mut _);
259 }
260 if res != 0 {
261 break;
262 }
263 }
264
265 if got_picture {
266 // unref previous frame.
267 if self.picture.is_some() {
268 let mut previous_picture = self.picture.unwrap();
269 dav1d_picture_unref((&mut previous_picture) as *mut _);
270 }
271 self.picture = Some(next_frame);
272 } else if category == Category::Alpha && self.picture.is_some() {
273 // Special case for alpha, re-use last frame.
274 } else {
275 return Err(AvifError::UnknownError("".into()));
276 }
277 }
278 self.picture_to_image(self.picture.unwrap_ref(), image, category)?;
279 Ok(())
280 }
281
get_next_image_grid( &mut self, _payloads: &[Vec<u8>], _spatial_id: u8, _grid_image_helper: &mut GridImageHelper, ) -> AvifResult<()>282 fn get_next_image_grid(
283 &mut self,
284 _payloads: &[Vec<u8>],
285 _spatial_id: u8,
286 _grid_image_helper: &mut GridImageHelper,
287 ) -> AvifResult<()> {
288 Err(AvifError::NotImplemented)
289 }
290 }
291
292 impl Drop for Dav1d {
drop(&mut self)293 fn drop(&mut self) {
294 if self.picture.is_some() {
295 unsafe { dav1d_picture_unref(self.picture.unwrap_mut() as *mut _) };
296 }
297 if self.context.is_some() {
298 unsafe { dav1d_close(&mut self.context.unwrap()) };
299 }
300 }
301 }
302