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