Discussion:
[libav-devel] Updates for libaom
Luca Barbato
2018-10-06 20:43:12 UTC
Permalink
Should be debated if we want to support aom 1.0 or just require a
version that produces the extradata by itself.
Luca Barbato
2018-10-06 20:43:13 UTC
Permalink
From: James Almer <***@gmail.com>

aom_codec_get_global_headers() is not implemented as of libaom 1.0.0 for AV1, so
we're forced to extract the relevant header OBUs from the first packet and propagate
them as packet side data.

Signed-off-by: James Almer <***@gmail.com>
Signed-off-by: Luca Barbato <***@gentoo.org>
---
configure | 1 +
libavcodec/libaomenc.c | 41 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 42 insertions(+)

diff --git a/configure b/configure
index 48e8536b07..8ac3c1c7c3 100755
--- a/configure
+++ b/configure
@@ -2372,6 +2372,7 @@ avisynth_demuxer_deps_any="avisynth avxsynth"
avisynth_demuxer_select="riffdec"
libaom_av1_decoder_deps="libaom"
libaom_av1_encoder_deps="libaom"
+libaom_av1_encoder_select="extract_extradata_bsf"
libdcadec_decoder_deps="libdcadec"
libfaac_encoder_deps="libfaac"
libfaac_encoder_select="audio_frame_queue"
diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c
index 9807bd5adb..9344909be4 100644
--- a/libavcodec/libaomenc.c
+++ b/libavcodec/libaomenc.c
@@ -49,6 +49,7 @@ struct FrameListData {

typedef struct AOMEncoderContext {
AVClass *class;
+ AVBSFContext *bsf;
struct aom_codec_ctx encoder;
struct aom_image rawimg;
struct aom_fixed_buf twopass_stats;
@@ -189,6 +190,7 @@ static av_cold int aom_free(AVCodecContext *avctx)
av_freep(&ctx->twopass_stats.buf);
av_freep(&avctx->stats_out);
free_frame_list(ctx->coded_frame_list);
+ av_bsf_free(&ctx->bsf);
return 0;
}

@@ -340,6 +342,28 @@ static av_cold int aom_init(AVCodecContext *avctx)
if (!cpb_props)
return AVERROR(ENOMEM);

+ if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
+ const AVBitStreamFilter *filter = av_bsf_get_by_name("extract_extradata");
+ int ret;
+
+ if (!filter) {
+ av_log(avctx, AV_LOG_ERROR, "extract_extradata bitstream filter "
+ "not found. This is a bug, please report it.\n");
+ return AVERROR_BUG;
+ }
+ ret = av_bsf_alloc(filter, &ctx->bsf);
+ if (ret < 0)
+ return ret;
+
+ ret = avcodec_parameters_from_context(ctx->bsf->par_in, avctx);
+ if (ret < 0)
+ return ret;
+
+ ret = av_bsf_init(ctx->bsf);
+ if (ret < 0)
+ return ret;
+ }
+
if (enccfg.rc_end_usage == AOM_CBR ||
enccfg.g_pass != AOM_RC_ONE_PASS) {
cpb_props->max_bitrate = avctx->rc_max_rate;
@@ -371,6 +395,7 @@ static inline void cx_pktcpy(struct FrameListData *dst,
static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame,
AVPacket *pkt)
{
+ AOMContext *ctx = avctx->priv_data;
int ret = ff_alloc_packet(pkt, cx_frame->sz);
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR,
@@ -382,6 +407,22 @@ static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame,

if (!!(cx_frame->flags & AOM_FRAME_IS_KEY))
pkt->flags |= AV_PKT_FLAG_KEY;
+
+ if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
+ ret = av_bsf_send_packet(ctx->bsf, pkt);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "extract_extradata filter "
+ "failed to send input packet\n");
+ return ret;
+ }
+ ret = av_bsf_receive_packet(ctx->bsf, pkt);
+
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "extract_extradata filter "
+ "failed to receive output packet\n");
+ return ret;
+ }
+ }
return pkt->size;
}
--
2.12.2
James Almer
2018-10-07 22:42:32 UTC
Permalink
Post by Luca Barbato
aom_codec_get_global_headers() is not implemented as of libaom 1.0.0 for AV1, so
we're forced to extract the relevant header OBUs from the first packet and propagate
them as packet side data.
It is now available in libaom git head, but who knows when they will tag
a new release...

If you'd rather avoid nonetheless the complexity, i can cook up a patch
to use it and make the minimum required libaom version something recent
enough. Unless the plan was to tag a libav release, in which case it
would probably not be a good idea.
Post by Luca Barbato
---
configure | 1 +
libavcodec/libaomenc.c | 41 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 42 insertions(+)
diff --git a/configure b/configure
index 48e8536b07..8ac3c1c7c3 100755
--- a/configure
+++ b/configure
@@ -2372,6 +2372,7 @@ avisynth_demuxer_deps_any="avisynth avxsynth"
avisynth_demuxer_select="riffdec"
libaom_av1_decoder_deps="libaom"
libaom_av1_encoder_deps="libaom"
+libaom_av1_encoder_select="extract_extradata_bsf"
libdcadec_decoder_deps="libdcadec"
libfaac_encoder_deps="libfaac"
libfaac_encoder_select="audio_frame_queue"
diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c
index 9807bd5adb..9344909be4 100644
--- a/libavcodec/libaomenc.c
+++ b/libavcodec/libaomenc.c
@@ -49,6 +49,7 @@ struct FrameListData {
typedef struct AOMEncoderContext {
AVClass *class;
+ AVBSFContext *bsf;
struct aom_codec_ctx encoder;
struct aom_image rawimg;
struct aom_fixed_buf twopass_stats;
@@ -189,6 +190,7 @@ static av_cold int aom_free(AVCodecContext *avctx)
av_freep(&ctx->twopass_stats.buf);
av_freep(&avctx->stats_out);
free_frame_list(ctx->coded_frame_list);
+ av_bsf_free(&ctx->bsf);
return 0;
}
@@ -340,6 +342,28 @@ static av_cold int aom_init(AVCodecContext *avctx)
if (!cpb_props)
return AVERROR(ENOMEM);
+ if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
+ const AVBitStreamFilter *filter = av_bsf_get_by_name("extract_extradata");
+ int ret;
+
+ if (!filter) {
+ av_log(avctx, AV_LOG_ERROR, "extract_extradata bitstream filter "
+ "not found. This is a bug, please report it.\n");
+ return AVERROR_BUG;
+ }
+ ret = av_bsf_alloc(filter, &ctx->bsf);
+ if (ret < 0)
+ return ret;
+
+ ret = avcodec_parameters_from_context(ctx->bsf->par_in, avctx);
+ if (ret < 0)
+ return ret;
+
+ ret = av_bsf_init(ctx->bsf);
+ if (ret < 0)
+ return ret;
+ }
+
if (enccfg.rc_end_usage == AOM_CBR ||
enccfg.g_pass != AOM_RC_ONE_PASS) {
cpb_props->max_bitrate = avctx->rc_max_rate;
@@ -371,6 +395,7 @@ static inline void cx_pktcpy(struct FrameListData *dst,
static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame,
AVPacket *pkt)
{
+ AOMContext *ctx = avctx->priv_data;
int ret = ff_alloc_packet(pkt, cx_frame->sz);
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR,
@@ -382,6 +407,22 @@ static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame,
if (!!(cx_frame->flags & AOM_FRAME_IS_KEY))
pkt->flags |= AV_PKT_FLAG_KEY;
+
+ if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
+ ret = av_bsf_send_packet(ctx->bsf, pkt);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "extract_extradata filter "
+ "failed to send input packet\n");
+ return ret;
+ }
+ ret = av_bsf_receive_packet(ctx->bsf, pkt);
+
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "extract_extradata filter "
+ "failed to receive output packet\n");
+ return ret;
+ }
+ }
return pkt->size;
}
Luca Barbato
2018-10-08 09:08:40 UTC
Permalink
Post by James Almer
If you'd rather avoid nonetheless the complexity, i can cook up a patch
to use it and make the minimum required libaom version something recent
enough. Unless the plan was to tag a libav release, in which case it
would probably not be a good idea.
If you have something almost ready I'd pick that and simplify the muxer
code to just reject non-extradata streams.

lu
James Almer
2018-10-08 16:19:06 UTC
Permalink
Signed-off-by: James Almer <***@gmail.com>
---
configure | 8 +++++++-
libavcodec/libaomenc.c | 34 +++++++++++++++++++++++++++++++++-
2 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/configure b/configure
index 48e8536b0..2aa7eb627 100755
--- a/configure
+++ b/configure
@@ -4664,7 +4664,13 @@ enabled cuvid && require cuvid cuviddec.h cuvidCreateDecoder -lnvcuv
enabled frei0r && require_headers frei0r.h
enabled gnutls && require_pkg_config gnutls gnutls gnutls/gnutls.h gnutls_global_init &&
check_lib gmp gmp.h mpz_export -lgmp
-enabled libaom && require_pkg_config libaom "aom >= 0.1.0" aom/aom_codec.h aom_codec_version
+enabled libaom && {
+ enabled libaom_av1_decoder && require_pkg_config libaom_av1_decoder "aom >= 1.0.0" "aom/aom_decoder.h aom/aomdx.h" aom_codec_av1_dx
+ enabled libaom_av1_encoder && {
+ require_pkg_config libaom_av1_encoder "aom >= 1.0.0" "aom/aom_encoder.h aom/aomcx.h" aom_codec_av1_cx &&
+ require_cpp_condition libaom_av1_encoder aom/aom_encoder.h "defined AOM_FRAME_IS_INTRAONLY";
+ }
+}
enabled libbs2b && require_pkg_config libbs2b libbs2b bs2b.h bs2b_open
enabled libdc1394 && require_pkg_config libdc1394 libdc1394-2 dc1394/dc1394.h dc1394_new
enabled libdcadec && require libdcadec libdcadec/dca_context.h dcadec_context_create -ldcadec
diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c
index 9807bd5ad..69e4ea126 100644
--- a/libavcodec/libaomenc.c
+++ b/libavcodec/libaomenc.c
@@ -68,6 +68,8 @@ static const char *const ctlidstr[] = {
[AOME_SET_CQ_LEVEL] = "AOME_SET_CQ_LEVEL",
[AOME_SET_ENABLEAUTOALTREF] = "AOME_SET_ENABLEAUTOALTREF",
[AOME_SET_STATIC_THRESHOLD] = "AOME_SET_STATIC_THRESHOLD",
+ [AV1E_SET_CHROMA_SUBSAMPLING_X] = "AV1E_SET_CHROMA_SUBSAMPLING_X",
+ [AV1E_SET_CHROMA_SUBSAMPLING_Y] = "AV1E_SET_CHROMA_SUBSAMPLING_Y",
};

static av_cold void log_encoder_error(AVCodecContext *avctx, const char *desc)
@@ -197,7 +199,7 @@ static av_cold int aom_init(AVCodecContext *avctx)
AOMContext *ctx = avctx->priv_data;
struct aom_codec_enc_cfg enccfg = { 0 };
AVCPBProperties *cpb_props;
- int res;
+ int res, h_shift, v_shift;
const struct aom_codec_iface *iface = &aom_codec_av1_cx_algo;

av_log(avctx, AV_LOG_INFO, "%s\n", aom_codec_version_str());
@@ -332,6 +334,13 @@ static av_cold int aom_init(AVCodecContext *avctx)
codecctl_int(avctx, AOME_SET_STATIC_THRESHOLD, ctx->static_thresh);
codecctl_int(avctx, AOME_SET_CQ_LEVEL, ctx->crf);

+ res = av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, &h_shift, &v_shift);
+ if (res < 0)
+ return res;
+
+ codecctl_int(avctx, AV1E_SET_CHROMA_SUBSAMPLING_X, h_shift);
+ codecctl_int(avctx, AV1E_SET_CHROMA_SUBSAMPLING_Y, v_shift);
+
// provide dummy value to initialize wrapper, values will be updated each _encode()
aom_img_wrap(&ctx->rawimg, ff_aom_pixfmt_to_imgfmt(avctx->pix_fmt),
avctx->width, avctx->height, 1, (unsigned char *)1);
@@ -340,6 +349,29 @@ static av_cold int aom_init(AVCodecContext *avctx)
if (!cpb_props)
return AVERROR(ENOMEM);

+ if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
+ aom_fixed_buf_t *seq = aom_codec_get_global_headers(&ctx->encoder);
+ if (!seq)
+ return AVERROR_UNKNOWN;
+
+ avctx->extradata = av_malloc(seq->sz + AV_INPUT_BUFFER_PADDING_SIZE);
+ if (!avctx->extradata) {
+ free(seq->buf);
+ free(seq);
+ return AVERROR(ENOMEM);
+ }
+ avctx->extradata_size = seq->sz;
+ memcpy(avctx->extradata, seq->buf, seq->sz);
+ memset(avctx->extradata + seq->sz, 0, AV_INPUT_BUFFER_PADDING_SIZE);
+
+ /* Doxy says: "The caller owns the memory associated with this buffer.
+ * Memory is allocated using malloc(), and should be freed
+ * via call to free()"
+ */
+ free(seq->buf);
+ free(seq);
+ }
+
if (enccfg.rc_end_usage == AOM_CBR ||
enccfg.g_pass != AOM_RC_ONE_PASS) {
cpb_props->max_bitrate = avctx->rc_max_rate;
--
2.19.0
Luca Barbato
2018-10-09 16:23:09 UTC
Permalink
Post by James Almer
---
configure | 8 +++++++-
libavcodec/libaomenc.c | 34 +++++++++++++++++++++++++++++++++-
2 files changed, 40 insertions(+), 2 deletions(-)
Looks great, I'd merge this and then rework the formats support set
based on this.

lu

Luca Barbato
2018-10-06 20:43:14 UTC
Permalink
From: James Almer <***@gmail.com>

Support for it was apparently never in the codebase, and the enum
value was recently removed from the public headers [1]

[1] https://aomedia.googlesource.com/aom/+/df4ffb73140fe31bebdabd17c1a7b53721e74838

Signed-off-by: James Almer <***@gmail.com>
Signed-off-by: Luca Barbato <***@gentoo.org>
---
libavcodec/libaomenc.c | 4 ----
1 file changed, 4 deletions(-)

diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c
index 9344909be4..3ac295c501 100644
--- a/libavcodec/libaomenc.c
+++ b/libavcodec/libaomenc.c
@@ -581,10 +581,6 @@ static const AVOption options[] = {
"alternate reference frame selection", OFFSET(lag_in_frames), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE},
{ "error-resilience", "Error resilience configuration", OFFSET(error_resilient), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, VE, "er"},
{ "default", "Improve resiliency against losses of whole frames", 0, AV_OPT_TYPE_CONST, {.i64 = AOM_ERROR_RESILIENT_DEFAULT}, 0, 0, VE, "er"},
- { "partitions", "The frame partitions are independently decodable "
- "by the bool decoder, meaning that partitions can be decoded even "
- "though earlier partitions have been lost. Note that intra predicition"
- " is still done over the partition boundary.", 0, AV_OPT_TYPE_CONST, {.i64 = AOM_ERROR_RESILIENT_PARTITIONS}, 0, 0, VE, "er"},
{ "crf", "Select the quality for constant quality mode", offsetof(AOMContext, crf), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 63, VE },
{ "static-thresh", "A change threshold on blocks below which they will be skipped by the encoder", OFFSET(static_thresh), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
{ "drop-threshold", "Frame drop threshold", offsetof(AOMContext, drop_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, VE },
--
2.12.2
Loading...