diff options
author | wm4 <wm4@nowhere> | 2013-06-25 00:43:04 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2013-06-25 00:43:04 +0200 |
commit | 403a266d466850621397c07e0b96cc2c493b2936 (patch) | |
tree | 0835a0908b3df8cca8374d173c34e0bf7df7d842 /core | |
parent | 536871d7e5848eb385b97202a33b9382b5e8ab0e (diff) | |
parent | 54851d60614e912fc422658302d72811a31b80f8 (diff) | |
download | mpv-403a266d466850621397c07e0b96cc2c493b2936.tar.bz2 mpv-403a266d466850621397c07e0b96cc2c493b2936.tar.xz |
Merge branch 'sub_mess2'
...the return.
Diffstat (limited to 'core')
-rw-r--r-- | core/charset_conv.c | 266 | ||||
-rw-r--r-- | core/charset_conv.h | 17 | ||||
-rw-r--r-- | core/command.c | 5 | ||||
-rw-r--r-- | core/encode_lavc.c | 2 | ||||
-rw-r--r-- | core/input/input.c | 2 | ||||
-rw-r--r-- | core/mp_core.h | 3 | ||||
-rw-r--r-- | core/mplayer.c | 110 | ||||
-rw-r--r-- | core/options.c | 9 | ||||
-rw-r--r-- | core/options.h | 3 |
9 files changed, 325 insertions, 92 deletions
diff --git a/core/charset_conv.c b/core/charset_conv.c new file mode 100644 index 0000000000..680c8f83f9 --- /dev/null +++ b/core/charset_conv.c @@ -0,0 +1,266 @@ +/* + * This file is part of mpv. + * + * Based on code taken from libass (ISC license), which was originally part + * of MPlayer (GPL). + * Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com> + * + * mpv 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. + * + * mpv 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 mpv. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <errno.h> +#include <assert.h> + +#include "config.h" + +#include "core/mp_msg.h" + +#ifdef CONFIG_ENCA +#include <enca.h> +#endif + +#ifdef CONFIG_LIBGUESS +#include <libguess.h> +#endif + +#ifdef CONFIG_ICONV +#include <iconv.h> +#endif + +#include "charset_conv.h" + +// Split the string on ':' into components. +// out_arr is at least max entries long. +// Return number of out_arr entries filled. +static int split_colon(const char *user_cp, int max, bstr *out_arr) +{ + if (!user_cp || max < 1) + return 0; + + int count = 0; + while (1) { + const char *next = strchr(user_cp, ':'); + if (next && max - count > 1) { + out_arr[count++] = (bstr){(char *)user_cp, next - user_cp}; + user_cp = next + 1; + } else { + out_arr[count++] = (bstr){(char *)user_cp, strlen(user_cp)}; + break; + } + } + return count; +} + +// Returns true if user_cp implies that calling mp_charset_guess() on the +// input data is required to determine the real codepage. This is the case +// if user_cp is not a real iconv codepage, but a magic value that requests +// for example ENCA charset auto-detection. +bool mp_charset_requires_guess(const char *user_cp) +{ + bstr res[2] = {{0}}; + split_colon(user_cp, 2, res); + return bstrcasecmp0(res[0], "enca") == 0 || + bstrcasecmp0(res[0], "guess") == 0; +} + +#ifdef CONFIG_ENCA +static const char *enca_guess(bstr buf, const char *language) +{ + if (!language || !language[0]) + language = "__"; // neutral language + + const char *detected_cp = NULL; + + EncaAnalyser analyser = enca_analyser_alloc(language); + if (analyser) { + enca_set_termination_strictness(analyser, 0); + EncaEncoding enc = enca_analyse_const(analyser, buf.start, buf.len); + const char *tmp = enca_charset_name(enc.charset, ENCA_NAME_STYLE_ICONV); + if (tmp && enc.charset != ENCA_CS_UNKNOWN) + detected_cp = tmp; + enca_analyser_free(analyser); + } else { + mp_msg(MSGT_SUBREADER, MSGL_ERR, "ENCA doesn't know language '%s'\n", + language); + size_t langcnt; + const char **languages = enca_get_languages(&langcnt); + mp_msg(MSGT_SUBREADER, MSGL_ERR, "ENCA supported languages:"); + for (int i = 0; i < langcnt; i++) + mp_msg(MSGT_SUBREADER, MSGL_ERR, " %s", languages[i]); + mp_msg(MSGT_SUBREADER, MSGL_ERR, "\n"); + free(languages); + } + + return detected_cp; +} +#endif + +#ifdef CONFIG_LIBGUESS +static const char *libguess_guess(bstr buf, const char *language) +{ + if (libguess_validate_utf8(buf.start, buf.len)) + return "UTF-8"; + + if (!language || !language[0] || strcmp(language, "help") == 0) { + mp_msg(MSGT_SUBREADER, MSGL_ERR, "libguess needs a language: " + "japanese taiwanese chinese korean russian arabic turkish " + "greek hebrew polish baltic\n"); + return NULL; + } + + return libguess_determine_encoding(buf.start, buf.len, language); +} +#endif + +// Runs charset auto-detection on the input buffer, and returns the result. +// If auto-detection fails, NULL is returned. +// If user_cp doesn't refer to any known auto-detection (for example because +// it's a real iconv codepage), user_cp is returned without even looking at +// the buf data. +const char *mp_charset_guess(bstr buf, const char *user_cp) +{ + if (!mp_charset_requires_guess(user_cp)) + return user_cp; + + bstr params[3] = {{0}}; + split_colon(user_cp, 3, params); + + bstr type = params[0]; + char lang[100]; + snprintf(lang, sizeof(lang), "%.*s", BSTR_P(params[1])); + const char *fallback = params[2].start; // last item, already 0-terminated + + const char *res = NULL; + +#ifdef CONFIG_ENCA + if (bstrcasecmp0(type, "enca") == 0) + res = enca_guess(buf, lang); +#endif +#ifdef CONFIG_LIBGUESS + if (bstrcasecmp0(type, "guess") == 0) + res = libguess_guess(buf, lang); +#endif + + if (res) { + mp_msg(MSGT_SUBREADER, MSGL_DBG2, "%.*s detected charset: '%s'\n", + BSTR_P(type), res); + } else { + res = fallback; + mp_msg(MSGT_SUBREADER, MSGL_DBG2, + "Detection with %.*s failed: fallback to %s\n", + BSTR_P(type), res && res[0] ? res : "no conversion"); + } + + return res; +} + +// Convert the data in buf to UTF-8. The charset argument can be an iconv +// codepage, a value returned by mp_charset_conv_guess(), or a special value +// that triggers autodetection of the charset (e.g. using ENCA). +// The auto-detection is the only difference to mp_iconv_to_utf8(). +// buf: same as mp_iconv_to_utf8() +// user_cp: iconv codepage, special value, NULL +// flags: same as mp_iconv_to_utf8() +// returns: same as mp_iconv_to_utf8() +bstr mp_charset_guess_and_conv_to_utf8(bstr buf, const char *user_cp, int flags) +{ + return mp_iconv_to_utf8(buf, mp_charset_guess(buf, user_cp), flags); +} + +// Use iconv to convert buf to UTF-8. +// Returns buf.start==NULL on error. Returns buf if cp is NULL, or if there is +// obviously no conversion required (e.g. if cp is "UTF-8"). +// Returns a newly allocated buffer if conversion is done and succeeds. The +// buffer will be terminated with 0 for convenience (the terminating 0 is not +// included in the returned length). +// Free the returned buffer with talloc_free(). +// buf: input data +// cp: iconv codepage (or NULL) +// flags: combination of MP_ICONV_* flags +// returns: buf (no conversion), .start==NULL (error), or allocated buffer +bstr mp_iconv_to_utf8(bstr buf, const char *cp, int flags) +{ +#ifdef CONFIG_ICONV + const char *tocp = "UTF-8"; + + if (!cp || !cp[0] || strcasecmp(cp, tocp) == 0) + return buf; + + if (strcasecmp(cp, "ASCII") == 0) + return buf; + + iconv_t icdsc; + if ((icdsc = iconv_open(tocp, cp)) == (iconv_t) (-1)) { + if (flags & MP_ICONV_VERBOSE) + mp_msg(MSGT_SUBREADER, MSGL_ERR, + "Error opening iconv with codepage '%s'\n", cp); + goto failure; + } + + size_t size = buf.len; + size_t osize = size; + size_t ileft = size; + size_t oleft = size - 1; + + char *outbuf = talloc_size(NULL, osize); + char *ip = buf.start; + char *op = outbuf; + + while (1) { + int clear = 0; + size_t rc; + if (ileft) + rc = iconv(icdsc, &ip, &ileft, &op, &oleft); + else { + clear = 1; // clear the conversion state and leave + rc = iconv(icdsc, NULL, NULL, &op, &oleft); + } + if (rc == (size_t) (-1)) { + if (errno == E2BIG) { + size_t offset = op - outbuf; + outbuf = talloc_realloc_size(NULL, outbuf, osize + size); + op = outbuf + offset; + osize += size; + oleft += size; + } else { + if (errno == EINVAL && (flags & MP_ICONV_ALLOW_CUTOFF)) { + // This is intended for cases where the input buffer is cut + // at a random byte position. If this happens in the middle + // of the buffer, it should still be an error. We say it's + // fine if the error is within 10 bytes of the end. + if (ileft <= 10) + break; + } + if (flags & MP_ICONV_VERBOSE) { + mp_msg(MSGT_SUBREADER, MSGL_ERR, + "Error recoding text with codepage '%s'\n", cp); + } + talloc_free(outbuf); + iconv_close(icdsc); + goto failure; + } + } else if (clear) + break; + } + + iconv_close(icdsc); + + outbuf[osize - oleft - 1] = 0; + return (bstr){outbuf, osize - oleft - 1}; +#endif + +failure: + return (bstr){0}; +} diff --git a/core/charset_conv.h b/core/charset_conv.h new file mode 100644 index 0000000000..00a2658da3 --- /dev/null +++ b/core/charset_conv.h @@ -0,0 +1,17 @@ +#ifndef MP_CHARSET_CONV_H +#define MP_CHARSET_CONV_H + +#include <stdbool.h> +#include "core/bstr.h" + +enum { + MP_ICONV_VERBOSE = 1, // print errors instead of failing silently + MP_ICONV_ALLOW_CUTOFF = 2, // allow partial input data +}; + +bool mp_charset_requires_guess(const char *user_cp); +const char *mp_charset_guess(bstr buf, const char *user_cp); +bstr mp_charset_guess_and_conv_to_utf8(bstr buf, const char *user_cp, int flags); +bstr mp_iconv_to_utf8(bstr buf, const char *cp, int flags); + +#endif diff --git a/core/command.c b/core/command.c index 4da0653425..c39bb3c16d 100644 --- a/core/command.c +++ b/core/command.c @@ -2281,7 +2281,7 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd) case MP_CMD_SUB_ADD: if (sh_video) { - mp_add_subtitles(mpctx, cmd->args[0].v.s, sh_video->fps, 0); + mp_add_subtitles(mpctx, cmd->args[0].v.s, 0); } break; @@ -2296,8 +2296,7 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd) struct track *sub = mp_track_by_tid(mpctx, STREAM_SUB, cmd->args[0].v.i); if (sh_video && sub && sub->is_external && sub->external_filename) { - struct track *nsub = mp_add_subtitles(mpctx, sub->external_filename, - sh_video->fps, 0); + struct track *nsub = mp_add_subtitles(mpctx, sub->external_filename, 0); if (nsub) { mp_remove_track(mpctx, sub); mp_switch_track(mpctx, nsub->type, nsub); diff --git a/core/encode_lavc.c b/core/encode_lavc.c index b09ecaa1ac..9fada7de58 100644 --- a/core/encode_lavc.c +++ b/core/encode_lavc.c @@ -404,7 +404,7 @@ static void encode_2pass_prepare(struct encode_lavc_context *ctx, set_to_avdictionary(dictp, "flags", "-pass2"); } else { struct bstr content = stream_read_complete(*bytebuf, NULL, - 1000000000, 1); + 1000000000); if (content.start == NULL) { mp_msg(MSGT_ENCODE, MSGL_WARN, "%s: could not read '%s', " "disabling 2-pass encoding at pass 1\n", diff --git a/core/input/input.c b/core/input/input.c index 2d7569c8e9..dfa7d1e5b4 100644 --- a/core/input/input.c +++ b/core/input/input.c @@ -1737,7 +1737,7 @@ static int parse_config_file(struct input_ctx *ictx, char *file, bool warn) mp_msg(MSGT_INPUT, MSGL_ERR, "Can't open input config file %s.\n", file); return 0; } - bstr res = stream_read_complete(s, NULL, 1000000, 0); + bstr res = stream_read_complete(s, NULL, 1000000); free_stream(s); mp_msg(MSGT_INPUT, MSGL_V, "Parsing input config file %s\n", file); int n_binds = parse_config(ictx, false, res, file); diff --git a/core/mp_core.h b/core/mp_core.h index 98a92cbea4..0bd6ecda15 100644 --- a/core/mp_core.h +++ b/core/mp_core.h @@ -290,8 +290,7 @@ extern int forced_subs_only; void uninit_player(struct MPContext *mpctx, unsigned int mask); void reinit_audio_chain(struct MPContext *mpctx); double playing_audio_pts(struct MPContext *mpctx); -struct track *mp_add_subtitles(struct MPContext *mpctx, char *filename, - float fps, int noerr); +struct track *mp_add_subtitles(struct MPContext *mpctx, char *filename, int noerr); int reinit_video_chain(struct MPContext *mpctx); int reinit_video_filters(struct MPContext *mpctx); void pause_player(struct MPContext *mpctx); diff --git a/core/mplayer.c b/core/mplayer.c index d28b5fdc4c..3cdd83021d 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -71,7 +71,6 @@ #include "core/mplayer.h" #include "core/m_property.h" -#include "sub/subreader.h" #include "sub/find_subfiles.h" #include "sub/dec_sub.h" #include "sub/sd.h" @@ -197,9 +196,6 @@ static const char av_desync_help_text[] = _( static void reset_subtitles(struct MPContext *mpctx); static void reinit_subs(struct MPContext *mpctx); -static struct track *open_external_file(struct MPContext *mpctx, char *filename, - char *demuxer_name, int stream_cache, - enum stream_type filter); static double get_relative_time(struct MPContext *mpctx) { @@ -982,6 +978,9 @@ static struct track *add_stream_track(struct MPContext *mpctx, }; MP_TARRAY_APPEND(mpctx, mpctx->tracks, mpctx->num_tracks, track); + if (stream->type == STREAM_SUB) + track->preloaded = !!stream->sub->track; + // Needed for DVD and Blu-ray. if (!track->lang) { struct stream_lang_req req = { @@ -1028,69 +1027,6 @@ static void add_dvd_tracks(struct MPContext *mpctx) #endif } -#ifdef CONFIG_ASS -static int free_sub_data(void *ptr) -{ - struct sh_sub *sh_sub = *(struct sh_sub **)ptr; - if (sh_sub->track) - ass_free_track(sh_sub->track); - talloc_free(sh_sub->sub_data); - return 1; -} -#endif - -struct track *mp_add_subtitles(struct MPContext *mpctx, char *filename, - float fps, int noerr) -{ - struct MPOpts *opts = &mpctx->opts; - struct ass_track *asst = NULL; - sub_data *subd = NULL; - - if (filename == NULL) - return NULL; - - // Note: no text subtitles without libass. This is mainly because sd_ass is - // used for rendering. Even when showing subtitles with term-osd, going - // through sd_ass makes the code much simpler, as sd_ass can handle all - // the weird special-cases. -#ifdef CONFIG_ASS - asst = mp_ass_read_stream(mpctx->ass_library, filename, opts->sub_cp); - if (!asst) - subd = sub_read_file(filename, fps, &mpctx->opts); - if (asst || subd) { - struct demuxer *d = new_sub_pseudo_demuxer(opts); - assert(d->num_streams == 1); - struct sh_stream *s = d->streams[0]; - assert(s->type == STREAM_SUB); - - s->codec = asst ? "ass" : subd->codec; - s->sub->track = asst; - s->sub->sub_data = subd; - - struct sh_sub **pptr = talloc(d, struct sh_sub*); - *pptr = s->sub; - talloc_set_destructor(pptr, free_sub_data); - - struct track *t = add_stream_track(mpctx, s, false); - t->is_external = true; - t->preloaded = true; - t->title = talloc_strdup(t, filename); - t->external_filename = talloc_strdup(t, filename); - MP_TARRAY_APPEND(NULL, mpctx->sources, mpctx->num_sources, d); - return t; - } -#endif - - // Used with libavformat subtitles. - struct track *ext = open_external_file(mpctx, filename, NULL, 0, STREAM_SUB); - if (ext) - return ext; - - mp_tmsg(MSGT_CPLAYER, noerr ? MSGL_WARN : MSGL_ERR, - "Cannot load subtitles: %s\n", filename); - return NULL; -} - int mp_get_cache_percent(struct MPContext *mpctx) { if (mpctx->stream) { @@ -2001,7 +1937,8 @@ static void reinit_subs(struct MPContext *mpctx) if (!mpctx->sh_sub->dec_sub) mpctx->sh_sub->dec_sub = sub_create(opts); - if (track->demuxer && !track->stream) { + assert(track->demuxer); + if (!track->stream) { // Lazily added DVD track - we must not miss the first subtitle packet, // which makes the demuxer create the sh_stream, and contains the first // subtitle event. @@ -2016,7 +1953,6 @@ static void reinit_subs(struct MPContext *mpctx) return; } - assert(track->demuxer && track->stream); mpctx->initialized_flags |= INITIALIZED_SUB; @@ -2027,12 +1963,22 @@ static void reinit_subs(struct MPContext *mpctx) if (!sub_is_initialized(dec_sub)) { int w = mpctx->sh_video ? mpctx->sh_video->disp_w : 0; int h = mpctx->sh_video ? mpctx->sh_video->disp_h : 0; + float fps = mpctx->sh_video ? mpctx->sh_video->fps : 25; set_dvdsub_fake_extradata(dec_sub, track->demuxer->stream, w, h); sub_set_video_res(dec_sub, w, h); + sub_set_video_fps(dec_sub, fps); sub_set_ass_renderer(dec_sub, mpctx->osd->ass_library, mpctx->osd->ass_renderer); sub_init_from_sh(dec_sub, sh_sub); + + // Don't do this if the file has video/audio streams. Don't do it even + // if it has only sub streams, because reading packets will change the + // demuxer position. + if (!track->preloaded && track->is_external) { + demux_seek(track->demuxer, 0, 0, SEEK_ABSOLUTE); + track->preloaded = sub_read_all_packets(dec_sub, sh_sub); + } } mpctx->osd->dec_sub = dec_sub; @@ -3920,16 +3866,15 @@ static void open_subtitles_from_options(struct MPContext *mpctx) // after reading video params we should load subtitles because // we know fps so now we can adjust subtitle time to ~6 seconds AST // check .sub - double sub_fps = mpctx->sh_video ? mpctx->sh_video->fps : 25; if (mpctx->opts.sub_name) { for (int i = 0; mpctx->opts.sub_name[i] != NULL; ++i) - mp_add_subtitles(mpctx, mpctx->opts.sub_name[i], sub_fps, 0); + mp_add_subtitles(mpctx, mpctx->opts.sub_name[i], 0); } if (mpctx->opts.sub_auto) { // auto load sub file ... char **tmp = find_text_subtitles(&mpctx->opts, mpctx->filename); int nsub = MP_TALLOC_ELEMS(tmp); for (int i = 0; i < nsub; i++) { - struct track *track = mp_add_subtitles(mpctx, tmp[i], sub_fps, 1); + struct track *track = mp_add_subtitles(mpctx, tmp[i], 1); if (track) track->auto_loaded = true; } @@ -3959,9 +3904,12 @@ static struct track *open_external_file(struct MPContext *mpctx, char *filename, case STREAM_SUB: ss = -1; break; } vs = -1; // avi can't go without video + struct demuxer_params params = { + .ass_library = mpctx->ass_library, // demux_libass requires it + }; struct demuxer *demuxer = demux_open_withparams(&mpctx->opts, stream, format, demuxer_name, - as, vs, ss, filename, NULL); + as, vs, ss, filename, ¶ms); if (!demuxer) { free_stream(stream); goto err_out; @@ -3999,12 +3947,11 @@ static void open_audiofiles_from_options(struct MPContext *mpctx) opts->audio_stream_cache, STREAM_AUDIO); } -// Just for -subfile. open_subtitles_from_options handles -sub text sub files. -static void open_subfiles_from_options(struct MPContext *mpctx) +struct track *mp_add_subtitles(struct MPContext *mpctx, char *filename, int noerr) { struct MPOpts *opts = &mpctx->opts; - open_external_file(mpctx, opts->sub_stream, opts->sub_demuxer_name, - 0, STREAM_SUB); + return open_external_file(mpctx, filename, opts->sub_demuxer_name, 0, + STREAM_SUB); } static void print_timeline(struct MPContext *mpctx) @@ -4293,13 +4240,20 @@ goto_reopen_demuxer: ; if (mpctx->timeline) timeline_set_part(mpctx, mpctx->timeline_part, true); + // Decide correct-pts mode based on first segment of video track + opts->correct_pts = opts->user_correct_pts; + if (opts->correct_pts < 0) { + opts->correct_pts = + demux_control(mpctx->demuxer, DEMUXER_CTRL_CORRECT_PTS, + NULL) == DEMUXER_CTRL_OK; + } + mpctx->initialized_flags |= INITIALIZED_DEMUXER; add_subtitle_fonts_from_sources(mpctx); open_subtitles_from_options(mpctx); open_audiofiles_from_options(mpctx); - open_subfiles_from_options(mpctx); check_previous_track_selection(mpctx); diff --git a/core/options.c b/core/options.c index f3e262fc17..40c8527394 100644 --- a/core/options.c +++ b/core/options.c @@ -406,7 +406,6 @@ const m_option_t mp_opts[] = { // demuxer.c - select audio/sub file/demuxer OPT_STRING("audiofile", audio_stream, 0), OPT_INTRANGE("audiofile-cache", audio_stream_cache, 0, 50, 65536), - OPT_STRING("subfile", sub_stream, 0), OPT_STRING("demuxer", demuxer_name, 0), OPT_STRING("audio-demuxer", audio_demuxer_name, 0), OPT_STRING("sub-demuxer", sub_demuxer_name, 0), @@ -493,12 +492,11 @@ const m_option_t mp_opts[] = { OPT_STRING("subcp", sub_cp, 0), OPT_FLOAT("sub-delay", sub_delay, 0), OPT_FLOAT("subfps", sub_fps, 0), + OPT_FLOAT("sub-speed", sub_speed, 0), OPT_FLAG("autosub", sub_auto, 0), OPT_FLAG("sub-visibility", sub_visibility, 0), OPT_FLAG("sub-forced-only", forced_subs_only, 0), - // enable Closed Captioning display - OPT_FLAG_CONSTANTS("overlapsub", suboverlap_enabled, 0, 0, 2), - OPT_FLAG_STORE("sub-no-text-pp", sub_no_text_pp, 0, 1), + OPT_FLAG_CONSTANTS("sub-fix-timing", suboverlap_enabled, 0, 1, 0), OPT_CHOICE("autosub-match", sub_match_fuzziness, 0, ({"exact", 0}, {"fuzzy", 1}, {"all", 2})), OPT_INTRANGE("sub-pos", sub_pos, 0, 0, 100), @@ -789,6 +787,7 @@ const struct MPOpts mp_default_opts = { .audio_display = 1, .sub_visibility = 1, .sub_pos = 100, + .sub_speed = 1.0, .extension_parsing = 1, .audio_output_channels = MP_CHMAP_INIT_STEREO, .audio_output_format = -1, // AF_FORMAT_UNKNOWN @@ -804,7 +803,7 @@ const struct MPOpts mp_default_opts = { .ass_vsfilter_aspect_compat = 1, .ass_style_override = 1, .use_embedded_fonts = 1, - .suboverlap_enabled = 1, + .suboverlap_enabled = 0, .hwdec_codecs = "all", diff --git a/core/options.h b/core/options.h index f925990a6c..0c6f6c7271 100644 --- a/core/options.h +++ b/core/options.h @@ -141,17 +141,16 @@ typedef struct MPOpts { int sub_pos; float sub_delay; float sub_fps; + float sub_speed; int forced_subs_only; char *quvi_format; // subreader.c int suboverlap_enabled; char *sub_cp; - int sub_no_text_pp; char *audio_stream; int audio_stream_cache; - char *sub_stream; char *demuxer_name; char *audio_demuxer_name; char *sub_demuxer_name; |