Signed-off-by: Vittorio Giovara <[email protected]>
---
libavfilter/af_aformat.c | 28 +++++++++----
libavfilter/af_channelmap.c | 2 +-
libavfilter/af_channelsplit.c | 6 ++-
libavfilter/af_join.c | 2 +-
libavfilter/avfiltergraph.c | 97 ++++++++++++++++++++++++++++++-------------
libavfilter/buffersrc.c | 2 +-
libavfilter/formats.c | 45 ++++++++++++++++++--
libavfilter/formats.h | 4 +-
8 files changed, 138 insertions(+), 48 deletions(-)
diff --git a/libavfilter/af_aformat.c b/libavfilter/af_aformat.c
index c5aa4f7148..61479cf286 100644
--- a/libavfilter/af_aformat.c
+++ b/libavfilter/af_aformat.c
@@ -94,13 +94,6 @@ static int get_sample_rate(const char *samplerate)
return FFMAX(ret, 0);
}
-static int get_channel_layout(const char *channel_layout)
-{
- AVChannelLayout ch_layout = {0};
- av_channel_layout_from_string(&ch_layout, channel_layout);
- return ch_layout.u.mask;
-}
-
static av_cold int init(AVFilterContext *ctx)
{
AFormatContext *s = ctx->priv;
@@ -109,8 +102,25 @@ static av_cold int init(AVFilterContext *ctx)
ff_add_format, av_get_sample_fmt, AV_SAMPLE_FMT_NONE,
"sample format");
PARSE_FORMATS(s->sample_rates_str, int, s->sample_rates, ff_add_format,
get_sample_rate, 0, "sample rate");
- PARSE_FORMATS(s->channel_layouts_str, uint64_t, s->channel_layouts,
- ff_add_channel_layout, get_channel_layout, 0, "channel
layout");
+ {
+ char *next, *cur = s->channel_layouts_str, sep = '|';
+ int ret;
+ while (cur) {
+ AVChannelLayout fmt = {0};
+ next = strchr(cur, sep);
+ if (next)
+ *next++ = 0;
+
+ ret = av_channel_layout_from_string(&fmt, cur);
+ if (ret < 0) {
+ av_log(ctx, AV_LOG_ERROR, "Error parsing channel layout:
%s.\n", cur);\
+ return ret;
+ }
+ ff_add_channel_layout(&s->channel_layouts, &fmt);
+
+ cur = next;
+ }
+ }
return 0;
}
diff --git a/libavfilter/af_channelmap.c b/libavfilter/af_channelmap.c
index 939f056d6f..54ff146c5b 100644
--- a/libavfilter/af_channelmap.c
+++ b/libavfilter/af_channelmap.c
@@ -296,7 +296,7 @@ static int channelmap_query_formats(AVFilterContext *ctx)
ChannelMapContext *s = ctx->priv;
AVFilterChannelLayouts *channel_layouts = NULL;
- ff_add_channel_layout(&channel_layouts, s->ch_layout.u.mask);
+ ff_add_channel_layout(&channel_layouts, &s->ch_layout);
ff_set_common_formats(ctx, ff_planar_sample_fmts());
ff_set_common_samplerates(ctx, ff_all_samplerates());
diff --git a/libavfilter/af_channelsplit.c b/libavfilter/af_channelsplit.c
index 41b3051c8c..b13919cdf0 100644
--- a/libavfilter/af_channelsplit.c
+++ b/libavfilter/af_channelsplit.c
@@ -85,16 +85,18 @@ static int query_formats(AVFilterContext *ctx)
ff_set_common_formats (ctx, ff_planar_sample_fmts());
ff_set_common_samplerates(ctx, ff_all_samplerates());
- ff_add_channel_layout(&in_layouts, s->ch_layout.u.mask);
+ ff_add_channel_layout(&in_layouts, &s->ch_layout);
ff_channel_layouts_ref(in_layouts, &ctx->inputs[0]->out_channel_layouts);
for (i = 0; i < ctx->nb_outputs; i++) {
AVFilterChannelLayouts *out_layouts = NULL;
+ AVChannelLayout tmp = {0};
int ret = av_channel_layout_get_channel(&s->ch_layout, i);
if (ret < 0)
return ret;
- ff_add_channel_layout(&out_layouts, 1ULL << ret);
+ av_channel_layout_from_mask(&tmp, 1ULL << ret);
+ ff_add_channel_layout(&out_layouts, &tmp);
ff_channel_layouts_ref(out_layouts,
&ctx->outputs[i]->in_channel_layouts);
}
diff --git a/libavfilter/af_join.c b/libavfilter/af_join.c
index 6c000b9257..70dc2d00d7 100644
--- a/libavfilter/af_join.c
+++ b/libavfilter/af_join.c
@@ -234,7 +234,7 @@ static int join_query_formats(AVFilterContext *ctx)
AVFilterChannelLayouts *layouts = NULL;
int i;
- ff_add_channel_layout(&layouts, s->ch_layout.u.mask);
+ ff_add_channel_layout(&layouts, &s->ch_layout);
ff_channel_layouts_ref(layouts, &ctx->outputs[0]->in_channel_layouts);
for (i = 0; i < ctx->nb_inputs; i++)
diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c
index c72016d2c8..d4ad433e5b 100644
--- a/libavfilter/avfiltergraph.c
+++ b/libavfilter/avfiltergraph.c
@@ -374,6 +374,8 @@ static int query_formats(AVFilterGraph *graph, AVClass
*log_ctx)
static int pick_format(AVFilterLink *link)
{
+ int ret;
+
if (!link || !link->in_formats)
return 0;
@@ -399,11 +401,15 @@ static int pick_format(AVFilterLink *link)
link->in_channel_layouts->nb_channel_layouts = 1;
#if FF_API_OLD_CHANNEL_LAYOUT
FF_DISABLE_DEPRECATION_WARNINGS
- link->channel_layout = link->in_channel_layouts->channel_layouts[0];
+ if (link->in_channel_layouts->channel_layouts[0].order ==
AV_CHANNEL_ORDER_NATIVE ||
+ link->in_channel_layouts->channel_layouts[0].order ==
AV_CHANNEL_ORDER_UNSPEC)
+ link->channel_layout =
link->in_channel_layouts->channel_layouts[0].u.mask;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
- av_channel_layout_from_mask(&link->ch_layout,
-
link->in_channel_layouts->channel_layouts[0]);
+ ret = av_channel_layout_copy(&link->ch_layout,
+
&link->in_channel_layouts->channel_layouts[0]);
+ if (ret < 0)
+ return ret;
}
ff_formats_unref(&link->in_formats);
@@ -459,8 +465,40 @@ static int reduce_formats_on_filter(AVFilterContext
*filter)
nb_formats, ff_add_format);
REDUCE_FORMATS(int, AVFilterFormats, samplerates, formats,
nb_formats, ff_add_format);
- REDUCE_FORMATS(uint64_t, AVFilterChannelLayouts, channel_layouts,
- channel_layouts, nb_channel_layouts, ff_add_channel_layout);
+
+ for (i = 0; i < filter->nb_inputs; i++) {
+ AVFilterLink *link = filter->inputs[i];
+ AVChannelLayout *fmt;
+
+ if (!link->out_channel_layouts ||
link->out_channel_layouts->nb_channel_layouts != 1)
+ continue;
+ fmt = &link->out_channel_layouts->channel_layouts[0];
+
+ for (j = 0; j < filter->nb_outputs; j++) {
+ AVFilterLink *out_link = filter->outputs[j];
+ AVFilterChannelLayouts *fmts;
+
+ if (link->type != out_link->type ||
+ out_link->in_channel_layouts->nb_channel_layouts == 1)
+ continue;
+ fmts = out_link->in_channel_layouts;
+
+ if (!out_link->in_channel_layouts->nb_channel_layouts) {
+ ff_add_channel_layout(&out_link->in_channel_layouts, fmt);
+ break;
+ }
+
+ for (k = 0; k < out_link->in_channel_layouts->nb_channel_layouts;
k++)
+ if (!av_channel_layout_compare(&fmts->channel_layouts[k],
fmt)) {
+ ret = av_channel_layout_copy(&fmts->channel_layouts[0],
fmt);
+ if (ret < 0)
+ return ret;
+ fmts->nb_channel_layouts = 1;
+ ret = 1;
+ break;
+ }
+ }
+ }
return ret;
}
@@ -582,20 +620,22 @@ static void
swap_channel_layouts_on_filter(AVFilterContext *filter)
continue;
for (j = 0; j < outlink->in_channel_layouts->nb_channel_layouts; j++) {
- uint64_t in_chlayout =
link->out_channel_layouts->channel_layouts[0];
- uint64_t out_chlayout =
outlink->in_channel_layouts->channel_layouts[j];
+ AVChannelLayout *in_ch_layout =
&link->out_channel_layouts->channel_layouts[0];
+ AVChannelLayout *out_ch_layout =
&outlink->in_channel_layouts->channel_layouts[j];
+ AVChannelLayout in = {0}, out = {0};
int in_channels;
int out_channels;
+ uint64_t in_mask = 0, out_mask = 0;
int count_diff;
int matched_channels, extra_channels;
int score = 0;
- AVChannelLayout in_ch_layout = {0};
- AVChannelLayout out_ch_layout = {0};
- av_channel_layout_from_mask( &in_ch_layout, in_chlayout);
- av_channel_layout_from_mask(&out_ch_layout, out_chlayout);
- in_channels = in_ch_layout.nb_channels;
- out_channels = out_ch_layout.nb_channels;
+ in_channels = in_ch_layout->nb_channels;
+ out_channels = out_ch_layout->nb_channels;
+ if ( in_ch_layout->order == AV_CHANNEL_ORDER_NATIVE)
+ in_mask = in_ch_layout->u.mask;
+ if (out_ch_layout->order == AV_CHANNEL_ORDER_NATIVE)
+ out_mask = out_ch_layout->u.mask;
count_diff = out_channels - in_channels;
/* channel substitution */
@@ -603,10 +643,13 @@ static void
swap_channel_layouts_on_filter(AVFilterContext *filter)
uint64_t cmp0 = ch_subst[k][0];
uint64_t cmp1 = ch_subst[k][1];
AVChannelLayout tmp = {0};
- if (( in_chlayout & cmp0) && (!(out_chlayout & cmp0)) &&
- (out_chlayout & cmp1) && (!( in_chlayout & cmp1))) {
- in_chlayout &= ~cmp0;
- out_chlayout &= ~cmp1;
+
+ if ( av_channel_layout_subset( in_ch_layout, cmp0) &&
+ !av_channel_layout_subset(out_ch_layout, cmp0) &&
+ av_channel_layout_subset(out_ch_layout, cmp1) &&
+ !av_channel_layout_subset( in_ch_layout, cmp1)) {
+ in_mask &= ~cmp0;
+ out_mask &= ~cmp1;
/* add score for channel match, minus a deduction for
having to do the substitution */
av_channel_layout_from_mask(&tmp, cmp1);
@@ -615,19 +658,17 @@ static void
swap_channel_layouts_on_filter(AVFilterContext *filter)
}
/* no penalty for LFE channel mismatch */
- if ( (in_chlayout & AV_CH_LOW_FREQUENCY) &&
- (out_chlayout & AV_CH_LOW_FREQUENCY))
+ if (av_channel_layout_subset( in_ch_layout, AV_CH_LOW_FREQUENCY) &&
+ av_channel_layout_subset(out_ch_layout, AV_CH_LOW_FREQUENCY))
score += 10;
- in_chlayout &= ~AV_CH_LOW_FREQUENCY;
- out_chlayout &= ~AV_CH_LOW_FREQUENCY;
+ in_mask &= ~AV_CH_LOW_FREQUENCY;
+ out_mask &= ~AV_CH_LOW_FREQUENCY;
- av_channel_layout_uninit( &in_ch_layout);
- av_channel_layout_uninit(&out_ch_layout);
- av_channel_layout_from_mask( &in_ch_layout, in_chlayout &
out_chlayout);
- av_channel_layout_from_mask(&out_ch_layout, out_chlayout &
(~in_chlayout));
+ av_channel_layout_from_mask( &in, in_mask & out_mask);
+ av_channel_layout_from_mask(&out, out_mask & (~in_mask));
- matched_channels = in_ch_layout.nb_channels;
- extra_channels = out_ch_layout.nb_channels;
+ matched_channels = in.nb_channels;
+ extra_channels = out.nb_channels;
score += 10 * matched_channels - 5 * extra_channels;
if (score > best_score ||
@@ -638,7 +679,7 @@ static void swap_channel_layouts_on_filter(AVFilterContext
*filter)
}
}
av_assert0(best_idx >= 0);
- FFSWAP(uint64_t, outlink->in_channel_layouts->channel_layouts[0],
+ FFSWAP(AVChannelLayout,
outlink->in_channel_layouts->channel_layouts[0],
outlink->in_channel_layouts->channel_layouts[best_idx]);
}
diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c
index 838e3ac08d..9f4e8dbf8a 100644
--- a/libavfilter/buffersrc.c
+++ b/libavfilter/buffersrc.c
@@ -347,7 +347,7 @@ static int query_formats(AVFilterContext *ctx)
ff_add_format(&samplerates, c->sample_rate);
ff_set_common_samplerates(ctx, samplerates);
- ff_add_channel_layout(&channel_layouts, c->ch_layout.u.mask);
+ ff_add_channel_layout(&channel_layouts, &c->ch_layout);
ff_set_common_channel_layouts(ctx, channel_layouts);
break;
default:
diff --git a/libavfilter/formats.c b/libavfilter/formats.c
index 7b5a93c325..251df0d721 100644
--- a/libavfilter/formats.c
+++ b/libavfilter/formats.c
@@ -131,8 +131,31 @@ AVFilterChannelLayouts
*ff_merge_channel_layouts(AVFilterChannelLayouts *a,
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);
+ int i, j, k = 0, count = FFMIN(a->nb_channel_layouts,
b->nb_channel_layouts);
+
+ if (!(ret = av_mallocz(sizeof(*ret))))
+ goto fail;
+
+ if (count) {
+ if (!(ret->channel_layouts =
av_malloc(sizeof(*ret->channel_layouts) * count)))
+ goto fail;
+ for (i = 0; i < a->nb_channel_layouts; i++)
+ for (j = 0; j < b->nb_channel_layouts; j++)
+ if (!av_channel_layout_compare(&a->channel_layouts[i],
+ &b->channel_layouts[j]))
+ if (av_channel_layout_copy(&ret->channel_layouts[k++],
+ &a->channel_layouts[i]) < 0)
+ goto fail;
+
+ ret->nb_channel_layouts = k;
+ }
+ /* check that there was at least one common format */
+ if (!ret->nb_channel_layouts)
+ goto fail;
+
+ MERGE_REF(ret, a, channel_layouts, AVFilterChannelLayouts, fail);
+ MERGE_REF(ret, b, channel_layouts, AVFilterChannelLayouts, fail);
+
} else if (a->nb_channel_layouts) {
MERGE_REF(a, b, channel_layouts, AVFilterChannelLayouts, fail);
ret = a;
@@ -210,9 +233,23 @@ int ff_add_format(AVFilterFormats **avff, int fmt)
ADD_FORMAT(avff, fmt, int, formats, nb_formats);
}
-int ff_add_channel_layout(AVFilterChannelLayouts **l, uint64_t channel_layout)
+int ff_add_channel_layout(AVFilterChannelLayouts **f, AVChannelLayout
*channel_layout)
{
- ADD_FORMAT(l, channel_layout, uint64_t, channel_layouts,
nb_channel_layouts);
+ AVChannelLayout *fmts;
+
+ if (!(*f) && !(*f = av_mallocz(sizeof(**f))))
+ return AVERROR(ENOMEM);
+
+ fmts = av_realloc((*f)->channel_layouts,
+ sizeof(*(*f)->channel_layouts) *
((*f)->nb_channel_layouts + 1));\
+ if (!fmts) {
+ av_freep(&f);
+ return AVERROR(ENOMEM);
+ }
+
+ (*f)->channel_layouts = fmts;
+ return
av_channel_layout_copy(&(*f)->channel_layouts[(*f)->nb_channel_layouts++],
+ channel_layout);
}
AVFilterFormats *ff_all_formats(enum AVMediaType type)
diff --git a/libavfilter/formats.h b/libavfilter/formats.h
index b273f8aa03..157ef757b3 100644
--- a/libavfilter/formats.h
+++ b/libavfilter/formats.h
@@ -70,7 +70,7 @@ struct AVFilterFormats {
};
typedef struct AVFilterChannelLayouts {
- uint64_t *channel_layouts; ///< list of channel layouts
+ AVChannelLayout *channel_layouts; ///< list of channel layouts
int nb_channel_layouts; ///< number of channel layouts
unsigned refcount; ///< number of references to this list
@@ -114,7 +114,7 @@ void ff_set_common_samplerates(AVFilterContext *ctx,
*/
void ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats);
-int ff_add_channel_layout(AVFilterChannelLayouts **l, uint64_t channel_layout);
+int ff_add_channel_layout(AVFilterChannelLayouts **l, AVChannelLayout
*channel_layout);
/**
* Add *ref as a new reference to f.
--
2.12.0
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel