mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-24 13:56:33 +02:00
avfilter: properly reduce YUV colorspace format lists
Doing this with REDUCE_FORMATS() instead of swap_color_*() is not only shorter, but more importantly comes with the benefit of being done inside a loop, allowing us to correctly propagate complex graphs involving multiple conversion filters (e.g. -vf scale,zscale). The latter family of swapping functions is only used to settle the best *remaining* entry if no exact match was found, and as such was never the correct solution to YUV colorspaces, which only care about exact matches. (cherry picked from commit b89ee2653919c14193f646ba03b2bf1d13c9aa2d)
This commit is contained in:
parent
87e5bc918a
commit
5cd6683ddc
@ -794,6 +794,10 @@ static int reduce_formats_on_filter(AVFilterContext *filter)
|
||||
nb_formats, ff_add_format);
|
||||
REDUCE_FORMATS(int, AVFilterFormats, samplerates, formats,
|
||||
nb_formats, ff_add_format);
|
||||
REDUCE_FORMATS(int, AVFilterFormats, color_spaces, formats,
|
||||
nb_formats, ff_add_format);
|
||||
REDUCE_FORMATS(int, AVFilterFormats, color_ranges, formats,
|
||||
nb_formats, ff_add_format);
|
||||
|
||||
/* reduce channel layouts */
|
||||
for (i = 0; i < filter->nb_inputs; i++) {
|
||||
@ -906,82 +910,6 @@ static void swap_samplerates(AVFilterGraph *graph)
|
||||
swap_samplerates_on_filter(graph->filters[i]);
|
||||
}
|
||||
|
||||
static void swap_color_spaces_on_filter(AVFilterContext *filter)
|
||||
{
|
||||
AVFilterLink *link = NULL;
|
||||
enum AVColorSpace csp;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < filter->nb_inputs; i++) {
|
||||
link = filter->inputs[i];
|
||||
if (link->type == AVMEDIA_TYPE_VIDEO &&
|
||||
link->outcfg.color_spaces->nb_formats == 1)
|
||||
break;
|
||||
}
|
||||
if (i == filter->nb_inputs)
|
||||
return;
|
||||
|
||||
csp = link->outcfg.color_spaces->formats[0];
|
||||
|
||||
for (i = 0; i < filter->nb_outputs; i++) {
|
||||
AVFilterLink *outlink = filter->outputs[i];
|
||||
if (outlink->type != AVMEDIA_TYPE_VIDEO)
|
||||
continue;
|
||||
/* there is no meaningful 'score' between different yuv matrices,
|
||||
* so just prioritize an exact match if it exists */
|
||||
for (int j = 0; j < outlink->incfg.color_spaces->nb_formats; j++) {
|
||||
if (csp == outlink->incfg.color_spaces->formats[j]) {
|
||||
FFSWAP(int, outlink->incfg.color_spaces->formats[0],
|
||||
outlink->incfg.color_spaces->formats[j]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void swap_color_spaces(AVFilterGraph *graph)
|
||||
{
|
||||
for (int i = 0; i < graph->nb_filters; i++)
|
||||
swap_color_spaces_on_filter(graph->filters[i]);
|
||||
}
|
||||
|
||||
static void swap_color_ranges_on_filter(AVFilterContext *filter)
|
||||
{
|
||||
AVFilterLink *link = NULL;
|
||||
enum AVColorRange range;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < filter->nb_inputs; i++) {
|
||||
link = filter->inputs[i];
|
||||
if (link->type == AVMEDIA_TYPE_VIDEO &&
|
||||
link->outcfg.color_ranges->nb_formats == 1)
|
||||
break;
|
||||
}
|
||||
if (i == filter->nb_inputs)
|
||||
return;
|
||||
|
||||
range = link->outcfg.color_ranges->formats[0];
|
||||
|
||||
for (i = 0; i < filter->nb_outputs; i++) {
|
||||
AVFilterLink *outlink = filter->outputs[i];
|
||||
if (outlink->type != AVMEDIA_TYPE_VIDEO)
|
||||
continue;
|
||||
for (int j = 0; j < outlink->incfg.color_ranges->nb_formats; j++) {
|
||||
if (range == outlink->incfg.color_ranges->formats[j]) {
|
||||
FFSWAP(int, outlink->incfg.color_ranges->formats[0],
|
||||
outlink->incfg.color_ranges->formats[j]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void swap_color_ranges(AVFilterGraph *graph)
|
||||
{
|
||||
for (int i = 0; i < graph->nb_filters; i++)
|
||||
swap_color_ranges_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)
|
||||
@ -1258,10 +1186,6 @@ static int graph_config_formats(AVFilterGraph *graph, void *log_ctx)
|
||||
if ((ret = reduce_formats(graph)) < 0)
|
||||
return ret;
|
||||
|
||||
/* for video filters, ensure that the best colorspace metadata is selected */
|
||||
swap_color_spaces(graph);
|
||||
swap_color_ranges(graph);
|
||||
|
||||
/* for audio filters, ensure the best format, sample rate and channel layout
|
||||
* is selected */
|
||||
swap_sample_fmts(graph);
|
||||
|
Loading…
x
Reference in New Issue
Block a user