summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--player/command.c58
-rw-r--r--player/core.h2
-rw-r--r--player/dvdnav.c39
-rw-r--r--player/loadfile.c3
-rw-r--r--player/lua.c31
-rw-r--r--player/osd.c36
-rw-r--r--player/playloop.c9
-rw-r--r--player/screenshot.c6
-rw-r--r--player/sub.c38
-rw-r--r--player/video.c4
-rw-r--r--sub/osd.c184
-rw-r--r--sub/osd.h119
-rw-r--r--sub/osd_dummy.c2
-rw-r--r--sub/osd_libass.c38
-rw-r--r--sub/osd_state.h68
-rw-r--r--video/out/gl_osd.c4
-rw-r--r--video/out/vo_direct3d.c2
-rw-r--r--video/out/vo_image.c2
-rw-r--r--video/out/vo_lavc.c3
-rw-r--r--video/out/vo_sdl.c2
-rw-r--r--video/out/vo_vaapi.c2
-rw-r--r--video/out/vo_vdpau.c2
-rw-r--r--video/out/vo_wayland.c2
-rw-r--r--video/out/vo_x11.c2
-rw-r--r--video/out/vo_xv.c2
25 files changed, 416 insertions, 244 deletions
diff --git a/player/command.c b/player/command.c
index 2334e844b4..bb0e9789cf 100644
--- a/player/command.c
+++ b/player/command.c
@@ -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);
diff --git a/player/core.h b/player/core.h
index edfdaec2e1..1018ea9df3 100644
--- a/player/core.h
+++ b/player/core.h
@@ -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
diff --git a/player/dvdnav.c b/player/dvdnav.c
index 7e28c1922b..fd370599c6 100644
--- a/player/dvdnav.c
+++ b/player/dvdnav.c
@@ -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]) {
diff --git a/player/loadfile.c b/player/loadfile.c
index 6262042709..b81da983f8 100644
--- a/player/loadfile.c
+++ b/player/loadfile.c
@@ -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);
}
diff --git a/player/lua.c b/player/lua.c
index f77f9d1a7e..ca92aa009d 100644
--- a/player/lua.c
+++ b/player/lua.c
@@ -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;
diff --git a/player/osd.c b/player/osd.c
index 8401f75b36..1f15e3ddc7 100644
--- a/player/osd.c
+++ b/player/osd.c
@@ -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)
diff --git a/player/playloop.c b/player/playloop.c
index 95e9a9c5a4..167a0722a2 100644
--- a/player/playloop.c
+++ b/player/playloop.c
@@ -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;
diff --git a/player/screenshot.c b/player/screenshot.c
index d5a6b1b3d0..9b8922c39a 100644
--- a/player/screenshot.c
+++ b/player/screenshot.c
@@ -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) {
diff --git a/player/sub.c b/player/sub.c
index 6d39ef2299..00b2260c67 100644
--- a/player/sub.c
+++ b/player/sub.c
@@ -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);
}
diff --git a/player/video.c b/player/video.c
index 17eaab619e..6f634270d2 100644
--- a/player/video.c
+++ b/player/video.c
@@ -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);
}
diff --git a/sub/osd.c b/sub/osd.c
index 56d845b97f..69ba554890 100644
--- a/sub/osd.c
+++ b/sub/osd.c
@@ -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_sub(struct osd_state *osd, int obj, struct osd_sub_state *substate)
+{
+ pthread_mutex_lock(&osd->lock);
+ osd->objs[obj]->sub_state = substate ? *substate : (struct osd_sub_state){0};
+ pthread_mutex_unlock(&osd->lock);
+}
+
+void osd_get_sub(struct osd_state *osd, int obj, struct osd_sub_state *substate)
+{
+ pthread_mutex_lock(&osd->lock);
+ *substate = osd->objs[obj]->sub_state;
+ pthread_mutex_unlock(&osd->lock);
}
-void osd_set_text(struct osd_state *osd, const char *text)
+bool osd_get_render_subs_in_filter(struct osd_state *osd)
{
- if (!set_text(osd, &osd->osd_text, text))
- osd_changed(osd, OSDTYPE_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_sub(struct osd_state *osd, struct osd_object *obj, const char *text)
+void osd_set_external2(struct osd_state *osd, struct sub_bitmaps *imgs)
{
- if (!set_text(obj, &obj->sub_text, text))
- osd_changed(osd, obj->type);
+ 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
diff --git a/sub/osd.h b/sub/osd.h
index 17e8a02c08..239286c5e6 100644
--- a/sub/osd.h
+++ b/sub/osd.h
@@ -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 */
diff --git a/sub/osd_dummy.c b/sub/osd_dummy.c
index cc2ba37377..6fc78ab368 100644
--- a/sub/osd_dummy.c
+++ b/sub/osd_dummy.c
@@ -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;
diff --git a/sub/osd_libass.c b/sub/osd_libass.c
index fb50dce9cd..90807fa60a 100644
--- a/sub/osd_libass.c
+++ b/sub/osd_libass.c
@@ -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);
}
diff --git a/sub/osd_state.h b/sub/osd_state.h
new file mode 100644
index 0000000000..55e484e3e0
--- /dev/null
+++ b/sub/osd_state.h
@@ -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
diff --git a/video/out/gl_osd.c b/video/out/gl_osd.c
index 99b64176ae..393619e554 100644
--- a/video/out/gl_osd.c
+++ b/video/out/gl_osd.c
@@ -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);
}
diff --git a/video/out/vo_direct3d.c b/video/out/vo_direct3d.c
index 6e189bc660..10539d4f18 100644
--- a/video/out/vo_direct3d.c
+++ b/video/out/vo_direct3d.c
@@ -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);
}
diff --git a/video/out/vo_image.c b/video/out/vo_image.c
index c99eae49b4..f7f3a35822 100644
--- a/video/out/vo_image.c
+++ b/video/out/vo_image.c
@@ -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)
diff --git a/video/out/vo_lavc.c b/video/out/vo_lavc.c
index c0b317da94..8a784db37b 100644
--- a/video/out/vo_lavc.c
+++ b/video/out/vo_lavc.c
@@ -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);
}
}
diff --git a/video/out/vo_sdl.c b/video/out/vo_sdl.c
index 893279a8f4..3f743a17a4 100644
--- a/video/out/vo_sdl.c
+++ b/video/out/vo_sdl.c
@@ -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)
diff --git a/video/out/vo_vaapi.c b/video/out/vo_vaapi.c
index cd2768a3ea..4876c454d9 100644
--- a/video/out/vo_vaapi.c
+++ b/video/out/vo_vaapi.c
@@ -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)
diff --git a/video/out/vo_vdpau.c b/video/out/vo_vdpau.c
index 5a0d11206a..c93c3eb0a6 100644
--- a/video/out/vo_vdpau.c
+++ b/video/out/vo_vdpau.c
@@ -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)
diff --git a/video/out/vo_wayland.c b/video/out/vo_wayland.c
index 1d9025b245..3ab9246553 100644
--- a/video/out/vo_wayland.c
+++ b/video/out/vo_wayland.c
@@ -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)
diff --git a/video/out/vo_x11.c b/video/out/vo_x11.c
index 8240f55b25..0da8715f5d 100644
--- a/video/out/vo_x11.c
+++ b/video/out/vo_x11.c
@@ -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)
diff --git a/video/out/vo_xv.c b/video/out/vo_xv.c
index 046dc21d85..53a46cbe5a 100644
--- a/video/out/vo_xv.c
+++ b/video/out/vo_xv.c
@@ -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)