diff options
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | command.c | 10 | ||||
-rw-r--r-- | libmpdemux/demuxer.c | 20 | ||||
-rw-r--r-- | libmpdemux/stheader.h | 5 | ||||
-rw-r--r-- | mp_core.h | 1 | ||||
-rw-r--r-- | mplayer.c | 60 | ||||
-rw-r--r-- | sub/dec_sub.c | 72 | ||||
-rw-r--r-- | sub/dec_sub.h | 14 | ||||
-rw-r--r-- | sub/sd.h | 16 | ||||
-rw-r--r-- | sub/sd_ass.c | 98 |
10 files changed, 244 insertions, 55 deletions
@@ -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 \ @@ -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: @@ -37,6 +37,7 @@ #define INITIALIZED_DEMUXER 512 #define INITIALIZED_ACODEC 1024 #define INITIALIZED_VCODEC 2048 +#define INITIALIZED_SUB 4096 #define INITIALIZED_ALL 0xFFFF @@ -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, +}; |