summaryrefslogtreecommitdiffstats
path: root/stream
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-09-26 00:14:58 +0200
committerwm4 <wm4@nowhere>2014-09-26 00:30:21 +0200
commitd6c27855d70f3909ea083e03ea51b458f2a35411 (patch)
treea8f7bf7f3c61e153609ed610764ab4be86bf6fde /stream
parentc3f77731380579323d3cf74bb739aace0a9d6717 (diff)
downloadmpv-d6c27855d70f3909ea083e03ea51b458f2a35411.tar.bz2
mpv-d6c27855d70f3909ea083e03ea51b458f2a35411.tar.xz
stream_bluray: allow opening BDMV directories directly
Similar as the previous commits. Most of the code is actually copied from the stream_dvdnav.c code, but I'd rather prefer to duplicate it, than to entangle them. The latter would probably result in terrible things in a few years.
Diffstat (limited to 'stream')
-rw-r--r--stream/stream.c2
-rw-r--r--stream/stream_bluray.c86
2 files changed, 88 insertions, 0 deletions
diff --git a/stream/stream.c b/stream/stream.c
index 6a231713fb..f551fd89b5 100644
--- a/stream/stream.c
+++ b/stream/stream.c
@@ -68,6 +68,7 @@ extern const stream_info_t stream_info_ifo;
extern const stream_info_t stream_info_ifo_dvdnav;
extern const stream_info_t stream_info_dvd;
extern const stream_info_t stream_info_dvdnav;
+extern const stream_info_t stream_info_bdmv_dir;
extern const stream_info_t stream_info_bluray;
extern const stream_info_t stream_info_bdnav;
extern const stream_info_t stream_info_rar_filter;
@@ -102,6 +103,7 @@ static const stream_info_t *const stream_list[] = {
&stream_info_dvdnav,
#endif
#if HAVE_LIBBLURAY
+ &stream_info_bdmv_dir,
&stream_info_bluray,
&stream_info_bdnav,
#endif
diff --git a/stream/stream_bluray.c b/stream/stream_bluray.c
index 686541b551..8ba796e609 100644
--- a/stream/stream_bluray.c
+++ b/stream/stream_bluray.c
@@ -28,6 +28,7 @@
*/
#include <string.h>
+#include <strings.h>
#include <assert.h>
#include <libbluray/bluray.h>
@@ -43,6 +44,7 @@
#include "common/msg.h"
#include "options/m_option.h"
#include "options/options.h"
+#include "options/path.h"
#include "stream.h"
#include "osdep/timer.h"
#include "discnav.h"
@@ -829,3 +831,87 @@ const stream_info_t stream_info_bdnav = {
NULL
},
};
+
+static bool check_bdmv(const char *path)
+{
+ if (strcasecmp(mp_basename(path), "MovieObject.bdmv"))
+ return false;
+
+ FILE *temp = fopen(path, "rb");
+ if (!temp)
+ return false;
+
+ bool r = false;
+
+ const char *sig = "MOBJ020";
+ char data[50];
+
+ if (fread(data, 50, 1, temp) == 1) {
+ if (memcmp(data, sig, strlen(sig)) == 0)
+ r = true;
+ }
+
+ fclose(temp);
+ return r;
+}
+
+// Destructively remove the current trailing path component.
+static void remove_prefix(char *path)
+{
+ size_t len = strlen(path);
+#if HAVE_DOS_PATHS
+ const char *seps = "/\\";
+#else
+ const char *seps = "/";
+#endif
+ while (len > 0 && !strchr(seps, path[len - 1]))
+ len--;
+ while (len > 0 && strchr(seps, path[len - 1]))
+ len--;
+ path[len] = '\0';
+}
+
+static int bdmv_dir_stream_open(stream_t *stream)
+{
+ struct bluray_priv_s *priv = talloc_ptrtype(stream, priv);
+ stream->priv = priv;
+ *priv = bluray_stream_priv_dflts;
+
+ char *path = mp_file_get_path(priv, bstr0(stream->url));
+ if (!path)
+ goto unsupported;
+
+ // We allow the path to point to a directory containing BDMV/, a
+ // directory containing MovieObject.bdmv, or that file itself.
+ if (!check_bdmv(path)) {
+ // On UNIX, just assume the filename has always this case.
+ char *npath = mp_path_join(priv, bstr0(path), bstr0("MovieObject.bdmv"));
+ if (!check_bdmv(npath)) {
+ npath = mp_path_join(priv, bstr0(path), bstr0("BDMV/MovieObject.bdmv"));
+ if (!check_bdmv(npath))
+ goto unsupported;
+ }
+ path = npath;
+ }
+
+ // Go up by 2 levels.
+ remove_prefix(path);
+ remove_prefix(path);
+ priv->cfg_device = path;
+ if (strlen(priv->cfg_device) <= 1)
+ goto unsupported;
+
+ MP_INFO(stream, "BDMV detected. Redirecting to bluray://\n");
+ return bluray_stream_open(stream);
+
+unsupported:
+ talloc_free(priv);
+ stream->priv = NULL;
+ return STREAM_UNSUPPORTED;
+}
+
+const stream_info_t stream_info_bdmv_dir = {
+ .name = "bdmv/bluray",
+ .open = bdmv_dir_stream_open,
+ .protocols = (const char*const[]){ "file", "", NULL },
+};