Source code

Revision control

Copy as Markdown

Other Tools

diff --git a/media/ffvpx/libavcodec/libaomenc.c b/media/ffvpx/libavcodec/libaomenc.c
index ebaf2d7ad764..9bcede34de8f 100644
--- a/media/ffvpx/libavcodec/libaomenc.c
+++ b/media/ffvpx/libavcodec/libaomenc.c
@@ -70,6 +70,13 @@ struct FrameListData {
struct FrameListData *next;
};
+struct ColorConfig {
+ enum AVColorPrimaries color_primaries;
+ enum AVColorTransferCharacteristic color_trc;
+ enum AVColorSpace colorspace;
+ enum AVColorRange color_range;
+};
+
typedef struct AOMEncoderContext {
AVClass *class;
AVBSFContext *bsf;
@@ -85,6 +92,7 @@ typedef struct AOMEncoderContext {
int arnr_strength;
int aq_mode;
int lag_in_frames;
+ int has_submitted_frame;
int error_resilient;
int crf;
int static_thresh;
@@ -139,6 +147,7 @@ typedef struct AOMEncoderContext {
int enable_diff_wtd_comp;
int enable_dist_wtd_comp;
int enable_dual_filter;
+ struct ColorConfig color_config;
AVDictionary *svc_parameters;
AVDictionary *aom_params;
} AOMContext;
@@ -571,20 +580,66 @@ static int set_pix_fmt(AVCodecContext *avctx, aom_codec_caps_t codec_caps,
return AVERROR_INVALIDDATA;
}
-static void set_color_range(AVCodecContext *avctx)
+static int set_color_range(AVCodecContext *avctx, enum AVColorRange color_range)
{
aom_color_range_t aom_cr;
- switch (avctx->color_range) {
+ switch (color_range) {
case AVCOL_RANGE_UNSPECIFIED:
case AVCOL_RANGE_MPEG: aom_cr = AOM_CR_STUDIO_RANGE; break;
case AVCOL_RANGE_JPEG: aom_cr = AOM_CR_FULL_RANGE; break;
default:
av_log(avctx, AV_LOG_WARNING, "Unsupported color range (%d)\n",
- avctx->color_range);
- return;
+ color_range);
+ return AVERROR(EINVAL);
}
- codecctl_int(avctx, AV1E_SET_COLOR_RANGE, aom_cr);
+ return codecctl_int(avctx, AV1E_SET_COLOR_RANGE, aom_cr);
+}
+
+static int set_color_config(AVCodecContext *avctx,
+ const struct ColorConfig *config)
+{
+ AOMContext *ctx = avctx->priv_data;
+ struct ColorConfig *curcfg = &ctx->color_config;
+ int res;
+
+ res = codecctl_int(avctx, AV1E_SET_COLOR_PRIMARIES,
+ config->color_primaries);
+ if (res < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to set color primaries to %d\n",
+ config->color_primaries);
+ return res;
+ }
+ curcfg->color_primaries = config->color_primaries;
+
+ res = codecctl_int(avctx, AV1E_SET_TRANSFER_CHARACTERISTICS,
+ config->color_trc);
+ if (res < 0) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Failed to set color transfer characteristics to %d\n",
+ config->color_trc);
+ return res;
+ }
+ curcfg->color_trc = config->color_trc;
+
+ res = codecctl_int(avctx, AV1E_SET_MATRIX_COEFFICIENTS,
+ config->colorspace);
+ if (res < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to set color space to %d\n",
+ config->colorspace);
+ return res;
+ }
+ curcfg->colorspace = config->colorspace;
+
+ res = set_color_range(avctx, config->color_range);
+ if (res < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to set color range to %d\n",
+ config->color_range);
+ return res;
+ }
+ curcfg->color_range = config->color_range;
+
+ return 0;
}
static int count_uniform_tiling(int dim, int sb_size, int tiles_log2)
@@ -964,6 +1019,8 @@ static av_cold int aom_init(AVCodecContext *avctx,
enccfg.kf_mode = AOM_KF_DISABLED;
}
+ ctx->lag_in_frames = enccfg.g_lag_in_frames;
+
/* Construct Encoder Context */
res = aom_codec_enc_init(&ctx->encoder, iface, &enccfg, flags);
if (res != AOM_CODEC_OK) {
@@ -988,20 +1045,29 @@ static av_cold int aom_init(AVCodecContext *avctx,
if (ctx->tune >= 0)
codecctl_int(avctx, AOME_SET_TUNING, ctx->tune);
- if (desc->flags & AV_PIX_FMT_FLAG_RGB) {
- codecctl_int(avctx, AV1E_SET_COLOR_PRIMARIES, AVCOL_PRI_BT709);
- codecctl_int(avctx, AV1E_SET_MATRIX_COEFFICIENTS, AVCOL_SPC_RGB);
- codecctl_int(avctx, AV1E_SET_TRANSFER_CHARACTERISTICS, AVCOL_TRC_IEC61966_2_1);
- } else {
- codecctl_int(avctx, AV1E_SET_COLOR_PRIMARIES, avctx->color_primaries);
- codecctl_int(avctx, AV1E_SET_MATRIX_COEFFICIENTS, avctx->colorspace);
- codecctl_int(avctx, AV1E_SET_TRANSFER_CHARACTERISTICS, avctx->color_trc);
- }
+ struct ColorConfig colorcfg;
+ if (desc->flags & AV_PIX_FMT_FLAG_RGB)
+ colorcfg = (struct ColorConfig) {
+ .color_primaries = AVCOL_PRI_BT709,
+ .color_trc = AVCOL_TRC_IEC61966_2_1,
+ .colorspace = AVCOL_SPC_RGB,
+ .color_range = avctx->color_range,
+ };
+ else
+ colorcfg = (struct ColorConfig) {
+ .color_primaries = avctx->color_primaries,
+ .color_trc = avctx->color_trc,
+ .colorspace = avctx->colorspace,
+ .color_range = avctx->color_range,
+ };
+ // Ignore the return value to follow the convention of other codecctl_int()
+ // calls.
+ set_color_config(avctx, &colorcfg);
+
if (ctx->aq_mode >= 0)
codecctl_int(avctx, AV1E_SET_AQ_MODE, ctx->aq_mode);
if (ctx->frame_parallel >= 0)
codecctl_int(avctx, AV1E_SET_FRAME_PARALLEL_DECODING, ctx->frame_parallel);
- set_color_range(avctx);
codecctl_int(avctx, AV1E_SET_SUPERBLOCK_SIZE, ctx->superblock_size);
if (ctx->uniform_tiles) {
@@ -1364,13 +1430,39 @@ static int aom_encode(AVCodecContext *avctx, AVPacket *pkt,
duration = 1;
}
+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
+ if (!(desc->flags & AV_PIX_FMT_FLAG_RGB)) {
+ const struct ColorConfig *curcfg = &ctx->color_config;
+ const struct ColorConfig newcfg = {
+ .color_primaries = frame->color_primaries,
+ .color_trc = frame->color_trc,
+ .colorspace = frame->colorspace,
+ .color_range = frame->color_range,
+ };
+ if (newcfg.color_primaries != curcfg->color_primaries ||
+ newcfg.color_trc != curcfg->color_trc ||
+ newcfg.colorspace != curcfg->colorspace ||
+ newcfg.color_range != curcfg->color_range) {
+ if (ctx->has_submitted_frame && ctx->lag_in_frames != 0) {
+ av_log(avctx, AV_LOG_WARNING,
+ "Ignoring color metadata change with lookahead enabled\n");
+ } else {
+ res = set_color_config(avctx, &newcfg);
+ if (res < 0)
+ return res;
+ }
+ }
+ }
+
switch (frame->color_range) {
- case AVCOL_RANGE_MPEG:
- rawimg->range = AOM_CR_STUDIO_RANGE;
- break;
case AVCOL_RANGE_JPEG:
rawimg->range = AOM_CR_FULL_RANGE;
break;
+ case AVCOL_RANGE_UNSPECIFIED:
+ case AVCOL_RANGE_MPEG:
+ default:
+ rawimg->range = AOM_CR_STUDIO_RANGE;
+ break;
}
aom_img_remove_metadata(rawimg);
@@ -1425,6 +1517,8 @@ static int aom_encode(AVCodecContext *avctx, AVPacket *pkt,
log_encoder_error(avctx, "Error encoding frame");
return AVERROR_INVALIDDATA;
}
+ if (frame)
+ ctx->has_submitted_frame = 1;
coded_size = queue_frames(avctx, pkt);
if (coded_size < 0)
return coded_size;