summaryrefslogtreecommitdiffstats
path: root/sub
diff options
context:
space:
mode:
Diffstat (limited to 'sub')
-rw-r--r--sub/dec_sub.h1
-rw-r--r--sub/osd.c53
-rw-r--r--sub/osd.h3
-rw-r--r--sub/osd_libass.c7
-rw-r--r--sub/osd_state.h8
-rw-r--r--sub/sd_ass.c22
-rw-r--r--sub/sd_lavc.c31
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 {
diff --git a/sub/osd.c b/sub/osd.c
index 381fa8892d..dfe75b7698 100644
--- a/sub/osd.c
+++ b/sub/osd.c
@@ -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;
}
diff --git a/sub/osd.h b/sub/osd.h
index 6bfa6dd525..cf66392904 100644
--- a/sub/osd.h
+++ b/sub/osd.h
@@ -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)