summaryrefslogtreecommitdiffstats
path: root/filters/f_hwtransfer.c
diff options
context:
space:
mode:
Diffstat (limited to 'filters/f_hwtransfer.c')
-rw-r--r--filters/f_hwtransfer.c53
1 files changed, 50 insertions, 3 deletions
diff --git a/filters/f_hwtransfer.c b/filters/f_hwtransfer.c
index 51ffbadbb9..f75e2dab28 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);
}