1
0
mirror of https://github.com/mpv-player/mpv synced 2025-01-03 05:22:23 +00:00

vaapi: mp_msg conversions

This ended up a little bit messy. In order to get a mp_log everywhere,
mostly make use of the fact that va_surface already references global
state anyway.
This commit is contained in:
wm4 2013-12-21 18:11:01 +01:00
parent 9e0b84c321
commit 70af7ab8e5
6 changed files with 135 additions and 123 deletions

View File

@ -55,6 +55,7 @@
#define MAX_SURFACES (MAX_DECODER_SURFACES + ADDTIONAL_SURFACES) #define MAX_SURFACES (MAX_DECODER_SURFACES + ADDTIONAL_SURFACES)
struct priv { struct priv {
struct mp_log *log;
struct mp_vaapi_ctx *ctx; struct mp_vaapi_ctx *ctx;
VADisplay display; VADisplay display;
Display *x11_display; Display *x11_display;
@ -166,7 +167,7 @@ static bool preallocate_surfaces(struct lavc_ctx *ctx, int num)
{ {
struct priv *p = ctx->hwdec_priv; struct priv *p = ctx->hwdec_priv;
if (!va_surface_pool_reserve(p->pool, num, p->w, p->h)) { if (!va_surface_pool_reserve(p->pool, num, p->w, p->h)) {
mp_msg(MSGT_VO, MSGL_ERR, "[vaapi] Could not allocate surfaces.\n"); MP_ERR(p, "Could not allocate surfaces.\n");
return false; return false;
} }
for (int i = 0; i < num; i++) { for (int i = 0; i < num; i++) {
@ -218,57 +219,55 @@ static int create_decoder(struct lavc_ctx *ctx)
const struct hwdec_profile_entry *pe = hwdec_find_profile(ctx, profiles); const struct hwdec_profile_entry *pe = hwdec_find_profile(ctx, profiles);
if (!pe) { if (!pe) {
mp_msg(MSGT_VO, MSGL_ERR, "[vaapi] Unsupported codec or profile.\n"); MP_ERR(p, "Unsupported codec or profile.\n");
goto error; goto error;
} }
int num_profiles = vaMaxNumProfiles(p->display); int num_profiles = vaMaxNumProfiles(p->display);
VAProfile *va_profiles = talloc_zero_array(tmp, VAProfile, num_profiles); VAProfile *va_profiles = talloc_zero_array(tmp, VAProfile, num_profiles);
status = vaQueryConfigProfiles(p->display, va_profiles, &num_profiles); status = vaQueryConfigProfiles(p->display, va_profiles, &num_profiles);
if (!check_va_status(status, "vaQueryConfigProfiles()")) if (!CHECK_VA_STATUS(p, "vaQueryConfigProfiles()"))
goto error; goto error;
mp_msg(MSGT_VO, MSGL_DBG2, "[vaapi] %d profiles available:\n", num_profiles); MP_DBG(p, "%d profiles available:\n", num_profiles);
for (int i = 0; i < num_profiles; i++) for (int i = 0; i < num_profiles; i++)
mp_msg(MSGT_VO, MSGL_DBG2, " %s\n", str_va_profile(va_profiles[i])); MP_DBG(p, " %s\n", str_va_profile(va_profiles[i]));
VAProfile va_profile = pe->hw_profile; VAProfile va_profile = pe->hw_profile;
if (!has_profile(va_profiles, num_profiles, va_profile)) { if (!has_profile(va_profiles, num_profiles, va_profile)) {
mp_msg(MSGT_VO, MSGL_ERR, MP_ERR(p, "Decoder profile '%s' not available.\n",
"[vaapi] Decoder profile '%s' not available.\n",
str_va_profile(va_profile)); str_va_profile(va_profile));
goto error; goto error;
} }
mp_msg(MSGT_VO, MSGL_V, "[vaapi] Using profile '%s'.\n", MP_VERBOSE(p, "Using profile '%s'.\n", str_va_profile(va_profile));
str_va_profile(va_profile));
int num_surfaces = hwdec_get_max_refs(ctx); int num_surfaces = hwdec_get_max_refs(ctx);
if (!is_direct_mapping(p->display)) { if (!is_direct_mapping(p->display)) {
mp_msg(MSGT_VO, MSGL_V, "[vaapi] No direct mapping.\n"); MP_VERBOSE(p, "No direct mapping.\n");
// Note: not sure why it has to be *=2 rather than +=1. // Note: not sure why it has to be *=2 rather than +=1.
num_surfaces *= 2; num_surfaces *= 2;
} }
num_surfaces = MPMIN(num_surfaces, MAX_DECODER_SURFACES) + ADDTIONAL_SURFACES; num_surfaces = MPMIN(num_surfaces, MAX_DECODER_SURFACES) + ADDTIONAL_SURFACES;
if (num_surfaces > MAX_SURFACES) { if (num_surfaces > MAX_SURFACES) {
mp_msg(MSGT_VO, MSGL_ERR, "[vaapi] Internal error: too many surfaces.\n"); MP_ERR(p, "Internal error: too many surfaces.\n");
goto error; goto error;
} }
if (!preallocate_surfaces(ctx, num_surfaces)) { if (!preallocate_surfaces(ctx, num_surfaces)) {
mp_msg(MSGT_VO, MSGL_ERR, "[vaapi] Could not allocate surfaces.\n"); MP_ERR(p, "Could not allocate surfaces.\n");
goto error; goto error;
} }
int num_ep = vaMaxNumEntrypoints(p->display); int num_ep = vaMaxNumEntrypoints(p->display);
VAEntrypoint *ep = talloc_zero_array(tmp, VAEntrypoint, num_ep); VAEntrypoint *ep = talloc_zero_array(tmp, VAEntrypoint, num_ep);
status = vaQueryConfigEntrypoints(p->display, va_profile, ep, &num_ep); status = vaQueryConfigEntrypoints(p->display, va_profile, ep, &num_ep);
if (!check_va_status(status, "vaQueryConfigEntrypoints()")) if (!CHECK_VA_STATUS(p, "vaQueryConfigEntrypoints()"))
goto error; goto error;
int entrypoint = find_entrypoint(p->format, ep, num_ep); int entrypoint = find_entrypoint(p->format, ep, num_ep);
if (entrypoint < 0) { if (entrypoint < 0) {
mp_msg(MSGT_VO, MSGL_ERR, "[vaapi] Could not find VA entrypoint.\n"); MP_ERR(p, "Could not find VA entrypoint.\n");
goto error; goto error;
} }
@ -277,23 +276,23 @@ static int create_decoder(struct lavc_ctx *ctx)
}; };
status = vaGetConfigAttributes(p->display, va_profile, entrypoint, status = vaGetConfigAttributes(p->display, va_profile, entrypoint,
&attrib, 1); &attrib, 1);
if (!check_va_status(status, "vaGetConfigAttributes()")) if (!CHECK_VA_STATUS(p, "vaGetConfigAttributes()"))
goto error; goto error;
if ((attrib.value & p->rt_format) == 0) { if ((attrib.value & p->rt_format) == 0) {
mp_msg(MSGT_VO, MSGL_ERR, "[vaapi] Chroma format not supported.\n"); MP_ERR(p, "Chroma format not supported.\n");
goto error; goto error;
} }
status = vaCreateConfig(p->display, va_profile, entrypoint, &attrib, 1, status = vaCreateConfig(p->display, va_profile, entrypoint, &attrib, 1,
&p->va_context->config_id); &p->va_context->config_id);
if (!check_va_status(status, "vaCreateConfig()")) if (!CHECK_VA_STATUS(p, "vaCreateConfig()"))
goto error; goto error;
status = vaCreateContext(p->display, p->va_context->config_id, status = vaCreateContext(p->display, p->va_context->config_id,
p->w, p->h, VA_PROGRESSIVE, p->w, p->h, VA_PROGRESSIVE,
p->surfaces, num_surfaces, p->surfaces, num_surfaces,
&p->va_context->context_id); &p->va_context->context_id);
if (!check_va_status(status, "vaCreateContext()")) if (!CHECK_VA_STATUS(p, "vaCreateContext()"))
goto error; goto error;
res = 0; res = 0;
@ -328,7 +327,7 @@ static struct mp_image *allocate_image(struct lavc_ctx *ctx, int format,
} }
va_surface_release(s); va_surface_release(s);
} }
mp_msg(MSGT_VO, MSGL_ERR, "[vaapi] Insufficient number of surfaces.\n"); MP_ERR(p, "Insufficient number of surfaces.\n");
return NULL; return NULL;
} }
@ -353,7 +352,7 @@ static bool create_va_dummy_ctx(struct priv *p)
VADisplay *display = vaGetDisplay(p->x11_display); VADisplay *display = vaGetDisplay(p->x11_display);
if (!display) if (!display)
goto destroy_ctx; goto destroy_ctx;
p->ctx = va_initialize(display); p->ctx = va_initialize(display, p->log);
if (!p->ctx) { if (!p->ctx) {
vaTerminate(display); vaTerminate(display);
goto destroy_ctx; goto destroy_ctx;
@ -385,6 +384,7 @@ static int init_with_vactx(struct lavc_ctx *ctx, struct mp_vaapi_ctx *vactx)
{ {
struct priv *p = talloc_ptrtype(NULL, p); struct priv *p = talloc_ptrtype(NULL, p);
*p = (struct priv) { *p = (struct priv) {
.log = mp_log_new(p, ctx->log, "vaapi"),
.ctx = vactx, .ctx = vactx,
.va_context = &p->va_context_storage, .va_context = &p->va_context_storage,
.rt_format = VA_RT_FORMAT_YUV420 .rt_format = VA_RT_FORMAT_YUV420
@ -398,7 +398,7 @@ static int init_with_vactx(struct lavc_ctx *ctx, struct mp_vaapi_ctx *vactx)
} }
p->display = p->ctx->display; p->display = p->ctx->display;
p->pool = va_surface_pool_alloc(p->display, p->rt_format); p->pool = va_surface_pool_alloc(p->ctx, p->rt_format);
p->sw_pool = talloc_steal(p, mp_image_pool_new(17)); p->sw_pool = talloc_steal(p, mp_image_pool_new(17));
p->va_context->display = p->display; p->va_context->display = p->display;
@ -432,7 +432,7 @@ static int probe(struct vd_lavc_hwdec *hwdec, struct mp_hwdec_info *info,
static int probe_copy(struct vd_lavc_hwdec *hwdec, struct mp_hwdec_info *info, static int probe_copy(struct vd_lavc_hwdec *hwdec, struct mp_hwdec_info *info,
const char *decoder) const char *decoder)
{ {
struct priv dummy = {0}; struct priv dummy = {mp_null_log};
if (!create_va_dummy_ctx(&dummy)) if (!create_va_dummy_ctx(&dummy))
return HWDEC_ERR_NO_CTX; return HWDEC_ERR_NO_CTX;
destroy_va_dummy_ctx(&dummy); destroy_va_dummy_ctx(&dummy);
@ -452,12 +452,10 @@ static struct mp_image *copy_image(struct lavc_ctx *ctx, struct mp_image *img)
struct va_surface *surface = va_surface_in_mp_image(img); struct va_surface *surface = va_surface_in_mp_image(img);
if (surface) { if (surface) {
struct mp_image *simg = struct mp_image *simg = va_surface_download(surface, p->sw_pool);
va_surface_download(surface, p->ctx->image_formats, p->sw_pool);
if (simg) { if (simg) {
if (!p->printed_readback_warning) { if (!p->printed_readback_warning) {
mp_msg(MSGT_VO, MSGL_WARN, "[vaapi] Using GPU readback. This " MP_WARN(p, "Using GPU readback. This is usually inefficient.\n");
"is usually inefficient.\n");
p->printed_readback_warning = true; p->printed_readback_warning = true;
} }
talloc_free(img); talloc_free(img);

View File

@ -24,11 +24,11 @@
#include "video/vaapi.h" #include "video/vaapi.h"
#include "video/hwdec.h" #include "video/hwdec.h"
static inline bool is_success(VAStatus status, const char *msg) static bool check_error(struct vf_instance *vf, VAStatus status, const char *msg)
{ {
if (status == VA_STATUS_SUCCESS) if (status == VA_STATUS_SUCCESS)
return true; return true;
mp_msg(MSGT_VFILTER, MSGL_ERR, "[vavpp] %s: %s\n", msg, vaErrorStr(status)); MP_ERR(vf, "%s: %s\n", msg, vaErrorStr(status));
return false; return false;
} }
@ -78,8 +78,9 @@ static inline void realloc_refs(struct surface_refs *refs, int num)
refs->num_required = num; refs->num_required = num;
} }
static bool update_pipeline(struct vf_priv_s *p, bool deint) static bool update_pipeline(struct vf_instance *vf, bool deint)
{ {
struct vf_priv_s *p = vf->priv;
VABufferID *filters = p->buffers; VABufferID *filters = p->buffers;
int num_filters = p->num_buffers; int num_filters = p->num_buffers;
if (p->deint_type && !deint) { if (p->deint_type && !deint) {
@ -101,7 +102,7 @@ static bool update_pipeline(struct vf_priv_s *p, bool deint)
caps.num_output_color_standards = VAProcColorStandardCount; caps.num_output_color_standards = VAProcColorStandardCount;
VAStatus status = vaQueryVideoProcPipelineCaps(p->display, p->context, VAStatus status = vaQueryVideoProcPipelineCaps(p->display, p->context,
filters, num_filters, &caps); filters, num_filters, &caps);
if (!is_success(status, "vaQueryVideoProcPipelineCaps()")) if (!check_error(vf, status, "vaQueryVideoProcPipelineCaps()"))
return false; return false;
p->pipe.filters = filters; p->pipe.filters = filters;
p->pipe.num_filters = num_filters; p->pipe.num_filters = num_filters;
@ -120,9 +121,10 @@ static inline int get_deint_field(struct vf_priv_s *p, int i,
return !!(mpi->fields & MP_IMGFIELD_TOP_FIRST) ^ i ? VA_TOP_FIELD : VA_BOTTOM_FIELD; return !!(mpi->fields & MP_IMGFIELD_TOP_FIRST) ^ i ? VA_TOP_FIELD : VA_BOTTOM_FIELD;
} }
static struct mp_image *render(struct vf_priv_s *p, struct va_surface *in, static struct mp_image *render(struct vf_instance *vf, struct va_surface *in,
unsigned int flags) unsigned int flags)
{ {
struct vf_priv_s *p = vf->priv;
if (!p->pipe.filters || !in) if (!p->pipe.filters || !in)
return NULL; return NULL;
struct va_surface *out = va_surface_pool_get(p->pool, in->w, in->h); struct va_surface *out = va_surface_pool_get(p->pool, in->w, in->h);
@ -132,7 +134,7 @@ static struct mp_image *render(struct vf_priv_s *p, struct va_surface *in,
int state = 0; int state = 0;
do { // not a loop, just for break do { // not a loop, just for break
VAStatus status = vaBeginPicture(p->display, p->context, out->id); VAStatus status = vaBeginPicture(p->display, p->context, out->id);
if (!is_success(status, "vaBeginPicture()")) if (!check_error(vf, status, "vaBeginPicture()"))
break; break;
state |= Begun; state |= Begun;
VABufferID buffer = VA_INVALID_ID; VABufferID buffer = VA_INVALID_ID;
@ -140,10 +142,10 @@ static struct mp_image *render(struct vf_priv_s *p, struct va_surface *in,
status = vaCreateBuffer(p->display, p->context, status = vaCreateBuffer(p->display, p->context,
VAProcPipelineParameterBufferType, VAProcPipelineParameterBufferType,
sizeof(*param), 1, NULL, &buffer); sizeof(*param), 1, NULL, &buffer);
if (!is_success(status, "vaCreateBuffer()")) if (!check_error(vf, status, "vaCreateBuffer()"))
break; break;
status = vaMapBuffer(p->display, buffer, (void**)&param); status = vaMapBuffer(p->display, buffer, (void**)&param);
if (!is_success(status, "vaMapBuffer()")) if (!check_error(vf, status, "vaMapBuffer()"))
break; break;
param->surface = in->id; param->surface = in->id;
param->surface_region = NULL; param->surface_region = NULL;
@ -158,7 +160,7 @@ static struct mp_image *render(struct vf_priv_s *p, struct va_surface *in,
param->num_forward_references = p->pipe.forward.num_required; param->num_forward_references = p->pipe.forward.num_required;
param->num_backward_references = p->pipe.backward.num_required; param->num_backward_references = p->pipe.backward.num_required;
status = vaRenderPicture(p->display, p->context, &buffer, 1); status = vaRenderPicture(p->display, p->context, &buffer, 1);
if (!is_success(status, "vaRenderPicture()")) if (!check_error(vf, status, "vaRenderPicture()"))
break; break;
state |= Rendered; state |= Rendered;
} while (false); } while (false);
@ -171,16 +173,17 @@ static struct mp_image *render(struct vf_priv_s *p, struct va_surface *in,
} }
// return value: the number of created images // return value: the number of created images
static int process(struct vf_priv_s *p, struct mp_image *in, static int process(struct vf_instance *vf, struct mp_image *in,
struct mp_image **out1, struct mp_image **out2) struct mp_image **out1, struct mp_image **out2)
{ {
struct vf_priv_s *p = vf->priv;
const bool deint = p->do_deint && p->deint_type > 0; const bool deint = p->do_deint && p->deint_type > 0;
if (!update_pipeline(p, deint) || !p->pipe.filters) // no filtering if (!update_pipeline(vf, deint) || !p->pipe.filters) // no filtering
return 0; return 0;
struct va_surface *surface = va_surface_in_mp_image(in); struct va_surface *surface = va_surface_in_mp_image(in);
const unsigned int csp = va_get_colorspace_flag(p->params.colorspace); const unsigned int csp = va_get_colorspace_flag(p->params.colorspace);
const unsigned int field = get_deint_field(p, 0, in); const unsigned int field = get_deint_field(p, 0, in);
*out1 = render(p, surface, field | csp); *out1 = render(vf, surface, field | csp);
if (!*out1) // cannot render if (!*out1) // cannot render
return 0; return 0;
mp_image_copy_attributes(*out1, in); mp_image_copy_attributes(*out1, in);
@ -189,7 +192,7 @@ static int process(struct vf_priv_s *p, struct mp_image *in,
const double add = (in->pts - p->prev_pts)*0.5; const double add = (in->pts - p->prev_pts)*0.5;
if (p->prev_pts == MP_NOPTS_VALUE || add <= 0.0 || add > 0.5) // no pts, skip it if (p->prev_pts == MP_NOPTS_VALUE || add <= 0.0 || add > 0.5) // no pts, skip it
return 1; return 1;
*out2 = render(p, surface, get_deint_field(p, 1, in) | csp); *out2 = render(vf, surface, get_deint_field(p, 1, in) | csp);
if (!*out2) // cannot render if (!*out2) // cannot render
return 1; return 1;
mp_image_copy_attributes(*out2, in); mp_image_copy_attributes(*out2, in);
@ -197,10 +200,11 @@ static int process(struct vf_priv_s *p, struct mp_image *in,
return 2; return 2;
} }
static struct mp_image *upload(struct vf_priv_s *p, struct mp_image *in) static struct mp_image *upload(struct vf_instance *vf, struct mp_image *in)
{ {
struct vf_priv_s *p = vf->priv;
struct va_surface *surface = struct va_surface *surface =
va_surface_pool_get_by_imgfmt(p->pool, p->va->image_formats, in->imgfmt, in->w, in->h); va_surface_pool_get_by_imgfmt(p->pool, in->imgfmt, in->w, in->h);
if (!surface) if (!surface)
surface = va_surface_pool_get(p->pool, in->w, in->h); // dummy surface = va_surface_pool_get(p->pool, in->w, in->h); // dummy
else else
@ -217,17 +221,17 @@ static int filter_ext(struct vf_instance *vf, struct mp_image *in)
const int rt_format = surface ? surface->rt_format : VA_RT_FORMAT_YUV420; const int rt_format = surface ? surface->rt_format : VA_RT_FORMAT_YUV420;
if (!p->pool || va_surface_pool_rt_format(p->pool) != rt_format) { if (!p->pool || va_surface_pool_rt_format(p->pool) != rt_format) {
va_surface_pool_release(p->pool); va_surface_pool_release(p->pool);
p->pool = va_surface_pool_alloc(p->display, rt_format); p->pool = va_surface_pool_alloc(p->va, rt_format);
} }
if (!surface) { if (!surface) {
struct mp_image *tmp = upload(p, in); struct mp_image *tmp = upload(vf, in);
talloc_free(in); talloc_free(in);
in = tmp; in = tmp;
} }
struct mp_image *out1, *out2; struct mp_image *out1, *out2;
const double pts = in->pts; const double pts = in->pts;
const int num = process(p, in, &out1, &out2); const int num = process(vf, in, &out1, &out2);
if (!num) if (!num)
vf_add_output_frame(vf, in); vf_add_output_frame(vf, in);
else { else {
@ -289,45 +293,48 @@ static int control(struct vf_instance *vf, int request, void* data)
} }
} }
static int va_query_filter_caps(struct vf_priv_s *p, VAProcFilterType type, static int va_query_filter_caps(struct vf_instance *vf, VAProcFilterType type,
void *caps, unsigned int count) void *caps, unsigned int count)
{ {
struct vf_priv_s *p = vf->priv;
VAStatus status = vaQueryVideoProcFilterCaps(p->display, p->context, type, VAStatus status = vaQueryVideoProcFilterCaps(p->display, p->context, type,
caps, &count); caps, &count);
return is_success(status, "vaQueryVideoProcFilterCaps()") ? count : 0; return check_error(vf, status, "vaQueryVideoProcFilterCaps()") ? count : 0;
} }
static VABufferID va_create_filter_buffer(struct vf_priv_s *p, int bytes, static VABufferID va_create_filter_buffer(struct vf_instance *vf, int bytes,
int num, void *data) int num, void *data)
{ {
struct vf_priv_s *p = vf->priv;
VABufferID buffer; VABufferID buffer;
VAStatus status = vaCreateBuffer(p->display, p->context, VAStatus status = vaCreateBuffer(p->display, p->context,
VAProcFilterParameterBufferType, VAProcFilterParameterBufferType,
bytes, num, data, &buffer); bytes, num, data, &buffer);
return is_success(status, "vaCreateBuffer()") ? buffer : VA_INVALID_ID; return check_error(vf, status, "vaCreateBuffer()") ? buffer : VA_INVALID_ID;
} }
static bool initialize(struct vf_priv_s *p) static bool initialize(struct vf_instance *vf)
{ {
struct vf_priv_s *p = vf->priv;
VAStatus status; VAStatus status;
VAConfigID config; VAConfigID config;
status = vaCreateConfig(p->display, VAProfileNone, VAEntrypointVideoProc, status = vaCreateConfig(p->display, VAProfileNone, VAEntrypointVideoProc,
NULL, 0, &config); NULL, 0, &config);
if (!is_success(status, "vaCreateConfig()")) // no entrypoint for video porc if (!check_error(vf, status, "vaCreateConfig()")) // no entrypoint for video porc
return false; return false;
p->config = config; p->config = config;
VAContextID context; VAContextID context;
status = vaCreateContext(p->display, p->config, 0, 0, 0, NULL, 0, &context); status = vaCreateContext(p->display, p->config, 0, 0, 0, NULL, 0, &context);
if (!is_success(status, "vaCreateContext()")) if (!check_error(vf, status, "vaCreateContext()"))
return false; return false;
p->context = context; p->context = context;
VAProcFilterType filters[VAProcFilterCount]; VAProcFilterType filters[VAProcFilterCount];
int num_filters = VAProcFilterCount; int num_filters = VAProcFilterCount;
status = vaQueryVideoProcFilters(p->display, p->context, filters, &num_filters); status = vaQueryVideoProcFilters(p->display, p->context, filters, &num_filters);
if (!is_success(status, "vaQueryVideoProcFilters()")) if (!check_error(vf, status, "vaQueryVideoProcFilters()"))
return false; return false;
VABufferID buffers[VAProcFilterCount]; VABufferID buffers[VAProcFilterCount];
@ -338,7 +345,7 @@ static bool initialize(struct vf_priv_s *p)
if (!p->deint_type) if (!p->deint_type)
continue; continue;
VAProcFilterCapDeinterlacing caps[VAProcDeinterlacingCount]; VAProcFilterCapDeinterlacing caps[VAProcDeinterlacingCount];
int num = va_query_filter_caps(p, VAProcFilterDeinterlacing, caps, int num = va_query_filter_caps(vf, VAProcFilterDeinterlacing, caps,
VAProcDeinterlacingCount); VAProcDeinterlacingCount);
if (!num) if (!num)
continue; continue;
@ -350,7 +357,7 @@ static bool initialize(struct vf_priv_s *p)
param.type = VAProcFilterDeinterlacing; param.type = VAProcFilterDeinterlacing;
param.algorithm = algorithm; param.algorithm = algorithm;
buffers[VAProcFilterDeinterlacing] = buffers[VAProcFilterDeinterlacing] =
va_create_filter_buffer(p, sizeof(param), 1, &param); va_create_filter_buffer(vf, sizeof(param), 1, &param);
} }
} // check other filters } // check other filters
} }
@ -378,7 +385,7 @@ static int vf_open(vf_instance_t *vf)
if (!p->va || !p->va->display) if (!p->va || !p->va->display)
return false; return false;
p->display = p->va->display; p->display = p->va->display;
if (initialize(p)) if (initialize(vf))
return true; return true;
uninit(vf); uninit(vf);
return false; return false;

View File

@ -29,6 +29,7 @@
#include "video/hwdec.h" #include "video/hwdec.h"
struct priv { struct priv {
struct mp_log *log;
struct mp_vaapi_ctx *ctx; struct mp_vaapi_ctx *ctx;
VADisplay *display; VADisplay *display;
GLuint gl_texture; GLuint gl_texture;
@ -42,7 +43,7 @@ static void destroy_texture(struct gl_hwdec *hw)
if (p->vaglx_surface) { if (p->vaglx_surface) {
status = vaDestroySurfaceGLX(p->display, p->vaglx_surface); status = vaDestroySurfaceGLX(p->display, p->vaglx_surface);
check_va_status(status, "vaDestroySurfaceGLX()"); CHECK_VA_STATUS(p, "vaDestroySurfaceGLX()");
p->vaglx_surface = NULL; p->vaglx_surface = NULL;
} }
@ -65,10 +66,11 @@ static int create(struct gl_hwdec *hw)
return -1; return -1;
struct priv *p = talloc_zero(hw, struct priv); struct priv *p = talloc_zero(hw, struct priv);
hw->priv = p; hw->priv = p;
p->log = hw->log;
p->display = vaGetDisplayGLX(hw->mpgl->vo->x11->display); p->display = vaGetDisplayGLX(hw->mpgl->vo->x11->display);
if (!p->display) if (!p->display)
return -1; return -1;
p->ctx = va_initialize(p->display); p->ctx = va_initialize(p->display, p->log);
if (!p->ctx) { if (!p->ctx) {
vaTerminate(p->display); vaTerminate(p->display);
return -1; return -1;
@ -98,7 +100,7 @@ static int reinit(struct gl_hwdec *hw, const struct mp_image_params *params)
status = vaCreateSurfaceGLX(p->display, GL_TEXTURE_2D, status = vaCreateSurfaceGLX(p->display, GL_TEXTURE_2D,
p->gl_texture, &p->vaglx_surface); p->gl_texture, &p->vaglx_surface);
return check_va_status(status, "vaCreateSurfaceGLX()") ? 0 : -1; return CHECK_VA_STATUS(p, "vaCreateSurfaceGLX()") ? 0 : -1;
} }
static int map_image(struct gl_hwdec *hw, struct mp_image *hw_image, static int map_image(struct gl_hwdec *hw, struct mp_image *hw_image,
@ -113,7 +115,7 @@ static int map_image(struct gl_hwdec *hw, struct mp_image *hw_image,
status = vaCopySurfaceGLX(p->display, p->vaglx_surface, status = vaCopySurfaceGLX(p->display, p->vaglx_surface,
va_surface_id_in_mp_image(hw_image), va_surface_id_in_mp_image(hw_image),
va_get_colorspace_flag(hw_image->colorspace)); va_get_colorspace_flag(hw_image->colorspace));
if (!check_va_status(status, "vaCopySurfaceGLX()")) if (!CHECK_VA_STATUS(p, "vaCopySurfaceGLX()"))
return -1; return -1;
out_textures[0] = p->gl_texture; out_textures[0] = p->gl_texture;

View File

@ -134,7 +134,7 @@ static bool alloc_swdec_surfaces(struct priv *p, int w, int h, int imgfmt)
free_video_specific(p); free_video_specific(p);
for (int i = 0; i < MAX_OUTPUT_SURFACES; i++) { for (int i = 0; i < MAX_OUTPUT_SURFACES; i++) {
p->swdec_surfaces[i] = p->swdec_surfaces[i] =
va_surface_pool_get_wrapped(p->pool, p->va_image_formats, imgfmt, w, h); va_surface_pool_get_wrapped(p->pool, imgfmt, w, h);
if (!p->swdec_surfaces[i]) if (!p->swdec_surfaces[i])
return false; return false;
} }
@ -190,8 +190,7 @@ static bool render_to_screen(struct priv *p, struct mp_image *mpi)
// 4:2:0 should work everywhere // 4:2:0 should work everywhere
int fmt = IMGFMT_420P; int fmt = IMGFMT_420P;
p->black_surface = p->black_surface =
va_surface_pool_get_by_imgfmt(p->pool, p->va_image_formats, va_surface_pool_get_by_imgfmt(p->pool, fmt, w, h);
fmt, w, h);
if (p->black_surface) { if (p->black_surface) {
struct mp_image *img = mp_image_alloc(fmt, w, h); struct mp_image *img = mp_image_alloc(fmt, w, h);
mp_image_clear(img, 0, 0, w, h); mp_image_clear(img, 0, 0, w, h);
@ -221,7 +220,7 @@ static bool render_to_screen(struct priv *p, struct mp_image *mpi)
sp->dst_x, sp->dst_y, sp->dst_x, sp->dst_y,
sp->dst_w, sp->dst_h, sp->dst_w, sp->dst_h,
flags); flags);
check_va_status(status, "vaAssociateSubpicture()"); CHECK_VA_STATUS(p, "vaAssociateSubpicture()");
} }
} }
@ -244,7 +243,7 @@ static bool render_to_screen(struct priv *p, struct mp_image *mpi)
p->dst_rect.y1 - p->dst_rect.y0, p->dst_rect.y1 - p->dst_rect.y0,
NULL, 0, NULL, 0,
flags); flags);
check_va_status(status, "vaPutSurface()"); CHECK_VA_STATUS(p, "vaPutSurface()");
for (int n = 0; n < MAX_OSD_PARTS; n++) { for (int n = 0; n < MAX_OSD_PARTS; n++) {
struct vaapi_osd_part *part = &p->osd_parts[n]; struct vaapi_osd_part *part = &p->osd_parts[n];
@ -252,7 +251,7 @@ static bool render_to_screen(struct priv *p, struct mp_image *mpi)
struct vaapi_subpic *sp = &part->subpic; struct vaapi_subpic *sp = &part->subpic;
status = vaDeassociateSubpicture(p->display, sp->id, status = vaDeassociateSubpicture(p->display, sp->id,
&surface, 1); &surface, 1);
check_va_status(status, "vaDeassociateSubpicture()"); CHECK_VA_STATUS(p, "vaDeassociateSubpicture()");
} }
} }
@ -292,8 +291,7 @@ static struct mp_image *get_screenshot(struct priv *p)
va_surface_in_mp_image(p->output_surfaces[p->visible_surface]); va_surface_in_mp_image(p->output_surfaces[p->visible_surface]);
if (!surface) if (!surface)
return NULL; return NULL;
struct mp_image *img = struct mp_image *img = va_surface_download(surface, NULL);
va_surface_download(surface, p->va_image_formats, NULL);
if (!img) if (!img)
return NULL; return NULL;
struct mp_image_params params = p->image_params; struct mp_image_params params = p->image_params;
@ -334,10 +332,10 @@ static int new_subpicture(struct priv *p, int w, int h,
}; };
status = vaCreateImage(p->display, &p->osd_format, w, h, &m.image); status = vaCreateImage(p->display, &p->osd_format, w, h, &m.image);
if (!check_va_status(status, "vaCreateImage()")) if (!CHECK_VA_STATUS(p, "vaCreateImage()"))
goto error; goto error;
status = vaCreateSubpicture(p->display, m.image.image_id, &m.subpic_id); status = vaCreateSubpicture(p->display, m.image.image_id, &m.subpic_id);
if (!check_va_status(status, "vaCreateSubpicture()")) if (!CHECK_VA_STATUS(p, "vaCreateSubpicture()"))
goto error; goto error;
*out = m; *out = m;
@ -377,7 +375,7 @@ static void draw_osd_cb(void *pctx, struct sub_bitmaps *imgs)
struct vaapi_osd_image *img = &part->image; struct vaapi_osd_image *img = &part->image;
struct mp_image vaimg; struct mp_image vaimg;
if (va_image_map(p->display, &img->image, &vaimg) < 0) if (va_image_map(p->mpvaapi, &img->image, &vaimg) < 0)
goto error; goto error;
// Clear borders and regions uncovered by sub-bitmaps // Clear borders and regions uncovered by sub-bitmaps
@ -398,7 +396,7 @@ static void draw_osd_cb(void *pctx, struct sub_bitmaps *imgs)
vaimg.stride[0], sub->stride); vaimg.stride[0], sub->stride);
} }
if (va_image_unmap(p->display, &img->image) < 0) if (va_image_unmap(p->mpvaapi, &img->image) < 0)
goto error; goto error;
part->subpic = (struct vaapi_subpic) { part->subpic = (struct vaapi_subpic) {
@ -496,7 +494,7 @@ static int set_equalizer(struct priv *p, const char *name, int value)
attr->value = ((value + 100) * r) / 200 + attr->min_value; attr->value = ((value + 100) * r) / 200 + attr->min_value;
status = vaSetDisplayAttributes(p->display, attr, 1); status = vaSetDisplayAttributes(p->display, attr, 1);
if (!check_va_status(status, "vaSetDisplayAttributes()")) if (!CHECK_VA_STATUS(p, "vaSetDisplayAttributes()"))
return VO_FALSE; return VO_FALSE;
return VO_TRUE; return VO_TRUE;
} }
@ -585,13 +583,13 @@ static int preinit(struct vo *vo)
if (!p->display) if (!p->display)
return -1; return -1;
p->mpvaapi = va_initialize(p->display); p->mpvaapi = va_initialize(p->display, p->log);
if (!p->mpvaapi) { if (!p->mpvaapi) {
vaTerminate(p->display); vaTerminate(p->display);
return -1; return -1;
} }
p->pool = va_surface_pool_alloc(p->display, VA_RT_FORMAT_YUV420); p->pool = va_surface_pool_alloc(p->mpvaapi, VA_RT_FORMAT_YUV420);
p->va_image_formats = p->mpvaapi->image_formats; p->va_image_formats = p->mpvaapi->image_formats;
int max_subpic_formats = vaMaxNumSubpictureFormats(p->display); int max_subpic_formats = vaMaxNumSubpictureFormats(p->display);
@ -601,7 +599,7 @@ static int preinit(struct vo *vo)
p->va_subpic_formats, p->va_subpic_formats,
p->va_subpic_flags, p->va_subpic_flags,
&p->va_num_subpic_formats); &p->va_num_subpic_formats);
if (!check_va_status(status, "vaQuerySubpictureFormats()")) if (!CHECK_VA_STATUS(p, "vaQuerySubpictureFormats()"))
p->va_num_subpic_formats = 0; p->va_num_subpic_formats = 0;
MP_VERBOSE(vo, "%d subpicture formats available:\n", MP_VERBOSE(vo, "%d subpicture formats available:\n",
p->va_num_subpic_formats); p->va_num_subpic_formats);
@ -634,7 +632,7 @@ static int preinit(struct vo *vo)
if (p->va_display_attrs) { if (p->va_display_attrs) {
status = vaQueryDisplayAttributes(p->display, p->va_display_attrs, status = vaQueryDisplayAttributes(p->display, p->va_display_attrs,
&p->va_num_display_attrs); &p->va_num_display_attrs);
if (!check_va_status(status, "vaQueryDisplayAttributes()")) if (!CHECK_VA_STATUS(p, "vaQueryDisplayAttributes()"))
p->va_num_display_attrs = 0; p->va_num_display_attrs = 0;
} }
return 0; return 0;

View File

@ -24,13 +24,10 @@
#include "img_format.h" #include "img_format.h"
#include "mp_image_pool.h" #include "mp_image_pool.h"
#define VA_VERBOSE(...) mp_msg(MSGT_VO, MSGL_V, "[vaapi] " __VA_ARGS__) bool check_va_status(struct mp_log *log, VAStatus status, const char *msg)
#define VA_ERROR(...) mp_msg(MSGT_VO, MSGL_ERR, "[vaapi] " __VA_ARGS__)
bool check_va_status(VAStatus status, const char *msg)
{ {
if (status != VA_STATUS_SUCCESS) { if (status != VA_STATUS_SUCCESS) {
mp_msg(MSGT_VO, MSGL_ERR, "[vaapi] %s: %s\n", msg, vaErrorStr(status)); mp_err(log, "%s: %s\n", msg, vaErrorStr(status));
return false; return false;
} }
return true; return true;
@ -96,30 +93,32 @@ static void va_get_formats(struct mp_vaapi_ctx *ctx)
int num = vaMaxNumImageFormats(ctx->display); int num = vaMaxNumImageFormats(ctx->display);
VAImageFormat entries[num]; VAImageFormat entries[num];
VAStatus status = vaQueryImageFormats(ctx->display, entries, &num); VAStatus status = vaQueryImageFormats(ctx->display, entries, &num);
if (!check_va_status(status, "vaQueryImageFormats()")) if (!CHECK_VA_STATUS(ctx, "vaQueryImageFormats()"))
return; return;
struct va_image_formats *formats = talloc_ptrtype(ctx, formats); struct va_image_formats *formats = talloc_ptrtype(ctx, formats);
formats->entries = talloc_array(formats, VAImageFormat, num); formats->entries = talloc_array(formats, VAImageFormat, num);
formats->num = num; formats->num = num;
VA_VERBOSE("%d image formats available:\n", num); MP_VERBOSE(ctx, "%d image formats available:\n", num);
for (int i = 0; i < num; i++) { for (int i = 0; i < num; i++) {
formats->entries[i] = entries[i]; formats->entries[i] = entries[i];
VA_VERBOSE(" %s\n", VA_STR_FOURCC(entries[i].fourcc)); MP_VERBOSE(ctx, " %s\n", VA_STR_FOURCC(entries[i].fourcc));
} }
ctx->image_formats = formats; ctx->image_formats = formats;
} }
struct mp_vaapi_ctx *va_initialize(VADisplay *display) struct mp_vaapi_ctx *va_initialize(VADisplay *display, struct mp_log *plog)
{ {
struct mp_log *log = mp_log_new(NULL, plog, "/vaapi");
int major_version, minor_version; int major_version, minor_version;
int status = vaInitialize(display, &major_version, &minor_version); int status = vaInitialize(display, &major_version, &minor_version);
if (!check_va_status(status, "vaInitialize()")) if (!check_va_status(log, status, "vaInitialize()"))
return NULL; goto error;
VA_VERBOSE("VA API version %d.%d\n", major_version, minor_version); mp_verbose(log, "VA API version %d.%d\n", major_version, minor_version);
struct mp_vaapi_ctx *res = talloc_ptrtype(NULL, res); struct mp_vaapi_ctx *res = talloc_ptrtype(NULL, res);
*res = (struct mp_vaapi_ctx) { *res = (struct mp_vaapi_ctx) {
.log = talloc_steal(res, log),
.display = display, .display = display,
}; };
@ -129,8 +128,9 @@ struct mp_vaapi_ctx *va_initialize(VADisplay *display)
return res; return res;
error: error:
if (res->display) if (res && res->display)
vaTerminate(res->display); vaTerminate(res->display);
talloc_free(log);
talloc_free(res); talloc_free(res);
return NULL; return NULL;
} }
@ -161,6 +161,8 @@ VAImageFormat *va_image_format_from_imgfmt(const struct va_image_formats *format
static void va_surface_destroy(struct va_surface *surface); static void va_surface_destroy(struct va_surface *surface);
struct va_surface_pool { struct va_surface_pool {
struct mp_log *log;
struct mp_vaapi_ctx *ctx;
VADisplay display; VADisplay display;
int rt_format; int rt_format;
int num_surfaces, lru_counter; int num_surfaces, lru_counter;
@ -168,6 +170,7 @@ struct va_surface_pool {
}; };
typedef struct va_surface_priv { typedef struct va_surface_priv {
struct mp_vaapi_ctx *ctx;
VADisplay display; VADisplay display;
VAImage image; // used for software decoding case VAImage image; // used for software decoding case
bool is_derived; // is image derived by vaDeriveImage()? bool is_derived; // is image derived by vaDeriveImage()?
@ -176,11 +179,13 @@ typedef struct va_surface_priv {
int order; // for LRU allocation int order; // for LRU allocation
} va_surface_priv_t; } va_surface_priv_t;
struct va_surface_pool *va_surface_pool_alloc(VADisplay display, int rt_format) struct va_surface_pool * va_surface_pool_alloc(struct mp_vaapi_ctx *ctx, int rt_format)
{ {
struct va_surface_pool *pool = talloc_ptrtype(NULL, pool); struct va_surface_pool *pool = talloc_ptrtype(NULL, pool);
*pool = (struct va_surface_pool) { *pool = (struct va_surface_pool) {
.display = display, .ctx = ctx,
.log = ctx->log,
.display = ctx->display,
.rt_format = rt_format .rt_format = rt_format
}; };
return pool; return pool;
@ -252,7 +257,7 @@ static struct va_surface *va_surface_alloc(struct va_surface_pool *pool,
VASurfaceID id = VA_INVALID_ID; VASurfaceID id = VA_INVALID_ID;
VAStatus status; VAStatus status;
status = vaCreateSurfaces(pool->display, w, h, pool->rt_format, 1, &id); status = vaCreateSurfaces(pool->display, w, h, pool->rt_format, 1, &id);
if (!check_va_status(status, "vaCreateSurfaces()")) if (!CHECK_VA_STATUS(pool, "vaCreateSurfaces()"))
return NULL; return NULL;
struct va_surface *surface = talloc_ptrtype(NULL, surface); struct va_surface *surface = talloc_ptrtype(NULL, surface);
@ -265,17 +270,16 @@ static struct va_surface *va_surface_alloc(struct va_surface_pool *pool,
surface->h = h; surface->h = h;
surface->rt_format = pool->rt_format; surface->rt_format = pool->rt_format;
surface->p = talloc_zero(surface, va_surface_priv_t); surface->p = talloc_zero(surface, va_surface_priv_t);
surface->p->ctx = pool->ctx;
surface->p->display = pool->display; surface->p->display = pool->display;
surface->p->image.image_id = surface->p->image.buf = VA_INVALID_ID; surface->p->image.image_id = surface->p->image.buf = VA_INVALID_ID;
return surface; return surface;
} }
struct mp_image *va_surface_pool_get_wrapped(struct va_surface_pool *pool, struct mp_image *va_surface_pool_get_wrapped(struct va_surface_pool *pool,
const struct va_image_formats *formats,
int imgfmt, int w, int h) int imgfmt, int w, int h)
{ {
return va_surface_wrap(va_surface_pool_get_by_imgfmt(pool, formats, imgfmt, return va_surface_wrap(va_surface_pool_get_by_imgfmt(pool, imgfmt, w, h));
w, h));
} }
int va_surface_pool_rt_format(const struct va_surface_pool *pool) int va_surface_pool_rt_format(const struct va_surface_pool *pool)
@ -346,7 +350,7 @@ static VAImage *va_surface_image_alloc(struct va_surface *surface,
if (p->image.format.fourcc == format->fourcc && if (p->image.format.fourcc == format->fourcc &&
p->image.width == surface->w && p->image.height == surface->h) { p->image.width == surface->w && p->image.height == surface->h) {
p->is_derived = true; p->is_derived = true;
VA_VERBOSE("Using vaDeriveImage()\n"); MP_VERBOSE(p->ctx, "Using vaDeriveImage()\n");
} else { } else {
vaDestroyImage(p->display, p->image.image_id); vaDestroyImage(p->display, p->image.image_id);
status = VA_STATUS_ERROR_OPERATION_FAILED; status = VA_STATUS_ERROR_OPERATION_FAILED;
@ -356,7 +360,7 @@ static VAImage *va_surface_image_alloc(struct va_surface *surface,
p->image.image_id = VA_INVALID_ID; p->image.image_id = VA_INVALID_ID;
status = vaCreateImage(p->display, format, surface->w, surface->h, status = vaCreateImage(p->display, format, surface->w, surface->h,
&p->image); &p->image);
if (!check_va_status(status, "vaCreateImage()")) { if (!CHECK_VA_STATUS(p->ctx, "vaCreateImage()")) {
p->image.image_id = VA_INVALID_ID; p->image.image_id = VA_INVALID_ID;
return NULL; return NULL;
} }
@ -367,12 +371,12 @@ static VAImage *va_surface_image_alloc(struct va_surface *surface,
struct va_surface *va_surface_pool_get_by_imgfmt(struct va_surface_pool *pool, struct va_surface *va_surface_pool_get_by_imgfmt(struct va_surface_pool *pool,
const struct va_image_formats *formats,
int imgfmt, int w, int h) int imgfmt, int w, int h)
{ {
if (imgfmt == IMGFMT_VAAPI) if (imgfmt == IMGFMT_VAAPI)
return va_surface_pool_get(pool, w, h); return va_surface_pool_get(pool, w, h);
VAImageFormat *format = va_image_format_from_imgfmt(formats, imgfmt); VAImageFormat *format =
va_image_format_from_imgfmt(pool->ctx->image_formats, imgfmt);
if (!format) if (!format)
return NULL; return NULL;
// WTF: no mapping from VAImageFormat -> VA_RT_FORMAT_ // WTF: no mapping from VAImageFormat -> VA_RT_FORMAT_
@ -420,14 +424,14 @@ VASurfaceID va_surface_id(const struct va_surface *surface)
return surface ? surface->id : VA_INVALID_ID; return surface ? surface->id : VA_INVALID_ID;
} }
bool va_image_map(VADisplay display, VAImage *image, struct mp_image *mpi) bool va_image_map(struct mp_vaapi_ctx *ctx, VAImage *image, struct mp_image *mpi)
{ {
int imgfmt = va_fourcc_to_imgfmt(image->format.fourcc); int imgfmt = va_fourcc_to_imgfmt(image->format.fourcc);
if (imgfmt == IMGFMT_NONE) if (imgfmt == IMGFMT_NONE)
return false; return false;
void *data = NULL; void *data = NULL;
const VAStatus status = vaMapBuffer(display, image->buf, &data); const VAStatus status = vaMapBuffer(ctx->display, image->buf, &data);
if (!check_va_status(status, "vaMapBuffer()")) if (!CHECK_VA_STATUS(ctx, "vaMapBuffer()"))
return false; return false;
*mpi = (struct mp_image) {0}; *mpi = (struct mp_image) {0};
@ -447,10 +451,10 @@ bool va_image_map(VADisplay display, VAImage *image, struct mp_image *mpi)
return true; return true;
} }
bool va_image_unmap(VADisplay display, VAImage *image) bool va_image_unmap(struct mp_vaapi_ctx *ctx, VAImage *image)
{ {
const VAStatus status = vaUnmapBuffer(display, image->buf); const VAStatus status = vaUnmapBuffer(ctx->display, image->buf);
return check_va_status(status, "vaUnmapBuffer()"); return CHECK_VA_STATUS(ctx, "vaUnmapBuffer()");
} }
bool va_surface_upload(struct va_surface *surface, struct mp_image *mpi) bool va_surface_upload(struct va_surface *surface, struct mp_image *mpi)
@ -463,17 +467,17 @@ bool va_surface_upload(struct va_surface *surface, struct mp_image *mpi)
return false; return false;
struct mp_image img; struct mp_image img;
if (!va_image_map(p->display, &p->image, &img)) if (!va_image_map(p->ctx, &p->image, &img))
return false; return false;
mp_image_copy(&img, mpi); mp_image_copy(&img, mpi);
va_image_unmap(p->display, &p->image); va_image_unmap(p->ctx, &p->image);
if (!p->is_derived) { if (!p->is_derived) {
VAStatus status = vaPutImage2(p->display, surface->id, VAStatus status = vaPutImage2(p->display, surface->id,
p->image.image_id, p->image.image_id,
0, 0, mpi->w, mpi->h, 0, 0, mpi->w, mpi->h,
0, 0, mpi->w, mpi->h); 0, 0, mpi->w, mpi->h);
if (!check_va_status(status, "vaPutImage()")) if (!CHECK_VA_STATUS(p->ctx, "vaPutImage()"))
return false; return false;
} }
@ -504,12 +508,12 @@ static struct mp_image *try_download(struct va_surface *surface,
struct mp_image *dst = NULL; struct mp_image *dst = NULL;
struct mp_image tmp; struct mp_image tmp;
if (va_image_map(surface->p->display, image, &tmp)) { if (va_image_map(surface->p->ctx, image, &tmp)) {
assert(tmp.imgfmt == imgfmt); assert(tmp.imgfmt == imgfmt);
dst = pool ? mp_image_pool_get(pool, imgfmt, tmp.w, tmp.h) dst = pool ? mp_image_pool_get(pool, imgfmt, tmp.w, tmp.h)
: mp_image_alloc(imgfmt, tmp.w, tmp.h); : mp_image_alloc(imgfmt, tmp.w, tmp.h);
mp_image_copy(dst, &tmp); mp_image_copy(dst, &tmp);
va_image_unmap(surface->p->display, image); va_image_unmap(surface->p->ctx, image);
} }
return dst; return dst;
} }
@ -518,11 +522,11 @@ static struct mp_image *try_download(struct va_surface *surface,
// Note: unlike va_surface_upload(), this will attempt to (re)create the // Note: unlike va_surface_upload(), this will attempt to (re)create the
// VAImage stored with the va_surface. // VAImage stored with the va_surface.
struct mp_image *va_surface_download(struct va_surface *surface, struct mp_image *va_surface_download(struct va_surface *surface,
const struct va_image_formats *formats,
struct mp_image_pool *pool) struct mp_image_pool *pool)
{ {
struct mp_vaapi_ctx *ctx = surface->p->ctx;
VAStatus status = vaSyncSurface(surface->p->display, surface->id); VAStatus status = vaSyncSurface(surface->p->display, surface->id);
if (!check_va_status(status, "vaSyncSurface()")) if (!CHECK_VA_STATUS(ctx, "vaSyncSurface()"))
return NULL; return NULL;
VAImage *image = &surface->p->image; VAImage *image = &surface->p->image;
@ -533,14 +537,14 @@ struct mp_image *va_surface_download(struct va_surface *surface,
} }
// We have no clue which format will work, so try them all. // We have no clue which format will work, so try them all.
for (int i = 0; i < formats->num; i++) { for (int i = 0; i < ctx->image_formats->num; i++) {
VAImageFormat *format = &formats->entries[i]; VAImageFormat *format = &ctx->image_formats->entries[i];
struct mp_image *mpi = try_download(surface, format, pool); struct mp_image *mpi = try_download(surface, format, pool);
if (mpi) if (mpi)
return mpi; return mpi;
} }
VA_ERROR("failed to get surface data.\n"); MP_ERR(ctx, "failed to get surface data.\n");
return NULL; return NULL;
} }

View File

@ -73,8 +73,10 @@
#include "mp_image.h" #include "mp_image.h"
struct mp_image_pool; struct mp_image_pool;
struct mp_log;
struct mp_vaapi_ctx { struct mp_vaapi_ctx {
struct mp_log *log;
VADisplay display; VADisplay display;
struct va_image_formats *image_formats; struct va_image_formats *image_formats;
}; };
@ -89,28 +91,30 @@ struct va_surface {
struct va_surface_priv *p; struct va_surface_priv *p;
}; };
bool check_va_status(VAStatus status, const char *msg); bool check_va_status(struct mp_log *log, VAStatus status, const char *msg);
#define CHECK_VA_STATUS(ctx, msg) check_va_status((ctx)->log, status, msg)
int va_get_colorspace_flag(enum mp_csp csp); int va_get_colorspace_flag(enum mp_csp csp);
struct mp_vaapi_ctx *va_initialize(VADisplay *display); struct mp_vaapi_ctx *va_initialize(VADisplay *display, struct mp_log *log);
void va_destroy(struct mp_vaapi_ctx *ctx); void va_destroy(struct mp_vaapi_ctx *ctx);
enum mp_imgfmt va_fourcc_to_imgfmt(uint32_t fourcc); enum mp_imgfmt va_fourcc_to_imgfmt(uint32_t fourcc);
uint32_t va_fourcc_from_imgfmt(int imgfmt); uint32_t va_fourcc_from_imgfmt(int imgfmt);
VAImageFormat * va_image_format_from_imgfmt(const struct va_image_formats *formats, int imgfmt); VAImageFormat * va_image_format_from_imgfmt(const struct va_image_formats *formats, int imgfmt);
bool va_image_map(VADisplay display, VAImage *image, struct mp_image *mpi); bool va_image_map(struct mp_vaapi_ctx *ctx, VAImage *image, struct mp_image *mpi);
bool va_image_unmap(VADisplay display, VAImage *image); bool va_image_unmap(struct mp_vaapi_ctx *ctx, VAImage *image);
struct va_surface_pool * va_surface_pool_alloc(VADisplay display, int rt_format); struct va_surface_pool * va_surface_pool_alloc(struct mp_vaapi_ctx *ctx, int rt_format);
void va_surface_pool_release(struct va_surface_pool *pool); void va_surface_pool_release(struct va_surface_pool *pool);
void va_surface_pool_releasep(struct va_surface_pool **pool); void va_surface_pool_releasep(struct va_surface_pool **pool);
void va_surface_pool_clear(struct va_surface_pool *pool); void va_surface_pool_clear(struct va_surface_pool *pool);
bool va_surface_pool_reserve(struct va_surface_pool *pool, int count, int w, int h); bool va_surface_pool_reserve(struct va_surface_pool *pool, int count, int w, int h);
int va_surface_pool_rt_format(const struct va_surface_pool *pool); int va_surface_pool_rt_format(const struct va_surface_pool *pool);
struct va_surface * va_surface_pool_get(struct va_surface_pool *pool, int w, int h); struct va_surface * va_surface_pool_get(struct va_surface_pool *pool, int w, int h);
struct va_surface * va_surface_pool_get_by_imgfmt(struct va_surface_pool *pool, const struct va_image_formats *formats, int imgfmt, int w, int h); struct va_surface * va_surface_pool_get_by_imgfmt(struct va_surface_pool *pool, int imgfmt, int w, int h);
struct mp_image * va_surface_pool_get_wrapped(struct va_surface_pool *pool, const struct va_image_formats *formats, int imgfmt, int w, int h); struct mp_image * va_surface_pool_get_wrapped(struct va_surface_pool *pool, int imgfmt, int w, int h);
void va_surface_release(struct va_surface *surface); void va_surface_release(struct va_surface *surface);
void va_surface_releasep(struct va_surface **surface); void va_surface_releasep(struct va_surface **surface);
@ -120,7 +124,6 @@ VASurfaceID va_surface_id(const struct va_surface *surface);
VASurfaceID va_surface_id_in_mp_image(const struct mp_image *mpi); VASurfaceID va_surface_id_in_mp_image(const struct mp_image *mpi);
bool va_surface_upload(struct va_surface *surface, struct mp_image *mpi); bool va_surface_upload(struct va_surface *surface, struct mp_image *mpi);
struct mp_image * va_surface_download(struct va_surface *surface, struct mp_image * va_surface_download(struct va_surface *surface,
const struct va_image_formats *formats,
struct mp_image_pool *pool); struct mp_image_pool *pool);
#endif #endif