sub: uglify OSD code path with locking

Do two things:
1. add locking to struct osd_state
2. make struct osd_state opaque

While 1. is somewhat simple, 2. is quite horrible. Lots of code accesses
lots of osd_state (and osd_object) members. To make sure everything is
accessed synchronously, I prefer making osd_state opaque, even if it
means adding pretty dumb accessors.

All of this is meant to allow running VO in their own threads.
Eventually, VOs will request OSD on their own, which means osd_state
will be accessed from foreign threads.
This commit is contained in:
wm4 2014-01-18 01:19:20 +01:00
parent 92a9f11a0b
commit 7f4a09bb85
25 changed files with 416 additions and 244 deletions

View File

@ -87,6 +87,7 @@ struct command_ctx {
#define OVERLAY_MAX_ID 64
void *overlay_map[OVERLAY_MAX_ID];
struct sub_bitmaps external2;
};
static int edit_filters(struct MPContext *mpctx, enum stream_type mediatype,
@ -1573,20 +1574,22 @@ static int mp_property_window_scale(m_option_t *prop, int action, void *arg,
static int mp_property_osd_w(m_option_t *prop, int action, void *arg,
MPContext *mpctx)
{
return m_property_int_ro(prop, action, arg, mpctx->osd->last_vo_res.w);
struct mp_osd_res vo_res = osd_get_vo_res(mpctx->osd, OSDTYPE_OSD);
return m_property_int_ro(prop, action, arg, vo_res.w);
}
static int mp_property_osd_h(m_option_t *prop, int action, void *arg,
MPContext *mpctx)
{
return m_property_int_ro(prop, action, arg, mpctx->osd->last_vo_res.w);
struct mp_osd_res vo_res = osd_get_vo_res(mpctx->osd, OSDTYPE_OSD);
return m_property_int_ro(prop, action, arg, vo_res.w);
}
static int mp_property_osd_par(m_option_t *prop, int action, void *arg,
MPContext *mpctx)
{
return m_property_double_ro(prop, action, arg,
mpctx->osd->last_vo_res.display_par);
struct mp_osd_res vo_res = osd_get_vo_res(mpctx->osd, OSDTYPE_OSD);
return m_property_double_ro(prop, action, arg, vo_res.display_par);
}
/// Video fps (RO)
@ -2348,7 +2351,7 @@ static int edit_filters_osd(struct MPContext *mpctx, enum stream_type mediatype,
static int ext2_sub_find(struct MPContext *mpctx, int id)
{
struct command_ctx *cmd = mpctx->command_ctx;
struct sub_bitmaps *sub = &mpctx->osd->external2;
struct sub_bitmaps *sub = &cmd->external2;
void *p = NULL;
if (id >= 0 && id < OVERLAY_MAX_ID)
p = cmd->overlay_map[id];
@ -2363,10 +2366,10 @@ static int ext2_sub_find(struct MPContext *mpctx, int id)
static int ext2_sub_alloc(struct MPContext *mpctx)
{
struct osd_state *osd = mpctx->osd;
struct sub_bitmaps *sub = &osd->external2;
struct command_ctx *cmd = mpctx->command_ctx;
struct sub_bitmaps *sub = &cmd->external2;
struct sub_bitmap b = {0};
MP_TARRAY_APPEND(osd, sub->parts, sub->num_parts, b);
MP_TARRAY_APPEND(cmd, sub->parts, sub->num_parts, b);
return sub->num_parts - 1;
}
@ -2375,14 +2378,16 @@ static int overlay_add(struct MPContext *mpctx, int id, int x, int y,
int stride)
{
struct command_ctx *cmd = mpctx->command_ctx;
struct osd_state *osd = mpctx->osd;
int r = -1;
// Temporarily unmap them to avoid race condition with concurrent access.
osd_set_external2(mpctx->osd, NULL);
if (strcmp(fmt, "bgra") != 0) {
MP_ERR(mpctx, "overlay_add: unsupported OSD format '%s'\n", fmt);
return -1;
goto error;
}
if (id < 0 || id >= OVERLAY_MAX_ID) {
MP_ERR(mpctx, "overlay_add: invalid id %d\n", id);
return -1;
goto error;
}
int fd = -1;
bool close_fd = true;
@ -2400,48 +2405,52 @@ static int overlay_add(struct MPContext *mpctx, int id, int x, int y,
close(fd);
if (!p) {
MP_ERR(mpctx, "overlay_add: could not open or map '%s'\n", file);
return -1;
goto error;
}
int index = ext2_sub_find(mpctx, id);
if (index < 0)
index = ext2_sub_alloc(mpctx);
if (index < 0) {
munmap(p, h * stride);
return -1;
goto error;
}
cmd->overlay_map[id] = p;
osd->external2.parts[index] = (struct sub_bitmap) {
cmd->external2.parts[index] = (struct sub_bitmap) {
.bitmap = p,
.stride = stride,
.x = x, .y = y,
.w = w, .h = h,
.dw = w, .dh = h,
};
osd->external2.bitmap_id = osd->external2.bitmap_pos_id = 1;
osd->external2.format = SUBBITMAP_RGBA;
osd->want_redraw = true;
return 0;
cmd->external2.bitmap_id = cmd->external2.bitmap_pos_id = 1;
cmd->external2.format = SUBBITMAP_RGBA;
r = 0;
error:
osd_set_external2(mpctx->osd, &cmd->external2);
return r;
}
static void overlay_remove(struct MPContext *mpctx, int id)
{
struct command_ctx *cmd = mpctx->command_ctx;
struct osd_state *osd = mpctx->osd;
osd_set_external2(mpctx->osd, NULL);
int index = ext2_sub_find(mpctx, id);
if (index >= 0) {
struct sub_bitmaps *sub = &osd->external2;
struct sub_bitmaps *sub = &cmd->external2;
struct sub_bitmap *part = &sub->parts[index];
munmap(part->bitmap, part->h * part->stride);
MP_TARRAY_REMOVE_AT(sub->parts, sub->num_parts, index);
cmd->overlay_map[id] = NULL;
sub->bitmap_id = sub->bitmap_pos_id = 1;
}
osd_set_external2(mpctx->osd, &cmd->external2);
}
static void overlay_uninit(struct MPContext *mpctx)
{
for (int id = 0; id < OVERLAY_MAX_ID; id++)
overlay_remove(mpctx, id);
osd_set_external2(mpctx->osd, NULL);
}
#else
@ -2739,12 +2748,13 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd)
case MP_CMD_SUB_STEP:
case MP_CMD_SUB_SEEK: {
struct osd_object *obj = mpctx->osd->objs[OSDTYPE_SUB];
if (obj->dec_sub) {
struct osd_sub_state state;
osd_get_sub(mpctx->osd, OSDTYPE_SUB, &state);
if (state.dec_sub) {
double a[2];
a[0] = mpctx->video_pts - obj->video_offset - opts->sub_delay;
a[0] = mpctx->video_pts - state.video_offset - opts->sub_delay;
a[1] = cmd->args[0].v.i;
if (sub_control(obj->dec_sub, SD_CTRL_SUB_STEP, a) > 0) {
if (sub_control(state.dec_sub, SD_CTRL_SUB_STEP, a) > 0) {
if (cmd->id == MP_CMD_SUB_STEP) {
opts->sub_delay -= a[0];
osd_changed_all(mpctx->osd);

View File

@ -23,6 +23,7 @@
#include "common/common.h"
#include "options/options.h"
#include "sub/osd.h"
// definitions used internally by the core player code
@ -158,6 +159,7 @@ typedef struct MPContext {
int osd_function;
double osd_function_visible;
double osd_last_update;
struct osd_progbar_state osd_progbar;
struct playlist *playlist;
char *filename; // currently playing file

View File

@ -39,8 +39,11 @@ struct mp_nav_state {
bool nav_eof;
bool nav_menu;
bool nav_draining;
// Accessed by OSD (possibly separate thread)
int hi_visible;
int highlight[4]; // x0 y0 x1 y1
int vidsize[2];
int subsize[2];
struct sub_bitmap *hi_elem;
};
@ -78,6 +81,7 @@ void mp_nav_reset(struct MPContext *mpctx)
return;
struct mp_nav_cmd inp = {MP_NAV_CMD_RESUME};
stream_control(mpctx->stream, STREAM_CTRL_NAV_CMD, &inp);
osd_set_nav_highlight(mpctx->osd, NULL);
nav->hi_visible = 0;
nav->nav_menu = false;
nav->nav_draining = false;
@ -90,6 +94,7 @@ void mp_nav_reset(struct MPContext *mpctx)
void mp_nav_destroy(struct MPContext *mpctx)
{
osd_set_nav_highlight(mpctx->osd, NULL);
if (!mpctx->nav_state)
return;
mp_input_disable_section(mpctx->input, "dvdnav");
@ -164,19 +169,32 @@ void mp_handle_nav(struct MPContext *mpctx)
mp_input_disable_section(mpctx->input, "dvdnav-menu");
}
break;
case MP_NAV_EVENT_HIGHLIGHT:
case MP_NAV_EVENT_HIGHLIGHT: {
MP_VERBOSE(nav, "highlight: %d %d %d - %d %d\n",
ev->u.highlight.display,
ev->u.highlight.sx, ev->u.highlight.sy,
ev->u.highlight.ex, ev->u.highlight.ey);
osd_set_nav_highlight(mpctx->osd, NULL);
nav->highlight[0] = ev->u.highlight.sx;
nav->highlight[1] = ev->u.highlight.sy;
nav->highlight[2] = ev->u.highlight.ex;
nav->highlight[3] = ev->u.highlight.ey;
nav->hi_visible = ev->u.highlight.display;
mpctx->osd->highlight_priv = mpctx;
osd_changed(mpctx->osd, OSDTYPE_NAV_HIGHLIGHT);
int sizes[2] = {0};
if (mpctx->d_sub[0])
sub_control(mpctx->d_sub[0], SD_CTRL_GET_RESOLUTION, sizes);
if (sizes[0] < 1 || sizes[1] < 1) {
struct mp_image_params vid = {0};
if (mpctx->d_video)
vid = mpctx->d_video->decoder_output;
sizes[0] = vid.w;
sizes[1] = vid.h;
}
for (int n = 0; n < 2; n++)
nav->vidsize[n] = sizes[n];
osd_set_nav_highlight(mpctx->osd, mpctx);
break;
}
default: ; // ignore
}
talloc_free(ev);
@ -209,10 +227,10 @@ void mp_handle_nav(struct MPContext *mpctx)
// Note: a proper solution would introduce something like
// SD_CTRL_APPLY_DVDNAV, which would crop the vobsub frame,
// and apply the current CLUT.
void mp_nav_get_highlight(struct osd_state *osd, struct mp_osd_res res,
void mp_nav_get_highlight(void *priv, struct mp_osd_res res,
struct sub_bitmaps *out_imgs)
{
struct MPContext *mpctx = osd->highlight_priv;
struct MPContext *mpctx = priv;
struct mp_nav_state *nav = mpctx ? mpctx->nav_state : NULL;
if (!nav)
return;
@ -221,16 +239,7 @@ void mp_nav_get_highlight(struct osd_state *osd, struct mp_osd_res res,
sub = talloc_zero(nav, struct sub_bitmap);
nav->hi_elem = sub;
int sizes[2] = {0};
if (mpctx->d_sub[0])
sub_control(mpctx->d_sub[0], SD_CTRL_GET_RESOLUTION, sizes);
if (sizes[0] < 1 || sizes[1] < 1) {
struct mp_image_params vid = {0};
if (mpctx->d_video)
vid = mpctx->d_video->decoder_output;
sizes[0] = vid.w;
sizes[1] = vid.h;
}
int sizes[2] = {nav->vidsize[0], nav->vidsize[1]};
if (sizes[0] < 1 || sizes[1] < 1)
return;
if (sizes[0] != nav->subsize[0] || sizes[1] != nav->subsize[1]) {

View File

@ -67,7 +67,8 @@ static void uninit_sub(struct MPContext *mpctx, int order)
if (mpctx->d_sub[order])
sub_reset(mpctx->d_sub[order]);
mpctx->d_sub[order] = NULL; // Note: not free'd.
mpctx->osd->objs[order ? OSDTYPE_SUB2 : OSDTYPE_SUB]->dec_sub = NULL;
int obj = order ? OSDTYPE_SUB2 : OSDTYPE_SUB;
osd_set_sub(mpctx->osd, obj, NULL);
reset_subtitles(mpctx, order);
reselect_demux_streams(mpctx);
}

View File

@ -479,17 +479,7 @@ static int script_set_osd_ass(lua_State *L)
int res_x = luaL_checkinteger(L, 1);
int res_y = luaL_checkinteger(L, 2);
const char *text = luaL_checkstring(L, 3);
if (!mpctx->osd->external ||
strcmp(mpctx->osd->external, text) != 0 ||
mpctx->osd->external_res_x != res_x ||
mpctx->osd->external_res_y != res_y)
{
talloc_free(mpctx->osd->external);
mpctx->osd->external = talloc_strdup(mpctx->osd, text);
mpctx->osd->external_res_x = res_x;
mpctx->osd->external_res_y = res_y;
osd_changed(mpctx->osd, OSDTYPE_EXTERNAL);
}
osd_set_external(mpctx->osd, res_x, res_y, (char *)text);
return 0;
}
@ -497,8 +487,7 @@ static int script_get_osd_resolution(lua_State *L)
{
struct MPContext *mpctx = get_mpctx(L);
int w, h;
osd_object_get_resolution(mpctx->osd, mpctx->osd->objs[OSDTYPE_EXTERNAL],
&w, &h);
osd_object_get_resolution(mpctx->osd, OSDTYPE_EXTERNAL, &w, &h);
lua_pushnumber(L, w);
lua_pushnumber(L, h);
return 2;
@ -507,11 +496,11 @@ static int script_get_osd_resolution(lua_State *L)
static int script_get_screen_size(lua_State *L)
{
struct MPContext *mpctx = get_mpctx(L);
struct osd_object *obj = mpctx->osd->objs[OSDTYPE_EXTERNAL];
double aspect = 1.0 * obj->vo_res.w / MPMAX(obj->vo_res.h, 1) /
obj->vo_res.display_par;
lua_pushnumber(L, obj->vo_res.w);
lua_pushnumber(L, obj->vo_res.h);
struct mp_osd_res vo_res = osd_get_vo_res(mpctx->osd, OSDTYPE_EXTERNAL);
double aspect = 1.0 * vo_res.w / MPMAX(vo_res.h, 1) /
vo_res.display_par;
lua_pushnumber(L, vo_res.w);
lua_pushnumber(L, vo_res.h);
lua_pushnumber(L, aspect);
return 3;
}
@ -522,8 +511,7 @@ static int script_get_mouse_pos(lua_State *L)
int px, py;
mp_input_get_mouse_pos(mpctx->input, &px, &py);
double sw, sh;
osd_object_get_scale_factor(mpctx->osd, mpctx->osd->objs[OSDTYPE_EXTERNAL],
&sw, &sh);
osd_object_get_scale_factor(mpctx->osd, OSDTYPE_EXTERNAL, &sw, &sh);
lua_pushnumber(L, px * sw);
lua_pushnumber(L, py * sh);
return 2;
@ -652,8 +640,7 @@ static int script_input_set_section_mouse_area(lua_State *L)
struct MPContext *mpctx = get_mpctx(L);
double sw, sh;
struct osd_object *obj = mpctx->osd->objs[OSDTYPE_EXTERNAL];
osd_object_get_scale_factor(mpctx->osd, obj, &sw, &sh);
osd_object_get_scale_factor(mpctx->osd, OSDTYPE_EXTERNAL, &sw, &sh);
char *section = (char *)luaL_checkstring(L, 1);
int x0 = luaL_checkinteger(L, 2) / sw;

View File

@ -292,8 +292,8 @@ static mp_osd_msg_t *get_osd_msg(struct MPContext *mpctx)
if (mpctx->osd_visible && now >= mpctx->osd_visible) {
mpctx->osd_visible = 0;
mpctx->osd->progbar_type = -1; // disable
osd_changed(mpctx->osd, OSDTYPE_PROGBAR);
mpctx->osd_progbar.type = -1; // disable
osd_set_progbar(mpctx->osd, &mpctx->osd_progbar);
}
if (mpctx->osd_function_visible && now >= mpctx->osd_function_visible) {
mpctx->osd_function_visible = 0;
@ -335,10 +335,10 @@ void set_osd_bar(struct MPContext *mpctx, int type, const char *name,
if (mpctx->video_out && opts->term_osd != 1) {
mpctx->osd_visible = mp_time_sec() + opts->osd_duration / 1000.0;
mpctx->osd->progbar_type = type;
mpctx->osd->progbar_value = (val - min) / (max - min);
mpctx->osd->progbar_num_stops = 0;
osd_changed(mpctx->osd, OSDTYPE_PROGBAR);
mpctx->osd_progbar.type = type;
mpctx->osd_progbar.value = (val - min) / (max - min);
mpctx->osd_progbar.num_stops = 0;
osd_set_progbar(mpctx->osd, &mpctx->osd_progbar);
return;
}
@ -351,20 +351,19 @@ void set_osd_bar(struct MPContext *mpctx, int type, const char *name,
static void update_osd_bar(struct MPContext *mpctx, int type,
double min, double max, double val)
{
if (mpctx->osd->progbar_type == type) {
if (mpctx->osd_progbar.type == type) {
float new_value = (val - min) / (max - min);
if (new_value != mpctx->osd->progbar_value) {
mpctx->osd->progbar_value = new_value;
osd_changed(mpctx->osd, OSDTYPE_PROGBAR);
if (new_value != mpctx->osd_progbar.value) {
mpctx->osd_progbar.value = new_value;
osd_set_progbar(mpctx->osd, &mpctx->osd_progbar);
}
}
}
static void set_osd_bar_chapters(struct MPContext *mpctx, int type)
{
struct osd_state *osd = mpctx->osd;
osd->progbar_num_stops = 0;
if (osd->progbar_type == type) {
mpctx->osd_progbar.num_stops = 0;
if (mpctx->osd_progbar.type == type) {
double len = get_time_length(mpctx);
if (len > 0) {
int num = get_chapter_count(mpctx);
@ -372,12 +371,13 @@ static void set_osd_bar_chapters(struct MPContext *mpctx, int type)
double time = chapter_start_time(mpctx, n);
if (time >= 0) {
float pos = time / len;
MP_TARRAY_APPEND(osd, osd->progbar_stops,
osd->progbar_num_stops, pos);
MP_TARRAY_APPEND(mpctx, mpctx->osd_progbar.stops,
mpctx->osd_progbar.num_stops, pos);
}
}
}
}
osd_set_progbar(mpctx->osd, &mpctx->osd_progbar);
}
// osd_function is the symbol appearing in the video status, such as OSD_PLAY
@ -394,7 +394,7 @@ void set_osd_function(struct MPContext *mpctx, int osd_function)
*/
void set_osd_subtitle(struct MPContext *mpctx, const char *text)
{
osd_set_sub(mpctx->osd, mpctx->osd->objs[OSDTYPE_SUB], text);
osd_set_text(mpctx->osd, OSDTYPE_SUB, text);
term_osd_set_subs(mpctx, text);
}
@ -495,7 +495,7 @@ void update_osd_msg(struct MPContext *mpctx)
// Look if we have a msg
mp_osd_msg_t *msg = get_osd_msg(mpctx);
if (msg && !msg->show_position) {
osd_set_text(osd, msg->msg);
osd_set_text(osd, OSDTYPE_OSD, msg->msg);
term_osd_set_text(mpctx, msg->msg);
return;
}
@ -510,7 +510,7 @@ void update_osd_msg(struct MPContext *mpctx)
if (osd_level >= 2)
sadd_osd_status(&text, mpctx, osd_level == 3);
osd_set_text(osd, text);
osd_set_text(osd, OSDTYPE_OSD, text);
talloc_free(text);
// always clear (term-osd has separate status line)

View File

@ -136,7 +136,7 @@ static void draw_osd(struct MPContext *mpctx)
{
struct vo *vo = mpctx->video_out;
mpctx->osd->vo_pts = mpctx->video_pts;
osd_set_vo_pts(mpctx->osd, mpctx->video_pts);
vo_draw_osd(vo, mpctx->osd);
}
@ -646,10 +646,9 @@ static bool handle_osd_redraw(struct MPContext *mpctx)
{
if (!mpctx->video_out || !mpctx->video_out->config_ok)
return false;
bool want_redraw = vo_get_want_redraw(mpctx->video_out);
if (mpctx->video_out->driver->draw_osd)
want_redraw |= mpctx->osd->want_redraw;
mpctx->osd->want_redraw = false;
bool want_redraw = vo_get_want_redraw(mpctx->video_out) |
(osd_query_and_reset_want_redraw(mpctx->osd) &&
mpctx->video_out->driver->draw_osd);
if (want_redraw) {
if (redraw_osd(mpctx))
return true;

View File

@ -307,7 +307,7 @@ static void add_subs(struct MPContext *mpctx, struct mp_image *image)
.display_par = sar / dar,
};
osd_draw_on_image(mpctx->osd, res, mpctx->osd->vo_pts,
osd_draw_on_image(mpctx->osd, res, osd_get_vo_pts(mpctx->osd),
OSD_DRAW_SUB_ONLY, image);
}
@ -330,7 +330,7 @@ static struct mp_image *screenshot_get(struct MPContext *mpctx, int mode)
{
struct mp_image *image = NULL;
if (mpctx->video_out && mpctx->video_out->config_ok) {
if (mode == MODE_SUBTITLES && mpctx->osd->render_subs_in_filter)
if (mode == MODE_SUBTITLES && osd_get_render_subs_in_filter(mpctx->osd))
mode = 0;
struct voctrl_screenshot_args args =
@ -386,7 +386,7 @@ void screenshot_request(struct MPContext *mpctx, int mode, bool each_frame,
{
screenshot_ctx *ctx = mpctx->screenshot_ctx;
if (mode == MODE_SUBTITLES && mpctx->osd->render_subs_in_filter)
if (mode == MODE_SUBTITLES && osd_get_render_subs_in_filter(mpctx->osd))
mode = 0;
if (each_frame) {

View File

@ -68,12 +68,11 @@ static bool is_interleaved(struct MPContext *mpctx, struct track *track)
void reset_subtitles(struct MPContext *mpctx, int order)
{
struct osd_object *osd_obj =
mpctx->osd->objs[order ? OSDTYPE_SUB2 : OSDTYPE_SUB];
int obj = order ? OSDTYPE_SUB2 : OSDTYPE_SUB;
if (mpctx->d_sub[order])
sub_reset(mpctx->d_sub[order]);
set_osd_subtitle(mpctx, NULL);
osd_set_sub(mpctx->osd, osd_obj, NULL);
osd_set_text(mpctx->osd, obj, NULL);
}
static void update_subtitle(struct MPContext *mpctx, int order)
@ -90,8 +89,7 @@ static void update_subtitle(struct MPContext *mpctx, int order)
struct track *track = mpctx->current_track[order][STREAM_SUB];
struct dec_sub *dec_sub = mpctx->d_sub[order];
assert(track && dec_sub);
struct osd_object *osd_obj
= mpctx->osd->objs[order ? OSDTYPE_SUB2 : OSDTYPE_SUB];
int obj = order ? OSDTYPE_SUB2 : OSDTYPE_SUB;
if (mpctx->d_video) {
struct mp_image_params params = mpctx->d_video->vf_input;
@ -99,9 +97,14 @@ static void update_subtitle(struct MPContext *mpctx, int order)
sub_control(dec_sub, SD_CTRL_SET_VIDEO_PARAMS, &params);
}
osd_obj->video_offset = track->under_timeline ? mpctx->video_offset : 0;
struct osd_sub_state state;
osd_get_sub(mpctx->osd, obj, &state);
double refpts_s = mpctx->playback_pts - osd_obj->video_offset;
state.video_offset = track->under_timeline ? mpctx->video_offset : 0;
osd_set_sub(mpctx->osd, obj, &state);
double refpts_s = mpctx->playback_pts - state.video_offset;
double curpts_s = refpts_s - opts->sub_delay;
if (!track->preloaded && track->stream) {
@ -136,14 +139,14 @@ static void update_subtitle(struct MPContext *mpctx, int order)
// Handle displaying subtitles on terminal; never done for secondary subs
if (order == 0) {
if (!osd_obj->render_bitmap_subs || !mpctx->video_out) {
if (!state.render_bitmap_subs || !mpctx->video_out) {
sub_lock(dec_sub);
set_osd_subtitle(mpctx, sub_get_text(dec_sub, curpts_s));
sub_unlock(dec_sub);
}
} else if (order == 1) {
sub_lock(dec_sub);
osd_set_sub(mpctx->osd, osd_obj, sub_get_text(dec_sub, curpts_s));
osd_set_text(mpctx->osd, obj, sub_get_text(dec_sub, curpts_s));
sub_unlock(dec_sub);
}
}
@ -225,8 +228,7 @@ void reinit_subs(struct MPContext *mpctx, int order)
{
struct MPOpts *opts = mpctx->opts;
struct track *track = mpctx->current_track[order][STREAM_SUB];
struct osd_object *osd_obj =
mpctx->osd->objs[order ? OSDTYPE_SUB2 : OSDTYPE_SUB];
int obj = order ? OSDTYPE_SUB2 : OSDTYPE_SUB;
int init_flag = order ? INITIALIZED_SUB2 : INITIALIZED_SUB;
assert(!(mpctx->initialized_flags & init_flag));
@ -256,16 +258,18 @@ void reinit_subs(struct MPContext *mpctx, int order)
reinit_subdec(mpctx, track, dec_sub);
osd_obj->dec_sub = dec_sub;
// Decides whether to use OSD path or normal subtitle rendering path.
osd_obj->render_bitmap_subs =
opts->ass_enabled || !sub_has_get_text(dec_sub);
struct osd_sub_state state = {
.dec_sub = dec_sub,
// Decides whether to use OSD path or normal subtitle rendering path.
.render_bitmap_subs = opts->ass_enabled || !sub_has_get_text(dec_sub),
};
// Secondary subs are rendered with the "text" renderer to transform them
// to toptitles.
if (order == 1 && sub_has_get_text(dec_sub))
osd_obj->render_bitmap_subs = false;
state.render_bitmap_subs = false;
reset_subtitles(mpctx, order);
osd_set_sub(mpctx->osd, obj, &state);
}

View File

@ -126,8 +126,8 @@ static void recreate_video_filters(struct MPContext *mpctx)
// for vf_sub
vf_control_any(d_video->vfilter, VFCTRL_SET_OSD_OBJ, mpctx->osd);
mpctx->osd->render_subs_in_filter
= vf_control_any(d_video->vfilter, VFCTRL_INIT_OSD, NULL) == CONTROL_OK;
osd_set_render_subs_in_filter(mpctx->osd,
vf_control_any(d_video->vfilter, VFCTRL_INIT_OSD, NULL) == CONTROL_OK);
set_allowed_vo_formats(d_video->vfilter, mpctx->video_out);
}

184
sub/osd.c
View File

@ -34,6 +34,7 @@
#include "common/global.h"
#include "common/msg.h"
#include "osd.h"
#include "osd_state.h"
#include "dec_sub.h"
#include "img_convert.h"
#include "draw_bmp.h"
@ -87,15 +88,15 @@ struct osd_state *osd_create(struct mpv_global *global)
.opts = global->opts,
.global = global,
.log = mp_log_new(osd, global->log, "osd"),
.osd_text = talloc_strdup(osd, ""),
.progbar_type = -1,
};
pthread_mutex_init(&osd->lock, NULL);
for (int n = 0; n < MAX_OSD_PARTS; n++) {
struct osd_object *obj = talloc(osd, struct osd_object);
*obj = (struct osd_object) {
.type = n,
.sub_text = talloc_strdup(obj, ""),
.text = talloc_strdup(obj, ""),
.progbar_state = {.type = -1},
};
for (int i = 0; i < OSD_CONV_CACHE_MAX; i++)
obj->cache[i] = talloc_steal(obj, osd_conv_cache_new());
@ -114,30 +115,102 @@ void osd_free(struct osd_state *osd)
if (!osd)
return;
osd_destroy_backend(osd);
pthread_mutex_destroy(&osd->lock);
talloc_free(osd);
}
static bool set_text(void *talloc_ctx, char **var, const char *text)
static void osd_changed_unlocked(struct osd_state *osd, int obj)
{
osd->objs[obj]->force_redraw = true;
osd->want_redraw = true;
}
void osd_set_text(struct osd_state *osd, int obj, const char *text)
{
pthread_mutex_lock(&osd->lock);
struct osd_object *osd_obj = osd->objs[obj];
if (!text)
text = "";
if (strcmp(*var, text) == 0)
return true;
talloc_free(*var);
*var = talloc_strdup(talloc_ctx, text);
return false;
if (strcmp(osd_obj->text, text) != 0) {
talloc_free(osd_obj->text);
osd_obj->text = talloc_strdup(osd_obj, text);
osd_changed_unlocked(osd, obj);
}
pthread_mutex_unlock(&osd->lock);
}
void osd_set_text(struct osd_state *osd, const char *text)
void osd_set_sub(struct osd_state *osd, int obj, struct osd_sub_state *substate)
{
if (!set_text(osd, &osd->osd_text, text))
osd_changed(osd, OSDTYPE_OSD);
pthread_mutex_lock(&osd->lock);
osd->objs[obj]->sub_state = substate ? *substate : (struct osd_sub_state){0};
pthread_mutex_unlock(&osd->lock);
}
void osd_set_sub(struct osd_state *osd, struct osd_object *obj, const char *text)
void osd_get_sub(struct osd_state *osd, int obj, struct osd_sub_state *substate)
{
if (!set_text(obj, &obj->sub_text, text))
osd_changed(osd, obj->type);
pthread_mutex_lock(&osd->lock);
*substate = osd->objs[obj]->sub_state;
pthread_mutex_unlock(&osd->lock);
}
bool osd_get_render_subs_in_filter(struct osd_state *osd)
{
pthread_mutex_lock(&osd->lock);
bool r = osd->render_subs_in_filter;
pthread_mutex_unlock(&osd->lock);
return r;
}
void osd_set_render_subs_in_filter(struct osd_state *osd, bool s)
{
pthread_mutex_lock(&osd->lock);
osd->render_subs_in_filter = s;
pthread_mutex_unlock(&osd->lock);
}
void osd_set_progbar(struct osd_state *osd, struct osd_progbar_state *s)
{
pthread_mutex_lock(&osd->lock);
struct osd_object *osd_obj = osd->objs[OSDTYPE_PROGBAR];
osd_obj->progbar_state.type = s->type;
osd_obj->progbar_state.value = s->value;
osd_obj->progbar_state.num_stops = s->num_stops;
MP_TARRAY_GROW(osd_obj, osd_obj->progbar_state.stops, s->num_stops);
memcpy(osd_obj->progbar_state.stops, s->stops,
sizeof(osd_obj->progbar_state.stops[0]) * s->num_stops);
osd_changed_unlocked(osd, osd_obj->type);
pthread_mutex_unlock(&osd->lock);
}
void osd_set_external(struct osd_state *osd, int res_x, int res_y, char *text)
{
pthread_mutex_lock(&osd->lock);
struct osd_object *osd_obj = osd->objs[OSDTYPE_EXTERNAL];
if (strcmp(osd_obj->text, text) != 0 ||
osd_obj->external_res_x != res_x ||
osd_obj->external_res_y != res_y)
{
talloc_free(osd_obj->text);
osd_obj->text = talloc_strdup(osd_obj, text);
osd_obj->external_res_x = res_x;
osd_obj->external_res_y = res_y;
osd_changed_unlocked(osd, osd_obj->type);
}
pthread_mutex_unlock(&osd->lock);
}
void osd_set_external2(struct osd_state *osd, struct sub_bitmaps *imgs)
{
pthread_mutex_lock(&osd->lock);
osd->objs[OSDTYPE_EXTERNAL2]->external2 = imgs;
pthread_mutex_unlock(&osd->lock);
}
void osd_set_nav_highlight(struct osd_state *osd, void *priv)
{
pthread_mutex_lock(&osd->lock);
osd->objs[OSDTYPE_NAV_HIGHLIGHT]->highlight_priv = priv;
pthread_mutex_unlock(&osd->lock);
}
static void render_object(struct osd_state *osd, struct osd_object *obj,
@ -159,21 +232,23 @@ static void render_object(struct osd_state *osd, struct osd_object *obj,
obj->vo_res = res;
if (obj->type == OSDTYPE_SUB || obj->type == OSDTYPE_SUB2) {
if (obj->render_bitmap_subs && obj->dec_sub) {
struct osd_sub_state *sub = &obj->sub_state;
if (sub->render_bitmap_subs && sub->dec_sub) {
double sub_pts = video_pts;
if (sub_pts != MP_NOPTS_VALUE)
sub_pts -= obj->video_offset + opts->sub_delay;
sub_get_bitmaps(obj->dec_sub, obj->vo_res, sub_pts, out_imgs);
sub_pts -= sub->video_offset + opts->sub_delay;
sub_get_bitmaps(sub->dec_sub, obj->vo_res, sub_pts, out_imgs);
} else {
osd_object_get_bitmaps(osd, obj, out_imgs);
}
} else if (obj->type == OSDTYPE_EXTERNAL2) {
if (osd->external2.format) {
*out_imgs = osd->external2;
osd->external2.bitmap_id = osd->external2.bitmap_pos_id = 0;
if (obj->external2 && obj->external2->format) {
*out_imgs = *obj->external2;
obj->external2->bitmap_id = obj->external2->bitmap_pos_id = 0;
}
} else if (obj->type == OSDTYPE_NAV_HIGHLIGHT) {
mp_nav_get_highlight(osd, obj->vo_res, out_imgs);
if (obj->highlight_priv)
mp_nav_get_highlight(osd, obj->vo_res, out_imgs);
} else {
osd_object_get_bitmaps(osd, obj, out_imgs);
}
@ -230,12 +305,11 @@ void osd_draw(struct osd_state *osd, struct mp_osd_res res,
const bool formats[SUBBITMAP_COUNT],
void (*cb)(void *ctx, struct sub_bitmaps *imgs), void *cb_ctx)
{
pthread_mutex_lock(&osd->lock);
if (draw_flags & OSD_DRAW_SUB_FILTER)
draw_flags |= OSD_DRAW_SUB_ONLY;
if (!(draw_flags & OSD_DRAW_SUB_ONLY))
osd->last_vo_res = res;
for (int n = 0; n < MAX_OSD_PARTS; n++) {
struct osd_object *obj = osd->objs[n];
@ -246,8 +320,8 @@ void osd_draw(struct osd_state *osd, struct mp_osd_res res,
if ((draw_flags & OSD_DRAW_SUB_ONLY) && !obj->is_sub)
continue;
if (obj->dec_sub)
sub_lock(obj->dec_sub);
if (obj->sub_state.dec_sub)
sub_lock(obj->sub_state.dec_sub);
struct sub_bitmaps imgs;
render_object(osd, obj, res, video_pts, formats, &imgs);
@ -260,9 +334,11 @@ void osd_draw(struct osd_state *osd, struct mp_osd_res res,
}
}
if (obj->dec_sub)
sub_unlock(obj->dec_sub);
if (obj->sub_state.dec_sub)
sub_unlock(obj->sub_state.dec_sub);
}
pthread_mutex_unlock(&osd->lock);
}
struct draw_on_image_closure {
@ -311,11 +387,9 @@ void osd_draw_on_image_p(struct osd_state *osd, struct mp_osd_res res,
void osd_changed(struct osd_state *osd, int new_value)
{
for (int n = 0; n < MAX_OSD_PARTS; n++) {
if (osd->objs[n]->type == new_value)
osd->objs[n]->force_redraw = true;
}
osd->want_redraw = true;
pthread_mutex_lock(&osd->lock);
osd_changed_unlocked(osd, new_value);
pthread_mutex_unlock(&osd->lock);
}
void osd_changed_all(struct osd_state *osd)
@ -324,15 +398,41 @@ void osd_changed_all(struct osd_state *osd)
osd_changed(osd, n);
}
bool osd_query_and_reset_want_redraw(struct osd_state *osd)
{
pthread_mutex_lock(&osd->lock);
bool r = osd->want_redraw;
osd->want_redraw = false;
pthread_mutex_unlock(&osd->lock);
return r;
}
double osd_get_vo_pts(struct osd_state *osd)
{
pthread_mutex_lock(&osd->lock);
double r = osd->vo_pts;
pthread_mutex_unlock(&osd->lock);
return r;
}
void osd_set_vo_pts(struct osd_state *osd, double vo_pts)
{
pthread_mutex_lock(&osd->lock);
osd->vo_pts = vo_pts;
pthread_mutex_unlock(&osd->lock);
}
// Scale factor to translate OSD coordinates to what the obj uses internally.
// osd_coordinates * (sw, sh) = obj_coordinates
void osd_object_get_scale_factor(struct osd_state *osd, struct osd_object *obj,
void osd_object_get_scale_factor(struct osd_state *osd, int obj,
double *sw, double *sh)
{
int nw, nh;
osd_object_get_resolution(osd, obj, &nw, &nh);
*sw = nw / (double)obj->vo_res.w;
*sh = nh / (double)obj->vo_res.h;
pthread_mutex_lock(&osd->lock);
*sw = nw / (double)osd->objs[obj]->vo_res.w;
*sh = nh / (double)osd->objs[obj]->vo_res.h;
pthread_mutex_unlock(&osd->lock);
}
// Turn *x and *y, which are given in OSD coordinates, to video coordinates.
@ -342,6 +442,7 @@ void osd_object_get_scale_factor(struct osd_state *osd, struct osd_object *obj,
void osd_coords_to_video(struct osd_state *osd, int frame_w, int frame_h,
int *x, int *y)
{
pthread_mutex_lock(&osd->lock);
struct mp_osd_res res = osd->objs[OSDTYPE_OSD]->vo_res;
int vidw = res.w - res.ml - res.mr;
int vidh = res.h - res.mt - res.mb;
@ -350,6 +451,15 @@ void osd_coords_to_video(struct osd_state *osd, int frame_w, int frame_h,
// The OSD size + margins make up the scaled rectangle of the video.
*x = (*x - res.ml) / xscale;
*y = (*y - res.mt) / yscale;
pthread_mutex_unlock(&osd->lock);
}
struct mp_osd_res osd_get_vo_res(struct osd_state *osd, int obj)
{
pthread_mutex_lock(&osd->lock);
struct mp_osd_res res = osd->objs[obj]->vo_res;
pthread_mutex_unlock(&osd->lock);
return res;
}
// Position the subbitmaps in imgs on the screen. Basically, this fits the

119
sub/osd.h
View File

@ -97,70 +97,6 @@ enum mp_osdtype {
MAX_OSD_PARTS
};
#define OSD_CONV_CACHE_MAX 4
struct osd_object {
int type; // OSDTYPE_*
bool is_sub;
bool force_redraw;
// OSDTYPE_SUB
struct dec_sub *dec_sub;
double video_offset;
bool render_bitmap_subs;
char *sub_text;
// caches for OSD conversion (internal to render_object())
struct osd_conv_cache *cache[OSD_CONV_CACHE_MAX];
struct sub_bitmaps cached;
// 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 sub_bitmap *parts_cache;
struct ass_track *osd_track;
struct ass_renderer *osd_render;
struct ass_library *osd_ass_library;
};
struct osd_state {
struct osd_object *objs[MAX_OSD_PARTS];
double vo_pts;
bool render_subs_in_filter;
struct mp_osd_res last_vo_res;
bool want_redraw;
// OSDTYPE_OSD
char *osd_text;
// OSDTYPE_PROGBAR
int progbar_type; // <0: disabled, 1-255: symbol, else: no symbol
float progbar_value; // range 0.0-1.0
float *progbar_stops; // used for chapter indicators (0.0-1.0 each)
int progbar_num_stops;
// OSDTYPE_EXTERNAL
char *external;
int external_res_x, external_res_y;
// OSDTYPE_EXTERNAL2
struct sub_bitmaps external2;
// OSDTYPE_NAV_HIGHLIGHT
void *highlight_priv;
struct MPOpts *opts;
struct mpv_global *global;
struct mp_log *log;
// Internal to sub.c
struct mp_draw_sub_cache *draw_cache;
};
// Start of OSD symbols in osd_font.pfb
#define OSD_CODEPOINTS 0xE000
@ -204,13 +140,47 @@ struct osd_style_opts {
extern const struct m_sub_options osd_style_conf;
struct osd_state;
struct osd_object;
struct mpv_global;
struct osd_state *osd_create(struct mpv_global *global);
void osd_set_text(struct osd_state *osd, const char *text);
void osd_set_sub(struct osd_state *osd, struct osd_object *obj, const char *text);
void osd_changed(struct osd_state *osd, int new_value);
void osd_changed_all(struct osd_state *osd);
void osd_free(struct osd_state *osd);
bool osd_query_and_reset_want_redraw(struct osd_state *osd);
double osd_get_vo_pts(struct osd_state *osd);
void osd_set_vo_pts(struct osd_state *osd, double vo_pts);
void osd_set_text(struct osd_state *osd, int obj, const char *text);
struct osd_sub_state {
struct dec_sub *dec_sub;
double video_offset;
bool render_bitmap_subs;
};
void osd_set_sub(struct osd_state *osd, int obj, struct osd_sub_state *substate);
void osd_get_sub(struct osd_state *osd, int obj, struct osd_sub_state *substate);
bool osd_get_render_subs_in_filter(struct osd_state *osd);
void osd_set_render_subs_in_filter(struct osd_state *osd, bool s);
struct osd_progbar_state {
int type; // <0: disabled, 1-255: symbol, else: no symbol
float value; // range 0.0-1.0
float *stops; // used for chapter indicators (0.0-1.0 each)
int num_stops;
};
void osd_set_progbar(struct osd_state *osd, struct osd_progbar_state *s);
void osd_set_external(struct osd_state *osd, int res_x, int res_y, char *text);
void osd_set_external2(struct osd_state *osd, struct sub_bitmaps *imgs);
void osd_set_nav_highlight(struct osd_state *osd, void *priv);
enum mp_osd_draw_flags {
OSD_DRAW_SUB_FILTER = (1 << 0),
OSD_DRAW_SUB_ONLY = (1 << 1),
@ -230,27 +200,34 @@ void osd_draw_on_image_p(struct osd_state *osd, struct mp_osd_res res,
double video_pts, int draw_flags,
struct mp_image_pool *pool, struct mp_image *dest);
void osd_object_get_scale_factor(struct osd_state *osd, struct osd_object *obj,
void osd_object_get_scale_factor(struct osd_state *osd, int obj,
double *sw, double *sh);
void osd_coords_to_video(struct osd_state *osd, int frame_w, int frame_h,
int *x, int *y);
struct mp_osd_res osd_get_vo_res(struct osd_state *osd, int obj);
void osd_rescale_bitmaps(struct sub_bitmaps *imgs, int frame_w, int frame_h,
struct mp_osd_res res, double compensate_par);
// defined in osd_libass.c and osd_dummy.c
// internal use only
void osd_object_get_bitmaps(struct osd_state *osd, struct osd_object *obj,
struct sub_bitmaps *out_imgs);
void osd_object_get_resolution(struct osd_state *osd, struct osd_object *obj,
int *out_w, int *out_h);
void osd_get_function_sym(char *buffer, size_t buffer_size, int osd_function);
void osd_init_backend(struct osd_state *osd);
void osd_destroy_backend(struct osd_state *osd);
// doesn't need locking
void osd_get_function_sym(char *buffer, size_t buffer_size, int osd_function);
// defined in backend, but locks if required
void osd_object_get_resolution(struct osd_state *osd, int obj,
int *out_w, int *out_h);
// defined in player
void mp_nav_get_highlight(struct osd_state *osd, struct mp_osd_res res,
void mp_nav_get_highlight(void *priv, struct mp_osd_res res,
struct sub_bitmaps *out_imgs);
#endif /* MPLAYER_SUB_H */

View File

@ -24,7 +24,7 @@ void osd_object_get_bitmaps(struct osd_state *osd, struct osd_object *obj,
*out_imgs = (struct sub_bitmaps) {0};
}
void osd_object_get_resolution(struct osd_state *osd, struct osd_object *obj,
void osd_object_get_resolution(struct osd_state *osd, int obj,
int *out_w, int *out_h)
{
*out_w = 0;

View File

@ -29,6 +29,7 @@
#include "common/common.h"
#include "common/msg.h"
#include "osd.h"
#include "osd_state.h"
static const char osd_font_pfb[] =
#include "sub/osd_font.h"
@ -193,7 +194,7 @@ static void update_osd(struct osd_state *osd, struct osd_object *obj)
create_ass_track(osd, obj, 0, 0);
clear_obj(obj);
if (!osd->osd_text[0])
if (!obj->text[0])
return;
struct osd_style_opts font = *opts->osd_style;
@ -207,7 +208,7 @@ static void update_osd(struct osd_state *osd, struct osd_object *obj)
ASS_Style *style = obj->osd_track->styles + obj->osd_track->default_style;
mp_ass_set_style(style, playresy, &font);
add_osd_ass_event_escaped(obj->osd_track, osd->osd_text);
add_osd_ass_event_escaped(obj->osd_track, obj->text);
}
// align: -1 .. +1
@ -322,7 +323,7 @@ static void update_progbar(struct osd_state *osd, struct osd_object *obj)
clear_obj(obj);
if (osd->progbar_type < 0)
if (obj->progbar_state.type < 0)
return;
float sx = px - border * 2 - height / 4; // includes additional spacing
@ -330,13 +331,13 @@ static void update_progbar(struct osd_state *osd, struct osd_object *obj)
bstr buf = bstr0(talloc_asprintf(NULL, "{\\an6\\pos(%f,%f)}", sx, sy));
if (osd->progbar_type == 0 || osd->progbar_type >= 256) {
if (obj->progbar_state.type == 0 || obj->progbar_state.type >= 256) {
// no sym
} else if (osd->progbar_type >= 32) {
mp_append_utf8_bstr(NULL, &buf, osd->progbar_type);
} else if (obj->progbar_state.type >= 32) {
mp_append_utf8_bstr(NULL, &buf, obj->progbar_state.type);
} else {
bstr_xappend(NULL, &buf, bstr0(ASS_USE_OSD_FONT));
mp_append_utf8_bstr(NULL, &buf, OSD_CODEPOINTS + osd->progbar_type);
mp_append_utf8_bstr(NULL, &buf, OSD_CODEPOINTS + obj->progbar_state.type);
bstr_xappend(NULL, &buf, bstr0("{\\r}"));
}
@ -347,7 +348,7 @@ static void update_progbar(struct osd_state *osd, struct osd_object *obj)
// filled area
d->text = talloc_asprintf_append(d->text, "{\\bord0\\pos(%f,%f)}", px, py);
ass_draw_start(d);
float pos = osd->progbar_value * width - border / 2;
float pos = obj->progbar_state.value * width - border / 2;
ass_draw_rect_cw(d, 0, 0, pos, height);
ass_draw_stop(d);
add_osd_ass_event(obj->osd_track, d->text);
@ -373,8 +374,8 @@ static void update_progbar(struct osd_state *osd, struct osd_object *obj)
ass_draw_rect_ccw(d, 0, 0, width, height);
// chapter marks
for (int n = 0; n < osd->progbar_num_stops; n++) {
float s = osd->progbar_stops[n] * width;
for (int n = 0; n < obj->progbar_state.num_stops; n++) {
float s = obj->progbar_state.stops[n] * width;
float dent = border * 1.3;
if (s > dent && s < width - dent) {
@ -395,10 +396,10 @@ static void update_progbar(struct osd_state *osd, struct osd_object *obj)
static void update_external(struct osd_state *osd, struct osd_object *obj)
{
create_ass_track(osd, obj, osd->external_res_x, osd->external_res_y);
create_ass_track(osd, obj, obj->external_res_x, obj->external_res_y);
clear_obj(obj);
bstr t = bstr0(osd->external);
bstr t = bstr0(obj->text);
while (t.len) {
bstr line;
bstr_split_tok(t, "\n", &line, &t);
@ -416,7 +417,7 @@ static void update_sub(struct osd_state *osd, struct osd_object *obj)
clear_obj(obj);
if (!obj->sub_text || !obj->sub_text[0] || obj->render_bitmap_subs)
if (!obj->text || !obj->text[0] || obj->sub_state.render_bitmap_subs)
return;
create_ass_renderer(osd, obj);
@ -435,7 +436,7 @@ static void update_sub(struct osd_state *osd, struct osd_object *obj)
ass_set_line_position(obj->osd_render, 100 - opts->sub_pos);
#endif
add_osd_ass_event_escaped(obj->osd_track, obj->sub_text);
add_osd_ass_event_escaped(obj->osd_track, obj->text);
}
static void update_object(struct osd_state *osd, struct osd_object *obj)
@ -474,9 +475,12 @@ void osd_object_get_bitmaps(struct osd_state *osd, struct osd_object *obj,
talloc_steal(obj, obj->parts_cache);
}
void osd_object_get_resolution(struct osd_state *osd, struct osd_object *obj,
void osd_object_get_resolution(struct osd_state *osd, int obj,
int *out_w, int *out_h)
{
*out_w = obj->osd_track ? obj->osd_track->PlayResX : 0;
*out_h = obj->osd_track ? obj->osd_track->PlayResY : 0;
pthread_mutex_lock(&osd->lock);
struct osd_object *osd_obj = osd->objs[obj];
*out_w = osd_obj->osd_track ? osd_obj->osd_track->PlayResX : 0;
*out_h = osd_obj->osd_track ? osd_obj->osd_track->PlayResY : 0;
pthread_mutex_unlock(&osd->lock);
}

68
sub/osd_state.h Normal file
View File

@ -0,0 +1,68 @@
#ifndef MP_OSD_STATE_H_
#define MP_OSD_STATE_H_
#include <pthread.h>
#include "osd.h"
#define OSD_CONV_CACHE_MAX 4
struct osd_object {
int type; // OSDTYPE_*
bool is_sub;
bool force_redraw;
// OSDTYPE_SUB/OSDTYPE_SUB2/OSDTYPE_OSD/OSDTYPE_EXTERNAL
char *text;
// OSDTYPE_PROGBAR
struct osd_progbar_state progbar_state;
// OSDTYPE_SUB/OSDTYPE_SUB2
struct osd_sub_state sub_state;
// OSDTYPE_EXTERNAL
int external_res_x, external_res_y;
// OSDTYPE_EXTERNAL2
struct sub_bitmaps *external2;
// OSDTYPE_NAV_HIGHLIGHT
void *highlight_priv;
// caches for OSD conversion (internal to render_object())
struct osd_conv_cache *cache[OSD_CONV_CACHE_MAX];
struct sub_bitmaps cached;
// 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 sub_bitmap *parts_cache;
struct ass_track *osd_track;
struct ass_renderer *osd_render;
struct ass_library *osd_ass_library;
};
struct osd_state {
pthread_mutex_t lock;
struct osd_object *objs[MAX_OSD_PARTS];
double vo_pts;
bool render_subs_in_filter;
bool want_redraw;
struct MPOpts *opts;
struct mpv_global *global;
struct mp_log *log;
struct mp_draw_sub_cache *draw_cache;
};
#endif

View File

@ -282,7 +282,7 @@ void mpgl_osd_draw_cb(struct mpgl_osd *ctx,
{
struct draw_cb_closure c = {ctx, cb, cb_ctx};
reset(ctx);
osd_draw(osd, res, osd->vo_pts, 0, ctx->formats, draw_cb, &c);
osd_draw(osd, res, osd_get_vo_pts(osd), 0, ctx->formats, draw_cb, &c);
}
void mpgl_osd_redraw_cb(struct mpgl_osd *ctx,
@ -376,5 +376,5 @@ static void draw_legacy_cb(void *pctx, struct sub_bitmaps *imgs)
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);
osd_draw(osd, res, osd_get_vo_pts(osd), 0, ctx->formats, draw_legacy_cb, ctx);
}

View File

@ -1700,7 +1700,7 @@ static void draw_osd(struct vo *vo, struct osd_state *osd)
if (!priv->d3d_device)
return;
osd_draw(osd, priv->osd_res, osd->vo_pts, 0, osd_fmt_supported,
osd_draw(osd, priv->osd_res, osd_get_vo_pts(osd), 0, osd_fmt_supported,
draw_osd_cb, priv);
}

View File

@ -97,7 +97,7 @@ static void draw_osd(struct vo *vo, struct osd_state *osd)
.display_par = sar / dar,
};
osd_draw_on_image(osd, dim, osd->vo_pts, OSD_DRAW_SUB_ONLY, p->current);
osd_draw_on_image(osd, dim, osd_get_vo_pts(osd), OSD_DRAW_SUB_ONLY, p->current);
}
static void flip_page(struct vo *vo)

View File

@ -500,7 +500,8 @@ static void draw_osd(struct vo *vo, struct osd_state *osd)
mp_image_set_colorspace_details(vc->lastimg, &vc->colorspace);
osd_draw_on_image(osd, dim, osd->vo_pts, OSD_DRAW_SUB_ONLY, vc->lastimg);
osd_draw_on_image(osd, dim, osd_get_vo_pts(osd), OSD_DRAW_SUB_ONLY,
vc->lastimg);
}
}

View File

@ -727,7 +727,7 @@ static void draw_osd(struct vo *vo, struct osd_state *osd)
[SUBBITMAP_RGBA] = true,
};
osd_draw(osd, vc->osd_res, osd->vo_pts, 0, osdformats, draw_osd_cb, vo);
osd_draw(osd, vc->osd_res, osd_get_vo_pts(osd), 0, osdformats, draw_osd_cb, vo);
}
static int preinit(struct vo *vo)

View File

@ -435,7 +435,7 @@ static void draw_osd(struct vo *vo, struct osd_state *osd)
for (int n = 0; n < MAX_OSD_PARTS; n++)
p->osd_parts[n].active = false;
osd_draw(osd, *res, osd->vo_pts, 0, osd_formats, draw_osd_cb, p);
osd_draw(osd, *res, osd_get_vo_pts(osd), 0, osd_formats, draw_osd_cb, p);
}
static int get_displayattribtype(const char *name)

View File

@ -997,7 +997,7 @@ static void draw_osd(struct vo *vo, struct osd_state *osd)
[SUBBITMAP_RGBA] = true,
};
osd_draw(osd, vc->osd_rect, osd->vo_pts, 0, formats, draw_osd_cb, vo);
osd_draw(osd, vc->osd_rect, osd_get_vo_pts(osd), 0, formats, draw_osd_cb, vo);
}
static int update_presentation_queue_status(struct vo *vo)

View File

@ -560,7 +560,7 @@ static void draw_osd(struct vo *vo, struct osd_state *osd)
{
struct priv *p = vo->priv;
struct mp_image img = buffer_get_mp_image(p, p->back_buffer);
osd_draw_on_image(osd, p->osd, osd->vo_pts, 0, &img);
osd_draw_on_image(osd, p->osd, osd_get_vo_pts(osd), 0, &img);
}
static void flip_page(struct vo *vo)

View File

@ -427,7 +427,7 @@ static void draw_osd(struct vo *vo, struct osd_state *osd)
struct mp_image img = get_x_buffer(p, p->current_buf);
osd_draw_on_image(osd, p->osd, osd->vo_pts, 0, &img);
osd_draw_on_image(osd, p->osd, osd_get_vo_pts(osd), 0, &img);
}
static mp_image_t *get_screenshot(struct vo *vo)

View File

@ -622,7 +622,7 @@ static void draw_osd(struct vo *vo, struct osd_state *osd)
.display_par = 1.0 / vo->aspdat.par,
};
osd_draw_on_image(osd, res, osd->vo_pts, 0, &img);
osd_draw_on_image(osd, res, osd_get_vo_pts(osd), 0, &img);
}
static void wait_for_completion(struct vo *vo, int max_outstanding)