Skip to content

Commit 02eda79

Browse files
committed
video: support priority order for VO format selection
1 parent 94e5a0f commit 02eda79

10 files changed

Lines changed: 52 additions & 22 deletions

File tree

filters/f_autoconvert.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ struct priv {
2424

2525
int *imgfmts;
2626
int *subfmts;
27+
uint8_t *priorities;
2728
int num_imgfmts;
2829
struct mp_image_params imgparams;
2930
bool imgparams_set;
@@ -69,15 +70,20 @@ void mp_autoconvert_clear(struct mp_autoconvert *c)
6970
p->force_update = true;
7071
}
7172

72-
void mp_autoconvert_add_imgfmt(struct mp_autoconvert *c, int imgfmt, int subfmt)
73+
void mp_autoconvert_add_imgfmt(struct mp_autoconvert *c, int imgfmt,
74+
int subfmt, uint8_t priority)
7375
{
7476
struct priv *p = c->f->priv;
7577

76-
MP_TARRAY_GROW(p, p->imgfmts, p->num_imgfmts);
77-
MP_TARRAY_GROW(p, p->subfmts, p->num_imgfmts);
78+
const int i = p->num_imgfmts;
7879

79-
p->imgfmts[p->num_imgfmts] = imgfmt;
80-
p->subfmts[p->num_imgfmts] = subfmt;
80+
MP_TARRAY_GROW(p, p->imgfmts, i);
81+
MP_TARRAY_GROW(p, p->subfmts, i);
82+
MP_TARRAY_GROW(p, p->priorities, i);
83+
84+
p->imgfmts[i] = imgfmt;
85+
p->subfmts[i] = subfmt;
86+
p->priorities[i] = priority;
8187

8288
p->num_imgfmts += 1;
8389
p->force_update = true;
@@ -97,14 +103,14 @@ void mp_autoconvert_set_target_image_params(struct mp_autoconvert *c,
97103
p->imgparams_set = true;
98104

99105
p->num_imgfmts = 0;
100-
mp_autoconvert_add_imgfmt(c, par->imgfmt, par->hw_subfmt);
106+
mp_autoconvert_add_imgfmt(c, par->imgfmt, par->hw_subfmt, 1);
101107
}
102108

103109
void mp_autoconvert_add_all_sw_imgfmts(struct mp_autoconvert *c)
104110
{
105111
for (int n = IMGFMT_START; n < IMGFMT_END; n++) {
106112
if (!IMGFMT_IS_HWACCEL(n))
107-
mp_autoconvert_add_imgfmt(c, n, 0);
113+
mp_autoconvert_add_imgfmt(c, n, 0, 1);
108114
}
109115
}
110116

@@ -307,7 +313,8 @@ static bool build_image_converter(struct mp_autoconvert *c, struct mp_log *log,
307313

308314
sws->force_scaler = c->force_scaler;
309315

310-
int out = mp_sws_find_best_out_format(sws, src_fmt, fmts, num_fmts);
316+
int out = mp_sws_find_best_out_format(sws, src_fmt, fmts,
317+
p->priorities, num_fmts);
311318
if (!out) {
312319
mp_err(log, "can't find video conversion for %s\n",
313320
mp_imgfmt_to_name(src_fmt));

filters/f_autoconvert.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ void mp_autoconvert_set_target_image_params(struct mp_autoconvert *c,
3939
// formats are allowed (even non-video).
4040
// subfmt can be used to specify underlying surface formats for hardware formats,
4141
// otherwise must be 0. (Mismatches lead to conversion errors.)
42-
void mp_autoconvert_add_imgfmt(struct mp_autoconvert *c, int imgfmt, int subfmt);
42+
// priority: higher is better
43+
void mp_autoconvert_add_imgfmt(struct mp_autoconvert *c, int imgfmt,
44+
int subfmt, uint8_t priority);
4345

4446
// Add all sw image formats. The effect is that hardware video image formats are
4547
// disallowed. The semantics are the same as calling mp_autoconvert_add_imgfmt()

filters/f_output_chain.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,14 @@ static void update_output_caps(struct chain *p)
8484
uint8_t allowed_output_formats[IMGFMT_END - IMGFMT_START] = {0};
8585
vo_query_formats(p->vo, allowed_output_formats);
8686

87+
MP_TRACE(p, "VO reports supported formats:\n");
8788
for (int n = 0; n < MP_ARRAY_SIZE(allowed_output_formats); n++) {
88-
if (allowed_output_formats[n])
89-
mp_autoconvert_add_imgfmt(p->convert, IMGFMT_START + n, 0);
89+
const uint8_t prio = allowed_output_formats[n];
90+
if (prio) {
91+
const int imgfmt = IMGFMT_START + n;
92+
mp_autoconvert_add_imgfmt(p->convert, imgfmt, 0, prio);
93+
MP_TRACE(p, " %-14s (%d)\n", mp_imgfmt_to_name(imgfmt), (int) prio);
94+
}
9095
}
9196
}
9297
}

filters/f_swscale.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,23 +41,32 @@
4141
#include "filter_internal.h"
4242

4343
int mp_sws_find_best_out_format(struct mp_sws_filter *sws, int in_format,
44-
int *out_formats, int num_out_formats)
44+
int *out_formats, uint8_t *priorities,
45+
int num_out_formats)
4546
{
4647
sws->sws->force_scaler = sws->force_scaler;
4748

4849
int best = 0;
50+
uint8_t prio = 0;
4951
for (int n = 0; n < num_out_formats; n++) {
5052
int out_format = out_formats[n];
5153

54+
if (priorities && priorities[n] < prio)
55+
continue;
56+
5257
if (!mp_sws_supports_formats(sws->sws, out_format, in_format))
5358
continue;
5459

5560
if (best) {
5661
int candidate = mp_imgfmt_select_best(best, out_format, in_format);
57-
if (candidate)
62+
if (candidate) {
5863
best = candidate;
64+
if (best == out_format && priorities)
65+
prio = priorities[n];
66+
}
5967
} else {
6068
best = out_format;
69+
prio = priorities ? priorities[n] : 0;
6170
}
6271
}
6372
return best;

filters/f_swscale.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@ struct mp_sws_filter *mp_sws_filter_create(struct mp_filter *parent);
2424

2525
// Return the best format based on the input format and a list of allowed output
2626
// formats. This tries to set the output format to the one that will result in
27-
// the least loss. Returns a format from out_formats[], or 0 if no format could
27+
// the least loss. If not NULL, priorities[] must be an array with the same size
28+
// as out_formats and will be taken into account when choosing (higher is better).
29+
// Returns a format from out_formats[], or 0 if no format could
2830
// be chosen (or it's not supported by libswscale).
2931
int mp_sws_find_best_out_format(struct mp_sws_filter *sws,
3032
int in_format, int *out_formats,
31-
int num_out_formats);
33+
uint8_t *priorities, int num_out_formats);
3234

3335
// Whether the given format is supported as input format.
3436
bool mp_sws_supports_input(int imgfmt);

player/playloop.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,16 +1024,19 @@ int handle_force_window(struct MPContext *mpctx, bool force)
10241024

10251025
if (!mpctx->video_out->config_ok || force) {
10261026
struct vo *vo = mpctx->video_out;
1027-
// Pick whatever works
1027+
// Pick most-preferred format
10281028
int config_format = 0;
1029+
uint8_t prio = 0;
10291030
uint8_t fmts[IMGFMT_END - IMGFMT_START] = {0};
10301031
vo_query_formats(vo, fmts);
10311032
for (int fmt = IMGFMT_START; fmt < IMGFMT_END; fmt++) {
1032-
if (fmts[fmt - IMGFMT_START]) {
1033+
if (fmts[fmt - IMGFMT_START] > prio) {
10331034
config_format = fmt;
1034-
break;
1035+
prio = fmts[fmt - IMGFMT_START];
10351036
}
10361037
}
1038+
if (!config_format)
1039+
goto err;
10371040

10381041
// Use a 16:9 aspect ratio so that fullscreen on a 16:9 screen will not
10391042
// have vertical margins, which can lead to a different size or position

video/filter/refqueue.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ struct mp_refqueue *mp_refqueue_alloc(struct mp_filter *f)
8181

8282
void mp_refqueue_add_in_format(struct mp_refqueue *q, int fmt, int subfmt)
8383
{
84-
mp_autoconvert_add_imgfmt(q->conv, fmt, subfmt);
84+
mp_autoconvert_add_imgfmt(q->conv, fmt, subfmt, 1);
8585
}
8686

8787
// The minimum number of frames required before and after the current frame.

video/filter/vf_format.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ static struct mp_filter *vf_format_create(struct mp_filter *parent, void *option
223223
priv->conv->force_scaler = priv->opts->force_scaler;
224224

225225
if (priv->opts->fmt)
226-
mp_autoconvert_add_imgfmt(priv->conv, priv->opts->fmt, 0);
226+
mp_autoconvert_add_imgfmt(priv->conv, priv->opts->fmt, 0, 1);
227227

228228
return f;
229229
}

video/filter/vf_vapoursynth.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -788,7 +788,7 @@ static struct mp_filter *vf_vapoursynth_create(struct mp_filter *parent,
788788
for (int n = 0; mpvs_fmt_table[n].bits; n++) {
789789
int imgfmt = mp_from_vs(mpvs_fmt_table[n].vs);
790790
if (imgfmt)
791-
mp_autoconvert_add_imgfmt(conv, imgfmt, 0);
791+
mp_autoconvert_add_imgfmt(conv, imgfmt, 0, 1);
792792
}
793793

794794
struct mp_filter *dur = mp_compute_frame_duration_create(f);

video/out/vo.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,8 +323,10 @@ struct vo_driver {
323323

324324
/*
325325
* Whether the given image format is supported and config() will succeed.
326+
* VO can choose fallback order of formats. Priority N-1 will only be considered if
327+
* no format of priority N is usable.
326328
* format: one of IMGFMT_*
327-
* returns: 0 on not supported, otherwise 1
329+
* returns: 0 if not supported, priority otherwise
328330
*/
329331
int (*query_format)(struct vo *vo, int format);
330332

0 commit comments

Comments
 (0)