demux_lavf: do a better job at guessing the vobsub .sub filename

Vobsubs come as .idx/.sub pair of files. The .idx file is the one that
should be opened, but the name of the .sub file is unknown. We can now
make our own guess what the name of that file is. In particular, improve
support with URLs (as these can have the file extension in the middle of
the filename string if there are HTTP parameters).

Note that this works only with newer ffmpeg versions, because the
recently added sub_name demuxer option is used for this.
This commit is contained in:
wm4 2015-05-28 21:51:54 +02:00
parent ce0bf9692f
commit 0949ee347d
1 changed files with 40 additions and 0 deletions

View File

@ -45,6 +45,7 @@
#include "demux.h" #include "demux.h"
#include "stheader.h" #include "stheader.h"
#include "options/m_option.h" #include "options/m_option.h"
#include "options/path.h"
#define INITIAL_PROBE_SIZE STREAM_BUFFER_SIZE #define INITIAL_PROBE_SIZE STREAM_BUFFER_SIZE
@ -414,6 +415,43 @@ static void parse_cryptokey(AVFormatContext *avfc, const char *str)
*key++ = (char2int(str[0]) << 4) | char2int(str[1]); *key++ = (char2int(str[0]) << 4) | char2int(str[1]);
} }
static char *replace_idx_ext(void *ta_ctx, bstr f)
{
if (f.len < 4 || f.start[f.len - 4] != '.')
return NULL;
char *ext = bstr_endswith0(f, "IDX") ? "SUB" : "sub"; // match case
return talloc_asprintf(ta_ctx, "%.*s.%s", f.len - 4, f.start, ext);
}
static void guess_and_set_vobsub_name(struct demuxer *demuxer, AVDictionary **d)
{
lavf_priv_t *priv = demuxer->priv;
if (!matches_avinputformat_name(priv, "vobsub"))
return;
void *tmp = talloc_new(NULL);
bstr bfilename = bstr0(priv->filename);
char *subname = NULL;
if (mp_is_url(bfilename)) {
// It might be a http URL, which has additional parameters after the
// end of the actual file path.
bstr start, end;
if (bstr_split_tok(bfilename, "?", &start, &end)) {
subname = replace_idx_ext(tmp, start);
if (subname)
subname = talloc_asprintf(tmp, "%s?%.*s", subname, BSTR_P(end));
}
}
if (!subname)
subname = replace_idx_ext(tmp, bfilename);
if (!subname)
subname = talloc_asprintf(tmp, "%.*s.sub", BSTR_P(bfilename));
MP_VERBOSE(demuxer, "Assuming associated .sub file: %s\n", subname);
av_dict_set(d, "sub_name", subname, 0);
talloc_free(tmp);
}
static void select_tracks(struct demuxer *demuxer, int start) static void select_tracks(struct demuxer *demuxer, int start)
{ {
lavf_priv_t *priv = demuxer->priv; lavf_priv_t *priv = demuxer->priv;
@ -742,6 +780,8 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check)
av_dict_set(&dopts, "rtsp_transport", transport, 0); av_dict_set(&dopts, "rtsp_transport", transport, 0);
} }
guess_and_set_vobsub_name(demuxer, &dopts);
avfc->interrupt_callback = (AVIOInterruptCB){ avfc->interrupt_callback = (AVIOInterruptCB){
.callback = interrupt_cb, .callback = interrupt_cb,
.opaque = demuxer, .opaque = demuxer,