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
44 AVFilterBufferRef *samplesref = NULL;44 AVFilterBufferRef *samplesref = NULL;
45 uint8_t **data;45 uint8_t **data;
46 int planar = av_sample_fmt_is_planar(link->format);46 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;
48 int planes = planar ? nb_channels : 1;48 int planes = planar ? nb_channels : 1;
49 int linesize;49 int linesize;
50 int full_perms = AV_PERM_READ | AV_PERM_WRITE | AV_PERM_PRESERVE |50 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
96 int channels = av_frame_get_channels(frame);96 int channels = av_frame_get_channels(frame);
97 int64_t layout = av_frame_get_channel_layout(frame);97 int64_t layout = av_frame_get_channel_layout(frame);
98 98
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
102 if (layout && av_get_channel_layout_nb_channels(layout) != av_frame_get_channels(frame)) {99 if (layout && av_get_channel_layout_nb_channels(layout) != av_frame_get_channels(frame)) {
103 av_log(0, AV_LOG_ERROR, "Layout indicates a different number of channels than actually present\n");100 av_log(0, AV_LOG_ERROR, "Layout indicates a different number of channels than actually present\n");
104 return NULL;101 return NULL;
libavfilter/avfiltergraph.c+79−6
@@ -185,9 +185,24 @@ AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, char *name) · 184 unmodified lines
185 return NULL;185 return NULL;
186}186}
187 187
188static 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
188static int filter_query_formats(AVFilterContext *ctx)203static int filter_query_formats(AVFilterContext *ctx)
189{204{
190 int ret;205 int ret, i;
191 AVFilterFormats *formats;206 AVFilterFormats *formats;
192 AVFilterChannelLayouts *chlayouts;207 AVFilterChannelLayouts *chlayouts;
193 AVFilterFormats *samplerates;208 AVFilterFormats *samplerates;
@@ -201,6 +216,11 @@ static int filter_query_formats(AVFilterContext *ctx) · 7 unmodified lines
201 return ret;216 return ret;
202 }217 }
203 218
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
204 formats = ff_all_formats(type);224 formats = ff_all_formats(type);
205 if (!formats)225 if (!formats)
206 return AVERROR(ENOMEM);226 return AVERROR(ENOMEM);
@@ -470,7 +490,7 @@ static int pick_format(AVFilterLink *link, AVFilterLink *ref) · 263 unmodified lines
470 link->in_samplerates->format_count = 1;490 link->in_samplerates->format_count = 1;
471 link->sample_rate = link->in_samplerates->formats[0];491 link->sample_rate = link->in_samplerates->formats[0];
472 492
473 if (!link->in_channel_layouts->nb_channel_layouts) {493 if (link->in_channel_layouts->all_layouts) {
474 av_log(link->src, AV_LOG_ERROR, "Cannot select channel layout for"494 av_log(link->src, AV_LOG_ERROR, "Cannot select channel layout for"
475 "the link between filters %s and %s.\n", link->src->name,495 "the link between filters %s and %s.\n", link->src->name,
476 link->dst->name);496 link->dst->name);
@@ -478,7 +498,10 @@ static int pick_format(AVFilterLink *link, AVFilterLink *ref) · 1 unmodified line
478 }498 }
479 link->in_channel_layouts->nb_channel_layouts = 1;499 link->in_channel_layouts->nb_channel_layouts = 1;
480 link->channel_layout = link->in_channel_layouts->channel_layouts[0];500 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);
482 }505 }
483 506
484 ff_formats_unref(&link->in_formats);507 ff_formats_unref(&link->in_formats);
@@ -534,8 +557,42 @@ static int reduce_formats_on_filter(AVFilterContext *filter) · 49 unmodified lines
534 format_count, ff_add_format);557 format_count, ff_add_format);
535 REDUCE_FORMATS(int, AVFilterFormats, samplerates, formats,558 REDUCE_FORMATS(int, AVFilterFormats, samplerates, formats,
536 format_count, ff_add_format);559 format_count, ff_add_format);
537 REDUCE_FORMATS(uint64_t, AVFilterChannelLayouts, channel_layouts,560
538 channel_layouts, nb_channel_layouts, ff_add_channel_layout);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 }
539 596
540 return ret;597 return ret;
541}598}
@@ -663,7 +720,23 @@ static void swap_channel_layouts_on_filter(AVFilterContext *filter) · 121 unmodified lines
663 int out_channels = av_get_channel_layout_nb_channels(out_chlayout);720 int out_channels = av_get_channel_layout_nb_channels(out_chlayout);
664 int count_diff = out_channels - in_channels;721 int count_diff = out_channels - in_channels;
665 int matched_channels, extra_channels;722 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 }
667 740
668 /* channel substitution */741 /* channel substitution */
669 for (k = 0; k < FF_ARRAY_ELEMS(ch_subst); k++) {742 for (k = 0; k < FF_ARRAY_ELEMS(ch_subst); k++) {
libavfilter/formats.c+73−9
@@ -19,6 +19,7 @@ · 18 unmodified lines
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */20 */
21 21
22#include "libavutil/avassert.h"
22#include "libavutil/channel_layout.h"23#include "libavutil/channel_layout.h"
23#include "libavutil/common.h"24#include "libavutil/common.h"
24#include "libavutil/eval.h"25#include "libavutil/eval.h"
@@ -28,6 +29,8 @@ · 3 unmodified lines
28#include "internal.h"29#include "internal.h"
29#include "formats.h"30#include "formats.h"
30 31
32#define KNOWN(l) (!FF_LAYOUT2COUNT(l)) /* for readability */
33
31/**34/**
32 * Add all refs from a to ret and destroy a.35 * Add all refs from a to ret and destroy a.
33 */36 */
@@ -136,21 +139,77 @@ AVFilterChannelLayouts *ff_merge_channel_layouts(AVFilterChannelLayouts *a, · 102 unmodified lines
136 AVFilterChannelLayouts *b)139 AVFilterChannelLayouts *b)
137{140{
138 AVFilterChannelLayouts *ret = NULL;141 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;
139 145
140 if (a == b) return a;146 if (a == b) return a;
141 147
142 if (a->nb_channel_layouts && b->nb_channel_layouts) {148 /* Put the most generic set in a, to avoid doing everything twice */
143 MERGE_FORMATS(ret, a, b, channel_layouts, nb_channel_layouts,149 if (a_all < b_all) {
144 AVFilterChannelLayouts, fail);150 FFSWAP(AVFilterChannelLayouts *, a, b);
145 } else if (a->nb_channel_layouts) {151 FFSWAP(unsigned, a_all, b_all);
146 MERGE_REF(a, b, channel_layouts, AVFilterChannelLayouts, fail);152 }
147 ret = a;153 if (a_all) {
148 } else {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 }
149 MERGE_REF(b, a, channel_layouts, AVFilterChannelLayouts, fail);161 MERGE_REF(b, a, channel_layouts, AVFilterChannelLayouts, fail);
150 ret = b;162 return b;
151 }163 }
152 164
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);
153 return ret;211 return ret;
212
154fail:213fail:
155 if (ret) {214 if (ret) {
156 av_freep(&ret->refs);215 av_freep(&ret->refs);
@@ -248,17 +307,19 @@ do { \ · 91 unmodified lines
248 \307 \
249 (*f)->list = fmts; \308 (*f)->list = fmts; \
250 (*f)->list[(*f)->nb++] = fmt; \309 (*f)->list[(*f)->nb++] = fmt; \
251 return 0; \
252} while (0)310} while (0)
253 311
254int ff_add_format(AVFilterFormats **avff, int64_t fmt)312int ff_add_format(AVFilterFormats **avff, int64_t fmt)
255{313{
256 ADD_FORMAT(avff, fmt, int, formats, format_count);314 ADD_FORMAT(avff, fmt, int, formats, format_count);
315 return 0;
257}316}
258 317
259int ff_add_channel_layout(AVFilterChannelLayouts **l, uint64_t channel_layout)318int ff_add_channel_layout(AVFilterChannelLayouts **l, uint64_t channel_layout)
260{319{
320 av_assert1(!(*l && (*l)->all_layouts));
261 ADD_FORMAT(l, channel_layout, uint64_t, channel_layouts, nb_channel_layouts);321 ADD_FORMAT(l, channel_layout, uint64_t, channel_layouts, nb_channel_layouts);
322 return 0;
262}323}
263 324
264AVFilterFormats *ff_all_formats(enum AVMediaType type)325AVFilterFormats *ff_all_formats(enum AVMediaType type)
@@ -309,6 +370,9 @@ AVFilterFormats *ff_all_samplerates(void) · 44 unmodified lines
309AVFilterChannelLayouts *ff_all_channel_layouts(void)370AVFilterChannelLayouts *ff_all_channel_layouts(void)
310{371{
311 AVFilterChannelLayouts *ret = av_mallocz(sizeof(*ret));372 AVFilterChannelLayouts *ret = av_mallocz(sizeof(*ret));
373 if (!ret)
374 return NULL;
375 ret->all_layouts = 1;
312 return ret;376 return ret;
313}377}
314 378
libavfilter/formats.h+31−0
@@ -69,14 +69,45 @@ struct AVFilterFormats { · 68 unmodified lines
69 struct AVFilterFormats ***refs; ///< references to this list69 struct AVFilterFormats ***refs; ///< references to this list
70};70};
71 71
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 */
72typedef struct AVFilterChannelLayouts {85typedef struct AVFilterChannelLayouts {
73 uint64_t *channel_layouts; ///< list of channel layouts86 uint64_t *channel_layouts; ///< list of channel layouts
74 int nb_channel_layouts; ///< number of channel layouts87 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
75 90
76 unsigned refcount; ///< number of references to this list91 unsigned refcount; ///< number of references to this list
77 struct AVFilterChannelLayouts ***refs; ///< references to this list92 struct AVFilterChannelLayouts ***refs; ///< references to this list
78} AVFilterChannelLayouts;93} AVFilterChannelLayouts;
79 94
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
80/**111/**
81 * Return a channel layouts/samplerates list which contains the intersection of112 * Return a channel layouts/samplerates list which contains the intersection of
82 * the layouts/samplerates of a and b. Also, all the references of a, all the113 * 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