[FFmpeg-devel] [PATCH v1 2/2] avcodec/h265_metadata_bsf: add option to insert a string as SEI unregistered user data

Limin Wang lance.lmwang at gmail.com
Tue Dec 17 12:29:30 EET 2019


On Wed, Dec 11, 2019 at 11:02:04PM +0800, lance.lmwang at gmail.com wrote:
> From: Limin Wang <lance.lmwang at gmail.com>
> 
> Signed-off-by: Limin Wang <lance.lmwang at gmail.com>
> ---
>  doc/bitstream_filters.texi     |  8 ++++++
>  libavcodec/h265_metadata_bsf.c | 65 +++++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 72 insertions(+), 1 deletion(-)
> 
> diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi
> index 8fe5b3a..81b41d7 100644
> --- a/doc/bitstream_filters.texi
> +++ b/doc/bitstream_filters.texi
> @@ -376,6 +376,14 @@ The argument must be the name of a level (for example, @samp{5.1}), a
>  or the special name @samp{auto} indicating that the filter should
>  attempt to guess the level from the input stream properties.
>  
> + at item sei_user_data
> +Insert a string as SEI unregistered user data.  The argument must
> +be of the form @emph{UUID+string}, where the UUID is as a 32-character
> +(16 bytes) hexadecimal string possibly separated by hyphens, and the
> +string can be anything.
> +
> +For example, @samp{086f3693-b7b3-4f2c-9653-21492feee5b8+hello} will
> +insert the string ``hello'' associated with the given 32-bit UUID.
>  @end table

Please use below patchset to check the result:
https://patchwork.ffmpeg.org/patch/16854/


>  
>  @section hevc_mp4toannexb
> diff --git a/libavcodec/h265_metadata_bsf.c b/libavcodec/h265_metadata_bsf.c
> index b3a1fda..f32ddf0 100644
> --- a/libavcodec/h265_metadata_bsf.c
> +++ b/libavcodec/h265_metadata_bsf.c
> @@ -16,6 +16,7 @@
>   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
>   */
>  
> +#include "libavutil/avstring.h"
>  #include "libavutil/common.h"
>  #include "libavutil/opt.h"
>  
> @@ -23,6 +24,7 @@
>  #include "cbs.h"
>  #include "cbs_h265.h"
>  #include "hevc.h"
> +#include "hevc_sei.h"
>  #include "h265_profile_level.h"
>  
>  enum {
> @@ -65,6 +67,8 @@ typedef struct H265MetadataContext {
>      int crop_top;
>      int crop_bottom;
>  
> +    const char *sei_user_data;
> +
>      int level;
>      int level_guess;
>      int level_warned;
> @@ -340,7 +344,7 @@ static int h265_metadata_filter(AVBSFContext *bsf, AVPacket *pkt)
>  {
>      H265MetadataContext *ctx = bsf->priv_data;
>      CodedBitstreamFragment *au = &ctx->access_unit;
> -    int err, i;
> +    int err, i, j, has_sps = 0, has_vps = 0;
>  
>      err = ff_bsf_get_packet_ref(bsf, pkt);
>      if (err < 0)
> @@ -410,11 +414,67 @@ static int h265_metadata_filter(AVBSFContext *bsf, AVPacket *pkt)
>              err = h265_metadata_update_vps(bsf, au->units[i].content);
>              if (err < 0)
>                  goto fail;
> +            has_vps = 1;
>          }
>          if (au->units[i].type == HEVC_NAL_SPS) {
>              err = h265_metadata_update_sps(bsf, au->units[i].content);
>              if (err < 0)
>                  goto fail;
> +            has_sps = 1;
> +        }
> +    }
> +
> +    // Only insert the SEI in access units containing SPSs or VPSs
> +    if (ctx->sei_user_data && (has_sps || has_vps)) {
> +        H265RawSEIPayload payload = {
> +            .payload_type = HEVC_SEI_TYPE_USER_DATA_UNREGISTERED,
> +        };
> +        H265RawSEIUserDataUnregistered *udu =
> +            &payload.payload.user_data_unregistered;
> +
> +        for (i = j = 0; j < 32 && ctx->sei_user_data[i]; i++) {
> +            int c, v;
> +            c = ctx->sei_user_data[i];
> +            if (c == '-') {
> +                continue;
> +            } else if (av_isxdigit(c)) {
> +                c = av_tolower(c);
> +                v = (c <= '9' ? c - '0' : c - 'a' + 10);
> +            } else {
> +                goto invalid_user_data;
> +            }
> +            if (i & 1)
> +                udu->uuid_iso_iec_11578[j / 2] |= v;
> +            else
> +                udu->uuid_iso_iec_11578[j / 2] = v << 4;
> +            ++j;
> +        }
> +        if (j == 32 && ctx->sei_user_data[i] == '+') {
> +            size_t len = strlen(ctx->sei_user_data + i + 1);
> +
> +            udu->data_ref = av_buffer_alloc(len + 1);
> +            if (!udu->data_ref) {
> +                err = AVERROR(ENOMEM);
> +                goto fail;
> +            }
> +
> +            udu->data        = udu->data_ref->data;
> +            udu->data_length = len + 1;
> +            memcpy(udu->data, ctx->sei_user_data + i + 1, len + 1);
> +
> +            err = ff_cbs_h265_add_sei_prefix_message(ctx->cbc, au, &payload);
> +            if (err < 0) {
> +                av_log(bsf, AV_LOG_ERROR, "Failed to add user data SEI "
> +                       "message to access unit.\n");
> +                goto fail;
> +            }
> +
> +        } else {
> +invalid_user_data:
> +            av_log(bsf, AV_LOG_ERROR, "Invalid user data: "
> +                   "must be \"UUID+string\".\n");
> +            err = AVERROR(EINVAL);
> +            goto fail;
>          }
>      }
>  
> @@ -547,6 +607,9 @@ static const AVOption h265_metadata_options[] = {
>          OFFSET(crop_bottom), AV_OPT_TYPE_INT,
>          { .i64 = -1 }, -1, HEVC_MAX_HEIGHT, FLAGS },
>  
> +    { "sei_user_data", "Insert SEI user data (UUID+string)",
> +        OFFSET(sei_user_data), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS },
> +
>      { "level", "Set level (tables A.6 and A.7)",
>          OFFSET(level), AV_OPT_TYPE_INT,
>          { .i64 = LEVEL_UNSET }, LEVEL_UNSET, 0xff, FLAGS, "level" },
> -- 
> 2.9.5
> 


More information about the ffmpeg-devel mailing list