diff options
-rw-r--r-- | player/command.c | 58 | ||||
-rw-r--r-- | player/core.h | 2 | ||||
-rw-r--r-- | player/dvdnav.c | 39 | ||||
-rw-r--r-- | player/loadfile.c | 3 | ||||
-rw-r--r-- | player/lua.c | 31 | ||||
-rw-r--r-- | player/osd.c | 36 | ||||
-rw-r--r-- | player/playloop.c | 9 | ||||
-rw-r--r-- | player/screenshot.c | 6 | ||||
-rw-r--r-- | player/sub.c | 38 | ||||
-rw-r--r-- | player/video.c | 4 | ||||
-rw-r--r-- | sub/osd.c | 184 | ||||
-rw-r--r-- | sub/osd.h | 119 | ||||
-rw-r--r-- | sub/osd_dummy.c | 2 | ||||
-rw-r--r-- | sub/osd_libass.c | 38 | ||||
-rw-r--r-- | sub/osd_state.h | 68 | ||||
-rw-r--r-- | video/out/gl_osd.c | 4 | ||||
-rw-r--r-- | video/out/vo_direct3d.c | 2 | ||||
-rw-r--r-- | video/out/vo_image.c | 2 | ||||
-rw-r--r-- | video/out/vo_lavc.c | 3 | ||||
-rw-r--r-- | video/out/vo_sdl.c | 2 | ||||
-rw-r--r-- | video/out/vo_vaapi.c | 2 | ||||
-rw-r--r-- | video/out/vo_vdpau.c | 2 | ||||
-rw-r--r-- | video/out/vo_wayland.c | 2 | ||||
-rw-r--r-- | video/out/vo_x11.c | 2 | ||||
-rw-r--r-- | video/out/vo_xv.c | 2 |
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, ¶ms); } - 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); } @@ -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); +} |