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