Merge avifCodec's open call with its getNextImage call to avoid codec init during parse, and simplify the codec API Fixes: #636
diff --git a/include/avif/internal.h b/include/avif/internal.h index 804f395..5e4c217 100644 --- a/include/avif/internal.h +++ b/include/avif/internal.h
@@ -218,8 +218,11 @@ struct avifCodec; struct avifCodecInternal; -typedef avifBool (*avifCodecOpenFunc)(struct avifCodec * codec, avifDecoder * decoder); // decode only -typedef avifBool (*avifCodecGetNextImageFunc)(struct avifCodec * codec, const avifDecodeSample * sample, avifBool alpha, avifImage * image); +typedef avifBool (*avifCodecGetNextImageFunc)(struct avifDecoder * decoder, + struct avifCodec * codec, + const avifDecodeSample * sample, + avifBool alpha, + avifImage * image); // EncodeImage and EncodeFinish are not required to always emit a sample, but when all images are // encoded and EncodeFinish is called, the number of samples emitted must match the number of submitted frames. // avifCodecEncodeImageFunc may return AVIF_RESULT_UNKNOWN_ERROR to automatically emit the appropriate @@ -242,7 +245,6 @@ // avifDiagnostics * diag; // Shallow copy; owned by avifEncoder or avifDecoder - avifCodecOpenFunc open; avifCodecGetNextImageFunc getNextImage; avifCodecEncodeImageFunc encodeImage; avifCodecEncodeFinishFunc encodeFinish;
diff --git a/src/codec_aom.c b/src/codec_aom.c index 7d5caf0..4d45a0c 100644 --- a/src/codec_aom.c +++ b/src/codec_aom.c
@@ -83,32 +83,35 @@ } #if defined(AVIF_CODEC_AOM_DECODE) -static avifBool aomCodecOpen(struct avifCodec * codec, avifDecoder * decoder) + +static avifBool aomCodecGetNextImage(struct avifDecoder * decoder, + struct avifCodec * codec, + const avifDecodeSample * sample, + avifBool alpha, + avifImage * image) { - aom_codec_dec_cfg_t cfg; - memset(&cfg, 0, sizeof(aom_codec_dec_cfg_t)); - cfg.threads = decoder->maxThreads; - cfg.allow_lowbitdepth = 1; + if (!codec->internal->decoderInitialized) { + aom_codec_dec_cfg_t cfg; + memset(&cfg, 0, sizeof(aom_codec_dec_cfg_t)); + cfg.threads = decoder->maxThreads; + cfg.allow_lowbitdepth = 1; - aom_codec_iface_t * decoder_interface = aom_codec_av1_dx(); - if (aom_codec_dec_init(&codec->internal->decoder, decoder_interface, &cfg, 0)) { - return AVIF_FALSE; - } - codec->internal->decoderInitialized = AVIF_TRUE; + aom_codec_iface_t * decoder_interface = aom_codec_av1_dx(); + if (aom_codec_dec_init(&codec->internal->decoder, decoder_interface, &cfg, 0)) { + return AVIF_FALSE; + } + codec->internal->decoderInitialized = AVIF_TRUE; - // Ensure that we only get the "highest spatial layer" as a single frame - // for each input sample, instead of getting each spatial layer as its own - // frame one at a time ("all layers"). - if (aom_codec_control(&codec->internal->decoder, AV1D_SET_OUTPUT_ALL_LAYERS, 0)) { - return AVIF_FALSE; + // Ensure that we only get the "highest spatial layer" as a single frame + // for each input sample, instead of getting each spatial layer as its own + // frame one at a time ("all layers"). + if (aom_codec_control(&codec->internal->decoder, AV1D_SET_OUTPUT_ALL_LAYERS, 0)) { + return AVIF_FALSE; + } + + codec->internal->iter = NULL; } - codec->internal->iter = NULL; - return AVIF_TRUE; -} - -static avifBool aomCodecGetNextImage(struct avifCodec * codec, const avifDecodeSample * sample, avifBool alpha, avifImage * image) -{ aom_image_t * nextFrame = NULL; for (;;) { nextFrame = aom_codec_get_frame(&codec->internal->decoder, &codec->internal->iter); @@ -854,7 +857,6 @@ memset(codec, 0, sizeof(struct avifCodec)); #if defined(AVIF_CODEC_AOM_DECODE) - codec->open = aomCodecOpen; codec->getNextImage = aomCodecGetNextImage; #endif
diff --git a/src/codec_dav1d.c b/src/codec_dav1d.c index 054f846..cc2f8e8 100644 --- a/src/codec_dav1d.c +++ b/src/codec_dav1d.c
@@ -49,7 +49,11 @@ avifFree(codec->internal); } -static avifBool dav1dCodecOpen(avifCodec * codec, avifDecoder * decoder) +static avifBool dav1dCodecGetNextImage(struct avifDecoder * decoder, + struct avifCodec * codec, + const avifDecodeSample * sample, + avifBool alpha, + avifImage * image) { if (codec->internal->dav1dContext == NULL) { // Give all available threads to decode a single frame as fast as possible @@ -60,11 +64,7 @@ return AVIF_FALSE; } } - return AVIF_TRUE; -} -static avifBool dav1dCodecGetNextImage(struct avifCodec * codec, const avifDecodeSample * sample, avifBool alpha, avifImage * image) -{ avifBool gotPicture = AVIF_FALSE; Dav1dPicture nextFrame; memset(&nextFrame, 0, sizeof(Dav1dPicture)); @@ -201,7 +201,6 @@ { avifCodec * codec = (avifCodec *)avifAlloc(sizeof(avifCodec)); memset(codec, 0, sizeof(struct avifCodec)); - codec->open = dav1dCodecOpen; codec->getNextImage = dav1dCodecGetNextImage; codec->destroyInternal = dav1dCodecDestroyInternal;
diff --git a/src/codec_libgav1.c b/src/codec_libgav1.c index 5b21c9c..1c88772 100644 --- a/src/codec_libgav1.c +++ b/src/codec_libgav1.c
@@ -23,7 +23,11 @@ avifFree(codec->internal); } -static avifBool gav1CodecOpen(avifCodec * codec, avifDecoder * decoder) +static avifBool gav1CodecGetNextImage(struct avifDecoder * decoder, + struct avifCodec * codec, + const avifDecodeSample * sample, + avifBool alpha, + avifImage * image) { if (codec->internal->gav1Decoder == NULL) { codec->internal->gav1Settings.threads = decoder->maxThreads; @@ -32,11 +36,7 @@ return AVIF_FALSE; } } - return AVIF_TRUE; -} -static avifBool gav1CodecGetNextImage(struct avifCodec * codec, const avifDecodeSample * sample, avifBool alpha, avifImage * image) -{ if (Libgav1DecoderEnqueueFrame(codec->internal->gav1Decoder, sample->data.data, sample->data.size, @@ -150,7 +150,6 @@ { avifCodec * codec = (avifCodec *)avifAlloc(sizeof(avifCodec)); memset(codec, 0, sizeof(struct avifCodec)); - codec->open = gav1CodecOpen; codec->getNextImage = gav1CodecGetNextImage; codec->destroyInternal = gav1CodecDestroyInternal;
diff --git a/src/read.c b/src/read.c index bea0150..6d186e1 100644 --- a/src/read.c +++ b/src/read.c
@@ -2745,9 +2745,6 @@ return AVIF_RESULT_NO_CODEC_AVAILABLE; } tile->codec->diag = &decoder->diag; - if (!tile->codec->open(tile->codec, decoder)) { - return AVIF_RESULT_DECODE_COLOR_FAILED; - } } return AVIF_RESULT_OK; } @@ -3234,7 +3231,7 @@ const avifDecodeSample * sample = &tile->input->samples.sample[nextImageIndex]; - if (!tile->codec->getNextImage(tile->codec, sample, tile->input->alpha, tile->image)) { + if (!tile->codec->getNextImage(decoder, tile->codec, sample, tile->input->alpha, tile->image)) { return tile->input->alpha ? AVIF_RESULT_DECODE_ALPHA_FAILED : AVIF_RESULT_DECODE_COLOR_FAILED; } }