diff mbox

[FFmpeg-devel,8/8] hevc_metadata: Update AVCodecParameters

Message ID 20181201192810.852-9-andreas.rheinhardt@googlemail.com
State Superseded
Headers show

Commit Message

Andreas Rheinhardt Dec. 1, 2018, 7:28 p.m. UTC
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. Notice that for field-based HEVC
the derived height is the height of a frame, which deviates from current
FFmpeg behaviour.

This commit also adds documentation for the new value.

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

Patch

diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi
index efd6834a3c..c65c2aba2c 100644
--- a/doc/bitstream_filters.texi
+++ b/doc/bitstream_filters.texi
@@ -372,6 +372,14 @@  will replace the current ones if the stream is already cropped.
 These fields are set in pixels.  Note that some sizes may not be
 representable if the chroma is subsampled (H.265 section 7.4.3.2.1).
 
+@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 hevc_mp4toannexb
diff --git a/libavcodec/h265_metadata_bsf.c b/libavcodec/h265_metadata_bsf.c
index 26eb2d05d0..47f2ba12ac 100644
--- a/libavcodec/h265_metadata_bsf.c
+++ b/libavcodec/h265_metadata_bsf.c
@@ -58,6 +58,8 @@  typedef struct H265MetadataContext {
     int crop_right;
     int crop_top;
     int crop_bottom;
+
+    int full_update;
 } H265MetadataContext;
 
 
@@ -89,8 +91,9 @@  static int h265_metadata_update_vps(AVBSFContext *bsf,
     return 0;
 }
 
-static int h265_metadata_update_sps(AVBSFContext *bsf,
-                                    H265RawSPS *sps)
+static int h265_metadata_update_sps(AVBSFContext *bsf, H265RawSPS *sps,
+                                    int *width, int *height,
+                                    int *chroma_location)
 {
     H265MetadataContext *ctx = bsf->priv_data;
     int need_vui = 0;
@@ -176,6 +179,9 @@  static int h265_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) {
@@ -224,6 +230,13 @@  static int h265_metadata_update_sps(AVBSFContext *bsf,
     CROP(bottom, crop_unit_y);
 #undef CROP
 
+    if (width && height) {
+        *width  = sps->pic_width_in_luma_samples  - crop_unit_x *
+                  (sps->conf_win_left_offset + sps->conf_win_right_offset);
+        *height = (1 + sps->vui.field_seq_flag) * (sps->pic_height_in_luma_samples
+                - crop_unit_y * (sps->conf_win_top_offset + sps->conf_win_bottom_offset));
+    }
+
     if (need_vui)
         sps->vui_parameters_present_flag = 1;
 
@@ -304,7 +317,8 @@  static int h265_metadata_filter(AVBSFContext *bsf, AVPacket *out)
                 goto fail;
         }
         if (au->units[i].type == HEVC_NAL_SPS) {
-            err = h265_metadata_update_sps(bsf, au->units[i].content);
+            err = h265_metadata_update_sps(bsf, au->units[i].content,
+                                           NULL, NULL, NULL);
             if (err < 0)
                 goto fail;
         }
@@ -335,7 +349,7 @@  static int h265_metadata_init(AVBSFContext *bsf)
 {
     H265MetadataContext *ctx = bsf->priv_data;
     CodedBitstreamFragment *au = &ctx->access_unit;
-    int err, i;
+    int err, i, width = -1, height = -1, chroma_location = -1;
 
     err = ff_cbs_init(&ctx->cbc, AV_CODEC_ID_HEVC, bsf);
     if (err < 0)
@@ -355,7 +369,9 @@  static int h265_metadata_init(AVBSFContext *bsf)
                     goto fail;
             }
             if (au->units[i].type == HEVC_NAL_SPS) {
-                err = h265_metadata_update_sps(bsf, au->units[i].content);
+                err = h265_metadata_update_sps(bsf, au->units[i].content,
+                                               &width, &height,
+                                               &chroma_location);
                 if (err < 0)
                     goto fail;
             }
@@ -368,6 +384,21 @@  static int h265_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, -1,
+                                       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);
@@ -439,6 +470,9 @@  static const AVOption h265_metadata_options[] = {
         OFFSET(crop_bottom), AV_OPT_TYPE_INT,
         { .i64 = -1 }, -1, HEVC_MAX_HEIGHT, FLAGS },
 
+    { "full_update", "Update not only bitstream, but also AVCodecParameters",
+        OFFSET(full_update), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, FLAGS},
+
     { NULL }
 };