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 super::gainmap::*;
16 use super::image::*;
17 use super::io::*;
18 use super::types::*;
19
20 use std::ffi::CStr;
21 use std::os::raw::c_char;
22
23 use crate::decoder::track::*;
24 use crate::decoder::*;
25 use crate::*;
26
27 #[repr(C)]
28 pub struct avifDecoder {
29 pub codecChoice: avifCodecChoice,
30 pub maxThreads: i32,
31 pub requestedSource: Source,
32 pub allowProgressive: avifBool,
33 pub allowIncremental: avifBool,
34 pub ignoreExif: avifBool,
35 pub ignoreXMP: avifBool,
36 pub imageSizeLimit: u32,
37 pub imageDimensionLimit: u32,
38 pub imageCountLimit: u32,
39 pub strictFlags: avifStrictFlags,
40
41 // Output params.
42 pub image: *mut avifImage,
43 pub imageIndex: i32,
44 pub imageCount: i32,
45 pub progressiveState: ProgressiveState,
46 pub imageTiming: ImageTiming,
47 pub timescale: u64,
48 pub duration: f64,
49 pub durationInTimescales: u64,
50 pub repetitionCount: i32,
51 pub alphaPresent: avifBool,
52 pub ioStats: IOStats,
53 pub diag: avifDiagnostics,
54 pub data: *mut avifDecoderData,
55 pub imageContentToDecode: avifImageContentTypeFlags,
56 pub imageSequenceTrackPresent: avifBool,
57
58 // These fields are not part of libavif. Any new fields that are to be header file compatible
59 // with libavif must be added before this line.
60 pub androidMediaCodecOutputColorFormat: AndroidMediaCodecOutputColorFormat,
61 pub compressionFormat: CompressionFormat,
62
63 // Rust specific fields that are not accessed from the C/C++ layer.
64 rust_decoder: Box<Decoder>,
65 image_object: avifImage,
66 gainmap_object: avifGainMap,
67 gainmap_image_object: avifImage,
68 }
69
70 impl Default for avifDecoder {
default() -> Self71 fn default() -> Self {
72 Self {
73 codecChoice: avifCodecChoice::Auto,
74 maxThreads: 1,
75 requestedSource: Source::Auto,
76 allowIncremental: AVIF_FALSE,
77 allowProgressive: AVIF_FALSE,
78 ignoreExif: AVIF_FALSE,
79 ignoreXMP: AVIF_FALSE,
80 imageSizeLimit: DEFAULT_IMAGE_SIZE_LIMIT,
81 imageDimensionLimit: DEFAULT_IMAGE_DIMENSION_LIMIT,
82 imageCountLimit: DEFAULT_IMAGE_COUNT_LIMIT,
83 strictFlags: AVIF_STRICT_ENABLED,
84 image: std::ptr::null_mut(),
85 imageIndex: -1,
86 imageCount: 0,
87 progressiveState: ProgressiveState::Unavailable,
88 imageTiming: ImageTiming::default(),
89 timescale: 0,
90 duration: 0.0,
91 durationInTimescales: 0,
92 repetitionCount: 0,
93 alphaPresent: AVIF_FALSE,
94 ioStats: Default::default(),
95 diag: avifDiagnostics::default(),
96 data: std::ptr::null_mut(),
97 imageContentToDecode: AVIF_IMAGE_CONTENT_COLOR_AND_ALPHA,
98 imageSequenceTrackPresent: AVIF_FALSE,
99 androidMediaCodecOutputColorFormat: AndroidMediaCodecOutputColorFormat::default(),
100 compressionFormat: CompressionFormat::default(),
101 rust_decoder: Box::<Decoder>::default(),
102 image_object: avifImage::default(),
103 gainmap_image_object: avifImage::default(),
104 gainmap_object: avifGainMap::default(),
105 }
106 }
107 }
108
109 #[no_mangle]
crabby_avifDecoderCreate() -> *mut avifDecoder110 pub unsafe extern "C" fn crabby_avifDecoderCreate() -> *mut avifDecoder {
111 Box::into_raw(Box::<avifDecoder>::default())
112 }
113
114 #[no_mangle]
crabby_avifDecoderSetIO(decoder: *mut avifDecoder, io: *mut avifIO)115 pub unsafe extern "C" fn crabby_avifDecoderSetIO(decoder: *mut avifDecoder, io: *mut avifIO) {
116 unsafe {
117 let rust_decoder = &mut (*decoder).rust_decoder;
118 rust_decoder.set_io(Box::new(avifIOWrapper::create(*io)));
119 }
120 }
121
122 #[no_mangle]
crabby_avifDecoderSetIOFile( decoder: *mut avifDecoder, filename: *const c_char, ) -> avifResult123 pub unsafe extern "C" fn crabby_avifDecoderSetIOFile(
124 decoder: *mut avifDecoder,
125 filename: *const c_char,
126 ) -> avifResult {
127 unsafe {
128 let rust_decoder = &mut (*decoder).rust_decoder;
129 let filename = String::from(CStr::from_ptr(filename).to_str().unwrap_or(""));
130 to_avifResult(&rust_decoder.set_io_file(&filename))
131 }
132 }
133
134 #[no_mangle]
crabby_avifDecoderSetIOMemory( decoder: *mut avifDecoder, data: *const u8, size: usize, ) -> avifResult135 pub unsafe extern "C" fn crabby_avifDecoderSetIOMemory(
136 decoder: *mut avifDecoder,
137 data: *const u8,
138 size: usize,
139 ) -> avifResult {
140 let rust_decoder = unsafe { &mut (*decoder).rust_decoder };
141 to_avifResult(unsafe { &rust_decoder.set_io_raw(data, size) })
142 }
143
144 #[no_mangle]
crabby_avifDecoderSetSource( decoder: *mut avifDecoder, source: Source, ) -> avifResult145 pub unsafe extern "C" fn crabby_avifDecoderSetSource(
146 decoder: *mut avifDecoder,
147 source: Source,
148 ) -> avifResult {
149 unsafe {
150 (*decoder).requestedSource = source;
151 }
152 avifResult::Ok
153 }
154
155 impl From<&avifDecoder> for Settings {
from(decoder: &avifDecoder) -> Self156 fn from(decoder: &avifDecoder) -> Self {
157 let strictness = if decoder.strictFlags == AVIF_STRICT_DISABLED {
158 Strictness::None
159 } else if decoder.strictFlags == AVIF_STRICT_ENABLED {
160 Strictness::All
161 } else {
162 let mut flags: Vec<StrictnessFlag> = Vec::new();
163 if (decoder.strictFlags & AVIF_STRICT_PIXI_REQUIRED) != 0 {
164 flags.push(StrictnessFlag::PixiRequired);
165 }
166 if (decoder.strictFlags & AVIF_STRICT_CLAP_VALID) != 0 {
167 flags.push(StrictnessFlag::ClapValid);
168 }
169 if (decoder.strictFlags & AVIF_STRICT_ALPHA_ISPE_REQUIRED) != 0 {
170 flags.push(StrictnessFlag::AlphaIspeRequired);
171 }
172 Strictness::SpecificInclude(flags)
173 };
174 let image_content_to_decode_flags: ImageContentType = match decoder.imageContentToDecode {
175 AVIF_IMAGE_CONTENT_ALL => ImageContentType::All,
176 AVIF_IMAGE_CONTENT_COLOR_AND_ALPHA => ImageContentType::ColorAndAlpha,
177 AVIF_IMAGE_CONTENT_GAIN_MAP => ImageContentType::GainMap,
178 _ => ImageContentType::None,
179 };
180 Self {
181 source: decoder.requestedSource,
182 strictness,
183 allow_progressive: decoder.allowProgressive == AVIF_TRUE,
184 allow_incremental: decoder.allowIncremental == AVIF_TRUE,
185 ignore_exif: decoder.ignoreExif == AVIF_TRUE,
186 ignore_xmp: decoder.ignoreXMP == AVIF_TRUE,
187 image_content_to_decode: image_content_to_decode_flags,
188 codec_choice: match decoder.codecChoice {
189 avifCodecChoice::Auto => CodecChoice::Auto,
190 avifCodecChoice::Dav1d => CodecChoice::Dav1d,
191 avifCodecChoice::Libgav1 => CodecChoice::Libgav1,
192 // Silently treat all other choices the same as Auto.
193 _ => CodecChoice::Auto,
194 },
195 image_size_limit: decoder.imageSizeLimit,
196 image_dimension_limit: decoder.imageDimensionLimit,
197 image_count_limit: decoder.imageCountLimit,
198 max_threads: u32::try_from(decoder.maxThreads).unwrap_or(0),
199 android_mediacodec_output_color_format: decoder.androidMediaCodecOutputColorFormat,
200 }
201 }
202 }
203
rust_decoder_to_avifDecoder(src: &Decoder, dst: &mut avifDecoder)204 fn rust_decoder_to_avifDecoder(src: &Decoder, dst: &mut avifDecoder) {
205 // Copy image.
206 let image = src.image().unwrap();
207 dst.image_object = image.into();
208
209 // Copy decoder properties.
210 dst.alphaPresent = to_avifBool(image.alpha_present);
211 dst.imageSequenceTrackPresent = to_avifBool(image.image_sequence_track_present);
212 dst.progressiveState = image.progressive_state;
213
214 dst.imageTiming = src.image_timing();
215 dst.imageCount = src.image_count() as i32;
216 dst.imageIndex = src.image_index();
217 dst.repetitionCount = match src.repetition_count() {
218 RepetitionCount::Unknown => AVIF_REPETITION_COUNT_UNKNOWN,
219 RepetitionCount::Infinite => AVIF_REPETITION_COUNT_INFINITE,
220 RepetitionCount::Finite(x) => x,
221 };
222 dst.timescale = src.timescale();
223 dst.durationInTimescales = src.duration_in_timescales();
224 dst.duration = src.duration();
225 dst.ioStats = src.io_stats();
226 dst.compressionFormat = src.compression_format();
227
228 if src.gainmap_present() {
229 dst.gainmap_image_object = (&src.gainmap().image).into();
230 dst.gainmap_object = src.gainmap().into();
231 if src.settings.image_content_to_decode.gainmap() {
232 dst.gainmap_object.image = (&mut dst.gainmap_image_object) as *mut avifImage;
233 }
234 dst.image_object.gainMap = (&mut dst.gainmap_object) as *mut avifGainMap;
235 }
236 dst.image = (&mut dst.image_object) as *mut avifImage;
237 }
238
239 #[no_mangle]
crabby_avifDecoderParse(decoder: *mut avifDecoder) -> avifResult240 pub unsafe extern "C" fn crabby_avifDecoderParse(decoder: *mut avifDecoder) -> avifResult {
241 unsafe {
242 let rust_decoder = &mut (*decoder).rust_decoder;
243 rust_decoder.settings = (&(*decoder)).into();
244
245 let res = rust_decoder.parse();
246 (*decoder).diag.set_from_result(&res);
247 if res.is_err() {
248 return to_avifResult(&res);
249 }
250 rust_decoder_to_avifDecoder(rust_decoder, &mut (*decoder));
251 avifResult::Ok
252 }
253 }
254
255 #[no_mangle]
crabby_avifDecoderNextImage(decoder: *mut avifDecoder) -> avifResult256 pub unsafe extern "C" fn crabby_avifDecoderNextImage(decoder: *mut avifDecoder) -> avifResult {
257 unsafe {
258 let rust_decoder = &mut (*decoder).rust_decoder;
259 rust_decoder.settings = (&(*decoder)).into();
260
261 let previous_decoded_row_count = rust_decoder.decoded_row_count();
262
263 let res = rust_decoder.next_image();
264 (*decoder).diag.set_from_result(&res);
265 let mut early_return = false;
266 if res.is_err() {
267 early_return = true;
268 if rust_decoder.settings.allow_incremental
269 && matches!(res.as_ref().err().unwrap(), AvifError::WaitingOnIo)
270 {
271 early_return = previous_decoded_row_count == rust_decoder.decoded_row_count();
272 }
273 }
274 if early_return {
275 return to_avifResult(&res);
276 }
277 rust_decoder_to_avifDecoder(rust_decoder, &mut (*decoder));
278 to_avifResult(&res)
279 }
280 }
281
282 #[no_mangle]
crabby_avifDecoderNthImage( decoder: *mut avifDecoder, frameIndex: u32, ) -> avifResult283 pub unsafe extern "C" fn crabby_avifDecoderNthImage(
284 decoder: *mut avifDecoder,
285 frameIndex: u32,
286 ) -> avifResult {
287 unsafe {
288 let rust_decoder = &mut (*decoder).rust_decoder;
289 rust_decoder.settings = (&(*decoder)).into();
290
291 let previous_decoded_row_count = rust_decoder.decoded_row_count();
292 let image_index = (rust_decoder.image_index() + 1) as u32;
293
294 let res = rust_decoder.nth_image(frameIndex);
295 (*decoder).diag.set_from_result(&res);
296 let mut early_return = false;
297 if res.is_err() {
298 early_return = true;
299 if rust_decoder.settings.allow_incremental
300 && matches!(res.as_ref().err().unwrap(), AvifError::WaitingOnIo)
301 {
302 if image_index != frameIndex {
303 early_return = false;
304 } else {
305 early_return = previous_decoded_row_count == rust_decoder.decoded_row_count();
306 }
307 }
308 }
309 if early_return {
310 return to_avifResult(&res);
311 }
312 rust_decoder_to_avifDecoder(rust_decoder, &mut (*decoder));
313 to_avifResult(&res)
314 }
315 }
316
317 #[no_mangle]
crabby_avifDecoderNthImageTiming( decoder: *const avifDecoder, frameIndex: u32, outTiming: *mut ImageTiming, ) -> avifResult318 pub unsafe extern "C" fn crabby_avifDecoderNthImageTiming(
319 decoder: *const avifDecoder,
320 frameIndex: u32,
321 outTiming: *mut ImageTiming,
322 ) -> avifResult {
323 let rust_decoder = unsafe { &(*decoder).rust_decoder };
324 let image_timing = rust_decoder.nth_image_timing(frameIndex);
325 if let Ok(timing) = image_timing {
326 unsafe {
327 *outTiming = timing;
328 }
329 }
330 to_avifResult(&image_timing)
331 }
332
333 #[no_mangle]
crabby_avifDecoderDestroy(decoder: *mut avifDecoder)334 pub unsafe extern "C" fn crabby_avifDecoderDestroy(decoder: *mut avifDecoder) {
335 unsafe {
336 let _ = Box::from_raw(decoder);
337 }
338 }
339
340 #[no_mangle]
crabby_avifDecoderRead( decoder: *mut avifDecoder, image: *mut avifImage, ) -> avifResult341 pub unsafe extern "C" fn crabby_avifDecoderRead(
342 decoder: *mut avifDecoder,
343 image: *mut avifImage,
344 ) -> avifResult {
345 unsafe {
346 let rust_decoder = &mut (*decoder).rust_decoder;
347 rust_decoder.settings = (&(*decoder)).into();
348
349 let res = rust_decoder.parse();
350 if res.is_err() {
351 return to_avifResult(&res);
352 }
353 let res = rust_decoder.next_image();
354 if res.is_err() {
355 return to_avifResult(&res);
356 }
357 rust_decoder_to_avifDecoder(rust_decoder, &mut (*decoder));
358 *image = (*decoder).image_object.clone();
359 avifResult::Ok
360 }
361 }
362
363 #[no_mangle]
crabby_avifDecoderReadMemory( decoder: *mut avifDecoder, image: *mut avifImage, data: *const u8, size: usize, ) -> avifResult364 pub unsafe extern "C" fn crabby_avifDecoderReadMemory(
365 decoder: *mut avifDecoder,
366 image: *mut avifImage,
367 data: *const u8,
368 size: usize,
369 ) -> avifResult {
370 unsafe {
371 let res = crabby_avifDecoderSetIOMemory(decoder, data, size);
372 if res != avifResult::Ok {
373 return res;
374 }
375 crabby_avifDecoderRead(decoder, image)
376 }
377 }
378
379 #[no_mangle]
crabby_avifDecoderReadFile( decoder: *mut avifDecoder, image: *mut avifImage, filename: *const c_char, ) -> avifResult380 pub unsafe extern "C" fn crabby_avifDecoderReadFile(
381 decoder: *mut avifDecoder,
382 image: *mut avifImage,
383 filename: *const c_char,
384 ) -> avifResult {
385 unsafe {
386 let res = crabby_avifDecoderSetIOFile(decoder, filename);
387 if res != avifResult::Ok {
388 return res;
389 }
390 crabby_avifDecoderRead(decoder, image)
391 }
392 }
393
394 #[no_mangle]
crabby_avifDecoderIsKeyframe( decoder: *const avifDecoder, frameIndex: u32, ) -> avifBool395 pub unsafe extern "C" fn crabby_avifDecoderIsKeyframe(
396 decoder: *const avifDecoder,
397 frameIndex: u32,
398 ) -> avifBool {
399 let rust_decoder = unsafe { &(*decoder).rust_decoder };
400 to_avifBool(rust_decoder.is_keyframe(frameIndex))
401 }
402
403 #[no_mangle]
crabby_avifDecoderNearestKeyframe( decoder: *const avifDecoder, frameIndex: u32, ) -> u32404 pub unsafe extern "C" fn crabby_avifDecoderNearestKeyframe(
405 decoder: *const avifDecoder,
406 frameIndex: u32,
407 ) -> u32 {
408 let rust_decoder = unsafe { &(*decoder).rust_decoder };
409 rust_decoder.nearest_keyframe(frameIndex)
410 }
411
412 #[no_mangle]
crabby_avifDecoderDecodedRowCount(decoder: *const avifDecoder) -> u32413 pub unsafe extern "C" fn crabby_avifDecoderDecodedRowCount(decoder: *const avifDecoder) -> u32 {
414 let rust_decoder = unsafe { &(*decoder).rust_decoder };
415 rust_decoder.decoded_row_count()
416 }
417
418 #[allow(non_camel_case_types)]
419 pub type avifExtent = Extent;
420
421 #[no_mangle]
crabby_avifDecoderNthImageMaxExtent( decoder: *const avifDecoder, frameIndex: u32, outExtent: *mut avifExtent, ) -> avifResult422 pub unsafe extern "C" fn crabby_avifDecoderNthImageMaxExtent(
423 decoder: *const avifDecoder,
424 frameIndex: u32,
425 outExtent: *mut avifExtent,
426 ) -> avifResult {
427 let rust_decoder = unsafe { &(*decoder).rust_decoder };
428 let res = rust_decoder.nth_image_max_extent(frameIndex);
429 if res.is_err() {
430 return to_avifResult(&res);
431 }
432 unsafe {
433 *outExtent = res.unwrap();
434 }
435 avifResult::Ok
436 }
437
438 #[no_mangle]
crabby_avifPeekCompatibleFileType(input: *const avifROData) -> avifBool439 pub unsafe extern "C" fn crabby_avifPeekCompatibleFileType(input: *const avifROData) -> avifBool {
440 let data = unsafe { std::slice::from_raw_parts((*input).data, (*input).size) };
441 to_avifBool(Decoder::peek_compatible_file_type(data))
442 }
443