mirror of https://github.com/mpv-player/mpv
vdpau: move RGB surface management out of the VO
Integrate it with the existing surface allocator in vdpau.c. The changes are a bit violent, because the vdpau API is so non-orthogonal: compared to video surfaces, output surfaces use a different ID type, different format types, and different API functions. Also, introduce IMGFMT_VDPAU_OUTPUT for VdpOutputSurfaces wrapped in mp_image, rather than hacking it. This is a bit cleaner.
This commit is contained in:
parent
dbed21cde4
commit
7b7e15a460
|
@ -42,6 +42,8 @@ struct mp_imgfmt_entry {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct mp_imgfmt_entry mp_imgfmt_list[] = {
|
static const struct mp_imgfmt_entry mp_imgfmt_list[] = {
|
||||||
|
// not in ffmpeg
|
||||||
|
FMT("vdpau_output", IMGFMT_VDPAU_OUTPUT)
|
||||||
// these formats are pretty common, and the "le"/"be" suffixes enforced
|
// these formats are pretty common, and the "le"/"be" suffixes enforced
|
||||||
// by FFmpeg are annoying
|
// by FFmpeg are annoying
|
||||||
FMT("yuv420p10", IMGFMT_420P10)
|
FMT("yuv420p10", IMGFMT_420P10)
|
||||||
|
@ -128,12 +130,26 @@ const char *mp_imgfmt_to_name(int fmt)
|
||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct mp_imgfmt_desc mp_only_imgfmt_desc(int mpfmt)
|
||||||
|
{
|
||||||
|
switch (mpfmt) {
|
||||||
|
case IMGFMT_VDPAU_OUTPUT:
|
||||||
|
return (struct mp_imgfmt_desc) {
|
||||||
|
.id = mpfmt,
|
||||||
|
.avformat = AV_PIX_FMT_NONE,
|
||||||
|
.name = mp_imgfmt_to_name(mpfmt),
|
||||||
|
.flags = MP_IMGFLAG_BE | MP_IMGFLAG_LE | MP_IMGFLAG_RGB,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return (struct mp_imgfmt_desc) {0};
|
||||||
|
}
|
||||||
|
|
||||||
struct mp_imgfmt_desc mp_imgfmt_get_desc(int mpfmt)
|
struct mp_imgfmt_desc mp_imgfmt_get_desc(int mpfmt)
|
||||||
{
|
{
|
||||||
enum AVPixelFormat fmt = imgfmt2pixfmt(mpfmt);
|
enum AVPixelFormat fmt = imgfmt2pixfmt(mpfmt);
|
||||||
const AVPixFmtDescriptor *pd = av_pix_fmt_desc_get(fmt);
|
const AVPixFmtDescriptor *pd = av_pix_fmt_desc_get(fmt);
|
||||||
if (!pd || fmt == AV_PIX_FMT_NONE)
|
if (!pd || fmt == AV_PIX_FMT_NONE)
|
||||||
return (struct mp_imgfmt_desc) {0};
|
return mp_only_imgfmt_desc(mpfmt);
|
||||||
|
|
||||||
struct mp_imgfmt_desc desc = {
|
struct mp_imgfmt_desc desc = {
|
||||||
.id = mpfmt,
|
.id = mpfmt,
|
||||||
|
|
|
@ -252,7 +252,8 @@ enum mp_imgfmt {
|
||||||
|
|
||||||
// Hardware accelerated formats. Plane data points to special data
|
// Hardware accelerated formats. Plane data points to special data
|
||||||
// structures, instead of pixel data.
|
// structures, instead of pixel data.
|
||||||
IMGFMT_VDPAU,
|
IMGFMT_VDPAU, // VdpVideoSurface
|
||||||
|
IMGFMT_VDPAU_OUTPUT, // VdpOutputSurface
|
||||||
IMGFMT_VDA,
|
IMGFMT_VDA,
|
||||||
IMGFMT_VAAPI,
|
IMGFMT_VAAPI,
|
||||||
|
|
||||||
|
@ -330,7 +331,8 @@ static inline bool IMGFMT_IS_RGB(int fmt)
|
||||||
#define IMGFMT_RGB_DEPTH(fmt) (mp_imgfmt_get_desc(fmt).plane_bits)
|
#define IMGFMT_RGB_DEPTH(fmt) (mp_imgfmt_get_desc(fmt).plane_bits)
|
||||||
|
|
||||||
#define IMGFMT_IS_HWACCEL(fmt) \
|
#define IMGFMT_IS_HWACCEL(fmt) \
|
||||||
((fmt) == IMGFMT_VDPAU || (fmt) == IMGFMT_VAAPI || (fmt) == IMGFMT_VDA)
|
((fmt) == IMGFMT_VDPAU || (fmt) == IMGFMT_VDPAU_OUTPUT || \
|
||||||
|
(fmt) == IMGFMT_VAAPI || (fmt) == IMGFMT_VDA)
|
||||||
|
|
||||||
int mp_imgfmt_from_name(bstr name, bool allow_hwaccel);
|
int mp_imgfmt_from_name(bstr name, bool allow_hwaccel);
|
||||||
const char *mp_imgfmt_to_name(int fmt);
|
const char *mp_imgfmt_to_name(int fmt);
|
||||||
|
|
|
@ -60,7 +60,6 @@
|
||||||
|
|
||||||
/* number of video and output surfaces */
|
/* number of video and output surfaces */
|
||||||
#define MAX_OUTPUT_SURFACES 15
|
#define MAX_OUTPUT_SURFACES 15
|
||||||
#define NUM_BUFFERED_VIDEO 5
|
|
||||||
|
|
||||||
/* Pixelformat used for output surfaces */
|
/* Pixelformat used for output surfaces */
|
||||||
#define OUTPUT_RGBA_FORMAT VDP_RGBA_FORMAT_B8G8R8A8
|
#define OUTPUT_RGBA_FORMAT VDP_RGBA_FORMAT_B8G8R8A8
|
||||||
|
@ -83,8 +82,6 @@ struct vdpctx {
|
||||||
VdpOutputSurface output_surfaces[MAX_OUTPUT_SURFACES];
|
VdpOutputSurface output_surfaces[MAX_OUTPUT_SURFACES];
|
||||||
VdpOutputSurface screenshot_surface;
|
VdpOutputSurface screenshot_surface;
|
||||||
int num_output_surfaces;
|
int num_output_surfaces;
|
||||||
VdpOutputSurface rgb_surfaces[NUM_BUFFERED_VIDEO];
|
|
||||||
bool rgb_surfaces_used[NUM_BUFFERED_VIDEO];
|
|
||||||
VdpOutputSurface black_pixel;
|
VdpOutputSurface black_pixel;
|
||||||
|
|
||||||
struct mp_image *current_image;
|
struct mp_image *current_image;
|
||||||
|
@ -177,7 +174,7 @@ static int render_video_to_output_surface(struct vo *vo,
|
||||||
"vdp_presentation_queue_block_until_surface_idle");
|
"vdp_presentation_queue_block_until_surface_idle");
|
||||||
|
|
||||||
if (vc->rgb_mode) {
|
if (vc->rgb_mode) {
|
||||||
VdpOutputSurface surface = (uintptr_t)mpi->planes[0];
|
VdpOutputSurface surface = (uintptr_t)mpi->planes[3];
|
||||||
int flags = VDP_OUTPUT_SURFACE_RENDER_ROTATE_0;
|
int flags = VDP_OUTPUT_SURFACE_RENDER_ROTATE_0;
|
||||||
vdp_st = vdp->output_surface_render_output_surface(output_surface,
|
vdp_st = vdp->output_surface_render_output_surface(output_surface,
|
||||||
NULL, vc->black_pixel,
|
NULL, vc->black_pixel,
|
||||||
|
@ -373,15 +370,6 @@ static void free_video_specific(struct vo *vo)
|
||||||
}
|
}
|
||||||
vc->screenshot_surface = VDP_INVALID_HANDLE;
|
vc->screenshot_surface = VDP_INVALID_HANDLE;
|
||||||
|
|
||||||
for (int n = 0; n < NUM_BUFFERED_VIDEO; n++) {
|
|
||||||
assert(!vc->rgb_surfaces_used[n]);
|
|
||||||
if (vc->rgb_surfaces[n] != VDP_INVALID_HANDLE) {
|
|
||||||
vdp_st = vdp->output_surface_destroy(vc->rgb_surfaces[n]);
|
|
||||||
CHECK_VDP_WARNING(vo, "Error when calling vdp_output_surface_destroy");
|
|
||||||
}
|
|
||||||
vc->rgb_surfaces[n] = VDP_INVALID_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vc->black_pixel != VDP_INVALID_HANDLE) {
|
if (vc->black_pixel != VDP_INVALID_HANDLE) {
|
||||||
vdp_st = vdp->output_surface_destroy(vc->black_pixel);
|
vdp_st = vdp->output_surface_destroy(vc->black_pixel);
|
||||||
CHECK_VDP_WARNING(vo, "Error when calling vdp_output_surface_destroy");
|
CHECK_VDP_WARNING(vo, "Error when calling vdp_output_surface_destroy");
|
||||||
|
@ -389,14 +377,6 @@ static void free_video_specific(struct vo *vo)
|
||||||
vc->black_pixel = VDP_INVALID_HANDLE;
|
vc->black_pixel = VDP_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_rgb_format(int imgfmt)
|
|
||||||
{
|
|
||||||
switch (imgfmt) {
|
|
||||||
case IMGFMT_BGR32: return VDP_RGBA_FORMAT_B8G8R8A8;
|
|
||||||
default: return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int initialize_vdpau_objects(struct vo *vo)
|
static int initialize_vdpau_objects(struct vo *vo)
|
||||||
{
|
{
|
||||||
struct vdpctx *vc = vo->priv;
|
struct vdpctx *vc = vo->priv;
|
||||||
|
@ -412,17 +392,6 @@ static int initialize_vdpau_objects(struct vo *vo)
|
||||||
if (win_x11_init_vdpau_flip_queue(vo) < 0)
|
if (win_x11_init_vdpau_flip_queue(vo) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (vc->rgb_mode) {
|
|
||||||
int format = get_rgb_format(vc->image_format);
|
|
||||||
for (int n = 0; n < NUM_BUFFERED_VIDEO; n++) {
|
|
||||||
vdp_st = vdp->output_surface_create(vc->vdp_device,
|
|
||||||
format,
|
|
||||||
vc->vid_width, vc->vid_height,
|
|
||||||
&vc->rgb_surfaces[n]);
|
|
||||||
CHECK_VDP_ERROR(vo, "Allocating RGB surface");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vc->black_pixel == VDP_INVALID_HANDLE) {
|
if (vc->black_pixel == VDP_INVALID_HANDLE) {
|
||||||
vdp_st = vdp->output_surface_create(vc->vdp_device, OUTPUT_RGBA_FORMAT,
|
vdp_st = vdp->output_surface_create(vc->vdp_device, OUTPUT_RGBA_FORMAT,
|
||||||
1, 1, &vc->black_pixel);
|
1, 1, &vc->black_pixel);
|
||||||
|
@ -443,8 +412,6 @@ static void mark_vdpau_objects_uninitialized(struct vo *vo)
|
||||||
{
|
{
|
||||||
struct vdpctx *vc = vo->priv;
|
struct vdpctx *vc = vo->priv;
|
||||||
|
|
||||||
for (int i = 0; i < NUM_BUFFERED_VIDEO; i++)
|
|
||||||
vc->rgb_surfaces[i] = VDP_INVALID_HANDLE;
|
|
||||||
forget_frames(vo, false);
|
forget_frames(vo, false);
|
||||||
vc->black_pixel = VDP_INVALID_HANDLE;
|
vc->black_pixel = VDP_INVALID_HANDLE;
|
||||||
vc->video_mixer->video_mixer = VDP_INVALID_HANDLE;
|
vc->video_mixer->video_mixer = VDP_INVALID_HANDLE;
|
||||||
|
@ -502,7 +469,7 @@ static int reconfig(struct vo *vo, struct mp_image_params *params, int flags)
|
||||||
vc->vid_width = params->w;
|
vc->vid_width = params->w;
|
||||||
vc->vid_height = params->h;
|
vc->vid_height = params->h;
|
||||||
|
|
||||||
vc->rgb_mode = get_rgb_format(params->imgfmt) >= 0;
|
vc->rgb_mode = mp_vdpau_get_rgb_format(params->imgfmt, NULL);
|
||||||
|
|
||||||
free_video_specific(vo);
|
free_video_specific(vo);
|
||||||
|
|
||||||
|
@ -872,33 +839,6 @@ static void flip_page_timed(struct vo *vo, int64_t pts_us, int duration)
|
||||||
vc->surface_num = WRAP_ADD(vc->surface_num, 1, vc->num_output_surfaces);
|
vc->surface_num = WRAP_ADD(vc->surface_num, 1, vc->num_output_surfaces);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_rgb_surface(void *ptr)
|
|
||||||
{
|
|
||||||
bool *entry = ptr;
|
|
||||||
*entry = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct mp_image *get_rgb_surface(struct vo *vo)
|
|
||||||
{
|
|
||||||
struct vdpctx *vc = vo->priv;
|
|
||||||
|
|
||||||
assert(vc->rgb_mode);
|
|
||||||
|
|
||||||
for (int n = 0; n < NUM_BUFFERED_VIDEO; n++) {
|
|
||||||
bool *used = &vc->rgb_surfaces_used[n];
|
|
||||||
if (!*used) {
|
|
||||||
*used = true;
|
|
||||||
struct mp_image mpi = {0};
|
|
||||||
mp_image_setfmt(&mpi, IMGFMT_VDPAU); // not really, but keep csp flags
|
|
||||||
mpi.planes[0] = (void *)(uintptr_t)vc->rgb_surfaces[n];
|
|
||||||
return mp_image_new_custom_ref(&mpi, used, free_rgb_surface);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MP_ERR(vo, "no surfaces available in get_rgb_surface\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void draw_image(struct vo *vo, struct mp_image *mpi)
|
static void draw_image(struct vo *vo, struct mp_image *mpi)
|
||||||
{
|
{
|
||||||
struct vdpctx *vc = vo->priv;
|
struct vdpctx *vc = vo->priv;
|
||||||
|
@ -912,29 +852,10 @@ static void draw_image(struct vo *vo, struct mp_image *mpi)
|
||||||
static struct mp_image *filter_image(struct vo *vo, struct mp_image *mpi)
|
static struct mp_image *filter_image(struct vo *vo, struct mp_image *mpi)
|
||||||
{
|
{
|
||||||
struct vdpctx *vc = vo->priv;
|
struct vdpctx *vc = vo->priv;
|
||||||
struct vdp_functions *vdp = vc->vdp;
|
|
||||||
struct mp_image *reserved_mpi = NULL;
|
|
||||||
VdpStatus vdp_st;
|
|
||||||
|
|
||||||
check_preemption(vo);
|
check_preemption(vo);
|
||||||
|
|
||||||
if (vc->rgb_mode) {
|
struct mp_image *reserved_mpi = mp_vdpau_upload_video_surface(vc->mpvdp, mpi);
|
||||||
reserved_mpi = get_rgb_surface(vo);
|
|
||||||
if (!reserved_mpi)
|
|
||||||
goto end;
|
|
||||||
VdpOutputSurface rgb_surface = (uintptr_t)reserved_mpi->planes[0];
|
|
||||||
if (rgb_surface != VDP_INVALID_HANDLE) {
|
|
||||||
vdp_st = vdp->output_surface_put_bits_native(rgb_surface,
|
|
||||||
&(const void *){mpi->planes[0]},
|
|
||||||
&(uint32_t){mpi->stride[0]},
|
|
||||||
NULL);
|
|
||||||
CHECK_VDP_WARNING(vo, "Error when calling "
|
|
||||||
"output_surface_put_bits_native");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reserved_mpi = mp_vdpau_upload_video_surface(vc->mpvdp, mpi);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!reserved_mpi)
|
if (!reserved_mpi)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
|
@ -1014,8 +935,7 @@ static int query_format(struct vo *vo, uint32_t format)
|
||||||
int flags = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW;
|
int flags = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW;
|
||||||
if (mp_vdpau_get_format(format, NULL, NULL))
|
if (mp_vdpau_get_format(format, NULL, NULL))
|
||||||
return flags;
|
return flags;
|
||||||
int rgb_format = get_rgb_format(format);
|
if (!vc->force_yuv && mp_vdpau_get_rgb_format(format, NULL))
|
||||||
if (!vc->force_yuv && rgb_format >= 0)
|
|
||||||
return flags;
|
return flags;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
119
video/vdpau.c
119
video/vdpau.c
|
@ -28,8 +28,11 @@
|
||||||
|
|
||||||
static void mark_vdpau_objects_uninitialized(struct mp_vdpau_ctx *ctx)
|
static void mark_vdpau_objects_uninitialized(struct mp_vdpau_ctx *ctx)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAX_VIDEO_SURFACES; i++)
|
for (int i = 0; i < MAX_VIDEO_SURFACES; i++) {
|
||||||
ctx->video_surfaces[i].surface = VDP_INVALID_HANDLE;
|
ctx->video_surfaces[i].surface = VDP_INVALID_HANDLE;
|
||||||
|
ctx->video_surfaces[i].osurface = VDP_INVALID_HANDLE;
|
||||||
|
ctx->video_surfaces[i].allocated = false;
|
||||||
|
}
|
||||||
ctx->vdp_device = VDP_INVALID_HANDLE;
|
ctx->vdp_device = VDP_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,30 +184,45 @@ static struct mp_image *create_ref(struct mp_vdpau_ctx *ctx, int index)
|
||||||
struct mp_image *res =
|
struct mp_image *res =
|
||||||
mp_image_new_custom_ref(&(struct mp_image){0}, ref,
|
mp_image_new_custom_ref(&(struct mp_image){0}, ref,
|
||||||
release_decoder_surface);
|
release_decoder_surface);
|
||||||
mp_image_setfmt(res, IMGFMT_VDPAU);
|
mp_image_setfmt(res, e->rgb ? IMGFMT_VDPAU_OUTPUT : IMGFMT_VDPAU);
|
||||||
mp_image_set_size(res, e->w, e->h);
|
mp_image_set_size(res, e->w, e->h);
|
||||||
res->planes[0] = (void *)"dummy"; // must be non-NULL, otherwise arbitrary
|
res->planes[0] = (void *)"dummy"; // must be non-NULL, otherwise arbitrary
|
||||||
res->planes[3] = (void *)(intptr_t)e->surface;
|
res->planes[3] = (void *)(intptr_t)(e->rgb ? e->osurface : e->surface);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mp_image *mp_vdpau_get_video_surface(struct mp_vdpau_ctx *ctx,
|
static struct mp_image *mp_vdpau_get_surface(struct mp_vdpau_ctx *ctx,
|
||||||
VdpChromaType chroma, int w, int h)
|
VdpChromaType chroma,
|
||||||
|
VdpRGBAFormat rgb_format,
|
||||||
|
bool rgb, int w, int h)
|
||||||
{
|
{
|
||||||
struct vdp_functions *vdp = &ctx->vdp;
|
struct vdp_functions *vdp = &ctx->vdp;
|
||||||
int surface_index = -1;
|
int surface_index = -1;
|
||||||
VdpStatus vdp_st;
|
VdpStatus vdp_st;
|
||||||
|
|
||||||
|
if (rgb) {
|
||||||
|
chroma = (VdpChromaType)-1;
|
||||||
|
} else {
|
||||||
|
rgb_format = (VdpChromaType)-1;
|
||||||
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&ctx->pool_lock);
|
pthread_mutex_lock(&ctx->pool_lock);
|
||||||
|
|
||||||
// Destroy all unused surfaces that don't have matching parameters
|
// Destroy all unused surfaces that don't have matching parameters
|
||||||
for (int n = 0; n < MAX_VIDEO_SURFACES; n++) {
|
for (int n = 0; n < MAX_VIDEO_SURFACES; n++) {
|
||||||
struct surface_entry *e = &ctx->video_surfaces[n];
|
struct surface_entry *e = &ctx->video_surfaces[n];
|
||||||
if (!e->in_use && e->surface != VDP_INVALID_HANDLE) {
|
if (!e->in_use && e->allocated) {
|
||||||
if (e->chroma != chroma || e->w != w || e->h != h) {
|
if (e->w != w || e->h != h || e->rgb != rgb ||
|
||||||
vdp_st = vdp->video_surface_destroy(e->surface);
|
e->chroma != chroma || e->rgb_format != rgb_format)
|
||||||
CHECK_VDP_WARNING(ctx, "Error when calling vdp_video_surface_destroy");
|
{
|
||||||
e->surface = VDP_INVALID_HANDLE;
|
if (e->rgb) {
|
||||||
|
vdp_st = vdp->output_surface_destroy(e->osurface);
|
||||||
|
} else {
|
||||||
|
vdp_st = vdp->video_surface_destroy(e->surface);
|
||||||
|
}
|
||||||
|
CHECK_VDP_WARNING(ctx, "Error when destroying surface");
|
||||||
|
e->surface = e->osurface = VDP_INVALID_HANDLE;
|
||||||
|
e->allocated = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -212,9 +230,11 @@ struct mp_image *mp_vdpau_get_video_surface(struct mp_vdpau_ctx *ctx,
|
||||||
// Try to find an existing unused surface
|
// Try to find an existing unused surface
|
||||||
for (int n = 0; n < MAX_VIDEO_SURFACES; n++) {
|
for (int n = 0; n < MAX_VIDEO_SURFACES; n++) {
|
||||||
struct surface_entry *e = &ctx->video_surfaces[n];
|
struct surface_entry *e = &ctx->video_surfaces[n];
|
||||||
if (!e->in_use && e->surface != VDP_INVALID_HANDLE) {
|
if (!e->in_use && e->allocated) {
|
||||||
assert(e->w == w && e->h == h);
|
assert(e->w == w && e->h == h);
|
||||||
assert(e->chroma == chroma);
|
assert(e->chroma == chroma);
|
||||||
|
assert(e->rgb_format == rgb_format);
|
||||||
|
assert(e->rgb == rgb);
|
||||||
surface_index = n;
|
surface_index = n;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -225,12 +245,23 @@ struct mp_image *mp_vdpau_get_video_surface(struct mp_vdpau_ctx *ctx,
|
||||||
struct surface_entry *e = &ctx->video_surfaces[n];
|
struct surface_entry *e = &ctx->video_surfaces[n];
|
||||||
if (!e->in_use) {
|
if (!e->in_use) {
|
||||||
assert(e->surface == VDP_INVALID_HANDLE);
|
assert(e->surface == VDP_INVALID_HANDLE);
|
||||||
|
assert(e->osurface == VDP_INVALID_HANDLE);
|
||||||
|
assert(!e->allocated);
|
||||||
e->chroma = chroma;
|
e->chroma = chroma;
|
||||||
|
e->rgb_format = rgb_format;
|
||||||
|
e->rgb = rgb;
|
||||||
e->w = w;
|
e->w = w;
|
||||||
e->h = h;
|
e->h = h;
|
||||||
vdp_st = vdp->video_surface_create(ctx->vdp_device, chroma,
|
if (rgb) {
|
||||||
w, h, &e->surface);
|
vdp_st = vdp->output_surface_create(ctx->vdp_device, rgb_format,
|
||||||
CHECK_VDP_WARNING(ctx, "Error when calling vdp_video_surface_create");
|
w, h, &e->osurface);
|
||||||
|
e->allocated = e->osurface != VDP_INVALID_HANDLE;
|
||||||
|
} else {
|
||||||
|
vdp_st = vdp->video_surface_create(ctx->vdp_device, chroma,
|
||||||
|
w, h, &e->surface);
|
||||||
|
e->allocated = e->surface != VDP_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
CHECK_VDP_WARNING(ctx, "Error when allocating surface");
|
||||||
surface_index = n;
|
surface_index = n;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -248,6 +279,12 @@ done: ;
|
||||||
return mpi;
|
return mpi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct mp_image *mp_vdpau_get_video_surface(struct mp_vdpau_ctx *ctx,
|
||||||
|
VdpChromaType chroma, int w, int h)
|
||||||
|
{
|
||||||
|
return mp_vdpau_get_surface(ctx, chroma, 0, false, w, h);
|
||||||
|
}
|
||||||
|
|
||||||
struct mp_vdpau_ctx *mp_vdpau_create_device_x11(struct mp_log *log,
|
struct mp_vdpau_ctx *mp_vdpau_create_device_x11(struct mp_log *log,
|
||||||
struct vo_x11_state *x11)
|
struct vo_x11_state *x11)
|
||||||
{
|
{
|
||||||
|
@ -281,6 +318,10 @@ void mp_vdpau_destroy(struct mp_vdpau_ctx *ctx)
|
||||||
vdp_st = vdp->video_surface_destroy(ctx->video_surfaces[i].surface);
|
vdp_st = vdp->video_surface_destroy(ctx->video_surfaces[i].surface);
|
||||||
CHECK_VDP_WARNING(ctx, "Error when calling vdp_video_surface_destroy");
|
CHECK_VDP_WARNING(ctx, "Error when calling vdp_video_surface_destroy");
|
||||||
}
|
}
|
||||||
|
if (ctx->video_surfaces[i].osurface != VDP_INVALID_HANDLE) {
|
||||||
|
vdp_st = vdp->output_surface_destroy(ctx->video_surfaces[i].osurface);
|
||||||
|
CHECK_VDP_WARNING(ctx, "Error when calling vdp_output_surface_destroy");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vdp->device_destroy && ctx->vdp_device != VDP_INVALID_HANDLE) {
|
if (vdp->device_destroy && ctx->vdp_device != VDP_INVALID_HANDLE) {
|
||||||
|
@ -327,6 +368,22 @@ bool mp_vdpau_get_format(int imgfmt, VdpChromaType *out_chroma_type,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool mp_vdpau_get_rgb_format(int imgfmt, VdpRGBAFormat *out_rgba_format)
|
||||||
|
{
|
||||||
|
VdpRGBAFormat format = (VdpRGBAFormat)-1;
|
||||||
|
|
||||||
|
switch (imgfmt) {
|
||||||
|
case IMGFMT_BGR32:
|
||||||
|
format = VDP_RGBA_FORMAT_B8G8R8A8; break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out_rgba_format)
|
||||||
|
*out_rgba_format = format;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Use mp_vdpau_get_video_surface, and upload mpi to it. Return NULL on failure.
|
// Use mp_vdpau_get_video_surface, and upload mpi to it. Return NULL on failure.
|
||||||
// If the image is already a vdpau video surface, just return a reference.
|
// If the image is already a vdpau video surface, just return a reference.
|
||||||
struct mp_image *mp_vdpau_upload_video_surface(struct mp_vdpau_ctx *ctx,
|
struct mp_image *mp_vdpau_upload_video_surface(struct mp_vdpau_ctx *ctx,
|
||||||
|
@ -335,26 +392,36 @@ struct mp_image *mp_vdpau_upload_video_surface(struct mp_vdpau_ctx *ctx,
|
||||||
struct vdp_functions *vdp = &ctx->vdp;
|
struct vdp_functions *vdp = &ctx->vdp;
|
||||||
VdpStatus vdp_st;
|
VdpStatus vdp_st;
|
||||||
|
|
||||||
if (mpi->imgfmt == IMGFMT_VDPAU)
|
if (mpi->imgfmt == IMGFMT_VDPAU || mpi->imgfmt == IMGFMT_VDPAU_OUTPUT)
|
||||||
return mp_image_new_ref(mpi);
|
return mp_image_new_ref(mpi);
|
||||||
|
|
||||||
VdpChromaType chroma_type;
|
VdpChromaType chroma = (VdpChromaType)-1;
|
||||||
VdpYCbCrFormat pixel_format;
|
VdpYCbCrFormat ycbcr = (VdpYCbCrFormat)-1;
|
||||||
if (!mp_vdpau_get_format(mpi->imgfmt, &chroma_type, &pixel_format))
|
VdpRGBAFormat rgbafmt = (VdpRGBAFormat)-1;
|
||||||
|
bool rgb = !mp_vdpau_get_format(mpi->imgfmt, &chroma, &ycbcr);
|
||||||
|
if (rgb && !mp_vdpau_get_rgb_format(mpi->imgfmt, &rgbafmt))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
struct mp_image *hwmpi =
|
struct mp_image *hwmpi =
|
||||||
mp_vdpau_get_video_surface(ctx, chroma_type, mpi->w, mpi->h);
|
mp_vdpau_get_surface(ctx, chroma, rgbafmt, rgb, mpi->w, mpi->h);
|
||||||
if (!hwmpi)
|
if (!hwmpi)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
VdpVideoSurface surface = (intptr_t)hwmpi->planes[3];
|
if (hwmpi->imgfmt == IMGFMT_VDPAU) {
|
||||||
const void *destdata[3] = {mpi->planes[0], mpi->planes[2], mpi->planes[1]};
|
VdpVideoSurface surface = (intptr_t)hwmpi->planes[3];
|
||||||
if (mpi->imgfmt == IMGFMT_NV12)
|
const void *destdata[3] = {mpi->planes[0], mpi->planes[2], mpi->planes[1]};
|
||||||
destdata[1] = destdata[2];
|
if (mpi->imgfmt == IMGFMT_NV12)
|
||||||
vdp_st = vdp->video_surface_put_bits_y_cb_cr(surface,
|
destdata[1] = destdata[2];
|
||||||
pixel_format, destdata, mpi->stride);
|
vdp_st = vdp->video_surface_put_bits_y_cb_cr(surface,
|
||||||
CHECK_VDP_WARNING(ctx, "Error when calling vdp_video_surface_put_bits_y_cb_cr");
|
ycbcr, destdata, mpi->stride);
|
||||||
|
} else {
|
||||||
|
VdpOutputSurface rgb_surface = (intptr_t)hwmpi->planes[3];
|
||||||
|
vdp_st = vdp->output_surface_put_bits_native(rgb_surface,
|
||||||
|
&(const void *){mpi->planes[0]},
|
||||||
|
&(uint32_t){mpi->stride[0]},
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
CHECK_VDP_WARNING(ctx, "Error when uploading surface");
|
||||||
|
|
||||||
mp_image_copy_attributes(hwmpi, mpi);
|
mp_image_copy_attributes(hwmpi, mpi);
|
||||||
return hwmpi;
|
return hwmpi;
|
||||||
|
|
|
@ -58,8 +58,12 @@ struct mp_vdpau_ctx {
|
||||||
pthread_mutex_t pool_lock;
|
pthread_mutex_t pool_lock;
|
||||||
struct surface_entry {
|
struct surface_entry {
|
||||||
VdpVideoSurface surface;
|
VdpVideoSurface surface;
|
||||||
|
VdpOutputSurface osurface;
|
||||||
|
bool allocated;
|
||||||
int w, h;
|
int w, h;
|
||||||
|
VdpRGBAFormat rgb_format;
|
||||||
VdpChromaType chroma;
|
VdpChromaType chroma;
|
||||||
|
bool rgb;
|
||||||
bool in_use;
|
bool in_use;
|
||||||
} video_surfaces[MAX_VIDEO_SURFACES];
|
} video_surfaces[MAX_VIDEO_SURFACES];
|
||||||
};
|
};
|
||||||
|
@ -75,6 +79,7 @@ struct mp_image *mp_vdpau_get_video_surface(struct mp_vdpau_ctx *ctx,
|
||||||
|
|
||||||
bool mp_vdpau_get_format(int imgfmt, VdpChromaType *out_chroma_type,
|
bool mp_vdpau_get_format(int imgfmt, VdpChromaType *out_chroma_type,
|
||||||
VdpYCbCrFormat *out_pixel_format);
|
VdpYCbCrFormat *out_pixel_format);
|
||||||
|
bool mp_vdpau_get_rgb_format(int imgfmt, VdpRGBAFormat *out_rgba_format);
|
||||||
|
|
||||||
struct mp_image *mp_vdpau_upload_video_surface(struct mp_vdpau_ctx *ctx,
|
struct mp_image *mp_vdpau_upload_video_surface(struct mp_vdpau_ctx *ctx,
|
||||||
struct mp_image *mpi);
|
struct mp_image *mpi);
|
||||||
|
|
Loading…
Reference in New Issue