[FFmpeg-devel,26/31] av1_metadata: Add option to update codec parameters

Submitted by Andreas Rheinhardt on June 19, 2019, 11:45 p.m.

Details

Message ID 20190619234521.15619-18-andreas.rheinhardt@gmail.com
State New
Headers show

Commit Message

Andreas Rheinhardt June 19, 2019, 11:45 p.m.
Up until now, this BSF only changed the bitstream and the extradata,
not the rest of the AVCodecParameters. The result is that e.g. some
muxers use outdated information to write header information that
conflicts with (and potentially precedes) the new information at the
bitstream level, so that using the bitstream filter might not have the
desired effect.

This commit changes this. It adds a mechanism by which the new
information can be used to update the AVCodecParameters, too. This is
the new default and an option has been added to revert to the old
behaviour.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
---
 doc/bitstream_filters.texi    |  6 ++++++
 libavcodec/av1_metadata_bsf.c | 39 +++++++++++++++++++++++++++++++----
 2 files changed, 41 insertions(+), 4 deletions(-)

Patch hide | download patch | download mbox

diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi
index 40e8adad0f..f625c8f768 100644
--- a/doc/bitstream_filters.texi
+++ b/doc/bitstream_filters.texi
@@ -90,6 +90,12 @@  has a fixed framerate.  Ignored if @option{tick_rate} is not also set.
 @item delete_padding
 Deletes Padding OBUs.
 
+@item full_update
+If this is set, an effort is made to update the AVCodecParameters in addition
+to the bitstream. If unset, muxers might add header information based upon
+the old AVCodecParameters that contradicts and potentially precedes the
+changes made at the bitstream level. On by default.
+
 @end table
 
 @section chomp
diff --git a/libavcodec/av1_metadata_bsf.c b/libavcodec/av1_metadata_bsf.c
index 7d9d15b1a0..fce1a194b7 100644
--- a/libavcodec/av1_metadata_bsf.c
+++ b/libavcodec/av1_metadata_bsf.c
@@ -48,11 +48,15 @@  typedef struct AV1MetadataContext {
     int num_ticks_per_picture;
 
     int delete_padding;
+
+    int full_update;
 } AV1MetadataContext;
 
 
 static int av1_metadata_update_sequence_header(AVBSFContext *bsf,
-                                               AV1RawSequenceHeader *seq)
+                                               AV1RawSequenceHeader *seq,
+                                               int *color_range,
+                                               int *chroma_sample_position)
 {
     AV1MetadataContext *ctx = bsf->priv_data;
     AV1RawColorConfig  *clc = &seq->color_config;
@@ -79,6 +83,8 @@  static int av1_metadata_update_sequence_header(AVBSFContext *bsf,
                    "on RGB streams encoded in BT.709 sRGB.\n");
         } else {
             clc->color_range = ctx->color_range;
+            if (color_range)
+                *color_range = ctx->color_range + 1;
         }
     }
 
@@ -88,6 +94,8 @@  static int av1_metadata_update_sequence_header(AVBSFContext *bsf,
                    "can only be set for 4:2:0 streams.\n");
         } else {
             clc->chroma_sample_position = ctx->chroma_sample_position;
+            if (chroma_sample_position)
+                *chroma_sample_position = ctx->chroma_sample_position;
         }
     }
 
@@ -137,7 +145,8 @@  static int av1_metadata_filter(AVBSFContext *bsf, AVPacket *pkt)
     for (i = 0; i < frag->nb_units; i++) {
         if (frag->units[i].type == AV1_OBU_SEQUENCE_HEADER) {
             obu = frag->units[i].content;
-            err = av1_metadata_update_sequence_header(bsf, &obu->obu.sequence_header);
+            err = av1_metadata_update_sequence_header(bsf, &obu->obu.sequence_header,
+                                                      NULL, NULL);
             if (err < 0)
                 goto fail;
         }
@@ -191,7 +200,7 @@  static int av1_metadata_init(AVBSFContext *bsf)
     AV1MetadataContext *ctx = bsf->priv_data;
     CodedBitstreamFragment *frag = &ctx->access_unit;
     AV1RawOBU *obu;
-    int err, i;
+    int err, i, color_range = -1, chroma_sample_position = -1;
 
     err = ff_cbs_init(&ctx->cbc, AV_CODEC_ID_AV1, bsf);
     if (err < 0)
@@ -207,7 +216,8 @@  static int av1_metadata_init(AVBSFContext *bsf)
         for (i = 0; i < frag->nb_units; i++) {
             if (frag->units[i].type == AV1_OBU_SEQUENCE_HEADER) {
                 obu = frag->units[i].content;
-                err = av1_metadata_update_sequence_header(bsf, &obu->obu.sequence_header);
+                err = av1_metadata_update_sequence_header(bsf, &obu->obu.sequence_header,
+                                                          &color_range, &chroma_sample_position);
                 if (err < 0)
                     goto fail;
             }
@@ -220,6 +230,24 @@  static int av1_metadata_init(AVBSFContext *bsf)
         }
     }
 
+    if (ctx->full_update) {
+        if (chroma_sample_position >= 0) {
+            static const uint8_t conversion_table[4] = {
+                AVCHROMA_LOC_UNSPECIFIED,
+                AVCHROMA_LOC_LEFT,
+                AVCHROMA_LOC_TOPLEFT,
+                AVCHROMA_LOC_UNSPECIFIED
+            };
+            chroma_sample_position = conversion_table[chroma_sample_position];
+        }
+
+        ff_cbs_update_video_parameters(ctx->cbc, bsf->par_out, -1, -1, -1, -1,
+                                       -1, color_range, ctx->color_primaries,
+                                       ctx->transfer_characteristics,
+                                       ctx->matrix_coefficients,
+                                       chroma_sample_position, -1);
+    }
+
     err = 0;
 fail:
     ff_cbs_fragment_reset(ctx->cbc, frag);
@@ -286,6 +314,9 @@  static const AVOption av1_metadata_options[] = {
         OFFSET(delete_padding), AV_OPT_TYPE_BOOL,
         { .i64 = 0 }, 0, 1, FLAGS},
 
+    { "full_update", "Update not only bitstream, but also AVCodecParameters.",
+        OFFSET(full_update), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, FLAGS},
+
     { NULL }
 };