History

lavfi: support unknown channel layouts.

Nicolas George committed 13 years ago

Commit b6afb2d1 parent fccd8c25 files · +184 −19Browse files

Unified · Split

5 files
  1. libavfilter/audio.c +1 −1
  2. libavfilter/avcodec.c +0 −3
  3. libavfilter/avfiltergraph.c +79 −6
  4. libavfilter/formats.c +73 −9
  5. libavfilter/formats.h +31 −0
libavfilter/audio.c+1−1
@@ -44,7 +44,7 @@ AVFilterBufferRef *ff_default_get_audio_buffer(AVFilterLink *link, int perms, · 43 unmodified lines
4444 AVFilterBufferRef *samplesref = NULL;
4545 uint8_t **data;
4646 int planar = av_sample_fmt_is_planar(link->format);
47− int nb_channels = av_get_channel_layout_nb_channels(link->channel_layout);
47+ int nb_channels = link->channels;
4848 int planes = planar ? nb_channels : 1;
4949 int linesize;
5050 int full_perms = AV_PERM_READ | AV_PERM_WRITE | AV_PERM_PRESERVE |
libavfilter/avcodec.c+0−3
@@ -96,9 +96,6 @@ AVFilterBufferRef *avfilter_get_audio_buffer_ref_from_frame(const AVFrame *frame · 95 unmodified lines
9696 int channels = av_frame_get_channels(frame);
9797 int64_t layout = av_frame_get_channel_layout(frame);
9898
99− if(av_frame_get_channels(frame) > 8) // libavfilter does not suport more than 8 channels FIXME, remove once libavfilter is fixed
100− return NULL;
101−
10299 if (layout && av_get_channel_layout_nb_channels(layout) != av_frame_get_channels(frame)) {
103100 av_log(0, AV_LOG_ERROR, "Layout indicates a different number of channels than actually present\n");
104101 return NULL;
libavfilter/avfiltergraph.c+79−6
@@ -185,9 +185,24 @@ AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, char *name) · 184 unmodified lines
185185 return NULL;
186186 }
187187
188+static void sanitize_channel_layouts(void *log, AVFilterChannelLayouts *l)
189+{
190+ if (!l)
191+ return;
192+ if (l->nb_channel_layouts) {
193+ if (l->all_layouts || l->all_counts)
194+ av_log(log, AV_LOG_WARNING, "All layouts set on non-empty list\n");
195+ l->all_layouts = l->all_counts = 0;
196+ } else {
197+ if (l->all_counts && !l->all_layouts)
198+ av_log(log, AV_LOG_WARNING, "All counts without all layouts\n");
199+ l->all_layouts = 1;
200+ }
201+}
202+
188203 static int filter_query_formats(AVFilterContext *ctx)
189204 {
190− int ret;
205+ int ret, i;
191206 AVFilterFormats *formats;
192207 AVFilterChannelLayouts *chlayouts;
193208 AVFilterFormats *samplerates;
@@ -201,6 +216,11 @@ static int filter_query_formats(AVFilterContext *ctx) · 7 unmodified lines
201216 return ret;
202217 }
203218
219+ for (i = 0; i < ctx->nb_inputs; i++)
220+ sanitize_channel_layouts(ctx, ctx->inputs[i]->out_channel_layouts);
221+ for (i = 0; i < ctx->nb_outputs; i++)
222+ sanitize_channel_layouts(ctx, ctx->outputs[i]->in_channel_layouts);
223+
204224 formats = ff_all_formats(type);
205225 if (!formats)
206226 return AVERROR(ENOMEM);
@@ -470,7 +490,7 @@ static int pick_format(AVFilterLink *link, AVFilterLink *ref) · 263 unmodified lines
470490 link->in_samplerates->format_count = 1;
471491 link->sample_rate = link->in_samplerates->formats[0];
472492
473− if (!link->in_channel_layouts->nb_channel_layouts) {
493+ if (link->in_channel_layouts->all_layouts) {
474494 av_log(link->src, AV_LOG_ERROR, "Cannot select channel layout for"
475495 "the link between filters %s and %s.\n", link->src->name,
476496 link->dst->name);
@@ -478,7 +498,10 @@ static int pick_format(AVFilterLink *link, AVFilterLink *ref) · 1 unmodified line
478498 }
479499 link->in_channel_layouts->nb_channel_layouts = 1;
480500 link->channel_layout = link->in_channel_layouts->channel_layouts[0];
481− link->channels = av_get_channel_layout_nb_channels(link->channel_layout);
501+ if ((link->channels = FF_LAYOUT2COUNT(link->channel_layout)))
502+ link->channel_layout = 0;
503+ else
504+ link->channels = av_get_channel_layout_nb_channels(link->channel_layout);
482505 }
483506
484507 ff_formats_unref(&link->in_formats);
@@ -534,8 +557,42 @@ static int reduce_formats_on_filter(AVFilterContext *filter) · 49 unmodified lines
534557 format_count, ff_add_format);
535558 REDUCE_FORMATS(int, AVFilterFormats, samplerates, formats,
536559 format_count, ff_add_format);
537− REDUCE_FORMATS(uint64_t, AVFilterChannelLayouts, channel_layouts,
538− channel_layouts, nb_channel_layouts, ff_add_channel_layout);
560+
561+ /* reduce channel layouts */
562+ for (i = 0; i < filter->nb_inputs; i++) {
563+ AVFilterLink *inlink = filter->inputs[i];
564+ uint64_t fmt;
565+
566+ if (!inlink->out_channel_layouts ||
567+ inlink->out_channel_layouts->nb_channel_layouts != 1)
568+ continue;
569+ fmt = inlink->out_channel_layouts->channel_layouts[0];
570+
571+ for (j = 0; j < filter->nb_outputs; j++) {
572+ AVFilterLink *outlink = filter->outputs[j];
573+ AVFilterChannelLayouts *fmts;
574+
575+ fmts = outlink->in_channel_layouts;
576+ if (inlink->type != outlink->type || fmts->nb_channel_layouts == 1)
577+ continue;
578+
579+ if (fmts->all_layouts) {
580+ /* Turn the infinite list into a singleton */
581+ fmts->all_layouts = fmts->all_counts = 0;
582+ ff_add_channel_layout(&outlink->in_channel_layouts, fmt);
583+ break;
584+ }
585+
586+ for (k = 0; k < outlink->in_channel_layouts->nb_channel_layouts; k++) {
587+ if (fmts->channel_layouts[k] == fmt) {
588+ fmts->channel_layouts[0] = fmt;
589+ fmts->nb_channel_layouts = 1;
590+ ret = 1;
591+ break;
592+ }
593+ }
594+ }
595+ }
539596
540597 return ret;
541598 }
@@ -663,7 +720,23 @@ static void swap_channel_layouts_on_filter(AVFilterContext *filter) · 121 unmodified lines
663720 int out_channels = av_get_channel_layout_nb_channels(out_chlayout);
664721 int count_diff = out_channels - in_channels;
665722 int matched_channels, extra_channels;
666− int score = 0;
723+ int score = 100000;
724+
725+ if (FF_LAYOUT2COUNT(in_chlayout) || FF_LAYOUT2COUNT(out_chlayout)) {
726+ /* Compute score in case the input or output layout encodes
727+ a channel count; in this case the score is not altered by
728+ the computation afterwards, as in_chlayout and
729+ out_chlayout have both been set to 0 */
730+ if (FF_LAYOUT2COUNT(in_chlayout))
731+ in_channels = FF_LAYOUT2COUNT(in_chlayout);
732+ if (FF_LAYOUT2COUNT(out_chlayout))
733+ out_channels = FF_LAYOUT2COUNT(out_chlayout);
734+ score -= 10000 + FFABS(out_channels - in_channels) +
735+ (in_channels > out_channels ? 10000 : 0);
736+ in_chlayout = out_chlayout = 0;
737+ /* Let the remaining computation run, even if the score
738+ value is not altered */
739+ }
667740
668741 /* channel substitution */
669742 for (k = 0; k < FF_ARRAY_ELEMS(ch_subst); k++) {
libavfilter/formats.c+73−9
@@ -19,6 +19,7 @@ · 18 unmodified lines
1919 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2020 */
2121
22+#include "libavutil/avassert.h"
2223 #include "libavutil/channel_layout.h"
2324 #include "libavutil/common.h"
2425 #include "libavutil/eval.h"
@@ -28,6 +29,8 @@ · 3 unmodified lines
2829 #include "internal.h"
2930 #include "formats.h"
3031
32+#define KNOWN(l) (!FF_LAYOUT2COUNT(l)) /* for readability */
33+
3134 /**
3235 * Add all refs from a to ret and destroy a.
3336 */
@@ -136,21 +139,77 @@ AVFilterChannelLayouts *ff_merge_channel_layouts(AVFilterChannelLayouts *a, · 102 unmodified lines
136139 AVFilterChannelLayouts *b)
137140 {
138141 AVFilterChannelLayouts *ret = NULL;
142+ unsigned a_all = a->all_layouts + a->all_counts;
143+ unsigned b_all = b->all_layouts + b->all_counts;
144+ int ret_max, ret_nb = 0, i, j, round;
139145
140146 if (a == b) return a;
141147
142− if (a->nb_channel_layouts && b->nb_channel_layouts) {
143− MERGE_FORMATS(ret, a, b, channel_layouts, nb_channel_layouts,
144− AVFilterChannelLayouts, fail);
145− } else if (a->nb_channel_layouts) {
146− MERGE_REF(a, b, channel_layouts, AVFilterChannelLayouts, fail);
147− ret = a;
148− } else {
148+ /* Put the most generic set in a, to avoid doing everything twice */
149+ if (a_all < b_all) {
150+ FFSWAP(AVFilterChannelLayouts *, a, b);
151+ FFSWAP(unsigned, a_all, b_all);
152+ }
153+ if (a_all) {
154+ if (a_all == 1 && !b_all) {
155+ /* keep only known layouts in b; works also for b_all = 1 */
156+ for (i = j = 0; i < b->nb_channel_layouts; i++)
157+ if (KNOWN(b->channel_layouts[i]))
158+ b->channel_layouts[j++] = b->channel_layouts[i];
159+ b->nb_channel_layouts = j;
160+ }
149161 MERGE_REF(b, a, channel_layouts, AVFilterChannelLayouts, fail);
150− ret = b;
162+ return b;
151163 }
152164
165+ ret_max = a->nb_channel_layouts + b->nb_channel_layouts;
166+ if (!(ret = av_mallocz(sizeof(*ret))) ||
167+ !(ret->channel_layouts = av_malloc(sizeof(*ret->channel_layouts) *
168+ ret_max)))
169+ goto fail;
170+
171+ /* a[known] intersect b[known] */
172+ for (i = 0; i < a->nb_channel_layouts; i++) {
173+ if (!KNOWN(a->channel_layouts[i]))
174+ continue;
175+ for (j = 0; j < b->nb_channel_layouts; j++) {
176+ if (a->channel_layouts[i] == b->channel_layouts[j]) {
177+ ret->channel_layouts[ret_nb++] = a->channel_layouts[i];
178+ a->channel_layouts[i] = b->channel_layouts[j] = 0;
179+ }
180+ }
181+ }
182+ /* 1st round: a[known] intersect b[generic]
183+ 2nd round: a[generic] intersect b[known] */
184+ for (round = 0; round < 2; round++) {
185+ for (i = 0; i < a->nb_channel_layouts; i++) {
186+ uint64_t fmt = a->channel_layouts[i], bfmt;
187+ if (!fmt || !KNOWN(fmt))
188+ continue;
189+ bfmt = FF_COUNT2LAYOUT(av_get_channel_layout_nb_channels(fmt));
190+ for (j = 0; j < b->nb_channel_layouts; j++)
191+ if (b->channel_layouts[j] == bfmt)
192+ ret->channel_layouts[ret_nb++] = a->channel_layouts[i];
193+ }
194+ /* 1st round: swap to prepare 2nd round; 2nd round: put it back */
195+ FFSWAP(AVFilterChannelLayouts *, a, b);
196+ }
197+ /* a[generic] intersect b[generic] */
198+ for (i = 0; i < a->nb_channel_layouts; i++) {
199+ if (KNOWN(a->channel_layouts[i]))
200+ continue;
201+ for (j = 0; j < b->nb_channel_layouts; j++)
202+ if (a->channel_layouts[i] == b->channel_layouts[j])
203+ ret->channel_layouts[ret_nb++] = a->channel_layouts[i];
204+ }
205+
206+ ret->nb_channel_layouts = ret_nb;
207+ if (!ret->nb_channel_layouts)
208+ goto fail;
209+ MERGE_REF(ret, a, channel_layouts, AVFilterChannelLayouts, fail);
210+ MERGE_REF(ret, b, channel_layouts, AVFilterChannelLayouts, fail);
153211 return ret;
212+
154213 fail:
155214 if (ret) {
156215 av_freep(&ret->refs);
@@ -248,17 +307,19 @@ do { \ · 91 unmodified lines
248307 \
249308 (*f)->list = fmts; \
250309 (*f)->list[(*f)->nb++] = fmt; \
251− return 0; \
252310 } while (0)
253311
254312 int ff_add_format(AVFilterFormats **avff, int64_t fmt)
255313 {
256314 ADD_FORMAT(avff, fmt, int, formats, format_count);
315+ return 0;
257316 }
258317
259318 int ff_add_channel_layout(AVFilterChannelLayouts **l, uint64_t channel_layout)
260319 {
320+ av_assert1(!(*l && (*l)->all_layouts));
261321 ADD_FORMAT(l, channel_layout, uint64_t, channel_layouts, nb_channel_layouts);
322+ return 0;
262323 }
263324
264325 AVFilterFormats *ff_all_formats(enum AVMediaType type)
@@ -309,6 +370,9 @@ AVFilterFormats *ff_all_samplerates(void) · 44 unmodified lines
309370 AVFilterChannelLayouts *ff_all_channel_layouts(void)
310371 {
311372 AVFilterChannelLayouts *ret = av_mallocz(sizeof(*ret));
373+ if (!ret)
374+ return NULL;
375+ ret->all_layouts = 1;
312376 return ret;
313377 }
314378
libavfilter/formats.h+31−0
@@ -69,14 +69,45 @@ struct AVFilterFormats { · 68 unmodified lines
6969 struct AVFilterFormats ***refs; ///< references to this list
7070 };
7171
72+/**
73+ * A list of supported channel layouts.
74+ *
75+ * The list works the same as AVFilterFormats, except for the following
76+ * differences:
77+ * - A list with all_layouts = 1 means all channel layouts with a known
78+ * disposition; nb_channel_layouts must then be 0.
79+ * - A list with all_counts = 1 means all channel counts, with a known or
80+ * unknown disposition; nb_channel_layouts must then be 0 and all_layouts 1.
81+ * - The list must not contain a layout with a known disposition and a
82+ * channel count with unknown disposition with the same number of channels
83+ * (e.g. AV_CH_LAYOUT_STEREO and FF_COUNT2LAYOUT(2).
84+ */
7285 typedef struct AVFilterChannelLayouts {
7386 uint64_t *channel_layouts; ///< list of channel layouts
7487 int nb_channel_layouts; ///< number of channel layouts
88+ char all_layouts; ///< accept any known channel layout
89+ char all_counts; ///< accept any channel layout or count
7590
7691 unsigned refcount; ///< number of references to this list
7792 struct AVFilterChannelLayouts ***refs; ///< references to this list
7893 } AVFilterChannelLayouts;
7994
95+/**
96+ * Encode a channel count as a channel layout.
97+ * FF_COUNT2LAYOUT(c) means any channel layout with c channels, with a known
98+ * or unknown disposition.
99+ * The result is only valid inside AVFilterChannelLayouts and immediately
100+ * related functions.
101+ */
102+#define FF_COUNT2LAYOUT(c) (0x8000000000000000ULL | (c))
103+
104+/**
105+ * Decode a channel count encoded as a channel layout.
106+ * Return 0 if the channel layout was a real one.
107+ */
108+#define FF_LAYOUT2COUNT(l) (((l) & 0x8000000000000000ULL) ? \
109+ (int)((l) & 0x7FFFFFFF) : 0)
110+
80111 /**
81112 * Return a channel layouts/samplerates list which contains the intersection of
82113 * the layouts/samplerates of a and b. Also, all the references of a, all the

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t