diff mbox series

[FFmpeg-devel,07/29] lavc: add a decoder option for configuring side data preference

Message ID 20240304130657.30631-7-anton@khirnov.net
State New
Headers show
Series [FFmpeg-devel,01/29] lavu/opt: factor per-type dispatch out of av_opt_get() | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Anton Khirnov March 4, 2024, 1:06 p.m. UTC
This and the following commits fix #10857
---
 doc/APIchanges             |  3 +++
 libavcodec/avcodec.h       | 20 ++++++++++++++++++++
 libavcodec/decode.c        | 36 ++++++++++++++++++++++++++++++++++++
 libavcodec/options_table.h | 13 +++++++++++++
 4 files changed, 72 insertions(+)

Comments

Derek Buitenhuis March 4, 2024, 2:05 p.m. UTC | #1
On 3/4/2024 1:06 PM, Anton Khirnov wrote:
> +    /**
> +     * Decoding only. May be set by the caller before avcodec_open2() to an
> +     * av_malloc()'ed array (or via AVOptions). Owned and freed by the decoder
> +     * afterwards.
> +     *
> +     * By default, when some side data type is present both in global
> +     * user-supplied coded_side_data and inside the coded bitstream, avcodec
> +     * will propagate the latter to the decoded frame.
> +     *
> +     * This array contains a list of AVPacketSideDataType for which this
> +     * preference should be switched, i.e. avcodec will prefer global side data
> +     * over those in stored in the bytestream. It may also contain a single -1,
> +     * in which case the preference is switched for all side data types.
> +     */
> +    int        *side_data_prefer_global;

My only comment is that it would be nice to include some text about what the practical
application of this option is, rather than just technical details. Something like:

    This can be useful, when, for example, input contains data in both the container
    and bitstream.

- Derek
Anton Khirnov March 5, 2024, 9:57 a.m. UTC | #2
Quoting Derek Buitenhuis (2024-03-04 15:05:29)
> On 3/4/2024 1:06 PM, Anton Khirnov wrote:
> > +    /**
> > +     * Decoding only. May be set by the caller before avcodec_open2() to an
> > +     * av_malloc()'ed array (or via AVOptions). Owned and freed by the decoder
> > +     * afterwards.
> > +     *
> > +     * By default, when some side data type is present both in global
> > +     * user-supplied coded_side_data and inside the coded bitstream, avcodec
> > +     * will propagate the latter to the decoded frame.
> > +     *
> > +     * This array contains a list of AVPacketSideDataType for which this
> > +     * preference should be switched, i.e. avcodec will prefer global side data
> > +     * over those in stored in the bytestream. It may also contain a single -1,
> > +     * in which case the preference is switched for all side data types.
> > +     */
> > +    int        *side_data_prefer_global;
> 
> My only comment is that it would be nice to include some text about what the practical
> application of this option is, rather than just technical details. Something like:
> 
>     This can be useful, when, for example, input contains data in both the container
>     and bitstream.

Added text to that effect locally.
James Almer March 5, 2024, 12:30 p.m. UTC | #3
On 3/4/2024 10:06 AM, Anton Khirnov wrote:
> This and the following commits fix #10857
> ---
>   doc/APIchanges             |  3 +++
>   libavcodec/avcodec.h       | 20 ++++++++++++++++++++
>   libavcodec/decode.c        | 36 ++++++++++++++++++++++++++++++++++++
>   libavcodec/options_table.h | 13 +++++++++++++
>   4 files changed, 72 insertions(+)
> 
> diff --git a/doc/APIchanges b/doc/APIchanges
> index 3209614ed6..5d8585d8ba 100644
> --- a/doc/APIchanges
> +++ b/doc/APIchanges
> @@ -2,6 +2,9 @@ The last version increases of all libraries were on 2023-02-09
>   
>   API changes, most recent first:
>   
> +2024-02-xx - xxxxxxxxxx - lavc 60.xx.100 - avcodec.h
> +  Add AVCodecContext.[nb_]side_data_prefer_global.
> +
>   2024-02-xx - xxxxxxxxxx - lavu 58.xx.100 - opt.h
>     Add AV_OPT_TYPE_FLAG_ARRAY and AVOptionArrayDef.
>   
> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> index 43859251cc..307a3e99db 100644
> --- a/libavcodec/avcodec.h
> +++ b/libavcodec/avcodec.h
> @@ -2120,6 +2120,26 @@ typedef struct AVCodecContext {
>        *   an error.
>        */
>       int64_t frame_num;
> +
> +    /**
> +     * Decoding only. May be set by the caller before avcodec_open2() to an
> +     * av_malloc()'ed array (or via AVOptions). Owned and freed by the decoder
> +     * afterwards.
> +     *
> +     * By default, when some side data type is present both in global
> +     * user-supplied coded_side_data and inside the coded bitstream, avcodec
> +     * will propagate the latter to the decoded frame.
> +     *
> +     * This array contains a list of AVPacketSideDataType for which this
> +     * preference should be switched, i.e. avcodec will prefer global side data
> +     * over those in stored in the bytestream. It may also contain a single -1,
> +     * in which case the preference is switched for all side data types.
> +     */
> +    int        *side_data_prefer_global;
> +    /**
> +     * Number of entries in side_data_prefer_global.
> +     */
> +    unsigned nb_side_data_prefer_global;
>   } AVCodecContext;
>   
>   /**
> diff --git a/libavcodec/decode.c b/libavcodec/decode.c
> index 7c67b18bc4..5c80ef9cd0 100644
> --- a/libavcodec/decode.c
> +++ b/libavcodec/decode.c
> @@ -60,6 +60,12 @@ typedef struct DecodeContext {
>        * The caller has submitted a NULL packet on input.
>        */
>       int draining_started;
> +
> +    /**
> +     * Bitmask indicating for which side data types we prefer global
> +     * side data over per-packet.
> +     */
> +    uint64_t side_data_pref_mask;
>   } DecodeContext;
>   
>   static DecodeContext *decode_ctx(AVCodecInternal *avci)
> @@ -1744,6 +1750,7 @@ int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
>   int ff_decode_preinit(AVCodecContext *avctx)
>   {
>       AVCodecInternal *avci = avctx->internal;
> +    DecodeContext     *dc = decode_ctx(avci);
>       int ret = 0;
>   
>       /* if the decoder init function was already called previously,
> @@ -1804,6 +1811,35 @@ int ff_decode_preinit(AVCodecContext *avctx)
>           avctx->export_side_data |= AV_CODEC_EXPORT_DATA_MVS;
>       }
>   
> +    if (avctx->nb_side_data_prefer_global == 1 &&
> +        avctx->side_data_prefer_global[0] == -1)
> +        dc->side_data_pref_mask = ~0ULL;
> +    else {
> +        for (unsigned i = 0; i < avctx->nb_side_data_prefer_global; i++) {
> +            int val = avctx->side_data_prefer_global[i];
> +
> +            if (val < 0 || val >= AV_PKT_DATA_NB) {
> +                av_log(avctx, AV_LOG_ERROR, "Invalid side data type: %d\n", val);
> +                return AVERROR(EINVAL);
> +            }
> +
> +            for (unsigned j = 0; j < FF_ARRAY_ELEMS(sd_global_map); j++) {
> +                if (sd_global_map[j].packet == val) {
> +                    val = sd_global_map[j].frame;
> +
> +                    // this code will need to be changed when we have more than
> +                    // 64 frame side data types
> +                    if (val >= 64) {
> +                        av_log(avctx, AV_LOG_ERROR, "Side data type too big\n");
> +                        return AVERROR_BUG;
> +                    }
> +
> +                    dc->side_data_pref_mask |= 1ULL << val;
> +                }
> +            }
> +        }
> +    }
> +
>       avci->in_pkt         = av_packet_alloc();
>       avci->last_pkt_props = av_packet_alloc();
>       if (!avci->in_pkt || !avci->last_pkt_props)
> diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h
> index ac32d8928a..3ff03d1cf0 100644
> --- a/libavcodec/options_table.h
> +++ b/libavcodec/options_table.h
> @@ -42,6 +42,8 @@
>   #define D AV_OPT_FLAG_DECODING_PARAM
>   #define CC AV_OPT_FLAG_CHILD_CONSTS
>   
> +#define AR AV_OPT_TYPE_FLAG_ARRAY
> +
>   #define AV_CODEC_DEFAULT_BITRATE 200*1000
>   
>   static const AVOption avcodec_options[] = {
> @@ -405,6 +407,17 @@ static const AVOption avcodec_options[] = {
>   {"unsafe_output", "allow potentially unsafe hwaccel frame output that might require special care to process successfully", 0, AV_OPT_TYPE_CONST, {.i64 = AV_HWACCEL_FLAG_UNSAFE_OUTPUT }, INT_MIN, INT_MAX, V | D, .unit = "hwaccel_flags"},
>   {"extra_hw_frames", "Number of extra hardware frames to allocate for the user", OFFSET(extra_hw_frames), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, V|D },
>   {"discard_damaged_percentage", "Percentage of damaged samples to discard a frame", OFFSET(discard_damaged_percentage), AV_OPT_TYPE_INT, {.i64 = 95 }, 0, 100, V|D },
> +{"side_data_prefer_global", "Comma-separated list of side data types for which global headers are preferred over frame-level data",
> +    OFFSET(side_data_prefer_global), AV_OPT_TYPE_INT | AR, .min = -1, .max = INT_MAX, .flags = V|A|S|D, .unit = "side_data_pkt" },
> +    {"replaygain",                  .default_val.i64 = AV_PKT_DATA_REPLAYGAIN,                  .type = AV_OPT_TYPE_CONST, .flags = A|D, .unit = "side_data_pkt" },
> +    {"displaymatrix",               .default_val.i64 = AV_PKT_DATA_DISPLAYMATRIX,               .type = AV_OPT_TYPE_CONST, .flags = A|D, .unit = "side_data_pkt" },
> +    {"spherical",                   .default_val.i64 = AV_PKT_DATA_SPHERICAL,                   .type = AV_OPT_TYPE_CONST, .flags = A|D, .unit = "side_data_pkt" },
> +    {"stereo3d",                    .default_val.i64 = AV_PKT_DATA_STEREO3D,                    .type = AV_OPT_TYPE_CONST, .flags = A|D, .unit = "side_data_pkt" },
> +    {"audio_service_type",          .default_val.i64 = AV_PKT_DATA_AUDIO_SERVICE_TYPE,          .type = AV_OPT_TYPE_CONST, .flags = A|D, .unit = "side_data_pkt" },
> +    {"mastering_display_metadata",  .default_val.i64 = AV_PKT_DATA_MASTERING_DISPLAY_METADATA,  .type = AV_OPT_TYPE_CONST, .flags = A|D, .unit = "side_data_pkt" },
> +    {"content_light_level",         .default_val.i64 = AV_PKT_DATA_CONTENT_LIGHT_LEVEL,         .type = AV_OPT_TYPE_CONST, .flags = A|D, .unit = "side_data_pkt" },
> +    {"icc_profile",                 .default_val.i64 = AV_PKT_DATA_ICC_PROFILE,                 .type = AV_OPT_TYPE_CONST, .flags = A|D, .unit = "side_data_pkt" },

> +    {"dynamic_hdr10_plus",          .default_val.i64 = AV_PKT_DATA_DYNAMIC_HDR10_PLUS,          .type = AV_OPT_TYPE_CONST, .flags = A|D, .unit = "side_data_pkt" },

This one packet/frame level only, not global. Is this option meant to 
also choose which one of those to use?

>   {NULL},
>   };
>
Anton Khirnov March 5, 2024, 2:29 p.m. UTC | #4
Quoting James Almer (2024-03-05 13:30:58)
> > +    {"dynamic_hdr10_plus",          .default_val.i64 = AV_PKT_DATA_DYNAMIC_HDR10_PLUS,          .type = AV_OPT_TYPE_CONST, .flags = A|D, .unit = "side_data_pkt" },
> 
> This one packet/frame level only, not global.

It is in sd_global_map

> Is this option meant to also choose which one of those to use?

???
James Almer March 5, 2024, 2:35 p.m. UTC | #5
On 3/5/2024 11:29 AM, Anton Khirnov wrote:
> Quoting James Almer (2024-03-05 13:30:58)
>>> +    {"dynamic_hdr10_plus",          .default_val.i64 = AV_PKT_DATA_DYNAMIC_HDR10_PLUS,          .type = AV_OPT_TYPE_CONST, .flags = A|D, .unit = "side_data_pkt" },
>>
>> This one packet/frame level only, not global.
> 
> It is in sd_global_map

Then that's a mistake, and I'm probably he culprit. HDR10+ is per frame 
metadata. Static HDR metadata are mastering_display and ccl.

> 
>> Is this option meant to also choose which one of those to use?
> 
> ???

You can have packet side data at the container level that corresponds to 
the same thinga per frame side data at the bitstream level does. In 
HDR10+ case, Matroska may have it in block additional, and then afaik it 
could be present in the hevc bitstream.
One of them should have priority, or the user could be given the choice.
Anton Khirnov March 5, 2024, 2:54 p.m. UTC | #6
Quoting James Almer (2024-03-05 15:35:02)
> On 3/5/2024 11:29 AM, Anton Khirnov wrote:
> > Quoting James Almer (2024-03-05 13:30:58)
> >>> +    {"dynamic_hdr10_plus",          .default_val.i64 = AV_PKT_DATA_DYNAMIC_HDR10_PLUS,          .type = AV_OPT_TYPE_CONST, .flags = A|D, .unit = "side_data_pkt" },
> >>
> >> This one packet/frame level only, not global.
> > 
> > It is in sd_global_map
> 
> Then that's a mistake, and I'm probably he culprit. HDR10+ is per frame 
> metadata. Static HDR metadata are mastering_display and ccl.

Ok, dropped from the options table locally.

> 
> > 
> >> Is this option meant to also choose which one of those to use?
> > 
> > ???
> 
> You can have packet side data at the container level that corresponds to 
> the same thinga per frame side data at the bitstream level does. In 
> HDR10+ case, Matroska may have it in block additional, and then afaik it 
> could be present in the hevc bitstream.
> One of them should have priority, or the user could be given the choice.

Right, I've thought about this a bit, but then couldn't find any side
data types that some container could export per-packet AND could also be
present in the bitstream.

One possible solution is to rename the option to something like
side_data_prefer_external (better names welcome), and have it switch
between user-supplied (i.e. global or per-packet) and in-bitstream side
data.

This adds an ambiguity for the hypothetical case where some side data
exists as global and per-packet - then I'd say lavc should default to
per-packet and leave the other case to the caller (should be very rare,
possibly could be handled with a bitstream filter).
James Almer March 5, 2024, 3:07 p.m. UTC | #7
On 3/5/2024 11:54 AM, Anton Khirnov wrote:
> Quoting James Almer (2024-03-05 15:35:02)
>> On 3/5/2024 11:29 AM, Anton Khirnov wrote:
>>> Quoting James Almer (2024-03-05 13:30:58)
>>>>> +    {"dynamic_hdr10_plus",          .default_val.i64 = AV_PKT_DATA_DYNAMIC_HDR10_PLUS,          .type = AV_OPT_TYPE_CONST, .flags = A|D, .unit = "side_data_pkt" },
>>>>
>>>> This one packet/frame level only, not global.
>>>
>>> It is in sd_global_map
>>
>> Then that's a mistake, and I'm probably he culprit. HDR10+ is per frame
>> metadata. Static HDR metadata are mastering_display and ccl.
> 
> Ok, dropped from the options table locally.
> 
>>
>>>
>>>> Is this option meant to also choose which one of those to use?
>>>
>>> ???
>>
>> You can have packet side data at the container level that corresponds to
>> the same thinga per frame side data at the bitstream level does. In
>> HDR10+ case, Matroska may have it in block additional, and then afaik it
>> could be present in the hevc bitstream.
>> One of them should have priority, or the user could be given the choice.
> 
> Right, I've thought about this a bit, but then couldn't find any side
> data types that some container could export per-packet AND could also be
> present in the bitstream.

Aside from HDR10+, I'm sure this scenario can also happen with closed 
captions.

> 
> One possible solution is to rename the option to something like
> side_data_prefer_external (better names welcome), and have it switch
> between user-supplied (i.e. global or per-packet) and in-bitstream side
> data.
> 
> This adds an ambiguity for the hypothetical case where some side data
> exists as global and per-packet - then I'd say lavc should default to
> per-packet and leave the other case to the caller (should be very rare,
> possibly could be handled with a bitstream filter).

If a given side data type at the container level were to be duplicated 
in the header (global) and per packet, then IMO the packet must have 
priority, given it's the container overriding its own parameters.
Anton Khirnov March 5, 2024, 3:19 p.m. UTC | #8
Quoting James Almer (2024-03-05 16:07:05)
> > 
> > One possible solution is to rename the option to something like
> > side_data_prefer_external (better names welcome), and have it switch
> > between user-supplied (i.e. global or per-packet) and in-bitstream side
> > data.
> > 
> > This adds an ambiguity for the hypothetical case where some side data
> > exists as global and per-packet - then I'd say lavc should default to
> > per-packet and leave the other case to the caller (should be very rare,
> > possibly could be handled with a bitstream filter).
> 
> If a given side data type at the container level were to be duplicated 
> in the header (global) and per packet, then IMO the packet must have 
> priority, given it's the container overriding its own parameters.

I'd be careful with 'must' - in a sane world that's what would be
reasonable, but I can definitely imagine a situation where you'd want
the reverse. But I do agree that it's not something lavc needs to
handle.
diff mbox series

Patch

diff --git a/doc/APIchanges b/doc/APIchanges
index 3209614ed6..5d8585d8ba 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,9 @@  The last version increases of all libraries were on 2023-02-09
 
 API changes, most recent first:
 
+2024-02-xx - xxxxxxxxxx - lavc 60.xx.100 - avcodec.h
+  Add AVCodecContext.[nb_]side_data_prefer_global.
+
 2024-02-xx - xxxxxxxxxx - lavu 58.xx.100 - opt.h
   Add AV_OPT_TYPE_FLAG_ARRAY and AVOptionArrayDef.
 
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 43859251cc..307a3e99db 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -2120,6 +2120,26 @@  typedef struct AVCodecContext {
      *   an error.
      */
     int64_t frame_num;
+
+    /**
+     * Decoding only. May be set by the caller before avcodec_open2() to an
+     * av_malloc()'ed array (or via AVOptions). Owned and freed by the decoder
+     * afterwards.
+     *
+     * By default, when some side data type is present both in global
+     * user-supplied coded_side_data and inside the coded bitstream, avcodec
+     * will propagate the latter to the decoded frame.
+     *
+     * This array contains a list of AVPacketSideDataType for which this
+     * preference should be switched, i.e. avcodec will prefer global side data
+     * over those in stored in the bytestream. It may also contain a single -1,
+     * in which case the preference is switched for all side data types.
+     */
+    int        *side_data_prefer_global;
+    /**
+     * Number of entries in side_data_prefer_global.
+     */
+    unsigned nb_side_data_prefer_global;
 } AVCodecContext;
 
 /**
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index 7c67b18bc4..5c80ef9cd0 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -60,6 +60,12 @@  typedef struct DecodeContext {
      * The caller has submitted a NULL packet on input.
      */
     int draining_started;
+
+    /**
+     * Bitmask indicating for which side data types we prefer global
+     * side data over per-packet.
+     */
+    uint64_t side_data_pref_mask;
 } DecodeContext;
 
 static DecodeContext *decode_ctx(AVCodecInternal *avci)
@@ -1744,6 +1750,7 @@  int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
 int ff_decode_preinit(AVCodecContext *avctx)
 {
     AVCodecInternal *avci = avctx->internal;
+    DecodeContext     *dc = decode_ctx(avci);
     int ret = 0;
 
     /* if the decoder init function was already called previously,
@@ -1804,6 +1811,35 @@  int ff_decode_preinit(AVCodecContext *avctx)
         avctx->export_side_data |= AV_CODEC_EXPORT_DATA_MVS;
     }
 
+    if (avctx->nb_side_data_prefer_global == 1 &&
+        avctx->side_data_prefer_global[0] == -1)
+        dc->side_data_pref_mask = ~0ULL;
+    else {
+        for (unsigned i = 0; i < avctx->nb_side_data_prefer_global; i++) {
+            int val = avctx->side_data_prefer_global[i];
+
+            if (val < 0 || val >= AV_PKT_DATA_NB) {
+                av_log(avctx, AV_LOG_ERROR, "Invalid side data type: %d\n", val);
+                return AVERROR(EINVAL);
+            }
+
+            for (unsigned j = 0; j < FF_ARRAY_ELEMS(sd_global_map); j++) {
+                if (sd_global_map[j].packet == val) {
+                    val = sd_global_map[j].frame;
+
+                    // this code will need to be changed when we have more than
+                    // 64 frame side data types
+                    if (val >= 64) {
+                        av_log(avctx, AV_LOG_ERROR, "Side data type too big\n");
+                        return AVERROR_BUG;
+                    }
+
+                    dc->side_data_pref_mask |= 1ULL << val;
+                }
+            }
+        }
+    }
+
     avci->in_pkt         = av_packet_alloc();
     avci->last_pkt_props = av_packet_alloc();
     if (!avci->in_pkt || !avci->last_pkt_props)
diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h
index ac32d8928a..3ff03d1cf0 100644
--- a/libavcodec/options_table.h
+++ b/libavcodec/options_table.h
@@ -42,6 +42,8 @@ 
 #define D AV_OPT_FLAG_DECODING_PARAM
 #define CC AV_OPT_FLAG_CHILD_CONSTS
 
+#define AR AV_OPT_TYPE_FLAG_ARRAY
+
 #define AV_CODEC_DEFAULT_BITRATE 200*1000
 
 static const AVOption avcodec_options[] = {
@@ -405,6 +407,17 @@  static const AVOption avcodec_options[] = {
 {"unsafe_output", "allow potentially unsafe hwaccel frame output that might require special care to process successfully", 0, AV_OPT_TYPE_CONST, {.i64 = AV_HWACCEL_FLAG_UNSAFE_OUTPUT }, INT_MIN, INT_MAX, V | D, .unit = "hwaccel_flags"},
 {"extra_hw_frames", "Number of extra hardware frames to allocate for the user", OFFSET(extra_hw_frames), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, V|D },
 {"discard_damaged_percentage", "Percentage of damaged samples to discard a frame", OFFSET(discard_damaged_percentage), AV_OPT_TYPE_INT, {.i64 = 95 }, 0, 100, V|D },
+{"side_data_prefer_global", "Comma-separated list of side data types for which global headers are preferred over frame-level data",
+    OFFSET(side_data_prefer_global), AV_OPT_TYPE_INT | AR, .min = -1, .max = INT_MAX, .flags = V|A|S|D, .unit = "side_data_pkt" },
+    {"replaygain",                  .default_val.i64 = AV_PKT_DATA_REPLAYGAIN,                  .type = AV_OPT_TYPE_CONST, .flags = A|D, .unit = "side_data_pkt" },
+    {"displaymatrix",               .default_val.i64 = AV_PKT_DATA_DISPLAYMATRIX,               .type = AV_OPT_TYPE_CONST, .flags = A|D, .unit = "side_data_pkt" },
+    {"spherical",                   .default_val.i64 = AV_PKT_DATA_SPHERICAL,                   .type = AV_OPT_TYPE_CONST, .flags = A|D, .unit = "side_data_pkt" },
+    {"stereo3d",                    .default_val.i64 = AV_PKT_DATA_STEREO3D,                    .type = AV_OPT_TYPE_CONST, .flags = A|D, .unit = "side_data_pkt" },
+    {"audio_service_type",          .default_val.i64 = AV_PKT_DATA_AUDIO_SERVICE_TYPE,          .type = AV_OPT_TYPE_CONST, .flags = A|D, .unit = "side_data_pkt" },
+    {"mastering_display_metadata",  .default_val.i64 = AV_PKT_DATA_MASTERING_DISPLAY_METADATA,  .type = AV_OPT_TYPE_CONST, .flags = A|D, .unit = "side_data_pkt" },
+    {"content_light_level",         .default_val.i64 = AV_PKT_DATA_CONTENT_LIGHT_LEVEL,         .type = AV_OPT_TYPE_CONST, .flags = A|D, .unit = "side_data_pkt" },
+    {"icc_profile",                 .default_val.i64 = AV_PKT_DATA_ICC_PROFILE,                 .type = AV_OPT_TYPE_CONST, .flags = A|D, .unit = "side_data_pkt" },
+    {"dynamic_hdr10_plus",          .default_val.i64 = AV_PKT_DATA_DYNAMIC_HDR10_PLUS,          .type = AV_OPT_TYPE_CONST, .flags = A|D, .unit = "side_data_pkt" },
 {NULL},
 };