diff --git a/filters/f_hwtransfer.c b/filters/f_hwtransfer.c index 51ffbadbb958..f75e2dab28a0 100644 --- a/filters/f_hwtransfer.c +++ b/filters/f_hwtransfer.c @@ -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); }