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) { AVFilterChannelLayouts *ret = NULL; if (a == b) return a; if (a->nb_channel_layouts && b->nb_channel_layouts) { MERGE_FORMATS(ret, a, b, channel_layouts, nb_channel_layouts, AVFilterChannelLayouts, fail); } else if (a->nb_channel_layouts) { MERGE_REF(a, b, channel_layouts, AVFilterChannelLayouts, fail); ret = a; } else { MERGE_REF(b, a, channel_layouts, AVFilterChannelLayouts, fail); ret = b; } return ret; fail: if (ret) { av_freep(&ret->refs); av_freep(&ret->channel_layouts); } av_freep(&ret); return NULL; }
AVFilterChannelLayouts *ff_merge_channel_layouts(AVFilterChannelLayouts *a, AVFilterChannelLayouts *b) { AVFilterChannelLayouts *ret = NULL; unsigned a_all = a->all_layouts + a->all_counts; unsigned b_all = b->all_layouts + b->all_counts; int ret_max, ret_nb = 0, i, j, round; if (a == b) return a; /* Put the most generic set in a, to avoid doing everything twice */ if (a_all < b_all) { FFSWAP(AVFilterChannelLayouts *, a, b); FFSWAP(unsigned, a_all, b_all); } if (a_all) { if (a_all == 1 && !b_all) { /* keep only known layouts in b; works also for b_all = 1 */ for (i = j = 0; i < b->nb_channel_layouts; i++) if (KNOWN(b->channel_layouts[i])) b->channel_layouts[j++] = b->channel_layouts[i]; /* Not optimal: the unknown layouts of b may become known after another merge. */ if (!j) return NULL; b->nb_channel_layouts = j; } MERGE_REF(b, a, channel_layouts, AVFilterChannelLayouts, fail); return b; } ret_max = a->nb_channel_layouts + b->nb_channel_layouts; if (!(ret = av_mallocz(sizeof(*ret))) || !(ret->channel_layouts = av_malloc(sizeof(*ret->channel_layouts) * ret_max))) goto fail; /* a[known] intersect b[known] */ for (i = 0; i < a->nb_channel_layouts; i++) { if (!KNOWN(a->channel_layouts[i])) continue; for (j = 0; j < b->nb_channel_layouts; j++) { if (a->channel_layouts[i] == b->channel_layouts[j]) { ret->channel_layouts[ret_nb++] = a->channel_layouts[i]; a->channel_layouts[i] = b->channel_layouts[j] = 0; } } } /* 1st round: a[known] intersect b[generic] 2nd round: a[generic] intersect b[known] */ for (round = 0; round < 2; round++) { for (i = 0; i < a->nb_channel_layouts; i++) { uint64_t fmt = a->channel_layouts[i], bfmt; if (!fmt || !KNOWN(fmt)) continue; bfmt = FF_COUNT2LAYOUT(av_get_channel_layout_nb_channels(fmt)); for (j = 0; j < b->nb_channel_layouts; j++) if (b->channel_layouts[j] == bfmt) ret->channel_layouts[ret_nb++] = a->channel_layouts[i]; } /* 1st round: swap to prepare 2nd round; 2nd round: put it back */ FFSWAP(AVFilterChannelLayouts *, a, b); } /* a[generic] intersect b[generic] */ for (i = 0; i < a->nb_channel_layouts; i++) { if (KNOWN(a->channel_layouts[i])) continue; for (j = 0; j < b->nb_channel_layouts; j++) if (a->channel_layouts[i] == b->channel_layouts[j]) ret->channel_layouts[ret_nb++] = a->channel_layouts[i]; } ret->nb_channel_layouts = ret_nb; if (!ret->nb_channel_layouts) goto fail; MERGE_REF(ret, a, channel_layouts, AVFilterChannelLayouts, fail); MERGE_REF(ret, b, channel_layouts, AVFilterChannelLayouts, fail); return ret; fail: if (ret) { av_freep(&ret->refs); av_freep(&ret->channel_layouts); } av_freep(&ret); return NULL; }