[1/2] avcodec/libaomenc: export Sequence Header and Metadata OBUs as extradata

Message ID 20181006204314.28016-2-lu_zero@gentoo.org
State New
Headers show
Series
  • [1/2] avcodec/libaomenc: export Sequence Header and Metadata OBUs as extradata
Related show

Commit Message

Luca Barbato Oct. 6, 2018, 8:43 p.m.
From: James Almer <jamrial@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 <jamrial@gmail.com>
Signed-off-by: Luca Barbato <lu_zero@gentoo.org>
---
 configure              |  1 +
 libavcodec/libaomenc.c | 41 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+)

Comments

James Almer Oct. 7, 2018, 10:42 p.m. | #1
On 10/6/2018 5:43 PM, Luca Barbato wrote:
> From: James Almer <jamrial@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.

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.

> 
> Signed-off-by: James Almer <jamrial@gmail.com>
> Signed-off-by: Luca Barbato <lu_zero@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;
>  }
>  
>
Luca Barbato Oct. 8, 2018, 9:08 a.m. | #2
On 08/10/2018 00:42, James Almer wrote:
> 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

Patch

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;
 }