vo_gpu: hwdec_vaegl: refactor format probing

No functional changes, just preparation for the next commit. Split the
probing into multiple functions. Prepare for the yet unused possibility
to pass AVVAAPIHWConfig to probing. try_format_pixfmt() now assumes it
can be called multiple times with the same format, so it filters the
format.

The format probing is now something like O(n^2) for n formats, but n
will most likely remain something under 50 or so.
This commit is contained in:
wm4 2019-07-06 02:34:30 +02:00
parent f7d9365eb9
commit c42a21c9fa
1 changed files with 68 additions and 44 deletions

View File

@ -25,7 +25,11 @@
#include "config.h"
#include "video/out/gpu/hwdec.h"
#include "video/out/hwdec/hwdec_vaapi.h"
#include "video/fmt-conversion.h"
#include "video/mp_image_pool.h"
#include "video/vaapi.h"
#if HAVE_VAAPI_DRM
#include "libmpv/render_gl.h"
@ -325,7 +329,7 @@ err:
return -1;
}
static bool try_format(struct ra_hwdec *hw, struct mp_image *surface)
static bool try_format_map(struct ra_hwdec *hw, struct mp_image *surface)
{
bool ok = false;
struct ra_hwdec_mapper *mapper = ra_hwdec_mapper_create(hw, &surface->params);
@ -335,59 +339,79 @@ static bool try_format(struct ra_hwdec *hw, struct mp_image *surface)
return ok;
}
static void try_format_pixfmt(struct ra_hwdec *hw, enum AVPixelFormat pixfmt)
{
struct priv_owner *p = hw->priv;
int mp_fmt = pixfmt2imgfmt(pixfmt);
if (!mp_fmt)
return;
int num_formats = 0;
for (int n = 0; p->formats && p->formats[n]; n++) {
if (p->formats[n] == mp_fmt)
return; // already added
num_formats += 1;
}
AVBufferRef *fref = NULL;
struct mp_image *s = NULL;
AVFrame *frame = NULL;
fref = av_hwframe_ctx_alloc(p->ctx->av_device_ref);
if (!fref)
goto err;
AVHWFramesContext *fctx = (void *)fref->data;
fctx->format = AV_PIX_FMT_VAAPI;
fctx->sw_format = pixfmt;
fctx->width = 128;
fctx->height = 128;
if (av_hwframe_ctx_init(fref) < 0)
goto err;
frame = av_frame_alloc();
if (!frame)
goto err;
if (av_hwframe_get_buffer(fref, frame, 0) < 0)
goto err;
s = mp_image_from_av_frame(frame);
if (!s || !mp_image_params_valid(&s->params))
goto err;
if (try_format_map(hw, s)) {
MP_TARRAY_APPEND(p, p->formats, num_formats, mp_fmt);
MP_TARRAY_APPEND(p, p->formats, num_formats, 0); // terminate it
}
err:
talloc_free(s);
av_frame_free(&frame);
av_buffer_unref(&fref);
}
static void try_format_config(struct ra_hwdec *hw, AVVAAPIHWConfig *hwconfig)
{
struct priv_owner *p = hw->priv;
AVHWFramesConstraints *fc =
av_hwdevice_get_hwframe_constraints(p->ctx->av_device_ref, hwconfig);
if (!fc) {
MP_WARN(hw, "failed to retrieve libavutil frame constraints\n");
return;
}
for (int n = 0; fc->valid_sw_formats[n] != AV_PIX_FMT_NONE; n++)
try_format_pixfmt(hw, fc->valid_sw_formats[n]);
av_hwframe_constraints_free(&fc);
}
static void determine_working_formats(struct ra_hwdec *hw)
{
struct priv_owner *p = hw->priv;
int num_formats = 0;
int *formats = NULL;
p->probing_formats = true;
AVHWFramesConstraints *fc =
av_hwdevice_get_hwframe_constraints(p->ctx->av_device_ref, NULL);
if (!fc) {
MP_WARN(hw, "failed to retrieve libavutil frame constraints\n");
goto done;
}
for (int n = 0; fc->valid_sw_formats[n] != AV_PIX_FMT_NONE; n++) {
AVBufferRef *fref = NULL;
struct mp_image *s = NULL;
AVFrame *frame = NULL;
fref = av_hwframe_ctx_alloc(p->ctx->av_device_ref);
if (!fref)
goto err;
AVHWFramesContext *fctx = (void *)fref->data;
fctx->format = AV_PIX_FMT_VAAPI;
fctx->sw_format = fc->valid_sw_formats[n];
fctx->width = 128;
fctx->height = 128;
if (av_hwframe_ctx_init(fref) < 0)
goto err;
frame = av_frame_alloc();
if (!frame)
goto err;
if (av_hwframe_get_buffer(fref, frame, 0) < 0)
goto err;
s = mp_image_from_av_frame(frame);
if (!s || !mp_image_params_valid(&s->params))
goto err;
if (try_format(hw, s))
MP_TARRAY_APPEND(p, formats, num_formats, s->params.hw_subfmt);
err:
talloc_free(s);
av_frame_free(&frame);
av_buffer_unref(&fref);
}
av_hwframe_constraints_free(&fc);
try_format_config(hw, NULL);
done:
MP_TARRAY_APPEND(p, formats, num_formats, 0); // terminate it
p->formats = formats;
p->probing_formats = false;
MP_VERBOSE(hw, "Supported formats:\n");
for (int n = 0; formats[n]; n++)
MP_VERBOSE(hw, " %s\n", mp_imgfmt_to_name(formats[n]));
for (int n = 0; p->formats && p->formats[n]; n++)
MP_VERBOSE(hw, " %s\n", mp_imgfmt_to_name(p->formats[n]));
}
const struct ra_hwdec_driver ra_hwdec_vaegl = {