avifEncoder now has a speed setting, codec_aom only flushes encoder when necessary (avoids lost frame packets), minor cleanup
diff --git a/src/codec_aom.c b/src/codec_aom.c
index fee504f..790f57f 100644
--- a/src/codec_aom.c
+++ b/src/codec_aom.c
@@ -234,6 +234,30 @@
aom_codec_iface_t * encoder_interface = aom_codec_av1_cx();
aom_codec_ctx_t aomEncoder;
+ // Map encoder speed to AOM usage + CpuUsed:
+ // Speed 0: GoodQuality CpuUsed 0
+ // Speed 1: GoodQuality CpuUsed 1
+ // Speed 2: GoodQuality CpuUsed 2
+ // Speed 3: GoodQuality CpuUsed 3
+ // Speed 4: GoodQuality CpuUsed 4
+ // Speed 5: GoodQuality CpuUsed 5
+ // Speed 6: RealTime CpuUsed 4
+ // Speed 7: RealTime CpuUsed 5
+ // Speed 8: RealTime CpuUsed 6
+ // Speed 9: RealTime CpuUsed 7
+ // Speed 10: RealTime CpuUsed 8
+ unsigned int aomUsage = AOM_USAGE_GOOD_QUALITY;
+ int aomCpuUsed = -1;
+ if (encoder->speed != AVIF_SPEED_DEFAULT) {
+ if (encoder->speed < 6) {
+ aomUsage = AOM_USAGE_GOOD_QUALITY;
+ aomCpuUsed = AVIF_CLAMP(encoder->speed, 0, 5);
+ } else {
+ aomUsage = AOM_USAGE_REALTIME;
+ aomCpuUsed = AVIF_CLAMP(encoder->speed - 2, 4, 8);
+ }
+ }
+
int yShift = 0;
aom_img_fmt_t aomFormat = avifImageCalcAOMFmt(image, alpha, &yShift);
if (aomFormat == AOM_IMG_FMT_NONE) {
@@ -244,7 +268,7 @@
avifGetPixelFormatInfo(image->yuvFormat, &formatInfo);
struct aom_codec_enc_cfg cfg;
- aom_codec_enc_config_default(encoder_interface, &cfg, 0);
+ aom_codec_enc_config_default(encoder_interface, &cfg, aomUsage);
cfg.g_profile = codec->configBox.seqProfile;
cfg.g_bit_depth = image->depth;
@@ -287,6 +311,9 @@
int tileColsLog2 = AVIF_CLAMP(encoder->tileColsLog2, 0, 6);
aom_codec_control(&aomEncoder, AV1E_SET_TILE_COLUMNS, tileColsLog2);
}
+ if (aomCpuUsed != -1) {
+ aom_codec_control(&aomEncoder, AOME_SET_CPUUSED, aomCpuUsed);
+ }
uint32_t uvHeight = image->height >> yShift;
aom_image_t * aomImage = aom_img_alloc(NULL, aomFormat, image->width, image->height, 16);
@@ -338,13 +365,19 @@
}
aom_codec_encode(&aomEncoder, aomImage, 0, 1, 0);
- aom_codec_encode(&aomEncoder, NULL, 0, 1, 0); // flush
+ avifBool flushed = AVIF_FALSE;
aom_codec_iter_t iter = NULL;
for (;;) {
const aom_codec_cx_pkt_t * pkt = aom_codec_get_cx_data(&aomEncoder, &iter);
- if (pkt == NULL)
- break;
+ if (pkt == NULL) {
+ if (flushed)
+ break;
+
+ aom_codec_encode(&aomEncoder, NULL, 0, 1, 0); // flush
+ flushed = AVIF_TRUE;
+ continue;
+ }
if (pkt->kind == AOM_CODEC_CX_FRAME_PKT) {
avifRWDataSet(obu, pkt->data.frame.buf, pkt->data.frame.sz);
success = AVIF_TRUE;
diff --git a/src/codec_rav1e.c b/src/codec_rav1e.c
index 920fbc2..adaa2e5 100644
--- a/src/codec_rav1e.c
+++ b/src/codec_rav1e.c
@@ -91,7 +91,6 @@
if (rav1e_config_parse_int(rav1eConfig, "quantizer", maxQuantizer) == -1) {
goto cleanup;
}
-
if (encoder->tileRowsLog2 != 0) {
int tileRowsLog2 = AVIF_CLAMP(encoder->tileRowsLog2, 0, 6);
if (rav1e_config_parse_int(rav1eConfig, "tile_rows", 1 << tileRowsLog2) == -1) {
@@ -104,6 +103,12 @@
goto cleanup;
}
}
+ if (encoder->speed != AVIF_SPEED_DEFAULT) {
+ int speed = AVIF_CLAMP(encoder->speed, 0, 10);
+ if (rav1e_config_parse_int(rav1eConfig, "speed", speed) == -1) {
+ goto cleanup;
+ }
+ }
if (image->profileFormat == AVIF_PROFILE_FORMAT_NCLX) {
rav1e_config_set_color_description(rav1eConfig,
diff --git a/src/write.c b/src/write.c
index b9c6447..35a11ce 100644
--- a/src/write.c
+++ b/src/write.c
@@ -31,6 +31,9 @@
encoder->maxThreads = 1;
encoder->minQuantizer = AVIF_QUANTIZER_LOSSLESS;
encoder->maxQuantizer = AVIF_QUANTIZER_LOSSLESS;
+ encoder->tileRowsLog2 = 0;
+ encoder->tileColsLog2 = 0;
+ encoder->speed = AVIF_SPEED_DEFAULT;
return encoder;
}
@@ -106,11 +109,6 @@
// -----------------------------------------------------------------------
// Encode AV1 OBUs
- // avifRWData * alphaOBUPtr = &alphaOBU;
- // if (avifImageIsOpaque(image)) {
- // alphaOBUPtr = NULL;
- // }
-
if (!codec[AVIF_CODEC_PLANES_COLOR]->encodeImage(codec[AVIF_CODEC_PLANES_COLOR], image, encoder, &colorOBU, AVIF_FALSE)) {
result = AVIF_RESULT_ENCODE_COLOR_FAILED;
goto writeCleanup;