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::decoder::tile::TileInfo; 16 use crate::decoder::Category; 17 use crate::decoder::ProgressiveState; 18 use crate::internal_utils::pixels::*; 19 use crate::internal_utils::*; 20 use crate::parser::mp4box::*; 21 use crate::utils::clap::CleanAperture; 22 use crate::*; 23 24 #[derive(Clone, Copy, Debug, PartialEq)] 25 pub enum Plane { 26 Y = 0, 27 U = 1, 28 V = 2, 29 A = 3, 30 } 31 32 impl From<usize> for Plane { from(plane: usize) -> Self33 fn from(plane: usize) -> Self { 34 match plane { 35 1 => Plane::U, 36 2 => Plane::V, 37 3 => Plane::A, 38 _ => Plane::Y, 39 } 40 } 41 } 42 43 impl Plane { to_usize(&self) -> usize44 pub fn to_usize(&self) -> usize { 45 match self { 46 Plane::Y => 0, 47 Plane::U => 1, 48 Plane::V => 2, 49 Plane::A => 3, 50 } 51 } 52 } 53 54 /// cbindgen:ignore 55 pub const MAX_PLANE_COUNT: usize = 4; 56 pub const YUV_PLANES: [Plane; 3] = [Plane::Y, Plane::U, Plane::V]; 57 pub const A_PLANE: [Plane; 1] = [Plane::A]; 58 pub const ALL_PLANES: [Plane; MAX_PLANE_COUNT] = [Plane::Y, Plane::U, Plane::V, Plane::A]; 59 60 #[repr(C)] 61 #[derive(Clone, Copy, Debug, Default, PartialEq)] 62 // VideoFullRangeFlag as specified in ISO/IEC 23091-2/ITU-T H.273. 63 pub enum YuvRange { 64 Limited = 0, 65 #[default] 66 Full = 1, 67 } 68 69 #[derive(Default)] 70 pub struct Image { 71 pub width: u32, 72 pub height: u32, 73 pub depth: u8, 74 75 pub yuv_format: PixelFormat, 76 pub yuv_range: YuvRange, 77 pub chroma_sample_position: ChromaSamplePosition, 78 79 pub alpha_present: bool, 80 pub alpha_premultiplied: bool, 81 82 pub row_bytes: [u32; MAX_PLANE_COUNT], 83 pub image_owns_planes: [bool; MAX_PLANE_COUNT], 84 85 pub planes: [Option<Pixels>; MAX_PLANE_COUNT], 86 87 pub color_primaries: ColorPrimaries, 88 pub transfer_characteristics: TransferCharacteristics, 89 pub matrix_coefficients: MatrixCoefficients, 90 91 pub clli: Option<ContentLightLevelInformation>, 92 pub pasp: Option<PixelAspectRatio>, 93 pub clap: Option<CleanAperture>, 94 pub irot_angle: Option<u8>, 95 pub imir_axis: Option<u8>, 96 97 pub exif: Vec<u8>, 98 pub icc: Vec<u8>, 99 pub xmp: Vec<u8>, 100 101 pub image_sequence_track_present: bool, 102 pub progressive_state: ProgressiveState, 103 } 104 105 pub struct PlaneData { 106 pub width: u32, 107 pub height: u32, 108 pub row_bytes: u32, 109 pub pixel_size: u32, 110 } 111 112 #[derive(Clone, Copy)] 113 pub enum PlaneRow<'a> { 114 Depth8(&'a [u8]), 115 Depth16(&'a [u16]), 116 } 117 118 impl Image { depth_valid(&self) -> bool119 pub fn depth_valid(&self) -> bool { 120 matches!(self.depth, 8 | 10 | 12 | 16) 121 } 122 max_channel(&self) -> u16123 pub fn max_channel(&self) -> u16 { 124 if !self.depth_valid() { 125 0 126 } else { 127 ((1i32 << self.depth) - 1) as u16 128 } 129 } 130 max_channel_f(&self) -> f32131 pub fn max_channel_f(&self) -> f32 { 132 self.max_channel() as f32 133 } 134 has_plane(&self, plane: Plane) -> bool135 pub fn has_plane(&self, plane: Plane) -> bool { 136 let plane_index = plane.to_usize(); 137 if self.planes[plane_index].is_none() || self.row_bytes[plane_index] == 0 { 138 return false; 139 } 140 self.planes[plane_index].unwrap_ref().has_data() 141 } 142 has_alpha(&self) -> bool143 pub fn has_alpha(&self) -> bool { 144 self.has_plane(Plane::A) 145 } 146 has_same_properties(&self, other: &Image) -> bool147 pub fn has_same_properties(&self, other: &Image) -> bool { 148 self.width == other.width && self.height == other.height && self.depth == other.depth 149 } 150 width(&self, plane: Plane) -> usize151 pub fn width(&self, plane: Plane) -> usize { 152 match plane { 153 Plane::Y | Plane::A => self.width as usize, 154 Plane::U => match self.yuv_format { 155 PixelFormat::Yuv444 156 | PixelFormat::AndroidP010 157 | PixelFormat::AndroidNv12 158 | PixelFormat::AndroidNv21 => self.width as usize, 159 PixelFormat::Yuv420 | PixelFormat::Yuv422 => (self.width as usize + 1) / 2, 160 PixelFormat::None | PixelFormat::Yuv400 => 0, 161 }, 162 Plane::V => match self.yuv_format { 163 PixelFormat::Yuv444 => self.width as usize, 164 PixelFormat::Yuv420 | PixelFormat::Yuv422 => (self.width as usize + 1) / 2, 165 PixelFormat::None 166 | PixelFormat::Yuv400 167 | PixelFormat::AndroidP010 168 | PixelFormat::AndroidNv12 169 | PixelFormat::AndroidNv21 => 0, 170 }, 171 } 172 } 173 height(&self, plane: Plane) -> usize174 pub fn height(&self, plane: Plane) -> usize { 175 match plane { 176 Plane::Y | Plane::A => self.height as usize, 177 Plane::U => match self.yuv_format { 178 PixelFormat::Yuv444 | PixelFormat::Yuv422 => self.height as usize, 179 PixelFormat::Yuv420 180 | PixelFormat::AndroidP010 181 | PixelFormat::AndroidNv12 182 | PixelFormat::AndroidNv21 => (self.height as usize + 1) / 2, 183 PixelFormat::None | PixelFormat::Yuv400 => 0, 184 }, 185 Plane::V => match self.yuv_format { 186 PixelFormat::Yuv444 | PixelFormat::Yuv422 => self.height as usize, 187 PixelFormat::Yuv420 => (self.height as usize + 1) / 2, 188 PixelFormat::None 189 | PixelFormat::Yuv400 190 | PixelFormat::AndroidP010 191 | PixelFormat::AndroidNv12 192 | PixelFormat::AndroidNv21 => 0, 193 }, 194 } 195 } 196 plane_data(&self, plane: Plane) -> Option<PlaneData>197 pub fn plane_data(&self, plane: Plane) -> Option<PlaneData> { 198 if !self.has_plane(plane) { 199 return None; 200 } 201 Some(PlaneData { 202 width: self.width(plane) as u32, 203 height: self.height(plane) as u32, 204 row_bytes: self.row_bytes[plane.to_usize()], 205 pixel_size: if self.depth == 8 { 1 } else { 2 }, 206 }) 207 } 208 row(&self, plane: Plane, row: u32) -> AvifResult<&[u8]>209 pub fn row(&self, plane: Plane, row: u32) -> AvifResult<&[u8]> { 210 let plane_data = self.plane_data(plane).ok_or(AvifError::NoContent)?; 211 let start = checked_mul!(row, plane_data.row_bytes)?; 212 self.planes[plane.to_usize()] 213 .unwrap_ref() 214 .slice(start, plane_data.row_bytes) 215 } 216 row_mut(&mut self, plane: Plane, row: u32) -> AvifResult<&mut [u8]>217 pub fn row_mut(&mut self, plane: Plane, row: u32) -> AvifResult<&mut [u8]> { 218 let plane_data = self.plane_data(plane).ok_or(AvifError::NoContent)?; 219 let row_bytes = plane_data.row_bytes; 220 let start = checked_mul!(row, row_bytes)?; 221 self.planes[plane.to_usize()] 222 .unwrap_mut() 223 .slice_mut(start, row_bytes) 224 } 225 row16(&self, plane: Plane, row: u32) -> AvifResult<&[u16]>226 pub fn row16(&self, plane: Plane, row: u32) -> AvifResult<&[u16]> { 227 let plane_data = self.plane_data(plane).ok_or(AvifError::NoContent)?; 228 let row_bytes = plane_data.row_bytes / 2; 229 let start = checked_mul!(row, row_bytes)?; 230 self.planes[plane.to_usize()] 231 .unwrap_ref() 232 .slice16(start, row_bytes) 233 } 234 row16_mut(&mut self, plane: Plane, row: u32) -> AvifResult<&mut [u16]>235 pub fn row16_mut(&mut self, plane: Plane, row: u32) -> AvifResult<&mut [u16]> { 236 let plane_data = self.plane_data(plane).ok_or(AvifError::NoContent)?; 237 let row_bytes = plane_data.row_bytes / 2; 238 let start = checked_mul!(row, row_bytes)?; 239 self.planes[plane.to_usize()] 240 .unwrap_mut() 241 .slice16_mut(start, row_bytes) 242 } 243 row_generic(&self, plane: Plane, row: u32) -> AvifResult<PlaneRow>244 pub fn row_generic(&self, plane: Plane, row: u32) -> AvifResult<PlaneRow> { 245 Ok(if self.depth == 8 { 246 PlaneRow::Depth8(self.row(plane, row)?) 247 } else { 248 PlaneRow::Depth16(self.row16(plane, row)?) 249 }) 250 } 251 clear_chroma_planes(&mut self)252 pub fn clear_chroma_planes(&mut self) { 253 for plane in [Plane::U, Plane::V] { 254 let plane = plane.to_usize(); 255 self.planes[plane] = None; 256 self.row_bytes[plane] = 0; 257 self.image_owns_planes[plane] = false; 258 } 259 } 260 allocate_planes(&mut self, category: Category) -> AvifResult<()>261 pub fn allocate_planes(&mut self, category: Category) -> AvifResult<()> { 262 let pixel_size: usize = if self.depth == 8 { 1 } else { 2 }; 263 for plane in category.planes() { 264 let plane = *plane; 265 let plane_index = plane.to_usize(); 266 let width = self.width(plane); 267 let plane_size = checked_mul!(width, self.height(plane))?; 268 let default_value = if plane == Plane::A { self.max_channel() } else { 0 }; 269 if self.planes[plane_index].is_some() 270 && self.planes[plane_index].unwrap_ref().size() == plane_size 271 && (self.planes[plane_index].unwrap_ref().pixel_bit_size() == 0 272 || self.planes[plane_index].unwrap_ref().pixel_bit_size() == pixel_size * 8) 273 { 274 continue; 275 } 276 self.planes[plane_index] = Some(if self.depth == 8 { 277 Pixels::Buffer(Vec::new()) 278 } else { 279 Pixels::Buffer16(Vec::new()) 280 }); 281 let pixels = self.planes[plane_index].unwrap_mut(); 282 pixels.resize(plane_size, default_value)?; 283 self.row_bytes[plane_index] = u32_from_usize(checked_mul!(width, pixel_size)?)?; 284 self.image_owns_planes[plane_index] = true; 285 } 286 Ok(()) 287 } 288 289 // If src contains pointers, this function will simply make a copy of the pointer without 290 // copying the actual pixels (stealing). If src contains buffer, this function will clone the 291 // buffers (copying). steal_or_copy_from(&mut self, src: &Image, category: Category) -> AvifResult<()>292 pub fn steal_or_copy_from(&mut self, src: &Image, category: Category) -> AvifResult<()> { 293 for plane in category.planes() { 294 let plane = plane.to_usize(); 295 (self.planes[plane], self.row_bytes[plane]) = match &src.planes[plane] { 296 Some(src_plane) => (Some(src_plane.clone()), src.row_bytes[plane]), 297 None => (None, 0), 298 } 299 } 300 Ok(()) 301 } 302 copy_from_tile( &mut self, tile: &Image, tile_info: &TileInfo, tile_index: u32, category: Category, ) -> AvifResult<()>303 pub fn copy_from_tile( 304 &mut self, 305 tile: &Image, 306 tile_info: &TileInfo, 307 tile_index: u32, 308 category: Category, 309 ) -> AvifResult<()> { 310 // This function is used only when |tile| contains pointers and self contains buffers. 311 let row_index = tile_index / tile_info.grid.columns; 312 let column_index = tile_index % tile_info.grid.columns; 313 for plane in category.planes() { 314 let plane = *plane; 315 let src_plane = tile.plane_data(plane); 316 if src_plane.is_none() { 317 continue; 318 } 319 let src_plane = src_plane.unwrap(); 320 // If this is the last tile column, clamp to left over width. 321 let src_width_to_copy = if column_index == tile_info.grid.columns - 1 { 322 let width_so_far = checked_mul!(src_plane.width, column_index)?; 323 checked_sub!(self.width(plane), usize_from_u32(width_so_far)?)? 324 } else { 325 usize_from_u32(src_plane.width)? 326 }; 327 328 // If this is the last tile row, clamp to left over height. 329 let src_height_to_copy = if row_index == tile_info.grid.rows - 1 { 330 let height_so_far = checked_mul!(src_plane.height, row_index)?; 331 checked_sub!(u32_from_usize(self.height(plane))?, height_so_far)? 332 } else { 333 src_plane.height 334 }; 335 336 let dst_y_start = checked_mul!(row_index, src_plane.height)?; 337 let dst_x_offset = usize_from_u32(checked_mul!(column_index, src_plane.width)?)?; 338 let dst_x_offset_end = checked_add!(dst_x_offset, src_width_to_copy)?; 339 if self.depth == 8 { 340 for y in 0..src_height_to_copy { 341 let src_row = tile.row(plane, y)?; 342 let src_slice = &src_row[0..src_width_to_copy]; 343 let dst_row = self.row_mut(plane, checked_add!(dst_y_start, y)?)?; 344 let dst_slice = &mut dst_row[dst_x_offset..dst_x_offset_end]; 345 dst_slice.copy_from_slice(src_slice); 346 } 347 } else { 348 for y in 0..src_height_to_copy { 349 let src_row = tile.row16(plane, y)?; 350 let src_slice = &src_row[0..src_width_to_copy]; 351 let dst_row = self.row16_mut(plane, checked_add!(dst_y_start, y)?)?; 352 let dst_slice = &mut dst_row[dst_x_offset..dst_x_offset_end]; 353 dst_slice.copy_from_slice(src_slice); 354 } 355 } 356 } 357 Ok(()) 358 } 359 } 360