diff options
Diffstat (limited to 'sub')
-rw-r--r-- | sub/dec_sub.h | 1 | ||||
-rw-r--r-- | sub/osd.c | 53 | ||||
-rw-r--r-- | sub/osd.h | 3 | ||||
-rw-r--r-- | sub/osd_libass.c | 7 | ||||
-rw-r--r-- | sub/osd_state.h | 8 | ||||
-rw-r--r-- | sub/sd_ass.c | 22 | ||||
-rw-r--r-- | sub/sd_lavc.c | 31 |
7 files changed, 64 insertions, 61 deletions
diff --git a/sub/dec_sub.h b/sub/dec_sub.h index 1048bf0ca6..341966a430 100644 --- a/sub/dec_sub.h +++ b/sub/dec_sub.h @@ -19,6 +19,7 @@ enum sd_ctrl { SD_CTRL_GET_RESOLUTION, SD_CTRL_SET_TOP, SD_CTRL_SET_VIDEO_DEF_FPS, + SD_CTRL_UPDATE_SPEED, }; struct attachment_list { @@ -81,6 +81,7 @@ const struct m_sub_options osd_style_conf = { .align_x = -1, .align_y = -1, }, + .change_flags = UPDATE_OSD, }; const struct m_sub_options sub_style_conf = { @@ -99,6 +100,7 @@ const struct m_sub_options sub_style_conf = { .align_x = 0, .align_y = 1, }, + .change_flags = UPDATE_OSD, }; static bool osd_res_equals(struct mp_osd_res a, struct mp_osd_res b) @@ -146,12 +148,6 @@ void osd_free(struct osd_state *osd) talloc_free(osd); } -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, const char *text) { pthread_mutex_lock(&osd->lock); @@ -161,7 +157,8 @@ void osd_set_text(struct osd_state *osd, const char *text) if (strcmp(osd_obj->text, text) != 0) { talloc_free(osd_obj->text); osd_obj->text = talloc_strdup(osd_obj, text); - osd_changed_unlocked(osd, osd_obj->type); + osd_obj->osd_changed = true; + osd->want_redraw_notification = true; } pthread_mutex_unlock(&osd->lock); } @@ -169,8 +166,12 @@ void osd_set_text(struct osd_state *osd, const char *text) void osd_set_sub(struct osd_state *osd, int index, struct dec_sub *dec_sub) { pthread_mutex_lock(&osd->lock); - if (index >= 0 && index < 2) - osd->objs[OSDTYPE_SUB + index]->sub = dec_sub; + if (index >= 0 && index < 2) { + struct osd_object *obj = osd->objs[OSDTYPE_SUB + index]; + obj->sub = dec_sub; + obj->vo_change_id += 1; + } + osd->want_redraw_notification = true; pthread_mutex_unlock(&osd->lock); } @@ -199,7 +200,8 @@ void osd_set_progbar(struct osd_state *osd, struct osd_progbar_state *s) 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); + osd_obj->osd_changed = true; + osd->want_redraw_notification = true; pthread_mutex_unlock(&osd->lock); } @@ -207,7 +209,8 @@ void osd_set_external2(struct osd_state *osd, struct sub_bitmaps *imgs) { pthread_mutex_lock(&osd->lock); osd->objs[OSDTYPE_EXTERNAL2]->external2 = imgs; - osd_changed_unlocked(osd, OSDTYPE_EXTERNAL2); + osd->objs[OSDTYPE_EXTERNAL2]->vo_change_id += 1; + osd->want_redraw_notification = true; pthread_mutex_unlock(&osd->lock); } @@ -216,7 +219,6 @@ static void check_obj_resize(struct osd_state *osd, struct mp_osd_res res, { if (!osd_res_equals(res, obj->vo_res)) { obj->vo_res = res; - obj->force_redraw = true; mp_client_broadcast_event(mp_client_api_get_core(osd->global->client_api), MP_EVENT_WIN_RESIZE, NULL); } @@ -269,10 +271,6 @@ static void render_object(struct osd_state *osd, struct osd_object *obj, osd_object_get_bitmaps(osd, obj, format, out_imgs); } - if (obj->force_redraw) - out_imgs->change_id++; - - obj->force_redraw = false; obj->vo_change_id += out_imgs->change_id; if (out_imgs->num_parts == 0) @@ -323,6 +321,13 @@ void osd_draw(struct osd_state *osd, struct mp_osd_res res, sub_unlock(obj->sub); } + // If this is called with OSD_DRAW_SUB_ONLY or OSD_DRAW_OSD_ONLY set, assume + // it will always draw the complete OSD by doing multiple osd_draw() calls. + // OSD_DRAW_SUB_FILTER on the other hand is an evil special-case, and we + // must not reset the flag when it happens. + if (!(draw_flags & OSD_DRAW_SUB_FILTER)) + osd->want_redraw_notification = false; + pthread_mutex_unlock(&osd->lock); } @@ -379,24 +384,20 @@ struct mp_osd_res osd_res_from_image_params(const struct mp_image_params *p) }; } -void osd_changed(struct osd_state *osd, int new_value) +// Typically called to react to OSD style changes. +void osd_changed(struct osd_state *osd) { pthread_mutex_lock(&osd->lock); - osd_changed_unlocked(osd, new_value); + osd->objs[OSDTYPE_OSD]->osd_changed = true; + osd->want_redraw_notification = true; pthread_mutex_unlock(&osd->lock); } -void osd_changed_all(struct osd_state *osd) -{ - for (int n = 0; n < MAX_OSD_PARTS; n++) - 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; + bool r = osd->want_redraw_notification; + osd->want_redraw_notification = false; pthread_mutex_unlock(&osd->lock); return r; } @@ -145,8 +145,7 @@ struct mpv_global; struct dec_sub; struct osd_state *osd_create(struct mpv_global *global); -void osd_changed(struct osd_state *osd, int new_value); -void osd_changed_all(struct osd_state *osd); +void osd_changed(struct osd_state *osd); void osd_free(struct osd_state *osd); bool osd_query_and_reset_want_redraw(struct osd_state *osd); diff --git a/sub/osd_libass.c b/sub/osd_libass.c index a9ab7eabd2..454d0387a4 100644 --- a/sub/osd_libass.c +++ b/sub/osd_libass.c @@ -431,6 +431,7 @@ static void update_progbar(struct osd_state *osd, struct osd_object *obj) static void update_osd(struct osd_state *osd, struct osd_object *obj) { + obj->osd_changed = false; clear_ass(&obj->ass); update_osd_text(osd, obj); update_progbar(osd, obj); @@ -489,6 +490,8 @@ void osd_set_external(struct osd_state *osd, void *id, int res_x, int res_y, int index = entry - &obj->externals[0]; destroy_external(entry); MP_TARRAY_REMOVE_AT(obj->externals, obj->num_externals, index); + obj->changed = true; + osd->want_redraw_notification = true; goto done; } @@ -501,7 +504,7 @@ void osd_set_external(struct osd_state *osd, void *id, int res_x, int res_y, entry->res_y = res_y; update_external(osd, obj, entry); obj->changed = true; - osd_changed_unlocked(osd, obj->type); + osd->want_redraw_notification = true; } done: @@ -527,7 +530,7 @@ static void append_ass(struct ass_state *ass, struct mp_osd_res *res, void osd_object_get_bitmaps(struct osd_state *osd, struct osd_object *obj, int format, struct sub_bitmaps *out_imgs) { - if (obj->force_redraw && obj->type == OSDTYPE_OSD) + if (obj->type == OSDTYPE_OSD && obj->osd_changed) update_osd(osd, obj); if (!obj->ass_packer) diff --git a/sub/osd_state.h b/sub/osd_state.h index 81bdbd633a..fbccd85e70 100644 --- a/sub/osd_state.h +++ b/sub/osd_state.h @@ -28,12 +28,9 @@ struct osd_object { int type; // OSDTYPE_* bool is_sub; - bool force_redraw; - // OSDTYPE_OSD + bool osd_changed; char *text; - - // OSDTYPE_OSD struct osd_progbar_state progbar_state; // OSDTYPE_SUB/OSDTYPE_SUB2 @@ -72,6 +69,7 @@ struct osd_state { bool render_subs_in_filter; bool want_redraw; + bool want_redraw_notification; struct MPOpts *opts; struct mpv_global *global; @@ -80,6 +78,4 @@ struct osd_state { struct mp_draw_sub_cache *draw_cache; }; -void osd_changed_unlocked(struct osd_state *osd, int obj); - #endif diff --git a/sub/sd_ass.c b/sub/sd_ass.c index 34a49c1501..31c66a6087 100644 --- a/sub/sd_ass.c +++ b/sub/sd_ass.c @@ -75,7 +75,7 @@ static void mp_ass_add_default_styles(ASS_Track *track, struct MPOpts *opts) track->default_style = sid; ASS_Style *style = track->styles + sid; style->Name = strdup("Default"); - mp_ass_set_style(style, track->PlayResY, opts->sub_text_style); + mp_ass_set_style(style, track->PlayResY, opts->sub_style); } if (opts->ass_style_override) @@ -138,7 +138,7 @@ static void enable_output(struct sd *sd, bool enable) } else { ctx->ass_renderer = ass_renderer_init(ctx->ass_library); - mp_ass_configure_fonts(ctx->ass_renderer, sd->opts->sub_text_style, + mp_ass_configure_fonts(ctx->ass_renderer, sd->opts->sub_style, sd->global, sd->log); } } @@ -329,14 +329,18 @@ static void configure_ass(struct sd *sd, struct mp_osd_res *dim, set_force_flags |= ASS_OVERRIDE_BIT_STYLE | ASS_OVERRIDE_BIT_FONT_SIZE; if (opts->ass_style_override == 4) set_force_flags |= ASS_OVERRIDE_BIT_FONT_SIZE; +#if LIBASS_VERSION >= 0x01201001 + if (converted) + set_force_flags |= ASS_OVERRIDE_BIT_ALIGNMENT; +#endif ass_set_selective_style_override_enabled(priv, set_force_flags); ASS_Style style = {0}; - mp_ass_set_style(&style, 288, opts->sub_text_style); + mp_ass_set_style(&style, 288, opts->sub_style); ass_set_selective_style_override(priv, &style); free(style.FontName); if (converted && track->default_style < track->n_styles) { mp_ass_set_style(track->styles + track->default_style, - track->PlayResY, opts->sub_text_style); + track->PlayResY, opts->sub_style); } ass_set_font_scale(priv, set_font_scale); ass_set_hinting(priv, set_hinting); @@ -594,6 +598,10 @@ static void fill_plaintext(struct sd *sd, double pts) return; bstr dst = {0}; + + if (ctx->on_top) + bstr_xappend(NULL, &dst, bstr0("{\\a6}")); + while (*text) { if (*text == '{') bstr_xappend(NULL, &dst, bstr0("\\")); @@ -614,9 +622,6 @@ static void fill_plaintext(struct sd *sd, double pts) event->Style = track->default_style; event->Text = strdup(dst.start); - if (track->default_style < track->n_styles) - track->styles[track->default_style].Alignment = ctx->on_top ? 6 : 2; - talloc_free(dst.start); } @@ -667,6 +672,9 @@ static int control(struct sd *sd, enum sd_ctrl cmd, void *arg) ctx->video_fps = *(double *)arg; update_subtitle_speed(sd); return CONTROL_OK; + case SD_CTRL_UPDATE_SPEED: + update_subtitle_speed(sd); + return CONTROL_OK; default: return CONTROL_UNKNOWN; } diff --git a/sub/sd_lavc.c b/sub/sd_lavc.c index 9c217a6936..2c1b327b38 100644 --- a/sub/sd_lavc.c +++ b/sub/sd_lavc.c @@ -22,6 +22,7 @@ #include <libavcodec/avcodec.h> #include <libavutil/common.h> #include <libavutil/intreadwrite.h> +#include <libavutil/opt.h> #include "config.h" @@ -106,6 +107,9 @@ static int init(struct sd *sd) // Supported codecs must be known to decode to paletted bitmaps switch (cid) { case AV_CODEC_ID_DVB_SUBTITLE: +#if LIBAVCODEC_VERSION_MICRO >= 100 + case AV_CODEC_ID_DVB_TELETEXT: +#endif case AV_CODEC_ID_HDMV_PGS_SUBTITLE: case AV_CODEC_ID_XSUB: case AV_CODEC_ID_DVD_SUBTITLE: @@ -123,25 +127,9 @@ static int init(struct sd *sd) if (!ctx) goto error; mp_lavc_set_extradata(ctx, sd->codec->extradata, sd->codec->extradata_size); + priv->pkt_timebase = mp_get_codec_timebase(sd->codec); #if LIBAVCODEC_VERSION_MICRO >= 100 - if (cid == AV_CODEC_ID_HDMV_PGS_SUBTITLE) { - // We don't always want to set this, because the ridiculously shitty - // libavcodec API will mess with certain fields (end_display_time) - // when setting it. On the other hand, PGS in particular needs PTS - // mangling. While the PGS decoder doesn't modify the timestamps (just - // reorder it), the ridiculously shitty libavcodec wants a timebase - // anyway and for no good reason. It always sets end_display_time to - // UINT32_MAX (which is a broken and undocumented way to say "unknown"), - // which coincidentally won't be overridden by the ridiculously shitty - // pkt_timebase code. also, Libav doesn't have the pkt_timebase field, - // because Libav tends to avoid _adding_ ridiculously shitty APIs. - priv->pkt_timebase = (AVRational){1, AV_TIME_BASE}; - ctx->pkt_timebase = priv->pkt_timebase; - } else { - // But old ffmpeg releases have a buggy pkt_timebase check, because the - // shit above wasn't bad enough! - ctx->pkt_timebase = (AVRational){0, 0}; - } + ctx->pkt_timebase = priv->pkt_timebase; #endif if (avcodec_open2(ctx, sub_codec, NULL) < 0) goto error; @@ -355,6 +343,13 @@ static void decode(struct sd *sd, struct demux_packet *packet) MP_WARN(sd, "Subtitle with unknown start time.\n"); mp_set_av_packet(&pkt, packet, &priv->pkt_timebase); + + if (ctx->codec_id == AV_CODEC_ID_DVB_TELETEXT) { + char page[4]; + snprintf(page, sizeof(page), "%d", opts->teletext_page); + av_opt_set(ctx, "txt_page", page, AV_OPT_SEARCH_CHILDREN); + } + int got_sub; int res = avcodec_decode_subtitle2(ctx, &sub, &got_sub, &pkt); if (res < 0 || !got_sub) |