diff mbox series

[FFmpeg-devel] libavutil: additional side_data accessor

Message ID 20210420100742.14357-1-bradh@frogmouth.net
State New
Headers show
Series [FFmpeg-devel] libavutil: additional side_data accessor | 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

Brad Hards April 20, 2021, 10:07 a.m. UTC
The existing function allows access the first instance of a given
type. Mostly that is OK, but some types can occur multiple times
(e.g. libx264 can write version info, VANC and UMID related data as
user data unregistered SEI.

This adds API to access additional instances of a given SEI type.
---
 libavutil/frame.c | 19 +++++++++++++++++++
 libavutil/frame.h | 20 ++++++++++++++++++++
 2 files changed, 39 insertions(+)

Comments

Nicolas George April 20, 2021, 10:10 a.m. UTC | #1
Brad Hards (12021-04-20):
> The existing function allows access the first instance of a given
> type. Mostly that is OK, but some types can occur multiple times
> (e.g. libx264 can write version info, VANC and UMID related data as
> user data unregistered SEI.
> 
> This adds API to access additional instances of a given SEI type.
> ---
>  libavutil/frame.c | 19 +++++++++++++++++++
>  libavutil/frame.h | 20 ++++++++++++++++++++
>  2 files changed, 39 insertions(+)

IIRC, there was a discussion a long time ago that concluded that
multiple instances of the same side data should not happen.

Somebody remembers it?

Regards,
James Almer April 20, 2021, 1:16 p.m. UTC | #2
On 4/20/2021 7:10 AM, Nicolas George wrote:
> Brad Hards (12021-04-20):
>> The existing function allows access the first instance of a given
>> type. Mostly that is OK, but some types can occur multiple times
>> (e.g. libx264 can write version info, VANC and UMID related data as
>> user data unregistered SEI.
>>
>> This adds API to access additional instances of a given SEI type.
>> ---
>>   libavutil/frame.c | 19 +++++++++++++++++++
>>   libavutil/frame.h | 20 ++++++++++++++++++++
>>   2 files changed, 39 insertions(+)
> 
> IIRC, there was a discussion a long time ago that concluded that
> multiple instances of the same side data should not happen.
> 
> Somebody remembers it?

I recall long ago i tried to make av_frame_new_side_data() replace the 
existing element if it found one, effectively limiting side data to one 
per type and copying the behavior of packet side data, but it was 
rejected as it was argued more than one per type had some use. And 
seeing that now decoders like h264 may attach more than one element of 
AV_FRAME_DATA_SEI_UNREGISTERED type as contained inside the bitstream 
AUs, it may be a good idea for it to be supported officially with our 
accessors (Right now you need to manually traverse the side data array 
to find all instances of a given type).

> 
> Regards,
> 
> 
> _______________________________________________
> 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".
>
Nicolas George April 20, 2021, 1:17 p.m. UTC | #3
James Almer (12021-04-20):
> I recall long ago i tried to make av_frame_new_side_data() replace the
> existing element if it found one, effectively limiting side data to one per
> type and copying the behavior of packet side data, but it was rejected as it
> was argued more than one per type had some use. And seeing that now decoders
> like h264 may attach more than one element of AV_FRAME_DATA_SEI_UNREGISTERED
> type as contained inside the bitstream AUs, it may be a good idea for it to
> be supported officially with our accessors (Right now you need to manually
> traverse the side data array to find all instances of a given type).

Thanks for the clarification, I remembered it backwards.

Regards,
Brad Hards April 28, 2021, 8:19 a.m. UTC | #4
Ping. Anything more required on this patch?

Brad
diff mbox series

Patch

diff --git a/libavutil/frame.c b/libavutil/frame.c
index 31a2117b82..662fcfd452 100644
--- a/libavutil/frame.c
+++ b/libavutil/frame.c
@@ -748,6 +748,25 @@  AVFrameSideData *av_frame_get_side_data(const AVFrame *frame,
     return NULL;
 }
 
+AVFrameSideData *av_frame_get_side_data_n(const AVFrame *frame,
+                                          enum AVFrameSideDataType type,
+                                          const int side_data_instance)
+{
+    int i;
+    int n = 0;
+
+    for (i = 0; i < frame->nb_side_data; i++) {
+        if (frame->side_data[i]->type == type) {
+            if (n == side_data_instance) {
+                return frame->side_data[i];
+            } else {
+                n++;
+            }
+        }
+    }
+    return NULL;
+}
+
 static int frame_copy_video(AVFrame *dst, const AVFrame *src)
 {
     const uint8_t *src_data[4];
diff --git a/libavutil/frame.h b/libavutil/frame.h
index a5ed91b20a..76dd14cbd5 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -943,12 +943,32 @@  AVFrameSideData *av_frame_new_side_data_from_buf(AVFrame *frame,
                                                  AVBufferRef *buf);
 
 /**
+ * Find the first instance of side data of a given type.
+ *
+ * @param frame a frame to find the side data in
+ * @param type type of the side data to find
+ *
  * @return a pointer to the side data of a given type on success, NULL if there
  * is no side data with such type in this frame.
  */
 AVFrameSideData *av_frame_get_side_data(const AVFrame *frame,
                                         enum AVFrameSideDataType type);
 
+/**
+ * Find a specified instance of side data of a given type.
+ *
+ * @param frame a frame to find the side data in
+ * @param type type of the side data to find
+ * @param side_data_instance instance of the side data to return (0 base).
+ *
+ * @return a pointer to the n'th instance of side data of a given type on
+ * success, NULL if there are less than side_data_instance instances of the
+ * given type.
+ */
+AVFrameSideData *av_frame_get_side_data_n(const AVFrame *frame,
+                                          enum AVFrameSideDataType type,
+                                          const int side_data_instance);
+
 /**
  * Remove and free all side data instances of the given type.
  */