summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--core/command.c20
-rw-r--r--core/mp_core.h6
-rw-r--r--core/mplayer.c147
-rw-r--r--core/mplayer.h3
-rw-r--r--sub/dec_sub.c24
-rw-r--r--sub/dec_sub.h5
-rw-r--r--sub/find_sub.c174
-rw-r--r--sub/osd_libass.c12
-rw-r--r--sub/sd.h4
-rw-r--r--sub/sd_ass.c102
-rw-r--r--sub/sd_lavc.c6
-rw-r--r--sub/sub.c39
-rw-r--r--sub/sub.h8
-rw-r--r--sub/subreader.c102
-rw-r--r--sub/subreader.h6
16 files changed, 214 insertions, 445 deletions
diff --git a/Makefile b/Makefile
index 1662f6f1e1..f7b94f44e9 100644
--- a/Makefile
+++ b/Makefile
@@ -227,7 +227,6 @@ SOURCES = talloc.c \
stream/url.c \
sub/dec_sub.c \
sub/draw_bmp.c \
- sub/find_sub.c \
sub/find_subfiles.c \
sub/img_convert.c \
sub/sd_lavc.c \
diff --git a/core/command.c b/core/command.c
index 3ee8f39c3d..7eb36be5f3 100644
--- a/core/command.c
+++ b/core/command.c
@@ -1307,7 +1307,6 @@ static int mp_property_sub_visibility(m_option_t *prop, int action,
switch (action) {
case M_PROPERTY_SET:
opts->sub_visibility = *(int *)arg;
- vo_osd_changed(OSDTYPE_SUBTITLE);
if (vo_spudec)
vo_osd_changed(OSDTYPE_SPU);
return M_PROPERTY_OK;
@@ -1991,26 +1990,18 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd)
}
case MP_CMD_SUB_STEP:
+#ifdef CONFIG_ASS
if (sh_video) {
int movement = cmd->args[0].v.i;
- struct track *track = mpctx->current_track[STREAM_SUB];
- bool available = false;
- if (track && track->subdata) {
- available = true;
- step_sub(track->subdata, mpctx->video_pts, movement);
- }
-#ifdef CONFIG_ASS
struct ass_track *ass_track = sub_get_ass_track(mpctx->osd);
if (ass_track) {
- available = true;
+ set_osd_tmsg(mpctx, OSD_MSG_SUB_DELAY, osdl, osd_duration,
+ "Sub delay: %d ms", ROUND(sub_delay * 1000));
sub_delay += ass_step_sub(ass_track,
(mpctx->video_pts + sub_delay) * 1000 + .5, movement) / 1000.;
}
-#endif
- if (available)
- set_osd_tmsg(mpctx, OSD_MSG_SUB_DELAY, osdl, osd_duration,
- "Sub delay: %d ms", ROUND(sub_delay * 1000));
}
+#endif
break;
case MP_CMD_OSD: {
@@ -2194,7 +2185,6 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd)
if (tv_channel_list) {
set_osd_tmsg(mpctx, OSD_MSG_TV_CHANNEL, osdl, osd_duration,
"Channel: %s", tv_channel_current->name);
- //vo_osd_changed(OSDTYPE_SUBTITLE);
}
}
#ifdef CONFIG_PVR
@@ -2232,7 +2222,6 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd)
if (tv_channel_list) {
set_osd_tmsg(mpctx, OSD_MSG_TV_CHANNEL, osdl, osd_duration,
"Channel: %s", tv_channel_current->name);
- //vo_osd_changed(OSDTYPE_SUBTITLE);
}
}
#ifdef CONFIG_PVR
@@ -2265,7 +2254,6 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd)
if (tv_channel_list) {
set_osd_tmsg(mpctx, OSD_MSG_TV_CHANNEL, osdl, osd_duration,
"Channel: %s", tv_channel_current->name);
- //vo_osd_changed(OSDTYPE_SUBTITLE);
}
}
#ifdef CONFIG_PVR
diff --git a/core/mp_core.h b/core/mp_core.h
index 9e61c8ffa3..665588c5c0 100644
--- a/core/mp_core.h
+++ b/core/mp_core.h
@@ -22,8 +22,6 @@
#include <stdbool.h>
#include "core/options.h"
-#include "sub/subreader.h"
-#include "sub/find_subfiles.h"
#include "audio/mixer.h"
#include "demux/demux.h"
@@ -112,9 +110,6 @@ struct track {
// External text subtitle using libass subtitle renderer.
// The sh_sub is a dummy and doesn't belong to a demuxer.
struct sh_sub *sh_sub;
-
- // External text subtitle using non-libass subtitle renderer.
- struct sub_data *subdata;
};
enum {
@@ -129,7 +124,6 @@ typedef struct MPContext {
struct osd_state *osd;
struct mp_osd_msg *osd_msg_stack;
char *terminal_osd_text;
- subtitle subs; // subtitle list used when reading subtitles from demuxer
int add_osd_seek_info; // bitfield of enum mp_osd_seek_info
double osd_visible; // for the osd bar only
diff --git a/core/mplayer.c b/core/mplayer.c
index 52aa34058c..602d1f0616 100644
--- a/core/mplayer.c
+++ b/core/mplayer.c
@@ -74,6 +74,7 @@
#include "sub/subreader.h"
#include "sub/find_subfiles.h"
#include "sub/dec_sub.h"
+#include "sub/sd.h"
#include "core/mp_osd.h"
#include "video/out/vo.h"
@@ -284,8 +285,6 @@ static void print_stream(struct MPContext *mpctx, struct track *t)
const char *codec = s ? s->codec : NULL;
if (!codec && t->sh_sub) // external subs hack
codec = t->sh_sub->gsh->codec;
- if (!codec && t->subdata)
- codec = t->subdata->codec;
mp_msg(MSGT_CPLAYER, MSGL_INFO, " (%s)", codec ? codec : "<unknown>");
if (t->is_external)
mp_msg(MSGT_CPLAYER, MSGL_INFO, " (external)");
@@ -1052,38 +1051,36 @@ struct track *mp_add_subtitles(struct MPContext *mpctx, char *filename,
float fps, int noerr)
{
struct MPOpts *opts = &mpctx->opts;
- sub_data *subd = NULL;
struct sh_sub *sh = NULL;
+ struct ass_track *asst = NULL;
+ const char *codec = NULL;
if (filename == NULL)
return NULL;
- if (opts->ass_enabled) {
+ // Note: no text subtitles without libass. This is mainly because sd_ass is
+ // used for rendering. Even when showing subtitles with term-osd, going
+ // through sd_ass makes the code much simpler, as sd_ass can handle all
+ // the weird special-cases.
#ifdef CONFIG_ASS
- struct ass_track *asst = mp_ass_read_stream(mpctx->ass_library,
- filename, sub_cp);
- bool is_native_ass = asst;
- const char *codec = NULL;
- if (!asst) {
- subd = sub_read_file(filename, fps, &mpctx->opts);
- if (subd) {
- codec = subd->codec;
- asst = mp_ass_read_subdata(mpctx->ass_library, opts, subd, fps);
- talloc_free(subd);
- subd = NULL;
- }
- }
- if (asst) {
- sh = sd_ass_create_from_track(asst, is_native_ass, opts);
- if (codec)
- sh->gsh->codec = codec;
+ if (opts->ass_enabled) {
+ asst = mp_ass_read_stream(mpctx->ass_library, filename, sub_cp);
+ codec = "ass";
+ }
+ if (!asst) {
+ sub_data *subd = sub_read_file(filename, fps, &mpctx->opts);
+ if (subd) {
+ codec = subd->codec;
+ asst = mp_ass_read_subdata(mpctx->ass_library, opts, subd, fps);
}
+ talloc_free(subd);
+ }
+ if (asst)
+ sh = sd_ass_create_from_track(asst, codec, opts);
#endif
- } else
- subd = sub_read_file(filename, fps, &mpctx->opts);
-
- if (!sh && !subd) {
+ if (!sh) {
+ // Used with image subtitles.
struct track *ext = open_external_file(mpctx, filename, NULL, 0,
STREAM_SUB);
if (ext)
@@ -1101,7 +1098,6 @@ struct track *mp_add_subtitles(struct MPContext *mpctx, char *filename,
.demuxer_id = -1,
.is_external = true,
.sh_sub = talloc_steal(track, sh),
- .subdata = talloc_steal(track, subd),
.external_filename = talloc_strdup(track, filename),
};
MP_TARRAY_APPEND(mpctx, mpctx->tracks, mpctx->num_tracks, track);
@@ -1545,23 +1541,16 @@ void set_osd_function(struct MPContext *mpctx, int osd_function)
/**
* \brief Display text subtitles on the OSD
*/
-void set_osd_subtitle(struct MPContext *mpctx, subtitle *subs)
-{
- int i;
- vo_sub = subs;
- vo_osd_changed(OSDTYPE_SUBTITLE);
- if (!mpctx->sh_video) {
- // reverse order, since newest set_osd_msg is displayed first
- for (i = SUB_MAX_TEXT - 1; i >= 0; i--) {
- if (!subs || i >= subs->lines || !subs->text[i])
- rm_osd_msg(mpctx, OSD_MSG_SUB_BASE + i);
- else {
- // HACK: currently display time for each sub line
- // except the last is set to 2 seconds.
- int display_time = i == subs->lines - 1 ? 180000 : 2000;
- set_osd_msg(mpctx, OSD_MSG_SUB_BASE + i, 1, display_time,
- "%s", subs->text[i]);
- }
+static void set_osd_subtitle(struct MPContext *mpctx, const char *text)
+{
+ if (!text)
+ text = "";
+ if (strcmp(mpctx->osd->sub_text, text) != 0) {
+ osd_set_sub(mpctx->osd, text);
+ if (!mpctx->sh_video) {
+ rm_osd_msg(mpctx, OSD_MSG_SUB_BASE);
+ if (text && text[0])
+ set_osd_msg(mpctx, OSD_MSG_SUB_BASE, 1, INT_MAX, "%s", text);
}
}
}
@@ -1877,9 +1866,7 @@ static void reset_subtitles(struct MPContext *mpctx)
{
if (mpctx->sh_sub)
sub_reset(mpctx->sh_sub, mpctx->osd);
- sub_clear_text(&mpctx->subs, MP_NOPTS_VALUE);
- if (vo_sub)
- set_osd_subtitle(mpctx, NULL);
+ set_osd_subtitle(mpctx, NULL);
if (vo_spudec) {
spudec_reset(vo_spudec);
vo_osd_changed(OSDTYPE_SPU);
@@ -1888,33 +1875,22 @@ static void reset_subtitles(struct MPContext *mpctx)
static void update_subtitles(struct MPContext *mpctx, double refpts_tl)
{
- struct MPOpts *opts = &mpctx->opts;
- struct sh_video *sh_video = mpctx->sh_video;
struct sh_sub *sh_sub = mpctx->sh_sub;
struct demux_stream *d_sub = sh_sub ? sh_sub->ds : NULL;
unsigned char *packet = NULL;
int len;
const char *type = sh_sub ? sh_sub->gsh->codec : NULL;
- mpctx->osd->sub_offset = mpctx->video_offset;
-
struct track *track = mpctx->current_track[STREAM_SUB];
if (!track)
return;
- if (!track->under_timeline)
- mpctx->osd->sub_offset = 0;
+ double video_offset = track->under_timeline ? mpctx->video_offset : 0;
- double refpts_s = refpts_tl - mpctx->osd->sub_offset;
- double curpts_s = refpts_s + sub_delay;
+ mpctx->osd->sub_offset = video_offset - sub_delay;
- // find sub
- if (track->subdata) {
- if (sub_fps == 0)
- sub_fps = sh_video ? sh_video->fps : 25;
- find_sub(mpctx, track->subdata, curpts_s *
- (track->subdata->sub_uses_time ? 100. : sub_fps));
- }
+ double curpts_s = refpts_tl - mpctx->osd->sub_offset;
+ double refpts_s = refpts_tl - video_offset;
// DVD sub:
if (is_dvd_sub(type) && !(sh_sub && sh_sub->active)) {
@@ -1955,7 +1931,7 @@ static void update_subtitles(struct MPContext *mpctx, double refpts_tl)
if (timestamp >= 0)
spudec_assemble(vo_spudec, packet, len, timestamp);
}
- } else if (d_sub && (is_text_sub(type) || (sh_sub && sh_sub->active))) {
+ } else if (d_sub && sh_sub && sh_sub->active) {
bool non_interleaved = is_non_interleaved(mpctx, track);
if (non_interleaved)
ds_get_next_pts(d_sub);
@@ -1967,7 +1943,7 @@ static void update_subtitles(struct MPContext *mpctx, double refpts_tl)
"Sub early: c_pts=%5.3f s_pts=%5.3f\n",
curpts_s, subpts_s);
// Libass handled subs can be fed to it in advance
- if (!opts->ass_enabled || !is_text_sub(type))
+ if (!sub_accept_packets_in_advance(sh_sub))
break;
// Try to avoid demuxing whole file at once
if (non_interleaved && subpts_s > curpts_s + 1)
@@ -1984,41 +1960,19 @@ static void update_subtitles(struct MPContext *mpctx, double refpts_tl)
len = FFMIN(len - 2, AV_RB16(packet));
packet += 2;
}
- if (sh_sub && sh_sub->active) {
- sub_decode(sh_sub, mpctx->osd, packet, len, subpts_s, duration);
- } else if (subpts_s != MP_NOPTS_VALUE) {
- // text sub
- if (duration < 0)
- sub_clear_text(&mpctx->subs, MP_NOPTS_VALUE);
- if (is_ass_sub(type)) { // ssa/ass subs without libass => convert to plaintext
- int i;
- unsigned char *p = packet;
- for (i = 0; i < 8 && *p != '\0'; p++)
- if (*p == ',')
- i++;
- if (*p == '\0') /* Broken line? */
- continue;
- len -= p - packet;
- packet = p;
- }
- double endpts_s = MP_NOPTS_VALUE;
- if (subpts_s != MP_NOPTS_VALUE && duration >= 0)
- endpts_s = subpts_s + duration;
- sub_add_text(&mpctx->subs, packet, len, endpts_s);
- set_osd_subtitle(mpctx, &mpctx->subs);
- }
+ sub_decode(sh_sub, mpctx->osd, packet, len, subpts_s, duration);
if (non_interleaved)
ds_get_next_pts(d_sub);
}
- if (!opts->ass_enabled)
- if (sub_clear_text(&mpctx->subs, curpts_s))
- set_osd_subtitle(mpctx, &mpctx->subs);
}
if (vo_spudec) {
spudec_heartbeat(vo_spudec, 90000 * curpts_s);
if (spudec_changed(vo_spudec))
vo_osd_changed(OSDTYPE_SPU);
}
+
+ if (!mpctx->osd->render_bitmap_subs)
+ set_osd_subtitle(mpctx, sub_get_text(mpctx->osd, curpts_s));
}
static int check_framedrop(struct MPContext *mpctx, double frame_time)
@@ -2130,12 +2084,8 @@ static void reinit_subs(struct MPContext *mpctx)
mpctx->initialized_flags |= INITIALIZED_SUB;
- if (track->subdata || track->sh_sub) {
-#ifdef CONFIG_ASS
- if (opts->ass_enabled && track->sh_sub)
- sub_init(track->sh_sub, mpctx->osd);
-#endif
- vo_osd_changed(OSDTYPE_SUBTITLE);
+ if (track->sh_sub) {
+ sub_init(track->sh_sub, mpctx->osd);
} else if (track->stream) {
struct stream *s = track->demuxer ? track->demuxer->stream : NULL;
if (s && s->type == STREAMTYPE_DVD)
@@ -2153,6 +2103,12 @@ static void reinit_subs(struct MPContext *mpctx)
else
sub_init(mpctx->sh_sub, mpctx->osd);
}
+
+ // Decides whether to use OSD path or normal subtitle rendering path.
+ mpctx->osd->render_bitmap_subs = true;
+ struct sh_sub *sh_sub = mpctx->osd->sh_sub;
+ if (sh_sub && sh_sub->active && sh_sub->sd_driver->get_text)
+ mpctx->osd->render_bitmap_subs = opts->ass_enabled;
}
static char *track_layout_hash(struct MPContext *mpctx)
@@ -4551,7 +4507,6 @@ terminate_playback: // don't jump here after ao/vo/getch initialization!
talloc_free(mpctx->resolve_result);
mpctx->resolve_result = NULL;
- vo_sub = NULL;
#ifdef CONFIG_ASS
if (mpctx->osd->ass_renderer)
ass_renderer_done(mpctx->osd->ass_renderer);
diff --git a/core/mplayer.h b/core/mplayer.h
index b96f814b68..825458b6f5 100644
--- a/core/mplayer.h
+++ b/core/mplayer.h
@@ -25,9 +25,6 @@
struct MPContext;
struct MPOpts;
-struct subtitle;
-
-void set_osd_subtitle(struct MPContext *mpctx, struct subtitle *subs);
struct mp_resolve_result {
char *url;
diff --git a/sub/dec_sub.c b/sub/dec_sub.c
index d3cedea80d..3de7d1223d 100644
--- a/sub/dec_sub.c
+++ b/sub/dec_sub.c
@@ -51,13 +51,13 @@ bool is_dvd_sub(const char *t)
void sub_init(struct sh_sub *sh, struct osd_state *osd)
{
- struct MPOpts *opts = sh->opts;
+ const char *format = sh->gsh->codec;
assert(!osd->sh_sub);
- if (sd_lavc.probe(sh))
+ if (sd_lavc.supports_format(format))
sh->sd_driver = &sd_lavc;
#ifdef CONFIG_ASS
- if (opts->ass_enabled && sd_ass.probe(sh))
+ if (sd_ass.supports_format(format))
sh->sd_driver = &sd_ass;
#endif
if (sh->sd_driver) {
@@ -70,6 +70,11 @@ void sub_init(struct sh_sub *sh, struct osd_state *osd)
}
}
+bool sub_accept_packets_in_advance(struct sh_sub *sh)
+{
+ return sh->active && sh->sd_driver->accept_packets_in_advance;
+}
+
void sub_decode(struct sh_sub *sh, struct osd_state *osd, void *data,
int data_len, double pts, double duration)
{
@@ -101,6 +106,19 @@ void sub_get_bitmaps(struct osd_state *osd, struct mp_osd_res dim, double pts,
osd->switch_sub_id = 0;
}
+char *sub_get_text(struct osd_state *osd, double pts)
+{
+ struct MPOpts *opts = osd->opts;
+ char *text = NULL;
+ if (!opts->sub_visibility || !osd->sh_sub || !osd->sh_sub->active) {
+ // -
+ } else {
+ if (osd->sh_sub->sd_driver->get_text)
+ text = osd->sh_sub->sd_driver->get_text(osd->sh_sub, osd, pts);
+ }
+ return text;
+}
+
void sub_reset(struct sh_sub *sh, struct osd_state *osd)
{
if (sh->active && sh->sd_driver->reset)
diff --git a/sub/dec_sub.h b/sub/dec_sub.h
index 593eac1e03..52fa05eebc 100644
--- a/sub/dec_sub.h
+++ b/sub/dec_sub.h
@@ -14,18 +14,19 @@ bool is_text_sub(const char *t);
bool is_ass_sub(const char *t);
bool is_dvd_sub(const char *t);
+bool sub_accept_packets_in_advance(struct sh_sub *sh);
void sub_decode(struct sh_sub *sh, struct osd_state *osd, void *data,
int data_len, double pts, double duration);
void sub_get_bitmaps(struct osd_state *osd, struct mp_osd_res dim, double pts,
struct sub_bitmaps *res);
+char *sub_get_text(struct osd_state *osd, double pts);
void sub_init(struct sh_sub *sh, struct osd_state *osd);
void sub_reset(struct sh_sub *sh, struct osd_state *osd);
void sub_switchoff(struct sh_sub *sh, struct osd_state *osd);
void sub_uninit(struct sh_sub *sh);
struct sh_sub *sd_ass_create_from_track(struct ass_track *track,
- bool vsfilter_aspect,
- struct MPOpts *opts);
+ const char *codec, struct MPOpts *opts);
#ifdef CONFIG_ASS
struct ass_track *sub_get_ass_track(struct osd_state *osd);
diff --git a/sub/find_sub.c b/sub/find_sub.c
deleted file mode 100644
index 5feef2a3e9..0000000000
--- a/sub/find_sub.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * .SUB
- *
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "config.h"
-
-#include <stdio.h>
-
-#include "sub.h"
-#include "subreader.h"
-
-#include "core/mp_msg.h"
-#include "core/mp_common.h"
-#include "core/mplayer.h"
-
-static int current_sub=0;
-
-//static subtitle* subtitles=NULL;
-static int nosub_range_start=-1;
-static int nosub_range_end=-1;
-static const sub_data *last_sub_data = NULL;
-
-void step_sub(sub_data *subd, float pts, int movement) {
- subtitle *subs;
- int key;
-
- if (subd == NULL) return;
- subs = subd->subtitles;
- key = (pts+sub_delay) * (subd->sub_uses_time ? 100 : sub_fps);
-
- /* Tell the OSD subsystem that the OSD contents will change soon */
- vo_osd_changed(OSDTYPE_SUBTITLE);
-
- /* If we are moving forward, don't count the next (current) subtitle
- * if we haven't displayed it yet. Same when moving other direction.
- */
- if (movement > 0 && key < subs[current_sub].start)
- movement--;
- if (movement < 0 && key >= subs[current_sub].end)
- movement++;
-
- /* Never move beyond first or last subtitle. */
- if (current_sub+movement < 0)
- movement = 0-current_sub;
- if (current_sub+movement >= subd->sub_num)
- movement = subd->sub_num - current_sub - 1;
-
- current_sub += movement;
- sub_delay = subs[current_sub].start / (subd->sub_uses_time ? 100 : sub_fps) - pts;
-}
-
-void find_sub(struct MPContext *mpctx, sub_data* subd,int key){
- subtitle *subs;
- subtitle *new_sub = NULL;
- int i,j;
-
- if ( !subd || subd->sub_num == 0) return;
- subs = subd->subtitles;
-
- if (last_sub_data != subd) {
- // Sub data changed, reset nosub range.
- last_sub_data = subd;
- nosub_range_start = -1;
- nosub_range_end = -1;
- }
-
- if(vo_sub){
- if(key>=vo_sub->start && key<=vo_sub->end) return; // OK!
- } else {
- if(key>nosub_range_start && key<nosub_range_end) return; // OK!
- }
- // sub changed!
-
- /* Tell the OSD subsystem that the OSD contents will change soon */
- vo_osd_changed(OSDTYPE_SUBTITLE);
-
- if(key<=0){
- // no sub here
- goto update;
- }
-
-// printf("\r---- sub changed ----\n");
-
- // check next sub.
- if(current_sub>=0 && current_sub+1 < subd->sub_num){
- if(key>subs[current_sub].end && key<subs[current_sub+1].start){
- // no sub
- nosub_range_start=subs[current_sub].end;
- nosub_range_end=subs[current_sub+1].start;
- goto update;
- }
- // next sub?
- ++current_sub;
- new_sub=&subs[current_sub];
- if(key>=new_sub->start && key<=new_sub->end) goto update; // OK!
- }
-
-// printf("\r---- sub log search... ----\n");
-
- // use logarithmic search:
- i=0;
- j = subd->sub_num - 1;
-// printf("Searching %d in %d..%d\n",key,subs[i].start,subs[j].end);
- while(j>=i){
- current_sub=(i+j+1)/2;
- new_sub=&subs[current_sub];
- if(key<new_sub->start) j=current_sub-1;
- else if(key>new_sub->end) i=current_sub+1;
- else goto update; // found!
- }
-// if(key>=new_sub->start && key<=new_sub->end) return; // OK!
-
- // check where are we...
- if(key<new_sub->start){
- if(current_sub<=0){
- // before the first sub
- nosub_range_start=key-1; // tricky
- nosub_range_end=new_sub->start;
-// printf("FIRST... key=%d end=%d \n",key,new_sub->start);
- new_sub=NULL;
- goto update;
- }
- --current_sub;
- if(key>subs[current_sub].end && key<subs[current_sub+1].start){
- // no sub
- nosub_range_start=subs[current_sub].end;
- nosub_range_end=subs[current_sub+1].start;
-// printf("No sub... 1 \n");
- new_sub=NULL;
- goto update;
- }
- printf("HEH???? ");
- } else {
- if(key<=new_sub->end) printf("JAJJ! "); else
- if(current_sub+1 >= subd->sub_num){
- // at the end?
- nosub_range_start=new_sub->end;
- nosub_range_end=0x7FFFFFFF; // MAXINT
-// printf("END!?\n");
- new_sub=NULL;
- goto update;
- } else
- if(key>subs[current_sub].end && key<subs[current_sub+1].start){
- // no sub
- nosub_range_start=subs[current_sub].end;
- nosub_range_end=subs[current_sub+1].start;
-// printf("No sub... 2 \n");
- new_sub=NULL;
- goto update;
- }
- }
-
- mp_msg(MSGT_FIXME,MSGL_FIXME,"SUB ERROR: %d ? %d --- %d [%d] \n",key,(int)new_sub->start,(int)new_sub->end,current_sub);
-
- new_sub=NULL; // no sub here
-update:
- set_osd_subtitle(mpctx, new_sub);
-}
diff --git a/sub/osd_libass.c b/sub/osd_libass.c
index d157f7925c..d8496c2f3b 100644
--- a/sub/osd_libass.c
+++ b/sub/osd_libass.c
@@ -354,7 +354,7 @@ static void update_sub(struct osd_state *osd, struct osd_object *obj)
clear_obj(obj);
- if (!(vo_sub && opts->sub_visibility))
+ if (!osd->sub_text || !osd->sub_text[0])
return;
if (!obj->osd_track)
@@ -370,15 +370,9 @@ static void update_sub(struct osd_state *osd, struct osd_object *obj)
ass_set_line_position(osd->osd_render, 100 - sub_pos);
#endif
- char *text = talloc_strdup(NULL, "");
-
- for (int n = 0; n < vo_sub->lines; n++)
- text = talloc_asprintf_append_buffer(text, "%s\n", vo_sub->text[n]);
-
- char *escaped_text = mangle_ass(text);
+ char *escaped_text = mangle_ass(osd->sub_text);
add_osd_ass_event(obj->osd_track, escaped_text);
talloc_free(escaped_text);
- talloc_free(text);
}
static void update_object(struct osd_state *osd, struct osd_object *obj)
@@ -387,7 +381,7 @@ static void update_object(struct osd_state *osd, struct osd_object *obj)
case OSDTYPE_OSD:
update_osd(osd, obj);
break;
- case OSDTYPE_SUBTITLE:
+ case OSDTYPE_SUBTEXT:
update_sub(osd, obj);
break;
case OSDTYPE_PROGBAR:
diff --git a/sub/sd.h b/sub/sd.h
index 881c429689..123a9bc45d 100644
--- a/sub/sd.h
+++ b/sub/sd.h
@@ -4,13 +4,15 @@
#include "dec_sub.h"
struct sd_functions {
- bool (*probe)(struct sh_sub *sh);
+ bool accept_packets_in_advance;
+ bool (*supports_format)(const char *format);
int (*init)(struct sh_sub *sh, struct osd_state *osd);
void (*decode)(struct sh_sub *sh, struct osd_state *osd,
void *data, int data_len, double pts, double duration);
void (*get_bitmaps)(struct sh_sub *sh, struct osd_state *osd,
struct mp_osd_res dim, double pts,
struct sub_bitmaps *res);
+ char *(*get_text)(struct sh_sub *sh, struct osd_state *osd, double pts);
void (*reset)(struct sh_sub *sh, struct osd_state *osd);
void (*switch_off)(struct sh_sub *sh, struct osd_state *osd);
void (*uninit)(struct sh_sub *sh);
diff --git a/sub/sd_ass.c b/sub/sd_ass.c
index 8d17835809..1501f5da54 100644
--- a/sub/sd_ass.c
+++ b/sub/sd_ass.c
@@ -17,10 +17,11 @@
*/
#include <stdlib.h>
-#include <ass/ass.h>
#include <assert.h>
#include <string.h>
+#include <ass/ass.h>
+
#include "talloc.h"
#include "core/options.h"
@@ -39,11 +40,12 @@ struct sd_ass_priv {
bool incomplete_event;
struct sub_bitmap *parts;
bool flush_on_seek;
+ char last_text[500];
};
-static bool probe(struct sh_sub *sh)
+static bool supports_format(const char *format)
{
- return is_text_sub(sh->gsh->codec);
+ return is_text_sub(format);
}
static void free_last_event(ASS_Track *track)
@@ -163,6 +165,89 @@ static void get_bitmaps(struct sh_sub *sh, struct osd_state *osd,
talloc_steal(ctx, ctx->parts);
}
+struct buf {
+ char *start;
+ int size;
+ int len;
+};
+
+static void append(struct buf *b, char c)
+{
+ if (b->len < b->size) {
+ b->start[b->len] = c;
+ b->len++;
+ }
+}
+
+static void ass_to_plaintext(struct buf *b, const char *in)
+{
+ bool in_tag = false;
+ bool in_drawing = false;
+ while (*in) {
+ if (in_tag) {
+ if (in[0] == '}') {
+ in += 1;
+ in_tag = false;
+ } else if (in[0] == '\\' && in[1] == 'p') {
+ in += 2;
+ // skip text between \pN and \p0 tags
+ if (in[0] == '0') {
+ in_drawing = false;
+ } else if (in[0] >= '1' && in[0] <= '9') {
+ in_drawing = true;
+ }
+ } else {
+ in += 1;
+ }
+ } else {
+ if (in[0] == '\\' && (in[1] == 'N' || in[1] == 'n')) {
+ in += 2;
+ append(b, '\n');
+ } else if (in[0] == '\\' && in[1] == 'h') {
+ in += 2;
+ append(b, ' ');
+ } else if (in[0] == '{') {
+ in += 1;
+ in_tag = true;
+ } else {
+ if (!in_drawing)
+ append(b, in[0]);
+ in += 1;
+ }
+ }
+ }
+}
+
+static char *get_text(struct sh_sub *sh, struct osd_state *osd, double pts)
+{
+ struct sd_ass_priv *ctx = sh->context;
+ ASS_Track *track = ctx->ass_track;
+
+ if (pts == MP_NOPTS_VALUE)
+ return NULL;
+
+ struct buf b = {ctx->last_text, sizeof(ctx->last_text) - 1};
+
+ for (int i = 0; i < track->n_events; ++i) {
+ ASS_Event *event = track->events + i;
+ double start = event->Start / 1000.0;
+ double end = (event->Start + event->Duration) / 1000.0;
+ if (pts >= start && pts < end) {
+ if (event->Text) {
+ ass_to_plaintext(&b, event->Text);
+ append(&b, '\n');
+ }
+ }
+ }
+
+ b.start[b.len] = '\0';
+
+ if (b.len > 0 && b.start[b.len - 1] == '\n')
+ b.start[b.len - 1] = '\0';
+
+ return ctx->last_text;
+}
+
static void reset(struct sh_sub *sh, struct osd_state *osd)
{
struct sd_ass_priv *ctx = sh->context;
@@ -183,10 +268,12 @@ static void uninit(struct sh_sub *sh)
}
const struct sd_functions sd_ass = {
- .probe = probe,
+ .accept_packets_in_advance = true,
+ .supports_format = supports_format,
.init = init,
.decode = decode,
.get_bitmaps = get_bitmaps,
+ .get_text = get_text,
.reset = reset,
.switch_off = reset,
.uninit = uninit,
@@ -199,20 +286,19 @@ static int sd_ass_track_destructor(void *ptr)
}
struct sh_sub *sd_ass_create_from_track(struct ass_track *track,
- bool vsfilter_aspect,
- struct MPOpts *opts)
+ const char *codec, struct MPOpts *opts)
{
struct sh_sub *sh = talloc(NULL, struct sh_sub);
talloc_set_destructor(sh, sd_ass_track_destructor);
*sh = (struct sh_sub) {
.opts = opts,
.gsh = talloc_struct(sh, struct sh_stream, {
- .codec = "ass",
+ .codec = codec,
}),
.sd_driver = &sd_ass,
.context = talloc_struct(sh, struct sd_ass_priv, {
.ass_track = track,
- .vsfilter_aspect = vsfilter_aspect,
+ .vsfilter_aspect = is_ass_sub(codec),
}),
.initialized = true,
};
diff --git a/sub/sd_lavc.c b/sub/sd_lavc.c
index 1665e36749..e067da6a43 100644
--- a/sub/sd_lavc.c
+++ b/sub/sd_lavc.c
@@ -41,9 +41,9 @@ struct sd_lavc_priv {
double endpts;
};
-static bool probe(struct sh_sub *sh)
+static bool supports_format(const char *format)
{
- enum AVCodecID cid = mp_codec_to_av_codec_id(sh->gsh->codec);
+ enum AVCodecID cid = mp_codec_to_av_codec_id(format);
// Supported codecs must be known to decode to paletted bitmaps
switch (cid) {
case AV_CODEC_ID_DVB_SUBTITLE:
@@ -241,7 +241,7 @@ static void uninit(struct sh_sub *sh)
}
const struct sd_functions sd_lavc = {
- .probe = probe,
+ .supports_format = supports_format,
.init = init,
.decode = decode,
.get_bitmaps = get_bitmaps,
diff --git a/sub/sub.c b/sub/sub.c
index 7111f39434..4e5420627c 100644
--- a/sub/sub.c
+++ b/sub/sub.c
@@ -45,8 +45,6 @@
int sub_pos=100;
int sub_visibility=1;