Unified · Split
| @@ -44,7 +44,7 @@ AVFilterBufferRef *ff_default_get_audio_buffer(AVFilterLink *link, int perms, · 43 unmodified lines | ||
| 44 | 44 | AVFilterBufferRef *samplesref = NULL; |
| 45 | 45 | uint8_t **data; |
| 46 | 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 | 48 | int planes = planar ? nb_channels : 1; |
| 49 | 49 | int linesize; |
| 50 | 50 | int full_perms = AV_PERM_READ | AV_PERM_WRITE | AV_PERM_PRESERVE | |
| @@ -96,9 +96,6 @@ AVFilterBufferRef *avfilter_get_audio_buffer_ref_from_frame(const AVFrame *frame · 95 unmodified lines | ||
| 96 | 96 | int channels = av_frame_get_channels(frame); |
| 97 | 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 | 99 | if (layout && av_get_channel_layout_nb_channels(layout) != av_frame_get_channels(frame)) { |
| 103 | 100 | av_log(0, AV_LOG_ERROR, "Layout indicates a different number of channels than actually present\n"); |
| 104 | 101 | return NULL; |
| @@ -185,9 +185,24 @@ AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, char *name) · 184 unmodified lines | ||
| 185 | 185 | return NULL; |
| 186 | 186 | } |
| 187 | 187 | |
| 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 | + | |
| 188 | 203 | static int filter_query_formats(AVFilterContext *ctx) |
| 189 | 204 | { |
| 190 | − int ret; | |
| 205 | + int ret, i; | |
| 191 | 206 | AVFilterFormats *formats; |
| 192 | 207 | AVFilterChannelLayouts *chlayouts; |
| 193 | 208 | AVFilterFormats *samplerates; |
| @@ -201,6 +216,11 @@ static int filter_query_formats(AVFilterContext *ctx) · 7 unmodified lines | ||
| 201 | 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 | 224 | formats = ff_all_formats(type); |
| 205 | 225 | if (!formats) |
| 206 | 226 | return AVERROR(ENOMEM); |
| @@ -470,7 +490,7 @@ static int pick_format(AVFilterLink *link, AVFilterLink *ref) · 263 unmodified lines | ||
| 470 | 490 | link->in_samplerates->format_count = 1; |
| 471 | 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 | 494 | av_log(link->src, AV_LOG_ERROR, "Cannot select channel layout for" |
| 475 | 495 | "the link between filters %s and %s.\n", link->src->name, |
| 476 | 496 | link->dst->name); |
| @@ -478,7 +498,10 @@ static int pick_format(AVFilterLink *link, AVFilterLink *ref) · 1 unmodified line | ||
| 478 | 498 | } |
| 479 | 499 | link->in_channel_layouts->nb_channel_layouts = 1; |
| 480 | 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 | 507 | ff_formats_unref(&link->in_formats); |
| @@ -534,8 +557,42 @@ static int reduce_formats_on_filter(AVFilterContext *filter) · 49 unmodified lines | ||
| 534 | 557 | format_count, ff_add_format); |
| 535 | 558 | REDUCE_FORMATS(int, AVFilterFormats, samplerates, formats, |
| 536 | 559 | 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 | + } | |
| 539 | 596 | |
| 540 | 597 | return ret; |
| 541 | 598 | } |
| @@ -663,7 +720,23 @@ static void swap_channel_layouts_on_filter(AVFilterContext *filter) · 121 unmodified lines | ||
| 663 | 720 | int out_channels = av_get_channel_layout_nb_channels(out_chlayout); |
| 664 | 721 | int count_diff = out_channels - in_channels; |
| 665 | 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 | 741 | /* channel substitution */ |
| 669 | 742 | for (k = 0; k < FF_ARRAY_ELEMS(ch_subst); k++) { |
| @@ -19,6 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 20 | 20 | */ |
| 21 | 21 | |
| 22 | +#include "libavutil/avassert.h" | |
| 22 | 23 | #include "libavutil/channel_layout.h" |
| 23 | 24 | #include "libavutil/common.h" |
| 24 | 25 | #include "libavutil/eval.h" |
| @@ -28,6 +29,8 @@ · 3 unmodified lines | ||
| 28 | 29 | #include "internal.h" |
| 29 | 30 | #include "formats.h" |
| 30 | 31 | |
| 32 | +#define KNOWN(l) (!FF_LAYOUT2COUNT(l)) /* for readability */ | |
| 33 | + | |
| 31 | 34 | /** |
| 32 | 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 | 139 | AVFilterChannelLayouts *b) |
| 137 | 140 | { |
| 138 | 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 | 146 | if (a == b) return a; |
| 141 | 147 | |
| 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 | + } | |
| 149 | 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 | 211 | return ret; |
| 212 | + | |
| 154 | 213 | fail: |
| 155 | 214 | if (ret) { |
| 156 | 215 | av_freep(&ret->refs); |
| @@ -248,17 +307,19 @@ do { \ · 91 unmodified lines | ||
| 248 | 307 | \ |
| 249 | 308 | (*f)->list = fmts; \ |
| 250 | 309 | (*f)->list[(*f)->nb++] = fmt; \ |
| 251 | − return 0; \ | |
| 252 | 310 | } while (0) |
| 253 | 311 | |
| 254 | 312 | int ff_add_format(AVFilterFormats **avff, int64_t fmt) |
| 255 | 313 | { |
| 256 | 314 | ADD_FORMAT(avff, fmt, int, formats, format_count); |
| 315 | + return 0; | |
| 257 | 316 | } |
| 258 | 317 | |
| 259 | 318 | int ff_add_channel_layout(AVFilterChannelLayouts **l, uint64_t channel_layout) |
| 260 | 319 | { |
| 320 | + av_assert1(!(*l && (*l)->all_layouts)); | |
| 261 | 321 | ADD_FORMAT(l, channel_layout, uint64_t, channel_layouts, nb_channel_layouts); |
| 322 | + return 0; | |
| 262 | 323 | } |
| 263 | 324 | |
| 264 | 325 | AVFilterFormats *ff_all_formats(enum AVMediaType type) |
| @@ -309,6 +370,9 @@ AVFilterFormats *ff_all_samplerates(void) · 44 unmodified lines | ||
| 309 | 370 | AVFilterChannelLayouts *ff_all_channel_layouts(void) |
| 310 | 371 | { |
| 311 | 372 | AVFilterChannelLayouts *ret = av_mallocz(sizeof(*ret)); |
| 373 | + if (!ret) | |
| 374 | + return NULL; | |
| 375 | + ret->all_layouts = 1; | |
| 312 | 376 | return ret; |
| 313 | 377 | } |
| 314 | 378 | |
| @@ -69,14 +69,45 @@ struct AVFilterFormats { · 68 unmodified lines | ||
| 69 | 69 | 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 | + */ | |
| 72 | 85 | typedef struct AVFilterChannelLayouts { |
| 73 | 86 | uint64_t *channel_layouts; ///< list of channel layouts |
| 74 | 87 | 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 | 91 | unsigned refcount; ///< number of references to this list |
| 77 | 92 | struct AVFilterChannelLayouts ***refs; ///< references to this list |
| 78 | 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 | 112 | * Return a channel layouts/samplerates list which contains the intersection of |
| 82 | 113 | * the layouts/samplerates of a and b. Also, all the references of a, all the |