diff mbox series

[FFmpeg-devel,01/27] cbs_h2645: Merge SEI messages in common between codecs

Message ID 20210101213537.169546-2-sw@jkqxz.net
State Superseded
Headers show
Series Metadata handling in CBS | expand

Checks

Context Check Description
andriy/x86_make success Make finished
andriy/x86_make_fate success Make fate finished
andriy/PPC64_make success Make finished
andriy/PPC64_make_fate success Make fate finished

Commit Message

Mark Thompson Jan. 1, 2021, 9:35 p.m. UTC
Make a new template file for common SEI messages - this will also apply
to H.266.
---
 libavcodec/cbs_h264.h                 |  37 +------
 libavcodec/cbs_h2645.c                |  24 +++--
 libavcodec/cbs_h264_syntax_template.c | 106 +-------------------
 libavcodec/cbs_h265.h                 |  45 ++-------
 libavcodec/cbs_h265_syntax_template.c | 135 ++++----------------------
 libavcodec/cbs_sei.h                  |  60 ++++++++++++
 libavcodec/cbs_sei_syntax_template.c  | 132 +++++++++++++++++++++++++
 libavcodec/h264_metadata_bsf.c        |   2 +-
 libavcodec/vaapi_encode_h264.c        |   2 +-
 libavcodec/vaapi_encode_h265.c        |  11 ++-
 10 files changed, 250 insertions(+), 304 deletions(-)
 create mode 100644 libavcodec/cbs_sei.h
 create mode 100644 libavcodec/cbs_sei_syntax_template.c

Comments

Nuo Mi Jan. 4, 2021, 2:32 p.m. UTC | #1
On Sat, Jan 2, 2021 at 5:45 AM Mark Thompson <sw@jkqxz.net> wrote:

> Make a new template file for common SEI messages - this will also apply
> to H.266.
> ---
>  libavcodec/cbs_h264.h                 |  37 +------
>  libavcodec/cbs_h2645.c                |  24 +++--
>  libavcodec/cbs_h264_syntax_template.c | 106 +-------------------
>  libavcodec/cbs_h265.h                 |  45 ++-------
>  libavcodec/cbs_h265_syntax_template.c | 135 ++++----------------------
>  libavcodec/cbs_sei.h                  |  60 ++++++++++++
>  libavcodec/cbs_sei_syntax_template.c  | 132 +++++++++++++++++++++++++
>  libavcodec/h264_metadata_bsf.c        |   2 +-
>  libavcodec/vaapi_encode_h264.c        |   2 +-
>  libavcodec/vaapi_encode_h265.c        |  11 ++-
>  10 files changed, 250 insertions(+), 304 deletions(-)
>  create mode 100644 libavcodec/cbs_sei.h
>  create mode 100644 libavcodec/cbs_sei_syntax_template.c
>
> diff --git a/libavcodec/cbs_h264.h b/libavcodec/cbs_h264.h
> index a6fe0a6af2..81113f1ad0 100644
> --- a/libavcodec/cbs_h264.h
> +++ b/libavcodec/cbs_h264.h
> @@ -24,6 +24,7 @@
>
>  #include "cbs.h"
>  #include "cbs_h2645.h"
> +#include "cbs_sei.h"
>  #include "h264.h"
>
>
> @@ -274,21 +275,6 @@ typedef struct H264RawSEIPanScanRect {
>      uint16_t pan_scan_rect_repetition_period;
>  } H264RawSEIPanScanRect;
>
> -typedef struct H264RawSEIUserDataRegistered {
> -    uint8_t itu_t_t35_country_code;
> -    uint8_t itu_t_t35_country_code_extension_byte;
> -    uint8_t     *data;
> -    AVBufferRef *data_ref;
> -    size_t       data_length;
> -} H264RawSEIUserDataRegistered;
> -
> -typedef struct H264RawSEIUserDataUnregistered {
> -    uint8_t uuid_iso_iec_11578[16];
> -    uint8_t     *data;
> -    AVBufferRef *data_ref;
> -    size_t       data_length;
> -} H264RawSEIUserDataUnregistered;
> -
>  typedef struct H264RawSEIRecoveryPoint {
>      uint16_t recovery_frame_cnt;
>      uint8_t exact_match_flag;
> @@ -305,19 +291,6 @@ typedef struct H264RawSEIDisplayOrientation {
>      uint8_t display_orientation_extension_flag;
>  } H264RawSEIDisplayOrientation;
>
> -typedef struct H264RawSEIMasteringDisplayColourVolume {
> -    uint16_t display_primaries_x[3];
> -    uint16_t display_primaries_y[3];
> -    uint16_t white_point_x;
> -    uint16_t white_point_y;
> -    uint32_t max_display_mastering_luminance;
> -    uint32_t min_display_mastering_luminance;
> -} H264RawSEIMasteringDisplayColourVolume;
> -
> -typedef struct H264RawSEIAlternativeTransferCharacteristics {
> -    uint8_t preferred_transfer_characteristics;
> -} H264RawSEIAlternativeTransferCharacteristics;
> -
>  typedef struct H264RawSEIPayload {
>      uint32_t payload_type;
>      uint32_t payload_size;
> @@ -326,12 +299,12 @@ typedef struct H264RawSEIPayload {
>          H264RawSEIPicTiming pic_timing;
>          H264RawSEIPanScanRect pan_scan_rect;
>          // H264RawSEIFiller filler -> no fields.
> -        H264RawSEIUserDataRegistered user_data_registered;
> -        H264RawSEIUserDataUnregistered user_data_unregistered;
> +        SEIRawUserDataRegistered user_data_registered;
> +        SEIRawUserDataUnregistered user_data_unregistered;
>          H264RawSEIRecoveryPoint recovery_point;
>          H264RawSEIDisplayOrientation display_orientation;
> -        H264RawSEIMasteringDisplayColourVolume
> mastering_display_colour_volume;
> -        H264RawSEIAlternativeTransferCharacteristics
> +        SEIRawMasteringDisplayColourVolume
> mastering_display_colour_volume;
> +        SEIRawAlternativeTransferCharacteristics
>              alternative_transfer_characteristics;
>          struct {
>              uint8_t     *data;
> diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c
> index 434322492c..ce58e47a36 100644
> --- a/libavcodec/cbs_h2645.c
> +++ b/libavcodec/cbs_h2645.c
> @@ -253,9 +253,11 @@ static int
> cbs_h265_payload_extension_present(GetBitContext *gbc, uint32_t paylo
>              return err; \
>      } while (0)
>
> -#define FUNC_NAME(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name
> -#define FUNC_H264(rw, name) FUNC_NAME(rw, h264, name)
> -#define FUNC_H265(rw, name) FUNC_NAME(rw, h265, name)
> +#define FUNC_NAME2(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name
> +#define FUNC_NAME1(rw, codec, name) FUNC_NAME2(rw, codec, name)
> +#define FUNC_H264(name) FUNC_NAME1(READWRITE, h264, name)
> +#define FUNC_H265(name) FUNC_NAME1(READWRITE, h265, name)
> +#define FUNC_SEI(name)  FUNC_NAME1(READWRITE, sei,  name)
>
>  #define SUBSCRIPTS(subs, ...) (subs > 0 ? ((int[subs + 1]){ subs,
> __VA_ARGS__ }) : NULL)
>
> @@ -356,11 +358,15 @@ static int
> cbs_h2645_read_more_rbsp_data(GetBitContext *gbc)
>          name = name ## _ref->data; \
>      } while (0)
>
> -#define FUNC(name) FUNC_H264(READWRITE, name)
> +#define FUNC(name) FUNC_SEI(name)
> +#include "cbs_sei_syntax_template.c"
> +#undef FUNC
> +
> +#define FUNC(name) FUNC_H264(name)
>  #include "cbs_h264_syntax_template.c"
>  #undef FUNC
>
> -#define FUNC(name) FUNC_H265(READWRITE, name)
> +#define FUNC(name) FUNC_H265(name)
>  #include "cbs_h265_syntax_template.c"
>  #undef FUNC
>
> @@ -428,11 +434,15 @@ static int
> cbs_h2645_read_more_rbsp_data(GetBitContext *gbc)
>          } \
>      } while (0)
>
> -#define FUNC(name) FUNC_H264(READWRITE, name)
> +#define FUNC(name) FUNC_SEI(name)
> +#include "cbs_sei_syntax_template.c"
> +#undef FUNC
> +
> +#define FUNC(name) FUNC_H264(name)
>  #include "cbs_h264_syntax_template.c"
>  #undef FUNC
>
> -#define FUNC(name) FUNC_H265(READWRITE, name)
> +#define FUNC(name) FUNC_H265(name)
>  #include "cbs_h265_syntax_template.c"
>  #undef FUNC
>
> diff --git a/libavcodec/cbs_h264_syntax_template.c
> b/libavcodec/cbs_h264_syntax_template.c
> index b65460996b..76ed51cc7b 100644
> --- a/libavcodec/cbs_h264_syntax_template.c
> +++ b/libavcodec/cbs_h264_syntax_template.c
> @@ -700,70 +700,6 @@ static int
> FUNC(sei_pan_scan_rect)(CodedBitstreamContext *ctx, RWContext *rw,
>      return 0;
>  }
>
> -static int FUNC(sei_user_data_registered)(CodedBitstreamContext *ctx,
> RWContext *rw,
> -                                          H264RawSEIUserDataRegistered
> *current,
> -                                          uint32_t *payload_size)
> -{
> -    int err, i, j;
> -
> -    HEADER("User Data Registered ITU-T T.35");
> -
> -    u(8, itu_t_t35_country_code, 0x00, 0xff);
> -    if (current->itu_t_t35_country_code != 0xff)
> -        i = 1;
> -    else {
> -        u(8, itu_t_t35_country_code_extension_byte, 0x00, 0xff);
> -        i = 2;
> -    }
> -
> -#ifdef READ
> -    if (*payload_size < i) {
> -        av_log(ctx->log_ctx, AV_LOG_ERROR,
> -               "Invalid SEI user data registered payload.\n");
> -        return AVERROR_INVALIDDATA;
> -    }
> -    current->data_length = *payload_size - i;
> -#else
> -    *payload_size = i + current->data_length;
> -#endif
> -
> -    allocate(current->data, current->data_length);
> -    for (j = 0; j < current->data_length; j++)
> -        xu(8, itu_t_t35_payload_byte[i], current->data[j], 0x00, 0xff, 1,
> i + j);
>
-
> -    return 0;
> -}
> -
> -static int FUNC(sei_user_data_unregistered)(CodedBitstreamContext *ctx,
> RWContext *rw,
> -
> H264RawSEIUserDataUnregistered *current,
> -                                            uint32_t *payload_size)
> -{
> -    int err, i;
> -
> -    HEADER("User Data Unregistered");
> -
> -#ifdef READ
> -    if (*payload_size < 16) {
> -        av_log(ctx->log_ctx, AV_LOG_ERROR,
> -               "Invalid SEI user data unregistered payload.\n");
> -        return AVERROR_INVALIDDATA;
> -    }
> -    current->data_length = *payload_size - 16;
> -#else
> -    *payload_size = 16 + current->data_length;
> -#endif
> -
> -    for (i = 0; i < 16; i++)
> -        us(8, uuid_iso_iec_11578[i], 0x00, 0xff, 1, i);
> -
> -    allocate(current->data, current->data_length);
> -
> -    for (i = 0; i < current->data_length; i++)
> -        xu(8, user_data_payload_byte[i], current->data[i], 0x00, 0xff, 1,
> i);
>
-
> -    return 0;
> -}
> -
>  static int FUNC(sei_recovery_point)(CodedBitstreamContext *ctx, RWContext
> *rw,
>                                      H264RawSEIRecoveryPoint *current)
>  {
> @@ -798,40 +734,6 @@ static int
> FUNC(sei_display_orientation)(CodedBitstreamContext *ctx, RWContext *
>      return 0;
>  }
>
> -static int
> FUNC(sei_mastering_display_colour_volume)(CodedBitstreamContext *ctx,
> RWContext *rw,
> -
>  H264RawSEIMasteringDisplayColourVolume *current)
> -{
> -    int err, c;
> -
> -    HEADER("Mastering Display Colour Volume");
> -
> -    for (c = 0; c < 3; c++) {
> -        us(16, display_primaries_x[c], 0, 50000, 1, c);
> -        us(16, display_primaries_y[c], 0, 50000, 1, c);
> -    }
> -
> -    u(16, white_point_x, 0, 50000);
> -    u(16, white_point_y, 0, 50000);
> -
> -    u(32, max_display_mastering_luminance, 1, MAX_UINT_BITS(32));
> -    u(32, min_display_mastering_luminance, 0,
> current->max_display_mastering_luminance - 1);
> -
> -    return 0;
> -}
> -
> -static int
> FUNC(sei_alternative_transfer_characteristics)(CodedBitstreamContext *ctx,
> -                                                          RWContext *rw,
> -
> H264RawSEIAlternativeTransferCharacteristics *current)
> -{
> -    int err;
> -
> -    HEADER("Alternative Transfer Characteristics");
> -
> -    ub(8, preferred_transfer_characteristics);
> -
> -    return 0;
> -}
> -
>  static int FUNC(sei_payload)(CodedBitstreamContext *ctx, RWContext *rw,
>                               H264RawSEIPayload *current)
>  {
> @@ -864,11 +766,11 @@ static int FUNC(sei_payload)(CodedBitstreamContext
> *ctx, RWContext *rw,
>          }
>          break;
>      case H264_SEI_TYPE_USER_DATA_REGISTERED:
> -        CHECK(FUNC(sei_user_data_registered)
> +        CHECK(FUNC_SEI(sei_user_data_registered)
>                (ctx, rw, &current->payload.user_data_registered,
> &current->payload_size));
>          break;
>      case H264_SEI_TYPE_USER_DATA_UNREGISTERED:
> -        CHECK(FUNC(sei_user_data_unregistered)
> +        CHECK(FUNC_SEI(sei_user_data_unregistered)
>                (ctx, rw, &current->payload.user_data_unregistered,
> &current->payload_size));
>          break;
>      case H264_SEI_TYPE_RECOVERY_POINT:
> @@ -880,11 +782,11 @@ static int FUNC(sei_payload)(CodedBitstreamContext
> *ctx, RWContext *rw,
>                (ctx, rw, &current->payload.display_orientation));
>          break;
>      case H264_SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME:
> -        CHECK(FUNC(sei_mastering_display_colour_volume)
> +        CHECK(FUNC_SEI(sei_mastering_display_colour_volume)
>                (ctx, rw,
> &current->payload.mastering_display_colour_volume));
>          break;
>      case H264_SEI_TYPE_ALTERNATIVE_TRANSFER:
> -        CHECK(FUNC(sei_alternative_transfer_characteristics)
> +        CHECK(FUNC_SEI(sei_alternative_transfer_characteristics)
>                (ctx, rw,
> &current->payload.alternative_transfer_characteristics));
>          break;
>      default:
> diff --git a/libavcodec/cbs_h265.h b/libavcodec/cbs_h265.h
> index 15b22bbfd4..d8e93e3bb8 100644
> --- a/libavcodec/cbs_h265.h
> +++ b/libavcodec/cbs_h265.h
> @@ -23,6 +23,7 @@
>  #include <stdint.h>
>
>  #include "cbs_h2645.h"
> +#include "cbs_sei.h"
>  #include "hevc.h"
>
>  enum {
> @@ -596,21 +597,6 @@ typedef struct H265RawSEIPanScanRect {
>      uint16_t pan_scan_rect_persistence_flag;
>  } H265RawSEIPanScanRect;
>
> -typedef struct H265RawSEIUserDataRegistered {
> -    uint8_t itu_t_t35_country_code;
> -    uint8_t itu_t_t35_country_code_extension_byte;
> -    uint8_t     *data;
> -    AVBufferRef *data_ref;
> -    size_t       data_length;
> -} H265RawSEIUserDataRegistered;
> -
> -typedef struct H265RawSEIUserDataUnregistered {
> -    uint8_t uuid_iso_iec_11578[16];
> -    uint8_t     *data;
> -    AVBufferRef *data_ref;
> -    size_t       data_length;
> -} H265RawSEIUserDataUnregistered;
> -
>  typedef struct H265RawSEIRecoveryPoint {
>      int16_t recovery_poc_cnt;
>      uint8_t exact_match_flag;
> @@ -661,24 +647,6 @@ typedef struct H265RawSEITimeCode {
>      int32_t  time_offset_value[3];
>  } H265RawSEITimeCode;
>
> -typedef struct H265RawSEIMasteringDisplayColourVolume {
> -    uint16_t display_primaries_x[3];
> -    uint16_t display_primaries_y[3];
> -    uint16_t white_point_x;
> -    uint16_t white_point_y;
> -    uint32_t max_display_mastering_luminance;
> -    uint32_t min_display_mastering_luminance;
> -} H265RawSEIMasteringDisplayColourVolume;
> -
> -typedef struct H265RawSEIContentLightLevelInfo {
> -    uint16_t max_content_light_level;
> -    uint16_t max_pic_average_light_level;
> -} H265RawSEIContentLightLevelInfo;
> -
> -typedef struct H265RawSEIAlternativeTransferCharacteristics {
> -    uint8_t preferred_transfer_characteristics;
> -} H265RawSEIAlternativeTransferCharacteristics;
> -
>  typedef struct H265RawSEIAlphaChannelInfo {
>      uint8_t  alpha_channel_cancel_flag;
>      uint8_t  alpha_channel_use_idc;
> @@ -697,16 +665,17 @@ typedef struct H265RawSEIPayload {
>          H265RawSEIBufferingPeriod buffering_period;
>          H265RawSEIPicTiming pic_timing;
>          H265RawSEIPanScanRect pan_scan_rect;
> -        H265RawSEIUserDataRegistered user_data_registered;
> -        H265RawSEIUserDataUnregistered user_data_unregistered;
> +        SEIRawUserDataRegistered user_data_registered;
> +        SEIRawUserDataUnregistered user_data_unregistered;
>          H265RawSEIRecoveryPoint recovery_point;
>          H265RawSEIDisplayOrientation display_orientation;
>          H265RawSEIActiveParameterSets active_parameter_sets;
>          H265RawSEIDecodedPictureHash decoded_picture_hash;
>          H265RawSEITimeCode time_code;
> -        H265RawSEIMasteringDisplayColourVolume mastering_display;
> -        H265RawSEIContentLightLevelInfo content_light_level;
> -        H265RawSEIAlternativeTransferCharacteristics
> +        SEIRawMasteringDisplayColourVolume
> +            mastering_display_colour_volume;
> +        SEIRawContentLightLevelInfo content_light_level;
> +        SEIRawAlternativeTransferCharacteristics
>              alternative_transfer_characteristics;
>          H265RawSEIAlphaChannelInfo alpha_channel_info;
>          struct {
> diff --git a/libavcodec/cbs_h265_syntax_template.c
> b/libavcodec/cbs_h265_syntax_template.c
> index 48fae82d04..e4cc1a9be8 100644
> --- a/libavcodec/cbs_h265_syntax_template.c
> +++ b/libavcodec/cbs_h265_syntax_template.c
> @@ -1808,70 +1808,6 @@ static int
> FUNC(sei_pan_scan_rect)(CodedBitstreamContext *ctx, RWContext *rw,
>      return 0;
>  }
>
> -static int FUNC(sei_user_data_registered)(CodedBitstreamContext *ctx,
> RWContext *rw,
> -                                          H265RawSEIUserDataRegistered
> *current,
> -                                          uint32_t *payload_size)
> -{
> -    int err, i, j;
> -
> -    HEADER("User Data Registered ITU-T T.35");
> -
> -    u(8, itu_t_t35_country_code, 0x00, 0xff);
> -    if (current->itu_t_t35_country_code != 0xff)
> -        i = 1;
> -    else {
> -        u(8, itu_t_t35_country_code_extension_byte, 0x00, 0xff);
> -        i = 2;
> -    }
> -
> -#ifdef READ
> -    if (*payload_size < i) {
> -        av_log(ctx->log_ctx, AV_LOG_ERROR,
> -               "Invalid SEI user data registered payload.\n");
> -        return AVERROR_INVALIDDATA;
> -    }
> -    current->data_length = *payload_size - i;
> -#else
> -    *payload_size = i + current->data_length;
> -#endif
> -
> -    allocate(current->data, current->data_length);
> -    for (j = 0; j < current->data_length; j++)
> -        xu(8, itu_t_t35_payload_byte[i], current->data[j], 0x00, 0xff, 1,
> i + j);
> -
> -    return 0;
> -}
> -
> -static int FUNC(sei_user_data_unregistered)(CodedBitstreamContext *ctx,
> RWContext *rw,
> -
> H265RawSEIUserDataUnregistered *current,
> -                                            uint32_t *payload_size)
> -{
> -    int err, i;
> -
> -    HEADER("User Data Unregistered");
> -
> -#ifdef READ
> -    if (*payload_size < 16) {
> -        av_log(ctx->log_ctx, AV_LOG_ERROR,
> -               "Invalid SEI user data unregistered payload.\n");
> -        return AVERROR_INVALIDDATA;
> -    }
> -    current->data_length = *payload_size - 16;
> -#else
> -    *payload_size = 16 + current->data_length;
> -#endif
> -
> -    for (i = 0; i < 16; i++)
> -        us(8, uuid_iso_iec_11578[i], 0x00, 0xff, 1, i);
> -
> -    allocate(current->data, current->data_length);
> -
> -    for (i = 0; i < current->data_length; i++)
> -        xu(8, user_data_payload_byte[i], current->data[i], 0x00, 0xff, 1,
> i);
> -
> -    return 0;
> -}
> -
>  static int FUNC(sei_recovery_point)(CodedBitstreamContext *ctx, RWContext
> *rw,
>                                      H265RawSEIRecoveryPoint *current)
>  {
> @@ -2022,55 +1958,6 @@ static int
> FUNC(sei_time_code)(CodedBitstreamContext *ctx, RWContext *rw,
>      return 0;
>  }
>
> -static int FUNC(sei_mastering_display)(CodedBitstreamContext *ctx,
> RWContext *rw,
> -
>  H265RawSEIMasteringDisplayColourVolume *current)
> -{
> -    int err, c;
> -
> -    HEADER("Mastering Display Colour Volume");
> -
> -    for (c = 0; c < 3; c++) {
> -        us(16, display_primaries_x[c], 0, 50000, 1, c);
> -        us(16, display_primaries_y[c], 0, 50000, 1, c);
> -    }
> -
> -    u(16, white_point_x, 0, 50000);
> -    u(16, white_point_y, 0, 50000);
> -
> -    u(32, max_display_mastering_luminance,
> -      1, MAX_UINT_BITS(32));
> -    u(32, min_display_mastering_luminance,
> -      0, current->max_display_mastering_luminance - 1);
> -
> -    return 0;
> -}
> -
> -static int FUNC(sei_content_light_level)(CodedBitstreamContext *ctx,
> RWContext *rw,
> -                                         H265RawSEIContentLightLevelInfo
> *current)
> -{
> -    int err;
> -
> -    HEADER("Content Light Level");
> -
> -    ub(16, max_content_light_level);
> -    ub(16, max_pic_average_light_level);
> -
> -    return 0;
> -}
> -
> -static int
> FUNC(sei_alternative_transfer_characteristics)(CodedBitstreamContext *ctx,
> -                                                          RWContext *rw,
> -
> H265RawSEIAlternativeTransferCharacteristics *current)
> -{
> -    int err;
> -
> -    HEADER("Alternative Transfer Characteristics");
> -
> -    ub(8, preferred_transfer_characteristics);
> -
> -    return 0;
> -}
> -
>  static int FUNC(sei_alpha_channel_info)(CodedBitstreamContext *ctx,
>                                          RWContext *rw,
>                                          H265RawSEIAlphaChannelInfo
> *current)
> @@ -2180,20 +2067,32 @@ static int FUNC(sei_payload)(CodedBitstreamContext
> *ctx, RWContext *rw,
>                                   &more_data)); \
>          break
>
> +#define SEI_TYPE_N2(type, prefix_valid, suffix_valid, name) \
> +    case HEVC_SEI_TYPE_ ## type: \
> +        SEI_TYPE_CHECK_VALID(name, prefix_valid, suffix_valid); \
> +        CHECK(FUNC_SEI(sei_ ## name)(ctx, rw, &current->payload.name)); \
> +        break
> +#define SEI_TYPE_S2(type, prefix_valid, suffix_valid, name) \
> +    case HEVC_SEI_TYPE_ ## type: \
> +        SEI_TYPE_CHECK_VALID(name, prefix_valid, suffix_valid); \
> +        CHECK(FUNC_SEI(sei_ ## name)(ctx, rw, &current->payload.name, \
> +                                     &current->payload_size)); \
> +        break
> +
>          SEI_TYPE_E(BUFFERING_PERIOD,         1, 0, buffering_period);
>          SEI_TYPE_N(PICTURE_TIMING,           1, 0, pic_timing);
>          SEI_TYPE_N(PAN_SCAN_RECT,            1, 0, pan_scan_rect);
> -        SEI_TYPE_S(USER_DATA_REGISTERED_ITU_T_T35,
> +        SEI_TYPE_S2(USER_DATA_REGISTERED_ITU_T_T35,
>                                               1, 1, user_data_registered);
> -        SEI_TYPE_S(USER_DATA_UNREGISTERED,   1, 1,
> user_data_unregistered);
> +        SEI_TYPE_S2(USER_DATA_UNREGISTERED,  1, 1,
> user_data_unregistered);
>          SEI_TYPE_N(RECOVERY_POINT,           1, 0, recovery_point);
>          SEI_TYPE_N(DISPLAY_ORIENTATION,      1, 0, display_orientation);
>          SEI_TYPE_N(ACTIVE_PARAMETER_SETS,    1, 0, active_parameter_sets);
>          SEI_TYPE_N(DECODED_PICTURE_HASH,     0, 1, decoded_picture_hash);
>          SEI_TYPE_N(TIME_CODE,                1, 0, time_code);
> -        SEI_TYPE_N(MASTERING_DISPLAY_INFO,   1, 0, mastering_display);
> -        SEI_TYPE_N(CONTENT_LIGHT_LEVEL_INFO, 1, 0, content_light_level);
> -        SEI_TYPE_N(ALTERNATIVE_TRANSFER_CHARACTERISTICS,
> +        SEI_TYPE_N2(MASTERING_DISPLAY_INFO,  1, 0,
> mastering_display_colour_volume);
> +        SEI_TYPE_N2(CONTENT_LIGHT_LEVEL_INFO,1, 0, content_light_level);
> +        SEI_TYPE_N2(ALTERNATIVE_TRANSFER_CHARACTERISTICS,
>                                               1, 0,
> alternative_transfer_characteristics);
>          SEI_TYPE_N(ALPHA_CHANNEL_INFO,       1, 0, alpha_channel_info);
>
> diff --git a/libavcodec/cbs_sei.h b/libavcodec/cbs_sei.h
> new file mode 100644
> index 0000000000..95beabf4d7
> --- /dev/null
> +++ b/libavcodec/cbs_sei.h
> @@ -0,0 +1,60 @@
> +/*
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * FFmpeg is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> 02110-1301 USA
> + */
> +
> +#ifndef AVCODEC_CBS_SEI_H
> +#define AVCODEC_CBS_SEI_H
> +
> +#include <stddef.h>
> +#include <stdint.h>
> +#include "libavutil/buffer.h"
> +
> +
> +typedef struct SEIRawUserDataRegistered {
> +    uint8_t      itu_t_t35_country_code;
> +    uint8_t      itu_t_t35_country_code_extension_byte;
> +    uint8_t     *data;
> +    AVBufferRef *data_ref;
> +    size_t       data_length;
> +} SEIRawUserDataRegistered;
> +
> +typedef struct SEIRawUserDataUnregistered {
> +    uint8_t      uuid_iso_iec_11578[16];
> +    uint8_t     *data;
> +    AVBufferRef *data_ref;
> +    size_t       data_length;
> +} SEIRawUserDataUnregistered;
> +
> +typedef struct SEIRawMasteringDisplayColourVolume {
> +    uint16_t display_primaries_x[3];
> +    uint16_t display_primaries_y[3];
> +    uint16_t white_point_x;
> +    uint16_t white_point_y;
> +    uint32_t max_display_mastering_luminance;
> +    uint32_t min_display_mastering_luminance;
> +} SEIRawMasteringDisplayColourVolume;
> +
> +typedef struct SEIRawContentLightLevelInfo {
> +    uint16_t max_content_light_level;
> +    uint16_t max_pic_average_light_level;
> +} SEIRawContentLightLevelInfo;
> +
> +typedef struct SEIRawAlternativeTransferCharacteristics {
> +    uint8_t preferred_transfer_characteristics;
> +} SEIRawAlternativeTransferCharacteristics;
> +
> +#endif /* AVCODEC_CBS_SEI_H */
> diff --git a/libavcodec/cbs_sei_syntax_template.c
> b/libavcodec/cbs_sei_syntax_template.c
> new file mode 100644
> index 0000000000..cc900830ae
> --- /dev/null
> +++ b/libavcodec/cbs_sei_syntax_template.c
> @@ -0,0 +1,132 @@
> +/*
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * FFmpeg is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> 02110-1301 USA
> + */
> +
> +static int FUNC(sei_user_data_registered)
> +    (CodedBitstreamContext *ctx, RWContext *rw,
> +     SEIRawUserDataRegistered *current, uint32_t *payload_size)
> +{
> +    int err, i, j;
> +
> +    HEADER("User Data Registered ITU-T T.35");
> +
> +    u(8, itu_t_t35_country_code, 0x00, 0xff);
> +    if (current->itu_t_t35_country_code != 0xff)
> +        i = 1;
> +    else {
> +        u(8, itu_t_t35_country_code_extension_byte, 0x00, 0xff);
> +        i = 2;
> +    }
> +
> +#ifdef READ
> +    if (*payload_size < i) {
> +        av_log(ctx->log_ctx, AV_LOG_ERROR,
> +               "Invalid SEI user data registered payload.\n");
> +        return AVERROR_INVALIDDATA;
> +    }
> +    current->data_length = *payload_size - i;
> +#else
> +    *payload_size = i + current->data_length;
> +#endif
> +
> +    allocate(current->data, current->data_length);
> +    for (j = 0; j < current->data_length; j++)
> +        xu(8, itu_t_t35_payload_byte[i], current->data[j], 0x00, 0xff, 1,
> i + j);
>
although it's just a name, change  itu_t_t35_payload_byte[i] to
itu_t_t35_payload_byte[i+j] maybe better?

> +
> +    return 0;
> +}
> +
> +static int FUNC(sei_user_data_unregistered)
> +    (CodedBitstreamContext *ctx, RWContext *rw,
> +     SEIRawUserDataUnregistered *current, uint32_t *payload_size)
> +{
> +    int err, i;
> +
> +    HEADER("User Data Unregistered");
> +
> +#ifdef READ
> +    if (*payload_size < 16) {
> +        av_log(ctx->log_ctx, AV_LOG_ERROR,
> +               "Invalid SEI user data unregistered payload.\n");
> +        return AVERROR_INVALIDDATA;
> +    }
> +    current->data_length = *payload_size - 16;
> +#else
> +    *payload_size = 16 + current->data_length;
> +#endif
> +
> +    for (i = 0; i < 16; i++)
> +        us(8, uuid_iso_iec_11578[i], 0x00, 0xff, 1, i);
> +
> +    allocate(current->data, current->data_length);
> +
> +    for (i = 0; i < current->data_length; i++)
> +        xu(8, user_data_payload_byte[i], current->data[i], 0x00, 0xff, 1,
> i);
> +
> +    return 0;
> +}
> +
> +static int FUNC(sei_mastering_display_colour_volume)
> +    (CodedBitstreamContext *ctx, RWContext *rw,
> +     SEIRawMasteringDisplayColourVolume *current)
> +{
> +    int err, c;
> +
> +    HEADER("Mastering Display Colour Volume");
> +
> +    for (c = 0; c < 3; c++) {
> +        us(16, display_primaries_x[c], 0, 50000, 1, c);
> +        us(16, display_primaries_y[c], 0, 50000, 1, c);
> +    }
> +
> +    u(16, white_point_x, 0, 50000);
> +    u(16, white_point_y, 0, 50000);
>
could you explain more about the 50000? it's not in spec.

> +
> +    u(32, max_display_mastering_luminance,
> +      1, MAX_UINT_BITS(32));
> +    u(32, min_display_mastering_luminance,
> +      0, current->max_display_mastering_luminance - 1);
> +
> +    return 0;
> +}
> +
> +static int FUNC(sei_content_light_level)
> +    (CodedBitstreamContext *ctx, RWContext *rw,
> +     SEIRawContentLightLevelInfo *current)
> +{
> +    int err;
> +
> +    HEADER("Content Light Level");
> +
> +    ub(16, max_content_light_level);
> +    ub(16, max_pic_average_light_level);
> +
> +    return 0;
> +}
> +
> +static int FUNC(sei_alternative_transfer_characteristics)
> +    (CodedBitstreamContext *ctx, RWContext *rw,
> +     SEIRawAlternativeTransferCharacteristics *current)
> +{
> +    int err;
> +
> +    HEADER("Alternative Transfer Characteristics");
> +
> +    ub(8, preferred_transfer_characteristics);
> +
> +    return 0;
> +}
> diff --git a/libavcodec/h264_metadata_bsf.c
> b/libavcodec/h264_metadata_bsf.c
> index eb1503159b..d7cf58095b 100644
> --- a/libavcodec/h264_metadata_bsf.c
> +++ b/libavcodec/h264_metadata_bsf.c
> @@ -416,7 +416,7 @@ static int h264_metadata_filter(AVBSFContext *bsf,
> AVPacket *pkt)
>          H264RawSEIPayload payload = {
>              .payload_type = H264_SEI_TYPE_USER_DATA_UNREGISTERED,
>          };
> -        H264RawSEIUserDataUnregistered *udu =
> +        SEIRawUserDataUnregistered *udu =
>              &payload.payload.user_data_unregistered;
>
>          for (i = j = 0; j < 32 && ctx->sei_user_data[i]; i++) {
> diff --git a/libavcodec/vaapi_encode_h264.c
> b/libavcodec/vaapi_encode_h264.c
> index e52a0e37a4..b577d09caf 100644
> --- a/libavcodec/vaapi_encode_h264.c
> +++ b/libavcodec/vaapi_encode_h264.c
> @@ -96,7 +96,7 @@ typedef struct VAAPIEncodeH264Context {
>      H264RawSEIBufferingPeriod      sei_buffering_period;
>      H264RawSEIPicTiming            sei_pic_timing;
>      H264RawSEIRecoveryPoint        sei_recovery_point;
> -    H264RawSEIUserDataUnregistered sei_identifier;
> +    SEIRawUserDataUnregistered     sei_identifier;
>      char                          *sei_identifier_string;
>
>      int aud_needed;
> diff --git a/libavcodec/vaapi_encode_h265.c
> b/libavcodec/vaapi_encode_h265.c
> index 3e0af17ea5..a7af763ae4 100644
> --- a/libavcodec/vaapi_encode_h265.c
> +++ b/libavcodec/vaapi_encode_h265.c
> @@ -76,8 +76,8 @@ typedef struct VAAPIEncodeH265Context {
>      H265RawSEI   raw_sei;
>      H265RawSlice raw_slice;
>
> -    H265RawSEIMasteringDisplayColourVolume sei_mastering_display;
> -    H265RawSEIContentLightLevelInfo        sei_content_light_level;
> +    SEIRawMasteringDisplayColourVolume sei_mastering_display;
> +    SEIRawContentLightLevelInfo        sei_content_light_level;
>
>      CodedBitstreamContext *cbc;
>      CodedBitstreamFragment current_access_unit;
> @@ -219,7 +219,8 @@ static int
> vaapi_encode_h265_write_extra_header(AVCodecContext *avctx,
>
>          if (priv->sei_needed & SEI_MASTERING_DISPLAY) {
>              sei->payload[i].payload_type =
> HEVC_SEI_TYPE_MASTERING_DISPLAY_INFO;
> -            sei->payload[i].payload.mastering_display =
> priv->sei_mastering_display;
> +            sei->payload[i].payload.mastering_display_colour_volume =
> +                priv->sei_mastering_display;
>              ++i;
>          }
>
> @@ -781,7 +782,7 @@ static int
> vaapi_encode_h265_init_picture_params(AVCodecContext *avctx,
>
>              // SEI is needed when both the primaries and luminance are set
>              if (mdm->has_primaries && mdm->has_luminance) {
> -                H265RawSEIMasteringDisplayColourVolume *mdcv =
> +                SEIRawMasteringDisplayColourVolume *mdcv =
>                      &priv->sei_mastering_display;
>                  const int mapping[3] = {1, 2, 0};
>                  const int chroma_den = 50000;
> @@ -826,7 +827,7 @@ static int
> vaapi_encode_h265_init_picture_params(AVCodecContext *avctx,
>          if (sd) {
>              AVContentLightMetadata *clm =
>                  (AVContentLightMetadata *)sd->data;
> -            H265RawSEIContentLightLevelInfo *clli =
> +            SEIRawContentLightLevelInfo *clli =
>                  &priv->sei_content_light_level;
>
>              clli->max_content_light_level     = FFMIN(clm->MaxCLL,
> 65535);
> --
> 2.29.2
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
James Almer Jan. 4, 2021, 2:47 p.m. UTC | #2
On 1/4/2021 11:32 AM, Nuo Mi wrote:
>> +static int FUNC(sei_mastering_display_colour_volume)
>> +    (CodedBitstreamContext *ctx, RWContext *rw,
>> +     SEIRawMasteringDisplayColourVolume *current)
>> +{
>> +    int err, c;
>> +
>> +    HEADER("Mastering Display Colour Volume");
>> +
>> +    for (c = 0; c < 3; c++) {
>> +        us(16, display_primaries_x[c], 0, 50000, 1, c);
>> +        us(16, display_primaries_y[c], 0, 50000, 1, c);
>> +    }
>> +
>> +    u(16, white_point_x, 0, 50000);
>> +    u(16, white_point_y, 0, 50000);
>>
> could you explain more about the 50000? it's not in spec.

Check patch 4/27. It was a constrain present in previous revisions of 
the spec.
Nuo Mi Jan. 4, 2021, 4:03 p.m. UTC | #3
Yeah, thanks for the reminder.

On Mon, Jan 4, 2021 at 10:47 PM James Almer <jamrial@gmail.com> wrote:

> On 1/4/2021 11:32 AM, Nuo Mi wrote:
> >> +static int FUNC(sei_mastering_display_colour_volume)
> >> +    (CodedBitstreamContext *ctx, RWContext *rw,
> >> +     SEIRawMasteringDisplayColourVolume *current)
> >> +{
> >> +    int err, c;
> >> +
> >> +    HEADER("Mastering Display Colour Volume");
> >> +
> >> +    for (c = 0; c < 3; c++) {
> >> +        us(16, display_primaries_x[c], 0, 50000, 1, c);
> >> +        us(16, display_primaries_y[c], 0, 50000, 1, c);
> >> +    }
> >> +
> >> +    u(16, white_point_x, 0, 50000);
> >> +    u(16, white_point_y, 0, 50000);
> >>
> > could you explain more about the 50000? it's not in spec.
>
> Check patch 4/27. It was a constrain present in previous revisions of
> the spec.
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Mark Thompson Jan. 6, 2021, 6:45 p.m. UTC | #4
On 04/01/2021 14:32, Nuo Mi wrote:
> On Sat, Jan 2, 2021 at 5:45 AM Mark Thompson <sw@jkqxz.net> wrote:
> 
>> Make a new template file for common SEI messages - this will also apply
>> to H.266.
>> ---
>>   libavcodec/cbs_h264.h                 |  37 +------
>>   libavcodec/cbs_h2645.c                |  24 +++--
>>   libavcodec/cbs_h264_syntax_template.c | 106 +-------------------
>>   libavcodec/cbs_h265.h                 |  45 ++-------
>>   libavcodec/cbs_h265_syntax_template.c | 135 ++++----------------------
>>   libavcodec/cbs_sei.h                  |  60 ++++++++++++
>>   libavcodec/cbs_sei_syntax_template.c  | 132 +++++++++++++++++++++++++
>>   libavcodec/h264_metadata_bsf.c        |   2 +-
>>   libavcodec/vaapi_encode_h264.c        |   2 +-
>>   libavcodec/vaapi_encode_h265.c        |  11 ++-
>>   10 files changed, 250 insertions(+), 304 deletions(-)
>>   create mode 100644 libavcodec/cbs_sei.h
>>   create mode 100644 libavcodec/cbs_sei_syntax_template.c
>>
>> ...
>> +
>> +static int FUNC(sei_user_data_registered)
>> +    (CodedBitstreamContext *ctx, RWContext *rw,
>> +     SEIRawUserDataRegistered *current, uint32_t *payload_size)
>> +{
>> +    int err, i, j;
>> +
>> +    HEADER("User Data Registered ITU-T T.35");
>> +
>> +    u(8, itu_t_t35_country_code, 0x00, 0xff);
>> +    if (current->itu_t_t35_country_code != 0xff)
>> +        i = 1;
>> +    else {
>> +        u(8, itu_t_t35_country_code_extension_byte, 0x00, 0xff);
>> +        i = 2;
>> +    }
>> +
>> +#ifdef READ
>> +    if (*payload_size < i) {
>> +        av_log(ctx->log_ctx, AV_LOG_ERROR,
>> +               "Invalid SEI user data registered payload.\n");
>> +        return AVERROR_INVALIDDATA;
>> +    }
>> +    current->data_length = *payload_size - i;
>> +#else
>> +    *payload_size = i + current->data_length;
>> +#endif
>> +
>> +    allocate(current->data, current->data_length);
>> +    for (j = 0; j < current->data_length; j++)
>> +        xu(8, itu_t_t35_payload_byte[i], current->data[j], 0x00, 0xff, 1,
>> i + j);
>>
> although it's just a name, change  itu_t_t35_payload_byte[i] to
> itu_t_t35_payload_byte[i+j] maybe better?

No, because there is no standard variable called j so it shouldn't be in the string.  i makes the most sense given that i is the loop index, though it's really i - (1 or 2).

Maybe it would cause less confusion to leave the brackets empty?  (After all, that element isn't actually an array, we just write it as one here because it's cleaner.)

>> +
>> +    return 0;
>> +}
>> +

- Mark
diff mbox series

Patch

diff --git a/libavcodec/cbs_h264.h b/libavcodec/cbs_h264.h
index a6fe0a6af2..81113f1ad0 100644
--- a/libavcodec/cbs_h264.h
+++ b/libavcodec/cbs_h264.h
@@ -24,6 +24,7 @@ 
 
 #include "cbs.h"
 #include "cbs_h2645.h"
+#include "cbs_sei.h"
 #include "h264.h"
 
 
@@ -274,21 +275,6 @@  typedef struct H264RawSEIPanScanRect {
     uint16_t pan_scan_rect_repetition_period;
 } H264RawSEIPanScanRect;
 
-typedef struct H264RawSEIUserDataRegistered {
-    uint8_t itu_t_t35_country_code;
-    uint8_t itu_t_t35_country_code_extension_byte;
-    uint8_t     *data;
-    AVBufferRef *data_ref;
-    size_t       data_length;
-} H264RawSEIUserDataRegistered;
-
-typedef struct H264RawSEIUserDataUnregistered {
-    uint8_t uuid_iso_iec_11578[16];
-    uint8_t     *data;
-    AVBufferRef *data_ref;
-    size_t       data_length;
-} H264RawSEIUserDataUnregistered;
-
 typedef struct H264RawSEIRecoveryPoint {
     uint16_t recovery_frame_cnt;
     uint8_t exact_match_flag;
@@ -305,19 +291,6 @@  typedef struct H264RawSEIDisplayOrientation {
     uint8_t display_orientation_extension_flag;
 } H264RawSEIDisplayOrientation;
 
-typedef struct H264RawSEIMasteringDisplayColourVolume {
-    uint16_t display_primaries_x[3];
-    uint16_t display_primaries_y[3];
-    uint16_t white_point_x;
-    uint16_t white_point_y;
-    uint32_t max_display_mastering_luminance;
-    uint32_t min_display_mastering_luminance;
-} H264RawSEIMasteringDisplayColourVolume;
-
-typedef struct H264RawSEIAlternativeTransferCharacteristics {
-    uint8_t preferred_transfer_characteristics;
-} H264RawSEIAlternativeTransferCharacteristics;
-
 typedef struct H264RawSEIPayload {
     uint32_t payload_type;
     uint32_t payload_size;
@@ -326,12 +299,12 @@  typedef struct H264RawSEIPayload {
         H264RawSEIPicTiming pic_timing;
         H264RawSEIPanScanRect pan_scan_rect;
         // H264RawSEIFiller filler -> no fields.
-        H264RawSEIUserDataRegistered user_data_registered;
-        H264RawSEIUserDataUnregistered user_data_unregistered;
+        SEIRawUserDataRegistered user_data_registered;
+        SEIRawUserDataUnregistered user_data_unregistered;
         H264RawSEIRecoveryPoint recovery_point;
         H264RawSEIDisplayOrientation display_orientation;
-        H264RawSEIMasteringDisplayColourVolume mastering_display_colour_volume;
-        H264RawSEIAlternativeTransferCharacteristics
+        SEIRawMasteringDisplayColourVolume mastering_display_colour_volume;
+        SEIRawAlternativeTransferCharacteristics
             alternative_transfer_characteristics;
         struct {
             uint8_t     *data;
diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c
index 434322492c..ce58e47a36 100644
--- a/libavcodec/cbs_h2645.c
+++ b/libavcodec/cbs_h2645.c
@@ -253,9 +253,11 @@  static int cbs_h265_payload_extension_present(GetBitContext *gbc, uint32_t paylo
             return err; \
     } while (0)
 
-#define FUNC_NAME(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name
-#define FUNC_H264(rw, name) FUNC_NAME(rw, h264, name)
-#define FUNC_H265(rw, name) FUNC_NAME(rw, h265, name)
+#define FUNC_NAME2(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name
+#define FUNC_NAME1(rw, codec, name) FUNC_NAME2(rw, codec, name)
+#define FUNC_H264(name) FUNC_NAME1(READWRITE, h264, name)
+#define FUNC_H265(name) FUNC_NAME1(READWRITE, h265, name)
+#define FUNC_SEI(name)  FUNC_NAME1(READWRITE, sei,  name)
 
 #define SUBSCRIPTS(subs, ...) (subs > 0 ? ((int[subs + 1]){ subs, __VA_ARGS__ }) : NULL)
 
@@ -356,11 +358,15 @@  static int cbs_h2645_read_more_rbsp_data(GetBitContext *gbc)
         name = name ## _ref->data; \
     } while (0)
 
-#define FUNC(name) FUNC_H264(READWRITE, name)
+#define FUNC(name) FUNC_SEI(name)
+#include "cbs_sei_syntax_template.c"
+#undef FUNC
+
+#define FUNC(name) FUNC_H264(name)
 #include "cbs_h264_syntax_template.c"
 #undef FUNC
 
-#define FUNC(name) FUNC_H265(READWRITE, name)
+#define FUNC(name) FUNC_H265(name)
 #include "cbs_h265_syntax_template.c"
 #undef FUNC
 
@@ -428,11 +434,15 @@  static int cbs_h2645_read_more_rbsp_data(GetBitContext *gbc)
         } \
     } while (0)
 
-#define FUNC(name) FUNC_H264(READWRITE, name)
+#define FUNC(name) FUNC_SEI(name)
+#include "cbs_sei_syntax_template.c"
+#undef FUNC
+
+#define FUNC(name) FUNC_H264(name)
 #include "cbs_h264_syntax_template.c"
 #undef FUNC
 
-#define FUNC(name) FUNC_H265(READWRITE, name)
+#define FUNC(name) FUNC_H265(name)
 #include "cbs_h265_syntax_template.c"
 #undef FUNC
 
diff --git a/libavcodec/cbs_h264_syntax_template.c b/libavcodec/cbs_h264_syntax_template.c
index b65460996b..76ed51cc7b 100644
--- a/libavcodec/cbs_h264_syntax_template.c
+++ b/libavcodec/cbs_h264_syntax_template.c
@@ -700,70 +700,6 @@  static int FUNC(sei_pan_scan_rect)(CodedBitstreamContext *ctx, RWContext *rw,
     return 0;
 }
 
-static int FUNC(sei_user_data_registered)(CodedBitstreamContext *ctx, RWContext *rw,
-                                          H264RawSEIUserDataRegistered *current,
-                                          uint32_t *payload_size)
-{
-    int err, i, j;
-
-    HEADER("User Data Registered ITU-T T.35");
-
-    u(8, itu_t_t35_country_code, 0x00, 0xff);
-    if (current->itu_t_t35_country_code != 0xff)
-        i = 1;
-    else {
-        u(8, itu_t_t35_country_code_extension_byte, 0x00, 0xff);
-        i = 2;
-    }
-
-#ifdef READ
-    if (*payload_size < i) {
-        av_log(ctx->log_ctx, AV_LOG_ERROR,
-               "Invalid SEI user data registered payload.\n");
-        return AVERROR_INVALIDDATA;
-    }
-    current->data_length = *payload_size - i;
-#else
-    *payload_size = i + current->data_length;
-#endif
-
-    allocate(current->data, current->data_length);
-    for (j = 0; j < current->data_length; j++)
-        xu(8, itu_t_t35_payload_byte[i], current->data[j], 0x00, 0xff, 1, i + j);
-
-    return 0;
-}
-
-static int FUNC(sei_user_data_unregistered)(CodedBitstreamContext *ctx, RWContext *rw,
-                                            H264RawSEIUserDataUnregistered *current,
-                                            uint32_t *payload_size)
-{
-    int err, i;
-
-    HEADER("User Data Unregistered");
-
-#ifdef READ
-    if (*payload_size < 16) {
-        av_log(ctx->log_ctx, AV_LOG_ERROR,
-               "Invalid SEI user data unregistered payload.\n");
-        return AVERROR_INVALIDDATA;
-    }
-    current->data_length = *payload_size - 16;
-#else
-    *payload_size = 16 + current->data_length;
-#endif
-
-    for (i = 0; i < 16; i++)
-        us(8, uuid_iso_iec_11578[i], 0x00, 0xff, 1, i);
-
-    allocate(current->data, current->data_length);
-
-    for (i = 0; i < current->data_length; i++)
-        xu(8, user_data_payload_byte[i], current->data[i], 0x00, 0xff, 1, i);
-
-    return 0;
-}
-
 static int FUNC(sei_recovery_point)(CodedBitstreamContext *ctx, RWContext *rw,
                                     H264RawSEIRecoveryPoint *current)
 {
@@ -798,40 +734,6 @@  static int FUNC(sei_display_orientation)(CodedBitstreamContext *ctx, RWContext *
     return 0;
 }
 
-static int FUNC(sei_mastering_display_colour_volume)(CodedBitstreamContext *ctx, RWContext *rw,
-                                                     H264RawSEIMasteringDisplayColourVolume *current)
-{
-    int err, c;
-
-    HEADER("Mastering Display Colour Volume");
-
-    for (c = 0; c < 3; c++) {
-        us(16, display_primaries_x[c], 0, 50000, 1, c);
-        us(16, display_primaries_y[c], 0, 50000, 1, c);
-    }
-
-    u(16, white_point_x, 0, 50000);
-    u(16, white_point_y, 0, 50000);
-
-    u(32, max_display_mastering_luminance, 1, MAX_UINT_BITS(32));
-    u(32, min_display_mastering_luminance, 0, current->max_display_mastering_luminance - 1);
-
-    return 0;
-}
-
-static int FUNC(sei_alternative_transfer_characteristics)(CodedBitstreamContext *ctx,
-                                                          RWContext *rw,
-                                                          H264RawSEIAlternativeTransferCharacteristics *current)
-{
-    int err;
-
-    HEADER("Alternative Transfer Characteristics");
-
-    ub(8, preferred_transfer_characteristics);
-
-    return 0;
-}
-
 static int FUNC(sei_payload)(CodedBitstreamContext *ctx, RWContext *rw,
                              H264RawSEIPayload *current)
 {
@@ -864,11 +766,11 @@  static int FUNC(sei_payload)(CodedBitstreamContext *ctx, RWContext *rw,
         }
         break;
     case H264_SEI_TYPE_USER_DATA_REGISTERED:
-        CHECK(FUNC(sei_user_data_registered)
+        CHECK(FUNC_SEI(sei_user_data_registered)
               (ctx, rw, &current->payload.user_data_registered, &current->payload_size));
         break;
     case H264_SEI_TYPE_USER_DATA_UNREGISTERED:
-        CHECK(FUNC(sei_user_data_unregistered)
+        CHECK(FUNC_SEI(sei_user_data_unregistered)
               (ctx, rw, &current->payload.user_data_unregistered, &current->payload_size));
         break;
     case H264_SEI_TYPE_RECOVERY_POINT:
@@ -880,11 +782,11 @@  static int FUNC(sei_payload)(CodedBitstreamContext *ctx, RWContext *rw,
               (ctx, rw, &current->payload.display_orientation));
         break;
     case H264_SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME:
-        CHECK(FUNC(sei_mastering_display_colour_volume)
+        CHECK(FUNC_SEI(sei_mastering_display_colour_volume)
               (ctx, rw, &current->payload.mastering_display_colour_volume));
         break;
     case H264_SEI_TYPE_ALTERNATIVE_TRANSFER:
-        CHECK(FUNC(sei_alternative_transfer_characteristics)
+        CHECK(FUNC_SEI(sei_alternative_transfer_characteristics)
               (ctx, rw, &current->payload.alternative_transfer_characteristics));
         break;
     default:
diff --git a/libavcodec/cbs_h265.h b/libavcodec/cbs_h265.h
index 15b22bbfd4..d8e93e3bb8 100644
--- a/libavcodec/cbs_h265.h
+++ b/libavcodec/cbs_h265.h
@@ -23,6 +23,7 @@ 
 #include <stdint.h>
 
 #include "cbs_h2645.h"
+#include "cbs_sei.h"
 #include "hevc.h"
 
 enum {
@@ -596,21 +597,6 @@  typedef struct H265RawSEIPanScanRect {
     uint16_t pan_scan_rect_persistence_flag;
 } H265RawSEIPanScanRect;
 
-typedef struct H265RawSEIUserDataRegistered {
-    uint8_t itu_t_t35_country_code;
-    uint8_t itu_t_t35_country_code_extension_byte;
-    uint8_t     *data;
-    AVBufferRef *data_ref;
-    size_t       data_length;
-} H265RawSEIUserDataRegistered;
-
-typedef struct H265RawSEIUserDataUnregistered {
-    uint8_t uuid_iso_iec_11578[16];
-    uint8_t     *data;
-    AVBufferRef *data_ref;
-    size_t       data_length;
-} H265RawSEIUserDataUnregistered;
-
 typedef struct H265RawSEIRecoveryPoint {
     int16_t recovery_poc_cnt;
     uint8_t exact_match_flag;
@@ -661,24 +647,6 @@  typedef struct H265RawSEITimeCode {
     int32_t  time_offset_value[3];
 } H265RawSEITimeCode;
 
-typedef struct H265RawSEIMasteringDisplayColourVolume {
-    uint16_t display_primaries_x[3];
-    uint16_t display_primaries_y[3];
-    uint16_t white_point_x;
-    uint16_t white_point_y;
-    uint32_t max_display_mastering_luminance;
-    uint32_t min_display_mastering_luminance;
-} H265RawSEIMasteringDisplayColourVolume;
-
-typedef struct H265RawSEIContentLightLevelInfo {
-    uint16_t max_content_light_level;
-    uint16_t max_pic_average_light_level;
-} H265RawSEIContentLightLevelInfo;
-
-typedef struct H265RawSEIAlternativeTransferCharacteristics {
-    uint8_t preferred_transfer_characteristics;
-} H265RawSEIAlternativeTransferCharacteristics;
-
 typedef struct H265RawSEIAlphaChannelInfo {
     uint8_t  alpha_channel_cancel_flag;
     uint8_t  alpha_channel_use_idc;
@@ -697,16 +665,17 @@  typedef struct H265RawSEIPayload {
         H265RawSEIBufferingPeriod buffering_period;
         H265RawSEIPicTiming pic_timing;
         H265RawSEIPanScanRect pan_scan_rect;
-        H265RawSEIUserDataRegistered user_data_registered;
-        H265RawSEIUserDataUnregistered user_data_unregistered;
+        SEIRawUserDataRegistered user_data_registered;
+        SEIRawUserDataUnregistered user_data_unregistered;
         H265RawSEIRecoveryPoint recovery_point;
         H265RawSEIDisplayOrientation display_orientation;
         H265RawSEIActiveParameterSets active_parameter_sets;
         H265RawSEIDecodedPictureHash decoded_picture_hash;
         H265RawSEITimeCode time_code;
-        H265RawSEIMasteringDisplayColourVolume mastering_display;
-        H265RawSEIContentLightLevelInfo content_light_level;
-        H265RawSEIAlternativeTransferCharacteristics
+        SEIRawMasteringDisplayColourVolume
+            mastering_display_colour_volume;
+        SEIRawContentLightLevelInfo content_light_level;
+        SEIRawAlternativeTransferCharacteristics
             alternative_transfer_characteristics;
         H265RawSEIAlphaChannelInfo alpha_channel_info;
         struct {
diff --git a/libavcodec/cbs_h265_syntax_template.c b/libavcodec/cbs_h265_syntax_template.c
index 48fae82d04..e4cc1a9be8 100644
--- a/libavcodec/cbs_h265_syntax_template.c
+++ b/libavcodec/cbs_h265_syntax_template.c
@@ -1808,70 +1808,6 @@  static int FUNC(sei_pan_scan_rect)(CodedBitstreamContext *ctx, RWContext *rw,
     return 0;
 }
 
-static int FUNC(sei_user_data_registered)(CodedBitstreamContext *ctx, RWContext *rw,
-                                          H265RawSEIUserDataRegistered *current,
-                                          uint32_t *payload_size)
-{
-    int err, i, j;
-
-    HEADER("User Data Registered ITU-T T.35");
-
-    u(8, itu_t_t35_country_code, 0x00, 0xff);
-    if (current->itu_t_t35_country_code != 0xff)
-        i = 1;
-    else {
-        u(8, itu_t_t35_country_code_extension_byte, 0x00, 0xff);
-        i = 2;
-    }
-
-#ifdef READ
-    if (*payload_size < i) {
-        av_log(ctx->log_ctx, AV_LOG_ERROR,
-               "Invalid SEI user data registered payload.\n");
-        return AVERROR_INVALIDDATA;
-    }
-    current->data_length = *payload_size - i;
-#else
-    *payload_size = i + current->data_length;
-#endif
-
-    allocate(current->data, current->data_length);
-    for (j = 0; j < current->data_length; j++)
-        xu(8, itu_t_t35_payload_byte[i], current->data[j], 0x00, 0xff, 1, i + j);
-
-    return 0;
-}
-
-static int FUNC(sei_user_data_unregistered)(CodedBitstreamContext *ctx, RWContext *rw,
-                                            H265RawSEIUserDataUnregistered *current,
-                                            uint32_t *payload_size)
-{
-    int err, i;
-
-    HEADER("User Data Unregistered");
-
-#ifdef READ
-    if (*payload_size < 16) {
-        av_log(ctx->log_ctx, AV_LOG_ERROR,
-               "Invalid SEI user data unregistered payload.\n");
-        return AVERROR_INVALIDDATA;
-    }
-    current->data_length = *payload_size - 16;
-#else
-    *payload_size = 16 + current->data_length;
-#endif
-
-    for (i = 0; i < 16; i++)
-        us(8, uuid_iso_iec_11578[i], 0x00, 0xff, 1, i);
-
-    allocate(current->data, current->data_length);
-
-    for (i = 0; i < current->data_length; i++)
-        xu(8, user_data_payload_byte[i], current->data[i], 0x00, 0xff, 1, i);
-
-    return 0;
-}
-
 static int FUNC(sei_recovery_point)(CodedBitstreamContext *ctx, RWContext *rw,
                                     H265RawSEIRecoveryPoint *current)
 {
@@ -2022,55 +1958,6 @@  static int FUNC(sei_time_code)(CodedBitstreamContext *ctx, RWContext *rw,
     return 0;
 }
 
-static int FUNC(sei_mastering_display)(CodedBitstreamContext *ctx, RWContext *rw,
-                                       H265RawSEIMasteringDisplayColourVolume *current)
-{
-    int err, c;
-
-    HEADER("Mastering Display Colour Volume");
-
-    for (c = 0; c < 3; c++) {
-        us(16, display_primaries_x[c], 0, 50000, 1, c);
-        us(16, display_primaries_y[c], 0, 50000, 1, c);
-    }
-
-    u(16, white_point_x, 0, 50000);
-    u(16, white_point_y, 0, 50000);
-
-    u(32, max_display_mastering_luminance,
-      1, MAX_UINT_BITS(32));
-    u(32, min_display_mastering_luminance,
-      0, current->max_display_mastering_luminance - 1);
-
-    return 0;
-}
-
-static int FUNC(sei_content_light_level)(CodedBitstreamContext *ctx, RWContext *rw,
-                                         H265RawSEIContentLightLevelInfo *current)
-{
-    int err;
-
-    HEADER("Content Light Level");
-
-    ub(16, max_content_light_level);
-    ub(16, max_pic_average_light_level);
-
-    return 0;
-}
-
-static int FUNC(sei_alternative_transfer_characteristics)(CodedBitstreamContext *ctx,
-                                                          RWContext *rw,
-                                                          H265RawSEIAlternativeTransferCharacteristics *current)
-{
-    int err;
-
-    HEADER("Alternative Transfer Characteristics");
-
-    ub(8, preferred_transfer_characteristics);
-
-    return 0;
-}
-
 static int FUNC(sei_alpha_channel_info)(CodedBitstreamContext *ctx,
                                         RWContext *rw,
                                         H265RawSEIAlphaChannelInfo *current)
@@ -2180,20 +2067,32 @@  static int FUNC(sei_payload)(CodedBitstreamContext *ctx, RWContext *rw,
                                  &more_data)); \
         break
 
+#define SEI_TYPE_N2(type, prefix_valid, suffix_valid, name) \
+    case HEVC_SEI_TYPE_ ## type: \
+        SEI_TYPE_CHECK_VALID(name, prefix_valid, suffix_valid); \
+        CHECK(FUNC_SEI(sei_ ## name)(ctx, rw, &current->payload.name)); \
+        break
+#define SEI_TYPE_S2(type, prefix_valid, suffix_valid, name) \
+    case HEVC_SEI_TYPE_ ## type: \
+        SEI_TYPE_CHECK_VALID(name, prefix_valid, suffix_valid); \
+        CHECK(FUNC_SEI(sei_ ## name)(ctx, rw, &current->payload.name, \
+                                     &current->payload_size)); \
+        break
+
         SEI_TYPE_E(BUFFERING_PERIOD,         1, 0, buffering_period);
         SEI_TYPE_N(PICTURE_TIMING,           1, 0, pic_timing);
         SEI_TYPE_N(PAN_SCAN_RECT,            1, 0, pan_scan_rect);
-        SEI_TYPE_S(USER_DATA_REGISTERED_ITU_T_T35,
+        SEI_TYPE_S2(USER_DATA_REGISTERED_ITU_T_T35,
                                              1, 1, user_data_registered);
-        SEI_TYPE_S(USER_DATA_UNREGISTERED,   1, 1, user_data_unregistered);
+        SEI_TYPE_S2(USER_DATA_UNREGISTERED,  1, 1, user_data_unregistered);
         SEI_TYPE_N(RECOVERY_POINT,           1, 0, recovery_point);
         SEI_TYPE_N(DISPLAY_ORIENTATION,      1, 0, display_orientation);
         SEI_TYPE_N(ACTIVE_PARAMETER_SETS,    1, 0, active_parameter_sets);
         SEI_TYPE_N(DECODED_PICTURE_HASH,     0, 1, decoded_picture_hash);
         SEI_TYPE_N(TIME_CODE,                1, 0, time_code);
-        SEI_TYPE_N(MASTERING_DISPLAY_INFO,   1, 0, mastering_display);
-        SEI_TYPE_N(CONTENT_LIGHT_LEVEL_INFO, 1, 0, content_light_level);
-        SEI_TYPE_N(ALTERNATIVE_TRANSFER_CHARACTERISTICS,
+        SEI_TYPE_N2(MASTERING_DISPLAY_INFO,  1, 0, mastering_display_colour_volume);
+        SEI_TYPE_N2(CONTENT_LIGHT_LEVEL_INFO,1, 0, content_light_level);
+        SEI_TYPE_N2(ALTERNATIVE_TRANSFER_CHARACTERISTICS,
                                              1, 0, alternative_transfer_characteristics);
         SEI_TYPE_N(ALPHA_CHANNEL_INFO,       1, 0, alpha_channel_info);
 
diff --git a/libavcodec/cbs_sei.h b/libavcodec/cbs_sei.h
new file mode 100644
index 0000000000..95beabf4d7
--- /dev/null
+++ b/libavcodec/cbs_sei.h
@@ -0,0 +1,60 @@ 
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_CBS_SEI_H
+#define AVCODEC_CBS_SEI_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include "libavutil/buffer.h"
+
+
+typedef struct SEIRawUserDataRegistered {
+    uint8_t      itu_t_t35_country_code;
+    uint8_t      itu_t_t35_country_code_extension_byte;
+    uint8_t     *data;
+    AVBufferRef *data_ref;
+    size_t       data_length;
+} SEIRawUserDataRegistered;
+
+typedef struct SEIRawUserDataUnregistered {
+    uint8_t      uuid_iso_iec_11578[16];
+    uint8_t     *data;
+    AVBufferRef *data_ref;
+    size_t       data_length;
+} SEIRawUserDataUnregistered;
+
+typedef struct SEIRawMasteringDisplayColourVolume {
+    uint16_t display_primaries_x[3];
+    uint16_t display_primaries_y[3];
+    uint16_t white_point_x;
+    uint16_t white_point_y;
+    uint32_t max_display_mastering_luminance;
+    uint32_t min_display_mastering_luminance;
+} SEIRawMasteringDisplayColourVolume;
+
+typedef struct SEIRawContentLightLevelInfo {
+    uint16_t max_content_light_level;
+    uint16_t max_pic_average_light_level;
+} SEIRawContentLightLevelInfo;
+
+typedef struct SEIRawAlternativeTransferCharacteristics {
+    uint8_t preferred_transfer_characteristics;
+} SEIRawAlternativeTransferCharacteristics;
+
+#endif /* AVCODEC_CBS_SEI_H */
diff --git a/libavcodec/cbs_sei_syntax_template.c b/libavcodec/cbs_sei_syntax_template.c
new file mode 100644
index 0000000000..cc900830ae
--- /dev/null
+++ b/libavcodec/cbs_sei_syntax_template.c
@@ -0,0 +1,132 @@ 
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+static int FUNC(sei_user_data_registered)
+    (CodedBitstreamContext *ctx, RWContext *rw,
+     SEIRawUserDataRegistered *current, uint32_t *payload_size)
+{
+    int err, i, j;
+
+    HEADER("User Data Registered ITU-T T.35");
+
+    u(8, itu_t_t35_country_code, 0x00, 0xff);
+    if (current->itu_t_t35_country_code != 0xff)
+        i = 1;
+    else {
+        u(8, itu_t_t35_country_code_extension_byte, 0x00, 0xff);
+        i = 2;
+    }
+
+#ifdef READ
+    if (*payload_size < i) {
+        av_log(ctx->log_ctx, AV_LOG_ERROR,
+               "Invalid SEI user data registered payload.\n");
+        return AVERROR_INVALIDDATA;
+    }
+    current->data_length = *payload_size - i;
+#else
+    *payload_size = i + current->data_length;
+#endif
+
+    allocate(current->data, current->data_length);
+    for (j = 0; j < current->data_length; j++)
+        xu(8, itu_t_t35_payload_byte[i], current->data[j], 0x00, 0xff, 1, i + j);
+
+    return 0;
+}
+
+static int FUNC(sei_user_data_unregistered)
+    (CodedBitstreamContext *ctx, RWContext *rw,
+     SEIRawUserDataUnregistered *current, uint32_t *payload_size)
+{
+    int err, i;
+
+    HEADER("User Data Unregistered");
+
+#ifdef READ
+    if (*payload_size < 16) {
+        av_log(ctx->log_ctx, AV_LOG_ERROR,
+               "Invalid SEI user data unregistered payload.\n");
+        return AVERROR_INVALIDDATA;
+    }
+    current->data_length = *payload_size - 16;
+#else
+    *payload_size = 16 + current->data_length;
+#endif
+
+    for (i = 0; i < 16; i++)
+        us(8, uuid_iso_iec_11578[i], 0x00, 0xff, 1, i);
+
+    allocate(current->data, current->data_length);
+
+    for (i = 0; i < current->data_length; i++)
+        xu(8, user_data_payload_byte[i], current->data[i], 0x00, 0xff, 1, i);
+
+    return 0;
+}
+
+static int FUNC(sei_mastering_display_colour_volume)
+    (CodedBitstreamContext *ctx, RWContext *rw,
+     SEIRawMasteringDisplayColourVolume *current)
+{
+    int err, c;
+
+    HEADER("Mastering Display Colour Volume");
+
+    for (c = 0; c < 3; c++) {
+        us(16, display_primaries_x[c], 0, 50000, 1, c);
+        us(16, display_primaries_y[c], 0, 50000, 1, c);
+    }
+
+    u(16, white_point_x, 0, 50000);
+    u(16, white_point_y, 0, 50000);
+
+    u(32, max_display_mastering_luminance,
+      1, MAX_UINT_BITS(32));
+    u(32, min_display_mastering_luminance,
+      0, current->max_display_mastering_luminance - 1);
+
+    return 0;
+}
+
+static int FUNC(sei_content_light_level)
+    (CodedBitstreamContext *ctx, RWContext *rw,
+     SEIRawContentLightLevelInfo *current)
+{
+    int err;
+
+    HEADER("Content Light Level");
+
+    ub(16, max_content_light_level);
+    ub(16, max_pic_average_light_level);
+
+    return 0;
+}
+
+static int FUNC(sei_alternative_transfer_characteristics)
+    (CodedBitstreamContext *ctx, RWContext *rw,
+     SEIRawAlternativeTransferCharacteristics *current)
+{
+    int err;
+
+    HEADER("Alternative Transfer Characteristics");
+
+    ub(8, preferred_transfer_characteristics);
+
+    return 0;
+}
diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c
index eb1503159b..d7cf58095b 100644
--- a/libavcodec/h264_metadata_bsf.c
+++ b/libavcodec/h264_metadata_bsf.c
@@ -416,7 +416,7 @@  static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *pkt)
         H264RawSEIPayload payload = {
             .payload_type = H264_SEI_TYPE_USER_DATA_UNREGISTERED,
         };
-        H264RawSEIUserDataUnregistered *udu =
+        SEIRawUserDataUnregistered *udu =
             &payload.payload.user_data_unregistered;
 
         for (i = j = 0; j < 32 && ctx->sei_user_data[i]; i++) {
diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c
index e52a0e37a4..b577d09caf 100644
--- a/libavcodec/vaapi_encode_h264.c
+++ b/libavcodec/vaapi_encode_h264.c
@@ -96,7 +96,7 @@  typedef struct VAAPIEncodeH264Context {
     H264RawSEIBufferingPeriod      sei_buffering_period;
     H264RawSEIPicTiming            sei_pic_timing;
     H264RawSEIRecoveryPoint        sei_recovery_point;
-    H264RawSEIUserDataUnregistered sei_identifier;
+    SEIRawUserDataUnregistered     sei_identifier;
     char                          *sei_identifier_string;
 
     int aud_needed;
diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c
index 3e0af17ea5..a7af763ae4 100644
--- a/libavcodec/vaapi_encode_h265.c
+++ b/libavcodec/vaapi_encode_h265.c
@@ -76,8 +76,8 @@  typedef struct VAAPIEncodeH265Context {
     H265RawSEI   raw_sei;
     H265RawSlice raw_slice;
 
-    H265RawSEIMasteringDisplayColourVolume sei_mastering_display;
-    H265RawSEIContentLightLevelInfo        sei_content_light_level;
+    SEIRawMasteringDisplayColourVolume sei_mastering_display;
+    SEIRawContentLightLevelInfo        sei_content_light_level;
 
     CodedBitstreamContext *cbc;
     CodedBitstreamFragment current_access_unit;
@@ -219,7 +219,8 @@  static int vaapi_encode_h265_write_extra_header(AVCodecContext *avctx,
 
         if (priv->sei_needed & SEI_MASTERING_DISPLAY) {
             sei->payload[i].payload_type = HEVC_SEI_TYPE_MASTERING_DISPLAY_INFO;
-            sei->payload[i].payload.mastering_display = priv->sei_mastering_display;
+            sei->payload[i].payload.mastering_display_colour_volume =
+                priv->sei_mastering_display;
             ++i;
         }
 
@@ -781,7 +782,7 @@  static int vaapi_encode_h265_init_picture_params(AVCodecContext *avctx,
 
             // SEI is needed when both the primaries and luminance are set
             if (mdm->has_primaries && mdm->has_luminance) {
-                H265RawSEIMasteringDisplayColourVolume *mdcv =
+                SEIRawMasteringDisplayColourVolume *mdcv =
                     &priv->sei_mastering_display;
                 const int mapping[3] = {1, 2, 0};
                 const int chroma_den = 50000;
@@ -826,7 +827,7 @@  static int vaapi_encode_h265_init_picture_params(AVCodecContext *avctx,
         if (sd) {
             AVContentLightMetadata *clm =
                 (AVContentLightMetadata *)sd->data;
-            H265RawSEIContentLightLevelInfo *clli =
+            SEIRawContentLightLevelInfo *clli =
                 &priv->sei_content_light_level;
 
             clli->max_content_light_level     = FFMIN(clm->MaxCLL,  65535);