[FFmpeg-devel,7/8] h264_metadata: Update AVCodecParameters

Submitted by Andreas Rheinhardt on Dec. 1, 2018, 7:28 p.m.

Details

Message ID 20181201192810.852-8-andreas.rheinhardt@googlemail.com
State New
Headers show

Commit Message

Andreas Rheinhardt Dec. 1, 2018, 7:28 p.m.
This commit adds an option to also update the AVCodecParameters to align
them with the changes at the bitstream level. It is on by default.

Given the importance of correct frame dimensions they are updated
even when the new option is disabled.

The commit also adds documentation for the new option.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@googlemail.com>
---
 doc/bitstream_filters.texi     |  8 ++++++
 libavcodec/h264_metadata_bsf.c | 48 ++++++++++++++++++++++++++++++----
 2 files changed, 51 insertions(+), 5 deletions(-)

Patch hide | download patch | download mbox

diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi
index f5bf4aa93e..efd6834a3c 100644
--- a/doc/bitstream_filters.texi
+++ b/doc/bitstream_filters.texi
@@ -282,6 +282,14 @@  level_idc value (for example, @samp{42}), or the special name @samp{auto}
 indicating that the filter should attempt to guess the level from the
 input stream properties.
 
+@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.
+
+The frame dimensions are always updated and not affected by this option.
+
 @end table
 
 @section h264_mp4toannexb
diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c
index e674f2a88d..9ed0af26ee 100644
--- a/libavcodec/h264_metadata_bsf.c
+++ b/libavcodec/h264_metadata_bsf.c
@@ -82,11 +82,14 @@  typedef struct H264MetadataContext {
     int flip;
 
     int level;
+
+    int full_update;
 } H264MetadataContext;
 
 
-static int h264_metadata_update_sps(AVBSFContext *bsf,
-                                    H264RawSPS *sps)
+static int h264_metadata_update_sps(AVBSFContext *bsf, H264RawSPS *sps,
+                                    int *width, int *height, int *level,
+                                    int *chroma_location)
 {
     H264MetadataContext *ctx = bsf->priv_data;
     int need_vui = 0;
@@ -172,6 +175,9 @@  static int h264_metadata_update_sps(AVBSFContext *bsf,
             ctx->chroma_sample_loc_type;
         sps->vui.chroma_loc_info_present_flag = 1;
         need_vui = 1;
+
+        if (chroma_location && sps->chroma_format_idc == 1)
+            *chroma_location = 1 + ctx->chroma_sample_loc_type;
     }
 
     if (ctx->tick_rate.num && ctx->tick_rate.den) {
@@ -216,6 +222,14 @@  static int h264_metadata_update_sps(AVBSFContext *bsf,
     CROP(bottom, crop_unit_y);
 #undef CROP
 
+    if (width && height) {
+        *width  = 16 * (sps->pic_width_in_mbs_minus1 + 1) - crop_unit_x *
+                  (sps->frame_crop_left_offset + sps->frame_crop_right_offset);
+        *height = 16 * (sps->pic_height_in_map_units_minus1 + 1)
+                     * (2 - sps->frame_mbs_only_flag)     - crop_unit_y *
+                  (sps->frame_crop_top_offset + sps->frame_crop_bottom_offset);
+    }
+
     if (ctx->level != LEVEL_UNSET) {
         int level_idc;
 
@@ -269,6 +283,9 @@  static int h264_metadata_update_sps(AVBSFContext *bsf,
         } else {
             sps->level_idc = level_idc;
         }
+
+        if (level)
+            *level = sps->level_idc;
     }
 
     if (need_vui)
@@ -359,7 +376,8 @@  static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out)
     has_sps = 0;
     for (i = 0; i < au->nb_units; i++) {
         if (au->units[i].type == H264_NAL_SPS) {
-            err = h264_metadata_update_sps(bsf, au->units[i].content);
+            err = h264_metadata_update_sps(bsf, au->units[i].content,
+                                           NULL, NULL, NULL, NULL);
             if (err < 0)
                 goto fail;
             has_sps = 1;
@@ -618,7 +636,7 @@  static int h264_metadata_init(AVBSFContext *bsf)
 {
     H264MetadataContext *ctx = bsf->priv_data;
     CodedBitstreamFragment *au = &ctx->access_unit;
-    int err, i;
+    int err, i, width = -1, height = -1, level = -1, chroma_location = -1;
 
     err = ff_cbs_init(&ctx->cbc, AV_CODEC_ID_H264, bsf);
     if (err < 0)
@@ -633,7 +651,9 @@  static int h264_metadata_init(AVBSFContext *bsf)
 
         for (i = 0; i < au->nb_units; i++) {
             if (au->units[i].type == H264_NAL_SPS) {
-                err = h264_metadata_update_sps(bsf, au->units[i].content);
+                err = h264_metadata_update_sps(bsf, au->units[i].content,
+                                               &width, &height, &level,
+                                               &chroma_location);
                 if (err < 0)
                     goto fail;
             }
@@ -646,6 +666,21 @@  static int h264_metadata_init(AVBSFContext *bsf)
         }
     }
 
+    if (ctx->full_update) {
+        int color_range = ctx->video_full_range_flag == -1 ? -1 :
+                          ctx->video_full_range_flag + 1;
+
+        ff_cbs_update_video_parameters(ctx->cbc, bsf->par_out, -1, level,
+                                       width, height, -1, color_range,
+                                       ctx->colour_primaries,
+                                       ctx->transfer_characteristics,
+                                       ctx->matrix_coefficients,
+                                       chroma_location, -1);
+    } else
+        ff_cbs_update_video_parameters(ctx->cbc, bsf->par_out, -1,
+                                       -1, width, height, -1, -1,
+                                       -1, -1, -1, -1, -1);
+
     err = 0;
 fail:
     ff_cbs_fragment_uninit(ctx->cbc, au);
@@ -776,6 +811,9 @@  static const AVOption h264_metadata_options[] = {
     { LEVEL("6.2", 62) },
 #undef LEVEL
 
+    { "full_update", "Update not only bitstream, but also AVCodecParameters",
+        OFFSET(full_update), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, FLAGS},
+
     { NULL }
 };