[FFmpeg-devel] [PATCH 3/5] avcodec/libaomenc: export Sequence Header and Metadata OBUs as extradata

James Almer jamrial at gmail.com
Mon Jul 9 21:26:52 EEST 2018


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 for now.

Signed-off-by: James Almer <jamrial at gmail.com>
---
This is far from ideal. Whereas the mp4 muxer can handle extradata
propagated as packet side data without issues, the Matroska one can't
feasibly do it since it would require to reserve space for it, and we
don't know just how big the resulting extradata can be as it may have
an arbitrary amount of OBUs.

libaom should ideally implement aom_codec_get_global_headers() for
AV1 (Which is clearly inspired by similar functionality in libx264
and other encoders, and can be used before any kind of image data is
sent to the encoder), so lobby is welcome :p

 configure              |  1 +
 libavcodec/libaomenc.c | 41 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+)

diff --git a/configure b/configure
index 1066df6621..a76dd06736 100755
--- a/configure
+++ b/configure
@@ -3046,6 +3046,7 @@ hevc_videotoolbox_encoder_deps="pthreads"
 hevc_videotoolbox_encoder_select="videotoolbox_encoder"
 libaom_av1_decoder_deps="libaom"
 libaom_av1_encoder_deps="libaom"
+libaom_av1_encoder_select="extract_extradata_bsf"
 libcelt_decoder_deps="libcelt"
 libcodec2_decoder_deps="libcodec2"
 libcodec2_encoder_deps="libcodec2"
diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c
index 41b05dc1c0..0b75dc139c 100644
--- a/libavcodec/libaomenc.c
+++ b/libavcodec/libaomenc.c
@@ -55,6 +55,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;
@@ -202,6 +203,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;
 }
 
@@ -463,6 +465,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;
@@ -494,6 +518,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_packet2(avctx, pkt, cx_frame->sz, 0);
     if (ret < 0) {
         av_log(avctx, AV_LOG_ERROR,
@@ -505,6 +530,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.18.0



More information about the ffmpeg-devel mailing list