Skip to content

Commit 9a6758c

Browse files
Correctly update encoder settings, clear csOptions after avifEncoderAddImage()
1 parent 98a453f commit 9a6758c

3 files changed

Lines changed: 31 additions & 44 deletions

File tree

include/avif/avif.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,6 +1130,7 @@ AVIF_API avifResult avifEncoderFinish(avifEncoder * encoder, avifRWData * output
11301130

11311131
// Codec-specific, optional "advanced" tuning settings, in the form of string key/value pairs.
11321132
// key must be non-NULL, but passing a NULL value will delete that key, if it exists.
1133+
// Settings will be sent to codec once at the next avifEncoderAddImage() call.
11331134
// Setting an incorrect or unknown option for the current codec will cause errors of type
11341135
// AVIF_RESULT_INVALID_CODEC_SPECIFIC_OPTION from avifEncoderWrite() or avifEncoderAddImage().
11351136
AVIF_API void avifEncoderSetCodecSpecificOption(avifEncoder * encoder, const char * key, const char * value);

src/codec_aom.c

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,7 @@ static avifBool avifProcessAOMOptionsPostInit(avifCodec * codec, avifBool alpha)
518518
}
519519
#endif // defined(HAVE_AOM_CODEC_SET_OPTION)
520520
}
521+
codec->csOptions->count = 0;
521522
return AVIF_TRUE;
522523
}
523524

@@ -606,26 +607,30 @@ static avifResult aomCodecEncodeImage(avifCodec * codec,
606607
avifDiagnosticsPrintf(codec->diag, "aom_codec_enc_config_default() failed: %s", aom_codec_err_to_string(err));
607608
return AVIF_RESULT_UNKNOWN_ERROR;
608609
}
610+
} else {
611+
cfg->g_usage = aomUsage;
609612
}
610613

611-
// Set our own default cfg->rc_end_usage value, which may differ from libaom's default.
612-
switch (aomUsage) {
613-
case AOM_USAGE_GOOD_QUALITY:
614-
// libaom's default is AOM_VBR. Change the default to AOM_Q since we don't need to
615-
// hit a certain target bit rate. It's easier to control the worst quality in Q
616-
// mode.
617-
cfg->rc_end_usage = AOM_Q;
618-
break;
619-
case AOM_USAGE_REALTIME:
620-
// For real-time mode we need to use CBR rate control mode. AOM_Q doesn't fit the
621-
// rate control requirements for real-time mode. CBR does.
622-
cfg->rc_end_usage = AOM_CBR;
623-
break;
614+
if (!codec->internal->endUsageSet) {
615+
// Set our own default cfg->rc_end_usage value, which may differ from libaom's default.
616+
switch (aomUsage) {
617+
case AOM_USAGE_GOOD_QUALITY:
618+
// libaom's default is AOM_VBR. Change the default to AOM_Q since we don't need to
619+
// hit a certain target bit rate. It's easier to control the worst quality in Q
620+
// mode.
621+
cfg->rc_end_usage = AOM_Q;
622+
break;
623+
case AOM_USAGE_REALTIME:
624+
// For real-time mode we need to use CBR rate control mode. AOM_Q doesn't fit the
625+
// rate control requirements for real-time mode. CBR does.
626+
cfg->rc_end_usage = AOM_CBR;
627+
break;
624628
#if defined(AOM_USAGE_ALL_INTRA)
625-
case AOM_USAGE_ALL_INTRA:
626-
cfg->rc_end_usage = AOM_Q;
627-
break;
629+
case AOM_USAGE_ALL_INTRA:
630+
cfg->rc_end_usage = AOM_Q;
631+
break;
628632
#endif
633+
}
629634
}
630635

631636
// Profile 0. 8-bit and 10-bit 4:2:0 and 4:0:0 only.
@@ -744,20 +749,12 @@ static avifResult aomCodecEncodeImage(avifCodec * codec,
744749
}
745750
}
746751

747-
if (lossless) {
748-
aom_codec_control(&codec->internal->encoder, AV1E_SET_LOSSLESS, 1);
749-
}
750-
if (encoder->maxThreads > 1) {
751-
aom_codec_control(&codec->internal->encoder, AV1E_SET_ROW_MT, 1);
752-
}
753-
if (encoder->tileRowsLog2 != 0) {
754-
int tileRowsLog2 = AVIF_CLAMP(encoder->tileRowsLog2, 0, 6);
755-
aom_codec_control(&codec->internal->encoder, AV1E_SET_TILE_ROWS, tileRowsLog2);
756-
}
757-
if (encoder->tileColsLog2 != 0) {
758-
int tileColsLog2 = AVIF_CLAMP(encoder->tileColsLog2, 0, 6);
759-
aom_codec_control(&codec->internal->encoder, AV1E_SET_TILE_COLUMNS, tileColsLog2);
760-
}
752+
aom_codec_control(&codec->internal->encoder, AV1E_SET_LOSSLESS, lossless);
753+
aom_codec_control(&codec->internal->encoder, AV1E_SET_ROW_MT, encoder->maxThreads > 1);
754+
int tileRowsLog2 = AVIF_CLAMP(encoder->tileRowsLog2, 0, 6);
755+
aom_codec_control(&codec->internal->encoder, AV1E_SET_TILE_ROWS, tileRowsLog2);
756+
int tileColsLog2 = AVIF_CLAMP(encoder->tileColsLog2, 0, 6);
757+
aom_codec_control(&codec->internal->encoder, AV1E_SET_TILE_COLUMNS, tileColsLog2);
761758
if (aomCpuUsed != -1) {
762759
if (aom_codec_control(&codec->internal->encoder, AOME_SET_CPUUSED, aomCpuUsed) != AOM_CODEC_OK) {
763760
return AVIF_RESULT_UNKNOWN_ERROR;

src/write.c

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,6 @@ typedef struct avifEncoderData
128128
uint16_t primaryItemID;
129129
avifBool singleImage; // if true, the AVIF_ADD_IMAGE_FLAG_SINGLE flag was set on the first call to avifEncoderAddImage()
130130
avifBool alphaPresent;
131-
avifBool csOptionsUpdated;
132131
} avifEncoderData;
133132

134133
static void avifEncoderDataDestroy(avifEncoderData * data);
@@ -319,7 +318,6 @@ void avifEncoderDestroy(avifEncoder * encoder)
319318
void avifEncoderSetCodecSpecificOption(avifEncoder * encoder, const char * key, const char * value)
320319
{
321320
avifCodecSpecificOptionsSet(encoder->csOptions, key, value);
322-
encoder->data->csOptionsUpdated = AVIF_TRUE; // False positive is possible but not important.
323321
}
324322

325323
static void avifBackupSettings(avifEncoder * encoder)
@@ -339,7 +337,6 @@ static void avifBackupSettings(avifEncoder * encoder)
339337
lastEncoder->tileRowsLog2 = encoder->tileRowsLog2;
340338
lastEncoder->tileColsLog2 = encoder->tileColsLog2;
341339
lastEncoder->speed = encoder->speed;
342-
encoder->data->csOptionsUpdated = AVIF_FALSE;
343340
}
344341

345342
// This function detect changes made on avifEncoder.
@@ -362,7 +359,7 @@ static avifBool avifEncoderSettingsChanged(const avifEncoder * encoder, avifBool
362359
(lastEncoder->maxQuantizer != encoder->maxQuantizer) || (lastEncoder->minQuantizerAlpha != encoder->minQuantizerAlpha) ||
363360
(lastEncoder->maxQuantizerAlpha != encoder->maxQuantizerAlpha) || (lastEncoder->tileRowsLog2 != encoder->tileRowsLog2) ||
364361
(lastEncoder->tileColsLog2 != encoder->tileColsLog2) || (lastEncoder->speed != encoder->speed) ||
365-
(encoder->data->csOptionsUpdated)) {
362+
(encoder->csOptions->count > 0)) {
366363
*needUpdate = AVIF_TRUE;
367364
}
368365

@@ -863,19 +860,11 @@ static avifResult avifEncoderAddImageInternal(avifEncoder * encoder,
863860
// Another frame in an image sequence
864861

865862
const avifImage * imageMetadata = encoder->data->imageMetadata;
866-
// HEIF (ISO 23008-12:2017), Section 6.6.2.3.1:
867-
// All input images shall have exactly the same width and height; call those tile_width and tile_height.
868-
// MIAF (ISO 23000-22:2019), Section 7.3.11.4.1:
869-
// All input images of a grid image item shall use the same coding format, chroma sampling format, and the
870-
// same decoder configuration (see 7.3.6.2).
871-
// If the first image in the sequence had an alpha plane (even if fully opaque), all
872-
// subsequence images must have alpha as well.
873-
if ((imageMetadata->width != firstCell->width) || (imageMetadata->height != firstCell->height) ||
874-
(imageMetadata->depth != firstCell->depth) || (imageMetadata->yuvFormat != firstCell->yuvFormat) ||
863+
// If the first image had an alpha plane (even if fully opaque), all subsequent images must have alpha as well.
864+
if ((imageMetadata->depth != firstCell->depth) || (imageMetadata->yuvFormat != firstCell->yuvFormat) ||
875865
(imageMetadata->yuvRange != firstCell->yuvRange) || (imageMetadata->colorPrimaries != firstCell->colorPrimaries) ||
876866
(imageMetadata->transferCharacteristics != firstCell->transferCharacteristics) ||
877867
(imageMetadata->matrixCoefficients != firstCell->matrixCoefficients) ||
878-
(!!imageMetadata->alphaPlane != !!firstCell->alphaPlane) ||
879868
(imageMetadata->alphaPremultiplied != firstCell->alphaPremultiplied) ||
880869
(encoder->data->alphaPresent && !firstCell->alphaPlane)) {
881870
return AVIF_RESULT_INCOMPATIBLE_IMAGE;

0 commit comments

Comments
 (0)