1
0
mirror of https://github.com/mpv-player/mpv synced 2024-12-28 01:52:19 +00:00

f_hwtransfer: whitelist vaapi formats that actually appear to work

(Oh yes, we could have skipped all the complexity, and hardcoded the
cases that work in the first place. This wouldn't be an issue if FFmpeg
or libva exported correct information. Also possible that FFmpeg's
filter chain does not allow to do this correctly in the first place,
since filters expose next to no meta information about what hw formats
etc. they need.)

Note that uploading yuv420p to a nv12 vaapi surface actually works, but
the blacklist excludes it. So this might get a bit slower. I'm not
bothering with this case because it's rarely needed, and the blacklist
specification would become a bit more complex if you had to specify
sw/upload format pairs.

Fixes: #7350
This commit is contained in:
wm4 2020-01-11 22:41:38 +01:00
parent a009b57c77
commit 7555e2a42a

View File

@ -22,6 +22,25 @@ struct priv {
struct mp_hwupload public;
};
struct ffmpeg_and_other_bugs {
int imgfmt; // hw format
const int *const whitelist_formats; // if non-NULL, allow only these
// sw formats
bool force_same_upload_fmt; // force upload fmt == sw fmt
};
// This garbage is so complex and buggy. Hardcoding knowledge makes it work,
// trying to use the dynamic information returned by the API does not. So fuck
// this shit, I'll just whitelist the cases that work, what the fuck.
static const struct ffmpeg_and_other_bugs shitlist[] = {
{
.imgfmt = IMGFMT_VAAPI,
.whitelist_formats = (const int[]){IMGFMT_NV12, IMGFMT_P010, 0},
.force_same_upload_fmt = true,
},
{0}
};
static bool update_format_decision(struct priv *p, int input_fmt)
{
struct mp_hwupload *u = &p->public;
@ -223,6 +242,14 @@ static bool probe_formats(struct mp_hwupload *u, int hw_imgfmt)
// supported formats. This should be relatively cheap as we don't create
// any real frames (although some backends do for probing info).
const struct ffmpeg_and_other_bugs *bugs = NULL;
for (int n = 0; shitlist[n].imgfmt; n++) {
if (shitlist[n].imgfmt == hw_imgfmt) {
bugs = &shitlist[n];
break;
}
}
for (int n = 0; cstr->valid_sw_formats &&
cstr->valid_sw_formats[n] != AV_PIX_FMT_NONE; n++)
{
@ -230,12 +257,28 @@ static bool probe_formats(struct mp_hwupload *u, int hw_imgfmt)
if (!imgfmt)
continue;
MP_VERBOSE(u->f, "looking at format %s\n", mp_imgfmt_to_name(imgfmt));
MP_VERBOSE(u->f, "looking at format %s/%s\n",
mp_imgfmt_to_name(hw_imgfmt),
mp_imgfmt_to_name(imgfmt));
if (bugs && bugs->whitelist_formats) {
bool found = false;
for (int i = 0; bugs->whitelist_formats[i]; i++) {
if (bugs->whitelist_formats[i] == imgfmt) {
found = true;
break;
}
}
if (!found) {
MP_VERBOSE(u->f, "... skipping blacklisted format\n");
continue;
}
}
// Creates an AVHWFramesContexts with the given parameters.
AVBufferRef *frames = NULL;
if (!mp_update_av_hw_frames_pool(&frames, ctx->av_device_ref,
hw_imgfmt, imgfmt, 128, 128))
hw_imgfmt, imgfmt, 128, 128))
{
MP_WARN(u->f, "failed to allocate pool\n");
continue;
@ -256,7 +299,11 @@ static bool probe_formats(struct mp_hwupload *u, int hw_imgfmt)
int fmt = pixfmt2imgfmt(fmts[i]);
if (!fmt)
continue;
MP_VERBOSE(u->f, "supports %s\n", mp_imgfmt_to_name(fmt));
MP_VERBOSE(u->f, " supports %s\n", mp_imgfmt_to_name(fmt));
if (bugs && bugs->force_same_upload_fmt && imgfmt != fmt) {
MP_VERBOSE(u->f, " ... skipping blacklisted format\n");
continue;
}
if (vo_supports(ctx, hw_imgfmt, fmt))
MP_TARRAY_APPEND(p, u->upload_fmts, u->num_upload_fmts, fmt);
}