[FFmpeg-devel] [PATCH 6/7] avfilter/formats: Always keep longer references list when merging lists

Andreas Rheinhardt andreas.rheinhardt at gmail.com
Sat Aug 15 08:48:15 EEST 2020


This means that one only needs to update the shorter list of references.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at gmail.com>
---
I doubt that this optimizations is worth the additional complexity. I
have just added it for you to decide.

 libavfilter/formats.c | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/libavfilter/formats.c b/libavfilter/formats.c
index 9788357952..4ac690ea8a 100644
--- a/libavfilter/formats.c
+++ b/libavfilter/formats.c
@@ -33,12 +33,23 @@
 
 /**
  * Add all refs from a to ret and destroy a.
+ * The macro may swap ret and a internally, but the combined list is in ret.
+ * If preserve_fmts is set, the fmts array is preserved when swapping.
  */
-#define MERGE_REF(ret, a, fmts, type, fail_statement)                      \
+#define MERGE_REF(ret, a, fmts, type, preserve_fmts, fail_statement)       \
 do {                                                                       \
     type ***tmp;                                                           \
     int i;                                                                 \
                                                                            \
+    if (ret->refcount < a->refcount) {                                     \
+        FFSWAP(type *, ret, a);                                            \
+        if (preserve_fmts) {                                               \
+            FFSWAP(type, *ret, *a);                                        \
+            FFSWAP(unsigned, ret->refcount, a->refcount);                  \
+            FFSWAP(type ***, ret->refs, a->refs);                          \
+        }                                                                  \
+    }                                                                      \
+                                                                           \
     if (!(tmp = av_realloc_array(ret->refs, ret->refcount + a->refcount,   \
                                  sizeof(*tmp))))                           \
         { fail_statement }                                                 \
@@ -60,6 +71,7 @@ do {                                                                       \
  * the formats are compatible.
  * If empty_allowed is set and one of a,b->nb is zero, the lists are
  * merged; otherwise, it is treated as error.
+ * The macro may swap a and b internally, but the combined list is in a.
  */
 #define MERGE_FORMATS(a, b, fmts, nb, type, check, empty_allowed)          \
 do {                                                                            \
@@ -94,7 +106,7 @@ do {
         a->fmts = tmp;                                                     \
                                                                                 \
 merge_ref:                                                                 \
-    MERGE_REF(a, b, fmts, type, return AVERROR(ENOMEM););                  \
+    MERGE_REF(a, b, fmts, type, 1, return AVERROR(ENOMEM););               \
 } while (0)
 
 static int merge_formats_internal(AVFilterFormats *a, AVFilterFormats *b,
@@ -199,7 +211,8 @@ int ff_merge_channel_layouts(AVFilterChannelLayouts *a,
                 return 0;
             b->nb_channel_layouts = j;
         }
-        MERGE_REF(b, a, channel_layouts, AVFilterChannelLayouts, return AVERROR(ENOMEM););
+        MERGE_REF(b, a, channel_layouts, AVFilterChannelLayouts,
+                  1, return AVERROR(ENOMEM););
         return 1;
     }
 
@@ -248,10 +261,7 @@ int ff_merge_channel_layouts(AVFilterChannelLayouts *a,
         return 0;
     }
 
-    if (a->refcount > b->refcount)
-        FFSWAP(AVFilterChannelLayouts *, a, b);
-
-    MERGE_REF(b, a, channel_layouts, AVFilterChannelLayouts,
+    MERGE_REF(b, a, channel_layouts, AVFilterChannelLayouts, 0,
               { av_free(channel_layouts); return AVERROR(ENOMEM); });
     av_freep(&b->channel_layouts);
     b->channel_layouts    = channel_layouts;
-- 
2.20.1



More information about the ffmpeg-devel mailing list