mirror of https://github.com/mpv-player/mpv
vo_vaapi: use new overlay API
This will probably make it slower. But since I don't care about vo_vaapi, that's perfectly OK. It serves mostly as a test for the previous commit. In addition, this code was pretty bad (custom broken scaling and not-blending that probably broke in some situation). If that wasn't enough, some vaapi drivers also provide only a single overlay at a time, while this code required a bunch. There also seems to be a Mesa bug: the overlay gets stretched when src_x/y was not 0. Or maybe I misunderstood how this is supposed to work. A bug is probably more likely? Nobody cares about this API.
This commit is contained in:
parent
55e1f15cdb
commit
3451908a34
|
@ -33,6 +33,7 @@
|
|||
#include "video/out/vo.h"
|
||||
#include "video/mp_image_pool.h"
|
||||
#include "video/sws_utils.h"
|
||||
#include "sub/draw_bmp.h"
|
||||
#include "sub/img_convert.h"
|
||||
#include "sub/osd.h"
|
||||
#include "x11_common.h"
|
||||
|
@ -83,8 +84,9 @@ struct priv {
|
|||
int force_scaled_osd;
|
||||
|
||||
VAImageFormat osd_format; // corresponds to OSD_VA_FORMAT
|
||||
struct vaapi_osd_part osd_parts[MAX_OSD_PARTS];
|
||||
struct vaapi_osd_part osd_part;
|
||||
bool osd_screen;
|
||||
struct mp_draw_sub_cache *osd_cache;
|
||||
|
||||
struct mp_image_pool *pool;
|
||||
|
||||
|
@ -102,12 +104,6 @@ struct priv {
|
|||
|
||||
#define OSD_VA_FORMAT VA_FOURCC_BGRA
|
||||
|
||||
static const bool osd_formats[SUBBITMAP_COUNT] = {
|
||||
// Actually BGRA, but only on little endian.
|
||||
// This will break on big endian, I think.
|
||||
[SUBBITMAP_RGBA] = true,
|
||||
};
|
||||
|
||||
static void draw_osd(struct vo *vo);
|
||||
|
||||
|
||||
|
@ -507,22 +503,20 @@ static bool render_to_screen(struct priv *p, struct mp_image *mpi)
|
|||
if (surface == VA_INVALID_ID)
|
||||
return false;
|
||||
|
||||
for (int n = 0; n < MAX_OSD_PARTS; n++) {
|
||||
struct vaapi_osd_part *part = &p->osd_parts[n];
|
||||
if (part->active) {
|
||||
struct vaapi_subpic *sp = &part->subpic;
|
||||
int flags = 0;
|
||||
if (p->osd_screen)
|
||||
flags |= VA_SUBPICTURE_DESTINATION_IS_SCREEN_COORD;
|
||||
status = vaAssociateSubpicture(p->display,
|
||||
sp->id, &surface, 1,
|
||||
sp->src_x, sp->src_y,
|
||||
sp->src_w, sp->src_h,
|
||||
sp->dst_x, sp->dst_y,
|
||||
sp->dst_w, sp->dst_h,
|
||||
flags);
|
||||
CHECK_VA_STATUS(p, "vaAssociateSubpicture()");
|
||||
}
|
||||
struct vaapi_osd_part *part = &p->osd_part;
|
||||
if (part->active) {
|
||||
struct vaapi_subpic *sp = &part->subpic;
|
||||
int flags = 0;
|
||||
if (p->osd_screen)
|
||||
flags |= VA_SUBPICTURE_DESTINATION_IS_SCREEN_COORD;
|
||||
status = vaAssociateSubpicture(p->display,
|
||||
sp->id, &surface, 1,
|
||||
sp->src_x, sp->src_y,
|
||||
sp->src_w, sp->src_h,
|
||||
sp->dst_x, sp->dst_y,
|
||||
sp->dst_w, sp->dst_h,
|
||||
flags);
|
||||
CHECK_VA_STATUS(p, "vaAssociateSubpicture()");
|
||||
}
|
||||
|
||||
int flags = va_get_colorspace_flag(p->image_params.color.space) |
|
||||
|
@ -542,14 +536,11 @@ static bool render_to_screen(struct priv *p, struct mp_image *mpi)
|
|||
flags);
|
||||
CHECK_VA_STATUS(p, "vaPutSurface()");
|
||||
|
||||
for (int n = 0; n < MAX_OSD_PARTS; n++) {
|
||||
struct vaapi_osd_part *part = &p->osd_parts[n];
|
||||
if (part->active) {
|
||||
struct vaapi_subpic *sp = &part->subpic;
|
||||
status = vaDeassociateSubpicture(p->display, sp->id,
|
||||
&surface, 1);
|
||||
CHECK_VA_STATUS(p, "vaDeassociateSubpicture()");
|
||||
}
|
||||
if (part->active) {
|
||||
struct vaapi_subpic *sp = &part->subpic;
|
||||
status = vaDeassociateSubpicture(p->display, sp->id,
|
||||
&surface, 1);
|
||||
CHECK_VA_STATUS(p, "vaDeassociateSubpicture()");
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -626,92 +617,6 @@ error:
|
|||
return -1;
|
||||
}
|
||||
|
||||
static void draw_osd_cb(void *pctx, struct sub_bitmaps *imgs)
|
||||
{
|
||||
struct priv *p = pctx;
|
||||
|
||||
struct vaapi_osd_part *part = &p->osd_parts[imgs->render_index];
|
||||
if (imgs->change_id != part->change_id) {
|
||||
part->change_id = imgs->change_id;
|
||||
|
||||
struct mp_rect bb;
|
||||
if (!mp_sub_bitmaps_bb(imgs, &bb))
|
||||
goto error;
|
||||
|
||||
// Prevent filtering artifacts on borders
|
||||
int pad = 2;
|
||||
|
||||
int w = bb.x1 - bb.x0;
|
||||
int h = bb.y1 - bb.y0;
|
||||
if (part->image.w < w + pad || part->image.h < h + pad) {
|
||||
int sw = MP_ALIGN_UP(w + pad, 64);
|
||||
int sh = MP_ALIGN_UP(h + pad, 64);
|
||||
if (new_subpicture(p, sw, sh, &part->image) < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
struct vaapi_osd_image *img = &part->image;
|
||||
struct mp_image vaimg;
|
||||
if (!va_image_map(p->mpvaapi, &img->image, &vaimg))
|
||||
goto error;
|
||||
|
||||
// Clear borders and regions uncovered by sub-bitmaps
|
||||
mp_image_clear(&vaimg, 0, 0, w + pad, h + pad);
|
||||
|
||||
for (int n = 0; n < imgs->num_parts; n++) {
|
||||
struct sub_bitmap *sub = &imgs->parts[n];
|
||||
|
||||
struct mp_image src = {0};
|
||||
mp_image_setfmt(&src, IMGFMT_BGRA);
|
||||
mp_image_set_size(&src, sub->w, sub->h);
|
||||
src.planes[0] = sub->bitmap;
|
||||
src.stride[0] = sub->stride;
|
||||
|
||||
struct mp_image *bmp = &src;
|
||||
|
||||
struct mp_image *tmp = NULL;
|
||||
if (sub->dw != sub->w || sub->dh != sub->h) {
|
||||
tmp = mp_image_alloc(IMGFMT_BGRA, sub->dw, sub->dh);
|
||||
if (!tmp)
|
||||
goto error;
|
||||
|
||||
mp_image_swscale(tmp, &src, mp_sws_fast_flags);
|
||||
|
||||
bmp = tmp;
|
||||
}
|
||||
|
||||
// Note: nothing guarantees that the sub-bitmaps don't overlap.
|
||||
// But in all currently existing cases, they don't.
|
||||
// We simply hope that this won't change, and nobody will
|
||||
// ever notice our little shortcut here.
|
||||
|
||||
size_t dst = (sub->y - bb.y0) * vaimg.stride[0] +
|
||||
(sub->x - bb.x0) * 4;
|
||||
|
||||
memcpy_pic(vaimg.planes[0] + dst, bmp->planes[0], sub->dw * 4,
|
||||
sub->dh, vaimg.stride[0], bmp->stride[0]);
|
||||
|
||||
talloc_free(tmp);
|
||||
}
|
||||
|
||||
if (!va_image_unmap(p->mpvaapi, &img->image))
|
||||
goto error;
|
||||
|
||||
part->subpic = (struct vaapi_subpic) {
|
||||
.id = img->subpic_id,
|
||||
.src_x = 0, .src_y = 0,
|
||||
.src_w = w, .src_h = h,
|
||||
.dst_x = bb.x0, .dst_y = bb.y0,
|
||||
.dst_w = w, .dst_h = h,
|
||||
};
|
||||
}
|
||||
|
||||
part->active = true;
|
||||
|
||||
error:
|
||||
;
|
||||
}
|
||||
|
||||
static void draw_osd(struct vo *vo)
|
||||
{
|
||||
struct priv *p = vo->priv;
|
||||
|
@ -731,9 +636,70 @@ static void draw_osd(struct vo *vo)
|
|||
res = &vid_res;
|
||||
}
|
||||
|
||||
for (int n = 0; n < MAX_OSD_PARTS; n++)
|
||||
p->osd_parts[n].active = false;
|
||||
osd_draw(vo->osd, *res, pts, 0, osd_formats, draw_osd_cb, p);
|
||||
p->osd_part.active = false;
|
||||
|
||||
if (!p->osd_cache)
|
||||
p->osd_cache = mp_draw_sub_alloc(p);
|
||||
|
||||
struct sub_bitmap_list *sbs = osd_render(vo->osd, *res, pts, 0,
|
||||
mp_draw_sub_formats);
|
||||
|
||||
struct mp_rect act_rc[1], mod_rc[64];
|
||||
int num_act_rc = 0, num_mod_rc = 0;
|
||||
|
||||
struct mp_image *osd = mp_draw_sub_overlay(p->osd_cache, sbs,
|
||||
act_rc, MP_ARRAY_SIZE(act_rc), &num_act_rc,
|
||||
mod_rc, MP_ARRAY_SIZE(mod_rc), &num_mod_rc);
|
||||
|
||||
if (!osd)
|
||||
goto error;
|
||||
|
||||
struct vaapi_osd_part *part = &p->osd_part;
|
||||
|
||||
part->active = false;
|
||||
|
||||
int w = res->w;
|
||||
int h = res->h;
|
||||
if (part->image.w != w || part->image.h != h) {
|
||||
if (new_subpicture(p, w, h, &part->image) < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
struct vaapi_osd_image *img = &part->image;
|
||||
struct mp_image vaimg;
|
||||
if (!va_image_map(p->mpvaapi, &img->image, &vaimg))
|
||||
goto error;
|
||||
|
||||
for (int n = 0; n < num_mod_rc; n++) {
|
||||
struct mp_rect *rc = &mod_rc[n];
|
||||
|
||||
int rw = mp_rect_w(*rc);
|
||||
int rh = mp_rect_h(*rc);
|
||||
|
||||
void *src = mp_image_pixel_ptr(osd, 0, rc->x0, rc->y0);
|
||||
void *dst = vaimg.planes[0] + rc->y0 * vaimg.stride[0] + rc->x0 * 4;
|
||||
|
||||
memcpy_pic(dst, src, rw * 4, rh, vaimg.stride[0], osd->stride[0]);
|
||||
}
|
||||
|
||||
if (!va_image_unmap(p->mpvaapi, &img->image))
|
||||
goto error;
|
||||
|
||||
if (num_act_rc) {
|
||||
struct mp_rect rc = act_rc[0];
|
||||
rc.x0 = rc.y0 = 0; // must be a Mesa bug
|
||||
part->subpic = (struct vaapi_subpic) {
|
||||
.id = img->subpic_id,
|
||||
.src_x = rc.x0, .src_y = rc.y0,
|
||||
.src_w = mp_rect_w(rc), .src_h = mp_rect_h(rc),
|
||||
.dst_x = rc.x0, .dst_y = rc.y0,
|
||||
.dst_w = mp_rect_w(rc), .dst_h = mp_rect_h(rc),
|
||||
};
|
||||
part->active = true;
|
||||
}
|
||||
|
||||
error:
|
||||
talloc_free(sbs);
|
||||
}
|
||||
|
||||
static int control(struct vo *vo, uint32_t request, void *data)
|
||||
|
@ -767,10 +733,8 @@ static void uninit(struct vo *vo)
|
|||
free_video_specific(p);
|
||||
talloc_free(p->pool);
|
||||
|
||||
for (int n = 0; n < MAX_OSD_PARTS; n++) {
|
||||
struct vaapi_osd_part *part = &p->osd_parts[n];
|
||||
free_subpicture(p, &part->image);
|
||||
}
|
||||
struct vaapi_osd_part *part = &p->osd_part;
|
||||
free_subpicture(p, &part->image);
|
||||
|
||||
if (vo->hwdec_devs) {
|
||||
hwdec_devices_remove(vo->hwdec_devs, &p->mpvaapi->hwctx);
|
||||
|
@ -847,11 +811,9 @@ static int preinit(struct vo *vo)
|
|||
if (!p->osd_format.fourcc)
|
||||
MP_ERR(vo, "OSD format not supported. Disabling OSD.\n");
|
||||
|
||||
for (int n = 0; n < MAX_OSD_PARTS; n++) {
|
||||
struct vaapi_osd_part *part = &p->osd_parts[n];
|
||||
part->image.image.image_id = VA_INVALID_ID;
|
||||
part->image.subpic_id = VA_INVALID_ID;
|
||||
}
|
||||
struct vaapi_osd_part *part = &p->osd_part;
|
||||
part->image.image.image_id = VA_INVALID_ID;
|
||||
part->image.subpic_id = VA_INVALID_ID;
|
||||
|
||||
int max_display_attrs = vaMaxNumDisplayAttributes(p->display);
|
||||
p->va_display_attrs = talloc_array(vo, VADisplayAttribute, max_display_attrs);
|
||||
|
|
Loading…
Reference in New Issue