• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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