|
|
@ -19,6 +19,7 @@ |
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "libavutil/avassert.h" |
|
|
|
#include "libavutil/channel_layout.h" |
|
|
|
#include "libavutil/channel_layout.h" |
|
|
|
#include "libavutil/common.h" |
|
|
|
#include "libavutil/common.h" |
|
|
|
#include "libavutil/eval.h" |
|
|
|
#include "libavutil/eval.h" |
|
|
@ -28,6 +29,8 @@ |
|
|
|
#include "internal.h" |
|
|
|
#include "internal.h" |
|
|
|
#include "formats.h" |
|
|
|
#include "formats.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define KNOWN(l) (!FF_LAYOUT2COUNT(l)) /* for readability */ |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Add all refs from a to ret and destroy a. |
|
|
|
* Add all refs from a to ret and destroy a. |
|
|
|
*/ |
|
|
|
*/ |
|
|
@ -136,21 +139,77 @@ AVFilterChannelLayouts *ff_merge_channel_layouts(AVFilterChannelLayouts *a, |
|
|
|
AVFilterChannelLayouts *b) |
|
|
|
AVFilterChannelLayouts *b) |
|
|
|
{ |
|
|
|
{ |
|
|
|
AVFilterChannelLayouts *ret = NULL; |
|
|
|
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; |
|
|
|
if (a == b) return a; |
|
|
|
|
|
|
|
|
|
|
|
if (a->nb_channel_layouts && b->nb_channel_layouts) { |
|
|
|
/* Put the most generic set in a, to avoid doing everything twice */ |
|
|
|
MERGE_FORMATS(ret, a, b, channel_layouts, nb_channel_layouts, |
|
|
|
if (a_all < b_all) { |
|
|
|
AVFilterChannelLayouts, fail); |
|
|
|
FFSWAP(AVFilterChannelLayouts *, a, b); |
|
|
|
} else if (a->nb_channel_layouts) { |
|
|
|
FFSWAP(unsigned, a_all, b_all); |
|
|
|
MERGE_REF(a, b, channel_layouts, AVFilterChannelLayouts, fail); |
|
|
|
|
|
|
|
ret = a; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
MERGE_REF(b, a, channel_layouts, AVFilterChannelLayouts, fail); |
|
|
|
|
|
|
|
ret = b; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
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]; |
|
|
|
|
|
|
|
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; |
|
|
|
return ret; |
|
|
|
|
|
|
|
|
|
|
|
fail: |
|
|
|
fail: |
|
|
|
if (ret) { |
|
|
|
if (ret) { |
|
|
|
av_freep(&ret->refs); |
|
|
|
av_freep(&ret->refs); |
|
|
@ -248,17 +307,19 @@ do { \ |
|
|
|
\
|
|
|
|
\
|
|
|
|
(*f)->list = fmts; \
|
|
|
|
(*f)->list = fmts; \
|
|
|
|
(*f)->list[(*f)->nb++] = fmt; \
|
|
|
|
(*f)->list[(*f)->nb++] = fmt; \
|
|
|
|
return 0; \
|
|
|
|
|
|
|
|
} while (0) |
|
|
|
} while (0) |
|
|
|
|
|
|
|
|
|
|
|
int ff_add_format(AVFilterFormats **avff, int64_t fmt) |
|
|
|
int ff_add_format(AVFilterFormats **avff, int64_t fmt) |
|
|
|
{ |
|
|
|
{ |
|
|
|
ADD_FORMAT(avff, fmt, int, formats, format_count); |
|
|
|
ADD_FORMAT(avff, fmt, int, formats, format_count); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int ff_add_channel_layout(AVFilterChannelLayouts **l, uint64_t channel_layout) |
|
|
|
int ff_add_channel_layout(AVFilterChannelLayouts **l, uint64_t channel_layout) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
av_assert1(!(*l && (*l)->all_layouts)); |
|
|
|
ADD_FORMAT(l, channel_layout, uint64_t, channel_layouts, nb_channel_layouts); |
|
|
|
ADD_FORMAT(l, channel_layout, uint64_t, channel_layouts, nb_channel_layouts); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
AVFilterFormats *ff_all_formats(enum AVMediaType type) |
|
|
|
AVFilterFormats *ff_all_formats(enum AVMediaType type) |
|
|
@ -309,6 +370,9 @@ AVFilterFormats *ff_all_samplerates(void) |
|
|
|
AVFilterChannelLayouts *ff_all_channel_layouts(void) |
|
|
|
AVFilterChannelLayouts *ff_all_channel_layouts(void) |
|
|
|
{ |
|
|
|
{ |
|
|
|
AVFilterChannelLayouts *ret = av_mallocz(sizeof(*ret)); |
|
|
|
AVFilterChannelLayouts *ret = av_mallocz(sizeof(*ret)); |
|
|
|
|
|
|
|
if (!ret) |
|
|
|
|
|
|
|
return NULL; |
|
|
|
|
|
|
|
ret->all_layouts = 1; |
|
|
|
return ret; |
|
|
|
return ret; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|