-
Notifications
You must be signed in to change notification settings - Fork 254
Clean up encoder settings update during encoding #1070
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -262,14 +262,14 @@ struct avifCodecInternal; | |
|
|
||
| typedef enum avifEncoderChange | ||
| { | ||
| AVIF_ENCODER_CHANGE_MIN_QUANTIZER = (1 << 0), | ||
| AVIF_ENCODER_CHANGE_MAX_QUANTIZER = (1 << 1), | ||
| AVIF_ENCODER_CHANGE_MIN_QUANTIZER_ALPHA = (1 << 2), | ||
| AVIF_ENCODER_CHANGE_MAX_QUANTIZER_ALPHA = (1 << 3), | ||
| AVIF_ENCODER_CHANGE_TILE_ROWS_LOG2 = (1 << 4), | ||
| AVIF_ENCODER_CHANGE_TILE_COLS_LOG2 = (1 << 5), | ||
|
|
||
| AVIF_ENCODER_CHANGE_CODEC_SPECIFIC = (1 << 31) | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Google's internal ClangTidy check warns that |
||
| AVIF_ENCODER_CHANGE_MIN_QUANTIZER = (1u << 0), | ||
| AVIF_ENCODER_CHANGE_MAX_QUANTIZER = (1u << 1), | ||
| AVIF_ENCODER_CHANGE_MIN_QUANTIZER_ALPHA = (1u << 2), | ||
| AVIF_ENCODER_CHANGE_MAX_QUANTIZER_ALPHA = (1u << 3), | ||
| AVIF_ENCODER_CHANGE_TILE_ROWS_LOG2 = (1u << 4), | ||
| AVIF_ENCODER_CHANGE_TILE_COLS_LOG2 = (1u << 5), | ||
|
|
||
| AVIF_ENCODER_CHANGE_CODEC_SPECIFIC = (1u << 31) | ||
| } avifEncoderChange; | ||
| typedef uint32_t avifEncoderChanges; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -532,10 +532,7 @@ static avifResult aomCodecEncodeImage(avifCodec * codec, | |
| avifCodecEncodeOutput * output) | ||
| { | ||
| struct aom_codec_enc_cfg * cfg = &codec->internal->cfg; | ||
| aom_codec_iface_t * encoderInterface = NULL; | ||
| unsigned int aomUsage = AOM_USAGE_GOOD_QUALITY; | ||
| int aomCpuUsed = -1; | ||
| avifBool lossless = AVIF_FALSE; | ||
| avifBool quantizerUpdated = AVIF_FALSE; | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I restored this function to its original structure. There is only one |
||
|
|
||
| if (!codec->internal->encoderInitialized) { | ||
| // Map encoder speed to AOM usage + CpuUsed: | ||
|
|
@@ -550,13 +547,15 @@ static avifResult aomCodecEncodeImage(avifCodec * codec, | |
| // Speed 8: RealTime CpuUsed 8 | ||
| // Speed 9: RealTime CpuUsed 9 | ||
| // Speed 10: RealTime CpuUsed 9 | ||
| unsigned int aomUsage = AOM_USAGE_GOOD_QUALITY; | ||
| // Use the new AOM_USAGE_ALL_INTRA (added in https://crbug.com/aomedia/2959) for still | ||
| // image encoding if it is available. | ||
| #if defined(AOM_USAGE_ALL_INTRA) | ||
| if (addImageFlags & AVIF_ADD_IMAGE_FLAG_SINGLE) { | ||
| aomUsage = AOM_USAGE_ALL_INTRA; | ||
| } | ||
| #endif | ||
| int aomCpuUsed = -1; | ||
| if (encoder->speed != AVIF_SPEED_DEFAULT) { | ||
| aomCpuUsed = AVIF_CLAMP(encoder->speed, 0, 9); | ||
| if (aomCpuUsed >= 7) { | ||
|
|
@@ -600,7 +599,7 @@ static avifResult aomCodecEncodeImage(avifCodec * codec, | |
|
|
||
| avifGetPixelFormatInfo(image->yuvFormat, &codec->internal->formatInfo); | ||
|
|
||
| encoderInterface = aom_codec_av1_cx(); | ||
| aom_codec_iface_t * encoderInterface = aom_codec_av1_cx(); | ||
| aom_codec_err_t err = aom_codec_enc_config_default(encoderInterface, cfg, aomUsage); | ||
| if (err != AOM_CODEC_OK) { | ||
| avifDiagnosticsPrintf(codec->diag, "aom_codec_enc_config_default() failed: %s", aom_codec_err_to_string(err)); | ||
|
|
@@ -665,7 +664,8 @@ static avifResult aomCodecEncodeImage(avifCodec * codec, | |
| cfg->g_profile = seqProfile; | ||
| cfg->g_bit_depth = image->depth; | ||
| cfg->g_input_bit_depth = image->depth; | ||
|
|
||
| cfg->g_w = image->width; | ||
| cfg->g_h = image->height; | ||
| if (addImageFlags & AVIF_ADD_IMAGE_FLAG_SINGLE) { | ||
| // Set the maximum number of frames to encode to 1. This instructs | ||
| // libaom to set still_picture and reduced_still_picture_header to | ||
|
|
@@ -688,6 +688,15 @@ static avifResult aomCodecEncodeImage(avifCodec * codec, | |
| cfg->g_threads = encoder->maxThreads; | ||
| } | ||
|
|
||
| if (alpha) { | ||
| cfg->rc_min_quantizer = AVIF_CLAMP(encoder->minQuantizerAlpha, 0, 63); | ||
| cfg->rc_max_quantizer = AVIF_CLAMP(encoder->maxQuantizerAlpha, 0, 63); | ||
| } else { | ||
| cfg->rc_min_quantizer = AVIF_CLAMP(encoder->minQuantizer, 0, 63); | ||
| cfg->rc_max_quantizer = AVIF_CLAMP(encoder->maxQuantizer, 0, 63); | ||
| } | ||
| quantizerUpdated = AVIF_TRUE; | ||
|
|
||
| codec->internal->monochromeEnabled = AVIF_FALSE; | ||
| if (aomVersion > aomVersion_2_0_0) { | ||
| // There exists a bug in libaom's chroma_check() function where it will attempt to | ||
|
|
@@ -703,103 +712,84 @@ static avifResult aomCodecEncodeImage(avifCodec * codec, | |
| cfg->monochrome = 1; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| avifBool dimensionsChanged = AVIF_FALSE; | ||
| if (!codec->internal->encoderInitialized) { | ||
| cfg->g_w = image->width; | ||
| cfg->g_h = image->height; | ||
| } else if ((cfg->g_w != image->width) || (cfg->g_h != image->height)) { | ||
| // We are not ready for dimension change for now. | ||
| return AVIF_RESULT_NOT_IMPLEMENTED; | ||
| } | ||
|
|
||
| if (!codec->internal->encoderInitialized || encoderChanges) { | ||
| int minQuantizer = AVIF_CLAMP(encoder->minQuantizer, 0, 63); | ||
| int maxQuantizer = AVIF_CLAMP(encoder->maxQuantizer, 0, 63); | ||
| if (alpha) { | ||
| minQuantizer = AVIF_CLAMP(encoder->minQuantizerAlpha, 0, 63); | ||
| maxQuantizer = AVIF_CLAMP(encoder->maxQuantizerAlpha, 0, 63); | ||
| if (!avifProcessAOMOptionsPreInit(codec, alpha, cfg)) { | ||
| return AVIF_RESULT_INVALID_CODEC_SPECIFIC_OPTION; | ||
| } | ||
| lossless = ((minQuantizer == AVIF_QUANTIZER_LOSSLESS) && (maxQuantizer == AVIF_QUANTIZER_LOSSLESS)); | ||
| cfg->rc_min_quantizer = minQuantizer; | ||
| cfg->rc_max_quantizer = maxQuantizer; | ||
| } | ||
|
|
||
| if (!codec->internal->encoderInitialized) { | ||
| aom_codec_flags_t encoderFlags = 0; | ||
| if (image->depth > 8) { | ||
| encoderFlags |= AOM_CODEC_USE_HIGHBITDEPTH; | ||
| } | ||
|
|
||
| if (!avifProcessAOMOptionsPreInit(codec, alpha, cfg)) { | ||
| return AVIF_RESULT_INVALID_CODEC_SPECIFIC_OPTION; | ||
| } | ||
|
|
||
| if (aom_codec_enc_init(&codec->internal->encoder, encoderInterface, cfg, encoderFlags) != AOM_CODEC_OK) { | ||
| avifDiagnosticsPrintf(codec->diag, | ||
| "aom_codec_enc_init() failed: %s: %s", | ||
| aom_codec_error(&codec->internal->encoder), | ||
| aom_codec_error_detail(&codec->internal->encoder)); | ||
| return AVIF_RESULT_UNKNOWN_ERROR; | ||
| } | ||
| codec->internal->encoderInitialized = AVIF_TRUE; | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that we must set Perhaps this should be documented better. |
||
|
|
||
| avifBool lossless = ((cfg->rc_min_quantizer == AVIF_QUANTIZER_LOSSLESS) && (cfg->rc_max_quantizer == AVIF_QUANTIZER_LOSSLESS)); | ||
| if (lossless) { | ||
| aom_codec_control(&codec->internal->encoder, AV1E_SET_LOSSLESS, 1); | ||
| } | ||
| if (encoder->maxThreads > 1) { | ||
| aom_codec_control(&codec->internal->encoder, AV1E_SET_ROW_MT, 1); | ||
| } | ||
| if (encoder->tileRowsLog2 != 0) { | ||
| int tileRowsLog2 = AVIF_CLAMP(encoder->tileRowsLog2, 0, 6); | ||
| aom_codec_control(&codec->internal->encoder, AV1E_SET_TILE_ROWS, tileRowsLog2); | ||
| } | ||
| if (encoder->tileColsLog2 != 0) { | ||
| int tileColsLog2 = AVIF_CLAMP(encoder->tileColsLog2, 0, 6); | ||
| aom_codec_control(&codec->internal->encoder, AV1E_SET_TILE_COLUMNS, tileColsLog2); | ||
| } | ||
| if (aomCpuUsed != -1) { | ||
| if (aom_codec_control(&codec->internal->encoder, AOME_SET_CPUUSED, aomCpuUsed) != AOM_CODEC_OK) { | ||
| return AVIF_RESULT_UNKNOWN_ERROR; | ||
| } | ||
| } | ||
| } else if ((encoderChanges & ~AVIF_ENCODER_CHANGE_CODEC_SPECIFIC) || dimensionsChanged) { | ||
| // Codec specific options does not change cfg, so no need to update it. | ||
| aom_codec_err_t err = aom_codec_enc_config_set(&codec->internal->encoder, cfg); | ||
| if (err != AOM_CODEC_OK) { | ||
| avifDiagnosticsPrintf(codec->diag, | ||
| "aom_codec_enc_config_set() failed: %s: %s", | ||
| aom_codec_error(&codec->internal->encoder), | ||
| aom_codec_error_detail(&codec->internal->encoder)); | ||
| return AVIF_RESULT_UNKNOWN_ERROR; | ||
| } | ||
| } | ||
|
|
||
| if (!codec->internal->encoderInitialized || (encoderChanges & AVIF_ENCODER_CHANGE_CODEC_SPECIFIC)) { | ||
| if (!avifProcessAOMOptionsPostInit(codec, alpha)) { | ||
| return AVIF_RESULT_INVALID_CODEC_SPECIFIC_OPTION; | ||
| } | ||
| } | ||
|
|
||
| avifBool quantizerUpdated = AVIF_FALSE; | ||
| if (!codec->internal->encoderInitialized) { | ||
| quantizerUpdated = AVIF_TRUE; | ||
| if (lossless) { | ||
| aom_codec_control(&codec->internal->encoder, AV1E_SET_LOSSLESS, lossless); | ||
| } | ||
| int tileRowsLog2 = AVIF_CLAMP(encoder->tileRowsLog2, 0, 6); | ||
| if (tileRowsLog2 > 0) { | ||
| aom_codec_control(&codec->internal->encoder, AV1E_SET_TILE_ROWS, tileRowsLog2); | ||
| } | ||
| int tileColsLog2 = AVIF_CLAMP(encoder->tileColsLog2, 0, 6); | ||
| if (tileColsLog2 > 0) { | ||
| aom_codec_control(&codec->internal->encoder, AV1E_SET_TILE_COLUMNS, tileColsLog2); | ||
| } | ||
| if (!codec->internal->tuningSet) { | ||
| if (aom_codec_control(&codec->internal->encoder, AOME_SET_TUNING, AOM_TUNE_SSIM) != AOM_CODEC_OK) { | ||
| return AVIF_RESULT_UNKNOWN_ERROR; | ||
| } | ||
| } | ||
| codec->internal->encoderInitialized = AVIF_TRUE; | ||
| } else if (encoderChanges) { | ||
| } else { | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This Please review this |
||
| avifBool dimensionsChanged = AVIF_FALSE; | ||
| if ((cfg->g_w != image->width) || (cfg->g_h != image->height)) { | ||
| // We are not ready for dimension change for now. | ||
| return AVIF_RESULT_NOT_IMPLEMENTED; | ||
| } | ||
| if (alpha) { | ||
| if (encoderChanges & (AVIF_ENCODER_CHANGE_MIN_QUANTIZER_ALPHA | AVIF_ENCODER_CHANGE_MAX_QUANTIZER_ALPHA)) { | ||
| cfg->rc_min_quantizer = AVIF_CLAMP(encoder->minQuantizerAlpha, 0, 63); | ||
| cfg->rc_max_quantizer = AVIF_CLAMP(encoder->maxQuantizerAlpha, 0, 63); | ||
| quantizerUpdated = AVIF_TRUE; | ||
| aom_codec_control(&codec->internal->encoder, AV1E_SET_LOSSLESS, lossless); | ||
| } | ||
| } else { | ||
| if (encoderChanges & (AVIF_ENCODER_CHANGE_MIN_QUANTIZER | AVIF_ENCODER_CHANGE_MAX_QUANTIZER)) { | ||
| cfg->rc_min_quantizer = AVIF_CLAMP(encoder->minQuantizer, 0, 63); | ||
| cfg->rc_max_quantizer = AVIF_CLAMP(encoder->maxQuantizer, 0, 63); | ||
| quantizerUpdated = AVIF_TRUE; | ||
| aom_codec_control(&codec->internal->encoder, AV1E_SET_LOSSLESS, lossless); | ||
| } | ||
| } | ||
| if (quantizerUpdated) { | ||
| avifBool lossless = | ||
| ((cfg->rc_min_quantizer == AVIF_QUANTIZER_LOSSLESS) && (cfg->rc_max_quantizer == AVIF_QUANTIZER_LOSSLESS)); | ||
| aom_codec_control(&codec->internal->encoder, AV1E_SET_LOSSLESS, lossless); | ||
| } | ||
| if (quantizerUpdated || dimensionsChanged) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For now using
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're right. The |
||
| aom_codec_err_t err = aom_codec_enc_config_set(&codec->internal->encoder, cfg); | ||
| if (err != AOM_CODEC_OK) { | ||
| avifDiagnosticsPrintf(codec->diag, | ||
| "aom_codec_enc_config_set() failed: %s: %s", | ||
| aom_codec_error(&codec->internal->encoder), | ||
| aom_codec_error_detail(&codec->internal->encoder)); | ||
| return AVIF_RESULT_UNKNOWN_ERROR; | ||
| } | ||
| } | ||
| if (encoderChanges & AVIF_ENCODER_CHANGE_TILE_ROWS_LOG2) { | ||
|
|
@@ -808,10 +798,15 @@ static avifResult aomCodecEncodeImage(avifCodec * codec, | |
| if (encoderChanges & AVIF_ENCODER_CHANGE_TILE_COLS_LOG2) { | ||
| aom_codec_control(&codec->internal->encoder, AV1E_SET_TILE_COLUMNS, AVIF_CLAMP(encoder->tileColsLog2, 0, 6)); | ||
| } | ||
| if (encoderChanges & AVIF_ENCODER_CHANGE_CODEC_SPECIFIC) { | ||
| if (!avifProcessAOMOptionsPostInit(codec, alpha)) { | ||
| return AVIF_RESULT_INVALID_CODEC_SPECIFIC_OPTION; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| #if defined(AOM_USAGE_ALL_INTRA) | ||
| if (aomUsage == AOM_USAGE_ALL_INTRA && !codec->internal->endUsageSet && !codec->internal->cqLevelSet && quantizerUpdated) { | ||
| if (quantizerUpdated && cfg->g_usage == AOM_USAGE_ALL_INTRA && !codec->internal->endUsageSet && !codec->internal->cqLevelSet) { | ||
| // The default rc_end_usage in all intra mode is AOM_Q, which requires cq-level to | ||
| // function. A libavif user may not know this internal detail and therefore may only | ||
| // set the min and max quantizers in the avifEncoder struct. If this is the case, set | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Commonly used members are listed before rarely used members.