mirror of
https://github.com/mpv-player/mpv.git
synced 2024-09-20 03:52:22 +02:00
stream_dvd: better .ifo probing
stream_dvd.c includes a pseudo-protocol that recognizes .IFO files, and plays them using libdvdread. This was relatively lazy, and could perhaps easily trigger with files that just had the .ifo extension. Make the checks stricter, and even probe the file header. Apparently the first bytes in an .ifo file are always "DVDVIDEO-VTS", so check for this. Refuse to load the main "video_ts.ifo". The plan is to use stream_dvdnav for it. This also removes at least 1 memory leak.
This commit is contained in:
parent
d8f993705c
commit
d191de8564
@ -266,6 +266,7 @@ void mp_cancel_reset(struct mp_cancel *c);
|
||||
|
||||
// stream_file.c
|
||||
char *mp_file_url_to_filename(void *talloc_ctx, bstr url);
|
||||
char *mp_file_get_path(void *talloc_ctx, bstr url);
|
||||
|
||||
void stream_print_proto_list(struct mp_log *log);
|
||||
|
||||
|
@ -33,6 +33,8 @@
|
||||
#include <dvdread/ifo_read.h>
|
||||
#include <dvdread/nav_read.h>
|
||||
|
||||
#include "osdep/io.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "talloc.h"
|
||||
#include "common/common.h"
|
||||
@ -46,6 +48,7 @@
|
||||
#include "stream.h"
|
||||
#include "options/m_option.h"
|
||||
#include "options/options.h"
|
||||
#include "options/path.h"
|
||||
|
||||
#include "stream_dvd_common.h"
|
||||
|
||||
@ -913,38 +916,37 @@ fail:
|
||||
return STREAM_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static int ifo_stream_open (stream_t *stream)
|
||||
static int ifo_stream_open(stream_t *stream)
|
||||
{
|
||||
char* filename;
|
||||
dvd_priv_t *priv = talloc_ptrtype(stream, priv);
|
||||
stream->priv = priv;
|
||||
*priv = stream_priv_dflts;
|
||||
|
||||
// "file://" prefix -> decode URL-style escapes
|
||||
if (strlen(stream->url) > strlen(stream->path))
|
||||
mp_url_unescape_inplace(stream->path);
|
||||
char *path = mp_file_get_path(priv, bstr0(stream->url));
|
||||
if (!path)
|
||||
goto unsupported;
|
||||
|
||||
int len = strlen(stream->path);
|
||||
if (len < 4 || strcasecmp (stream->path + len - 4, ".ifo"))
|
||||
return STREAM_UNSUPPORTED;
|
||||
if (!dvd_probe(path, ".ifo", "DVDVIDEO-VTS"))
|
||||
goto unsupported;
|
||||
|
||||
MP_INFO(stream, ".IFO detected. Redirecting to dvd://\n");
|
||||
char *base = mp_basename(path);
|
||||
|
||||
filename = strdup(basename(stream->path));
|
||||
// Only accept individual titles - use dvdnav for video_ts.ifo
|
||||
if (strncasecmp(base, "vts_", 4))
|
||||
goto unsupported;
|
||||
|
||||
talloc_free(priv->cfg_device);
|
||||
priv->cfg_device = talloc_strdup(NULL, dirname(stream->path));
|
||||
if(!strncasecmp(filename,"vts_",4))
|
||||
{
|
||||
if(sscanf(filename+3, "_%02d_", &priv->cfg_title)!=0)
|
||||
priv->cfg_title = 0;
|
||||
}else
|
||||
priv->cfg_title = 0;
|
||||
if (sscanf(base + 3, "_%02d_", &priv->cfg_title) != 1)
|
||||
goto unsupported;
|
||||
|
||||
free(filename);
|
||||
stream->url=talloc_strdup(stream, "dvdread://");
|
||||
priv->cfg_device = bstrto0(priv, mp_dirname(path));
|
||||
|
||||
MP_INFO(stream, ".IFO detected. Redirecting to dvdread://\n");
|
||||
return open_s(stream);
|
||||
|
||||
unsupported:
|
||||
talloc_free(priv);
|
||||
stream->priv = NULL;
|
||||
return STREAM_UNSUPPORTED;
|
||||
}
|
||||
|
||||
const stream_info_t stream_info_dvd = {
|
||||
|
@ -21,6 +21,9 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <libavutil/intreadwrite.h>
|
||||
|
||||
#include "config.h"
|
||||
@ -42,6 +45,7 @@
|
||||
#include "osdep/io.h"
|
||||
|
||||
#include "common/msg.h"
|
||||
#include "misc/bstr.h"
|
||||
#include "stream_dvd_common.h"
|
||||
|
||||
const char * const dvd_audio_stream_types[8] = { "ac3","unknown","mpeg1","mpeg2ext","lpcm","unknown","dts" };
|
||||
@ -134,3 +138,28 @@ int mp_dvdtimetomsec(dvd_time_t *dt)
|
||||
msec += (((dt->frame_u & 0x30) >> 3) * 5 + (dt->frame_u & 0x0f)) * 100000 / framerate;
|
||||
return msec;
|
||||
}
|
||||
|
||||
// Check if this is likely to be an .ifo or similar file.
|
||||
int dvd_probe(const char *path, const char *ext, const char *sig)
|
||||
{
|
||||
if (!bstr_case_endswith(bstr0(path), bstr0(ext)))
|
||||
return false;
|
||||
|
||||
FILE *temp = fopen(path, "rb");
|
||||
if (!temp)
|
||||
return false;
|
||||
|
||||
bool r = false;
|
||||
|
||||
char data[50];
|
||||
|
||||
assert(strlen(sig) <= sizeof(data));
|
||||
|
||||
if (fread(data, 50, 1, temp) == 1) {
|
||||
if (memcmp(data, sig, strlen(sig)) == 0)
|
||||
r = true;
|
||||
}
|
||||
|
||||
fclose(temp);
|
||||
return r;
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
#define MPLAYER_STREAM_DVD_COMMON_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <dvdread/ifo_types.h>
|
||||
#include <stdbool.h>
|
||||
#include "stream.h"
|
||||
|
||||
extern const char * const dvd_audio_stream_channels[6];
|
||||
@ -29,4 +29,6 @@ extern const char * const dvd_audio_stream_types[8];
|
||||
void dvd_set_speed(stream_t *stream, char *device, unsigned speed);
|
||||
int mp_dvdtimetomsec(dvd_time_t *dt);
|
||||
|
||||
int dvd_probe(const char *path, const char *ext, const char *sig);
|
||||
|
||||
#endif /* MPLAYER_STREAM_DVD_COMMON_H */
|
||||
|
@ -126,6 +126,17 @@ char *mp_file_url_to_filename(void *talloc_ctx, bstr url)
|
||||
return filename;
|
||||
}
|
||||
|
||||
// Return talloc_strdup's filesystem path if local, otherwise NULL.
|
||||
// Unlike mp_file_url_to_filename(), doesn't return NULL if already local.
|
||||
char *mp_file_get_path(void *talloc_ctx, bstr url)
|
||||
{
|
||||
if (mp_split_proto(url, &(bstr){0}).len) {
|
||||
return mp_file_url_to_filename(talloc_ctx, url);
|
||||
} else {
|
||||
return bstrto0(talloc_ctx, url);
|
||||
}
|
||||
}
|
||||
|
||||
#if HAVE_BSD_FSTATFS
|
||||
static bool check_stream_network(stream_t *stream)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user