diff options
author | wm4 <wm4@nowhere> | 2013-06-22 02:09:52 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2013-06-25 00:11:56 +0200 |
commit | cfa45c40dc0cfe44b699029168b62d4d3e16c288 (patch) | |
tree | 5a80d3b6e82711a5816c509e803c029b93342892 /demux | |
parent | 1bfae45a88ac7c24b74a6f7ca6eb4aa27d20c653 (diff) | |
download | mpv-cfa45c40dc0cfe44b699029168b62d4d3e16c288.tar.bz2 mpv-cfa45c40dc0cfe44b699029168b62d4d3e16c288.tar.xz |
sub: add demux_libass wrapper, drop old hacks
demux_libass.c allows us to make subtitle format detection part of the
normal file loading process. libass has no probe function, but trying to
load the start of a file (the first 4 KB) is good enough. Hope that
libass can even handle random binary input gracefully without printing
stupid log messages, and that the libass parser doesn't accept too many
non-ASS files as input.
This doesn't handle the -subcp option correctly yet. This will be fixed
later.
Diffstat (limited to 'demux')
-rw-r--r-- | demux/demux.c | 17 | ||||
-rw-r--r-- | demux/demux.h | 6 | ||||
-rw-r--r-- | demux/demux_libass.c | 108 | ||||
-rw-r--r-- | demux/demux_sub.c | 38 |
4 files changed, 112 insertions, 57 deletions
diff --git a/demux/demux.c b/demux/demux.c index 369e7f3226..b66f5e3e61 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -67,7 +67,7 @@ extern const demuxer_desc_t demuxer_desc_mpeg_es; extern const demuxer_desc_t demuxer_desc_mpeg4_es; extern const demuxer_desc_t demuxer_desc_h264_es; extern const demuxer_desc_t demuxer_desc_mpeg_ts; -extern const demuxer_desc_t demuxer_desc_sub; +extern const demuxer_desc_t demuxer_desc_libass; extern const demuxer_desc_t demuxer_desc_subreader; /* Please do not add any new demuxers here. If you want to implement a new @@ -82,6 +82,7 @@ const demuxer_desc_t *const demuxer_list[] = { #ifdef CONFIG_TV &demuxer_desc_tv, #endif + &demuxer_desc_libass, &demuxer_desc_matroska, &demuxer_desc_lavf, &demuxer_desc_subreader, @@ -99,8 +100,6 @@ const demuxer_desc_t *const demuxer_list[] = { &demuxer_desc_mpeg_ts, // auto-probe last, because it checks file-extensions only &demuxer_desc_mf, - // no auto-probe - &demuxer_desc_sub, /* Please do not add any new demuxers here. If you want to implement a new * demuxer, add it to libavformat, except for wrappers around external * libraries and demuxers requiring binary support. */ @@ -289,18 +288,6 @@ static demuxer_t *new_demuxer(struct MPOpts *opts, stream_t *stream, int type, return d; } -// for demux_sub.c -demuxer_t *new_sub_pseudo_demuxer(struct MPOpts *opts) -{ - struct stream *s = open_stream("null://", NULL, NULL); - assert(s); - struct demuxer *d = new_demuxer(opts, s, DEMUXER_TYPE_SUB, - -1, -1, -1, NULL); - new_sh_stream(d, STREAM_SUB); - talloc_steal(d, s); - return d; -} - static struct sh_stream *new_sh_stream_id(demuxer_t *demuxer, enum stream_type type, int stream_index, diff --git a/demux/demux.h b/demux/demux.h index 9c10ca0201..f49a236b80 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -72,13 +72,13 @@ enum demuxer_type { DEMUXER_TYPE_EDL, DEMUXER_TYPE_CUE, DEMUXER_TYPE_SUBREADER, + DEMUXER_TYPE_LIBASS, /* Values after this are for internal use and can not be selected * as demuxer type by the user (-demuxer option). */ DEMUXER_TYPE_END, DEMUXER_TYPE_PLAYLIST, - DEMUXER_TYPE_SUB, }; enum timestamp_type { @@ -217,6 +217,7 @@ struct demuxer_params { unsigned char (*matroska_wanted_uids)[16]; int matroska_wanted_segment; bool *matroska_was_valid; + struct ass_library *ass_library; }; typedef struct demuxer { @@ -307,9 +308,6 @@ static inline void *realloc_struct(void *ptr, size_t nmemb, size_t size) return realloc(ptr, nmemb * size); } -demuxer_t *new_sub_pseudo_demuxer(struct MPOpts *opts); - - void free_demuxer(struct demuxer *demuxer); int demuxer_add_packet(demuxer_t *demuxer, struct sh_stream *stream, diff --git a/demux/demux_libass.c b/demux/demux_libass.c new file mode 100644 index 0000000000..1b7dc24452 --- /dev/null +++ b/demux/demux_libass.c @@ -0,0 +1,108 @@ +/* + * This file is part of mpv. + * + * 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/>. + */ + +// Note: just wraps libass, and makes the subtitle track available though +// sh_sub->track. It doesn't produce packets and doesn't support seeking. + +#include <ass/ass.h> +#include <ass/ass_types.h> + +#include "core/options.h" +#include "core/mp_msg.h" +#include "stream/stream.h" +#include "demux.h" + +#define PROBE_SIZE (4 * 1024) + +struct priv { + ASS_Track *track; +}; + +static int d_check_file(struct demuxer *demuxer) +{ + struct stream *s = demuxer->stream; + // Older versions of libass will behave strange if renderer and track + // library handles mismatch, so make sure everything uses a global handle. + ASS_Library *lib = demuxer->params ? demuxer->params->ass_library : NULL; + if (!lib) + return 0; + + // Probe by loading a part of the beginning of the file with libass. + // Incomplete scripts are usually ok, and we hope libass is not verbose + // when dealing with (from its perspective) completely broken binary + // garbage. + + bstr buf = stream_peek(s, PROBE_SIZE); + // Older versions of libass will overwrite the input buffer, and despite + // passing length, expect a 0 termination. + void *tmp = talloc_size(NULL, buf.len + 1); + memcpy(tmp, buf.start, buf.len); + buf.start = tmp; + buf.start[buf.len] = '\0'; + ASS_Track *track = ass_read_memory(lib, buf.start, buf.len, NULL); + talloc_free(buf.start); + if (!track) + return 0; + ass_free_track(track); + + // Actually load the full thing. + + buf = stream_read_complete(s, NULL, 100000000); + if (!buf.start) { + mp_tmsg(MSGT_ASS, MSGL_ERR, "Refusing to load subtitle file " + "larger than 100 MB: %s\n", demuxer->filename); + return 0; + } + track = ass_read_memory(lib, buf.start, buf.len, NULL); + talloc_free(buf.start); + if (!track) + return 0; + + track->name = strdup(demuxer->filename); + + struct priv *p = talloc_ptrtype(demuxer, p); + *p = (struct priv) { + .track = track, + }; + + struct sh_stream *sh = new_sh_stream(demuxer, STREAM_SUB); + sh->sub->track = track; + sh->codec = "ass"; + + return DEMUXER_TYPE_LIBASS; +} + +static void d_close(struct demuxer *demuxer) +{ + struct priv *p = demuxer->priv; + if (p) { + if (p->track) + ass_free_track(p->track); + } +} + +const struct demuxer_desc demuxer_desc_libass = { + .info = "Read subtitles with libass", + .name = "libass", + .shortdesc = "ASS/SSA subtitles (libass)", + .author = "", + .comment = "", + .safe_check = 1, + .type = DEMUXER_TYPE_LIBASS, + .check_file = d_check_file, + .close = d_close, +}; diff --git a/demux/demux_sub.c b/demux/demux_sub.c deleted file mode 100644 index ab99091215..0000000000 --- a/demux/demux_sub.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * This file is part of mpv. - * - * 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/>. - */ - -// Note: not a real demuxer. The frontend has its own code to open subtitle -// code, and then creates a new dummy demuxer with new_sub_demuxer(). -// But eventually, all subtitles should be opened this way, and this -// file can be removed. - -#include "demux.h" - -static int dummy_fill_buffer(struct demuxer *demuxer, struct demux_stream *ds) -{ - return 0; -} - -const struct demuxer_desc demuxer_desc_sub = { - .info = "External subtitles pseudo demuxer", - .name = "sub", - .shortdesc = "sub", - .author = "", - .comment = "", - .type = DEMUXER_TYPE_SUB, - .fill_buffer = dummy_fill_buffer, -}; |