summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/input.rst13
-rw-r--r--player/command.c24
-rw-r--r--player/sub.c7
-rw-r--r--sub/dec_sub.c10
-rw-r--r--sub/dec_sub.h7
-rw-r--r--sub/sd.h2
-rw-r--r--sub/sd_ass.c17
7 files changed, 62 insertions, 18 deletions
diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst
index af80052b1d..be48644cfd 100644
--- a/DOCS/man/input.rst
+++ b/DOCS/man/input.rst
@@ -2461,6 +2461,19 @@ Property list
This property is experimental and might be removed in the future.
+``sub-text-ass``
+ Like ``sub-text``, but return the text in ASS format. Text subtitles in
+ other formats are converted. For native ASS subtitles, events that do
+ not contain any text (but vector drawings etc.) are not filtered out. If
+ multiple events match with the current playback time, they are concatenated
+ with line breaks. Contains only the "Text" part of the events.
+
+ This property is not enough to render ASS subtitles correctly, because ASS
+ header and per-event metadata are not returned. You likely need to do
+ further filtering on the returned string to make it useful.
+
+ This property is experimental and might be removed in the future.
+
``sub-start``
Return the current subtitle start time (in seconds). If there's multiple
current subtitles, returns the first start time. If no current subtitle is
diff --git a/player/command.c b/player/command.c
index 2c44a3f095..322ce973c9 100644
--- a/player/command.c
+++ b/player/command.c
@@ -2695,6 +2695,7 @@ static int mp_property_sub_pos(void *ctx, struct m_property *prop,
static int mp_property_sub_text(void *ctx, struct m_property *prop,
int action, void *arg)
{
+ int type = *(int *)prop->priv;
MPContext *mpctx = ctx;
struct track *track = mpctx->current_track[0][STREAM_SUB];
struct dec_sub *sub = track ? track->d_sub : NULL;
@@ -2702,11 +2703,19 @@ static int mp_property_sub_text(void *ctx, struct m_property *prop,
if (!sub || pts == MP_NOPTS_VALUE)
return M_PROPERTY_UNAVAILABLE;
- char *text = sub_get_text(sub, pts);
- if (!text)
- text = "";
-
- return m_property_strdup_ro(action, arg, text);
+ switch (action) {
+ case M_PROPERTY_GET: {
+ char *text = sub_get_text(sub, pts, type);
+ if (!text)
+ text = talloc_strdup(NULL, "");
+ *(char **)arg = text;
+ return M_PROPERTY_OK;
+ }
+ case M_PROPERTY_GET_TYPE:
+ *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_STRING};
+ return M_PROPERTY_OK;
+ }
+ return M_PROPERTY_NOT_IMPLEMENTED;
}
static struct sd_times get_times(void *ctx, struct m_property *prop,
@@ -3489,7 +3498,10 @@ static const struct m_property mp_properties_base[] = {
{"sub-delay", mp_property_sub_delay},
{"sub-speed", mp_property_sub_speed},
{"sub-pos", mp_property_sub_pos},
- {"sub-text", mp_property_sub_text},
+ {"sub-text", mp_property_sub_text,
+ .priv = (void *)&(const int){SD_TEXT_TYPE_PLAIN}},
+ {"sub-text-ass", mp_property_sub_text,
+ .priv = (void *)&(const int){SD_TEXT_TYPE_ASS}},
{"sub-start", mp_property_sub_start},
{"sub-end", mp_property_sub_end},
diff --git a/player/sub.c b/player/sub.c
index a40a6d5e9d..ae2a85ac1c 100644
--- a/player/sub.c
+++ b/player/sub.c
@@ -105,8 +105,11 @@ static bool update_subtitle(struct MPContext *mpctx, double video_pts,
return false;
// Handle displaying subtitles on terminal; never done for secondary subs
- if (mpctx->current_track[0][STREAM_SUB] == track && !mpctx->video_out)
- term_osd_set_subs(mpctx, sub_get_text(dec_sub, video_pts));
+ if (mpctx->current_track[0][STREAM_SUB] == track && !mpctx->video_out) {
+ char *text = sub_get_text(dec_sub, video_pts, SD_TEXT_TYPE_PLAIN);
+ term_osd_set_subs(mpctx, text);
+ talloc_free(text);
+ }
// Handle displaying subtitles on VO with no video being played. This is
// quite different, because normally subtitles are redrawn on new video
diff --git a/sub/dec_sub.c b/sub/dec_sub.c
index 76e96bc16b..aedb836235 100644
--- a/sub/dec_sub.c
+++ b/sub/dec_sub.c
@@ -348,10 +348,10 @@ struct sub_bitmaps *sub_get_bitmaps(struct dec_sub *sub, struct mp_osd_res dim,
return res;
}
-// See sub_get_bitmaps() for locking requirements.
-// It can be called unlocked too, but then only 1 thread must call this function
-// at a time (unless exclusive access is guaranteed).
-char *sub_get_text(struct dec_sub *sub, double pts)
+// This can only be called by the main thread, due to the returned text pointing
+// to a buffer bound to the sub object. The main thread is the designated
+// "outside" owner of the buffer.
+char *sub_get_text(struct dec_sub *sub, double pts, enum sd_text_type type)
{
pthread_mutex_lock(&sub->lock);
char *text = NULL;
@@ -362,7 +362,7 @@ char *sub_get_text(struct dec_sub *sub, double pts)
update_segment(sub);
if (sub->sd->driver->get_text)
- text = sub->sd->driver->get_text(sub->sd, pts);
+ text = sub->sd->driver->get_text(sub->sd, pts, type);
pthread_mutex_unlock(&sub->lock);
return text;
}
diff --git a/sub/dec_sub.h b/sub/dec_sub.h
index 8d0c76cd14..f998b59f6b 100644
--- a/sub/dec_sub.h
+++ b/sub/dec_sub.h
@@ -22,6 +22,11 @@ enum sd_ctrl {
SD_CTRL_UPDATE_OPTS,
};
+enum sd_text_type {
+ SD_TEXT_TYPE_PLAIN,
+ SD_TEXT_TYPE_ASS,
+};
+
struct sd_times {
double start;
double end;
@@ -41,7 +46,7 @@ void sub_preload(struct dec_sub *sub);
bool sub_read_packets(struct dec_sub *sub, double video_pts);
struct sub_bitmaps *sub_get_bitmaps(struct dec_sub *sub, struct mp_osd_res dim,
int format, double pts);
-char *sub_get_text(struct dec_sub *sub, double pts);
+char *sub_get_text(struct dec_sub *sub, double pts, enum sd_text_type type);
struct sd_times sub_get_times(struct dec_sub *sub, double pts);
void sub_reset(struct dec_sub *sub);
void sub_select(struct dec_sub *sub, bool selected);
diff --git a/sub/sd.h b/sub/sd.h
index d3d70bf594..38bab3aa7a 100644
--- a/sub/sd.h
+++ b/sub/sd.h
@@ -40,7 +40,7 @@ struct sd_functions {
struct sub_bitmaps *(*get_bitmaps)(struct sd *sd, struct mp_osd_res dim,
int format, double pts);
- char *(*get_text)(struct sd *sd, double pts);
+ char *(*get_text)(struct sd *sd, double pts, enum sd_text_type type);
struct sd_times (*get_times)(struct sd *sd, double pts);
};
diff --git a/sub/sd_ass.c b/sub/sd_ass.c
index d51f892dd4..46f16908b0 100644
--- a/sub/sd_ass.c
+++ b/sub/sd_ass.c
@@ -627,7 +627,7 @@ static bool is_whitespace_only(char *s, int len)
return true;
}
-static char *get_text(struct sd *sd, double pts)
+static char *get_text_buf(struct sd *sd, double pts, enum sd_text_type type)
{
struct sd_ass_priv *ctx = sd->priv;
ASS_Track *track = ctx->ass_track;
@@ -643,7 +643,13 @@ static char *get_text(struct sd *sd, double pts)
if (ipts >= event->Start && ipts < event->Start + event->Duration) {
if (event->Text) {
int start = b.len;
- ass_to_plaintext(&b, event->Text);
+ if (type == SD_TEXT_TYPE_PLAIN) {
+ ass_to_plaintext(&b, event->Text);
+ } else {
+ char *t = event->Text;
+ while (*t)
+ append(&b, *t++);
+ }
if (is_whitespace_only(&b.start[start], b.len - start)) {
b.len = start;
} else {
@@ -661,6 +667,11 @@ static char *get_text(struct sd *sd, double pts)
return ctx->last_text;
}
+static char *get_text(struct sd *sd, double pts, enum sd_text_type type)
+{
+ return talloc_strdup(NULL, get_text_buf(sd, pts, type));
+}
+
static struct sd_times get_times(struct sd *sd, double pts)
{
struct sd_ass_priv *ctx = sd->priv;
@@ -697,7 +708,7 @@ static void fill_plaintext(struct sd *sd, double pts)
ass_flush_events(track);
- char *text = get_text(sd, pts);
+ char *text = get_text_buf(sd, pts, SD_TEXT_TYPE_PLAIN);
if (!text)
return;