|
|
@ -461,6 +461,74 @@ static void swap_channel_layouts(AVFilterGraph *graph) |
|
|
|
swap_channel_layouts_on_filter(graph->filters[i]); |
|
|
|
swap_channel_layouts_on_filter(graph->filters[i]); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void swap_sample_fmts_on_filter(AVFilterContext *filter) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
AVFilterLink *link = NULL; |
|
|
|
|
|
|
|
int format, bps; |
|
|
|
|
|
|
|
int i, j; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < filter->input_count; i++) { |
|
|
|
|
|
|
|
link = filter->inputs[i]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (link->type == AVMEDIA_TYPE_AUDIO && |
|
|
|
|
|
|
|
link->out_formats->format_count == 1) |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (i == filter->input_count) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
format = link->out_formats->formats[0]; |
|
|
|
|
|
|
|
bps = av_get_bytes_per_sample(format); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < filter->output_count; i++) { |
|
|
|
|
|
|
|
AVFilterLink *outlink = filter->outputs[i]; |
|
|
|
|
|
|
|
int best_idx, best_score = INT_MIN; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (outlink->type != AVMEDIA_TYPE_AUDIO || |
|
|
|
|
|
|
|
outlink->in_formats->format_count < 2) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (j = 0; j < outlink->in_formats->format_count; j++) { |
|
|
|
|
|
|
|
int out_format = outlink->in_formats->formats[j]; |
|
|
|
|
|
|
|
int out_bps = av_get_bytes_per_sample(out_format); |
|
|
|
|
|
|
|
int score; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (av_get_packed_sample_fmt(out_format) == format || |
|
|
|
|
|
|
|
av_get_planar_sample_fmt(out_format) == format) { |
|
|
|
|
|
|
|
best_idx = j; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* for s32 and float prefer double to prevent loss of information */ |
|
|
|
|
|
|
|
if (bps == 4 && out_bps == 8) { |
|
|
|
|
|
|
|
best_idx = j; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* prefer closest higher or equal bps */ |
|
|
|
|
|
|
|
score = -abs(out_bps - bps); |
|
|
|
|
|
|
|
if (out_bps >= bps) |
|
|
|
|
|
|
|
score += INT_MAX/2; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (score > best_score) { |
|
|
|
|
|
|
|
best_score = score; |
|
|
|
|
|
|
|
best_idx = j; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
FFSWAP(int, outlink->in_formats->formats[0], |
|
|
|
|
|
|
|
outlink->in_formats->formats[best_idx]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void swap_sample_fmts(AVFilterGraph *graph) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < graph->filter_count; i++) |
|
|
|
|
|
|
|
swap_sample_fmts_on_filter(graph->filters[i]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int pick_formats(AVFilterGraph *graph) |
|
|
|
static int pick_formats(AVFilterGraph *graph) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int i, j, ret; |
|
|
|
int i, j, ret; |
|
|
@ -491,8 +559,9 @@ int ff_avfilter_graph_config_formats(AVFilterGraph *graph, AVClass *log_ctx) |
|
|
|
* of format conversion inside filters */ |
|
|
|
* of format conversion inside filters */ |
|
|
|
reduce_formats(graph); |
|
|
|
reduce_formats(graph); |
|
|
|
|
|
|
|
|
|
|
|
/* for audio filters, ensure the best sample rate and channel layout
|
|
|
|
/* for audio filters, ensure the best format, sample rate and channel layout
|
|
|
|
* is selected */ |
|
|
|
* is selected */ |
|
|
|
|
|
|
|
swap_sample_fmts(graph); |
|
|
|
swap_samplerates(graph); |
|
|
|
swap_samplerates(graph); |
|
|
|
swap_channel_layouts(graph); |
|
|
|
swap_channel_layouts(graph); |
|
|
|
|
|
|
|
|
|
|
|