diff mbox series

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

Message ID 20240223143115.16521-17-anton@khirnov.net
State New
Headers show
Series [FFmpeg-devel,01/38] lavu/opt: cosmetics, change option flags to (1 << N) style | expand

Checks

Context Check Description
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Anton Khirnov Feb. 23, 2024, 1:58 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 | 12 ++++++++++++
 4 files changed, 71 insertions(+)

Comments

Marton Balint Feb. 23, 2024, 5:51 p.m. UTC | #1
On Fri, 23 Feb 2024, 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 | 12 ++++++++++++
> 4 files changed, 71 insertions(+)
>
> diff --git a/doc/APIchanges b/doc/APIchanges
> index 371fd2f465..78744a674a 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_FLAG_ARRAY and AVOption.array_max_size.
>
> 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;

Why is this a list and AV_OPT_FLAG_ARRAY? This simply should be a mask, so 
AV_OPT_TYPE_FLAGS.

Regards,
Marton
James Almer Feb. 23, 2024, 5:53 p.m. UTC | #2
On 2/23/2024 2:51 PM, Marton Balint wrote:
> 
> 
> On Fri, 23 Feb 2024, 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 | 12 ++++++++++++
>> 4 files changed, 71 insertions(+)
>>
>> diff --git a/doc/APIchanges b/doc/APIchanges
>> index 371fd2f465..78744a674a 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_FLAG_ARRAY and AVOption.array_max_size.
>>
>> 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;
> 
> Why is this a list and AV_OPT_FLAG_ARRAY? This simply should be a mask, 
> so AV_OPT_TYPE_FLAGS.

That would effectively limit side data element types to 64.
James Almer Feb. 23, 2024, 6:34 p.m. UTC | #3
On 2/23/2024 2:53 PM, James Almer wrote:
> On 2/23/2024 2:51 PM, Marton Balint wrote:
>>
>>
>> On Fri, 23 Feb 2024, 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 | 12 ++++++++++++
>>> 4 files changed, 71 insertions(+)
>>>
>>> diff --git a/doc/APIchanges b/doc/APIchanges
>>> index 371fd2f465..78744a674a 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_FLAG_ARRAY and AVOption.array_max_size.
>>>
>>> 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;
>>
>> Why is this a list and AV_OPT_FLAG_ARRAY? This simply should be a 
>> mask, so AV_OPT_TYPE_FLAGS.
> 
> That would effectively limit side data element types to 64.

Actually no, it'd be 32 since _FLAGS expects an unsigned int.
Anton Khirnov Feb. 26, 2024, 5:08 p.m. UTC | #4
Quoting James Almer (2024-02-23 19:34:51)
> Actually no, it'd be 32 since _FLAGS expects an unsigned int.

And we currently have 36 packet side data types.

Now this option can only apply to some of them, but then we'd have to
introduce some kind a of a complicated mapping scheme, and we still end
up with a rather low limit.
diff mbox series

Patch

diff --git a/doc/APIchanges b/doc/APIchanges
index 371fd2f465..78744a674a 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_FLAG_ARRAY and AVOption.array_max_size.
 
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 da6446d879..5524e229c2 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..2f4f60218c 100644
--- a/libavcodec/options_table.h
+++ b/libavcodec/options_table.h
@@ -41,6 +41,7 @@ 
 #define E AV_OPT_FLAG_ENCODING_PARAM
 #define D AV_OPT_FLAG_DECODING_PARAM
 #define CC AV_OPT_FLAG_CHILD_CONSTS
+#define AR AV_OPT_FLAG_ARRAY
 
 #define AV_CODEC_DEFAULT_BITRATE 200*1000
 
@@ -405,6 +406,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, .min = -1, .max = INT_MAX, .flags = V|A|S|D|AR, .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},
 };