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