@@ -532,10 +532,7 @@ static avifResult aomCodecEncodeImage(avifCodec * codec,
532532 avifCodecEncodeOutput * output )
533533{
534534 struct aom_codec_enc_cfg * cfg = & codec -> internal -> cfg ;
535- aom_codec_iface_t * encoderInterface = NULL ;
536- unsigned int aomUsage = AOM_USAGE_GOOD_QUALITY ;
537- int aomCpuUsed = -1 ;
538- avifBool lossless = AVIF_FALSE ;
535+ avifBool quantizerUpdated = AVIF_FALSE ;
539536
540537 if (!codec -> internal -> encoderInitialized ) {
541538 // Map encoder speed to AOM usage + CpuUsed:
@@ -550,13 +547,15 @@ static avifResult aomCodecEncodeImage(avifCodec * codec,
550547 // Speed 8: RealTime CpuUsed 8
551548 // Speed 9: RealTime CpuUsed 9
552549 // Speed 10: RealTime CpuUsed 9
550+ unsigned int aomUsage = AOM_USAGE_GOOD_QUALITY ;
553551 // Use the new AOM_USAGE_ALL_INTRA (added in https://crbug.com/aomedia/2959) for still
554552 // image encoding if it is available.
555553#if defined(AOM_USAGE_ALL_INTRA )
556554 if (addImageFlags & AVIF_ADD_IMAGE_FLAG_SINGLE ) {
557555 aomUsage = AOM_USAGE_ALL_INTRA ;
558556 }
559557#endif
558+ int aomCpuUsed = -1 ;
560559 if (encoder -> speed != AVIF_SPEED_DEFAULT ) {
561560 aomCpuUsed = AVIF_CLAMP (encoder -> speed , 0 , 9 );
562561 if (aomCpuUsed >= 7 ) {
@@ -600,7 +599,7 @@ static avifResult aomCodecEncodeImage(avifCodec * codec,
600599
601600 avifGetPixelFormatInfo (image -> yuvFormat , & codec -> internal -> formatInfo );
602601
603- encoderInterface = aom_codec_av1_cx ();
602+ aom_codec_iface_t * encoderInterface = aom_codec_av1_cx ();
604603 aom_codec_err_t err = aom_codec_enc_config_default (encoderInterface , cfg , aomUsage );
605604 if (err != AOM_CODEC_OK ) {
606605 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,
665664 cfg -> g_profile = seqProfile ;
666665 cfg -> g_bit_depth = image -> depth ;
667666 cfg -> g_input_bit_depth = image -> depth ;
668-
667+ cfg -> g_w = image -> width ;
668+ cfg -> g_h = image -> height ;
669669 if (addImageFlags & AVIF_ADD_IMAGE_FLAG_SINGLE ) {
670670 // Set the maximum number of frames to encode to 1. This instructs
671671 // libaom to set still_picture and reduced_still_picture_header to
@@ -688,6 +688,15 @@ static avifResult aomCodecEncodeImage(avifCodec * codec,
688688 cfg -> g_threads = encoder -> maxThreads ;
689689 }
690690
691+ if (alpha ) {
692+ cfg -> rc_min_quantizer = AVIF_CLAMP (encoder -> minQuantizerAlpha , 0 , 63 );
693+ cfg -> rc_max_quantizer = AVIF_CLAMP (encoder -> maxQuantizerAlpha , 0 , 63 );
694+ } else {
695+ cfg -> rc_min_quantizer = AVIF_CLAMP (encoder -> minQuantizer , 0 , 63 );
696+ cfg -> rc_max_quantizer = AVIF_CLAMP (encoder -> maxQuantizer , 0 , 63 );
697+ }
698+ quantizerUpdated = AVIF_TRUE ;
699+
691700 codec -> internal -> monochromeEnabled = AVIF_FALSE ;
692701 if (aomVersion > aomVersion_2_0_0 ) {
693702 // There exists a bug in libaom's chroma_check() function where it will attempt to
@@ -703,103 +712,84 @@ static avifResult aomCodecEncodeImage(avifCodec * codec,
703712 cfg -> monochrome = 1 ;
704713 }
705714 }
706- }
707-
708- avifBool dimensionsChanged = AVIF_FALSE ;
709- if (!codec -> internal -> encoderInitialized ) {
710- cfg -> g_w = image -> width ;
711- cfg -> g_h = image -> height ;
712- } else if ((cfg -> g_w != image -> width ) || (cfg -> g_h != image -> height )) {
713- // We are not ready for dimension change for now.
714- return AVIF_RESULT_NOT_IMPLEMENTED ;
715- }
716715
717- if (!codec -> internal -> encoderInitialized || encoderChanges ) {
718- int minQuantizer = AVIF_CLAMP (encoder -> minQuantizer , 0 , 63 );
719- int maxQuantizer = AVIF_CLAMP (encoder -> maxQuantizer , 0 , 63 );
720- if (alpha ) {
721- minQuantizer = AVIF_CLAMP (encoder -> minQuantizerAlpha , 0 , 63 );
722- maxQuantizer = AVIF_CLAMP (encoder -> maxQuantizerAlpha , 0 , 63 );
716+ if (!avifProcessAOMOptionsPreInit (codec , alpha , cfg )) {
717+ return AVIF_RESULT_INVALID_CODEC_SPECIFIC_OPTION ;
723718 }
724- lossless = ((minQuantizer == AVIF_QUANTIZER_LOSSLESS ) && (maxQuantizer == AVIF_QUANTIZER_LOSSLESS ));
725- cfg -> rc_min_quantizer = minQuantizer ;
726- cfg -> rc_max_quantizer = maxQuantizer ;
727- }
728719
729- if (!codec -> internal -> encoderInitialized ) {
730720 aom_codec_flags_t encoderFlags = 0 ;
731721 if (image -> depth > 8 ) {
732722 encoderFlags |= AOM_CODEC_USE_HIGHBITDEPTH ;
733723 }
734-
735- if (!avifProcessAOMOptionsPreInit (codec , alpha , cfg )) {
736- return AVIF_RESULT_INVALID_CODEC_SPECIFIC_OPTION ;
737- }
738-
739724 if (aom_codec_enc_init (& codec -> internal -> encoder , encoderInterface , cfg , encoderFlags ) != AOM_CODEC_OK ) {
740725 avifDiagnosticsPrintf (codec -> diag ,
741726 "aom_codec_enc_init() failed: %s: %s" ,
742727 aom_codec_error (& codec -> internal -> encoder ),
743728 aom_codec_error_detail (& codec -> internal -> encoder ));
744729 return AVIF_RESULT_UNKNOWN_ERROR ;
745730 }
731+ codec -> internal -> encoderInitialized = AVIF_TRUE ;
746732
733+ avifBool lossless = ((cfg -> rc_min_quantizer == AVIF_QUANTIZER_LOSSLESS ) && (cfg -> rc_max_quantizer == AVIF_QUANTIZER_LOSSLESS ));
734+ if (lossless ) {
735+ aom_codec_control (& codec -> internal -> encoder , AV1E_SET_LOSSLESS , 1 );
736+ }
747737 if (encoder -> maxThreads > 1 ) {
748738 aom_codec_control (& codec -> internal -> encoder , AV1E_SET_ROW_MT , 1 );
749739 }
740+ if (encoder -> tileRowsLog2 != 0 ) {
741+ int tileRowsLog2 = AVIF_CLAMP (encoder -> tileRowsLog2 , 0 , 6 );
742+ aom_codec_control (& codec -> internal -> encoder , AV1E_SET_TILE_ROWS , tileRowsLog2 );
743+ }
744+ if (encoder -> tileColsLog2 != 0 ) {
745+ int tileColsLog2 = AVIF_CLAMP (encoder -> tileColsLog2 , 0 , 6 );
746+ aom_codec_control (& codec -> internal -> encoder , AV1E_SET_TILE_COLUMNS , tileColsLog2 );
747+ }
750748 if (aomCpuUsed != -1 ) {
751749 if (aom_codec_control (& codec -> internal -> encoder , AOME_SET_CPUUSED , aomCpuUsed ) != AOM_CODEC_OK ) {
752750 return AVIF_RESULT_UNKNOWN_ERROR ;
753751 }
754752 }
755- } else if ((encoderChanges & ~AVIF_ENCODER_CHANGE_CODEC_SPECIFIC ) || dimensionsChanged ) {
756- // Codec specific options does not change cfg, so no need to update it.
757- aom_codec_err_t err = aom_codec_enc_config_set (& codec -> internal -> encoder , cfg );
758- if (err != AOM_CODEC_OK ) {
759- avifDiagnosticsPrintf (codec -> diag ,
760- "aom_codec_enc_config_set() failed: %s: %s" ,
761- aom_codec_error (& codec -> internal -> encoder ),
762- aom_codec_error_detail (& codec -> internal -> encoder ));
763- return AVIF_RESULT_UNKNOWN_ERROR ;
764- }
765- }
766-
767- if (!codec -> internal -> encoderInitialized || (encoderChanges & AVIF_ENCODER_CHANGE_CODEC_SPECIFIC )) {
768753 if (!avifProcessAOMOptionsPostInit (codec , alpha )) {
769754 return AVIF_RESULT_INVALID_CODEC_SPECIFIC_OPTION ;
770755 }
771- }
772-
773- avifBool quantizerUpdated = AVIF_FALSE ;
774- if (!codec -> internal -> encoderInitialized ) {
775- quantizerUpdated = AVIF_TRUE ;
776- if (lossless ) {
777- aom_codec_control (& codec -> internal -> encoder , AV1E_SET_LOSSLESS , lossless );
778- }
779- int tileRowsLog2 = AVIF_CLAMP (encoder -> tileRowsLog2 , 0 , 6 );
780- if (tileRowsLog2 > 0 ) {
781- aom_codec_control (& codec -> internal -> encoder , AV1E_SET_TILE_ROWS , tileRowsLog2 );
782- }
783- int tileColsLog2 = AVIF_CLAMP (encoder -> tileColsLog2 , 0 , 6 );
784- if (tileColsLog2 > 0 ) {
785- aom_codec_control (& codec -> internal -> encoder , AV1E_SET_TILE_COLUMNS , tileColsLog2 );
786- }
787756 if (!codec -> internal -> tuningSet ) {
788757 if (aom_codec_control (& codec -> internal -> encoder , AOME_SET_TUNING , AOM_TUNE_SSIM ) != AOM_CODEC_OK ) {
789758 return AVIF_RESULT_UNKNOWN_ERROR ;
790759 }
791760 }
792- codec -> internal -> encoderInitialized = AVIF_TRUE ;
793- } else if (encoderChanges ) {
761+ } else {
762+ avifBool dimensionsChanged = AVIF_FALSE ;
763+ if ((cfg -> g_w != image -> width ) || (cfg -> g_h != image -> height )) {
764+ // We are not ready for dimension change for now.
765+ return AVIF_RESULT_NOT_IMPLEMENTED ;
766+ }
794767 if (alpha ) {
795768 if (encoderChanges & (AVIF_ENCODER_CHANGE_MIN_QUANTIZER_ALPHA | AVIF_ENCODER_CHANGE_MAX_QUANTIZER_ALPHA )) {
769+ cfg -> rc_min_quantizer = AVIF_CLAMP (encoder -> minQuantizerAlpha , 0 , 63 );
770+ cfg -> rc_max_quantizer = AVIF_CLAMP (encoder -> maxQuantizerAlpha , 0 , 63 );
796771 quantizerUpdated = AVIF_TRUE ;
797- aom_codec_control (& codec -> internal -> encoder , AV1E_SET_LOSSLESS , lossless );
798772 }
799773 } else {
800774 if (encoderChanges & (AVIF_ENCODER_CHANGE_MIN_QUANTIZER | AVIF_ENCODER_CHANGE_MAX_QUANTIZER )) {
775+ cfg -> rc_min_quantizer = AVIF_CLAMP (encoder -> minQuantizer , 0 , 63 );
776+ cfg -> rc_max_quantizer = AVIF_CLAMP (encoder -> maxQuantizer , 0 , 63 );
801777 quantizerUpdated = AVIF_TRUE ;
802- aom_codec_control (& codec -> internal -> encoder , AV1E_SET_LOSSLESS , lossless );
778+ }
779+ }
780+ if (quantizerUpdated ) {
781+ avifBool lossless =
782+ ((cfg -> rc_min_quantizer == AVIF_QUANTIZER_LOSSLESS ) && (cfg -> rc_max_quantizer == AVIF_QUANTIZER_LOSSLESS ));
783+ aom_codec_control (& codec -> internal -> encoder , AV1E_SET_LOSSLESS , lossless );
784+ }
785+ if (quantizerUpdated || dimensionsChanged ) {
786+ aom_codec_err_t err = aom_codec_enc_config_set (& codec -> internal -> encoder , cfg );
787+ if (err != AOM_CODEC_OK ) {
788+ avifDiagnosticsPrintf (codec -> diag ,
789+ "aom_codec_enc_config_set() failed: %s: %s" ,
790+ aom_codec_error (& codec -> internal -> encoder ),
791+ aom_codec_error_detail (& codec -> internal -> encoder ));
792+ return AVIF_RESULT_UNKNOWN_ERROR ;
803793 }
804794 }
805795 if (encoderChanges & AVIF_ENCODER_CHANGE_TILE_ROWS_LOG2 ) {
@@ -808,10 +798,15 @@ static avifResult aomCodecEncodeImage(avifCodec * codec,
808798 if (encoderChanges & AVIF_ENCODER_CHANGE_TILE_COLS_LOG2 ) {
809799 aom_codec_control (& codec -> internal -> encoder , AV1E_SET_TILE_COLUMNS , AVIF_CLAMP (encoder -> tileColsLog2 , 0 , 6 ));
810800 }
801+ if (encoderChanges & AVIF_ENCODER_CHANGE_CODEC_SPECIFIC ) {
802+ if (!avifProcessAOMOptionsPostInit (codec , alpha )) {
803+ return AVIF_RESULT_INVALID_CODEC_SPECIFIC_OPTION ;
804+ }
805+ }
811806 }
812807
813808#if defined(AOM_USAGE_ALL_INTRA )
814- if (aomUsage == AOM_USAGE_ALL_INTRA && !codec -> internal -> endUsageSet && !codec -> internal -> cqLevelSet && quantizerUpdated ) {
809+ if (quantizerUpdated && cfg -> g_usage == AOM_USAGE_ALL_INTRA && !codec -> internal -> endUsageSet && !codec -> internal -> cqLevelSet ) {
815810 // The default rc_end_usage in all intra mode is AOM_Q, which requires cq-level to
816811 // function. A libavif user may not know this internal detail and therefore may only
817812 // set the min and max quantizers in the avifEncoder struct. If this is the case, set
0 commit comments