From fd754d4c82a5488cd2e33af09c82238da6e793df Mon Sep 17 00:00:00 2001 From: Wan-Teh Chang Date: Tue, 6 Aug 2024 12:00:48 -0700 Subject: [PATCH] Remove decoder param of avifCodecGetNextImageFunc Remove the decoder parameter of avifCodecGetNextImageFunc so that the avifCodec struct is independent of the avifDecoder struct. Add the maxThreads and imageSizeLimit fields to the avifCodec struct so that they remain available to avifCodecGetNextImageFunc. This allows us to remove the avifDecoder local variable in avifEncoderDecodeSatoBaseImage(). --- include/avif/internal.h | 10 ++++++---- src/codec_aom.c | 3 +-- src/codec_avm.c | 3 +-- src/codec_dav1d.c | 7 +++---- src/codec_libgav1.c | 3 +-- src/read.c | 4 +++- src/write.c | 10 +++------- 7 files changed, 18 insertions(+), 22 deletions(-) diff --git a/include/avif/internal.h b/include/avif/internal.h index d81e698b3b..68e4defcb1 100644 --- a/include/avif/internal.h +++ b/include/avif/internal.h @@ -573,7 +573,6 @@ typedef enum avifEncoderChange typedef int avifEncoderChanges; typedef avifBool (*avifCodecGetNextImageFunc)(struct avifCodec * codec, - struct avifDecoder * decoder, const avifDecodeSample * sample, avifBool alpha, avifBool * isLimitedRangeAlpha, @@ -618,9 +617,12 @@ typedef struct avifCodec struct avifCodecInternal * internal; // up to each codec to use how it wants // avifDiagnostics * diag; // Shallow copy; owned by avifEncoder or avifDecoder - // - uint8_t operatingPoint; // Operating point, defaults to 0. - avifBool allLayers; // if true, the underlying codec must decode all layers, not just the best layer + + // Decoder options (for getNextImage): + int maxThreads; // See avifDecoder::maxThreads. + uint32_t imageSizeLimit; // See avifDecoder::imageSizeLimit. + uint8_t operatingPoint; // Operating point, defaults to 0. + avifBool allLayers; // if true, the underlying codec must decode all layers, not just the best layer avifCodecGetNextImageFunc getNextImage; avifCodecEncodeImageFunc encodeImage; diff --git a/src/codec_aom.c b/src/codec_aom.c index d11f8ee4e5..396c32f40a 100644 --- a/src/codec_aom.c +++ b/src/codec_aom.c @@ -91,7 +91,6 @@ static void aomCodecDestroyInternal(avifCodec * codec) #if defined(AVIF_CODEC_AOM_DECODE) static avifBool aomCodecGetNextImage(struct avifCodec * codec, - struct avifDecoder * decoder, const avifDecodeSample * sample, avifBool alpha, avifBool * isLimitedRangeAlpha, @@ -100,7 +99,7 @@ static avifBool aomCodecGetNextImage(struct avifCodec * codec, if (!codec->internal->decoderInitialized) { aom_codec_dec_cfg_t cfg; memset(&cfg, 0, sizeof(aom_codec_dec_cfg_t)); - cfg.threads = decoder->maxThreads; + cfg.threads = codec->maxThreads; cfg.allow_lowbitdepth = 1; aom_codec_iface_t * decoder_interface = aom_codec_av1_dx(); diff --git a/src/codec_avm.c b/src/codec_avm.c index 0ac61b5ba2..cff2f3d085 100644 --- a/src/codec_avm.c +++ b/src/codec_avm.c @@ -53,7 +53,6 @@ static avifResult avifCheckCodecVersionAVM() } static avifBool avmCodecGetNextImage(struct avifCodec * codec, - struct avifDecoder * decoder, const avifDecodeSample * sample, avifBool alpha, avifBool * isLimitedRangeAlpha, @@ -64,7 +63,7 @@ static avifBool avmCodecGetNextImage(struct avifCodec * codec, aom_codec_dec_cfg_t cfg; memset(&cfg, 0, sizeof(aom_codec_dec_cfg_t)); - cfg.threads = decoder->maxThreads; + cfg.threads = codec->maxThreads; aom_codec_iface_t * decoder_interface = aom_codec_av1_dx(); if (aom_codec_dec_init(&codec->internal->decoder, decoder_interface, &cfg, 0)) { diff --git a/src/codec_dav1d.c b/src/codec_dav1d.c index 804b531a45..5aff5a1262 100644 --- a/src/codec_dav1d.c +++ b/src/codec_dav1d.c @@ -49,7 +49,6 @@ static void dav1dCodecDestroyInternal(avifCodec * codec) } static avifBool dav1dCodecGetNextImage(struct avifCodec * codec, - struct avifDecoder * decoder, const avifDecodeSample * sample, avifBool alpha, avifBool * isLimitedRangeAlpha, @@ -61,16 +60,16 @@ static avifBool dav1dCodecGetNextImage(struct avifCodec * codec, // Give all available threads to decode a single frame as fast as possible #if DAV1D_API_VERSION_MAJOR >= 6 dav1dSettings.max_frame_delay = 1; - dav1dSettings.n_threads = AVIF_CLAMP(decoder->maxThreads, 1, DAV1D_MAX_THREADS); + dav1dSettings.n_threads = AVIF_CLAMP(codec->maxThreads, 1, DAV1D_MAX_THREADS); #else dav1dSettings.n_frame_threads = 1; - dav1dSettings.n_tile_threads = AVIF_CLAMP(decoder->maxThreads, 1, DAV1D_MAX_TILE_THREADS); + dav1dSettings.n_tile_threads = AVIF_CLAMP(codec->maxThreads, 1, DAV1D_MAX_TILE_THREADS); #endif // DAV1D_API_VERSION_MAJOR >= 6 // Set a maximum frame size limit to avoid OOM'ing fuzzers. In 32-bit builds, if // frame_size_limit > 8192 * 8192, dav1d reduces frame_size_limit to 8192 * 8192 and logs // a message, so we set frame_size_limit to at most 8192 * 8192 to avoid the dav1d_log // message. - dav1dSettings.frame_size_limit = (sizeof(size_t) < 8) ? AVIF_MIN(decoder->imageSizeLimit, 8192 * 8192) : decoder->imageSizeLimit; + dav1dSettings.frame_size_limit = (sizeof(size_t) < 8) ? AVIF_MIN(codec->imageSizeLimit, 8192 * 8192) : codec->imageSizeLimit; dav1dSettings.operating_point = codec->operatingPoint; dav1dSettings.all_layers = codec->allLayers; diff --git a/src/codec_libgav1.c b/src/codec_libgav1.c index 458ffcf8b9..43cb81f099 100644 --- a/src/codec_libgav1.c +++ b/src/codec_libgav1.c @@ -24,14 +24,13 @@ static void gav1CodecDestroyInternal(avifCodec * codec) } static avifBool gav1CodecGetNextImage(struct avifCodec * codec, - struct avifDecoder * decoder, const avifDecodeSample * sample, avifBool alpha, avifBool * isLimitedRangeAlpha, avifImage * image) { if (codec->internal->gav1Decoder == NULL) { - codec->internal->gav1Settings.threads = decoder->maxThreads; + codec->internal->gav1Settings.threads = codec->maxThreads; codec->internal->gav1Settings.operating_point = codec->operatingPoint; codec->internal->gav1Settings.output_all_layers = codec->allLayers; diff --git a/src/read.c b/src/read.c index 04db847736..98bf7cbce8 100644 --- a/src/read.c +++ b/src/read.c @@ -5711,7 +5711,9 @@ static avifResult avifDecoderDecodeTiles(avifDecoder * decoder, uint32_t nextIma } avifBool isLimitedRangeAlpha = AVIF_FALSE; - if (!tile->codec->getNextImage(tile->codec, decoder, sample, avifIsAlpha(tile->input->itemCategory), &isLimitedRangeAlpha, tile->image)) { + tile->codec->maxThreads = decoder->maxThreads; + tile->codec->imageSizeLimit = decoder->imageSizeLimit; + if (!tile->codec->getNextImage(tile->codec, sample, avifIsAlpha(tile->input->itemCategory), &isLimitedRangeAlpha, tile->image)) { avifDiagnosticsPrintf(&decoder->diag, "tile->codec->getNextImage() failed"); return avifGetErrorForItemCategory(tile->input->itemCategory); } diff --git a/src/write.c b/src/write.c index b53a7258fa..028f52d52d 100644 --- a/src/write.c +++ b/src/write.c @@ -1331,17 +1331,13 @@ static avifResult avifEncoderDecodeSatoBaseImage(avifEncoder * encoder, } AVIF_ASSERT_OR_RETURN(sample.data.size != 0); // There should be at least one base item. - // avifCodecGetNextImageFunc() uses only a few fields of its decoder argument. - avifDecoder decoder; - memset(&decoder, 0, sizeof(decoder)); - decoder.maxThreads = encoder->maxThreads; - decoder.imageSizeLimit = AVIF_DEFAULT_IMAGE_SIZE_LIMIT; - AVIF_CHECKRES(avifCodecCreate(AVIF_CODEC_CHOICE_AUTO, AVIF_CODEC_FLAG_CAN_DECODE, codec)); (*codec)->diag = &encoder->diag; + (*codec)->maxThreads = encoder->maxThreads; + (*codec)->imageSizeLimit = AVIF_DEFAULT_IMAGE_SIZE_LIMIT; AVIF_CHECKRES(avifImageCreateAllocate(decodedBaseImage, original, numBits, planes)); avifBool isLimitedRangeAlpha = AVIF_FALSE; // Ignored. - AVIF_CHECKERR((*codec)->getNextImage(*codec, &decoder, &sample, planes == AVIF_PLANES_A, &isLimitedRangeAlpha, *decodedBaseImage), + AVIF_CHECKERR((*codec)->getNextImage(*codec, &sample, planes == AVIF_PLANES_A, &isLimitedRangeAlpha, *decodedBaseImage), AVIF_RESULT_ENCODE_SAMPLE_TRANSFORM_FAILED); return AVIF_RESULT_OK; }