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 libgav1_sys::bindings::*;
24 
25 use std::mem::MaybeUninit;
26 
27 #[derive(Debug, Default)]
28 pub struct Libgav1 {
29     decoder: Option<*mut Libgav1Decoder>,
30     image: Option<Libgav1DecoderBuffer>,
31 }
32 
33 #[allow(non_upper_case_globals)]
34 // The type of the fields from from dav1d_sys::bindings::* are dependent on the compiler that
35 // is used to generate the bindings, version of dav1d, etc. So allow clippy to ignore
36 // unnecessary cast warnings.
37 #[allow(clippy::unnecessary_cast)]
38 impl Decoder for Libgav1 {
initialize(&mut self, config: &DecoderConfig) -> AvifResult<()>39     fn initialize(&mut self, config: &DecoderConfig) -> AvifResult<()> {
40         if self.decoder.is_some() {
41             return Ok(()); // Already initialized.
42         }
43         let mut settings_uninit: MaybeUninit<Libgav1DecoderSettings> = MaybeUninit::uninit();
44         unsafe {
45             Libgav1DecoderSettingsInitDefault(settings_uninit.as_mut_ptr());
46         }
47         let mut settings = unsafe { settings_uninit.assume_init() };
48         settings.threads = i32::try_from(config.max_threads).unwrap_or(1);
49         settings.operating_point = config.operating_point as i32;
50         settings.output_all_layers = if config.all_layers { 1 } else { 0 };
51         unsafe {
52             let mut dec = MaybeUninit::uninit();
53             let ret = Libgav1DecoderCreate(&settings, dec.as_mut_ptr());
54             if ret != Libgav1StatusCode_kLibgav1StatusOk {
55                 return Err(AvifError::UnknownError(format!(
56                     "Libgav1DecoderCreate returned {ret}"
57                 )));
58             }
59             self.decoder = Some(dec.assume_init());
60         }
61         Ok(())
62     }
63 
get_next_image( &mut self, av1_payload: &[u8], spatial_id: u8, image: &mut Image, category: Category, ) -> AvifResult<()>64     fn get_next_image(
65         &mut self,
66         av1_payload: &[u8],
67         spatial_id: u8,
68         image: &mut Image,
69         category: Category,
70     ) -> AvifResult<()> {
71         if self.decoder.is_none() {
72             self.initialize(&DecoderConfig::default())?;
73         }
74         unsafe {
75             let ret = Libgav1DecoderEnqueueFrame(
76                 self.decoder.unwrap(),
77                 av1_payload.as_ptr(),
78                 av1_payload.len(),
79                 0,
80                 std::ptr::null_mut(),
81             );
82             if ret != Libgav1StatusCode_kLibgav1StatusOk {
83                 return Err(AvifError::UnknownError(format!(
84                     "Libgav1DecoderEnqueueFrame returned {ret}"
85                 )));
86             }
87             self.image = None;
88             let mut next_frame: *const Libgav1DecoderBuffer = std::ptr::null_mut();
89             loop {
90                 let ret = Libgav1DecoderDequeueFrame(self.decoder.unwrap(), &mut next_frame);
91                 if ret != Libgav1StatusCode_kLibgav1StatusOk {
92                     return Err(AvifError::UnknownError(format!(
93                         "Libgav1DecoderDequeueFrame returned {ret}"
94                     )));
95                 }
96                 if !next_frame.is_null()
97                     && spatial_id != 0xFF
98                     && (*next_frame).spatial_id as u8 != spatial_id
99                 {
100                     next_frame = std::ptr::null_mut();
101                 } else {
102                     break;
103                 }
104             }
105             // Got an image.
106             if next_frame.is_null() {
107                 if category == Category::Alpha {
108                     // Special case for alpha, re-use last frame.
109                 } else {
110                     return Err(AvifError::UnknownError("".into()));
111                 }
112             } else {
113                 self.image = Some(*next_frame);
114             }
115 
116             let gav1_image = &self.image.unwrap();
117             match category {
118                 Category::Alpha => {
119                     if image.width > 0
120                         && image.height > 0
121                         && (image.width != (gav1_image.displayed_width[0] as u32)
122                             || image.height != (gav1_image.displayed_height[0] as u32)
123                             || image.depth != (gav1_image.bitdepth as u8))
124                     {
125                         // Alpha plane does not match the previous alpha plane.
126                         return Err(AvifError::UnknownError("".into()));
127                     }
128                     image.width = gav1_image.displayed_width[0] as u32;
129                     image.height = gav1_image.displayed_height[0] as u32;
130                     image.depth = gav1_image.bitdepth as u8;
131                     image.row_bytes[3] = gav1_image.stride[0] as u32;
132                     image.planes[3] = Some(Pixels::from_raw_pointer(
133                         gav1_image.plane[0],
134                         image.depth as u32,
135                         image.height,
136                         image.row_bytes[3],
137                     )?);
138                     image.image_owns_planes[3] = false;
139                     image.yuv_range =
140                         if gav1_image.color_range == Libgav1ColorRange_kLibgav1ColorRangeStudio {
141                             YuvRange::Limited
142                         } else {
143                             YuvRange::Full
144                         };
145                 }
146                 _ => {
147                     image.width = gav1_image.displayed_width[0] as u32;
148                     image.height = gav1_image.displayed_height[0] as u32;
149                     image.depth = gav1_image.bitdepth as u8;
150 
151                     image.yuv_format = match gav1_image.image_format {
152                         Libgav1ImageFormat_kLibgav1ImageFormatMonochrome400 => PixelFormat::Yuv400,
153                         Libgav1ImageFormat_kLibgav1ImageFormatYuv420 => PixelFormat::Yuv420,
154                         Libgav1ImageFormat_kLibgav1ImageFormatYuv422 => PixelFormat::Yuv422,
155                         Libgav1ImageFormat_kLibgav1ImageFormatYuv444 => PixelFormat::Yuv444,
156                         _ => PixelFormat::Yuv420, // not reached.
157                     };
158                     image.yuv_range =
159                         if gav1_image.color_range == Libgav1ColorRange_kLibgav1ColorRangeStudio {
160                             YuvRange::Limited
161                         } else {
162                             YuvRange::Full
163                         };
164                     image.chroma_sample_position =
165                         (gav1_image.chroma_sample_position as u32).into();
166 
167                     image.color_primaries = (gav1_image.color_primary as u16).into();
168                     image.transfer_characteristics =
169                         (gav1_image.transfer_characteristics as u16).into();
170                     image.matrix_coefficients = (gav1_image.matrix_coefficients as u16).into();
171 
172                     for plane in 0usize..image.yuv_format.plane_count() {
173                         image.row_bytes[plane] = gav1_image.stride[plane] as u32;
174                         image.planes[plane] = Some(Pixels::from_raw_pointer(
175                             gav1_image.plane[plane],
176                             image.depth as u32,
177                             image.height,
178                             image.row_bytes[plane],
179                         )?);
180                         image.image_owns_planes[plane] = false;
181                     }
182                     if image.yuv_format == PixelFormat::Yuv400 {
183                         // Clear left over chroma planes from previous frames.
184                         image.clear_chroma_planes();
185                     }
186                 }
187             }
188         }
189         Ok(())
190     }
191 }
192 
193 impl Drop for Libgav1 {
drop(&mut self)194     fn drop(&mut self) {
195         if self.decoder.is_some() {
196             unsafe { Libgav1DecoderDestroy(self.decoder.unwrap()) };
197         }
198     }
199 }
200