summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile3
-rw-r--r--command.c10
-rw-r--r--libmpdemux/demuxer.c20
-rw-r--r--libmpdemux/stheader.h5
-rw-r--r--mp_core.h1
-rw-r--r--mplayer.c60
-rw-r--r--sub/dec_sub.c72
-rw-r--r--sub/dec_sub.h14
-rw-r--r--sub/sd.h16
-rw-r--r--sub/sd_ass.c98
10 files changed, 244 insertions, 55 deletions
diff --git a/Makefile b/Makefile
index da2033392b..9f5dbc6f23 100644
--- a/Makefile
+++ b/Makefile
@@ -132,6 +132,7 @@ SRCS_COMMON-$(LADSPA) += libaf/af_ladspa.c
SRCS_COMMON-$(LIBA52) += libmpcodecs/ad_liba52.c
SRCS_COMMON-$(LIBASS) += ass_mp.c \
libmpcodecs/vf_ass.c \
+ sub/sd_ass.c \
SRCS_COMMON-$(LIBBLURAY) += stream/stream_bluray.c
SRCS_COMMON-$(LIBBS2B) += libaf/af_bs2b.c
@@ -515,6 +516,7 @@ SRCS_COMMON = asxparser.c \
stream/stream_mf.c \
stream/stream_null.c \
stream/url.c \
+ sub/dec_sub.c \
$(SRCS_COMMON-yes)
@@ -687,6 +689,7 @@ DIRS = . \
stream/freesdp \
stream/librtsp \
stream/realrtsp \
+ sub \
tremor \
TOOLS \
vidix \
diff --git a/command.c b/command.c
index 5474b92fed..40ea205c00 100644
--- a/command.c
+++ b/command.c
@@ -32,6 +32,7 @@
#include "codec-cfg.h"
#include "mplayer.h"
#include "libvo/sub.h"
+#include "sub/dec_sub.h"
#include "m_option.h"
#include "m_property.h"
#include "m_config.h"
@@ -1656,6 +1657,7 @@ static int mp_property_sub(m_option_t *prop, int action, void *arg,
d_sub->id = -2;
}
mpctx->osd->ass_track = NULL;
+ uninit_player(mpctx, INITIALIZED_SUB);
if (source == SUB_SOURCE_VOBSUB) {
vobsub_id = vobsub_get_id_by_index(vo_vobsub, source_pos);
@@ -1690,10 +1692,10 @@ static int mp_property_sub(m_option_t *prop, int action, void *arg,
sh_sub_t *sh = d_sub->sh;
if (sh->type == 'v')
init_vo_spudec(mpctx);
-#ifdef CONFIG_ASS
- else if (opts->ass_enabled)
- mpctx->osd->ass_track = sh->ass_track;
-#endif
+ else {
+ sub_init(sh, mpctx->osd);
+ mpctx->initialized_flags |= INITIALIZED_SUB;
+ }
} else {
d_sub->id = -2;
d_sub->sh = NULL;
diff --git a/libmpdemux/demuxer.c b/libmpdemux/demuxer.c
index dc5d8858bc..c45cb18729 100644
--- a/libmpdemux/demuxer.c
+++ b/libmpdemux/demuxer.c
@@ -43,8 +43,6 @@
#include "libmpcodecs/dec_teletext.h"
#include "libmpcodecs/vd_ffmpeg.h"
-#include "ass_mp.h"
-
#ifdef CONFIG_FFMPEG
#include "libavcodec/avcodec.h"
#if MP_INPUT_BUFFER_PADDING_SIZE < FF_INPUT_BUFFER_PADDING_SIZE
@@ -295,10 +293,6 @@ static void free_sh_sub(sh_sub_t *sh)
{
mp_msg(MSGT_DEMUXER, MSGL_DBG2, "DEMUXER: freeing sh_sub at %p\n", sh);
free(sh->extradata);
-#ifdef CONFIG_ASS
- if (sh->ass_track)
- ass_free_track(sh->ass_track);
-#endif
free(sh->lang);
#ifdef CONFIG_FFMPEG
clear_parser((sh_common_t *)sh);
@@ -998,20 +992,6 @@ static struct demuxer *demux_open_stream(struct MPOpts *opts,
sh_video->fps, sh_video->i_bps * 0.008f,
sh_video->i_bps / 1024.0f);
}
-#ifdef CONFIG_ASS
- if (opts->ass_enabled && ass_library) {
- for (int i = 0; i < MAX_S_STREAMS; ++i) {
- sh_sub_t *sh = demuxer->s_streams[i];
- if (sh && sh->type == 'a') {
- sh->ass_track = ass_new_track(ass_library);
- if (sh->ass_track && sh->extradata)
- ass_process_codec_private(sh->ass_track, sh->extradata,
- sh->extradata_len);
- } else if (sh && sh->type != 'v')
- sh->ass_track = ass_default_track(ass_library);
- }
- }
-#endif
return demuxer;
}
diff --git a/libmpdemux/stheader.h b/libmpdemux/stheader.h
index 4bb2da3ac7..dc84518abc 100644
--- a/libmpdemux/stheader.h
+++ b/libmpdemux/stheader.h
@@ -19,6 +19,8 @@
#ifndef MPLAYER_STHEADER_H
#define MPLAYER_STHEADER_H
+#include <stdbool.h>
+
#include "aviheader.h"
#include "ms_hdr.h"
struct MPOpts;
@@ -135,9 +137,10 @@ typedef struct sh_sub {
SH_COMMON
int sid;
char type; // t = text, v = VobSub, a = SSA/ASS
+ bool active; // after track switch decoder may stay initialized, not active
unsigned char* extradata; // extra header data passed from demuxer
int extradata_len;
- struct ass_track *ass_track; // for SSA/ASS streams (type == 'a')
+ const struct sd_functions *sd_driver;
} sh_sub_t;
// demuxer.c:
diff --git a/mp_core.h b/mp_core.h
index 51337b4ee1..3e8b17132a 100644
--- a/mp_core.h
+++ b/mp_core.h
@@ -37,6 +37,7 @@
#define INITIALIZED_DEMUXER 512
#define INITIALIZED_ACODEC 1024
#define INITIALIZED_VCODEC 2048
+#define INITIALIZED_SUB 4096
#define INITIALIZED_ALL 0xFFFF
diff --git a/mplayer.c b/mplayer.c
index 59ce629300..ecdc4e11af 100644
--- a/mplayer.c
+++ b/mplayer.c
@@ -72,6 +72,7 @@
#include "libavutil/avstring.h"
#include "subreader.h"
+#include "sub/dec_sub.h"
#include "mp_osd.h"
#include "libvo/video_out.h"
@@ -601,6 +602,15 @@ static void mp_dvdnav_context_free(MPContext *ctx){
}
#endif
+static void uninit_subs(struct demuxer *demuxer)
+{
+ for (int i = 0; i < MAX_S_STREAMS; i++) {
+ struct sh_sub *sh = demuxer->s_streams[i];
+ if (sh && sh->initialized)
+ sub_uninit(sh);
+ }
+}
+
void uninit_player(struct MPContext *mpctx, unsigned int mask){
mask &= mpctx->initialized_flags;
@@ -614,6 +624,12 @@ void uninit_player(struct MPContext *mpctx, unsigned int mask){
mpctx->mixer.afilter = NULL;
}
+ if (mask & INITIALIZED_SUB) {
+ mpctx->initialized_flags &= ~INITIALIZED_SUB;
+ if (mpctx->d_sub->sh)
+ sub_switchoff(mpctx->d_sub->sh, mpctx->osd);
+ }
+
if(mask&INITIALIZED_VCODEC){
mpctx->initialized_flags&=~INITIALIZED_VCODEC;
current_module="uninit_vcodec";
@@ -630,6 +646,7 @@ void uninit_player(struct MPContext *mpctx, unsigned int mask){
if (mpctx->num_sources) {
mpctx->demuxer = mpctx->sources[0].demuxer;
for (int i = 1; i < mpctx->num_sources; i++) {
+ uninit_subs(mpctx->sources[i].demuxer);
free_stream(mpctx->sources[i].stream);
free_demuxer(mpctx->sources[i].demuxer);
}
@@ -646,6 +663,7 @@ void uninit_player(struct MPContext *mpctx, unsigned int mask){
mpctx->video_offset = 0;
if(mpctx->demuxer){
mpctx->stream=mpctx->demuxer->stream;
+ uninit_subs(mpctx->demuxer);
free_demuxer(mpctx->demuxer);
}
mpctx->demuxer=NULL;
@@ -1802,11 +1820,6 @@ double playing_audio_pts(struct MPContext *mpctx)
mpctx->audio_out->get_delay();
}
-static bool is_text_sub(int type)
-{
- return type == 't' || type == 'm' || type == 'a';
-}
-
static bool is_av_sub(int type)
{
return type == 'b' || type == 'p' || type == 'x';
@@ -1821,9 +1834,12 @@ void update_subtitles(struct MPContext *mpctx, double refpts,
double curpts = refpts + sub_delay;
unsigned char *packet=NULL;
int len;
- int type = d_sub->sh ? ((sh_sub_t *)d_sub->sh)->type : 'v';
+ struct sh_sub *sh_sub = d_sub->sh;
+ int type = sh_sub ? sh_sub->type : 'v';
static subtitle subs;
if (reset) {
+ if (sh_sub)
+ sub_reset(sh_sub, mpctx->osd);
sub_clear_text(&subs, MP_NOPTS_VALUE);
if (vo_sub)
set_osd_subtitle(mpctx, NULL);
@@ -1833,7 +1849,7 @@ void update_subtitles(struct MPContext *mpctx, double refpts,
}
#ifdef CONFIG_FFMPEG
if (is_av_sub(type))
- reset_avsub(d_sub->sh);
+ reset_avsub(sh_sub);
#endif
return;
}
@@ -1915,7 +1931,7 @@ void update_subtitles(struct MPContext *mpctx, double refpts,
len = ds_get_packet_sub(d_sub, &packet);
if (is_av_sub(type)) {
#ifdef CONFIG_FFMPEG
- decode_avsub(d_sub->sh, packet, len, subpts, endpts);
+ decode_avsub(sh_sub, packet, len, subpts, endpts);
#endif
continue;
}
@@ -1940,29 +1956,13 @@ void update_subtitles(struct MPContext *mpctx, double refpts,
}
continue;
}
-#ifdef CONFIG_ASS
- if (opts->ass_enabled) {
- sh_sub_t* sh = d_sub->sh;
- mpctx->osd->ass_track = sh ? sh->ass_track : NULL;
- if (!mpctx->osd->ass_track) continue;
- if (type == 'a') { // ssa/ass subs with libass
- ass_process_chunk(mpctx->osd->ass_track, packet, len,
- (long long)(subpts*1000 + 0.5),
- (long long)((endpts-subpts)*1000 + 0.5));
- } else { // plaintext subs with libass
- if (subpts != MP_NOPTS_VALUE) {
- subtitle tmp_subs = {0};
- if (endpts == MP_NOPTS_VALUE) endpts = subpts + 3;
- sub_add_text(&tmp_subs, packet, len, endpts);
- tmp_subs.start = subpts * 100;
- tmp_subs.end = endpts * 100;
- ass_process_subtitle(mpctx->osd->ass_track, &tmp_subs);
- sub_clear_text(&tmp_subs, MP_NOPTS_VALUE);
- }
- }
+ if (sh_sub && sh_sub->active) {
+ double duration = -1;
+ if (endpts != MP_NOPTS_VALUE)
+ duration = endpts - subpts;
+ sub_decode(sh_sub, mpctx->osd, packet, len, subpts, duration);
continue;
}
-#endif
if (subpts != MP_NOPTS_VALUE) {
if (endpts == MP_NOPTS_VALUE)
sub_clear_text(&subs, MP_NOPTS_VALUE);
@@ -3024,7 +3024,7 @@ static bool timeline_set_part(struct MPContext *mpctx, int i)
mpctx->video_offset = n->start - n->source_start;
if (n->source == p->source)
return false;
- uninit_player(mpctx, INITIALIZED_VCODEC | (mpctx->opts.fixed_vo && mpctx->opts.video_id != -2 ? 0 : INITIALIZED_VO) | INITIALIZED_AO | INITIALIZED_ACODEC);
+ uninit_player(mpctx, INITIALIZED_VCODEC | (mpctx->opts.fixed_vo && mpctx->opts.video_id != -2 ? 0 : INITIALIZED_VO) | INITIALIZED_AO | INITIALIZED_ACODEC | INITIALIZED_SUB);
mpctx->demuxer = n->source->demuxer;
mpctx->d_video = mpctx->demuxer->video;
mpctx->d_audio = mpctx->demuxer->audio;
diff --git a/sub/dec_sub.c b/sub/dec_sub.c
new file mode 100644
index 0000000000..6a6d1d77e5
--- /dev/null
+++ b/sub/dec_sub.c
@@ -0,0 +1,72 @@
+/*
+ * 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 <stdlib.h>
+#include <stdbool.h>
+#include <assert.h>
+
+#include "config.h"
+#include "libmpdemux/stheader.h"
+#include "sd.h"
+#include "dec_sub.h"
+#include "options.h"
+
+extern const struct sd_functions sd_ass;
+
+void sub_init(struct sh_sub *sh, struct osd_state *osd)
+{
+ struct MPOpts *opts = sh->opts;
+
+#ifdef CONFIG_ASS
+ if (opts->ass_enabled && is_text_sub(sh->type))
+ sh->sd_driver = &sd_ass;
+#endif
+ if (sh->sd_driver) {
+ sh->sd_driver->init(sh, osd);
+ sh->initialized = true;
+ sh->active = true;
+ }
+}
+
+void sub_decode(struct sh_sub *sh, struct osd_state *osd, void *data,
+ int data_len, double pts, double duration)
+{
+ if (sh->active && sh->sd_driver->decode)
+ sh->sd_driver->decode(sh, osd, data, data_len, pts, duration);
+}
+
+void sub_reset(struct sh_sub *sh, struct osd_state *osd)
+{
+ if (sh->active && sh->sd_driver->reset)
+ sh->sd_driver->reset(sh, osd);
+}
+
+void sub_switchoff(struct sh_sub *sh, struct osd_state *osd)
+{
+ if (sh->active && sh->sd_driver->switch_off)
+ sh->sd_driver->switch_off(sh, osd);
+ sh->active = false;
+}
+
+void sub_uninit(struct sh_sub *sh)
+{
+ assert (!sh->active);
+ if (sh->initialized && sh->sd_driver->uninit)
+ sh->sd_driver->uninit(sh);
+ sh->initialized = false;
+}
diff --git a/sub/dec_sub.h b/sub/dec_sub.h
new file mode 100644
index 0000000000..d6fbef25f0
--- /dev/null
+++ b/sub/dec_sub.h
@@ -0,0 +1,14 @@
+struct sh_sub;
+struct osd_state;
+
+static inline bool is_text_sub(int type)
+{
+ return type == 't' || type == 'm' || type == 'a';
+}
+
+void sub_decode(struct sh_sub *sh, struct osd_state *osd, void *data,
+ int data_len, double pts, double duration);
+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);
diff --git a/sub/sd.h b/sub/sd.h
new file mode 100644
index 0000000000..d5aea5c1a6
--- /dev/null
+++ b/sub/sd.h
@@ -0,0 +1,16 @@
+#ifndef MPLAYER_SD_H
+#define MPLAYER_SD_H
+
+struct osd_state;
+struct sh_sub;
+
+struct sd_functions {
+ void (*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 (*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);
+};
+
+#endif
diff --git a/sub/sd_ass.c b/sub/sd_ass.c
new file mode 100644
index 0000000000..a25d50a805
--- /dev/null
+++ b/sub/sd_ass.c
@@ -0,0 +1,98 @@
+/*
+ * 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 <stdlib.h>
+#include <ass/ass.h>
+#include <assert.h>
+
+#include "talloc.h"
+
+#include "mpcommon.h"
+#include "libmpdemux/stheader.h"
+#include "libvo/sub.h"
+#include "ass_mp.h"
+#include "sd.h"
+
+struct sd_ass_priv {
+ struct ass_track *ass_track;
+};
+
+static void init(struct sh_sub *sh, struct osd_state *osd)
+{
+ struct sd_ass_priv *ctx;
+
+ if (sh->initialized) {
+ ctx = sh->context;
+ } else {
+ ctx = talloc_zero(NULL, struct sd_ass_priv);
+ sh->context = ctx;
+ if (sh->type == 'a') {
+ ctx->ass_track = ass_new_track(ass_library);
+ if (sh->extradata)
+ ass_process_codec_private(ctx->ass_track, sh->extradata,
+ sh->extradata_len);
+ } else
+ ctx->ass_track = ass_default_track(ass_library);
+ }
+
+ assert(osd->ass_track == NULL);
+ osd->ass_track = ctx->ass_track;
+}
+
+static void decode(struct sh_sub *sh, struct osd_state *osd, void *data,
+ int data_len, double pts, double duration)
+{
+ struct sd_ass_priv *ctx = sh->context;
+
+ if (sh->type == 'a') { // ssa/ass subs
+ ass_process_chunk(ctx->ass_track, data, data_len,
+ (long long)(pts*1000 + 0.5),
+ (long long)(duration*1000 + 0.5));
+ } else { // plaintext subs
+ if (pts != MP_NOPTS_VALUE) {
+ subtitle tmp_subs = {0};
+ if (duration <= 0)
+ duration = 3;
+ sub_add_text(&tmp_subs, data, data_len, pts + duration);
+ tmp_subs.start = pts * 100;
+ tmp_subs.end = (pts + duration) * 100;
+ ass_process_subtitle(ctx->ass_track, &tmp_subs);
+ sub_clear_text(&tmp_subs, MP_NOPTS_VALUE);
+ }
+ }
+}
+
+static void switch_off(struct sh_sub *sh, struct osd_state *osd)
+{
+ osd->ass_track = NULL;
+}
+
+static void uninit(struct sh_sub *sh)
+{
+ struct sd_ass_priv *ctx = sh->context;
+
+ ass_free_track(ctx->ass_track);
+ talloc_free(ctx);
+}
+
+const struct sd_functions sd_ass = {
+ .init = init,
+ .decode = decode,
+ .switch_off = switch_off,
+ .uninit = uninit,
+};