Re: [FFmpeg-devel] [PATCH 1/7 v4] avutil/frame: add a flag to allow overwritting existing entries

2024-03-28 Thread James Almer

On 3/28/2024 9:21 AM, Anton Khirnov wrote:

Quoting James Almer (2024-03-28 12:41:40)

On 3/28/2024 8:23 AM, Anton Khirnov wrote:

Quoting James Almer (2024-03-28 04:12:04)

Enable it only for side data types that don't allow more than one entry.

Signed-off-by: James Almer 
---
   libavutil/frame.c | 59 ---
   libavutil/frame.h | 27 +-
   libavutil/tests/side_data_array.c | 52 +++
   tests/ref/fate/side_data_array| 22 ++--
   4 files changed, 115 insertions(+), 45 deletions(-)

diff --git a/libavutil/frame.c b/libavutil/frame.c
index ef1613c344..d9bd19b2aa 100644
--- a/libavutil/frame.c
+++ b/libavutil/frame.c
@@ -799,12 +799,34 @@ AVFrameSideData *av_frame_side_data_new(AVFrameSideData 
***sd, int *nb_sd,
   enum AVFrameSideDataType type,
   size_t size, unsigned int flags)
   {
-AVBufferRef *buf = av_buffer_alloc(size);
+const AVSideDataDescriptor *desc = av_frame_side_data_desc(type);
+AVBufferRef *buf;
   AVFrameSideData *ret = NULL;
   
   if (flags & AV_FRAME_SIDE_DATA_FLAG_UNIQUE)

   remove_side_data(sd, nb_sd, type);
+if (!desc || !(desc->props & AV_SIDE_DATA_PROP_MULTI)) {


desc == NULL means type is invalid


This being a generic alloc function, it should IMO not be limited to
currently defined types. And I chose to treat them as non multi, as
that's the most common scenario.


Andreas argued in the thread adding descriptors that side data type
without a descriptor is invalid and should explode. I tend to agree.


I agree with that when you're handling side data that comes from 
something like a filter or similar modules within our libraries, as 
that'd be a bug. But this is the public core API for side data, and i 
don't see a reason why we should fail if the caller does 
av_frame_side_data_new(, _sd, 1000, 1, 0);. We never did before, 
and doing it now feels wrong.

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


Re: [FFmpeg-devel] [PATCH 1/7 v4] avutil/frame: add a flag to allow overwritting existing entries

2024-03-28 Thread Anton Khirnov
Quoting James Almer (2024-03-28 12:41:40)
> On 3/28/2024 8:23 AM, Anton Khirnov wrote:
> > Quoting James Almer (2024-03-28 04:12:04)
> >> Enable it only for side data types that don't allow more than one entry.
> >>
> >> Signed-off-by: James Almer 
> >> ---
> >>   libavutil/frame.c | 59 ---
> >>   libavutil/frame.h | 27 +-
> >>   libavutil/tests/side_data_array.c | 52 +++
> >>   tests/ref/fate/side_data_array| 22 ++--
> >>   4 files changed, 115 insertions(+), 45 deletions(-)
> >>
> >> diff --git a/libavutil/frame.c b/libavutil/frame.c
> >> index ef1613c344..d9bd19b2aa 100644
> >> --- a/libavutil/frame.c
> >> +++ b/libavutil/frame.c
> >> @@ -799,12 +799,34 @@ AVFrameSideData 
> >> *av_frame_side_data_new(AVFrameSideData ***sd, int *nb_sd,
> >>   enum AVFrameSideDataType type,
> >>   size_t size, unsigned int flags)
> >>   {
> >> -AVBufferRef *buf = av_buffer_alloc(size);
> >> +const AVSideDataDescriptor *desc = av_frame_side_data_desc(type);
> >> +AVBufferRef *buf;
> >>   AVFrameSideData *ret = NULL;
> >>   
> >>   if (flags & AV_FRAME_SIDE_DATA_FLAG_UNIQUE)
> >>   remove_side_data(sd, nb_sd, type);
> >> +if (!desc || !(desc->props & AV_SIDE_DATA_PROP_MULTI)) {
> > 
> > desc == NULL means type is invalid
> 
> This being a generic alloc function, it should IMO not be limited to 
> currently defined types. And I chose to treat them as non multi, as 
> that's the most common scenario.

Andreas argued in the thread adding descriptors that side data type
without a descriptor is invalid and should explode. I tend to agree.

-- 
Anton Khirnov
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


Re: [FFmpeg-devel] [PATCH 1/7 v4] avutil/frame: add a flag to allow overwritting existing entries

2024-03-28 Thread James Almer

On 3/28/2024 8:23 AM, Anton Khirnov wrote:

Quoting James Almer (2024-03-28 04:12:04)

Enable it only for side data types that don't allow more than one entry.

Signed-off-by: James Almer 
---
  libavutil/frame.c | 59 ---
  libavutil/frame.h | 27 +-
  libavutil/tests/side_data_array.c | 52 +++
  tests/ref/fate/side_data_array| 22 ++--
  4 files changed, 115 insertions(+), 45 deletions(-)

diff --git a/libavutil/frame.c b/libavutil/frame.c
index ef1613c344..d9bd19b2aa 100644
--- a/libavutil/frame.c
+++ b/libavutil/frame.c
@@ -799,12 +799,34 @@ AVFrameSideData *av_frame_side_data_new(AVFrameSideData 
***sd, int *nb_sd,
  enum AVFrameSideDataType type,
  size_t size, unsigned int flags)
  {
-AVBufferRef *buf = av_buffer_alloc(size);
+const AVSideDataDescriptor *desc = av_frame_side_data_desc(type);
+AVBufferRef *buf;
  AVFrameSideData *ret = NULL;
  
  if (flags & AV_FRAME_SIDE_DATA_FLAG_UNIQUE)

  remove_side_data(sd, nb_sd, type);
+if (!desc || !(desc->props & AV_SIDE_DATA_PROP_MULTI)) {


desc == NULL means type is invalid


This being a generic alloc function, it should IMO not be limited to 
currently defined types. And I chose to treat them as non multi, as 
that's the most common scenario.





+for (int i = 0; i < *nb_sd; i++) {
+AVFrameSideData *entry = ((*sd)[i]);
+if (entry->type != type)
+continue;


Why are you not calling av_frame_side_data_get()?


An oversight i guess :p




@@ -822,13 +845,41 @@ int av_frame_side_data_clone(AVFrameSideData ***sd, int 
*nb_sd,
  if (!sd || !src || !nb_sd || (*nb_sd && !*sd))
  return AVERROR(EINVAL);
  
+desc = av_frame_side_data_desc(src->type);

+if (flags & AV_FRAME_SIDE_DATA_FLAG_UNIQUE)
+remove_side_data(sd, nb_sd, src->type);
+if (!desc || !(desc->props & AV_SIDE_DATA_PROP_MULTI)) {
+for (int i = 0; i < *nb_sd; i++) {
+AVFrameSideData *entry = ((*sd)[i]);
+AVDictionary *dict = NULL;
+
+if (entry->type != src->type)
+continue;
+if (!(flags & AV_FRAME_SIDE_DATA_FLAG_REPLACE))
+return AVERROR(EEXIST);
+
+ret = av_dict_copy(, src->metadata, 0);
+if (ret < 0)
+return ret;
+
+ret = av_buffer_replace(>buf, src->buf);
+if (ret < 0) {
+av_dict_free();
+return ret;
+}
+
+av_dict_free(>metadata);
+entry->metadata = dict;
+entry->data = src->data;
+entry->size = src->size;
+return 0;
+}


This whole block looks very similar to the one you're adding to
av_frame_side_data_new().


I can try to factorize it.




+}
+
  buf = av_buffer_ref(src->buf);
  if (!buf)
  return AVERROR(ENOMEM);
  
-if (flags & AV_FRAME_SIDE_DATA_FLAG_UNIQUE)

-remove_side_data(sd, nb_sd, src->type);
-
  sd_dst = add_side_data_from_buf(sd, nb_sd, src->type, buf);
  if (!sd_dst) {
  av_buffer_unref();
diff --git a/libavutil/frame.h b/libavutil/frame.h
index 3b6d746a16..2ea129888e 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -1040,7 +1040,14 @@ const AVSideDataDescriptor *av_frame_side_data_desc(enum 
AVFrameSideDataType typ
   */
  void av_frame_side_data_free(AVFrameSideData ***sd, int *nb_sd);
  
+/**

+ * Remove existing entries before adding new ones.
+ */
  #define AV_FRAME_SIDE_DATA_FLAG_UNIQUE (1 << 0)
+/**
+ * Don't add a new entry if another of the same type exists.


This should mention that it only applies to MULTI side data types.


Ok.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


Re: [FFmpeg-devel] [PATCH 1/7 v4] avutil/frame: add a flag to allow overwritting existing entries

2024-03-28 Thread Anton Khirnov
Quoting James Almer (2024-03-28 04:12:04)
> Enable it only for side data types that don't allow more than one entry.
> 
> Signed-off-by: James Almer 
> ---
>  libavutil/frame.c | 59 ---
>  libavutil/frame.h | 27 +-
>  libavutil/tests/side_data_array.c | 52 +++
>  tests/ref/fate/side_data_array| 22 ++--
>  4 files changed, 115 insertions(+), 45 deletions(-)
> 
> diff --git a/libavutil/frame.c b/libavutil/frame.c
> index ef1613c344..d9bd19b2aa 100644
> --- a/libavutil/frame.c
> +++ b/libavutil/frame.c
> @@ -799,12 +799,34 @@ AVFrameSideData *av_frame_side_data_new(AVFrameSideData 
> ***sd, int *nb_sd,
>  enum AVFrameSideDataType type,
>  size_t size, unsigned int flags)
>  {
> -AVBufferRef *buf = av_buffer_alloc(size);
> +const AVSideDataDescriptor *desc = av_frame_side_data_desc(type);
> +AVBufferRef *buf;
>  AVFrameSideData *ret = NULL;
>  
>  if (flags & AV_FRAME_SIDE_DATA_FLAG_UNIQUE)
>  remove_side_data(sd, nb_sd, type);
> +if (!desc || !(desc->props & AV_SIDE_DATA_PROP_MULTI)) {

desc == NULL means type is invalid

> +for (int i = 0; i < *nb_sd; i++) {
> +AVFrameSideData *entry = ((*sd)[i]);
> +if (entry->type != type)
> +continue;

Why are you not calling av_frame_side_data_get()?

> @@ -822,13 +845,41 @@ int av_frame_side_data_clone(AVFrameSideData ***sd, int 
> *nb_sd,
>  if (!sd || !src || !nb_sd || (*nb_sd && !*sd))
>  return AVERROR(EINVAL);
>  
> +desc = av_frame_side_data_desc(src->type);
> +if (flags & AV_FRAME_SIDE_DATA_FLAG_UNIQUE)
> +remove_side_data(sd, nb_sd, src->type);
> +if (!desc || !(desc->props & AV_SIDE_DATA_PROP_MULTI)) {
> +for (int i = 0; i < *nb_sd; i++) {
> +AVFrameSideData *entry = ((*sd)[i]);
> +AVDictionary *dict = NULL;
> +
> +if (entry->type != src->type)
> +continue;
> +if (!(flags & AV_FRAME_SIDE_DATA_FLAG_REPLACE))
> +return AVERROR(EEXIST);
> +
> +ret = av_dict_copy(, src->metadata, 0);
> +if (ret < 0)
> +return ret;
> +
> +ret = av_buffer_replace(>buf, src->buf);
> +if (ret < 0) {
> +av_dict_free();
> +return ret;
> +}
> +
> +av_dict_free(>metadata);
> +entry->metadata = dict;
> +entry->data = src->data;
> +entry->size = src->size;
> +return 0;
> +}

This whole block looks very similar to the one you're adding to
av_frame_side_data_new().

> +}
> +
>  buf = av_buffer_ref(src->buf);
>  if (!buf)
>  return AVERROR(ENOMEM);
>  
> -if (flags & AV_FRAME_SIDE_DATA_FLAG_UNIQUE)
> -remove_side_data(sd, nb_sd, src->type);
> -
>  sd_dst = add_side_data_from_buf(sd, nb_sd, src->type, buf);
>  if (!sd_dst) {
>  av_buffer_unref();
> diff --git a/libavutil/frame.h b/libavutil/frame.h
> index 3b6d746a16..2ea129888e 100644
> --- a/libavutil/frame.h
> +++ b/libavutil/frame.h
> @@ -1040,7 +1040,14 @@ const AVSideDataDescriptor 
> *av_frame_side_data_desc(enum AVFrameSideDataType typ
>   */
>  void av_frame_side_data_free(AVFrameSideData ***sd, int *nb_sd);
>  
> +/**
> + * Remove existing entries before adding new ones.
> + */
>  #define AV_FRAME_SIDE_DATA_FLAG_UNIQUE (1 << 0)
> +/**
> + * Don't add a new entry if another of the same type exists.

This should mention that it only applies to MULTI side data types.

-- 
Anton Khirnov
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


[FFmpeg-devel] [PATCH 1/7 v4] avutil/frame: add a flag to allow overwritting existing entries

2024-03-27 Thread James Almer
Enable it only for side data types that don't allow more than one entry.

Signed-off-by: James Almer 
---
 libavutil/frame.c | 59 ---
 libavutil/frame.h | 27 +-
 libavutil/tests/side_data_array.c | 52 +++
 tests/ref/fate/side_data_array| 22 ++--
 4 files changed, 115 insertions(+), 45 deletions(-)

diff --git a/libavutil/frame.c b/libavutil/frame.c
index ef1613c344..d9bd19b2aa 100644
--- a/libavutil/frame.c
+++ b/libavutil/frame.c
@@ -799,12 +799,34 @@ AVFrameSideData *av_frame_side_data_new(AVFrameSideData 
***sd, int *nb_sd,
 enum AVFrameSideDataType type,
 size_t size, unsigned int flags)
 {
-AVBufferRef *buf = av_buffer_alloc(size);
+const AVSideDataDescriptor *desc = av_frame_side_data_desc(type);
+AVBufferRef *buf;
 AVFrameSideData *ret = NULL;
 
 if (flags & AV_FRAME_SIDE_DATA_FLAG_UNIQUE)
 remove_side_data(sd, nb_sd, type);
+if (!desc || !(desc->props & AV_SIDE_DATA_PROP_MULTI)) {
+for (int i = 0; i < *nb_sd; i++) {
+AVFrameSideData *entry = ((*sd)[i]);
+if (entry->type != type)
+continue;
+if (!(flags & AV_FRAME_SIDE_DATA_FLAG_REPLACE))
+return NULL;
+
+buf = av_buffer_alloc(size);
+if (!buf)
+return NULL;
+
+av_buffer_unref(>buf);
+av_dict_free(>metadata);
+entry->buf  = buf;
+entry->data = buf->data;
+entry->size = buf->size;
+return entry;
+}
+}
 
+buf = av_buffer_alloc(size);
 ret = add_side_data_from_buf(sd, nb_sd, type, buf);
 if (!ret)
 av_buffer_unref();
@@ -815,6 +837,7 @@ AVFrameSideData *av_frame_side_data_new(AVFrameSideData 
***sd, int *nb_sd,
 int av_frame_side_data_clone(AVFrameSideData ***sd, int *nb_sd,
  const AVFrameSideData *src, unsigned int flags)
 {
+const AVSideDataDescriptor *desc;
 AVBufferRef *buf= NULL;
 AVFrameSideData *sd_dst = NULL;
 int  ret= AVERROR_BUG;
@@ -822,13 +845,41 @@ int av_frame_side_data_clone(AVFrameSideData ***sd, int 
*nb_sd,
 if (!sd || !src || !nb_sd || (*nb_sd && !*sd))
 return AVERROR(EINVAL);
 
+desc = av_frame_side_data_desc(src->type);
+if (flags & AV_FRAME_SIDE_DATA_FLAG_UNIQUE)
+remove_side_data(sd, nb_sd, src->type);
+if (!desc || !(desc->props & AV_SIDE_DATA_PROP_MULTI)) {
+for (int i = 0; i < *nb_sd; i++) {
+AVFrameSideData *entry = ((*sd)[i]);
+AVDictionary *dict = NULL;
+
+if (entry->type != src->type)
+continue;
+if (!(flags & AV_FRAME_SIDE_DATA_FLAG_REPLACE))
+return AVERROR(EEXIST);
+
+ret = av_dict_copy(, src->metadata, 0);
+if (ret < 0)
+return ret;
+
+ret = av_buffer_replace(>buf, src->buf);
+if (ret < 0) {
+av_dict_free();
+return ret;
+}
+
+av_dict_free(>metadata);
+entry->metadata = dict;
+entry->data = src->data;
+entry->size = src->size;
+return 0;
+}
+}
+
 buf = av_buffer_ref(src->buf);
 if (!buf)
 return AVERROR(ENOMEM);
 
-if (flags & AV_FRAME_SIDE_DATA_FLAG_UNIQUE)
-remove_side_data(sd, nb_sd, src->type);
-
 sd_dst = add_side_data_from_buf(sd, nb_sd, src->type, buf);
 if (!sd_dst) {
 av_buffer_unref();
diff --git a/libavutil/frame.h b/libavutil/frame.h
index 3b6d746a16..2ea129888e 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -1040,7 +1040,14 @@ const AVSideDataDescriptor *av_frame_side_data_desc(enum 
AVFrameSideDataType typ
  */
 void av_frame_side_data_free(AVFrameSideData ***sd, int *nb_sd);
 
+/**
+ * Remove existing entries before adding new ones.
+ */
 #define AV_FRAME_SIDE_DATA_FLAG_UNIQUE (1 << 0)
+/**
+ * Don't add a new entry if another of the same type exists.
+ */
+#define AV_FRAME_SIDE_DATA_FLAG_REPLACE (1 << 1)
 
 /**
  * Add new side data entry to an array.
@@ -1053,10 +1060,12 @@ void av_frame_side_data_free(AVFrameSideData ***sd, int 
*nb_sd);
  * @param size  size of the side data
  * @param flags Some combination of AV_FRAME_SIDE_DATA_FLAG_* flags, or 0.
  *
- * @return newly added side data on success, NULL on error. In case of
- * AV_FRAME_SIDE_DATA_FLAG_UNIQUE being set, entries of matching
- * AVFrameSideDataType will be removed before the addition is
- * attempted.
+ * @return newly added side data on success, NULL on error.
+ * @note In case of AV_FRAME_SIDE_DATA_FLAG_UNIQUE being set, entries of
+ *   matching AVFrameSideDataType will be removed before the addition
+ *   is attempted.
+ * @note In