+/**
+ * Add all refs from a to ret and destroy a.
+ */
+#define MERGE_REF(ret, a, fmts, type, fail) \
+do { \
+ type ***tmp; \
+ int i; \
+ \
+ if (!(tmp = av_realloc(ret->refs, \
+ sizeof(*tmp) * (ret->refcount + a->refcount)))) \
+ goto fail; \
+ ret->refs = tmp; \
+ \
+ for (i = 0; i < a->refcount; i ++) { \
+ ret->refs[ret->refcount] = a->refs[i]; \
+ *ret->refs[ret->refcount++] = ret; \
+ } \
+ \
+ av_freep(&a->refs); \
+ av_freep(&a->fmts); \
+ av_freep(&a); \
+} while (0)
+
+/**
+ * Add all formats common for a and b to ret, copy the refs and destroy
+ * a and b.
+ */
+#define MERGE_FORMATS(ret, a, b, fmts, nb, type, fail) \
+do { \
+ int i, j, k = 0, count = FFMIN(a->nb, b->nb); \
+ \
+ if (!(ret = av_mallocz(sizeof(*ret)))) \
+ goto fail; \
+ \
+ if (count) { \
+ if (!(ret->fmts = av_malloc(sizeof(*ret->fmts) * count))) \
+ goto fail; \
+ for (i = 0; i < a->nb; i++) \
+ for (j = 0; j < b->nb; j++) \
+ if (a->fmts[i] == b->fmts[j]) \
+ ret->fmts[k++] = a->fmts[i]; \
+ \
+ ret->nb = k; \
+ } \
+ /* check that there was at least one common format */ \
+ if (!ret->nb) \
+ goto fail; \
+ \
+ MERGE_REF(ret, a, fmts, type, fail); \
+ MERGE_REF(ret, b, fmts, type, fail); \
+} while (0)
+
+AVFilterFormats *ff_merge_formats(AVFilterFormats *a, AVFilterFormats *b)
+{
+ AVFilterFormats *ret = NULL;
+
+ if (a == b)
+ return a;
+
+ MERGE_FORMATS(ret, a, b, formats, nb_formats, AVFilterFormats, fail);
+
+ return ret;
+fail:
+ if (ret) {
+ av_freep(&ret->refs);
+ av_freep(&ret->formats);
+ }
+ av_freep(&ret);
+ return NULL;
+}
+
+AVFilterFormats *ff_merge_samplerates(AVFilterFormats *a,
+ AVFilterFormats *b)
+{
+ AVFilterFormats *ret = NULL;
+
+ if (a == b) return a;
+
+ if (a->nb_formats && b->nb_formats) {
+ MERGE_FORMATS(ret, a, b, formats, nb_formats, AVFilterFormats, fail);
+ } else if (a->nb_formats) {
+ MERGE_REF(a, b, formats, AVFilterFormats, fail);
+ ret = a;
+ } else {
+ MERGE_REF(b, a, formats, AVFilterFormats, fail);
+ ret = b;
+ }
+
+ return ret;
+fail:
+ if (ret) {
+ av_freep(&ret->refs);
+ av_freep(&ret->formats);
+ }
+ av_freep(&ret);
+ return NULL;
+}
+
+AVFilterChannelLayouts *ff_merge_channel_layouts(AVFilterChannelLayouts *a,
+ AVFilterChannelLayouts *b)