diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2012-07-28 01:42:19 +0400 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2012-07-28 01:42:19 +0400 |
commit | c6963a220d5849fd5399c056b21ec66de7a0df37 (patch) | |
tree | 142ce617e997fd542f0f2ccd460212b5a3dc6835 /libavfilter/avfiltergraph.c | |
parent | 94c3e11a6f62bf13a7e6f1b9287c6112bf6ee445 (diff) | |
parent | 5361e10a5e8740146c09a115477310c77b927215 (diff) |
Merge remote-tracking branch 'qatar/master'
* qatar/master:
proresdsp: port x86 assembly to cpuflags.
lavr: x86: improve non-SSE4 version of S16_TO_S32_SX macro
lavfi: better channel layout negotiation
alac: check for truncated packets
alac: reverse lpc coeff order, simplify filter
lavr: add x86-optimized mixing functions
x86: add support for fmaddps fma4 instruction with abstraction to avx/sse
tscc2: fix typo in array index
build: use COMPILE template for HOSTOBJS
build: do full flag handling for all compiler-type tools
eval: fix printing of NaN in eval fate test.
build: Rename aandct component to more descriptive aandcttables
mpegaudio: bury inline asm under HAVE_INLINE_ASM.
x86inc: automatically insert vzeroupper for YMM functions.
rtmp: Check the buffer length of ping packets
rtmp: Allow having more unknown data at the end of a chunk size packet without failing
rtmp: Prevent reading outside of an allocate buffer when receiving server bandwidth packets
Conflicts:
Makefile
configure
libavcodec/x86/proresdsp.asm
libavutil/eval.c
Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavfilter/avfiltergraph.c')
-rw-r--r-- | libavfilter/avfiltergraph.c | 83 |
1 files changed, 72 insertions, 11 deletions
diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c index 4b41529e3a..a5517fc5e0 100644 --- a/libavfilter/avfiltergraph.c +++ b/libavfilter/avfiltergraph.c @@ -578,11 +578,44 @@ static void swap_samplerates(AVFilterGraph *graph) swap_samplerates_on_filter(graph->filters[i]); } +#define CH_CENTER_PAIR (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER) +#define CH_FRONT_PAIR (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT) +#define CH_STEREO_PAIR (AV_CH_STEREO_LEFT | AV_CH_STEREO_RIGHT) +#define CH_WIDE_PAIR (AV_CH_WIDE_LEFT | AV_CH_WIDE_RIGHT) +#define CH_SIDE_PAIR (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT) +#define CH_DIRECT_PAIR (AV_CH_SURROUND_DIRECT_LEFT | AV_CH_SURROUND_DIRECT_RIGHT) +#define CH_BACK_PAIR (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT) + +/* allowable substitutions for channel pairs when comparing layouts, + * ordered by priority for both values */ +static const uint64_t ch_subst[][2] = { + { CH_FRONT_PAIR, CH_CENTER_PAIR }, + { CH_FRONT_PAIR, CH_WIDE_PAIR }, + { CH_FRONT_PAIR, AV_CH_FRONT_CENTER }, + { CH_CENTER_PAIR, CH_FRONT_PAIR }, + { CH_CENTER_PAIR, CH_WIDE_PAIR }, + { CH_CENTER_PAIR, AV_CH_FRONT_CENTER }, + { CH_WIDE_PAIR, CH_FRONT_PAIR }, + { CH_WIDE_PAIR, CH_CENTER_PAIR }, + { CH_WIDE_PAIR, AV_CH_FRONT_CENTER }, + { AV_CH_FRONT_CENTER, CH_FRONT_PAIR }, + { AV_CH_FRONT_CENTER, CH_CENTER_PAIR }, + { AV_CH_FRONT_CENTER, CH_WIDE_PAIR }, + { CH_SIDE_PAIR, CH_DIRECT_PAIR }, + { CH_SIDE_PAIR, CH_BACK_PAIR }, + { CH_SIDE_PAIR, AV_CH_BACK_CENTER }, + { CH_BACK_PAIR, CH_DIRECT_PAIR }, + { CH_BACK_PAIR, CH_SIDE_PAIR }, + { CH_BACK_PAIR, AV_CH_BACK_CENTER }, + { AV_CH_BACK_CENTER, CH_BACK_PAIR }, + { AV_CH_BACK_CENTER, CH_DIRECT_PAIR }, + { AV_CH_BACK_CENTER, CH_SIDE_PAIR }, +}; + static void swap_channel_layouts_on_filter(AVFilterContext *filter) { AVFilterLink *link = NULL; - uint64_t chlayout; - int i, j; + int i, j, k; for (i = 0; i < filter->nb_inputs; i++) { link = filter->inputs[i]; @@ -594,27 +627,55 @@ static void swap_channel_layouts_on_filter(AVFilterContext *filter) if (i == filter->nb_inputs) return; - chlayout = link->out_channel_layouts->channel_layouts[0]; - for (i = 0; i < filter->nb_outputs; i++) { AVFilterLink *outlink = filter->outputs[i]; - int best_idx, best_score = INT_MIN; + int best_idx, best_score = INT_MIN, best_count_diff = INT_MAX; if (outlink->type != AVMEDIA_TYPE_AUDIO || outlink->in_channel_layouts->nb_channel_layouts < 2) 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]; - int matched_channels = av_get_channel_layout_nb_channels(chlayout & - out_chlayout); - int extra_channels = av_get_channel_layout_nb_channels(out_chlayout & - (~chlayout)); - int score = matched_channels - extra_channels; + int in_channels = av_get_channel_layout_nb_channels(in_chlayout); + int out_channels = av_get_channel_layout_nb_channels(out_chlayout); + int count_diff = out_channels - in_channels; + int matched_channels, extra_channels; + int score = 0; + + /* channel substitution */ + for (k = 0; k < FF_ARRAY_ELEMS(ch_subst); k++) { + uint64_t cmp0 = ch_subst[k][0]; + uint64_t cmp1 = ch_subst[k][1]; + if (( in_chlayout & cmp0) && (!(out_chlayout & cmp0)) && + (out_chlayout & cmp1) && (!( in_chlayout & cmp1))) { + in_chlayout &= ~cmp0; + out_chlayout &= ~cmp1; + /* add score for channel match, minus a deduction for + having to do the substitution */ + score += 10 * av_get_channel_layout_nb_channels(cmp1) - 2; + } + } - if (score > best_score) { + /* no penalty for LFE channel mismatch */ + if ( (in_chlayout & AV_CH_LOW_FREQUENCY) && + (out_chlayout & AV_CH_LOW_FREQUENCY)) + score += 10; + in_chlayout &= ~AV_CH_LOW_FREQUENCY; + out_chlayout &= ~AV_CH_LOW_FREQUENCY; + + matched_channels = av_get_channel_layout_nb_channels(in_chlayout & + out_chlayout); + extra_channels = av_get_channel_layout_nb_channels(out_chlayout & + (~in_chlayout)); + score += 10 * matched_channels - 5 * extra_channels; + + if (score > best_score || + (count_diff < best_count_diff && score == best_score)) { best_score = score; best_idx = j; + best_count_diff = count_diff; } } FFSWAP(uint64_t, outlink->in_channel_layouts->channel_layouts[0], |