aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Uoti Urpala <uau@glyph.nonexistent.invalid>2011-01-26 20:42:15 +0200
committerGravatar Uoti Urpala <uau@glyph.nonexistent.invalid>2011-01-26 20:42:15 +0200
commitf50f34245efa1012855a693558680bcfb7c348e5 (patch)
tree76e8fc186a96fdc1106b5c634d5937e514a06037
parentec55a188e4d0232acd50fcabc0a3db3be2b9538e (diff)
parentc9026cb3210205b07e2e068467a18ee40f9259a3 (diff)
Merge branch 'sub'
* sub: sub/OSD: move some related files to sub/ subtitles: options: enable -ass by default subtitles: change default libass rendering style demux_mkv, chapters: change millisecond arithmetic to ns cleanup: rename ass_* functions to mp_ass_* subs: use correct font aspect ratio for libass + converted subs cleanup: some random minor code simplification and cleanup vf_vo: fix EOSD change detection bug sd_ass: remove subreader use, support plaintext markup subtitles: style support for common SubRip tags and MicroDVD core: ordered chapters: fix bad subtitle parameter subs/demux: don't try to enable sub track when creating it subtitles/demux: store duration instead of endpts in demux packets subtitles: add framework for subtitle decoders options: add special -leak-report option subtitles: remove code trying to handle text subs with libavcodec cleanup: move MP_NOPTS_VALUE definition to mpcommon.h subtitles: move global ass_track to struct osd_state core: move most mpcommon.c contents to mplayer.c core: move global "subdata" and "vo_sub_last" to mpctx subtitles: remove sub_last_pts hack options: move -noconfig to option struct, simplify
-rw-r--r--DOCS/man/en/mplayer.124
-rw-r--r--Makefile32
-rw-r--r--TOOLS/subrip.c4
-rw-r--r--cfg-common.h3
-rw-r--r--cfg-mplayer.h1
-rw-r--r--command.c71
-rw-r--r--defaultopts.c6
-rw-r--r--libmenu/menu.c4
-rw-r--r--libmenu/menu_cmdlist.c2
-rw-r--r--libmenu/menu_console.c2
-rw-r--r--libmenu/menu_list.c2
-rw-r--r--libmenu/menu_txt.c2
-rw-r--r--libmenu/vf_menu.c4
-rw-r--r--libmpcodecs/vf.h9
-rw-r--r--libmpcodecs/vf_ass.c50
-rw-r--r--libmpcodecs/vf_expand.c2
-rw-r--r--libmpcodecs/vf_vo.c78
-rw-r--r--libmpdemux/demux_lavf.c10
-rw-r--r--libmpdemux/demux_mkv.c64
-rw-r--r--libmpdemux/demux_mov.c2
-rw-r--r--libmpdemux/demux_ogg.c4
-rw-r--r--libmpdemux/demux_ty.c2
-rw-r--r--libmpdemux/demux_ty_osd.c4
-rw-r--r--libmpdemux/demuxer.c38
-rw-r--r--libmpdemux/demuxer.h6
-rw-r--r--libmpdemux/stheader.h5
-rw-r--r--libmpdemux/video.c2
-rw-r--r--libvo/old_vo_wrapper.c2
-rw-r--r--libvo/vesa_lvo.c2
-rw-r--r--libvo/video_out.h7
-rw-r--r--libvo/vo_aa.c4
-rw-r--r--libvo/vo_caca.c2
-rw-r--r--libvo/vo_corevideo.m2
-rw-r--r--libvo/vo_dfbmga.c2
-rw-r--r--libvo/vo_dga.c2
-rw-r--r--libvo/vo_direct3d.c4
-rw-r--r--libvo/vo_directfb2.c2
-rw-r--r--libvo/vo_directx.c2
-rw-r--r--libvo/vo_dxr2.c2
-rw-r--r--libvo/vo_dxr3.c2
-rw-r--r--libvo/vo_fbdev.c2
-rw-r--r--libvo/vo_fbdev2.c2
-rw-r--r--libvo/vo_gl.c6
-rw-r--r--libvo/vo_gl2.c2
-rw-r--r--libvo/vo_kva.c2
-rw-r--r--libvo/vo_mga.c2
-rw-r--r--libvo/vo_quartz.c2
-rw-r--r--libvo/vo_s3fb.c2
-rw-r--r--libvo/vo_sdl.c2
-rw-r--r--libvo/vo_svga.c2
-rw-r--r--libvo/vo_tdfxfb.c2
-rw-r--r--libvo/vo_vdpau.c8
-rw-r--r--libvo/vo_vesa.c2
-rw-r--r--libvo/vo_wii.c2
-rw-r--r--libvo/vo_x11.c2
-rw-r--r--libvo/vo_xmga.c2
-rw-r--r--libvo/vo_xv.c2
-rw-r--r--libvo/vo_xvmc.c2
-rw-r--r--libvo/vo_xvr100.c2
-rw-r--r--libvo/vo_yuv4mpeg.c2
-rw-r--r--libvo/vosub_vidix.c2
-rw-r--r--m_option.c2
-rw-r--r--mp_core.h9
-rw-r--r--mpcommon.c345
-rw-r--r--mpcommon.h30
-rw-r--r--mplayer.c391
-rw-r--r--mplayer.h5
-rw-r--r--options.h1
-rw-r--r--stream/stream_dvdnav.c2
-rw-r--r--sub/ass_mp.c (renamed from ass_mp.c)56
-rw-r--r--sub/ass_mp.h (renamed from ass_mp.h)19
-rw-r--r--sub/av_sub.c (renamed from av_sub.c)47
-rw-r--r--sub/av_sub.h (renamed from av_sub.h)4
-rw-r--r--sub/dec_sub.c72
-rw-r--r--sub/dec_sub.h14
-rw-r--r--sub/find_sub.c (renamed from find_sub.c)6
-rw-r--r--sub/font_load.c (renamed from libvo/font_load.c)0
-rw-r--r--sub/font_load.h (renamed from libvo/font_load.h)0
-rw-r--r--sub/font_load_ft.c (renamed from libvo/font_load_ft.c)0
-rw-r--r--sub/osd_font.h (renamed from libvo/osd_font.h)0
-rw-r--r--sub/sd.h16
-rw-r--r--sub/sd_ass.c154
-rw-r--r--sub/spudec.c (renamed from spudec.c)3
-rw-r--r--sub/spudec.h (renamed from spudec.h)0
-rw-r--r--sub/sub.c (renamed from libvo/sub.c)2
-rw-r--r--sub/sub.h (renamed from libvo/sub.h)6
-rw-r--r--sub/sub_cc.c (renamed from sub_cc.c)2
-rw-r--r--sub/sub_cc.h (renamed from sub_cc.h)0
-rw-r--r--sub/subassconvert.c502
-rw-r--r--sub/subassconvert.h27
-rw-r--r--sub/subreader.c (renamed from subreader.c)154
-rw-r--r--sub/subreader.h (renamed from subreader.h)4
-rw-r--r--sub/unrar_exec.c (renamed from unrar_exec.c)0
-rw-r--r--sub/unrar_exec.h (renamed from unrar_exec.h)0
-rw-r--r--sub/vobsub.c (renamed from vobsub.c)0
-rw-r--r--sub/vobsub.h (renamed from vobsub.h)0
96 files changed, 1625 insertions, 768 deletions
diff --git a/DOCS/man/en/mplayer.1 b/DOCS/man/en/mplayer.1
index cc5f912053..ae13cac060 100644
--- a/DOCS/man/en/mplayer.1
+++ b/DOCS/man/en/mplayer.1
@@ -2088,14 +2088,17 @@ FIXME: Document this.
Also see \-vf expand.
.
.TP
-.B \-ass (FreeType only)
-Turn on SSA/ASS subtitle rendering.
-With this option, libass will be used for SSA/ASS
-external subtitles and Matroska tracks.
+.B \-ass, \-noass (FreeType only)
+Use libass to render all text subtitles.
+This enables support for the native styling of SSA/ASS subtitles,
+and also support for some styling features in other subtitle formats by
+conversion to ASS markup.
+Enabled by default if the player was compiled with libass support.
.br
.I NOTE:
-Unlike normal OSD, libass uses fontconfig by default. To disable it, use
-\-nofontconfig.
+Some of the other subtitle options were written for the old non-libass
+subtitle rendering system and may not work the same way or at all with
+libass rendering enabled.
.
.TP
.B \-ass\-border\-color <value>
@@ -2272,13 +2275,8 @@ With Fontconfig, this option determines the Fontconfig font pattern.
.PD 1
.
.TP
-.B \-fontconfig (fontconfig only)
-Enables the usage of fontconfig managed fonts.
-.br
-.I NOTE:
-By default fontconfig is used for libass-rendered subtitles and not used for
-OSD. With \-fontconfig it is used for both libass and OSD, with \-nofontconfig
-it is not used at all.
+.B \-fontconfig, \-nofontconfig (fontconfig only)
+Enables the use of fontconfig managed fonts. Enabled by default.
.
.TP
.B \-forcedsubsonly
diff --git a/Makefile b/Makefile
index bb80bc4fad..ee0ce5be4a 100644
--- a/Makefile
+++ b/Makefile
@@ -27,7 +27,7 @@ SRCS_AUDIO_INPUT-$(ALSA1X) += stream/ai_alsa1x.c
SRCS_AUDIO_INPUT-$(ALSA9) += stream/ai_alsa.c
SRCS_AUDIO_INPUT-$(OSS) += stream/ai_oss.c
SRCS_COMMON-$(AUDIO_INPUT) += $(SRCS_AUDIO_INPUT-yes)
-SRCS_COMMON-$(BITMAP_FONT) += libvo/font_load.c
+SRCS_COMMON-$(BITMAP_FONT) += sub/font_load.c
SRCS_COMMON-$(CDDA) += stream/stream_cdda.c \
stream/cdinfo.c
SRCS_COMMON-$(CDDB) += stream/stream_cddb.c
@@ -101,7 +101,6 @@ SRCS_COMMON-$(FASTMEMCPY) += libvo/aclib.c
SRCS_COMMON-$(FFMPEG) += libmpcodecs/vf_pp.c \
av_opts.c \
libaf/af_lavcac3enc.c \
- av_sub.c \
libaf/af_lavcresample.c \
libmpcodecs/ad_ffmpeg.c \
libmpcodecs/vd_ffmpeg.c \
@@ -111,6 +110,7 @@ SRCS_COMMON-$(FFMPEG) += libmpcodecs/vf_pp.c \
libmpcodecs/vf_uspp.c \
libmpdemux/demux_lavf.c \
stream/stream_ffmpeg.c \
+ sub/av_sub.c \
# Requires a new enough libavutil that installs eval.h
SRCS_COMMON-$(FFMPEG_EVAL_API) += libmpcodecs/vf_geq.c \
@@ -122,7 +122,7 @@ SRCS_COMMON-$(FFMPEG_INTERNALS) += libmpcodecs/vf_fspp.c \
libmpcodecs/vf_qp.c \
libmpcodecs/vf_spp.c \
-SRCS_COMMON-$(FREETYPE) += libvo/font_load_ft.c
+SRCS_COMMON-$(FREETYPE) += sub/font_load_ft.c
SRCS_COMMON-$(FTP) += stream/stream_ftp.c
SRCS_COMMON-$(GIF) += libmpdemux/demux_gif.c
SRCS_COMMON-$(HAVE_POSIX_SELECT) += libmpcodecs/vf_bmovl.c
@@ -130,8 +130,9 @@ SRCS_COMMON-$(HAVE_SYS_MMAN_H) += libaf/af_export.c osdep/mmap_anon.c
SRCS_COMMON-$(JPEG) += libmpcodecs/vd_ijpg.c
SRCS_COMMON-$(LADSPA) += libaf/af_ladspa.c
SRCS_COMMON-$(LIBA52) += libmpcodecs/ad_liba52.c
-SRCS_COMMON-$(LIBASS) += ass_mp.c \
- libmpcodecs/vf_ass.c \
+SRCS_COMMON-$(LIBASS) += libmpcodecs/vf_ass.c \
+ sub/ass_mp.c \
+ sub/sd_ass.c \
SRCS_COMMON-$(LIBBLURAY) += stream/stream_bluray.c
SRCS_COMMON-$(LIBBS2B) += libaf/af_bs2b.c
@@ -268,7 +269,7 @@ SRCS_COMMON-$(TV_DSHOW) += stream/tvi_dshow.c \
SRCS_COMMON-$(TV_V4L1) += stream/tvi_v4l.c stream/audio_in.c
SRCS_COMMON-$(TV_V4L2) += stream/tvi_v4l2.c stream/audio_in.c
-SRCS_COMMON-$(UNRAR_EXEC) += unrar_exec.c
+SRCS_COMMON-$(UNRAR_EXEC) += sub/unrar_exec.c
SRCS_COMMON-$(VCD) += stream/stream_vcd.c
SRCS_COMMON-$(VORBIS) += libmpcodecs/ad_libvorbis.c \
libmpdemux/demux_ogg.c
@@ -327,7 +328,6 @@ SRCS_COMMON = asxparser.c \
cpudetect.c \
defaultopts.c \
edl.c \
- find_sub.c \
fmt-conversion.c \
m_config.c \
m_option.c \
@@ -338,12 +338,8 @@ SRCS_COMMON = asxparser.c \
path.c \
playtree.c \
playtreeparser.c \
- spudec.c \
- sub_cc.c \
subopt-helper.c \
- subreader.c \
talloc.c \
- vobsub.c \
libaf/af.c \
libaf/af_center.c \
libaf/af_channels.c \
@@ -503,7 +499,6 @@ SRCS_COMMON = asxparser.c \
libmpdemux/yuv4mpeg.c \
libmpdemux/yuv4mpeg_ratio.c \
libvo/osd.c \
- libvo/sub.c \
osdep/findfiles.c \
osdep/numcores.c \
osdep/$(GETCH) \
@@ -515,6 +510,14 @@ SRCS_COMMON = asxparser.c \
stream/stream_mf.c \
stream/stream_null.c \
stream/url.c \
+ sub/sub.c \
+ sub/sub_cc.c \
+ sub/dec_sub.c \
+ sub/find_sub.c \
+ sub/spudec.c \
+ sub/subassconvert.c \
+ sub/subreader.c \
+ sub/vobsub.c \
$(SRCS_COMMON-yes)
@@ -687,6 +690,7 @@ DIRS = . \
stream/freesdp \
stream/librtsp \
stream/realrtsp \
+ sub \
tremor \
TOOLS \
vidix \
@@ -913,8 +917,8 @@ toolsclean:
TOOLS/bmovl-test$(EXESUF): -lSDL_image
-TOOLS/subrip$(EXESUF): vobsub.o spudec.o unrar_exec.o libvo/aclib.o \
- libswscale/libswscale.a libavutil/libavutil.a $(TEST_OBJS)
+TOOLS/subrip$(EXESUF): sub/vobsub.o sub/spudec.o sub/unrar_exec.o \
+ libvo/aclib.o \ libswscale/libswscale.a libavutil/libavutil.a $(TEST_OBJS)
TOOLS/vfw2menc$(EXESUF): -lwinmm -lole32
diff --git a/TOOLS/subrip.c b/TOOLS/subrip.c
index 85ee1c78e0..fb9395c413 100644
--- a/TOOLS/subrip.c
+++ b/TOOLS/subrip.c
@@ -31,8 +31,8 @@
#include <sys/types.h>
#include <sys/wait.h>
#include "libvo/video_out.h"
-#include "vobsub.h"
-#include "spudec.h"
+#include "sub/vobsub.h"
+#include "sub/spudec.h"
/* linking hacks */
char *mplayer_version;
diff --git a/cfg-common.h b/cfg-common.h
index 7f4123cc56..e56d87b3de 100644
--- a/cfg-common.h
+++ b/cfg-common.h
@@ -379,7 +379,8 @@ const m_option_t common_opts[] = {
{"priority", &proc_priority, CONF_TYPE_STRING, 0, 0, 0, NULL},
#endif
{"codecpath", &codec_path, CONF_TYPE_STRING, 0, 0, 0, NULL},
- {"noconfig", (void *) noconfig_opts, CONF_TYPE_SUBCONFIG, CONF_GLOBAL|CONF_NOCFG|CONF_PRE_PARSE, 0, 0, NULL},
+ OPT_CHOICE("noconfig", noconfig, CONF_GLOBAL | CONF_NOCFG | CONF_PRE_PARSE,
+ ({"off", 0}, {"user", 1}, {"system", 2}, {"all", 3})),
// ------------------------- stream options --------------------
diff --git a/cfg-mplayer.h b/cfg-mplayer.h
index ff5dd8a2c8..003e7f9c54 100644
--- a/cfg-mplayer.h
+++ b/cfg-mplayer.h
@@ -294,6 +294,7 @@ const m_option_t mplayer_opts[]={
{"lircconf", &lirc_configfile, CONF_TYPE_STRING, CONF_GLOBAL, 0, 0, NULL},
#endif
+ {"leak-report", "", CONF_TYPE_PRINT, 0, 0, 0, (void*)1},
// these should be removed when gmplayer is forgotten
{"gui", "Internal GUI was removed. Use some other frontend instead.\n", CONF_TYPE_PRINT, 0, 0, 0, NULL},
{"nogui", "Internal GUI was removed, -nogui is no longer valid.\n", CONF_TYPE_PRINT, 0, 0, 0, NULL},
diff --git a/command.c b/command.c
index 4408a584a6..c00112114e 100644
--- a/command.c
+++ b/command.c
@@ -31,7 +31,8 @@
#include "libmpdemux/stheader.h"
#include "codec-cfg.h"
#include "mplayer.h"
-#include "libvo/sub.h"
+#include "sub/sub.h"
+#include "sub/dec_sub.h"
#include "m_option.h"
#include "m_property.h"
#include "m_config.h"
@@ -40,7 +41,7 @@
#include "libmpcodecs/vd.h"
#include "mp_osd.h"
#include "libvo/video_out.h"
-#include "libvo/font_load.h"
+#include "sub/font_load.h"
#include "playtree.h"
#include "libao2/audio_out.h"
#include "mpcommon.h"
@@ -48,10 +49,10 @@
#include "libmpcodecs/dec_video.h"
#include "libmpcodecs/dec_audio.h"
#include "libmpcodecs/dec_teletext.h"
-#include "vobsub.h"
-#include "spudec.h"
+#include "sub/vobsub.h"
+#include "sub/spudec.h"
#include "path.h"
-#include "ass_mp.h"
+#include "sub/ass_mp.h"
#include "stream/tv.h"
#include "stream/stream_radio.h"
#include "stream/pvr.h"
@@ -193,15 +194,16 @@ static void log_sub(struct MPContext *mpctx)
char *fname;
FILE *f;
int i;
+ struct subtitle *vo_sub_last = mpctx->vo_sub_last;
- if (subdata == NULL || vo_sub_last == NULL)
+ if (mpctx->subdata == NULL || vo_sub_last == NULL)
return;
fname = get_path("subtitle_log");
f = fopen(fname, "a");
if (!f)
return;
fprintf(f, "----------------------------------------------------------\n");
- if (subdata->sub_uses_time) {
+ if (mpctx->subdata->sub_uses_time) {
fprintf(f,
"N: %s S: %02ld:%02ld:%02ld.%02ld E: %02ld:%02ld:%02ld.%02ld\n",
mpctx->filename, vo_sub_last->start / 360000,
@@ -1522,7 +1524,6 @@ static int mp_property_sub(m_option_t *prop, int action, void *arg,
demux_stream_t *const d_sub = mpctx->d_sub;
int source = -1, reset_spu = 0;
int source_pos = -1;
- char *sub_name;
update_global_sub_size(mpctx);
const int global_sub_size = mpctx->global_sub_size;
@@ -1541,13 +1542,15 @@ static int mp_property_sub(m_option_t *prop, int action, void *arg,
return M_PROPERTY_ERROR;
*(char **) arg = malloc(64);
(*(char **) arg)[63] = 0;
- sub_name = 0;
- if (subdata)
- sub_name = subdata->filename;
+ char *sub_name = NULL;
+ if (mpctx->subdata)
+ sub_name = mpctx->subdata->filename;
#ifdef CONFIG_ASS
- if (ass_track && ass_track->name)
- sub_name = ass_track->name;
+ if (mpctx->osd->ass_track)
+ sub_name = mpctx->osd->ass_track->name;
#endif
+ if (!sub_name && mpctx->subdata)
+ sub_name = mpctx->subdata->filename;
if (sub_name) {
const char *tmp = mp_basename(sub_name);
@@ -1644,7 +1647,7 @@ static int mp_property_sub(m_option_t *prop, int action, void *arg,
mpctx->global_sub_pos, source);
mpctx->set_of_sub_pos = -1;
- subdata = NULL;
+ mpctx->subdata = NULL;
vobsub_id = -1;
opts->sub_id = -1;
@@ -1653,21 +1656,25 @@ static int mp_property_sub(m_option_t *prop, int action, void *arg,
reset_spu = 1;
d_sub->id = -2;
}
-#ifdef CONFIG_ASS
- ass_track = 0;
-#endif
+ 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);
} else if (source == SUB_SOURCE_SUBS) {
mpctx->set_of_sub_pos = source_pos;
#ifdef CONFIG_ASS
- if (opts->ass_enabled && mpctx->set_of_ass_tracks[mpctx->set_of_sub_pos])
- ass_track = mpctx->set_of_ass_tracks[mpctx->set_of_sub_pos];
- else
+ if (opts->ass_enabled
+ && mpctx->set_of_ass_tracks[mpctx->set_of_sub_pos]) {
+ mpctx->osd->ass_track =
+ mpctx->set_of_ass_tracks[mpctx->set_of_sub_pos];
+ mpctx->osd->ass_track_changed = true;
+ mpctx->osd->vsfilter_aspect =
+ mpctx->track_was_native_ass[mpctx->set_of_sub_pos];
+ } else
#endif
{
- subdata = mpctx->set_of_subtitles[mpctx->set_of_sub_pos];
+ mpctx->subdata = mpctx->set_of_subtitles[mpctx->set_of_sub_pos];
vo_osd_changed(OSDTYPE_SUBTITLE);
}
} else if (source == SUB_SOURCE_DEMUX) {
@@ -1690,10 +1697,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)
- 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;
@@ -1710,7 +1717,7 @@ static int mp_property_sub(m_option_t *prop, int action, void *arg,
}
#endif
- update_subtitles(mpctx, &mpctx->opts, mpctx->sh_video, 0, 0, d_sub, 1);
+ update_subtitles(mpctx, 0, 0, true);
return M_PROPERTY_OK;
}
@@ -2692,10 +2699,8 @@ static void remove_subtitle_range(MPContext *mpctx, int start, int count)
if (mpctx->set_of_sub_pos >= start && mpctx->set_of_sub_pos < end) {
mpctx->global_sub_pos = -2;
- subdata = NULL;
-#ifdef CONFIG_ASS
- ass_track = NULL;
-#endif
+ mpctx->subdata = NULL;
+ mpctx->osd->ass_track = NULL;
mp_input_queue_cmd(mpctx->input, mp_input_parse_cmd("sub_select"));
} else if (mpctx->set_of_sub_pos >= end) {
mpctx->set_of_sub_pos -= count;
@@ -2931,11 +2936,11 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd)
case MP_CMD_SUB_STEP:
if (sh_video) {
int movement = cmd->args[0].v.i;
- step_sub(subdata, mpctx->video_pts, movement);
+ step_sub(mpctx->subdata, mpctx->video_pts, movement);
#ifdef CONFIG_ASS
- if (ass_track)
+ if (mpctx->osd->ass_track)
sub_delay +=
- ass_step_sub(ass_track,
+ ass_step_sub(mpctx->osd->ass_track,
(mpctx->video_pts +
sub_delay) * 1000 + .5, movement) / 1000.;
#endif
diff --git a/defaultopts.c b/defaultopts.c
index e9c2d85dce..d49841a731 100644
--- a/defaultopts.c
+++ b/defaultopts.c
@@ -46,6 +46,10 @@ void set_default_mplayer_options(struct MPOpts *opts)
.movie_aspect = -1.,
.flip = -1,
.vd_use_slices = 1,
+#ifdef CONFIG_ASS
+ .ass_enabled = 1,
+#endif
+
.lavc_param = {
.workaround_bugs = 1, // autodetect
.error_resilience = 2,
@@ -60,8 +64,6 @@ void set_default_mplayer_options(struct MPOpts *opts)
.use_lircc = 1,
#ifdef CONFIG_APPLE_REMOTE
.use_ar = 1,
-#else
- .use_ar = 0,
#endif
.default_bindings = 1,
}
diff --git a/libmenu/menu.c b/libmenu/menu.c
index 8a9cb28872..f537cd1671 100644
--- a/libmenu/menu.c
+++ b/libmenu/menu.c
@@ -26,8 +26,8 @@
#include <unistd.h>
#include "libvo/osd.h"
-#include "libvo/font_load.h"
-#include "libvo/sub.h"
+#include "sub/font_load.h"
+#include "sub/sub.h"
#include "osdep/keycodes.h"
#include "asxparser.h"
#include "stream/stream.h"
diff --git a/libmenu/menu_cmdlist.c b/libmenu/menu_cmdlist.c
index 5b7812be5e..14026d04c4 100644
--- a/libmenu/menu_cmdlist.c
+++ b/libmenu/menu_cmdlist.c
@@ -33,7 +33,7 @@
#include "menu.h"
#include "menu_list.h"
-#include "libvo/font_load.h"
+#include "sub/font_load.h"
#include "input/input.h"
diff --git a/libmenu/menu_console.c b/libmenu/menu_console.c
index dd706b65cb..eb8595e9ab 100644
--- a/libmenu/menu_console.c
+++ b/libmenu/menu_console.c
@@ -38,7 +38,7 @@
#include "m_option.h"
#include "menu.h"
-#include "libvo/font_load.h"
+#include "sub/font_load.h"
#include "osdep/keycodes.h"
#include "input/input.h"
#include "osdep/timer.h"
diff --git a/libmenu/menu_list.c b/libmenu/menu_list.c
index 28264ce04c..37f10d123e 100644
--- a/libmenu/menu_list.c
+++ b/libmenu/menu_list.c
@@ -29,7 +29,7 @@
#include "m_struct.h"
#include "menu.h"
-#include "libvo/font_load.h"
+#include "sub/font_load.h"
#include "osdep/keycodes.h"
#define IMPL 1
diff --git a/libmenu/menu_txt.c b/libmenu/menu_txt.c
index 308d9547c0..0170320884 100644
--- a/libmenu/menu_txt.c
+++ b/libmenu/menu_txt.c
@@ -30,7 +30,7 @@
#include "m_option.h"
#include "menu.h"
-#include "libvo/font_load.h"
+#include "sub/font_load.h"
#include "osdep/keycodes.h"
struct menu_priv_s {
diff --git a/libmenu/vf_menu.c b/libmenu/vf_menu.c
index 1a5d003e94..994c7134ea 100644
--- a/libmenu/vf_menu.c
+++ b/libmenu/vf_menu.c
@@ -32,8 +32,8 @@
#include "libvo/fastmemcpy.h"
#include "libvo/video_out.h"
-#include "libvo/font_load.h"
-#include "libvo/sub.h"
+#include "sub/font_load.h"
+#include "sub/sub.h"
#include "input/input.h"
#include "m_struct.h"
#include "menu.h"
diff --git a/libmpcodecs/vf.h b/libmpcodecs/vf.h
index 0d10abd6c6..58cfaaf787 100644
--- a/libmpcodecs/vf.h
+++ b/libmpcodecs/vf.h
@@ -20,6 +20,7 @@
#define MPLAYER_VF_H
#include "mp_image.h"
+#include "mpcommon.h"
struct MPOpts;
struct vf_instance;
@@ -107,8 +108,8 @@ typedef struct vf_seteq_s
#define VFCTRL_DRAW_EOSD 16 /* Render EOSD */
#define VFCTRL_SET_DEINTERLACE 18 /* Set deinterlacing status */
#define VFCTRL_GET_DEINTERLACE 19 /* Get deinterlacing status */
-/* Hack to make the OSD state object available to vf_expand which accesses
- * the OSD state outside of normal OSD draw time. */
+/* Hack to make the OSD state object available to vf_expand and vf_ass which
+ * access OSD/subtitle state outside of normal OSD draw time. */
#define VFCTRL_SET_OSD_OBJ 20
#define VFCTRL_REDRAW_OSD 21 /* Change user-visible OSD immediately */
#define VFCTRL_SET_YUV_COLORSPACE 22
@@ -116,10 +117,6 @@ typedef struct vf_seteq_s
#include "vfcap.h"
-//FIXME this should be in a common header, but i dunno which
-#define MP_NOPTS_VALUE (-1LL<<63) //both int64_t and double should be able to represent this exactly
-
-
// functions:
void vf_mpi_clear(mp_image_t* mpi,int x0,int y0,int w,int h);
mp_image_t* vf_get_image(vf_instance_t* vf, unsigned int outfmt, int mp_imgtype, int mp_imgflag, int w, int h);
diff --git a/libmpcodecs/vf_ass.c b/libmpcodecs/vf_ass.c
index 2678986025..4047316a50 100644
--- a/libmpcodecs/vf_ass.c
+++ b/libmpcodecs/vf_ass.c
@@ -33,13 +33,14 @@
#include "img_format.h"
#include "mp_image.h"
#include "vf.h"
+#include "sub/sub.h"
#include "libvo/fastmemcpy.h"
#include "m_option.h"
#include "m_struct.h"
-#include "ass_mp.h"
+#include "sub/ass_mp.h"
#define _r(c) ((c)>>24)
#define _g(c) (((c)>>16)&0xFF)
@@ -59,7 +60,9 @@ static const struct vf_priv_s {
// 0 = insert always
int auto_insert;
- ASS_Renderer *ass_priv;
+ struct osd_state *osd;
+ ASS_Renderer *renderer_realaspect;
+ ASS_Renderer *renderer_vsfilter;
unsigned char *planes[3];
struct line_limits {
@@ -68,9 +71,7 @@ static const struct vf_priv_s {
} *line_limits;
} vf_priv_dflt;
-extern ASS_Track *ass_track;
extern float sub_delay;
-extern int sub_visibility;
static int config(struct vf_instance *vf,
int width, int height, int d_width, int d_height,
@@ -92,9 +93,14 @@ static int config(struct vf_instance *vf,
vf->priv->planes[2] = malloc(vf->priv->outw * vf->priv->outh);
vf->priv->line_limits = malloc((vf->priv->outh + 1) / 2 * sizeof(*vf->priv->line_limits));
- if (vf->priv->ass_priv) {
- ass_configure(vf->priv->ass_priv, vf->priv->outw, vf->priv->outh, 0);
- ass_set_aspect_ratio(vf->priv->ass_priv, 1, 1);
+ if (vf->priv->renderer_realaspect) {
+ mp_ass_configure(vf->priv->renderer_realaspect,
+ vf->priv->outw, vf->priv->outh, 0);
+ mp_ass_configure(vf->priv->renderer_vsfilter,
+ vf->priv->outw, vf->priv->outh, 0);
+ ass_set_aspect_ratio(vf->priv->renderer_realaspect,
+ (double)width / height * d_height / d_width, 1);
+ ass_set_aspect_ratio(vf->priv->renderer_vsfilter, 1, 1);
}
return vf_next_config(vf, vf->priv->outw, vf->priv->outh, d_width,
@@ -351,9 +357,12 @@ static int render_frame(struct vf_instance *vf, mp_image_t *mpi,
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
{
ASS_Image *images = 0;
- if (sub_visibility && vf->priv->ass_priv && ass_track
+ ASS_Renderer *renderer = vf->priv->osd->vsfilter_aspect ?
+ vf->priv->renderer_vsfilter : vf->priv->renderer_realaspect;
+ if (sub_visibility && renderer && vf->priv->osd->ass_track
&& (pts != MP_NOPTS_VALUE))
- images = ass_mp_render_frame(vf->priv->ass_priv, ass_track,
+ images = mp_ass_render_frame(renderer,
+ vf->priv->osd->ass_track,
(pts + sub_delay) * 1000 + .5, NULL);
prepare_image(vf, mpi);
@@ -377,14 +386,23 @@ static int query_format(struct vf_instance *vf, unsigned int fmt)
static int control(vf_instance_t *vf, int request, void *data)
{
switch (request) {
+ case VFCTRL_SET_OSD_OBJ:
+ vf->priv->osd = data;
+ break;
case VFCTRL_INIT_EOSD:
- vf->priv->ass_priv = ass_renderer_init((ASS_Library *)data);
- if (!vf->priv->ass_priv)
+ vf->priv->renderer_realaspect = ass_renderer_init((ASS_Library *)data);
+ if (!vf->priv->renderer_realaspect)
+ return CONTROL_FALSE;
+ vf->priv->renderer_vsfilter = ass_renderer_init((ASS_Library *)data);
+ if (!vf->priv->renderer_vsfilter) {
+ ass_renderer_done(vf->priv->renderer_realaspect);
return CONTROL_FALSE;
- ass_configure_fonts(vf->priv->ass_priv);
+ }
+ mp_ass_configure_fonts(vf->priv->renderer_realaspect);
+ mp_ass_configure_fonts(vf->priv->renderer_vsfilter);
return CONTROL_TRUE;
case VFCTRL_DRAW_EOSD:
- if (vf->priv->ass_priv)
+ if (vf->priv->renderer_realaspect)
return CONTROL_TRUE;
break;
}
@@ -393,8 +411,10 @@ static int control(vf_instance_t *vf, int request, void *data)
static void uninit(struct vf_instance *vf)
{
- if (vf->priv->ass_priv)
- ass_renderer_done(vf->priv->ass_priv);
+ if (vf->priv->renderer_realaspect) {
+ ass_renderer_done(vf->priv->renderer_realaspect);
+ ass_renderer_done(vf->priv->renderer_vsfilter);
+ }
free(vf->priv->planes[1]);
free(vf->priv->planes[2]);
free(vf->priv->line_limits);
diff --git a/libmpcodecs/vf_expand.c b/libmpcodecs/vf_expand.c
index 57226acb93..95580b9f26 100644
--- a/libmpcodecs/vf_expand.c
+++ b/libmpcodecs/vf_expand.c
@@ -35,7 +35,7 @@
#include "libavutil/avutil.h"
#ifdef OSD_SUPPORT
-#include "libvo/sub.h"
+#include "sub/sub.h"
#include "libvo/osd.h"
#endif
diff --git a/libmpcodecs/vf_vo.c b/libmpcodecs/vf_vo.c
index 0e8563d5a6..8bbaf465b3 100644
--- a/libmpcodecs/vf_vo.c
+++ b/libmpcodecs/vf_vo.c
@@ -29,21 +29,19 @@
#include "libvo/video_out.h"
-#ifdef CONFIG_ASS
-#include "ass_mp.h"
-extern ASS_Track *ass_track;
-#endif
+#include "sub/ass_mp.h"
+#include "sub/sub.h"
//===========================================================================//
-extern int sub_visibility;
extern float sub_delay;
struct vf_priv_s {
struct vo *vo;
#ifdef CONFIG_ASS
- ASS_Renderer *ass_priv;
- int prev_visibility;
+ ASS_Renderer *renderer_realaspect;
+ ASS_Renderer *renderer_vsfilter;
+ bool prev_visibility;
double scale_ratio;
#endif
};
@@ -86,8 +84,12 @@ static int config(struct vf_instance *vf,
#ifdef CONFIG_ASS
vf->priv->scale_ratio = (double) d_width / d_height * height / width;
- if (vf->priv->ass_priv)
- ass_configure(vf->priv->ass_priv, width, height, !!(vf->default_caps & VFCAP_EOSD_UNSCALED));
+ if (vf->priv->renderer_realaspect) {
+ mp_ass_configure(vf->priv->renderer_realaspect, width, height,
+ vf->default_caps & VFCAP_EOSD_UNSCALED);
+ mp_ass_configure(vf->priv->renderer_vsfilter, width, height,
+ vf->default_caps & VFCAP_EOSD_UNSCALED);
+ }
#endif
return 1;
@@ -133,33 +135,55 @@ static int control(struct vf_instance *vf, int request, void* data)
#ifdef CONFIG_ASS
case VFCTRL_INIT_EOSD:
{
- vf->priv->ass_priv = ass_renderer_init((ASS_Library*)data);
- if (!vf->priv->ass_priv) return CONTROL_FALSE;
- ass_configure_fonts(vf->priv->ass_priv);
- vf->priv->prev_visibility = 0;
+ vf->priv->renderer_realaspect = ass_renderer_init(data);
+ if (!vf->priv->renderer_realaspect)
+ return CONTROL_FALSE;
+ vf->priv->renderer_vsfilter = ass_renderer_init(data);
+ if (!vf->priv->renderer_vsfilter) {
+ ass_renderer_done(vf->priv->renderer_realaspect);
+ return CONTROL_FALSE;
+ }
+ mp_ass_configure_fonts(vf->priv->renderer_realaspect);
+ mp_ass_configure_fonts(vf->priv->renderer_vsfilter);
+ vf->priv->prev_visibility = false;
return CONTROL_TRUE;
}
case VFCTRL_DRAW_EOSD:
{
+ struct osd_state *osd = data;
mp_eosd_images_t images = {NULL, 2};
double pts = video_out->next_pts;
- if (!video_out->config_ok || !vf->priv->ass_priv) return CONTROL_FALSE;
- if (sub_visibility && vf->priv->ass_priv && ass_track && (pts != MP_NOPTS_VALUE)) {
- mp_eosd_res_t res;
- memset(&res, 0, sizeof(res));
+ ASS_Renderer *renderer;
+ double scale;
+ if (osd->vsfilter_aspect) {
+ renderer = vf->priv->renderer_vsfilter;
+ scale = vf->priv->scale_ratio;
+ } else {
+ renderer = vf->priv->renderer_realaspect;
+ scale = 1;
+ }
+ if (!video_out->config_ok || !renderer)
+ return CONTROL_FALSE;
+ if (osd->ass_track_changed)
+ vf->priv->prev_visibility = false;
+ osd->ass_track_changed = false;
+ if (sub_visibility && osd->ass_track && (pts != MP_NOPTS_VALUE)) {
+ struct mp_eosd_res res = {0};
if (vo_control(video_out, VOCTRL_GET_EOSD_RES, &res) == VO_TRUE) {
- ass_set_frame_size(vf->priv->ass_priv, res.w, res.h);
- ass_set_margins(vf->priv->ass_priv, res.mt, res.mb, res.ml, res.mr);
- ass_set_aspect_ratio(vf->priv->ass_priv, vf->priv->scale_ratio, 1);
+ ass_set_frame_size(renderer, res.w, res.h);
+ ass_set_margins(renderer, res.mt, res.mb, res.ml, res.mr);
+ ass_set_aspect_ratio(renderer, scale, 1);
}
- images.imgs = ass_mp_render_frame(vf->priv->ass_priv, ass_track, (pts+sub_delay) * 1000 + .5, &images.changed);
+ images.imgs = mp_ass_render_frame(renderer,
+ osd->ass_track,
+ (pts+sub_delay) * 1000 + .5,
+ &images.changed);
if (!vf->priv->prev_visibility)
images.changed = 2;
- vf->priv->prev_visibility = 1;
+ vf->priv->prev_visibility = true;
} else
- vf->priv->prev_visibility = 0;
- vf->priv->prev_visibility = sub_visibility;
+ vf->priv->prev_visibility = false;
return vo_control(video_out, VOCTRL_DRAW_EOSD, &images) == VO_TRUE;
}
#endif
@@ -223,8 +247,10 @@ static void uninit(struct vf_instance *vf)
* to get rid of numbered-mpi references that will now be invalid. */
vo_seek_reset(video_out);
#ifdef CONFIG_ASS
- if (vf->priv->ass_priv)
- ass_renderer_done(vf->priv->ass_priv);
+ if (vf->priv->renderer_realaspect) {
+ ass_renderer_done(vf->priv->renderer_realaspect);
+ ass_renderer_done(vf->priv->renderer_vsfilter);
+ }
#endif
free(vf->priv);
}
diff --git a/libmpdemux/demux_lavf.c b/libmpdemux/demux_lavf.c
index 7f665a86bb..6a32240ebd 100644
--- a/libmpdemux/demux_lavf.c
+++ b/libmpdemux/demux_lavf.c
@@ -36,7 +36,7 @@
#include "demuxer.h"
#include "stheader.h"
#include "m_option.h"
-#include "libvo/sub.h"
+#include "sub/sub.h"
#include "libavformat/avformat.h"
#include "libavformat/avio.h"
@@ -588,8 +588,8 @@ static demuxer_t* demux_open_lavf(demuxer_t *demuxer){
for(i=0; i < avfc->nb_chapters; i++) {
AVChapter *c = avfc->chapters[i];
- uint64_t start = av_rescale_q(c->start, c->time_base, (AVRational){1,1000});
- uint64_t end = av_rescale_q(c->end, c->time_base, (AVRational){1,1000});
+ uint64_t start = av_rescale_q(c->start, c->time_base, (AVRational){1,1000000000});
+ uint64_t end = av_rescale_q(c->end, c->time_base, (AVRational){1,1000000000});
t = av_metadata_get(c->metadata, "title", NULL, 0);
demuxer_add_chapter(demuxer, t ? BSTR(t->value) : BSTR(NULL), start, end);
}
@@ -756,11 +756,11 @@ static int demux_lavf_fill_buffer(demuxer_t *demux, demux_stream_t *dsds){
if(ts != AV_NOPTS_VALUE){
dp->pts = ts * av_q2d(priv->avfc->streams[id]->time_base);
priv->last_pts= dp->pts * AV_TIME_BASE;
- // always set endpts for subtitles, even if PKT_FLAG_KEY is not set,
+ // always set duration for subtitles, even if PKT_FLAG_KEY is not set,
// otherwise they will stay on screen to long if e.g. ASS is demuxed from mkv
if((ds == demux->sub || (pkt.flags & PKT_FLAG_KEY)) &&
pkt.convergence_duration > 0)
- dp->endpts = dp->pts + pkt.convergence_duration * av_q2d(priv->avfc->streams[id]->time_base);
+ dp->duration = pkt.convergence_duration * av_q2d(priv->avfc->streams[id]->time_base);
}
dp->pos=demux->filepos;
dp->flags= !!(pkt.flags&PKT_FLAG_KEY);
diff --git a/libmpdemux/demux_mkv.c b/libmpdemux/demux_mkv.c
index 2414b01b4b..7432b59d46 100644
--- a/libmpdemux/demux_mkv.c
+++ b/libmpdemux/demux_mkv.c
@@ -41,11 +41,7 @@
#include "mp_msg.h"
-#include "vobsub.h"
-#include "subreader.h"
-#include "libvo/sub.h"
-
-#include "ass_mp.h"
+#include "sub/sub.h"
#include "libavutil/common.h"
@@ -184,7 +180,7 @@ typedef struct mkv_demuxer {
} *cluster_positions;
int num_cluster_pos;
- int64_t skip_to_timecode;
+ uint64_t skip_to_timecode;
int v_skip_to_keyframe, a_skip_to_keyframe;
int num_audio_tracks;
@@ -786,8 +782,8 @@ static int demux_mkv_read_chapters(struct demuxer *demuxer)
if (!ca->n_chapter_time_start)
mp_msg(MSGT_DEMUX, warn_level,
"[mkv] Chapter lacks start time\n");
- chapter.start = ca->chapter_time_start / 1000000;
- chapter.end = ca->chapter_time_end / 1000000;
+ chapter.start = ca->chapter_time_start;
+ chapter.end = ca->chapter_time_end;
if (ca->n_chapter_display) {
if (ca->n_chapter_display > 1)
@@ -824,14 +820,14 @@ static int demux_mkv_read_chapters(struct demuxer *demuxer)
mp_msg(MSGT_DEMUX, MSGL_V,
"[mkv] Chapter %u from %02d:%02d:%02d.%03d "
"to %02d:%02d:%02d.%03d, %.*s\n", i,
- (int) (chapter.start / 60 / 60 / 1000),
- (int) ((chapter.start / 60 / 1000) % 60),
- (int) ((chapter.start / 1000) % 60),
- (int) (chapter.start % 1000),
- (int) (chapter.end / 60 / 60 / 1000),
- (int) ((chapter.end / 60 / 1000) % 60),
- (int) ((chapter.end / 1000) % 60),
- (int) (chapter.end % 1000),
+ (int) (chapter.start / 60 / 60 / 1000000000),
+ (int) ((chapter.start / 60 / 1000000000) % 60),
+ (int) ((chapter.start / 1000000000) % 60),
+ (int) (chapter.start % 1000000000),
+ (int) (chapter.end / 60 / 60 / 1000000000),
+ (int) ((chapter.end / 60 / 1000000000) % 60),
+ (int) ((chapter.end / 1000000000) % 60),
+ (int) (chapter.end % 1000000000),
BSTR_P(name));
if (idx == selected_edition){
@@ -1883,13 +1879,13 @@ static void handle_subtitles(demuxer_t *demuxer, mkv_track_t *track,
sub_utf8 = 1;
dp = new_demux_packet(size);
memcpy(dp->buffer, block, size);
- dp->pts = timecode / 1000.0;
- dp->endpts = (timecode + block_duration) / 1000.0;
+ dp->pts = timecode / 1e9;
+ dp->duration = block_duration / 1e9;
ds_add_packet(demuxer->sub, dp);
}
static void handle_realvideo(demuxer_t *demuxer, mkv_track_t *track,
- uint8_t *buffer, uint32_t size, int block_bref)
+ uint8_t *buffer, uint32_t size, int64_t block_bref)
{
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
demux_packet_t *dp;
@@ -1915,7 +1911,7 @@ static void handle_realvideo(demuxer_t *demuxer, mkv_track_t *track,
}
static void handle_realaudio(demuxer_t *demuxer, mkv_track_t *track,
- uint8_t *buffer, uint32_t size, int block_bref)
+ uint8_t *buffer, uint32_t size, int64_t block_bref)
{
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
int sps = track->sub_packet_size;
@@ -2028,7 +2024,7 @@ static int handle_block(demuxer_t *demuxer, uint8_t *block, uint64_t length,
mkv_track_t *track = NULL;
demux_stream_t *ds = NULL;
uint64_t old_length;
- int64_t tc;
+ uint64_t tc;
uint32_t *lace_size;
uint8_t laces, flags;
int i, num, tmp, use_this_block = 1;
@@ -2048,10 +2044,8 @@ static int handle_block(demuxer_t *demuxer, uint8_t *block, uint64_t length,
return 0;
block += old_length - length;
- tc = (time * mkv_d->tc_scale + mkv_d->cluster_tc) / 1000000.0 + 0.5;
- if (tc < 0)
- tc = 0;
- current_pts = tc / 1000.0;
+ tc = time * mkv_d->tc_scale + mkv_d->cluster_tc;
+ current_pts = tc / 1e9;
for (i = 0; i < mkv_d->num_tracks; i++)
if (mkv_d->tracks[i]->tnum == num) {
@@ -2080,7 +2074,7 @@ static int handle_block(demuxer_t *demuxer, uint8_t *block, uint64_t length,
sh_audio_t *sh = (sh_audio_t *) ds->sh;
if (block_duration != 0) {
- sh->i_bps = length * 1000 / block_duration;
+ sh->i_bps = length * 1e9 / block_duration;
track->fix_i_bps = 0;
} else if (track->qt_last_a_pts == 0.0)
track->qt_last_a_pts = current_pts;
@@ -2186,8 +2180,7 @@ static int demux_mkv_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds)
free(block);
return 0;
}
- block_duration =
- block_duration * mkv_d->tc_scale / 1000000.0 + 0.5;
+ block_duration *= mkv_d->tc_scale;
break;
case MATROSKA_ID_BLOCK:
@@ -2387,7 +2380,7 @@ static struct mkv_index *seek_with_cues(struct demuxer *demuxer, int seek_id,
* target time after the last entry - then still seek to the first/last
* entry if that's further in the direction wanted than mkv_d->last_pts.
*/
- int64_t min_diff = target_timecode - mkv_d->last_pts * 1000;
+ int64_t min_diff = target_timecode - (int64_t)(mkv_d->last_pts * 1e9 + 0.5);
if (flags & SEEK_BACKWARD)
min_diff = -min_diff;
min_diff = FFMAX(min_diff, 1);
@@ -2395,8 +2388,7 @@ static struct mkv_index *seek_with_cues(struct demuxer *demuxer, int seek_id,
if (seek_id < 0 || mkv_d->indexes[i].tnum == seek_id) {
int64_t diff =
target_timecode -
- (int64_t) (mkv_d->indexes[i].timecode *
- mkv_d->tc_scale / 1000000.0 + 0.5);
+ (int64_t) (mkv_d->indexes[i].timecode * mkv_d->tc_scale);
if (flags & SEEK_BACKWARD)
diff = -diff;
if (diff <= 0) {
@@ -2442,9 +2434,8 @@ static void demux_mkv_seek(demuxer_t *demuxer, float rel_seek_secs,
if (!(flags & SEEK_ABSOLUTE)) /* relative seek */
rel_seek_secs += mkv_d->last_pts;
- int64_t target_timecode = rel_seek_secs * 1000.0;
- if (target_timecode < 0)
- target_timecode = 0;
+ rel_seek_secs = FFMAX(rel_seek_secs, 0);
+ int64_t target_timecode = rel_seek_secs * 1e9 + 0.5;
if (mkv_d->indexes == NULL) { /* no index was found */
if (seek_creating_index(demuxer, rel_seek_secs, flags) < 0)
@@ -2462,7 +2453,8 @@ static void demux_mkv_seek(demuxer_t *demuxer, float rel_seek_secs,
if (flags & SEEK_FORWARD)
mkv_d->skip_to_timecode = target_timecode;
else
- mkv_d->skip_to_timecode = index ? index->timecode : 0;
+ mkv_d->skip_to_timecode = index ? index->timecode * mkv_d->tc_scale
+ : 0;
mkv_d->a_skip_to_keyframe = 1;
demux_mkv_fill_buffer(demuxer, NULL);
@@ -2496,7 +2488,7 @@ static void demux_mkv_seek(demuxer_t *demuxer, float rel_seek_secs,
if (demuxer->video->id >= 0)
mkv_d->v_skip_to_keyframe = 1;
- mkv_d->skip_to_timecode = index->timecode;
+ mkv_d->skip_to_timecode = index->timecode * mkv_d->tc_scale;
mkv_d->a_skip_to_keyframe = 1;
demux_mkv_fill_buffer(demuxer, NULL);
diff --git a/libmpdemux/demux_mov.c b/libmpdemux/demux_mov.c
index 3175ae34bd..5ecb076698 100644
--- a/libmpdemux/demux_mov.c
+++ b/libmpdemux/demux_mov.c
@@ -64,7 +64,7 @@
#include "libavutil/common.h"
#include "ffmpeg_files/intreadwrite.h"
-#include "libvo/sub.h"
+#include "sub/sub.h"
#include "demux_mov.h"
#include "qtpalette.h"
diff --git a/libmpdemux/demux_ogg.c b/libmpdemux/demux_ogg.c
index 1883c36cd1..3ba2627414 100644
--- a/libmpdemux/demux_ogg.c
+++ b/libmpdemux/demux_ogg.c
@@ -166,8 +166,8 @@ typedef struct ogg_demuxer {
//-------- subtitle support - should be moved to decoder layer, and queue
// - subtitles up in demuxer buffer...
-#include "subreader.h"
-#include "libvo/sub.h"
+#include "sub/subreader.h"
+#include "sub/sub.h"
#define OGG_SUB_MAX_LINE 128
static subtitle ogg_sub;
diff --git a/libmpdemux/demux_ty.c b/libmpdemux/demux_ty.c
index 5d6958a970..4309ad1387 100644
--- a/libmpdemux/demux_ty.c
+++ b/libmpdemux/demux_ty.c
@@ -44,7 +44,7 @@
#include "demux_ty_osd.h"
#include "parse_es.h"
#include "stheader.h"
-#include "sub_cc.h"
+#include "sub/sub_cc.h"
#include "libavutil/avstring.h"
#include "ffmpeg_files/intreadwrite.h"
diff --git a/libmpdemux/demux_ty_osd.c b/libmpdemux/demux_ty_osd.c
index 0d419b0813..983c243f98 100644
--- a/libmpdemux/demux_ty_osd.c
+++ b/libmpdemux/demux_ty_osd.c
@@ -23,8 +23,8 @@
//#include "stheader.h"
//#include "mp3_hdr.h"
//#include "subreader.h"
-#include "sub_cc.h"
-#include "libvo/sub.h"
+#include "sub/sub_cc.h"
+#include "sub/sub.h"
#include "demux_ty_osd.h"
//#include "dvdauth.h"
diff --git a/libmpdemux/demuxer.c b/libmpdemux/demuxer.c
index 056822e1ab..6607f2399f 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
@@ -188,7 +186,7 @@ struct demux_packet *new_demux_packet(size_t len)
dp->len = len;
dp->next = NULL;
dp->pts = MP_NOPTS_VALUE;
- dp->endpts = MP_NOPTS_VALUE;
+ dp->duration = -1;
dp->stream_pts = MP_NOPTS_VALUE;
dp->pos = 0;
dp->flags = 0;
@@ -351,10 +349,6 @@ sh_sub_t *new_sh_sub_sid(demuxer_t *demuxer, int id, int sid)
sh->opts = demuxer->opts;
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SUBTITLE_ID=%d\n", sid);
}
- if (sid == demuxer->opts->sub_id) {
- demuxer->sub->id = id;
- demuxer->sub->sh = demuxer->s_streams[id];
- }
return demuxer->s_streams[id];
}
@@ -373,10 +367,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);
@@ -1076,20 +1066,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;
}
@@ -1418,9 +1394,9 @@ int demuxer_add_chapter(demuxer_t *demuxer, struct bstr name,
talloc_strdup(demuxer->chapters, mp_gtext("unknown"));
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CHAPTER_ID=%d\n", demuxer->num_chapters);
- mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CHAPTER_%d_START=%"PRIu64"\n", demuxer->num_chapters, start);
+ mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CHAPTER_%d_START=%"PRIu64"\n", demuxer->num_chapters, start / 1000000);
if (end)
- mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CHAPTER_%d_END=%"PRIu64"\n", demuxer->num_chapters, end);
+ mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CHAPTER_%d_END=%"PRIu64"\n", demuxer->num_chapters, end / 1000000);
if (name.start)
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CHAPTER_%d_NAME=%.*s\n", demuxer->num_chapters, BSTR_P(name));
@@ -1473,7 +1449,7 @@ int demuxer_seek_chapter(demuxer_t *demuxer, int chapter, double *seek_pts,
if (chapter < 0)
chapter = 0;
- *seek_pts = demuxer->chapters[chapter].start / 1000.0;
+ *seek_pts = demuxer->chapters[chapter].start / 1e9;
if (chapter_name)
*chapter_name = talloc_strdup(NULL, demuxer->chapters[chapter].name);
@@ -1490,7 +1466,7 @@ int demuxer_get_current_chapter(demuxer_t *demuxer, double time_now)
&chapter) == STREAM_UNSUPPORTED)
chapter = -2;
} else {
- uint64_t now = time_now * 1000 + 0.5;
+ uint64_t now = time_now * 1e9 + 0.5;
for (chapter = demuxer->num_chapters - 1; chapter >= 0; --chapter) {
if (demuxer->chapters[chapter].start <= now)
break;
@@ -1533,8 +1509,8 @@ float demuxer_chapter_time(demuxer_t *demuxer, int chapter, float *end)
if (demuxer->num_chapters && demuxer->chapters && chapter >= 0
&& chapter < demuxer->num_chapters) {
if (end)
- *end = demuxer->chapters[chapter].end / 1000.0;
- return demuxer->chapters[chapter].start / 1000.0;
+ *end = demuxer->chapters[chapter].end / 1e9;
+ return demuxer->chapters[chapter].start / 1e9;
}
return -1.0;
}
diff --git a/libmpdemux/demuxer.h b/libmpdemux/demuxer.h
index 742e42aa74..e66b8f8a12 100644
--- a/libmpdemux/demuxer.h
+++ b/libmpdemux/demuxer.h
@@ -27,6 +27,7 @@
#include "stream/stream.h"
#include "bstr.h"
+#include "mpcommon.h"
struct MPOpts;
@@ -96,9 +97,6 @@ struct MPOpts;
// A virtual demuxer type for the network code
#define DEMUXER_TYPE_PLAYLIST (2<<16)
-
-#define MP_NOPTS_VALUE (-1LL<<63) //both int64_t and double should be able to represent this exactly
-
enum timestamp_type {
TIMESTAMP_TYPE_PTS,
TIMESTAMP_TYPE_SORT,
@@ -129,7 +127,7 @@ enum timestamp_type {
typedef struct demux_packet {
int len;
double pts;
- double endpts;
+ double duration;
double stream_pts;
off_t pos; // position in index (AVI) or file (MPG)
unsigned char* buffer;
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/libmpdemux/video.c b/libmpdemux/video.c
index bda6e661ae..400a995d57 100644
--- a/libmpdemux/video.c
+++ b/libmpdemux/video.c
@@ -38,7 +38,7 @@
#include "mpeg_hdr.h"
/* sub_cc (closed captions)*/
-#include "sub_cc.h"
+#include "sub/sub_cc.h"
/* biCompression constant */
#define BI_RGB 0L
diff --git a/libvo/old_vo_wrapper.c b/libvo/old_vo_wrapper.c
index bdbc8b8349..a99511d831 100644
--- a/libvo/old_vo_wrapper.c
+++ b/libvo/old_vo_wrapper.c
@@ -20,7 +20,7 @@
#include <stdint.h>
#include "old_vo_wrapper.h"
#include "video_out.h"
-#include "sub.h"
+#include "sub/sub.h"
struct vo *global_vo;
struct osd_state *global_osd;
diff --git a/libvo/vesa_lvo.c b/libvo/vesa_lvo.c
index 4f4c796250..f5cbab4757 100644
--- a/libvo/vesa_lvo.c
+++ b/libvo/vesa_lvo.c
@@ -39,7 +39,7 @@
#include "fastmemcpy.h"
#include "osd.h"
#include "video_out.h"
-#include "sub.h"
+#include "sub/sub.h"
#include "libmpcodecs/vfcap.h"
#define WIDTH_ALIGN 32 /* should be 16 for rage:422 and 32 for rage:420 */
diff --git a/libvo/video_out.h b/libvo/video_out.h
index 36a161aaf5..5fac7dd02d 100644
--- a/libvo/video_out.h
+++ b/libvo/video_out.h
@@ -26,11 +26,8 @@
#include <inttypes.h>
#include <stdbool.h>
-//#include "font_load.h"
#include "libmpcodecs/img_format.h"
-//#include "vidix/vidix.h"
-
-#define MP_NOPTS_VALUE (-1LL<<63)
+#include "mpcommon.h"
#define VO_EVENT_EXPOSE 1
#define VO_EVENT_RESIZE 2
@@ -80,7 +77,7 @@ struct voctrl_get_equalizer_args {
#define VOCTRL_BORDER 27
#define VOCTRL_DRAW_EOSD 28
#define VOCTRL_GET_EOSD_RES 29
-typedef struct {
+typedef struct mp_eosd_res {
int w, h; // screen dimensions, including black borders
int mt, mb, ml, mr; // borders (top, bottom, left, right)
} mp_eosd_res_t;
diff --git a/libvo/vo_aa.c b/libvo/vo_aa.c
index 3e55803982..99e313d399 100644
--- a/libvo/vo_aa.c
+++ b/libvo/vo_aa.c
@@ -39,8 +39,8 @@
#include "aspect.h"
#include "libswscale/swscale.h"
#include "libmpcodecs/vf_scale.h"
-#include "font_load.h"
-#include "sub.h"
+#include "sub/font_load.h"
+#include "sub/sub.h"
#include "osdep/keycodes.h"
#include <aalib.h>
diff --git a/libvo/vo_caca.c b/libvo/vo_caca.c
index 75e862ef91..2a5ebad4e7 100644
--- a/libvo/vo_caca.c
+++ b/libvo/vo_caca.c
@@ -35,7 +35,7 @@
#include "config.h"
#include "video_out.h"
#include "video_out_internal.h"
-#include "sub.h"
+#include "sub/sub.h"
#include "osdep/keycodes.h"
#include "mp_msg.h"
diff --git a/libvo/vo_corevideo.m b/libvo/vo_corevideo.m
index 585898a076..a964de7e57 100644
--- a/libvo/vo_corevideo.m
+++ b/libvo/vo_corevideo.m
@@ -40,7 +40,7 @@
#include "mp_msg.h"
#include "m_option.h"
#include "mp_fifo.h"
-#include "libvo/sub.h"
+#include "sub/sub.h"
#include "subopt-helper.h"
#include "input/input.h"
diff --git a/libvo/vo_dfbmga.c b/libvo/vo_dfbmga.c
index a0a9d07760..b83f3c5e52 100644
--- a/libvo/vo_dfbmga.c
+++ b/libvo/vo_dfbmga.c
@@ -31,7 +31,7 @@
#include "video_out.h"
#include "video_out_internal.h"
#include "fastmemcpy.h"
-#include "sub.h"
+#include "sub/sub.h"
#include "mp_msg.h"
#include "aspect.h"
#include "mp_fifo.h"
diff --git a/libvo/vo_dga.c b/libvo/vo_dga.c
index 879831761d..94d42774a8 100644
--- a/libvo/vo_dga.c
+++ b/libvo/vo_dga.c
@@ -333,7 +333,7 @@ static void check_events(void)
//---------------------------------------------------------
-#include "sub.h"
+#include "sub/sub.h"
static void draw_osd(void)
{
diff --git a/libvo/vo_direct3d.c b/libvo/vo_direct3d.c
index 384dcb477b..65f5a6c2d1 100644
--- a/libvo/vo_direct3d.c
+++ b/libvo/vo_direct3d.c
@@ -30,8 +30,8 @@
#include "aspect.h"
#include "w32_common.h"
#include "libavutil/common.h"
-#include "font_load.h"
-#include "sub.h"
+#include "sub/font_load.h"
+#include "sub/sub.h"
static const vo_info_t info =
{
diff --git a/libvo/vo_directfb2.c b/libvo/vo_directfb2.c
index 1fb5577075..c011d20225 100644
--- a/libvo/vo_directfb2.c
+++ b/libvo/vo_directfb2.c
@@ -33,7 +33,7 @@
#include "video_out.h"
#include "video_out_internal.h"
#include "fastmemcpy.h"
-#include "sub.h"
+#include "sub/sub.h"
#include "mp_msg.h"
#include "aspect.h"
#include "subopt-helper.h"
diff --git a/libvo/vo_directx.c b/libvo/vo_directx.c
index b80f0bdc01..494d6c8424 100644
--- a/libvo/vo_directx.c
+++ b/libvo/vo_directx.c
@@ -37,7 +37,7 @@
#include "aspect.h"
#include "geometry.h"
#include "mp_fifo.h"
-#include "sub.h"
+#include "sub/sub.h"
#ifndef WM_XBUTTONDOWN
# define WM_XBUTTONDOWN 0x020B
diff --git a/libvo/vo_dxr2.c b/libvo/vo_dxr2.c
index 00d5d2f3c0..71c402cd9a 100644
--- a/libvo/vo_dxr2.c
+++ b/libvo/vo_dxr2.c
@@ -34,7 +34,7 @@
#include "video_out_internal.h"
#include "mp_msg.h"
#include "m_option.h"
-#include "sub.h"
+#include "sub/sub.h"
#include "path.h"
#include "libmpdemux/mpeg_packetizer.h"
#include "x11_common.h"
diff --git a/libvo/vo_dxr3.c b/libvo/vo_dxr3.c
index 3494e25f00..8f7b471306 100644
--- a/libvo/vo_dxr3.c
+++ b/libvo/vo_dxr3.c
@@ -42,7 +42,7 @@
#include "video_out_internal.h"
#include "aspect.h"
#include "spuenc.h"
-#include "sub.h"
+#include "sub/sub.h"
#ifdef CONFIG_X11
#include "x11_common.h"
#endif
diff --git a/libvo/vo_fbdev.c b/libvo/vo_fbdev.c
index 991673a9cd..2d422af269 100644
--- a/libvo/vo_fbdev.c
+++ b/libvo/vo_fbdev.c
@@ -39,7 +39,7 @@
#include "video_out.h"
#include "video_out_internal.h"
#include "fastmemcpy.h"
-#include "sub.h"
+#include "sub/sub.h"
#include "geometry.h"
#ifdef CONFIG_VIDIX
#include "vosub_vidix.h"
diff --git a/libvo/vo_fbdev2.c b/libvo/vo_fbdev2.c
index a4929afe13..612b145464 100644
--- a/libvo/vo_fbdev2.c
+++ b/libvo/vo_fbdev2.c
@@ -34,7 +34,7 @@
#include "video_out.h"
#include "video_out_internal.h"
#include "fastmemcpy.h"
-#include "sub.h"
+#include "sub/sub.h"
#include "mp_msg.h"
static const vo_info_t info = {
diff --git a/libvo/vo_gl.c b/libvo/vo_gl.c
index 8ffd82b6fd..c062614d3a 100644
--- a/libvo/vo_gl.c
+++ b/libvo/vo_gl.c
@@ -31,13 +31,13 @@
#include "subopt-helper.h"
#include "video_out.h"
#include "video_out_internal.h"
-#include "font_load.h"
-#include "sub.h"
+#include "sub/font_load.h"
+#include "sub/sub.h"
#include "gl_common.h"
#include "aspect.h"
#include "fastmemcpy.h"
-#include "ass_mp.h"
+#include "sub/ass_mp.h"
#ifdef CONFIG_GL_SDL
#ifdef CONFIG_SDL_SDL_H
diff --git a/libvo/vo_gl2.c b/libvo/vo_gl2.c
index 14137f76a6..957125069b 100644
--- a/libvo/vo_gl2.c
+++ b/libvo/vo_gl2.c
@@ -29,7 +29,7 @@
#include "subopt-helper.h"
#include "video_out.h"
#include "video_out_internal.h"
-#include "sub.h"
+#include "sub/sub.h"
#include "gl_common.h"
#include "aspect.h"
diff --git a/libvo/vo_kva.c b/libvo/vo_kva.c
index 7994fe9143..155a779e4e 100644
--- a/libvo/vo_kva.c
+++ b/libvo/vo_kva.c
@@ -47,7 +47,7 @@
#include "input/input.h"
#include "input/mouse.h"
#include "subopt-helper.h"
-#include "sub.h"
+#include "sub/sub.h"
#include "cpudetect.h"
#include "libswscale/swscale.h"
diff --git a/libvo/vo_mga.c b/libvo/vo_mga.c
index d398ec001a..df99251847 100644
--- a/libvo/vo_mga.c
+++ b/libvo/vo_mga.c
@@ -34,7 +34,7 @@
#include <linux/fb.h>
#include "drivers/mga_vid.h"
-#include "sub.h"
+#include "sub/sub.h"
#include "aspect.h"
static const vo_info_t info =
diff --git a/libvo/vo_quartz.c b/libvo/vo_quartz.c
index 07edf2538d..65797c988b 100644
--- a/libvo/vo_quartz.c
+++ b/libvo/vo_quartz.c
@@ -48,7 +48,7 @@
#include "m_option.h"
#include "mp_fifo.h"
#include "mpbswap.h"
-#include "sub.h"
+#include "sub/sub.h"
#include "input/input.h"
#include "input/mouse.h"
diff --git a/libvo/vo_s3fb.c b/libvo/vo_s3fb.c
index 5b884b75b8..a0d54e0ca9 100644
--- a/libvo/vo_s3fb.c
+++ b/libvo/vo_s3fb.c
@@ -44,7 +44,7 @@
#include "video_out.h"
#include "video_out_internal.h"
#include "aspect.h"
-#include "sub.h"
+#include "sub/sub.h"
static const vo_info_t info =
{
diff --git a/libvo/vo_sdl.c b/libvo/vo_sdl.c
index 9715dd98fb..be6e741295 100644
--- a/libvo/vo_sdl.c
+++ b/libvo/vo_sdl.c
@@ -63,7 +63,7 @@
#include "video_out_internal.h"
#include "fastmemcpy.h"
-#include "sub.h"
+#include "sub/sub.h"
#include "aspect.h"
#include "libmpcodecs/vfcap.h"
diff --git a/libvo/vo_svga.c b/libvo/vo_svga.c
index c74cf61089..d44821df05 100644
--- a/libvo/vo_svga.c
+++ b/libvo/vo_svga.c
@@ -59,7 +59,7 @@ TODO:
#include "vosub_vidix.h"
#endif
-#include "sub.h"
+#include "sub/sub.h"
#include "mp_msg.h"
//#include "mp_image.h"
diff --git a/libvo/vo_tdfxfb.c b/libvo/vo_tdfxfb.c
index b9255eaf8f..6e14f600b7 100644
--- a/libvo/vo_tdfxfb.c
+++ b/libvo/vo_tdfxfb.c
@@ -62,7 +62,7 @@
#include "video_out_internal.h"
#include "drivers/3dfx.h"
#include "aspect.h"
-#include "sub.h"
+#include "sub/sub.h"
static const vo_info_t info =
{
diff --git a/libvo/vo_vdpau.c b/libvo/vo_vdpau.c
index f8748b5574..210fe797dc 100644
--- a/libvo/vo_vdpau.c
+++ b/libvo/vo_vdpau.c
@@ -41,7 +41,7 @@
#include "video_out.h"
#include "x11_common.h"
#include "aspect.h"
-#include "sub.h"
+#include "sub/sub.h"
#include "subopt-helper.h"
#include "libmpcodecs/vfcap.h"
#include "libmpcodecs/mp_image.h"
@@ -49,12 +49,12 @@
#include "libavcodec/vdpau.h"
-#include "font_load.h"
+#include "sub/font_load.h"
#include "libavutil/common.h"
#include "libavutil/mathematics.h"
-#include "ass_mp.h"
+#include "sub/ass_mp.h"
#define WRAP_ADD(x, a, m) ((a) < 0 \
? ((x)+(a)+(m) < (m) ? (x)+(a)+(m) : (x)+(a)) \
@@ -1803,7 +1803,7 @@ static int control(struct vo *vo, uint32_t request, void *data)
draw_eosd(vo);
return VO_TRUE;
case VOCTRL_GET_EOSD_RES: {
- mp_eosd_res_t *r = data;
+ struct mp_eosd_res *r = data;
r->w = vo->dwidth;
r->h = vo->dheight;
r->ml = r->mr = vc->border_x;
diff --git a/libvo/vo_vesa.c b/libvo/vo_vesa.c
index 8c367586ee..698b9f033a 100644
--- a/libvo/vo_vesa.c
+++ b/libvo/vo_vesa.c
@@ -48,7 +48,7 @@
#include "video_out_internal.h"
#include "fastmemcpy.h"
-#include "sub.h"
+#include "sub/sub.h"
#include "libavutil/common.h"
#include "mpbswap.h"
#include "aspect.h"
diff --git a/libvo/vo_wii.c b/libvo/vo_wii.c
index 148e641bdb..b7c07fc6cb 100644
--- a/libvo/vo_wii.c
+++ b/libvo/vo_wii.c
@@ -51,7 +51,7 @@
#include "config.h"
#include "video_out.h"
#include "video_out_internal.h"
-#include "sub.h"
+#include "sub/sub.h"
#include "mp_msg.h"
static const vo_info_t info = {
diff --git a/libvo/vo_x11.c b/libvo/vo_x11.c
index bdf561cb53..ec85c7b747 100644
--- a/libvo/vo_x11.c
+++ b/libvo/vo_x11.c
@@ -46,7 +46,7 @@ static int gXErrorFlag;
static int CompletionType = -1;
#endif
-#include "sub.h"
+#include "sub/sub.h"
#include "libswscale/swscale.h"
#include "libmpcodecs/vf_scale.h"
diff --git a/libvo/vo_xmga.c b/libvo/vo_xmga.c
index 9072c8b3a2..cc6cd1cd0e 100644
--- a/libvo/vo_xmga.c
+++ b/libvo/vo_xmga.c
@@ -46,7 +46,7 @@
#endif
#include "x11_common.h"
-#include "sub.h"
+#include "sub/sub.h"
#include "aspect.h"
#ifdef SHOW_TIME
diff --git a/libvo/vo_xv.c b/libvo/vo_xv.c
index 63221782e2..67d1cffb95 100644
--- a/libvo/vo_xv.c
+++ b/libvo/vo_xv.c
@@ -56,7 +56,7 @@ Buffer allocation:
#include "x11_common.h"
#include "fastmemcpy.h"
-#include "sub.h"
+#include "sub/sub.h"
#include "aspect.h"
#include "subopt-helper.h"
diff --git a/libvo/vo_xvmc.c b/libvo/vo_xvmc.c
index 252a2cf87f..21a279beaa 100644
--- a/libvo/vo_xvmc.c
+++ b/libvo/vo_xvmc.c
@@ -45,7 +45,7 @@
#include "libavcodec/avcodec.h"
#include "libavcodec/xvmc.h"
-#include "sub.h"
+#include "sub/sub.h"
#include "aspect.h"
#include "subopt-helper.h"
diff --git a/libvo/vo_xvr100.c b/libvo/vo_xvr100.c
index 7a82c436fb..fcd3b35b54 100644
--- a/libvo/vo_xvr100.c
+++ b/libvo/vo_xvr100.c
@@ -48,7 +48,7 @@
#include "aspect.h"
#include "geometry.h"
#include "fastmemcpy.h"
-#include "sub.h"
+#include "sub/sub.h"
#include "mp_msg.h"
diff --git a/libvo/vo_yuv4mpeg.c b/libvo/vo_yuv4mpeg.c
index 5901cce2c2..67013eaa90 100644
--- a/libvo/vo_yuv4mpeg.c
+++ b/libvo/vo_yuv4mpeg.c
@@ -51,7 +51,7 @@
#include "mp_msg.h"
-#include "sub.h"
+#include "sub/sub.h"
#include "fastmemcpy.h"
#include "libavutil/rational.h"
diff --git a/libvo/vosub_vidix.c b/libvo/vosub_vidix.c
index b06306e98b..f4add7db4c 100644
--- a/libvo/vosub_vidix.c
+++ b/libvo/vosub_vidix.c
@@ -41,7 +41,7 @@
#include "fastmemcpy.h"
#include "osd.h"
#include "video_out.h"
-#include "sub.h"
+#include "sub/sub.h"
#include "vosub_vidix.h"
#include "old_vo_wrapper.h"
diff --git a/m_option.c b/m_option.c
index a0f01e6344..3cca348b1e 100644
--- a/m_option.c
+++ b/m_option.c
@@ -970,7 +970,7 @@ static int parse_print(const m_option_t* opt,const char *name, const char *param
if(opt->priv == NULL)
return M_OPT_EXIT;
- return 1;
+ return 0;
}
const m_option_type_t m_option_type_print = {
diff --git a/mp_core.h b/mp_core.h
index 00b8fa91ef..825718f161 100644
--- a/mp_core.h
+++ b/mp_core.h
@@ -23,7 +23,7 @@
#include "options.h"
#include "mixer.h"
-#include "subreader.h"
+#include "sub/subreader.h"
// definitions used internally by the core player code
@@ -37,6 +37,7 @@
#define INITIALIZED_DEMUXER 512
#define INITIALIZED_ACODEC 1024
#define INITIALIZED_VCODEC 2048
+#define INITIALIZED_SUB 4096
#define INITIALIZED_ALL 0xFFFF
@@ -88,6 +89,9 @@ typedef struct MPContext {
struct mp_fifo *key_fifo;
struct input_ctx *input;
struct osd_state *osd;
+ struct sub_data *subdata; // current sub_data style subtitles if any
+ // last sub_data style sub line if any, used by log_sub() only
+ struct subtitle *vo_sub_last;
bool add_osd_seek_info;
// if nonzero, hide current OSD contents when GetTimerMS() reaches this
@@ -194,6 +198,7 @@ typedef struct MPContext {
// parsed by libass or NULL if format unsupported
struct ass_track *set_of_ass_tracks[MAX_SUBTITLE_FILES];
sub_data* set_of_subtitles[MAX_SUBTITLE_FILES];
+ bool track_was_native_ass[MAX_SUBTITLE_FILES];
int file_format;
@@ -243,5 +248,7 @@ double get_current_time(struct MPContext *mpctx);
int get_percent_pos(struct MPContext *mpctx);
int get_current_chapter(struct MPContext *mpctx);
char *chapter_display_name(struct MPContext *mpctx, int chapter);
+void update_subtitles(struct MPContext *mpctx, double refpts,
+ double sub_offset, bool reset);
#endif /* MPLAYER_MP_CORE_H */
diff --git a/mpcommon.c b/mpcommon.c
index f1b1828c1f..47c056a08e 100644
--- a/mpcommon.c
+++ b/mpcommon.c
@@ -16,351 +16,6 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#if defined(__MINGW32__) || defined(__CYGWIN__)
-#include <windows.h>
-#endif
-#include <stdlib.h>
-#include <stdbool.h>
-
-#include "mpcommon.h"
-#include "options.h"
-#include "stream/stream.h"
-#include "libmpdemux/demuxer.h"
-#include "libmpdemux/stheader.h"
-#include "mplayer.h"
-#include "libvo/sub.h"
-#include "libvo/video_out.h"
-#include "cpudetect.h"
-#include "mp_msg.h"
-#include "spudec.h"
#include "version.h"
-#include "vobsub.h"
-#include "av_sub.h"
-#include "libmpcodecs/dec_teletext.h"
-#include "ffmpeg_files/intreadwrite.h"
-#include "m_option.h"
-
-double sub_last_pts = -303;
-
-#ifdef CONFIG_ASS
-#include "ass_mp.h"
-ASS_Track *ass_track = 0; // current track to render
-#endif
-
-sub_data* subdata = NULL;
-subtitle* vo_sub_last = NULL;
const char *mplayer_version = "MPlayer " VERSION;
-
-void print_version(const char* name)
-{
- mp_msg(MSGT_CPLAYER, MSGL_INFO, MP_TITLE, name);
-
- /* Test for CPU capabilities (and corresponding OS support) for optimizing */
- GetCpuCaps(&gCpuCaps);
-#if ARCH_X86
- mp_msg(MSGT_CPLAYER, MSGL_V,
- "CPUflags: MMX: %d MMX2: %d 3DNow: %d 3DNowExt: %d SSE: %d SSE2: %d SSSE3: %d\n",
- gCpuCaps.hasMMX, gCpuCaps.hasMMX2,
- gCpuCaps.has3DNow, gCpuCaps.has3DNowExt,
- gCpuCaps.hasSSE, gCpuCaps.hasSSE2, gCpuCaps.hasSSSE3);
-#if CONFIG_RUNTIME_CPUDETECT
- mp_tmsg(MSGT_CPLAYER,MSGL_V, "Compiled with runtime CPU detection.\n");
-#else
- mp_tmsg(MSGT_CPLAYER,MSGL_V, "Compiled for x86 CPU with extensions:");
-if (HAVE_MMX)
- mp_msg(MSGT_CPLAYER,MSGL_V," MMX");
-if (HAVE_MMX2)
- mp_msg(MSGT_CPLAYER,MSGL_V," MMX2");
-if (HAVE_AMD3DNOW)
- mp_msg(MSGT_CPLAYER,MSGL_V," 3DNow");
-if (HAVE_AMD3DNOWEXT)
- mp_msg(MSGT_CPLAYER,MSGL_V," 3DNowExt");
-if (HAVE_SSE)
- mp_msg(MSGT_CPLAYER,MSGL_V," SSE");
-if (HAVE_SSE2)
- mp_msg(MSGT_CPLAYER,MSGL_V," SSE2");
-if (HAVE_SSSE3)
- mp_msg(MSGT_CPLAYER,MSGL_V," SSSE3");
-if (HAVE_CMOV)
- mp_msg(MSGT_CPLAYER,MSGL_V," CMOV");
- mp_msg(MSGT_CPLAYER,MSGL_V,"\n");
-#endif /* CONFIG_RUNTIME_CPUDETECT */
-#endif /* ARCH_X86 */
-}
-
-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';
-}
-
-void update_subtitles(struct MPContext *mpctx, struct MPOpts *opts,
- sh_video_t *sh_video, double refpts, double sub_offset,
- demux_stream_t *d_dvdsub, int reset)
-{
- double curpts = refpts + sub_delay;
- unsigned char *packet=NULL;
- int len;
- int type = d_dvdsub->sh ? ((sh_sub_t *)d_dvdsub->sh)->type : 'v';
- static subtitle subs;
- if (reset) {
- sub_clear_text(&subs, MP_NOPTS_VALUE);
- if (vo_sub) {
- set_osd_subtitle(mpctx, NULL);
- }
- if (vo_spudec) {
- spudec_reset(vo_spudec);
- vo_osd_changed(OSDTYPE_SPU);
- }
-#ifdef CONFIG_FFMPEG
- if (is_av_sub(type))
- reset_avsub(d_dvdsub->sh);
-#endif
- return;
- }
- // find sub
- if (subdata) {
- if (sub_fps==0) sub_fps = sh_video ? sh_video->fps : 25;
- current_module = "find_sub";
- if (refpts > sub_last_pts || refpts < sub_last_pts-1.0) {
- find_sub(mpctx, subdata, curpts *
- (subdata->sub_uses_time ? 100. : sub_fps));
- if (vo_sub) vo_sub_last = vo_sub;
- // FIXME! frame counter...
- sub_last_pts = refpts;
- }
- }
-
- // DVD sub:
- if (vobsub_id >= 0 || type == 'v') {
- int timestamp;
- current_module = "spudec";
- /* Get a sub packet from the DVD or a vobsub */
- while(1) {
- // Vobsub
- len = 0;
- if (vo_vobsub) {
- if (curpts >= 0) {
- len = vobsub_get_packet(vo_vobsub, curpts,
- (void**)&packet, &timestamp);
- if (len > 0) {
- mp_dbg(MSGT_CPLAYER,MSGL_V,"\rVOB sub: len=%d v_pts=%5.3f v_timer=%5.3f sub=%5.3f ts=%d \n",len,refpts,sh_video->timer,timestamp / 90000.0,timestamp);
- }
- }
- } else {
- // DVD sub
- len = ds_get_packet_sub(d_dvdsub, (unsigned char**)&packet);
- if (len > 0) {
- // XXX This is wrong, sh_video->pts can be arbitrarily
- // much behind demuxing position. Unfortunately using
- // d_video->pts which would have been the simplest
- // improvement doesn't work because mpeg specific hacks
- // in video.c set d_video->pts to 0.
- float x = d_dvdsub->pts - refpts;
- if (x > -20 && x < 20) // prevent missing subs on pts reset
- timestamp = 90000*d_dvdsub->pts;
- else timestamp = 90000*curpts;
- mp_dbg(MSGT_CPLAYER, MSGL_V, "\rDVD sub: len=%d "
- "v_pts=%5.3f s_pts=%5.3f ts=%d \n", len,
- refpts, d_dvdsub->pts, timestamp);
- }
- }
- if (len<=0 || !packet) break;
- // create it only here, since with some broken demuxers we might
- // type = v but no DVD sub and we currently do not change the
- // "original frame size" ever after init, leading to wrong-sized
- // PGS subtitles.
- if (!vo_spudec)
- vo_spudec = spudec_new(NULL);
- if (vo_vobsub || timestamp >= 0)
- spudec_assemble(vo_spudec, packet, len, timestamp);
- }
- } else if (is_text_sub(type) || is_av_sub(type) || type == 'd') {
- if (type == 'd' && !d_dvdsub->demuxer->teletext) {
- tt_stream_props tsp = {0};
- void *ptr = &tsp;
- if (teletext_control(NULL, TV_VBI_CONTROL_START, &ptr) == VBI_CONTROL_TRUE)
- d_dvdsub->demuxer->teletext = ptr;
- }
- if (d_dvdsub->non_interleaved)
- ds_get_next_pts(d_dvdsub);
-
- int orig_type = type;
- while (d_dvdsub->first) {
- double subpts = ds_get_next_pts(d_dvdsub) + sub_offset;
- type = orig_type;
- if (subpts > curpts) {
- // Libass handled subs can be fed to it in advance
- if (!opts->ass_enabled || !is_text_sub(type))
- break;
- // Try to avoid demuxing whole file at once
- if (d_dvdsub->non_interleaved && subpts > curpts + 1)
- break;
- }
- double endpts = d_dvdsub->first->endpts + sub_offset;
- len = ds_get_packet_sub(d_dvdsub, &packet);
- if (is_av_sub(type)) {
-#ifdef CONFIG_FFMPEG
- type = decode_avsub(d_dvdsub->sh, &packet, &len, &subpts, &endpts);
- if (type <= 0)
-#endif
- continue;
- }
- if (type == 'm') {
- if (len < 2) continue;
- len = FFMIN(len - 2, AV_RB16(packet));
- packet += 2;
- }
- if (type == 'd') {
- if (d_dvdsub->demuxer->teletext) {
- uint8_t *p = packet;
- p++;
- len--;
- while (len >= 46) {
- int sublen = p[1];
- if (p[0] == 2 || p[0] == 3)
- teletext_control(d_dvdsub->demuxer->teletext,
- TV_VBI_CONTROL_DECODE_DVB, p + 2);
- p += sublen + 2;
- len -= sublen + 2;
- }
- }
- continue;
- }
-#ifdef CONFIG_ASS
- if (opts->ass_enabled) {
- sh_sub_t* sh = d_dvdsub->sh;
- ass_track = sh ? sh->ass_track : NULL;
- if (!ass_track) continue;
- if (type == 'a') { // ssa/ass subs with libass
- ass_process_chunk(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(ass_track, &tmp_subs);
- sub_clear_text(&tmp_subs, MP_NOPTS_VALUE);
- }
- }
- continue;
- }
-#endif
- if (subpts != MP_NOPTS_VALUE) {
- if (endpts == MP_NOPTS_VALUE)
- sub_clear_text(&subs, MP_NOPTS_VALUE);
- if (type == 'a') { // 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;
- }
- sub_add_text(&subs, packet, len, endpts);
- set_osd_subtitle(mpctx, &subs);
- }
- if (d_dvdsub->non_interleaved)
- ds_get_next_pts(d_dvdsub);
- }
- if (!opts->ass_enabled)
- if (sub_clear_text(&subs, curpts))
- set_osd_subtitle(mpctx, &subs);
- }
- if (vo_spudec) {
- spudec_heartbeat(vo_spudec, 90000*curpts);
- if (spudec_changed(vo_spudec))
- vo_osd_changed(OSDTYPE_SPU);
- }
-
- current_module=NULL;
-}
-
-void update_teletext(sh_video_t *sh_video, demuxer_t *demuxer, int reset)
-{
- int page_changed;
-
- if (!demuxer->teletext)
- return;
-
- //Also forcing page update when such ioctl is not supported or call error occured
- if(teletext_control(demuxer->teletext,TV_VBI_CONTROL_IS_CHANGED,&page_changed)!=VBI_CONTROL_TRUE)
- page_changed=1;
-
- if(!page_changed)
- return;
-
- if(teletext_control(demuxer->teletext,TV_VBI_CONTROL_GET_VBIPAGE,&vo_osd_teletext_page)!=VBI_CONTROL_TRUE)
- vo_osd_teletext_page=NULL;
- if(teletext_control(demuxer->teletext,TV_VBI_CONTROL_GET_HALF_PAGE,&vo_osd_teletext_half)!=VBI_CONTROL_TRUE)
- vo_osd_teletext_half=0;
- if(teletext_control(demuxer->teletext,TV_VBI_CONTROL_GET_MODE,&vo_osd_teletext_mode)!=VBI_CONTROL_TRUE)
- vo_osd_teletext_mode=0;
- if(teletext_control(demuxer->teletext,TV_VBI_CONTROL_GET_FORMAT,&vo_osd_teletext_format)!=VBI_CONTROL_TRUE)
- vo_osd_teletext_format=0;
- vo_osd_changed(OSDTYPE_TELETEXT);
-
- teletext_control(demuxer->teletext,TV_VBI_CONTROL_MARK_UNCHANGED,NULL);
-}
-
-int select_audio(demuxer_t* demuxer, int audio_id, char* audio_lang)
-{
- if (audio_id == -1)
- audio_id = demuxer_audio_track_by_lang_and_default(demuxer, audio_lang);
- if (audio_id != -1) // -1 (automatic) is the default behaviour of demuxers
- demuxer_switch_audio(demuxer, audio_id);
- if (audio_id == -2) { // some demuxers don't yet know how to switch to no sound
- demuxer->audio->id = -2;
- demuxer->audio->sh = NULL;
- }
- return demuxer->audio->id;
-}
-
-bool attachment_is_font(struct demux_attachment *att)
-{
- if (!att->name || !att->type || !att->data || !att->data_size)
- return false;
- // match against MIME types
- if (strcmp(att->type, "application/x-truetype-font") == 0
- || strcmp(att->type, "application/x-font") == 0)
- return true;
- // fallback: match against file extension
- if (strlen(att->name) > 4) {
- char *ext = att->name + strlen(att->name) - 4;
- if (strcasecmp(ext, ".ttf") == 0 || strcasecmp(ext, ".ttc") == 0
- || strcasecmp(ext, ".otf") == 0)
- return true;
- }
- return false;
-}
-
-/* Parse -noconfig common to both programs */
-int disable_system_conf=0;
-int disable_user_conf=0;
-
-/* Disable all configuration files */
-static void noconfig_all(void)
-{
- disable_system_conf = 1;
- disable_user_conf = 1;
-}
-
-const m_option_t noconfig_opts[] = {
- {"all", noconfig_all, CONF_TYPE_FUNC, CONF_GLOBAL|CONF_NOCFG|CONF_PRE_PARSE, 0, 0, NULL},
- {"system", &disable_system_conf, CONF_TYPE_FLAG, CONF_GLOBAL|CONF_NOCFG|CONF_PRE_PARSE, 0, 1, NULL},
- {"user", &disable_user_conf, CONF_TYPE_FLAG, CONF_GLOBAL|CONF_NOCFG|CONF_PRE_PARSE, 0, 1, NULL},
- {NULL, NULL, 0, 0, 0, 0, NULL}
-};
-
diff --git a/mpcommon.h b/mpcommon.h
index d34be23e32..82b860bd87 100644
--- a/mpcommon.h
+++ b/mpcommon.h
@@ -19,35 +19,9 @@
#ifndef MPLAYER_MPCOMMON_H
#define MPLAYER_MPCOMMON_H
-#include <stdbool.h>
-
-struct subtitle;
-
-extern double sub_last_pts;
-extern struct ass_track *ass_track;
-extern struct subtitle *vo_sub_last;
-
-extern int disable_system_conf;
-extern int disable_user_conf;
+// both int64_t and double should be able to represent this exactly
+#define MP_NOPTS_VALUE (-1LL<<63)
extern const char *mplayer_version;
-struct MPContext;
-struct demuxer;
-struct demux_stream;
-struct demux_attachment;
-struct sh_video;
-struct MPOpts;
-
-void print_version(const char* name);
-void update_subtitles(struct MPContext *mpctx, struct MPOpts *opts,
- struct sh_video *sh_video, double refpts,
- double sub_offset, struct demux_stream *d_dvdsub,
- int reset);
-void update_teletext(struct sh_video *sh_video, struct demuxer *demuxer,
- int reset);
-int select_audio(struct demuxer *demuxer, int audio_id, char *audio_lang);
-void set_osd_subtitle(struct MPContext *mpctx, struct subtitle *subs);
-bool attachment_is_font(struct demux_attachment *att);
-
#endif /* MPLAYER_MPCOMMON_H */
diff --git a/mplayer.c b/mplayer.c
index e5c9019ccc..fd7dbc6fab 100644
--- a/mplayer.c
+++ b/mplayer.c
@@ -71,13 +71,19 @@
#include "libavutil/avstring.h"
-#include "subreader.h"
+#include "sub/subreader.h"
+#include "sub/dec_sub.h"
#include "mp_osd.h"
#include "libvo/video_out.h"
-#include "libvo/font_load.h"
-#include "libvo/sub.h"
+#include "sub/font_load.h"
+#include "sub/sub.h"
+#include "ffmpeg_files/intreadwrite.h"
+#include "sub/av_sub.h"
+#include "libmpcodecs/dec_teletext.h"
+#include "cpudetect.h"
+#include "version.h"
#ifdef CONFIG_X11
#include "libvo/x11_common.h"
@@ -89,8 +95,8 @@
#include "edl.h"
-#include "spudec.h"
-#include "vobsub.h"
+#include "sub/spudec.h"
+#include "sub/vobsub.h"
#include "osdep/getch2.h"
#include "osdep/timer.h"
@@ -328,7 +334,7 @@ char *vobsub_name=NULL;
int subcc_enabled=0;
int suboverlap_enabled = 1;
-#include "ass_mp.h"
+#include "sub/ass_mp.h"
char* current_module=NULL; // for debugging
@@ -595,6 +601,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;
@@ -608,6 +623,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";
@@ -624,6 +645,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);
}
@@ -640,6 +662,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;
@@ -868,9 +891,10 @@ static int cfg_include(m_option_t *conf, char *filename)
static void parse_cfgfiles(struct MPContext *mpctx, m_config_t* conf)
{
+ struct MPOpts *opts = &mpctx->opts;
char *conffile;
int conffile_fd;
-if (!disable_system_conf &&
+ if (!(opts->noconfig & 2) &&
m_config_parse_config_file(conf, MPLAYER_CONFDIR "/mplayer.conf") < 0)
exit_player(mpctx, EXIT_NONE);
if ((conffile = get_path("")) == NULL) {
@@ -890,7 +914,7 @@ if ((conffile = get_path("")) == NULL) {
write(conffile_fd, default_config, strlen(default_config));
close(conffile_fd);
}
- if (!disable_user_conf &&
+ if (!(opts->noconfig & 1) &&
m_config_parse_config_file(conf, conffile) < 0)
exit_player(mpctx, EXIT_NONE);
free(conffile);
@@ -1067,31 +1091,30 @@ void add_subtitles(struct MPContext *mpctx, char *filename, float fps, int noerr
struct MPOpts *opts = &mpctx->opts;
sub_data *subd = NULL;
struct ass_track *asst = NULL;
+ bool is_native_ass = false;
- if (filename == NULL || mpctx->set_of_sub_size >= MAX_SUBTITLE_FILES) {
+ if (filename == NULL || mpctx->set_of_sub_size >= MAX_SUBTITLE_FILES)
return;
- }
#ifdef CONFIG_ASS
if (opts->ass_enabled) {
#ifdef CONFIG_ICONV
- asst = ass_read_stream(ass_library, filename, sub_cp);
+ asst = mp_ass_read_stream(ass_library, filename, sub_cp);
#else
- asst = ass_read_stream(ass_library, filename, 0);
+ asst = mp_ass_read_stream(ass_library, filename, 0);
#endif
+ is_native_ass = asst;
if (!asst) {
- subd = sub_read_file(filename, fps);
+ subd = sub_read_file(filename, fps, &mpctx->opts);
if (subd) {
- asst = ass_read_subdata(ass_library, subd, fps);
- if (asst) {
- sub_free(subd);
- subd = NULL;
- }
+ asst = mp_ass_read_subdata(ass_library, subd, fps);
+ sub_free(subd);
+ subd = NULL;
}
}
} else
#endif
- subd = sub_read_file(filename, fps);
+ subd = sub_read_file(filename, fps, &mpctx->opts);
if (!asst && !subd) {
@@ -1102,6 +1125,7 @@ void add_subtitles(struct MPContext *mpctx, char *filename, float fps, int noerr
mpctx->set_of_ass_tracks[mpctx->set_of_sub_size] = asst;
mpctx->set_of_subtitles[mpctx->set_of_sub_size] = subd;
+ mpctx->track_was_native_ass[mpctx->set_of_sub_size] = is_native_ass;
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_FILE_SUB_ID=%d\n", mpctx->set_of_sub_size);
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_FILE_SUB_FILENAME=%s\n",
filename_recode(filename));
@@ -1795,6 +1819,209 @@ double playing_audio_pts(struct MPContext *mpctx)
mpctx->audio_out->get_delay();
}
+static bool is_av_sub(int type)
+{
+ return type == 'b' || type == 'p' || type == 'x';
+}
+
+void update_subtitles(struct MPContext *mpctx, double refpts,
+ double sub_offset, bool reset)
+{
+ struct MPOpts *opts = &mpctx->opts;
+ struct sh_video *sh_video = mpctx->sh_video;
+ struct demux_stream *d_sub = mpctx->d_sub;
+ double curpts = refpts + sub_delay;
+ unsigned char *packet=NULL;
+ int len;
+ 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);
+ if (vo_spudec) {
+ spudec_reset(vo_spudec);
+ vo_osd_changed(OSDTYPE_SPU);
+ }
+#ifdef CONFIG_FFMPEG
+ if (is_av_sub(type))
+ reset_avsub(sh_sub);
+#endif
+ return;
+ }
+ // find sub
+ if (mpctx->subdata) {
+ if (sub_fps==0) sub_fps = sh_video ? sh_video->fps : 25;
+ current_module = "find_sub";
+ find_sub(mpctx, mpctx->subdata, curpts *
+ (mpctx->subdata->sub_uses_time ? 100. : sub_fps));
+ if (vo_sub)
+ mpctx->vo_sub_last = vo_sub;
+ }
+
+ // DVD sub:
+ if (vobsub_id >= 0 || type == 'v') {
+ int timestamp;
+ current_module = "spudec";
+ /* Get a sub packet from the DVD or a vobsub */
+ while(1) {
+ // Vobsub
+ len = 0;
+ if (vo_vobsub) {
+ if (curpts >= 0) {
+ len = vobsub_get_packet(vo_vobsub, curpts,
+ (void**)&packet, &timestamp);
+ if (len > 0) {
+ mp_dbg(MSGT_CPLAYER,MSGL_V,"\rVOB sub: len=%d v_pts=%5.3f v_timer=%5.3f sub=%5.3f ts=%d \n",len,refpts,sh_video->timer,timestamp / 90000.0,timestamp);
+ }
+ }
+ } else {
+ // DVD sub
+ len = ds_get_packet_sub(d_sub, (unsigned char**)&packet);
+ if (len > 0) {
+ // XXX This is wrong, sh_video->pts can be arbitrarily
+ // much behind demuxing position. Unfortunately using
+ // d_video->pts which would have been the simplest
+ // improvement doesn't work because mpeg specific hacks
+ // in video.c set d_video->pts to 0.
+ float x = d_sub->pts - refpts;
+ if (x > -20 && x < 20) // prevent missing subs on pts reset
+ timestamp = 90000*d_sub->pts;
+ else timestamp = 90000*curpts;
+ mp_dbg(MSGT_CPLAYER, MSGL_V, "\rDVD sub: len=%d "
+ "v_pts=%5.3f s_pts=%5.3f ts=%d \n", len,
+ refpts, d_sub->pts, timestamp);
+ }
+ }
+ if (len<=0 || !packet) break;
+ // create it only here, since with some broken demuxers we might
+ // type = v but no DVD sub and we currently do not change the
+ // "original frame size" ever after init, leading to wrong-sized
+ // PGS subtitles.
+ if (!vo_spudec)
+ vo_spudec = spudec_new(NULL);
+ if (vo_vobsub || timestamp >= 0)
+ spudec_assemble(vo_spudec, packet, len, timestamp);
+ }
+ } else if (is_text_sub(type) || is_av_sub(type) || type == 'd') {
+ if (type == 'd' && !d_sub->demuxer->teletext) {
+ tt_stream_props tsp = {0};
+ void *ptr = &tsp;
+ if (teletext_control(NULL, TV_VBI_CONTROL_START, &ptr) == VBI_CONTROL_TRUE)
+ d_sub->demuxer->teletext = ptr;
+ }
+ if (d_sub->non_interleaved)
+ ds_get_next_pts(d_sub);
+
+ while (d_sub->first) {
+ double subpts = ds_get_next_pts(d_sub) + sub_offset;
+ if (subpts > curpts) {
+ // Libass handled subs can be fed to it in advance
+ if (!opts->ass_enabled || !is_text_sub(type))
+ break;
+ // Try to avoid demuxing whole file at once
+ if (d_sub->non_interleaved && subpts > curpts + 1)
+ break;
+ }
+ double duration = d_sub->first->duration;
+ len = ds_get_packet_sub(d_sub, &packet);
+ if (is_av_sub(type)) {
+#ifdef CONFIG_FFMPEG
+ decode_avsub(sh_sub, packet, len, subpts, duration);
+#endif
+ continue;
+ }
+ if (type == 'm') {
+ if (len < 2) continue;
+ len = FFMIN(len - 2, AV_RB16(packet));
+ packet += 2;
+ }
+ if (type == 'd') {
+ if (d_sub->demuxer->teletext) {
+ uint8_t *p = packet;
+ p++;
+ len--;
+ while (len >= 46) {
+ int sublen = p[1];
+ if (p[0] == 2 || p[0] == 3)
+ teletext_control(d_sub->demuxer->teletext,
+ TV_VBI_CONTROL_DECODE_DVB, p + 2);
+ p += sublen + 2;
+ len -= sublen + 2;
+ }
+ }
+ continue;
+ }
+ if (sh_sub && sh_sub->active) {
+ sub_decode(sh_sub, mpctx->osd, packet, len, subpts, duration);
+ continue;
+ }
+ if (subpts != MP_NOPTS_VALUE) {
+ if (duration < 0)
+ sub_clear_text(&subs, MP_NOPTS_VALUE);
+ if (type == 'a') { // 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 = MP_NOPTS_VALUE;
+ if (subpts != MP_NOPTS_VALUE && duration >= 0)
+ endpts = subpts + duration;
+ sub_add_text(&subs, packet, len, endpts);
+ set_osd_subtitle(mpctx, &subs);
+ }
+ if (d_sub->non_interleaved)
+ ds_get_next_pts(d_sub);
+ }
+ if (!opts->ass_enabled)
+ if (sub_clear_text(&subs, curpts))
+ set_osd_subtitle(mpctx, &subs);
+ }
+ if (vo_spudec) {
+ spudec_heartbeat(vo_spudec, 90000*curpts);
+ if (spudec_changed(vo_spudec))
+ vo_osd_changed(OSDTYPE_SPU);
+ }
+
+ current_module=NULL;
+}
+
+static void update_teletext(sh_video_t *sh_video, demuxer_t *demuxer, int reset)
+{
+ int page_changed;
+
+ if (!demuxer->teletext)
+ return;
+
+ //Also forcing page update when such ioctl is not supported or call error occured
+ if(teletext_control(demuxer->teletext,TV_VBI_CONTROL_IS_CHANGED,&page_changed)!=VBI_CONTROL_TRUE)
+ page_changed=1;
+
+ if(!page_changed)
+ return;
+
+ if(teletext_control(demuxer->teletext,TV_VBI_CONTROL_GET_VBIPAGE,&vo_osd_teletext_page)!=VBI_CONTROL_TRUE)
+ vo_osd_teletext_page=NULL;
+ if(teletext_control(demuxer->teletext,TV_VBI_CONTROL_GET_HALF_PAGE,&vo_osd_teletext_half)!=VBI_CONTROL_TRUE)
+ vo_osd_teletext_half=0;
+ if(teletext_control(demuxer->teletext,TV_VBI_CONTROL_GET_MODE,&vo_osd_teletext_mode)!=VBI_CONTROL_TRUE)
+ vo_osd_teletext_mode=0;
+ if(teletext_control(demuxer->teletext,TV_VBI_CONTROL_GET_FORMAT,&vo_osd_teletext_format)!=VBI_CONTROL_TRUE)
+ vo_osd_teletext_format=0;
+ vo_osd_changed(OSDTYPE_TELETEXT);
+
+ teletext_control(demuxer->teletext,TV_VBI_CONTROL_MARK_UNCHANGED,NULL);
+}
+
static int check_framedrop(struct MPContext *mpctx, double frame_time) {
struct MPOpts *opts = &mpctx->opts;
// check for frame-drop:
@@ -2735,7 +2962,7 @@ static void reinit_decoders(struct MPContext *mpctx)
{
reinit_video_chain(mpctx);
reinit_audio_chain(mpctx);
- mp_property_do("sub", M_PROPERTY_SET, &mpctx->global_sub_pos, mpctx);
+ mp_property_do("sub", M_PROPERTY_SET, &(int){mpctx->global_sub_pos}, mpctx);
}
static void seek_reset(struct MPContext *mpctx)
@@ -2756,9 +2983,8 @@ static void seek_reset(struct MPContext *mpctx)
// be completely wrong (probably 0).
mpctx->sh_video->pts = mpctx->d_video->pts + mpctx->video_offset;
mpctx->video_pts = mpctx->sh_video->pts;
- update_subtitles(mpctx, &mpctx->opts, mpctx->sh_video,
- mpctx->sh_video->pts, mpctx->video_offset,
- mpctx->d_sub, 1);
+ update_subtitles(mpctx, mpctx->sh_video->pts, mpctx->video_offset,
+ true);
update_teletext(mpctx->sh_video, mpctx->demuxer, 1);
}
@@ -2769,8 +2995,8 @@ static void seek_reset(struct MPContext *mpctx)
mpctx->sh_audio->a_buffer_len = 0;
mpctx->sh_audio->a_out_buffer_len = 0;
if (!mpctx->sh_video)
- update_subtitles(mpctx, &mpctx->opts, NULL, mpctx->sh_audio->pts,
- mpctx->video_offset, mpctx->d_sub, 1);
+ update_subtitles(mpctx, mpctx->sh_audio->pts,
+ mpctx->video_offset, true);
}
if (vo_vobsub && mpctx->sh_video) {
@@ -2797,7 +3023,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;
@@ -3108,8 +3334,7 @@ static void run_playloop(struct MPContext *mpctx)
if (end_at.type == END_AT_TIME && end_at.pos < a_pos)
mpctx->stop_play = PT_NEXT_ENTRY;
- update_subtitles(mpctx, &mpctx->opts, NULL, a_pos, mpctx->video_offset,
- mpctx->d_sub, 0);
+ update_subtitles(mpctx, a_pos, mpctx->video_offset, false);
update_osd_msg(mpctx);
} else {
@@ -3180,12 +3405,11 @@ static void run_playloop(struct MPContext *mpctx)
if (!frame_time_remaining && blit_frame) {
struct sh_video *sh_video = mpctx->sh_video;
mpctx->video_pts = sh_video->pts;
- update_subtitles(mpctx, &mpctx->opts, sh_video, sh_video->pts,
- mpctx->video_offset, mpctx->d_sub, 0);
+ update_subtitles(mpctx, sh_video->pts, mpctx->video_offset, false);
update_teletext(sh_video, mpctx->demuxer, 0);
update_osd_msg(mpctx);
struct vf_instance *vf = sh_video->vfilter;
- vf->control(vf, VFCTRL_DRAW_EOSD, NULL);
+ vf->control(vf, VFCTRL_DRAW_EOSD, mpctx->osd);
vf->control(vf, VFCTRL_DRAW_OSD, mpctx->osd);
vo_osd_changed(0);
@@ -3509,11 +3733,12 @@ static void build_ordered_chapter_timeline(struct MPContext *mpctx)
* specify chapter end times that are one frame too early;
* we don't want to try seeking over a one frame gap. */
int64_t join_diff = c->start - starttime - prev_part_offset;
- if (part_count == 0 || FFABS(join_diff) > opts->chapter_merge_threshold
+ if (part_count == 0
+ || FFABS(join_diff) > opts->chapter_merge_threshold * 1000000
|| sources + j != timeline[part_count - 1].source) {
timeline[part_count].source = sources + j;
- timeline[part_count].start = starttime / 1000.;
- timeline[part_count].source_start = c->start / 1000.;
+ timeline[part_count].start = starttime / 1e9;
+ timeline[part_count].source_start = c->start / 1e9;
prev_part_offset = c->start - starttime;
part_count++;
} else if (part_count > 0 && join_diff) {
@@ -3523,12 +3748,12 @@ static void build_ordered_chapter_timeline(struct MPContext *mpctx)
"offset %d ms.\n", i, (int) join_diff);
starttime += join_diff;
}
- chapters[num_chapters].start = starttime / 1000.;
+ chapters[num_chapters].start = starttime / 1e9;
chapters[num_chapters].name = talloc_strdup(chapters, c->name);
starttime += c->end - c->start;
num_chapters++;
}
- timeline[part_count].start = starttime / 1000.;
+ timeline[part_count].start = starttime / 1e9;
if (!part_count) {
// None of the parts come from the file itself???
@@ -3543,7 +3768,7 @@ static void build_ordered_chapter_timeline(struct MPContext *mpctx)
timeline[part_count].start);
if (missing_time)
mp_msg(MSGT_CPLAYER, MSGL_ERR, "There are %.3f seconds missing "
- "from the timeline!\n", missing_time / 1000.);
+ "from the timeline!\n", missing_time / 1e9);
mp_msg(MSGT_CPLAYER, MSGL_V, "Source files:\n");
for (int i = 0; i < num_sources; i++)
mp_msg(MSGT_CPLAYER, MSGL_V, "%d: %s\n", i,
@@ -3574,12 +3799,80 @@ static int read_keys(void *ctx, int fd)
return mplayer_get_key(ctx, 0);
}
+static bool attachment_is_font(struct demux_attachment *att)
+{
+ if (!att->name || !att->type || !att->data || !att->data_size)
+ return false;
+ // match against MIME types
+ if (strcmp(att->type, "application/x-truetype-font") == 0
+ || strcmp(att->type, "application/x-font") == 0)
+ return true;
+ // fallback: match against file extension
+ if (strlen(att->name) > 4) {
+ char *ext = att->name + strlen(att->name) - 4;
+ if (strcasecmp(ext, ".ttf") == 0 || strcasecmp(ext, ".ttc") == 0
+ || strcasecmp(ext, ".otf") == 0)
+ return true;
+ }
+ return false;
+}
+
+static int select_audio(demuxer_t *demuxer, int audio_id, char *audio_lang)
+{
+ if (audio_id == -1)
+ audio_id = demuxer_audio_track_by_lang_and_default(demuxer, audio_lang);
+ if (audio_id != -1) // -1 (automatic) is the default behaviour of demuxers
+ demuxer_switch_audio(demuxer, audio_id);
+ if (audio_id == -2) { // some demuxers don't yet know how to switch to no sound
+ demuxer->audio->id = -2;
+ demuxer->audio->sh = NULL;
+ }
+ return demuxer->audio->id;
+}
+
+static void print_version(const char* name)
+{
+ mp_msg(MSGT_CPLAYER, MSGL_INFO, MP_TITLE, name);
+
+ /* Test for CPU capabilities (and corresponding OS support) for optimizing */
+ GetCpuCaps(&gCpuCaps);
+#if ARCH_X86
+ mp_msg(MSGT_CPLAYER, MSGL_V,
+ "CPUflags: MMX: %d MMX2: %d 3DNow: %d 3DNowExt: %d SSE: %d SSE2: %d SSSE3: %d\n",
+ gCpuCaps.hasMMX, gCpuCaps.hasMMX2,
+ gCpuCaps.has3DNow, gCpuCaps.has3DNowExt,
+ gCpuCaps.hasSSE, gCpuCaps.hasSSE2, gCpuCaps.hasSSSE3);
+#if CONFIG_RUNTIME_CPUDETECT
+ mp_tmsg(MSGT_CPLAYER,MSGL_V, "Compiled with runtime CPU detection.\n");
+#else
+ mp_tmsg(MSGT_CPLAYER,MSGL_V, "Compiled for x86 CPU with extensions:");
+if (HAVE_MMX)
+ mp_msg(MSGT_CPLAYER,MSGL_V," MMX");
+if (HAVE_MMX2)
+ mp_msg(MSGT_CPLAYER,MSGL_V," MMX2");
+if (HAVE_AMD3DNOW)
+ mp_msg(MSGT_CPLAYER,MSGL_V," 3DNow");
+if (HAVE_AMD3DNOWEXT)
+ mp_msg(MSGT_CPLAYER,MSGL_V," 3DNowExt");
+if (HAVE_SSE)
+ mp_msg(MSGT_CPLAYER,MSGL_V," SSE");
+if (HAVE_SSE2)
+ mp_msg(MSGT_CPLAYER,MSGL_V," SSE2");
+if (HAVE_SSSE3)
+ mp_msg(MSGT_CPLAYER,MSGL_V," SSSE3");
+if (HAVE_CMOV)
+ mp_msg(MSGT_CPLAYER,MSGL_V," CMOV");
+ mp_msg(MSGT_CPLAYER,MSGL_V,"\n");
+#endif /* CONFIG_RUNTIME_CPUDETECT */
+#endif /* ARCH_X86 */
+}
/* This preprocessor directive is a hack to generate a mplayer-nomain.o object
* file for some tools to link against. */
#ifndef DISABLE_MAIN
int main(int argc,char* argv[]){
-
+ if (argc > 1 && !strcmp(argv[1], "-leak-report"))
+ talloc_enable_leak_report();
char * mem_ptr;
@@ -3798,7 +4091,7 @@ if(!codecs_file || !parse_codec_cfg(codecs_file)){
#endif
#ifdef CONFIG_ASS
- ass_library = ass_init();
+ ass_library = mp_ass_init();
#endif
#ifdef HAVE_RTC
@@ -4413,14 +4706,14 @@ if(vo_spudec==NULL &&
mpctx->sub_counts[SUB_SOURCE_SUBS] = mpctx->set_of_sub_size;
if (select_subtitle(mpctx)) {
- if(subdata)
+ if(mpctx->subdata)
switch (stream_dump_type) {
- case 3: list_sub_file(subdata); break;
- case 4: dump_mpsub(subdata, mpctx->sh_video->fps); break;
- case 6: dump_srt(subdata, mpctx->sh_video->fps); break;
- case 7: dump_microdvd(subdata, mpctx->sh_video->fps); break;
- case 8: dump_jacosub(subdata, mpctx->sh_video->fps); break;
- case 9: dump_sami(subdata, mpctx->sh_video->fps); break;
+ case 3: list_sub_file(mpctx->subdata); break;
+ case 4: dump_mpsub(mpctx->subdata, mpctx->sh_video->fps); break;
+ case 6: dump_srt(mpctx->subdata, mpctx->sh_video->fps); break;
+ case 7: dump_microdvd(mpctx->subdata, mpctx->sh_video->fps); break;
+ case 8: dump_jacosub(mpctx->subdata, mpctx->sh_video->fps); break;
+ case 9: dump_sami(mpctx->subdata, mpctx->sh_video->fps); break;
}
}
@@ -4643,10 +4936,10 @@ if(mpctx->set_of_sub_size > 0) {
}
mpctx->set_of_sub_size = 0;
}
-vo_sub_last = vo_sub=NULL;
-subdata=NULL;
+mpctx->vo_sub_last = vo_sub=NULL;
+mpctx->subdata=NULL;
#ifdef CONFIG_ASS
-ass_track = NULL;
+mpctx->osd->ass_track = NULL;
if(ass_library)
ass_clear_fonts(ass_library);
#endif
diff --git a/mplayer.h b/mplayer.h
index 7a8eec34e8..4f0c927763 100644
--- a/mplayer.h
+++ b/mplayer.h
@@ -19,6 +19,8 @@
#ifndef MPLAYER_MPLAYER_H
#define MPLAYER_MPLAYER_H
+#include <stdlib.h>
+
#include "mp_msg.h"
extern char* current_module;
@@ -57,5 +59,8 @@ static inline void exit_player_bad(const char *how)
}
struct MPContext;
+struct subtitle;
+
+void set_osd_subtitle(struct MPContext *mpctx, struct subtitle *subs);
#endif /* MPLAYER_MPLAYER_H */
diff --git a/options.h b/options.h
index 12ac475f9e..0fb0a7d809 100644
--- a/options.h
+++ b/options.h
@@ -39,6 +39,7 @@ typedef struct MPOpts {
int ordered_chapters;
int chapter_merge_threshold;
int quiet;
+ int noconfig;
float stream_cache_min_percent;
float stream_cache_seek_min_percent;
int chapterrange[2];
diff --git a/stream/stream_dvdnav.c b/stream/stream_dvdnav.c
index bbd2b2085b..21522f8b6b 100644
--- a/stream/stream_dvdnav.c
+++ b/stream/stream_dvdnav.c
@@ -33,7 +33,7 @@
#include "stream_dvdnav.h"
#include "libvo/video_out.h"
#include "libavutil/common.h"
-#include "spudec.h"
+#include "sub/spudec.h"
#include "m_option.h"
#include "m_struct.h"
#include "stream_dvd_common.h"
diff --git a/ass_mp.c b/sub/ass_mp.c
index 31acb521b8..98602ace03 100644
--- a/ass_mp.c
+++ b/sub/ass_mp.c
@@ -22,6 +22,7 @@
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
+#include <stdbool.h>
#include <ass/ass.h>
#include <ass/ass_types.h>
@@ -69,9 +70,7 @@ extern char *sub_cp;
static char *sub_cp = 0;
#endif
-void process_force_style(ASS_Track *track);
-
-ASS_Track *ass_default_track(ASS_Library *library)
+ASS_Track *mp_ass_default_track(ASS_Library *library)
{
ASS_Track *track = ass_new_track(library);
@@ -84,13 +83,9 @@ ASS_Track *ass_default_track(ASS_Library *library)
ass_read_styles(track, ass_styles_file, sub_cp);
if (track->n_styles == 0) {
- ASS_Style *style;
- int sid;
- double fs;
- uint32_t c1, c2;
-
- sid = ass_alloc_style(track);
- style = track->styles + sid;
+ track->Kerning = true;
+ int sid = ass_alloc_style(track);
+ ASS_Style *style = track->styles + sid;
style->Name = strdup("Default");
style->FontName = (font_fontconfig >= 0
&& sub_font_name) ? strdup(sub_font_name)
@@ -98,30 +93,34 @@ ASS_Track *ass_default_track(ASS_Library *library)
&& font_name) ? strdup(font_name) : strdup("Sans");
style->treat_fontname_as_pattern = 1;
- fs = track->PlayResY * text_font_scale_factor / 100.;
- // approximate autoscale coefficients
+ double fs = track->PlayResY * text_font_scale_factor / 100.;
+ /* The font size is always proportional to video height only;
+ * real -subfont-autoscale behavior is not implemented.
+ * Apply a correction that corresponds to about 4:3 aspect ratio
+ * video to get a size somewhat closer to what non-libass rendering
+ * would produce with the same text_font_scale_factor
+ * and subtitle_autoscale.
+ */
if (subtitle_autoscale == 2)
fs *= 1.3;
else if (subtitle_autoscale == 3)
- fs *= 1.4;
- style->FontSize = fs;
+ fs *= 1.7;
+ uint32_t c1 = 0xFFFFFF00;
+ uint32_t c2 = 0x00000000;
if (ass_color)
c1 = strtoll(ass_color, NULL, 16);
- else
- c1 = 0xFFFF0000;
if (ass_border_color)
c2 = strtoll(ass_border_color, NULL, 16);
- else
- c2 = 0x00000000;
+ style->FontSize = fs;
style->PrimaryColour = c1;
style->SecondaryColour = c1;
style->OutlineColour = c2;
style->BackColour = 0x00000000;
style->BorderStyle = 1;
style->Alignment = 2;
- style->Outline = 2;
+ style->Outline = fs / 16;
style->MarginL = 10;
style->MarginR = 10;
style->MarginV = 5;
@@ -154,7 +153,7 @@ static int check_duplicate_plaintext_event(ASS_Track *track)
* note: assumes that subtitle is _not_ fps-based; caller must manually correct
* Start and Duration in other case.
**/
-int ass_process_subtitle(ASS_Track *track, subtitle *sub)
+static int ass_process_subtitle(ASS_Track *track, subtitle *sub)
{
int eid;
ASS_Event *event;
@@ -210,13 +209,13 @@ int ass_process_subtitle(ASS_Track *track, subtitle *sub)
* \param fps video framerate
* \return newly allocated ASS_Track, filled with subtitles from subdata
*/
-ASS_Track *ass_read_subdata(ASS_Library *library, sub_data *subdata,
- double fps)
+ASS_Track *mp_ass_read_subdata(ASS_Library *library, sub_data *subdata,
+ double fps)
{
ASS_Track *track;
int i;
- track = ass_default_track(library);
+ track = mp_ass_default_track(library);
track->name = subdata->filename ? strdup(subdata->filename) : 0;
for (i = 0; i < subdata->sub_num; ++i) {
@@ -231,7 +230,8 @@ ASS_Track *ass_read_subdata(ASS_Library *library, sub_data *subdata,
return track;
}
-ASS_Track *ass_read_stream(ASS_Library *library, const char *fname, char *charset)
+ASS_Track *mp_ass_read_stream(ASS_Library *library, const char *fname,
+ char *charset)
{
int i;
char *buf = NULL;
@@ -280,7 +280,7 @@ ASS_Track *ass_read_stream(ASS_Library *library, const char *fname, char *charse
return track;
}
-void ass_configure(ASS_Renderer *priv, int w, int h, int unscaled)
+void mp_ass_configure(ASS_Renderer *priv, int w, int h, bool unscaled)
{
int hinting;
ass_set_frame_size(priv, w, h);
@@ -295,7 +295,7 @@ void ass_configure(ASS_Renderer *priv, int w, int h, int unscaled)
ass_set_line_spacing(priv, ass_line_spacing);
}
-void ass_configure_fonts(ASS_Renderer *priv)
+void mp_ass_configure_fonts(ASS_Renderer *priv)
{
char *dir, *path, *family;
dir = get_path("fonts");
@@ -327,7 +327,7 @@ static void message_callback(int level, const char *format, va_list va, void *ct
mp_msg(MSGT_ASS, level, "\n");
}
-ASS_Library *ass_init(void)
+ASS_Library *mp_ass_init(void)
{
ASS_Library *priv;
char *path = get_path("fonts");
@@ -342,7 +342,7 @@ ASS_Library *ass_init(void)
int ass_force_reload = 0; // flag set if global ass-related settings were changed
-ASS_Image *ass_mp_render_frame(ASS_Renderer *priv, ASS_Track *track,
+ASS_Image *mp_ass_render_frame(ASS_Renderer *priv, ASS_Track *track,
long long now, int *detect_change)
{
if (ass_force_reload) {
diff --git a/ass_mp.h b/sub/ass_mp.h
index 0694426898..965b063403 100644
--- a/ass_mp.h
+++ b/sub/ass_mp.h
@@ -22,6 +22,7 @@
#define MPLAYER_ASS_MP_H
#include <stdint.h>
+#include <stdbool.h>
#include "config.h"
#include "subreader.h"
@@ -43,18 +44,18 @@ extern char *ass_border_color;
extern char *ass_styles_file;
extern int ass_hinting;
-ASS_Track *ass_default_track(ASS_Library *library);
-int ass_process_subtitle(ASS_Track *track, subtitle *sub);
-ASS_Track *ass_read_subdata(ASS_Library *library, sub_data *subdata,
- double fps);
-ASS_Track *ass_read_stream(ASS_Library *library, const char *fname, char *charset);
+ASS_Track *mp_ass_default_track(ASS_Library *library);
+ASS_Track *mp_ass_read_subdata(ASS_Library *library, sub_data *subdata,
+ double fps);
+ASS_Track *mp_ass_read_stream(ASS_Library *library, const char *fname,
+ char *charset);
-void ass_configure(ASS_Renderer *priv, int w, int h, int hinting);
-void ass_configure_fonts(ASS_Renderer *priv);
-ASS_Library *ass_init(void);
+void mp_ass_configure(ASS_Renderer *priv, int w, int h, bool unscaled);
+void mp_ass_configure_fonts(ASS_Renderer *priv);
+ASS_Library *mp_ass_init(void);
extern int ass_force_reload;
-ASS_Image *ass_mp_render_frame(ASS_Renderer *priv, ASS_Track *track,
+ASS_Image *mp_ass_render_frame(ASS_Renderer *priv, ASS_Track *track,
long long now, int *detect_change);
#else /* CONFIG_ASS */
diff --git a/av_sub.c b/sub/av_sub.c
index e850e2ffa2..a68fbce083 100644
--- a/av_sub.c
+++ b/sub/av_sub.c
@@ -19,7 +19,7 @@
#include <libavcodec/avcodec.h>
#include "libmpdemux/stheader.h"
-#include "libvo/sub.h"
+#include "sub.h"
#include "spudec.h"
#include "av_sub.h"
@@ -35,12 +35,11 @@ void reset_avsub(struct sh_sub *sh)
* Decode a subtitle packet via libavcodec.
* \return < 0 on error, > 0 if further processing is needed
*/
-int decode_avsub(struct sh_sub *sh, uint8_t **data, int *size,
- double *pts, double *endpts)
+int decode_avsub(struct sh_sub *sh, uint8_t *data, int size,
+ double pts, double duration)
{
AVCodecContext *ctx = sh->context;
enum CodecID cid = CODEC_ID_NONE;
- int new_type = 0;
int res;
int got_sub;
AVSubtitle sub;
@@ -56,11 +55,11 @@ int decode_avsub(struct sh_sub *sh, uint8_t **data, int *size,
}
av_init_packet(&pkt);
- pkt.data = *data;
- pkt.size = *size;
- pkt.pts = *pts * 1000;
- if (*pts != MP_NOPTS_VALUE && *endpts != MP_NOPTS_VALUE)
- pkt.convergence_duration = (*endpts - *pts) * 1000;
+ pkt.data = data;
+ pkt.size = size;
+ pkt.pts = pts * 1000;
+ if (duration >= 0)
+ pkt.convergence_duration = duration * 1000;
if (!ctx) {
AVCodec *sub_codec;
avcodec_init();
@@ -78,13 +77,16 @@ int decode_avsub(struct sh_sub *sh, uint8_t **data, int *size,
res = avcodec_decode_subtitle2(ctx, &sub, &got_sub, &pkt);
if (res < 0)
return res;
- if (*pts != MP_NOPTS_VALUE) {
+ if (pts != MP_NOPTS_VALUE) {
if (sub.end_display_time > sub.start_display_time)
- *endpts = *pts + sub.end_display_time / 1000.0;
- *pts += sub.start_display_time / 1000.0;
+ duration = (sub.end_display_time - sub.start_display_time) / 1000.0;
+ pts += sub.start_display_time / 1000.0;
}
+ double endpts = MP_NOPTS_VALUE;
+ if (pts != MP_NOPTS_VALUE && duration >= 0)
+ endpts = pts + duration;
if (got_sub && vo_spudec && sub.num_rects == 0)
- spudec_set_paletted(vo_spudec, NULL, 0, NULL, 0, 0, 0, 0, *pts, *endpts);
+ spudec_set_paletted(vo_spudec, NULL, 0, NULL, 0, 0, 0, 0, pts, endpts);
if (got_sub && sub.num_rects > 0) {
switch (sub.rects[0]->type) {
case SUBTITLE_BITMAP:
@@ -98,19 +100,14 @@ int decode_avsub(struct sh_sub *sh, uint8_t **data, int *size,
sub.rects[0]->y,
sub.rects[0]->w,
sub.rects[0]->h,
- *pts,
- *endpts);
+ pts,
+ endpts);
vo_osd_changed(OSDTYPE_SPU);
break;
- case SUBTITLE_TEXT:
- *data = strdup(sub.rects[0]->text);
- *size = strlen(*data);
- new_type = 't';
- break;
- case SUBTITLE_ASS:
- *data = strdup(sub.rects[0]->ass);
- *size = strlen(*data);
- new_type = 'a';
+ default:
+ mp_msg(MSGT_SUBREADER, MSGL_ERR, "sd_avsub: unsupported subtitle "
+ "type from libavcodec\n");
+ res = -1;
break;
}
}
@@ -118,5 +115,5 @@ int decode_avsub(struct sh_sub *sh, uint8_t **data, int *size,
if (got_sub)
avsubtitle_free(&sub);
#endif
- return new_type;
+ return res;
}
diff --git a/av_sub.h b/sub/av_sub.h
index 690ed6c1f1..af3edc4d34 100644
--- a/av_sub.h
+++ b/sub/av_sub.h
@@ -24,7 +24,7 @@
struct sh_sub;
void reset_avsub(struct sh_sub *sh);
-int decode_avsub(struct sh_sub *sh, uint8_t **data, int *size,
- double *pts, double *endpts);
+int decode_avsub(struct sh_sub *sh, uint8_t *data, int size,
+ double pts, double endpts);
#endif /* MPLAYER_AV_SUB_H */
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/find_sub.c b/sub/find_sub.c
index d0ea3c0016..97c232b1db 100644
--- a/find_sub.c
+++ b/sub/find_sub.c
@@ -23,11 +23,12 @@
#include <stdio.h>
#include "libvo/video_out.h"
-#include "libvo/sub.h"
+#include "sub.h"
#include "subreader.h"
#include "mp_msg.h"
#include "mpcommon.h"
+#include "mplayer.h"
static int current_sub=0;
@@ -36,9 +37,6 @@ static int nosub_range_start=-1;
static int nosub_range_end=-1;
static const sub_data *last_sub_data = NULL;
-extern float sub_delay;
-extern float sub_fps;
-
void step_sub(sub_data *subd, float pts, int movement) {
subtitle *subs;
int key;
diff --git a/libvo/font_load.c b/sub/font_load.c
index e9980b8e41..e9980b8e41 100644
--- a/libvo/font_load.c
+++ b/sub/font_load.c
diff --git a/libvo/font_load.h b/sub/font_load.h
index 7efe067aaf..7efe067aaf 100644
--- a/libvo/font_load.h
+++ b/sub/font_load.h
diff --git a/libvo/font_load_ft.c b/sub/font_load_ft.c
index 41a0f886cb..41a0f886cb 100644
--- a/libvo/font_load_ft.c
+++ b/sub/font_load_ft.c
diff --git a/libvo/osd_font.h b/sub/osd_font.h
index 6be45bc1fa..6be45bc1fa 100644
--- a/libvo/osd_font.h
+++ b/sub/osd_font.h
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..ba5710611e
--- /dev/null
+++ b/sub/sd_ass.c
@@ -0,0 +1,154 @@
+/*
+ * 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 <string.h>
+
+#include "talloc.h"
+
+#include "mpcommon.h"
+#include "libmpdemux/stheader.h"
+#include "sub.h"
+#include "ass_mp.h"
+#include "sd.h"
+#include "subassconvert.h"
+
+struct sd_ass_priv {
+ struct ass_track *ass_track;
+ bool incomplete_event;
+};
+
+static void free_last_event(ASS_Track *track)
+{
+ assert(track->n_events > 0);
+ ass_free_event(track, track->n_events - 1);
+ track->n_events--;
+}
+
+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 = mp_ass_default_track(ass_library);
+ }
+
+ assert(osd->ass_track == NULL);
+ osd->ass_track = ctx->ass_track;
+ osd->vsfilter_aspect = sh->type == 'a';
+ osd->ass_track_changed = true;
+}
+
+static void decode(struct sh_sub *sh, struct osd_state *osd, void *data,
+ int data_len, double pts, double duration)
+{
+ unsigned char *text = data;
+ struct sd_ass_priv *ctx = sh->context;
+ ASS_Track *track = ctx->ass_track;
+
+ if (sh->type == 'a') { // ssa/ass subs
+ ass_process_chunk(track, data, data_len,
+ (long long)(pts*1000 + 0.5),
+ (long long)(duration*1000 + 0.5));
+ return;
+ }
+ // plaintext subs
+ if (pts == MP_NOPTS_VALUE) {
+ mp_msg(MSGT_SUBREADER, MSGL_WARN, "Subtitle without pts, ignored\n");
+ return;
+ }
+ long long ipts = pts * 1000 + 0.5;
+ long long iduration = duration * 1000 + 0.5;
+ if (ctx->incomplete_event) {
+ ctx->incomplete_event = false;
+ ASS_Event *event = track->events + track->n_events - 1;
+ if (ipts <= event->Start)
+ free_last_event(track);
+ else
+ event->Duration = ipts - event->Start;
+ }
+ // Note: we rely on there being guaranteed 0 bytes after data packets
+ int len = strlen(text);
+ if (len < 5) {
+ // Some tracks use a whitespace (but not empty) packet to mark end
+ // of previous subtitle.
+ for (int i = 0; i < len; i++)
+ if (!strchr(" \f\n\r\t\v", text[i]))
+ goto not_all_whitespace;
+ return;
+ }
+ not_all_whitespace:;
+ char buf[500];
+ subassconvert_subrip(text, buf, sizeof(buf));
+ for (int i = 0; i < track->n_events; i++)
+ if (track->events[i].Start == ipts
+ && (duration <= 0 || track->events[i].Duration == iduration)
+ && strcmp(track->events[i].Text, buf) == 0)
+ return; // We've already added this subtitle
+ if (duration <= 0) {
+ iduration = 10000;
+ ctx->incomplete_event = true;
+ }
+ int eid = ass_alloc_event(track);
+ ASS_Event *event = track->events + eid;
+ event->Start = ipts;
+ event->Duration = iduration;
+ event->Text = strdup(buf);
+}
+
+static void reset(struct sh_sub *sh, struct osd_state *osd)
+{
+ struct sd_ass_priv *ctx = sh->context;
+ if (ctx->incomplete_event)
+ free_last_event(ctx->ass_track);
+ ctx->incomplete_event = false;
+}
+
+static void switch_off(struct sh_sub *sh, struct osd_state *osd)
+{
+ reset(sh, 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,
+ .reset = reset,
+ .switch_off = switch_off,
+ .uninit = uninit,
+};
diff --git a/spudec.c b/sub/spudec.c
index de7d443ffc..f48d47fd2a 100644
--- a/spudec.c
+++ b/sub/spudec.c
@@ -43,6 +43,7 @@
#include "libavutil/avutil.h"
#include "ffmpeg_files/intreadwrite.h"
#include "libswscale/swscale.h"
+#include "mpcommon.h"
/* Valid values for spu_aamode:
0: none (fastest, most ugly)
@@ -1336,8 +1337,6 @@ void spudec_set_hw_spu(void *this, struct vo *hw_spu)
vo_control(hw_spu, VOCTRL_SET_SPU_PALETTE, spu->global_palette);
}
-#define MP_NOPTS_VALUE (-1LL<<63) //both int64_t and double should be able to represent this exactly
-
/**
* palette must contain at least 256 32-bit entries, otherwise crashes
* are possible
diff --git a/spudec.h b/sub/spudec.h
index 2b3828c34c..2b3828c34c 100644
--- a/spudec.h
+++ b/sub/spudec.h
diff --git a/libvo/sub.c b/sub/sub.c
index 58a777070e..62d79ca6f3 100644
--- a/libvo/sub.c
+++ b/sub/sub.c
@@ -35,7 +35,7 @@
#include "talloc.h"
#include "mplayer.h"
#include "mp_msg.h"
-#include "video_out.h"
+#include "libvo/video_out.h"
#include "font_load.h"
#include "sub.h"
#include "spudec.h"
diff --git a/libvo/sub.h b/sub/sub.h
index d5a30e0b86..8309613ea6 100644
--- a/libvo/sub.h
+++ b/sub/sub.h
@@ -19,6 +19,8 @@
#ifndef MPLAYER_SUB_H
#define MPLAYER_SUB_H
+#include <stdbool.h>
+
typedef struct mp_osd_bbox_s {
int x1,y1,x2,y2;
} mp_osd_bbox_t;
@@ -69,11 +71,13 @@ typedef struct mp_osd_obj_s {
struct osd_state {
unsigned char osd_text[128];
struct font_desc *sub_font;
+ struct ass_track *ass_track;
+ bool ass_track_changed;
+ bool vsfilter_aspect;
};
#include "subreader.h"
-extern sub_data* subdata; //currently used subtitles
extern subtitle* vo_sub;
extern void* vo_osd_teletext_page;
diff --git a/sub_cc.c b/sub/sub_cc.c
index 2422518355..f18fa28c54 100644
--- a/sub_cc.c
+++ b/sub/sub_cc.c
@@ -38,7 +38,7 @@
#include "subreader.h"
#include "libvo/video_out.h"
-#include "libvo/sub.h"
+#include "sub.h"
#define CC_MAX_LINE_LENGTH 64
diff --git a/sub_cc.h b/sub/sub_cc.h
index f5f6924057..f5f6924057 100644
--- a/sub_cc.h
+++ b/sub/sub_cc.h
diff --git a/sub/subassconvert.c b/sub/subassconvert.c
new file mode 100644
index 0000000000..773cb7f4d7
--- /dev/null
+++ b/sub/subassconvert.c
@@ -0,0 +1,502 @@
+/*
+ * Subtitles converter to SSA/ASS in order to allow special formatting
+ *
+ * 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 <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdbool.h>
+
+#include "mp_msg.h"
+#include "subassconvert.h"
+#include "bstr.h"
+#include "libavutil/common.h"
+
+struct line {
+ char *buf;
+ int bufsize;
+ int len;
+};
+
+#ifdef __GNUC__
+static void append_text(struct line *dst, char *fmt, ...) __attribute__ ((format(printf, 2, 3)));
+#endif
+
+static void append_text(struct line *dst, char *fmt, ...)
+{
+ va_list va;
+ va_start(va, fmt);
+ int ret = vsnprintf(dst->buf + dst->len, dst->bufsize - dst->len, fmt, va);
+ if (ret < 0)
+ goto out;
+ dst->len += ret;
+ if (dst->len > dst->bufsize)
+ dst->len = dst->bufsize;
+ out:
+ va_end(va);
+}
+
+static int indexof(const char *s, int c)
+{
+ char *f = strchr(s, c);
+ return f ? (f - s) : -1;
+}
+
+
+
+/*
+ * SubRip
+ *
+ * Support basic tags (italic, bold, underline, strike-through)
+ * and font tag with size, color and face attributes.
+ *
+ */
+
+struct font_tag {
+ int size;
+ uint32_t color;
+ struct bstr face;
+ bool has_size : 1;
+ bool has_color : 1;
+ bool has_face : 1;
+};
+
+static const struct tag_conv {
+ char *from;
+ char *to;
+} subrip_basic_tags[] = {
+ {"<i>", "{\\i1}"}, {"</i>", "{\\i0}"},
+ {"<b>", "{\\b1}"}, {"</b>", "{\\b0}"},
+ {"<u>", "{\\u1}"}, {"</u>", "{\\u0}"},
+ {"<s>", "{\\s1}"}, {"</s>", "{\\s0}"},
+ {"{", "\\{"}, {"}", "\\}"},
+ {"\n", "\\N"}
+};
+
+static const struct {
+ char *s;
+ uint32_t v;
+} subrip_web_colors[] = {
+ /* 16 named HTML colors in BGR format */
+ {"red", 0x0000ff}, {"blue", 0xff0000}, {"lime", 0x00ff00},
+ {"aqua", 0xffff00}, {"purple", 0x800080}, {"yellow", 0x00ffff},
+ {"fuchsia", 0xff00ff}, {"white", 0xffffff}, {"gray", 0x808080},
+ {"maroon", 0x000080}, {"olive", 0x008080}, {"black", 0x000000},
+ {"silver", 0xc0c0c0}, {"teal", 0x808000}, {"green", 0x008000},
+ {"navy", 0x800000}
+};
+
+#define SUBRIP_MAX_STACKED_FONT_TAGS 16
+
+void subassconvert_subrip(const char *orig, char *dest, int dest_buffer_size)
+{
+ /* line is not const to avoid warnings with strtol, etc.
+ * orig content won't be changed */
+ char *line = (char *)orig;
+ struct line new_line = {
+ .buf = dest,
+ .bufsize = dest_buffer_size,
+ };
+ struct font_tag font_stack[SUBRIP_MAX_STACKED_FONT_TAGS + 1];
+ font_stack[0] = (struct font_tag){0}; // type with all defaults
+ int sp = 0;
+
+ while (*line && new_line.len < new_line.bufsize - 1) {
+ char *orig_line = line;
+
+ for (int i = 0; i < FF_ARRAY_ELEMS(subrip_basic_tags); i++) {
+ const struct tag_conv *tag = &subrip_basic_tags[i];
+ int from_len = strlen(tag->from);
+ if (strncmp(line, tag->from, from_len) == 0) {
+ append_text(&new_line, "%s", tag->to);
+ line += from_len;
+ }
+ }
+
+ if (strncmp(line, "</font>", 7) == 0) {
+ /* Closing font tag */
+ line += 7;
+
+ if (sp > 0) {
+ struct font_tag *tag = &font_stack[sp];
+ struct font_tag *last_tag = &tag[-1];
+ sp--;
+
+ if (tag->has_size) {
+ if (!last_tag->has_size)
+ append_text(&new_line, "{\\fs}");
+ else if (last_tag->size != tag->size)
+ append_text(&new_line, "{\\fs%d}", last_tag->size);
+ }
+
+ if (tag->has_color) {
+ if (!last_tag->has_color)
+ append_text(&new_line, "{\\c}");
+ else if (last_tag->color != tag->color)
+ append_text(&new_line, "{\\c&H%06X&}", last_tag->color);
+ }
+
+ if (tag->has_face) {
+ if (!last_tag->has_face)
+ append_text(&new_line, "{\\fn}");
+ else if (bstrcmp(last_tag->face, tag->face) != 0)
+ append_text(&new_line, "{\\fn%.*s}",
+ BSTR_P(last_tag->face));
+ }
+ }
+ } else if (strncmp(line, "<font ", 6) == 0
+ && sp + 1 < FF_ARRAY_ELEMS(font_stack)) {
+ /* Opening font tag */
+ char *potential_font_tag_start = line;
+ int len_backup = new_line.len;
+ struct font_tag *tag = &font_stack[sp + 1];
+ bool has_valid_attr = false;
+
+ *tag = tag[-1]; // keep values from previous tag
+ line += 6;
+
+ while (*line && *line != '>') {
+ if (strncmp(line, "size=\"", 6) == 0) {
+ line += 6;
+ tag->size = strtol(line, &line, 10);
+ if (*line != '"')
+ break;
+ append_text(&new_line, "{\\fs%d}", tag->size);
+ tag->has_size = true;
+ has_valid_attr = true;
+ } else if (strncmp(line, "color=\"", 7) == 0) {
+ line += 7;
+ if (*line == '#') {
+ // #RRGGBB format
+ line++;
+ tag->color = strtol(line, &line, 16) & 0x00ffffff;
+ if (*line != '"')
+ break;
+ tag->color = ((tag->color & 0xff) << 16)
+ | (tag->color & 0xff00)
+ | ((tag->color & 0xff0000) >> 16);
+ } else {
+ // Standard web colors
+ int len = indexof(line, '"');
+ if (len <= 0)
+ break;
+ for (int i = 0; i < FF_ARRAY_ELEMS(subrip_web_colors); i++) {
+ char *color = subrip_web_colors[i].s;
+ if (strlen(color) == len
+ && strncasecmp(line, color, len) == 0) {
+ tag->color = subrip_web_colors[i].v;
+ goto foundcolor;
+ }
+ }
+
+ /* We didn't find any matching color */
+ mp_tmsg(MSGT_SUBREADER, MSGL_WARN,
+ "SubRip: unknown font color in subtitle: %s\n", orig);
+ append_text(&new_line, "{\\c}");
+ line += len + 1;
+ continue;
+
+ foundcolor:
+ line += len;
+ }
+ append_text(&new_line, "{\\c&H%06X&}", tag->color);
+ tag->has_color = true;
+ has_valid_attr = true;
+ } else if (strncmp(line, "face=\"", 6) == 0) {
+ /* Font face attribute */
+ line += 6;
+ int len = indexof(line, '"');
+ if (len <= 0)
+ break;
+ tag->face.start = line;
+ tag->face.len = len;
+ line += len;
+ append_text(&new_line, "{\\fn%.*s}", BSTR_P(tag->face));
+ tag->has_face = true;
+ has_valid_attr = true;
+ }
+ line++;
+ }
+
+ if (!has_valid_attr || *line != '>') { /* Not valid font tag */
+ line = potential_font_tag_start;
+ new_line.len = len_backup;
+ } else {
+ sp++;
+ line++;
+ }
+ }
+
+ /* Tag conversion code didn't match */
+ if (line == orig_line)
+ new_line.buf[new_line.len++] = *line++;
+ }
+ new_line.buf[new_line.len] = 0;
+}
+
+
+/*
+ * MicroDVD
+ *
+ * Based on the specifications found here:
+ * https://trac.videolan.org/vlc/ticket/1825#comment:6
+ */
+
+struct microdvd_tag {
+ char key;
+ int persistent;
+ uint32_t data1;
+ uint32_t data2;
+ struct bstr data_string;
+};
+
+#define MICRODVD_PERSISTENT_OFF 0
+#define MICRODVD_PERSISTENT_ON 1
+#define MICRODVD_PERSISTENT_OPENED 2
+
+// Color, Font, Size, cHarset, stYle, Position, cOordinate
+#define MICRODVD_TAGS "cfshyYpo"
+
+static void microdvd_set_tag(struct microdvd_tag *tags, struct microdvd_tag tag)
+{
+ int tag_index = indexof(MICRODVD_TAGS, tag.key);
+
+ if (tag_index < 0)
+ return;
+ memcpy(&tags[tag_index], &tag, sizeof(tag));
+}
+
+// italic, bold, underline, strike-through
+#define MICRODVD_STYLES "ibus"
+
+static char *microdvd_load_tags(struct microdvd_tag *tags, char *s)
+{
+ while (*s == '{') {
+ char *start = s;
+ char tag_char = *(s + 1);
+ struct microdvd_tag tag = {0};
+
+ if (!tag_char || *(s + 2) != ':')
+ break;
+ s += 3;
+
+ switch (tag_char) {
+
+ /* Style */
+ case 'Y':
+ tag.persistent = MICRODVD_PERSISTENT_ON;
+ case 'y':
+ while (*s && *s != '}') {
+ int style_index = indexof(MICRODVD_STYLES, *s);
+
+ if (style_index >= 0)
+ tag.data1 |= (1 << style_index);
+ s++;
+ }
+ if (*s != '}')
+ break;
+ /* We must distinguish persistent and non-persistent styles
+ * to handle this kind of style tags: {y:ib}{Y:us} */
+ tag.key = tag_char;
+ break;
+
+ /* Color */
+ case 'C':
+ tag.persistent = MICRODVD_PERSISTENT_ON;
+ case 'c':
+ tag.data1 = strtol(s, &s, 16) & 0x00ffffff;
+ if (*s != '}')
+ break;
+ tag.key = 'c';
+ break;
+
+ /* Font name */
+ case 'F':
+ tag.persistent = MICRODVD_PERSISTENT_ON;
+ case 'f':
+ {
+ int len = indexof(s, '}');
+ if (len < 0)
+ break;
+ tag.data_string.start = s;
+ tag.data_string.len = len;
+ s += len;
+ tag.key = 'f';
+ break;
+ }
+
+ /* Font size */
+ case 'S':
+ tag.persistent = MICRODVD_PERSISTENT_ON;
+ case 's':
+ tag.data1 = strtol(s, &s, 10);
+ if (*s != '}')
+ break;
+ tag.key = 's';
+ break;
+
+ /* Charset */
+ case 'H':
+ {
+ //TODO: not yet handled, just parsed.
+ int len = indexof(s, '}');
+ if (len < 0)
+ break;
+ tag.data_string.start = s;
+ tag.data_string.len = len;
+ s += len;
+ tag.key = 'h';
+ break;
+ }
+
+ /* Position */
+ case 'P':
+ tag.persistent = MICRODVD_PERSISTENT_ON;
+ tag.data1 = (*s++ == '1');
+ if (*s != '}')
+ break;
+ tag.key = 'p';
+ break;
+
+ /* Coordinates */
+ case 'o':
+ tag.persistent = MICRODVD_PERSISTENT_ON;
+ tag.data1 = strtol(s, &s, 10);
+ if (*s != ',')
+ break;
+ s++;
+ tag.data2 = strtol(s, &s, 10);
+ if (*s != '}')
+ break;
+ tag.key = 'o';
+ break;
+
+ default: /* Unknown tag, we consider it to be text */
+ break;
+ }
+
+ if (tag.key == 0)
+ return start;
+
+ microdvd_set_tag(tags, tag);
+ s++;
+ }
+ return s;
+}
+
+static void microdvd_open_tags(struct line *new_line, struct microdvd_tag *tags)
+{
+ for (int i = 0; i < sizeof(MICRODVD_TAGS) - 1; i++) {
+ if (tags[i].persistent == MICRODVD_PERSISTENT_OPENED)
+ continue;
+ switch (tags[i].key) {
+ case 'Y':
+ case 'y':
+ for (int sidx = 0; sidx < sizeof(MICRODVD_STYLES) - 1; sidx++)
+ if (tags[i].data1 & (1 << sidx))
+ append_text(new_line, "{\\%c1}", MICRODVD_STYLES[sidx]);
+ break;
+
+ case 'c':
+ append_text(new_line, "{\\c&H%06X&}", tags[i].data1);
+ break;
+
+ case 'f':
+ append_text(new_line, "{\\fn%.*s}", BSTR_P(tags[i].data_string));
+ break;
+
+ case 's':
+ append_text(new_line, "{\\fs%d}", tags[i].data1);
+ break;
+
+ case 'p':
+ if (tags[i].data1 == 0)
+ append_text(new_line, "{\\an8}");
+ break;
+
+ case 'o':
+ append_text(new_line, "{\\pos(%d,%d)}",
+ tags[i].data1, tags[i].data2);
+ break;
+ }
+ if (tags[i].persistent == MICRODVD_PERSISTENT_ON)
+ tags[i].persistent = MICRODVD_PERSISTENT_OPENED;
+ }
+}
+
+static void microdvd_close_no_persistent_tags(struct line *new_line,
+ struct microdvd_tag *tags)
+{
+ int i;
+
+ for (i = sizeof(MICRODVD_TAGS) - 2; i; i--) {
+ if (tags[i].persistent != MICRODVD_PERSISTENT_OFF)
+ continue;
+ switch (tags[i].key) {
+
+ case 'y':
+ for (int sidx = sizeof(MICRODVD_STYLES) - 2; sidx >= 0; sidx--)
+ if (tags[i].data1 & (1 << sidx))
+ append_text(new_line, "{\\%c0}", MICRODVD_STYLES[sidx]);
+ break;
+
+ case 'c':
+ append_text(new_line, "{\\c}");
+ break;
+
+ case 'f':
+ append_text(new_line, "{\\fn}");
+ break;
+
+ case 's':
+ append_text(new_line, "{\\fs}");
+ break;
+ }
+ tags[i].key = 0;
+ }
+}
+
+void subassconvert_microdvd(const char *orig, char *dest, int dest_buffer_size)
+{
+ /* line is not const to avoid warnings with strtol, etc.
+ * orig content won't be changed */
+ char *line = (char *)orig;
+ struct line new_line = {
+ .buf = dest,
+ .bufsize = dest_buffer_size,
+ };
+ struct microdvd_tag tags[sizeof(MICRODVD_TAGS) - 1] = {{0}};
+
+ while (*line) {
+ line = microdvd_load_tags(tags, line);
+ microdvd_open_tags(&new_line, tags);
+
+ while (*line && *line != '|')
+ new_line.buf[new_line.len++] = *line++;
+
+ if (*line == '|') {
+ microdvd_close_no_persistent_tags(&new_line, tags);
+ append_text(&new_line, "\\N");
+ line++;
+ }
+ }
+ new_line.buf[new_line.len] = 0;
+}
diff --git a/sub/subassconvert.h b/sub/subassconvert.h
new file mode 100644
index 0000000000..e6a4425198
--- /dev/null
+++ b/sub/subassconvert.h
@@ -0,0 +1,27 @@
+/*
+ * Header for subtitles converter to SSA/ASS
+ *
+ * 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.
+ */
+
+#ifndef MPLAYER_SUBASSCONVERT_H
+#define MPLAYER_SUBASSCONVERT_H
+
+void subassconvert_subrip(const char *orig, char *dest, int dest_buffer_size);
+void subassconvert_microdvd(const char *orig, char *dest, int dest_buffer_size);
+
+#endif
diff --git a/subreader.c b/sub/subreader.c
index 3d422ddbdf..1f9294ec47 100644
--- a/subreader.c
+++ b/sub/subreader.c
@@ -32,6 +32,9 @@
#include "config.h"
#include "mp_msg.h"
#include "subreader.h"
+#include "mpcommon.h"
+#include "subassconvert.h"
+#include "options.h"
#include "stream/stream.h"
#include "libavutil/common.h"
#include "libavutil/avstring.h"
@@ -53,6 +56,12 @@ int flip_hebrew = 1; ///flip subtitles using fribidi
int fribidi_flip_commas = 0; ///flip comma when fribidi is used
#endif
+// Parameter struct for the format-specific readline functions
+struct readline_args {
+ int utf16;
+ struct MPOpts *opts;
+};
+
/* Maximal length of line of a subtitle */
#define LINE_LEN 1000
static float mpsub_position=0;
@@ -118,7 +127,10 @@ static void sami_add_line(subtitle *current, char *buffer, char **pos) {
*pos = buffer;
}
-static subtitle *sub_read_line_sami(stream_t* st, subtitle *current, int utf16) {
+static subtitle *sub_read_line_sami(stream_t* st, subtitle *current,
+ struct readline_args *args)
+{
+ int utf16 = args->utf16;
static char line[LINE_LEN+1];
static char *s = NULL, *slacktime_s;
char text[LINE_LEN+1], *p=NULL, *q;
@@ -277,7 +289,10 @@ static char *sub_readtext(char *source, char **dest) {
else return NULL; // last text field
}
-static subtitle *sub_read_line_microdvd(stream_t *st,subtitle *current, int utf16) {
+static subtitle *sub_read_line_microdvd(stream_t *st,subtitle *current,
+ struct readline_args *args)
+{
+ int utf16 = args->utf16;
char line[LINE_LEN+1];
char line2[LINE_LEN+1];
char *p, *next;
@@ -292,7 +307,11 @@ static subtitle *sub_read_line_microdvd(stream_t *st,subtitle *current, int utf1
"{%ld}{%ld}%[^\r\n]",
&(current->start), &(current->end), line2) < 3));
- p=line2;
+ if (args->opts->ass_enabled) {
+ subassconvert_microdvd(line2, line, LINE_LEN + 1);
+ p = line;
+ } else
+ p = line2;
next=p, i=0;
while ((next =sub_readtext (next, &(current->text[i])))) {
@@ -305,7 +324,10 @@ static subtitle *sub_read_line_microdvd(stream_t *st,subtitle *current, int utf1
return current;
}
-static subtitle *sub_read_line_mpl2(stream_t *st,subtitle *current, int utf16) {
+static subtitle *sub_read_line_mpl2(stream_t *st,subtitle *current,
+ struct readline_args *args)
+{
+ int utf16 = args->utf16;
char line[LINE_LEN+1];
char line2[LINE_LEN+1];
char *p, *next;
@@ -331,7 +353,10 @@ static subtitle *sub_read_line_mpl2(stream_t *st,subtitle *current, int utf16) {
return current;
}
-static subtitle *sub_read_line_subrip(stream_t* st, subtitle *current, int utf16) {
+static subtitle *sub_read_line_subrip(stream_t* st, subtitle *current,
+ struct readline_args *args)
+{
+ int utf16 = args->utf16;
char line[LINE_LEN+1];
int a1,a2,a3,a4,b1,b2,b3,b4;
char *p=NULL, *q=NULL;
@@ -361,12 +386,75 @@ static subtitle *sub_read_line_subrip(stream_t* st, subtitle *current, int utf16
return current;
}
-static subtitle *sub_read_line_subviewer(stream_t *st,subtitle *current, int utf16) {
+static subtitle *sub_ass_read_line_subviewer(stream_t *st, subtitle *current,
+ struct readline_args *args)
+{
+ int utf16 = args->utf16;
+ int a1, a2, a3, a4, b1, b2, b3, b4, j = 0;
+
+ while (!current->text[0]) {
+ char line[LINE_LEN + 1], full_line[LINE_LEN + 1], sep;
+ int i;
+
+ /* Parse SubRip header */
+ if (!stream_read_line(st, line, LINE_LEN, utf16))
+ return NULL;
+ if (sscanf(line, "%d:%d:%d%[,.:]%d --> %d:%d:%d%[,.:]%d",
+ &a1, &a2, &a3, &sep, &a4, &b1, &b2, &b3, &sep, &b4) < 10)
+ continue;
+
+ current->start = a1 * 360000 + a2 * 6000 + a3 * 100 + a4 / 10;
+ current->end = b1 * 360000 + b2 * 6000 + b3 * 100 + b4 / 10;
+
+ /* Concat lines */
+ full_line[0] = 0;
+ for (i = 0; i < SUB_MAX_TEXT; i++) {
+ int blank = 1, len = 0;
+ char *p;
+
+ if (!stream_read_line(st, line, LINE_LEN, utf16))
+ break;
+
+ for (p = line; *p != '\n' && *p != '\r' && *p; p++, len++)
+ if (*p != ' ' && *p != '\t')
+ blank = 0;
+
+ if (blank)
+ break;
+
+ *p = 0;
+
+ if (!(j + 1 + len < sizeof(full_line) - 1))
+ break;
+
+ if (j != 0)
+ full_line[j++] = '\n';
+ strcpy(&full_line[j], line);
+ j += len;
+ }
+
+ /* Use the ASS/SSA converter to transform the whole lines */
+ if (full_line[0]) {
+ char converted_line[LINE_LEN + 1];
+ subassconvert_subrip(full_line, converted_line, LINE_LEN + 1);
+ current->text[0] = strdup(converted_line);
+ current->lines = 1;
+ }
+ }
+ return current;
+}
+
+static subtitle *sub_read_line_subviewer(stream_t *st,subtitle *current,
+ struct readline_args *args)
+{
+ int utf16 = args->utf16;
char line[LINE_LEN+1];
int a1,a2,a3,a4,b1,b2,b3,b4;
char *p=NULL;
int i,len;
+ if (args->opts->ass_enabled)
+ return sub_ass_read_line_subviewer(st, current, args);
while (!current->text[0]) {
if (!stream_read_line (st, line, LINE_LEN, utf16)) return NULL;
if ((len=sscanf (line, "%d:%d:%d%[,.:]%d --> %d:%d:%d%[,.:]%d",&a1,&a2,&a3,(char *)&i,&a4,&b1,&b2,&b3,(char *)&i,&b4)) < 10)
@@ -413,7 +501,10 @@ static subtitle *sub_read_line_subviewer(stream_t *st,subtitle *current, int utf
return current;
}
-static subtitle *sub_read_line_subviewer2(stream_t *st,subtitle *current, int utf16) {
+static subtitle *sub_read_line_subviewer2(stream_t *st,subtitle *current,
+ struct readline_args *args)
+{
+ int utf16 = args->utf16;
char line[LINE_LEN+1];
int a1,a2,a3,a4;
char *p=NULL;
@@ -446,7 +537,10 @@ static subtitle *sub_read_line_subviewer2(stream_t *st,subtitle *current, int ut
}
-static subtitle *sub_read_line_vplayer(stream_t *st,subtitle *current, int utf16) {
+static subtitle *sub_read_line_vplayer(stream_t *st,subtitle *current,
+ struct readline_args *args)
+{
+ int utf16 = args->utf16;
char line[LINE_LEN+1];
int a1,a2,a3;
char *p=NULL, *next,separator;
@@ -492,7 +586,11 @@ static subtitle *sub_read_line_vplayer(stream_t *st,subtitle *current, int utf16
return current;
}
-static subtitle *sub_read_line_rt(stream_t *st,subtitle *current, int utf16) {
+static subtitle *sub_read_line_rt(stream_t *st,subtitle *current,
+ struct readline_args *args)
+{
+ int utf16 = args->utf16;
+
//TODO: This format uses quite rich (sub/super)set of xhtml
// I couldn't check it since DTD is not included.
// WARNING: full XML parses can be required for proper parsing
@@ -542,7 +640,9 @@ static subtitle *sub_read_line_rt(stream_t *st,subtitle *current, int utf16) {
return current;
}
-static subtitle *sub_read_line_ssa(stream_t *st,subtitle *current, int utf16) {
+static subtitle *sub_read_line_ssa(stream_t *st,subtitle *current,
+ struct readline_args *args)
+{
/*
* Sub Station Alpha v4 (and v2?) scripts have 9 commas before subtitle
* other Sub Station Alpha scripts have only 8 commas before subtitle
@@ -552,6 +652,7 @@ static subtitle *sub_read_line_ssa(stream_t *st,subtitle *current, int utf16) {
* http://www.scriptclub.org is a good place to find more examples
* http://www.eswat.demon.co.uk is where the SSA specs can be found
*/
+ int utf16 = args->utf16;
int comma;
static int max_comma = 32; /* let's use 32 for the case that the */
/* amount of commas increase with newer SSA versions */
@@ -644,7 +745,10 @@ static void sub_pp_ssa(subtitle *sub) {
*
* by set, based on code by szabi (dunnowhat sub format ;-)
*/
-static subtitle *sub_read_line_pjs(stream_t *st,subtitle *current, int utf16) {
+static subtitle *sub_read_line_pjs(stream_t *st,subtitle *current,
+ struct readline_args *args)
+{
+ int utf16 = args->utf16;
char line[LINE_LEN+1];
char text[LINE_LEN+1], *s, *d;
@@ -682,7 +786,10 @@ static subtitle *sub_read_line_pjs(stream_t *st,subtitle *current, int utf16) {
return current;
}
-static subtitle *sub_read_line_mpsub(stream_t *st, subtitle *current, int utf16) {
+static subtitle *sub_read_line_mpsub(stream_t *st, subtitle *current,
+ struct readline_args *args)
+{
+ int utf16 = args->utf16;
char line[LINE_LEN+1];
float a,b;
int num=0;
@@ -727,7 +834,10 @@ static subtitle *sub_read_line_mpsub(stream_t *st, subtitle *current, int utf16)
subtitle *previous_aqt_sub = NULL;
#endif
-static subtitle *sub_read_line_aqt(stream_t *st,subtitle *current, int utf16) {
+static subtitle *sub_read_line_aqt(stream_t *st,subtitle *current,
+ struct readline_args *args)
+{
+ int utf16 = args->utf16;
char line[LINE_LEN+1];
char *next;
int i;
@@ -784,7 +894,10 @@ static subtitle *sub_read_line_aqt(stream_t *st,subtitle *current, int utf16) {
subtitle *previous_subrip09_sub = NULL;
#endif
-static subtitle *sub_read_line_subrip09(stream_t *st,subtitle *current, int utf16) {
+static subtitle *sub_read_line_subrip09(stream_t *st,subtitle *current,
+ struct readline_args *args)
+{
+ int utf16 = args->utf16;
char line[LINE_LEN+1];
int a1,a2,a3;
char * next=NULL;
@@ -836,8 +949,10 @@ static subtitle *sub_read_line_subrip09(stream_t *st,subtitle *current, int utf1
return current;
}
-static subtitle *sub_read_line_jacosub(stream_t* st, subtitle * current, int utf16)
+static subtitle *sub_read_line_jacosub(stream_t* st, subtitle * current,
+ struct readline_args *args)
{
+ int utf16 = args->utf16;
char line1[LINE_LEN], line2[LINE_LEN], directive[LINE_LEN], *p, *q;
unsigned a1, a2, a3, a4, b1, b2, b3, b4, comment = 0;
static unsigned jacoTimeres = 30;
@@ -1284,7 +1399,8 @@ static void adjust_subs_time(subtitle* sub, float subtime, float fps, int block,
}
struct subreader {
- subtitle * (*read)(stream_t *st,subtitle *dest,int utf16);
+ subtitle * (*read)(stream_t *st, subtitle *dest,
+ struct readline_args *args);
void (*post)(subtitle *dest);
const char *name;
};
@@ -1350,7 +1466,8 @@ const char* guess_cp(stream_t *st, const char *preferred_language, const char *f
#undef MAX_GUESS_BUFFER_SIZE
#endif
-sub_data* sub_read_file (char *filename, float fps) {
+sub_data* sub_read_file(char *filename, float fps, struct MPOpts *opts)
+{
int utf16;
stream_t* fd;
int n_max, n_first, i, j, sub_first, sub_orig;
@@ -1435,7 +1552,7 @@ sub_data* sub_read_file (char *filename, float fps) {
sub = &first[sub_num];
#endif
memset(sub, '\0', sizeof(subtitle));
- sub=srp->read(fd,sub,utf16);
+ sub=srp->read(fd, sub, &(struct readline_args){utf16, opts});
if(!sub) break; // EOF
#ifdef CONFIG_ICONV
if ((sub!=ERR) && sub_utf8 == 2) sub=subcp_recode(sub);
@@ -2359,7 +2476,6 @@ void sub_add_text(subtitle *sub, const char *txt, int len, double endpts) {
#endif
}
-#define MP_NOPTS_VALUE (-1LL<<63)
/**
* \brief remove outdated subtitle lines.
* \param sub subtitle struct to modify
diff --git a/subreader.h b/sub/subreader.h
index b1aa07421b..9c7465d71a 100644
--- a/subreader.h
+++ b/sub/subreader.h
@@ -20,6 +20,7 @@
#define MPLAYER_SUBREADER_H
#include <stdio.h>
+#include <stdbool.h>
#include "config.h"
@@ -84,7 +85,8 @@ extern char *fribidi_charset;
extern int flip_hebrew;
extern int fribidi_flip_commas;
-sub_data* sub_read_file (char *filename, float pts);
+struct MPOpts;
+sub_data* sub_read_file (char *filename, float pts, struct MPOpts *opts);
subtitle* subcp_recode (subtitle *sub);
// enca_fd is the file enca uses to determine the codepage.
// setting to NULL disables enca.
diff --git a/unrar_exec.c b/sub/unrar_exec.c
index 6de8c59bef..6de8c59bef 100644
--- a/unrar_exec.c
+++ b/sub/unrar_exec.c
diff --git a/unrar_exec.h b/sub/unrar_exec.h
index 5754083fd7..5754083fd7 100644
--- a/unrar_exec.h
+++ b/sub/unrar_exec.h
diff --git a/vobsub.c b/sub/vobsub.c
index 08efa3acec..08efa3acec 100644
--- a/vobsub.c
+++ b/sub/vobsub.c
diff --git a/vobsub.h b/sub/vobsub.h
index b076e4b6bc..b076e4b6bc 100644
--- a/vobsub.h
+++ b/sub/vobsub.h