VO, sub: refactor

Remove VFCTRL_DRAW_OSD, VFCAP_EOSD_FILTER, VFCAP_EOSD_RGBA, VFCAP_EOSD,
VOCTRL_DRAW_EOSD, VOCTRL_GET_EOSD_RES, VOCTRL_QUERY_EOSD_FORMAT.

Remove draw_osd_with_eosd(), which rendered the OSD by calling
VOCTRL_DRAW_EOSD. Change VOs to call osd_draw() directly, which takes
a callback as argument. (This basically works like the old OSD API,
except multiple OSD bitmap formats are supported and caching is
possible.)

Remove all mentions of "eosd". It's simply "osd" now.

Make OSD size per-OSD-object, as they can be different when using
vf_sub. Include display_par/video_par in resolution change detection.

Fix the issue with margin borders in vo_corevideo.
This commit is contained in:
wm4 2012-10-19 19:25:18 +02:00
parent a4f9077f6c
commit 4d11f32162
30 changed files with 331 additions and 375 deletions

View File

@ -664,14 +664,14 @@ screenshot
``Taking screenshots`` section for details.
ass
Moves SSA/ASS subtitle rendering to an arbitrary point in the filter
Moves subtitle rendering to an arbitrary point in the filter
chain, or force subtitle rendering in the video filter as opposed to using
video output EOSD support. See the ``--ass`` option.
video output OSD support.
*EXAMPLE*:
``--vf=ass,eq``
Moves SSA/ASS rendering before the eq filter. This will put both
Moves sub rendering before the eq filter. This will put both
subtitle colors and video under the influence of the video equalizer
settings.

View File

@ -171,8 +171,8 @@ direct3d_shaders (Windows only)
Never render YUV video with more than 8 bits per component.
(Using this flag will force software conversion to 8 bit.)
disable-eosd
Disable EOSD rendering for subtitles.
disable-osd
Disable OSD rendering for subtitles.
(Using this flag might force the insertion of the 'ass' video filter,
which will render the subtitles in software.)

View File

@ -99,7 +99,6 @@ struct vf_ctrl_screenshot {
#define VFCTRL_SET_PP_LEVEL 5 // set postprocessing level
#define VFCTRL_SET_EQUALIZER 6 // set color options (brightness,contrast etc)
#define VFCTRL_GET_EQUALIZER 8 // get color options (brightness,contrast etc)
#define VFCTRL_DRAW_OSD 7
#define VFCTRL_DUPLICATE_FRAME 11 // For encoding - encode zero-change frame
#define VFCTRL_SKIP_NEXT_FRAME 12 // For encoding - drop the next frame that passes thru
#define VFCTRL_FLUSH_FRAMES 13 // For encoding - flush delayed frames

View File

@ -49,12 +49,12 @@ static const struct vf_priv_s {
unsigned int outfmt;
struct mp_csp_details csp;
// 1 = auto-added filter: insert only if chain does not support EOSD already
// 1 = auto-added filter: insert only if chain does not support OSD already
// 0 = insert always
int auto_insert;
struct osd_state *osd;
struct mp_eosd_res dim;
struct mp_osd_res dim;
} vf_priv_dflt = {
.csp = MP_CSP_DETAILS_DEFAULTS,
};
@ -78,7 +78,7 @@ static int config(struct vf_instance *vf,
double dar = (double)d_width / d_height;
double sar = (double)width / height;
vf->priv->dim = (struct mp_eosd_res) {
vf->priv->dim = (struct mp_osd_res) {
.w = vf->priv->outw,
.h = vf->priv->outh,
.mt = opts->ass_top_margin,
@ -227,11 +227,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
prepare_image(vf, mpi);
if (pts != MP_NOPTS_VALUE) {
struct sub_render_params subparams = {
.pts = pts,
.dim = priv->dim,
};
osd_draw_on_image(osd, &subparams, OSD_DRAW_SUB_FILTER, vf->dmpi,
osd_draw_on_image(osd, priv->dim, pts, OSD_DRAW_SUB_FILTER, vf->dmpi,
&priv->csp);
}
@ -287,7 +283,7 @@ static int vf_open(vf_instance_t *vf, char *args)
if (!vf->priv->outfmt) {
uninit(vf);
return 0;
} else if (vf->priv->auto_insert && flags & VFCAP_EOSD) {
} else if (vf->priv->auto_insert && flags & VFCAP_OSD) {
uninit(vf);
return -1;
}
@ -301,7 +297,7 @@ static int vf_open(vf_instance_t *vf, char *args)
vf->control = control;
vf->get_image = get_image;
vf->put_image = put_image;
vf->default_caps = VFCAP_EOSD | VFCAP_EOSD_FILTER;
vf->default_caps = VFCAP_OSD;
return 1;
}

View File

@ -91,11 +91,6 @@ static int control(struct vf_instance *vf, int request, void *data)
return vo_control(video_out, VOCTRL_GET_YUV_COLORSPACE, data) == true;
case VFCTRL_SET_YUV_COLORSPACE:
return vo_control(video_out, VOCTRL_SET_YUV_COLORSPACE, data) == true;
case VFCTRL_DRAW_OSD:
if (!video_out->config_ok)
return CONTROL_FALSE; // vo not configured?
vo_draw_osd(video_out, data);
return CONTROL_TRUE;
case VFCTRL_SET_EQUALIZER: {
vf_equalizer_t *eq = data;
if (!video_out->config_ok)

View File

@ -40,11 +40,7 @@
#define VFCAP_ACCEPT_STRIDE 0x400
// filter does postprocessing (so you shouldn't scale/filter image before it)
#define VFCAP_POSTPROC 0x800
// filter can draw EOSD
#define VFCAP_EOSD 0x2000
// used by libvo and vf_vo, indicates the VO does not support draw_slice for this format
#define VOCAP_NOSLICES 0x8000
#define VFCAP_EOSD_FILTER 0x20000 // EOSD is drawn in filter chain
#define VFCAP_EOSD_RGBA 0x40000
#endif /* MPLAYER_VFCAP_H */

View File

@ -68,6 +68,9 @@ struct mpgl_osd *mpgl_osd_init(GL *gl, bool legacy)
ctx->parts[n] = p;
}
for (int n = 0; n < SUBBITMAP_COUNT; n++)
ctx->formats[n] = ctx->fmt_table[n].type != 0;
return ctx;
}
@ -84,11 +87,6 @@ void mpgl_osd_destroy(struct mpgl_osd *ctx)
talloc_free(ctx);
}
bool mpgl_osd_query_format(struct mpgl_osd *ctx, int osd_format)
{
return ctx->fmt_table[osd_format].type != 0;
}
static bool upload_pbo(struct mpgl_osd *ctx, struct mpgl_osd_part *osd,
struct sub_bitmaps *imgs)
{
@ -159,9 +157,9 @@ static bool upload_osd(struct mpgl_osd *ctx, struct mpgl_osd_part *osd,
osd->packer->padding = ctx->scaled || imgs->scaled;
int r = packer_pack_from_subbitmaps(osd->packer, imgs);
if (r < 0) {
mp_msg(MSGT_VO, MSGL_ERR, "[gl] EOSD bitmaps do not fit on "
"a surface with the maximum supported size %dx%d.\n",
osd->packer->w_max, osd->packer->h_max);
mp_msg(MSGT_VO, MSGL_ERR, "[gl] OSD bitmaps do not fit on "
"a surface with the maximum supported size %dx%d.\n",
osd->packer->w_max, osd->packer->h_max);
return false;
}
@ -207,7 +205,7 @@ static bool upload_osd(struct mpgl_osd *ctx, struct mpgl_osd_part *osd,
struct mpgl_osd_part *mpgl_osd_generate(struct mpgl_osd *ctx,
struct sub_bitmaps *imgs)
{
if (imgs->num_parts == 0 || !mpgl_osd_query_format(ctx, imgs->format))
if (imgs->num_parts == 0 || !ctx->formats[imgs->format])
return NULL;
struct mpgl_osd_part *osd = ctx->parts[imgs->render_index];
@ -226,7 +224,7 @@ struct mpgl_osd_part *mpgl_osd_generate(struct mpgl_osd *ctx,
return osd->packer->count ? osd : NULL;
}
void mpgl_osd_gl_set_state(struct mpgl_osd *ctx, struct mpgl_osd_part *p)
void mpgl_osd_set_gl_state(struct mpgl_osd *ctx, struct mpgl_osd_part *p)
{
GL *gl = ctx->gl;
@ -235,7 +233,7 @@ void mpgl_osd_gl_set_state(struct mpgl_osd *ctx, struct mpgl_osd_part *p)
gl->BlendFunc(blend_factors[p->format][0], blend_factors[p->format][1]);
}
void mpgl_osd_gl_unset_state(struct mpgl_osd *ctx, struct mpgl_osd_part *p)
void mpgl_osd_unset_gl_state(struct mpgl_osd *ctx, struct mpgl_osd_part *p)
{
GL *gl = ctx->gl;
@ -249,8 +247,9 @@ struct vertex {
float texcoord[2];
};
void mpgl_osd_draw_legacy(struct mpgl_osd *ctx, struct sub_bitmaps *imgs)
static void draw_legacy_cb(void *pctx, struct sub_bitmaps *imgs)
{
struct mpgl_osd *ctx = pctx;
struct mpgl_osd_part *osd = mpgl_osd_generate(ctx, imgs);
if (!osd)
return;
@ -309,11 +308,17 @@ void mpgl_osd_draw_legacy(struct mpgl_osd *ctx, struct sub_bitmaps *imgs)
gl->EnableClientState(GL_TEXTURE_COORD_ARRAY);
gl->EnableClientState(GL_COLOR_ARRAY);
mpgl_osd_gl_set_state(ctx, osd);
mpgl_osd_set_gl_state(ctx, osd);
gl->DrawArrays(GL_TRIANGLES, 0, osd->num_vertices);
mpgl_osd_gl_unset_state(ctx, osd);
mpgl_osd_unset_gl_state(ctx, osd);
gl->DisableClientState(GL_VERTEX_ARRAY);
gl->DisableClientState(GL_TEXTURE_COORD_ARRAY);
gl->DisableClientState(GL_COLOR_ARRAY);
}
void mpgl_osd_draw_legacy(struct mpgl_osd *ctx, struct osd_state *osd,
struct mp_osd_res res)
{
osd_draw(osd, res, osd->vo_pts, 0, ctx->formats, draw_legacy_cb, ctx);
}

View File

@ -24,19 +24,20 @@ struct mpgl_osd {
bool scaled;
struct mpgl_osd_part *parts[MAX_OSD_PARTS];
const struct osd_fmt_entry *fmt_table;
bool formats[SUBBITMAP_COUNT];
void *scratch;
};
struct mpgl_osd *mpgl_osd_init(GL *gl, bool legacy);
void mpgl_osd_destroy(struct mpgl_osd *ctx);
bool mpgl_osd_query_format(struct mpgl_osd *ctx, int osd_format);
void mpgl_osd_draw_legacy(struct mpgl_osd *ctx, struct sub_bitmaps *b);
struct mpgl_osd_part *mpgl_osd_generate(struct mpgl_osd *ctx,
struct sub_bitmaps *b);
void mpgl_osd_gl_set_state(struct mpgl_osd *ctx, struct mpgl_osd_part *p);
void mpgl_osd_gl_unset_state(struct mpgl_osd *ctx, struct mpgl_osd_part *p);
void mpgl_osd_set_gl_state(struct mpgl_osd *ctx, struct mpgl_osd_part *p);
void mpgl_osd_unset_gl_state(struct mpgl_osd *ctx, struct mpgl_osd_part *p);
void mpgl_osd_draw_legacy(struct mpgl_osd *ctx, struct osd_state *osd,
struct mp_osd_res res);
#endif

View File

@ -64,9 +64,6 @@ enum mp_voctrl {
VOCTRL_ONTOP,
VOCTRL_ROOTWIN,
VOCTRL_BORDER,
VOCTRL_DRAW_EOSD,
VOCTRL_GET_EOSD_RES, // struct mp_eosd_res
VOCTRL_QUERY_EOSD_FORMAT, // int
VOCTRL_SET_DEINTERLACE,
VOCTRL_GET_DEINTERLACE,

View File

@ -19,6 +19,8 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <assert.h>
#import "vo_corevideo.h"
// mplayer includes
@ -50,6 +52,7 @@ struct priv {
unsigned int image_width;
unsigned int image_height;
struct mp_csp_details colorspace;
int ass_border_x, ass_border_y;
CVPixelBufferRef pixelBuffer;
CVOpenGLTextureCacheRef textureCache;
@ -84,6 +87,8 @@ static void resize(struct vo *vo, int width, int height)
scale_x = (GLdouble)new_w / (GLdouble)p->image_width;
scale_y = (GLdouble)new_h / (GLdouble)p->image_height;
gl->Scaled(scale_x, scale_y, 1);
p->ass_border_x = (vo->dwidth - new_w) / 2;
p->ass_border_y = (vo->dheight - new_h) / 2;
}
gl->Ortho(0, p->image_width, p->image_height, 0, -1.0, 1.0);
@ -249,7 +254,7 @@ static int query_format(struct vo *vo, uint32_t format)
struct priv *p = vo->priv;
const int flags = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW |
VFCAP_OSD | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN |
VOCAP_NOSLICES | VFCAP_EOSD;
VOCAP_NOSLICES;
switch (format) {
case IMGFMT_YUY2:
p->pixelFormat = kYUVSPixelFormat;
@ -293,6 +298,26 @@ static int preinit(struct vo *vo, const char *arg)
return 0;
}
static void draw_osd(struct vo *vo, struct osd_state *osd)
{
struct priv *p = vo->priv;
GL *gl = p->mpglctx->gl;
assert(p->osd);
struct mp_osd_res res = {
.w = vo->dwidth,
.h = vo->dheight,
.ml = p->ass_border_x,
.mr = p->ass_border_x,
.mt = p->ass_border_y,
.mb = p->ass_border_y,
.display_par = vo->monitor_par,
.video_par = vo->aspdat.par,
};
mpgl_osd_draw_legacy(p->osd, osd, res);
}
static CFStringRef get_cv_csp_matrix(struct vo *vo)
{
struct priv *p = vo->priv;
@ -324,19 +349,6 @@ static int control(struct vo *vo, uint32_t request, void *data)
return draw_image(vo, data);
case VOCTRL_QUERY_FORMAT:
return query_format(vo, *(uint32_t*)data);
case VOCTRL_DRAW_EOSD:
mpgl_osd_draw_legacy(p->osd, data);
return VO_TRUE;
case VOCTRL_QUERY_EOSD_FORMAT:
return mpgl_osd_query_format(p->osd, *(int *)data)
? VO_TRUE : VO_NOTIMPL;
case VOCTRL_GET_EOSD_RES: {
struct mp_eosd_res *r = data;
r->w = vo->dwidth;
r->h = vo->dheight;
r->mt = r->mb = r->ml = r->mr = 0;
return VO_TRUE;
}
case VOCTRL_ONTOP:
p->mpglctx->ontop(vo);
return VO_TRUE;
@ -377,7 +389,7 @@ const struct vo_driver video_out_corevideo = {
.preinit = preinit,
.config = config,
.control = control,
.draw_osd = draw_osd_with_eosd,
.draw_osd = draw_osd,
.flip_page = flip_page,
.check_events = check_events,
.uninit = uninit,

View File

@ -59,13 +59,13 @@
#define DEVTYPE D3DDEVTYPE_HAL
//#define DEVTYPE D3DDEVTYPE_REF
#define D3DFVF_EOSD_VERTEX (D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_DIFFUSE)
#define D3DFVF_OSD_VERTEX (D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_DIFFUSE)
typedef struct {
float x, y, z;
D3DCOLOR color;
float tu, tv;
} vertex_eosd;
} vertex_osd;
#define D3DFVF_VIDEO_VERTEX (D3DFVF_XYZ | D3DFVF_TEX3)
@ -113,7 +113,7 @@ struct osdpart {
int bitmap_id, bitmap_pos_id;
struct d3dtex texture;
int num_vertices;
vertex_eosd *vertices;
vertex_osd *vertices;
struct bitmap_packer *packer;
};
@ -125,7 +125,7 @@ typedef struct d3d_priv {
int opt_disable_stretchrect;
int opt_disable_shaders;
int opt_only_8bit;
int opt_disable_eosd;
int opt_disable_osd;
int opt_disable_texture_align;
// debugging
int opt_force_power_of_2;
@ -232,6 +232,10 @@ static const D3DFORMAT osd_fmt_table[SUBBITMAP_COUNT] = {
[SUBBITMAP_LIBASS] = D3DFMT_A8,
[SUBBITMAP_RGBA] = D3DFMT_A8R8G8B8,
};
static const bool osd_fmt_supported[SUBBITMAP_COUNT] = {
[SUBBITMAP_LIBASS] = true,
[SUBBITMAP_RGBA] = true,
};
static void update_colorspace(d3d_priv *priv);
@ -241,7 +245,6 @@ static uint32_t d3d_draw_frame(d3d_priv *priv);
static int draw_slice(struct vo *vo, uint8_t *src[], int stride[], int w, int h,
int x, int y);
static void uninit(struct vo *vo);
static void draw_osd(d3d_priv *priv, struct sub_bitmaps *imgs);
static void flip_page(struct vo *vo);
static mp_image_t *get_screenshot(d3d_priv *priv);
static mp_image_t *get_window_screenshot(d3d_priv *priv);
@ -1224,11 +1227,11 @@ static int query_format(d3d_priv *priv, uint32_t movie_fmt)
if (!init_rendering_mode(priv, movie_fmt, false))
return 0;
int eosd_caps = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW
| VFCAP_OSD | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN;
if (!priv->opt_disable_eosd)
eosd_caps |= VFCAP_EOSD | VFCAP_EOSD_RGBA;
return eosd_caps;
int osd_caps = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW
| VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN;
if (!priv->opt_disable_osd)
osd_caps |= VFCAP_OSD;
return osd_caps;
}
/****************************************************************************
@ -1296,7 +1299,7 @@ static void update_colorspace(d3d_priv *priv)
}
const char *options_help_text = "-vo direct3d command line help:\n"
"Example: -vo direct3d:disable-eosd:disable-textures\n"
"Example: -vo direct3d:disable-osd:disable-textures\n"
"Options:\n"
" prefer-stretchrect\n"
" Use IDirect3DDevice9::StretchRect over other methods if possible.\n"
@ -1311,8 +1314,8 @@ const char *options_help_text = "-vo direct3d command line help:\n"
" only-8bit\n"
" Never render YUV video with more than 8 bits per component.\n"
" (Using this flag will force software conversion to 8 bit.)\n"
" disable-eosd\n"
" Disable EOSD rendering for subtitles.\n"
" disable-osd\n"
" Disable OSD rendering.\n"
" (Using this flag might force the insertion of the 'ass' video filter,\n"
" which will render the subtitles in software.)\n"
" disable-texture-align\n"
@ -1386,7 +1389,7 @@ static int preinit_internal(struct vo *vo, const char *arg, bool allow_shaders)
{"disable-stretchrect", OPT_ARG_BOOL, &priv->opt_disable_stretchrect},
{"disable-shaders", OPT_ARG_BOOL, &priv->opt_disable_shaders},
{"only-8bit", OPT_ARG_BOOL, &priv->opt_only_8bit},
{"disable-eosd", OPT_ARG_BOOL, &priv->opt_disable_eosd},
{"disable-osd", OPT_ARG_BOOL, &priv->opt_disable_osd},
{"force-power-of-2", OPT_ARG_BOOL, &priv->opt_force_power_of_2},
{"disable-texture-align", OPT_ARG_BOOL, &priv->opt_disable_texture_align},
{"texture-memory", OPT_ARG_INT, &priv->opt_texture_memory},
@ -1507,21 +1510,6 @@ static int control(struct vo *vo, uint32_t request, void *data)
return VO_TRUE;
case VOCTRL_GET_PANSCAN:
return VO_TRUE;
case VOCTRL_DRAW_EOSD:
if (!data)
return VO_FALSE;
draw_osd(priv, data);
return VO_TRUE;
case VOCTRL_QUERY_EOSD_FORMAT:
return osd_fmt_table[*(int *)data] ? VO_TRUE : VO_NOTIMPL;
case VOCTRL_GET_EOSD_RES: {
struct mp_eosd_res *r = data;
r->w = vo->dwidth;
r->h = vo->dheight;
r->ml = r->mr = priv->border_x;
r->mt = r->mb = priv->border_y;
return VO_TRUE;
}
case VOCTRL_SCREENSHOT: {
struct voctrl_screenshot_args *args = data;
if (args->full_window)
@ -1905,7 +1893,7 @@ static bool upload_osd(d3d_priv *priv, struct osdpart *osd,
osd->packer->padding = imgs->scaled; // assume 2x2 filter on scaling
int r = packer_pack_from_subbitmaps(osd->packer, imgs);
if (r < 0) {
mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>EOSD bitmaps do not fit on "
mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>OSD bitmaps do not fit on "
"a surface with the maximum supported size %dx%d.\n",
osd->packer->w_max, osd->packer->h_max);
return false;
@ -1939,7 +1927,7 @@ static bool upload_osd(d3d_priv *priv, struct osdpart *osd,
if (FAILED(IDirect3DTexture9_LockRect(osd->texture.system, 0, &locked_rect,
&dirty_rc, 0)))
{
mp_msg(MSGT_VO,MSGL_ERR, "<vo_direct3d>EOSD texture lock failed.\n");
mp_msg(MSGT_VO,MSGL_ERR, "<vo_direct3d>OSD texture lock failed.\n");
return false;
}
@ -1948,7 +1936,7 @@ static bool upload_osd(d3d_priv *priv, struct osdpart *osd,
locked_rect.Pitch);
if (FAILED(IDirect3DTexture9_UnlockRect(osd->texture.system, 0))) {
mp_msg(MSGT_VO,MSGL_ERR, "<vo_direct3d>EOSD texture unlock failed.\n");
mp_msg(MSGT_VO,MSGL_ERR, "<vo_direct3d>OSD texture unlock failed.\n");
return false;
}
@ -1985,10 +1973,9 @@ static D3DCOLOR ass_to_d3d_color(uint32_t color)
return D3DCOLOR_ARGB(a, r, g, b);
}
static void draw_osd(d3d_priv *priv, struct sub_bitmaps *imgs)
static void draw_osd_cb(void *ctx, struct sub_bitmaps *imgs)
{
if (!priv->d3d_device)
return;
d3d_priv *priv = ctx;
struct osdpart *osd = generate_osd(priv, imgs);
if (!osd)
@ -1999,7 +1986,7 @@ static void draw_osd(d3d_priv *priv, struct sub_bitmaps *imgs)
// the number of vertices by using an indexed vertex array, but it's
// probably not worth doing)
osd->num_vertices = osd->packer->count * 6;
osd->vertices = talloc_realloc(osd, osd->vertices, vertex_eosd,
osd->vertices = talloc_realloc(osd, osd->vertices, vertex_osd,
osd->num_vertices);
float tex_w = osd->texture.tex_w;
@ -2022,11 +2009,11 @@ static void draw_osd(d3d_priv *priv, struct sub_bitmaps *imgs)
float tx1 = (p.x + b->w) / tex_w;
float ty1 = (p.y + b->h) / tex_h;
vertex_eosd *v = &osd->vertices[n * 6];
v[0] = (vertex_eosd) { x0, y0, 0, color, tx0, ty0 };
v[1] = (vertex_eosd) { x1, y0, 0, color, tx1, ty0 };
v[2] = (vertex_eosd) { x0, y1, 0, color, tx0, ty1 };
v[3] = (vertex_eosd) { x1, y1, 0, color, tx1, ty1 };
vertex_osd *v = &osd->vertices[n * 6];
v[0] = (vertex_osd) { x0, y0, 0, color, tx0, ty0 };
v[1] = (vertex_osd) { x1, y0, 0, color, tx1, ty0 };
v[2] = (vertex_osd) { x0, y1, 0, color, tx0, ty1 };
v[3] = (vertex_osd) { x1, y1, 0, color, tx1, ty1 };
v[4] = v[2];
v[5] = v[1];
}
@ -2054,10 +2041,10 @@ static void draw_osd(d3d_priv *priv, struct sub_bitmaps *imgs)
D3DBLEND_ONE);
}
IDirect3DDevice9_SetFVF(priv->d3d_device, D3DFVF_EOSD_VERTEX);
IDirect3DDevice9_SetFVF(priv->d3d_device, D3DFVF_OSD_VERTEX);
IDirect3DDevice9_DrawPrimitiveUP(priv->d3d_device, D3DPT_TRIANGLELIST,
osd->num_vertices / 3,
osd->vertices, sizeof(vertex_eosd));
osd->vertices, sizeof(vertex_osd));
IDirect3DDevice9_SetTextureStageState(priv->d3d_device,0,
D3DTSS_COLORARG1, D3DTA_TEXTURE);
@ -2072,6 +2059,27 @@ static void draw_osd(d3d_priv *priv, struct sub_bitmaps *imgs)
D3DRS_ALPHABLENDENABLE, FALSE);
}
static void draw_osd(struct vo *vo, struct osd_state *osd)
{
d3d_priv *priv = vo->priv;
if (!priv->d3d_device)
return;
struct mp_osd_res res = {
.w = vo->dwidth,
.h = vo->dheight,
.ml = priv->border_x,
.mr = priv->border_x,
.mt = priv->border_y,
.mb = priv->border_y,
.display_par = vo->monitor_par,
.video_par = vo->aspdat.par,
};
osd_draw(osd, res, osd->vo_pts, 0, osd_fmt_supported, draw_osd_cb, priv);
}
#define AUTHOR "Georgi Petrov (gogothebee) <gogothebee@gmail.com> and others"
const struct vo_driver video_out_direct3d = {
@ -2086,7 +2094,7 @@ const struct vo_driver video_out_direct3d = {
.config = config,
.control = control,
.draw_slice = draw_slice,
.draw_osd = draw_osd_with_eosd,
.draw_osd = draw_osd,
.flip_page = flip_page,
.check_events = check_events,
.uninit = uninit,
@ -2104,7 +2112,7 @@ const struct vo_driver video_out_direct3d_shaders = {
.config = config,
.control = control,
.draw_slice = draw_slice,
.draw_osd = draw_osd_with_eosd,
.draw_osd = draw_osd,
.flip_page = flip_page,
.check_events = check_events,
.uninit = uninit,

View File

@ -198,8 +198,8 @@ static int query_format(struct vo *vo, uint32_t format)
VFCAP_CSP_SUPPORTED |
// we can do it
VFCAP_CSP_SUPPORTED_BY_HW |
// we don't convert colorspaces here (TODO: if we add EOSD rendering, only set this flag if EOSD can be rendered without extra conversions)
VFCAP_OSD | VFCAP_EOSD |
// we don't convert colorspaces here
VFCAP_OSD |
// we have OSD
VOCAP_NOSLICES;
// we don't use slices
@ -494,17 +494,15 @@ static void draw_osd(struct vo *vo, struct osd_state *osd)
double sar = (double)asp.orgw / asp.orgh;
double dar = (double)asp.prew / asp.preh;
struct sub_render_params subparams = {
.pts = osd->vo_sub_pts,
.dim = {
.w = asp.orgw,
.h = asp.orgh,
.display_par = sar / dar,
.video_par = dar / sar,
},
struct mp_osd_res dim = {
.w = asp.orgw,
.h = asp.orgh,
.display_par = sar / dar,
.video_par = dar / sar,
};
osd_draw_on_image(osd, &subparams, 0, vc->lastimg, &vc->colorspace);
osd_draw_on_image(osd, dim, osd->vo_pts, 0, vc->lastimg,
&vc->colorspace);
}
}

View File

@ -1420,12 +1420,11 @@ static mp_image_t *get_window_screenshot(struct gl_priv *p)
return image;
}
static void draw_eosd(struct gl_priv *p, struct sub_bitmaps *imgs)
static void draw_osd_cb(void *ctx, struct sub_bitmaps *imgs)
{
struct gl_priv *p = ctx;
GL *gl = p->gl;
assert(p->osd);
struct mpgl_osd_part *osd = mpgl_osd_generate(p->osd, imgs);
if (!osd)
return;
@ -1459,14 +1458,33 @@ static void draw_eosd(struct gl_priv *p, struct sub_bitmaps *imgs)
debug_check_gl(p, "before drawing osd");
gl->UseProgram(p->osd_programs[osd->format]);
mpgl_osd_gl_set_state(p->osd, osd);
mpgl_osd_set_gl_state(p->osd, osd);
draw_triangles(p, osd->vertices, osd->num_vertices);
mpgl_osd_gl_unset_state(p->osd, osd);
mpgl_osd_unset_gl_state(p->osd, osd);
gl->UseProgram(0);
debug_check_gl(p, "after drawing osd");
}
static void draw_osd(struct vo *vo, struct osd_state *osd)
{
struct gl_priv *p = vo->priv;
assert(p->osd);
struct mp_osd_res res = {
.w = vo->dwidth,
.h = vo->dheight,
.ml = p->border_x,
.mr = p->border_x,
.mt = p->border_y,
.mb = p->border_y,
.display_par = vo->monitor_par,
.video_par = vo->aspdat.par,
};
osd_draw(osd, res, osd->vo_pts, 0, p->osd->formats, draw_osd_cb, p);
}
// Disable features that are not supported with the current OpenGL version.
static void check_gl_features(struct gl_priv *p)
{
@ -1691,7 +1709,7 @@ static int query_format(uint32_t format)
{
int caps = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_FLIP |
VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_ACCEPT_STRIDE |
VFCAP_OSD | VFCAP_EOSD | VFCAP_EOSD_RGBA;
VFCAP_OSD;
if (!init_format(format, NULL))
return 0;
return caps;
@ -1767,24 +1785,6 @@ static int control(struct vo *vo, uint32_t request, void *data)
return query_format(*(uint32_t *)data);
case VOCTRL_DRAW_IMAGE:
return draw_image(p, data);
case VOCTRL_DRAW_EOSD:
if (!data)
return VO_FALSE;
draw_eosd(p, data);
return VO_TRUE;
case VOCTRL_GET_EOSD_RES: {
struct mp_eosd_res *r = data;
r->w = vo->dwidth;
r->h = vo->dheight;
r->ml = r->mr = p->border_x;
r->mt = r->mb = p->border_y;
return VO_TRUE;
}
case VOCTRL_QUERY_EOSD_FORMAT: {
int f = *(int *)data;
return (mpgl_osd_query_format(p->osd, f) && osd_shaders[f])
? VO_TRUE : VO_NOTIMPL;
}
case VOCTRL_ONTOP:
if (!p->glctx->ontop)
break;
@ -2304,7 +2304,7 @@ const struct vo_driver video_out_opengl = {
.config = config,
.control = control,
.draw_slice = draw_slice,
.draw_osd = draw_osd_with_eosd,
.draw_osd = draw_osd,
.flip_page = flip_page,
.check_events = check_events,
.uninit = uninit,
@ -2322,7 +2322,7 @@ const struct vo_driver video_out_opengl_hq = {
.config = config,
.control = control,
.draw_slice = draw_slice,
.draw_osd = draw_osd_with_eosd,
.draw_osd = draw_osd,
.flip_page = flip_page,
.check_events = check_events,
.uninit = uninit,

View File

@ -26,6 +26,7 @@
#include <string.h>
#include <math.h>
#include <stdbool.h>
#include <assert.h>
#include "config.h"
#include "talloc.h"
@ -229,11 +230,14 @@ static void update_yuvconv(struct vo *vo)
}
}
// Note: relies on state being setup, like projection matrix and blending
static void render_osd(struct vo *vo, struct sub_bitmaps *imgs)
static void draw_osd(struct vo *vo, struct osd_state *osd)
{
struct gl_priv *p = vo->priv;
GL *gl = p->gl;
assert(p->osd);
if (!p->use_osd)
return;
if (!p->scaled_osd) {
gl->MatrixMode(GL_PROJECTION);
@ -241,9 +245,26 @@ static void render_osd(struct vo *vo, struct sub_bitmaps *imgs)
gl->LoadIdentity();
gl->Ortho(0, vo->dwidth, vo->dheight, 0, -1, 1);
}
gl->Color4ub((p->osd_color >> 16) & 0xff, (p->osd_color >> 8) & 0xff,
p->osd_color & 0xff, 0xff - (p->osd_color >> 24));
mpgl_osd_draw_legacy(p->osd, imgs);
struct mp_osd_res res = {
.w = vo->dwidth,
.h = vo->dheight,
.display_par = vo->monitor_par,
.video_par = vo->aspdat.par,
};
if (p->scaled_osd) {
res.w = p->image_width;
res.h = p->image_height;
} else if (aspect_scaling()) {
res.ml = res.mr = p->ass_border_x;
res.mt = res.mb = p->ass_border_y;
}
mpgl_osd_draw_legacy(p->osd, osd, res);
if (!p->scaled_osd)
gl->PopMatrix();
}
@ -843,7 +864,7 @@ static int query_format(struct vo *vo, uint32_t format)
int caps = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_FLIP |
VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_ACCEPT_STRIDE;
if (p->use_osd)
caps |= VFCAP_OSD | VFCAP_EOSD;
caps |= VFCAP_OSD;
if (format == IMGFMT_RGB24 || format == IMGFMT_RGBA)
return caps;
if (p->use_yuv && mp_get_chroma_shift(format, NULL, NULL, &depth) &&
@ -1077,25 +1098,6 @@ static int control(struct vo *vo, uint32_t request, void *data)
return query_format(vo, *(uint32_t *)data);
case VOCTRL_DRAW_IMAGE:
return draw_image(vo, data);
case VOCTRL_DRAW_EOSD:
render_osd(vo, data);
return VO_TRUE;
case VOCTRL_QUERY_EOSD_FORMAT:
return mpgl_osd_query_format(p->osd, *(int *)data) ? VO_TRUE : VO_NOTIMPL;
case VOCTRL_GET_EOSD_RES: {
struct mp_eosd_res *r = data;
r->w = vo->dwidth;
r->h = vo->dheight;
r->mt = r->mb = r->ml = r->mr = 0;
if (p->scaled_osd) {
r->w = p->image_width;
r->h = p->image_height;
} else if (aspect_scaling()) {
r->ml = r->mr = p->ass_border_x;
r->mt = r->mb = p->ass_border_y;
}
return VO_TRUE;
}
case VOCTRL_ONTOP:
if (!p->glctx->ontop)
break;
@ -1177,7 +1179,7 @@ const struct vo_driver video_out_opengl_old = {
.config = config,
.control = control,
.draw_slice = draw_slice,
.draw_osd = draw_osd_with_eosd,
.draw_osd = draw_osd,
.flip_page = flip_page,
.check_events = check_events,
.uninit = uninit,

View File

@ -157,15 +157,15 @@ struct vdpctx {
VdpChromaType vdp_chroma_type;
VdpYCbCrFormat vdp_pixel_format;
// EOSD
struct eosd_bitmap_surface {
// OSD
struct osd_bitmap_surface {
VdpRGBAFormat format;
VdpBitmapSurface surface;
uint32_t max_width;
uint32_t max_height;
struct bitmap_packer *packer;
// List of surfaces to be rendered
struct eosd_target {
struct osd_target {
VdpRect source;
VdpRect dest;
VdpColor color;
@ -174,7 +174,7 @@ struct vdpctx {
int render_count;
int bitmap_id;
int bitmap_pos_id;
} eosd_surfaces[MAX_OSD_PARTS];
} osd_surfaces[MAX_OSD_PARTS];
// Video equalizer
struct mp_csp_equalizer video_eq;
@ -183,6 +183,8 @@ struct vdpctx {
bool mode_switched;
};
static bool status_ok(struct vo *vo);
static int change_vdptime_sync(struct vdpctx *vc, unsigned int *t)
{
struct vdp_functions *vdp = vc->vdp;
@ -800,10 +802,10 @@ static void mark_vdpau_objects_uninitialized(struct vo *vo)
vc->output_surfaces[i] = VDP_INVALID_HANDLE;
vc->vdp_device = VDP_INVALID_HANDLE;
for (int i = 0; i < MAX_OSD_PARTS; i++) {
struct eosd_bitmap_surface *sfc = &vc->eosd_surfaces[i];
struct osd_bitmap_surface *sfc = &vc->osd_surfaces[i];
talloc_free(sfc->packer);
sfc->bitmap_id = sfc->bitmap_pos_id = 0;
*sfc = (struct eosd_bitmap_surface){
*sfc = (struct osd_bitmap_surface){
.surface = VDP_INVALID_HANDLE,
};
}
@ -941,18 +943,18 @@ static struct bitmap_packer *make_packer(struct vo *vo, VdpRGBAFormat format)
VdpStatus vdp_st = vdp->
bitmap_surface_query_capabilities(vc->vdp_device, format,
&(VdpBool){0}, &w_max, &h_max);
CHECK_ST_WARNING("Query to get max EOSD surface size failed");
CHECK_ST_WARNING("Query to get max OSD surface size failed");
packer->w_max = w_max;
packer->h_max = h_max;
return packer;
}
static void draw_eosd(struct vo *vo, int index)
static void draw_osd_part(struct vo *vo, int index)
{
struct vdpctx *vc = vo->priv;
struct vdp_functions *vdp = vc->vdp;
VdpStatus vdp_st;
struct eosd_bitmap_surface *sfc = &vc->eosd_surfaces[index];
struct osd_bitmap_surface *sfc = &vc->osd_surfaces[index];
VdpOutputSurface output_surface = vc->output_surfaces[vc->surface_num];
int i;
@ -986,16 +988,16 @@ static void draw_eosd(struct vo *vo, int index)
&sfc->targets[i].color,
blend,
VDP_OUTPUT_SURFACE_RENDER_ROTATE_0);
CHECK_ST_WARNING("EOSD: Error when rendering");
CHECK_ST_WARNING("OSD: Error when rendering");
}
}
static void generate_eosd(struct vo *vo, struct sub_bitmaps *imgs)
static void generate_osd_part(struct vo *vo, struct sub_bitmaps *imgs)
{
struct vdpctx *vc = vo->priv;
struct vdp_functions *vdp = vc->vdp;
VdpStatus vdp_st;
struct eosd_bitmap_surface *sfc = &vc->eosd_surfaces[imgs->render_index];
struct osd_bitmap_surface *sfc = &vc->osd_surfaces[imgs->render_index];
bool need_upload = false;
if (imgs->bitmap_pos_id == sfc->bitmap_pos_id)
@ -1007,7 +1009,7 @@ static void generate_eosd(struct vo *vo, struct sub_bitmaps *imgs)
return;
if (imgs->bitmap_id == sfc->bitmap_id)
goto eosd_skip_upload;
goto osd_skip_upload;
need_upload = true;
VdpRGBAFormat format;
@ -1034,7 +1036,7 @@ static void generate_eosd(struct vo *vo, struct sub_bitmaps *imgs)
sfc->packer->padding = imgs->scaled; // assume 2x2 filter on scaling
int r = packer_pack_from_subbitmaps(sfc->packer, imgs);
if (r < 0) {
mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] EOSD bitmaps do not fit on "
mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] OSD bitmaps do not fit on "
"a surface with the maximum supported size\n");
return;
} else if (r == 1) {
@ -1043,13 +1045,13 @@ static void generate_eosd(struct vo *vo, struct sub_bitmaps *imgs)
CHECK_ST_WARNING("Error when calling vdp_bitmap_surface_destroy");
}
mp_msg(MSGT_VO, MSGL_V, "[vdpau] Allocating a %dx%d surface for "
"EOSD bitmaps.\n", sfc->packer->w, sfc->packer->h);
"OSD bitmaps.\n", sfc->packer->w, sfc->packer->h);
vdp_st = vdp->bitmap_surface_create(vc->vdp_device, format,
sfc->packer->w, sfc->packer->h,
true, &sfc->surface);
if (vdp_st != VDP_STATUS_OK)
sfc->surface = VDP_INVALID_HANDLE;
CHECK_ST_WARNING("EOSD: error when creating surface");
CHECK_ST_WARNING("OSD: error when creating surface");
}
if (imgs->scaled) {
char zeros[sfc->packer->used_width * format_size];
@ -1060,7 +1062,7 @@ static void generate_eosd(struct vo *vo, struct sub_bitmaps *imgs)
sfc->packer->used_height});
}
eosd_skip_upload:
osd_skip_upload:
if (sfc->surface == VDP_INVALID_HANDLE)
return;
if (sfc->packer->count > sfc->targets_size) {
@ -1072,7 +1074,7 @@ eosd_skip_upload:
for (int i = 0 ;i < sfc->packer->count; i++) {
struct sub_bitmap *b = &imgs->parts[i];
struct eosd_target *target = sfc->targets + sfc->render_count;
struct osd_target *target = sfc->targets + sfc->render_count;
int x = sfc->packer->result[i].x;
int y = sfc->packer->result[i].y;
target->source = (VdpRect){x, y, x + b->w, y + b->h};
@ -1091,7 +1093,7 @@ eosd_skip_upload:
&(const void *){b->bitmap},
&(uint32_t){b->stride},
&target->source);
CHECK_ST_WARNING("EOSD: putbits failed");
CHECK_ST_WARNING("OSD: putbits failed");
}
sfc->render_count++;
}
@ -1100,6 +1102,39 @@ eosd_skip_upload:
sfc->bitmap_pos_id = imgs->bitmap_pos_id;
}
static void draw_osd_cb(void *ctx, struct sub_bitmaps *imgs)
{
struct vo *vo = ctx;
generate_osd_part(vo, imgs);
draw_osd_part(vo, imgs->render_index);
}
static void draw_osd(struct vo *vo, struct osd_state *osd)
{
struct vdpctx *vc = vo->priv;
if (!status_ok(vo))
return;
static const bool formats[SUBBITMAP_COUNT] = {
[SUBBITMAP_LIBASS] = true,
[SUBBITMAP_RGBA] = true,
};
struct mp_osd_res res = {
.w = vo->dwidth,
.h = vo->dheight,
.ml = vc->border_x,
.mr = vc->border_x,
.mt = vc->border_y,
.mb = vc->border_y,
.display_par = vo->monitor_par,
.video_par = vo->aspdat.par,
};
osd_draw(osd, res, osd->vo_pts, 0, formats, draw_osd_cb, vo);
}
static int update_presentation_queue_status(struct vo *vo)
{
struct vdpctx *vc = vo->priv;
@ -1401,8 +1436,8 @@ static uint32_t get_image(struct vo *vo, mp_image_t *mpi)
static int query_format(uint32_t format)
{
int default_flags = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW
| VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_OSD | VFCAP_EOSD
| VFCAP_EOSD_RGBA | VFCAP_FLIP;
| VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_OSD
| VFCAP_FLIP;
switch (format) {
case IMGFMT_YV12:
case IMGFMT_I420:
@ -1451,7 +1486,7 @@ static void destroy_vdpau_objects(struct vo *vo)
}
for (int i = 0; i < MAX_OSD_PARTS; i++) {
struct eosd_bitmap_surface *sfc = &vc->eosd_surfaces[i];
struct osd_bitmap_surface *sfc = &vc->osd_surfaces[i];
if (sfc->surface != VDP_INVALID_HANDLE) {
vdp_st = vdp->bitmap_surface_destroy(sfc->surface);
CHECK_ST_WARNING("Error when calling vdp_bitmap_surface_destroy");
@ -1619,28 +1654,6 @@ static int control(struct vo *vo, uint32_t request, void *data)
case VOCTRL_UPDATE_SCREENINFO:
update_xinerama_info(vo);
return VO_TRUE;
case VOCTRL_DRAW_EOSD:
if (!data)
return VO_FALSE;
if (status_ok(vo)) {
struct sub_bitmaps *imgs = data;
generate_eosd(vo, imgs);
draw_eosd(vo, imgs->render_index);
}
return VO_TRUE;
case VOCTRL_GET_EOSD_RES: {
struct mp_eosd_res *r = data;
r->w = vo->dwidth;
r->h = vo->dheight;
r->ml = r->mr = vc->border_x;
r->mt = r->mb = vc->border_y;
return VO_TRUE;
}
case VOCTRL_QUERY_EOSD_FORMAT: {
int format = *(int *)data;
return (format == SUBBITMAP_LIBASS || format == SUBBITMAP_RGBA)
? VO_TRUE : VO_NOTIMPL;
}
case VOCTRL_NEWFRAME:
vc->deint_queue_pos = next_deint_queue_pos(vo, true);
if (status_ok(vo))
@ -1688,7 +1701,7 @@ const struct vo_driver video_out_vdpau = {
.draw_image = draw_image,
.get_buffered_frame = set_next_frame_info,
.draw_slice = draw_slice,
.draw_osd = draw_osd_with_eosd,
.draw_osd = draw_osd,
.flip_page_timed = flip_page_timed,
.check_events = check_events,
.uninit = uninit,

View File

@ -42,7 +42,6 @@
#endif
#include "sub/sub.h"
#include "sub/dec_sub.h"
#include "libmpcodecs/sws_utils.h"
#define MODE_RGB 0x1
@ -443,17 +442,14 @@ static void draw_osd(struct vo *vo, struct osd_state *osd)
struct mp_csp_details csp = MP_CSP_DETAILS_DEFAULTS;
struct sub_render_params subparams = {
.pts = osd->vo_sub_pts,
.dim = {
.w = img.w,
.h = img.h,
.display_par = vo->monitor_par,
.video_par = vo->aspdat.par,
},
struct mp_osd_res res = {
.w = img.w,
.h = img.h,
.display_par = vo->monitor_par,
.video_par = vo->aspdat.par,
};
osd_draw_on_image(osd, &subparams, 0, &img, &csp);
osd_draw_on_image(osd, res, osd->vo_pts, 0, &img, &csp);
}
static void flip_page(struct vo *vo)

View File

@ -50,7 +50,6 @@
#include "x11_common.h"
#include "fastmemcpy.h"
#include "sub/sub.h"
#include "sub/dec_sub.h"
#include "aspect.h"
#include "csputils.h"
#include "subopt-helper.h"
@ -348,17 +347,14 @@ static void draw_osd(struct vo *vo, struct osd_state *osd)
struct vo_rect *dst = &ctx->dst_rect;
double xvpar = (double)dst->width / dst->height * src->height / src->width;
struct sub_render_params subparams = {
.pts = osd->vo_sub_pts,
.dim = {
.w = ctx->image_width,
.h = ctx->image_height,
.display_par = vo->monitor_par / xvpar,
.video_par = vo->aspdat.par,
},
struct mp_osd_res res = {
.w = ctx->image_width,
.h = ctx->image_height,
.display_par = vo->monitor_par / xvpar,
.video_par = vo->aspdat.par,
};
if (osd_draw_on_image(osd, &subparams, 0, &img, &csp))
if (osd_draw_on_image(osd, res, osd->vo_pts, 0, &img, &csp))
ctx->unchanged_image = false;
}
@ -466,7 +462,7 @@ static uint32_t draw_image(struct vo *vo, mp_image_t *mpi)
static int query_format(struct xvctx *ctx, uint32_t format)
{
uint32_t i;
int flag = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_OSD | VFCAP_EOSD | VFCAP_ACCEPT_STRIDE; // FIXME! check for DOWN
int flag = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_OSD | VFCAP_OSD | VFCAP_ACCEPT_STRIDE; // FIXME! check for DOWN
/* check image formats */
for (i = 0; i < ctx->formats; i++) {

View File

@ -2292,7 +2292,7 @@ int reinit_video_chain(struct MPContext *mpctx)
&retcode);
if (vf_ass)
sh_video->vfilter = vf_ass;
else if (retcode == -1) // vf_ass open() returns -1 VO has EOSD
else if (retcode == -1) // vf_ass open() returns -1 VO has OSD
mp_msg(MSGT_CPLAYER, MSGL_V, "[ass] vf_ass not needed\n");
else
mp_msg(MSGT_CPLAYER, MSGL_ERR,
@ -2546,17 +2546,15 @@ void unpause_player(struct MPContext *mpctx)
static int redraw_osd(struct MPContext *mpctx)
{
struct sh_video *sh_video = mpctx->sh_video;
struct vf_instance *vf = sh_video->vfilter;
if (vo_redraw_frame(mpctx->video_out) < 0)
struct vo *vo = mpctx->video_out;
if (vo_redraw_frame(vo) < 0)
return -1;
mpctx->osd->vo_sub_pts = mpctx->video_pts;
// NOTE: probably should use VO ctrl directly, and/or check if a filter does
// OSD rendering (a filter can't redraw anything here)
vf->control(vf, VFCTRL_DRAW_OSD, mpctx->osd);
vo_osd_reset_changed();
vo_flip_page(mpctx->video_out, 0, -1);
mpctx->osd->vo_pts = mpctx->video_pts;
vo_draw_osd(vo, mpctx->osd);
osd_reset_changed(mpctx->osd);
vo_flip_page(vo, 0, -1);
return 0;
}
@ -3160,10 +3158,10 @@ static void run_playloop(struct MPContext *mpctx)
mpctx->video_pts = sh_video->pts;
update_subtitles(mpctx, sh_video->pts);
update_osd_msg(mpctx);
struct vf_instance *vf = sh_video->vfilter;
mpctx->osd->vo_sub_pts = mpctx->video_pts;
vf->control(vf, VFCTRL_DRAW_OSD, mpctx->osd);
vo_osd_reset_changed();
mpctx->osd->vo_pts = mpctx->video_pts;
vo_draw_osd(vo, mpctx->osd);
osd_reset_changed(mpctx->osd);
mpctx->time_frame -= get_relative_time(mpctx);
mpctx->time_frame -= vo->flip_queue_offset;
@ -3305,8 +3303,7 @@ static void run_playloop(struct MPContext *mpctx)
if (sleeptime > 0) {
if (!mpctx->sh_video)
goto novideo;
if (vo_osd_has_changed(mpctx->osd) || mpctx->video_out->want_redraw)
{
if (osd_has_changed(mpctx->osd) || mpctx->video_out->want_redraw) {
if (redraw_osd(mpctx) < 0) {
if (mpctx->paused && video_left)
add_step_frame(mpctx);

View File

@ -228,7 +228,7 @@ ASS_Track *mp_ass_read_stream(ASS_Library *library, const char *fname,
}
void mp_ass_configure(ASS_Renderer *priv, struct MPOpts *opts,
struct mp_eosd_res *dim)
struct mp_osd_res *dim)
{
ass_set_frame_size(priv, dim->w, dim->h);
ass_set_margins(priv, dim->mt, dim->mb, dim->ml, dim->mr);
@ -282,7 +282,7 @@ void mp_ass_render_frame(ASS_Renderer *renderer, ASS_Track *track, double time,
struct sub_bitmap **parts, struct sub_bitmaps *res)
{
int changed;
res->imgs = ass_render_frame(renderer, track, time, &changed);
ASS_Image *imgs = ass_render_frame(renderer, track, time, &changed);
if (changed == 2)
res->bitmap_id = ++res->bitmap_pos_id;
else if (changed)
@ -292,7 +292,7 @@ void mp_ass_render_frame(ASS_Renderer *renderer, ASS_Track *track, double time,
res->parts = *parts;
res->num_parts = 0;
int num_parts_alloc = MP_TALLOC_ELEMS(res->parts);
for (struct ass_image *img = res->imgs; img; img = img->next) {
for (struct ass_image *img = imgs; img; img = img->next) {
if (img->w == 0 || img->h == 0)
continue;
if (res->num_parts >= num_parts_alloc) {

View File

@ -32,7 +32,7 @@
#include <ass/ass_types.h>
struct MPOpts;
struct mp_eosd_res;
struct mp_osd_res;
ASS_Track *mp_ass_default_track(ASS_Library *library, struct MPOpts *opts);
ASS_Track *mp_ass_read_subdata(ASS_Library *library, struct MPOpts *opts,
@ -42,7 +42,7 @@ ASS_Track *mp_ass_read_stream(ASS_Library *library, const char *fname,
struct MPOpts;
void mp_ass_configure(ASS_Renderer *priv, struct MPOpts *opts,
struct mp_eosd_res *dim);
struct mp_osd_res *dim);
void mp_ass_configure_fonts(ASS_Renderer *priv);
ASS_Library *mp_ass_init(struct MPOpts *opts);
@ -53,7 +53,7 @@ void mp_ass_render_frame(ASS_Renderer *renderer, ASS_Track *track, double time,
#else /* CONFIG_ASS */
/* Needed for EOSD code using this type to compile */
/* Needed for OSD code using this type to compile */
typedef struct ass_image {
int w, h;

View File

@ -58,7 +58,7 @@ void sub_decode(struct sh_sub *sh, struct osd_state *osd, void *data,
sh->sd_driver->decode(sh, osd, data, data_len, pts, duration);
}
void sub_get_bitmaps(struct osd_state *osd, struct sub_render_params *params,
void sub_get_bitmaps(struct osd_state *osd, struct mp_osd_res dim, double pts,
struct sub_bitmaps *res)
{
struct MPOpts *opts = osd->opts;
@ -74,7 +74,7 @@ void sub_get_bitmaps(struct osd_state *osd, struct sub_render_params *params,
osd->switch_sub_id++;
} else {
if (osd->sh_sub->sd_driver->get_bitmaps)
osd->sh_sub->sd_driver->get_bitmaps(osd->sh_sub, osd, params, res);
osd->sh_sub->sd_driver->get_bitmaps(osd->sh_sub, osd, dim, pts, res);
}
res->bitmap_id += osd->switch_sub_id;

View File

@ -4,16 +4,11 @@
#include <stdbool.h>
#include <stdint.h>
#include "sub.h"
#include "sub/sub.h"
struct sh_sub;
struct ass_track;
struct MPOpts *opts;
struct sub_render_params {
double pts;
struct mp_eosd_res dim;
};
struct MPOpts;
static inline bool is_text_sub(int type)
{
@ -22,7 +17,7 @@ static inline bool is_text_sub(int type)
void sub_decode(struct sh_sub *sh, struct osd_state *osd, void *data,
int data_len, double pts, double duration);
void sub_get_bitmaps(struct osd_state *osd, struct sub_render_params *params,
void sub_get_bitmaps(struct osd_state *osd, struct mp_osd_res dim, double pts,
struct sub_bitmaps *res);
void sub_init(struct sh_sub *sh, struct osd_state *osd);
void sub_reset(struct sh_sub *sh, struct osd_state *osd);

View File

@ -191,7 +191,7 @@ static void update_progbar(struct osd_state *osd, struct osd_object *obj)
// Assume the OSD bar takes 2/3 of the OSD width at PlayResY=288 and
// FontSize=22 with an OSD aspect ratio of 16:9. Rescale as needed.
// xxx can fail when unknown fonts are involved
double asp = (double)osd->res.w / osd->res.h;
double asp = (double)obj->vo_res.w / obj->vo_res.h;
double scale = (asp / 1.77777) * (obj->osd_track->PlayResY / 288.0);
style->ScaleX = style->ScaleY = scale;
style->FontSize = 22.0;
@ -282,8 +282,8 @@ void osd_object_get_bitmaps(struct osd_state *osd, struct osd_object *obj,
if (!obj->osd_track)
return;
ass_set_frame_size(osd->osd_render, osd->res.w, osd->res.h);
ass_set_aspect_ratio(osd->osd_render, osd->res.display_par, 1.0);
ass_set_frame_size(osd->osd_render, obj->vo_res.w, obj->vo_res.h);
ass_set_aspect_ratio(osd->osd_render, obj->vo_res.display_par, 1.0);
mp_ass_render_frame(osd->osd_render, obj->osd_track, 0,
&obj->parts_cache, out_imgs);
talloc_steal(obj, obj->parts_cache);

View File

@ -1,17 +1,14 @@
#ifndef MPLAYER_SD_H
#define MPLAYER_SD_H
struct osd_state;
struct sub_render_params;
struct sh_sub;
struct sub_bitmaps;
#include "dec_sub.h"
struct sd_functions {
int (*init)(struct sh_sub *sh, struct osd_state *osd);
void (*decode)(struct sh_sub *sh, struct osd_state *osd,
void *data, int data_len, double pts, double duration);
void (*get_bitmaps)(struct sh_sub *sh, struct osd_state *osd,
struct sub_render_params *params,
struct mp_osd_res dim, double pts,
struct sub_bitmaps *res);
void (*reset)(struct sh_sub *sh, struct osd_state *osd);
void (*switch_off)(struct sh_sub *sh, struct osd_state *osd);

View File

@ -128,24 +128,24 @@ static void decode(struct sh_sub *sh, struct osd_state *osd, void *data,
}
static void get_bitmaps(struct sh_sub *sh, struct osd_state *osd,
struct sub_render_params *params,
struct mp_osd_res dim, double pts,
struct sub_bitmaps *res)
{
struct sd_ass_priv *ctx = sh->context;
struct MPOpts *opts = osd->opts;
if (params->pts == MP_NOPTS_VALUE)
if (pts == MP_NOPTS_VALUE)
return;
double scale = params->dim.display_par;
double scale = dim.display_par;
bool use_vs_aspect = opts->ass_style_override
? opts->ass_vsfilter_aspect_compat : 1;
if (ctx->vsfilter_aspect && use_vs_aspect)
scale = scale * params->dim.video_par;
scale = scale * dim.video_par;
ASS_Renderer *renderer = osd->ass_renderer;
mp_ass_configure(renderer, opts, &params->dim);
mp_ass_configure(renderer, opts, &dim);
ass_set_aspect_ratio(renderer, scale, 1);
mp_ass_render_frame(renderer, ctx->ass_track, params->pts * 1000 + .5,
mp_ass_render_frame(renderer, ctx->ass_track, pts * 1000 + .5,
&ctx->parts, res);
talloc_steal(ctx, ctx->parts);
}

View File

@ -176,13 +176,13 @@ static void decode(struct sh_sub *sh, struct osd_state *osd, void *data,
}
static void get_bitmaps(struct sh_sub *sh, struct osd_state *osd,
struct sub_render_params *params,
struct mp_osd_res d, double pts,
struct sub_bitmaps *res)
{
struct sd_lavc_priv *priv = sh->context;
if (priv->endpts != MP_NOPTS_VALUE && (params->pts >= priv->endpts ||
params->pts < priv->endpts - 300))
if (priv->endpts != MP_NOPTS_VALUE && (pts >= priv->endpts ||
pts < priv->endpts - 300))
clear(priv);
if (priv->bitmaps_changed && priv->count > 0)
priv->outbitmaps = talloc_memdup(priv, priv->inbitmaps,
@ -190,14 +190,13 @@ static void get_bitmaps(struct sh_sub *sh, struct osd_state *osd,
int inw = priv->avctx->width;
int inh = priv->avctx->height;
guess_resolution(sh->type, &inw, &inh);
struct mp_eosd_res *d = &params->dim;
double xscale = (double) (d->w - d->ml - d->mr) / inw;
double yscale = (double) (d->h - d->mt - d->mb) / inh;
double xscale = (double) (d.w - d.ml - d.mr) / inw;
double yscale = (double) (d.h - d.mt - d.mb) / inh;
for (int i = 0; i < priv->count; i++) {
struct sub_bitmap *bi = &priv->inbitmaps[i];
struct sub_bitmap *bo = &priv->outbitmaps[i];
bo->x = bi->x * xscale + d->ml;
bo->y = bi->y * yscale + d->mt;
bo->x = bi->x * xscale + d.ml;
bo->y = bi->y * yscale + d.mt;
bo->dw = bi->w * xscale;
bo->dh = bi->h * yscale;
}

View File

@ -634,7 +634,7 @@ void spudec_set_forced_subs_only(void * const this, const unsigned int flag)
}
}
void spudec_get_indexed(void *this, struct mp_eosd_res *dim,
void spudec_get_indexed(void *this, struct mp_osd_res *dim,
struct sub_bitmaps *res)
{
spudec_handle_t *spu = this;

View File

@ -22,11 +22,11 @@
#include <stdint.h>
struct sub_bitmaps;
struct mp_eosd_res;
struct mp_osd_res;
void spudec_heartbeat(void *this, unsigned int pts100);
void spudec_assemble(void *this, unsigned char *packet, unsigned int len, int pts100);
void spudec_get_indexed(void *this, struct mp_eosd_res *dim, struct sub_bitmaps *res);
void spudec_get_indexed(void *this, struct mp_osd_res *dim, struct sub_bitmaps *res);
void *spudec_new_scaled(unsigned int *palette, unsigned int frame_width, unsigned int frame_height, uint8_t *extradata, int extradata_len);
void *spudec_new(unsigned int *palette);
void spudec_free(void *this);

View File

@ -91,21 +91,12 @@ void *vo_vobsub=NULL;
static struct osd_state *global_osd;
static void osd_update_ext(struct osd_state *osd, struct mp_eosd_res res)
static bool osd_res_equals(struct mp_osd_res a, struct mp_osd_res b)
{
struct mp_eosd_res old = osd->res;
if (old.w != res.w || old.h != res.h || old.ml != res.ml || old.mt != res.mt
|| old.mr != res.mr || old.mb != res.mb)
{
osd->res = res;
for (int n = 0; n < MAX_OSD_PARTS; n++)
osd->objs[n]->force_redraw = true;
}
}
void osd_update(struct osd_state *osd, int w, int h)
{
osd_update_ext(osd, (struct mp_eosd_res) {.w = w, .h = h});
return a.w == b.w && a.h == b.h && a.ml == b.ml && a.mt == b.mt
&& a.mr == b.mr && a.mb == b.mb
&& a.display_par == b.display_par
&& a.video_par == b.video_par;
}
struct osd_state *osd_create(struct MPOpts *opts, struct ass_library *asslib)
@ -163,22 +154,24 @@ static bool spu_visible(struct osd_state *osd, struct osd_object *obj)
}
static void render_object(struct osd_state *osd, struct osd_object *obj,
struct sub_bitmaps *out_imgs,
struct sub_render_params *sub_params,
const bool formats[SUBBITMAP_COUNT])
struct mp_osd_res res, double video_pts,
const bool formats[SUBBITMAP_COUNT],
struct sub_bitmaps *out_imgs)
{
*out_imgs = (struct sub_bitmaps) {0};
if (!osd_res_equals(res, obj->vo_res))
obj->force_redraw = true;
obj->vo_res = res;
if (obj->type == OSDTYPE_SPU) {
if (spu_visible(osd, obj)) {
//spudec_get_bitmap(vo_spudec, osd->res.w, osd->res.h, out_imgs);
spudec_get_indexed(vo_spudec, &osd->res, out_imgs);
}
if (spu_visible(osd, obj))
spudec_get_indexed(vo_spudec, &obj->vo_res, out_imgs);
} else if (obj->type == OSDTYPE_SUB) {
struct sub_render_params p = *sub_params;
if (p.pts != MP_NOPTS_VALUE)
p.pts += sub_delay - osd->sub_offset;
sub_get_bitmaps(osd, &p, out_imgs);
double sub_pts = video_pts;
if (sub_pts != MP_NOPTS_VALUE)
sub_pts += sub_delay - osd->sub_offset;
sub_get_bitmaps(osd, obj->vo_res, sub_pts, out_imgs);
} else {
osd_object_get_bitmaps(osd, obj, out_imgs);
}
@ -212,24 +205,22 @@ static void render_object(struct osd_state *osd, struct osd_object *obj,
bool cached = false; // do we have a copy of all the image data?
if (formats[SUBBITMAP_RGBA] && out_imgs->format == SUBBITMAP_INDEXED) {
if (formats[SUBBITMAP_RGBA] && out_imgs->format == SUBBITMAP_INDEXED)
cached |= osd_conv_idx_to_rgba(obj->cache[0], out_imgs);
}
if (cached)
obj->cached = *out_imgs;
}
// draw_flags is a bit field of OSD_DRAW_* constants
void osd_draw(struct osd_state *osd, struct sub_render_params *params,
int draw_flags, const bool formats[SUBBITMAP_COUNT],
void osd_draw(struct osd_state *osd, struct mp_osd_res res,
double video_pts, int draw_flags,
const bool formats[SUBBITMAP_COUNT],
void (*cb)(void *ctx, struct sub_bitmaps *imgs), void *cb_ctx)
{
if (draw_flags & OSD_DRAW_SUB_FILTER)
draw_flags |= OSD_DRAW_SUB_ONLY;
osd_update_ext(osd, params->dim);
for (int n = 0; n < MAX_OSD_PARTS; n++) {
struct osd_object *obj = osd->objs[n];
@ -241,7 +232,7 @@ void osd_draw(struct osd_state *osd, struct sub_render_params *params,
continue;
struct sub_bitmaps imgs;
render_object(osd, obj, &imgs, params, formats);
render_object(osd, obj, res, video_pts, formats, &imgs);
if (imgs.num_parts > 0) {
if (formats[imgs.format]) {
cb(cb_ctx, &imgs);
@ -254,35 +245,6 @@ void osd_draw(struct osd_state *osd, struct sub_render_params *params,
}
}
static void vo_draw_eosd(void *ctx, struct sub_bitmaps *imgs)
{
struct vo *vo = ctx;
vo_control(vo, VOCTRL_DRAW_EOSD, imgs);
}
void draw_osd_with_eosd(struct vo *vo, struct osd_state *osd)
{
struct mp_eosd_res dim = {0};
if (vo_control(vo, VOCTRL_GET_EOSD_RES, &dim) != VO_TRUE)
return;
bool formats[SUBBITMAP_COUNT];
for (int n = 0; n < SUBBITMAP_COUNT; n++) {
int data = n;
formats[n] = vo_control(vo, VOCTRL_QUERY_EOSD_FORMAT, &data) == VO_TRUE;
}
dim.display_par = vo->monitor_par;
dim.video_par = vo->aspdat.par;
struct sub_render_params subparams = {
.pts = osd->vo_sub_pts,
.dim = dim,
};
osd_draw(osd, &subparams, 0, formats, &vo_draw_eosd, vo);
}
struct draw_on_image_closure {
struct osd_state *osd;
struct mp_image *dest;
@ -301,12 +263,12 @@ static void draw_on_image(void *ctx, struct sub_bitmaps *imgs)
}
// Returns whether anything was drawn.
bool osd_draw_on_image(struct osd_state *osd, struct sub_render_params *params,
int draw_flags, struct mp_image *dest,
bool osd_draw_on_image(struct osd_state *osd, struct mp_osd_res res,
double video_pts, int draw_flags, struct mp_image *dest,
struct mp_csp_details *dest_csp)
{
struct draw_on_image_closure closure = {osd, dest, dest_csp};
osd_draw(osd, params, draw_flags, mp_draw_sub_formats,
osd_draw(osd, res, video_pts, draw_flags, mp_draw_sub_formats,
&draw_on_image, &closure);
return closure.changed;
}
@ -320,7 +282,7 @@ void vo_osd_changed(int new_value)
}
}
bool vo_osd_has_changed(struct osd_state *osd)
bool osd_has_changed(struct osd_state *osd)
{
for (int n = 0; n < MAX_OSD_PARTS; n++) {
if (osd->objs[n]->force_redraw)
@ -329,10 +291,8 @@ bool vo_osd_has_changed(struct osd_state *osd)
return false;
}
// Needed for VOs using the old OSD API (osd_draw_text_[ext]).
void vo_osd_reset_changed(void)
void osd_reset_changed(struct osd_state *osd)
{
struct osd_state *osd = global_osd;
for (int n = 0; n < MAX_OSD_PARTS; n++)
osd->objs[n]->force_redraw = false;
}

View File

@ -72,14 +72,11 @@ struct sub_bitmaps {
struct sub_bitmap *parts;
int num_parts;
// Provided for VOs with old code
struct ass_image *imgs;
// Incremented on each change
int bitmap_id, bitmap_pos_id;
};
struct mp_eosd_res {
struct mp_osd_res {
int w, h; // screen dimensions, including black borders
int mt, mb, ml, mr; // borders (top, bottom, left, right)
double display_par;
@ -111,6 +108,7 @@ struct osd_object {
// VO cache state
int vo_bitmap_id;
int vo_bitmap_pos_id;
struct mp_osd_res vo_res;
// Internally used by osd_libass.c
struct ass_track *osd_track;
@ -124,12 +122,10 @@ struct osd_state {
struct ass_renderer *ass_renderer;
struct sh_sub *sh_sub;
double sub_offset;
double vo_sub_pts;
double vo_pts;
bool render_subs_in_filter;
struct mp_eosd_res res;
char *osd_text; // OSDTYPE_OSD
int progbar_type, progbar_value; // OSDTYPE_PROGBAR
@ -204,14 +200,11 @@ extern float sub_fps;
extern int sub_justify;
void draw_osd_with_eosd(struct vo *vo, struct osd_state *osd);
struct osd_state *osd_create(struct MPOpts *opts, struct ass_library *asslib);
void osd_set_text(struct osd_state *osd, const char *text);
void osd_update(struct osd_state *osd, int dxs, int dys);
void vo_osd_changed(int new_value);
void vo_osd_reset_changed(void);
bool vo_osd_has_changed(struct osd_state *osd);
void osd_reset_changed(struct osd_state *osd);
bool osd_has_changed(struct osd_state *osd);
void osd_free(struct osd_state *osd);
enum mp_osd_draw_flags {
@ -219,14 +212,15 @@ enum mp_osd_draw_flags {
OSD_DRAW_SUB_ONLY = (1 << 1),
};
void osd_draw(struct osd_state *osd, struct sub_render_params *params,
int draw_flags, const bool formats[SUBBITMAP_COUNT],
void osd_draw(struct osd_state *osd, struct mp_osd_res res,
double video_pts, int draw_flags,
const bool formats[SUBBITMAP_COUNT],
void (*cb)(void *ctx, struct sub_bitmaps *imgs), void *cb_ctx);
struct mp_image;
struct mp_csp_details;
bool osd_draw_on_image(struct osd_state *osd, struct sub_render_params *params,
int draw_flags, struct mp_image *dest,
bool osd_draw_on_image(struct osd_state *osd, struct mp_osd_res res,
double video_pts, int draw_flags, struct mp_image *dest,
struct mp_csp_details *dest_csp);
bool sub_bitmaps_bb(struct sub_bitmaps *imgs, int *x1, int *y1,