Skip to content

Commit

Permalink
Add the ability to playback remote DVD and Blu-ray directory images a…
Browse files Browse the repository at this point in the history
…nd DVD

ISO files via MythTV's streaming protocol.  The full implementation is an
interim solution, parts of it will be changed in the future.
Post 0.24, we'll probably be moving the libraries into the new 'external'
subdir.  The desire is to coordinate a standard 'plugable' layout where can
plug in our RingBuffer wrapper routines without having to modify the upstream
library in any way.  the Blu-ray library already has partial support for this,
but it will need extending to fully allow us to use the library for remote
streaming without making any of our own changes to the code.

URI Examples (substitute in your favorite Storage Group and subdirectory):

Blu-ray image (BDMV subdirectory is under a 'Demos/x264_bluray_demo'
  directory in Storage Group)

  mythavtest myth://MyDiscImages@192.168.1.100/Demos/x264_bluray_demo

DVD image (VIDEO_TS subdirectory is under the 'Hot_Dogs_II' directory)

  mythavtest myth://MyDiscImages@192.168.1.100/Hot_Dogs_II

DVD ISO (ISO is in a 'Documentaries' sudirectory of the Storage Group

  mythavtest myth://MyISOs@192.168.1.100/Documentaries/Hot_Dogs_II.iso

ISO playback is by far the fastest, the libs do a lot of seeking around
which exposes some inefficiencies in our RingBuffer.  These are being
looked at, so performance should improve.  Directory image playback
does take longer to startup than ISO playback, but once playback
has started, they should both perform about the same since the RingBuffer
has a built-in read-ahead buffer.

Encrypted DVDs are not supported for remote streaming.  In other words,
you can't currently point a Backend's Storage Group at /dev/dvd or a
directory where you have a DVD mounted and expect to be able to watch
it on a remote frontend.


NOTE: This does modify the binary API, AND the protocol version, so make clean,
upgrade everything, etc..



git-svn-id: http://svn.mythtv.org/svn/trunk@25858 7dbf422c-18fa-0310-86e9-fd20926502f2
  • Loading branch information
cpinkham committed Aug 26, 2010
1 parent 9c3564a commit 3af3489
Show file tree
Hide file tree
Showing 28 changed files with 769 additions and 48 deletions.
2 changes: 1 addition & 1 deletion mythtv/bindings/perl/MythTV.pm
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ package MythTV;
# Note: as of July 21, 2010, this is actually a string, to account for proto
# versions of the form "58a". This will get used if protocol versions are
# changed on a fixes branch ongoing.
our $PROTO_VERSION = "58";
our $PROTO_VERSION = "59";

# NUMPROGRAMLINES is defined in mythtv/libs/libmythtv/programinfo.h and is
# the number of items in a ProgramInfo QStringList group used by
Expand Down
2 changes: 1 addition & 1 deletion mythtv/bindings/python/MythTV/static.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
MVSCHEMA_VERSION = 1036
NVSCHEMA_VERSION = 1007
MUSICSCHEMA_VERSION = 1017
PROTO_VERSION = '58'
PROTO_VERSION = '59'
BACKEND_SEP = '[]:[]'

class MARKUP( object ):
Expand Down
4 changes: 2 additions & 2 deletions mythtv/libs/libmyth/programinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1865,13 +1865,13 @@ void ProgramInfo::SetPathname(const QString &pn) const
ProgramInfoType pit = kProgramInfoTypeVideoFile;
if (chanid)
pit = kProgramInfoTypeRecording;
else if (pathname.toLower().startsWith("dvd:"))
else if (myth_FileIsDVD(pathname))
pit = kProgramInfoTypeVideoDVD;
else if (pathname.toLower().startsWith("http:"))
pit = kProgramInfoTypeVideoStreamingHTML;
else if (pathname.toLower().startsWith("rtsp:"))
pit = kProgramInfoTypeVideoStreamingRTSP;
else if (pathname.toLower().startsWith("bd:"))
else if (myth_FileIsBD(pathname))
pit = kProgramInfoTypeVideoBD;
const_cast<ProgramInfo*>(this)->SetProgramInfoType(pit);
}
Expand Down
35 changes: 35 additions & 0 deletions mythtv/libs/libmyth/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ using namespace std;
#include "msocketdevice.h"
#include "mythsocket.h"
#include "mythcoreutil.h"
#include "remotefile.h"

#include "mythconfig.h" // for CONFIG_DARWIN

Expand Down Expand Up @@ -1306,4 +1307,38 @@ void myth_yield(void)
#endif
}

bool myth_FileIsDVD(const QString &filename)
{
if ((filename.toLower().startsWith("dvd:")) ||
(filename.toLower().endsWith(".iso")) ||
(filename.toLower().endsWith(".img")) ||
(QDir(filename + "/VIDEO_TS").exists()))
return true;

if (filename.toLower().startsWith("myth://"))
{
QString tmpFile = filename + "/VIDEO_TS";
if (RemoteFile::Exists(tmpFile))
return true;
}

return false;
}

bool myth_FileIsBD(const QString &filename)
{
if ((filename.toLower().startsWith("bd:")) ||
(QDir(filename + "/BDMV").exists()))
return true;

if (filename.toLower().startsWith("myth://"))
{
QString tmpFile = filename + "/BDMV";
if (RemoteFile::Exists(tmpFile))
return true;
}

return false;
}

/* vim: set expandtab tabstop=4 shiftwidth=4: */
3 changes: 3 additions & 0 deletions mythtv/libs/libmyth/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ MPUBLIC bool IsPulseAudioRunning(void);
MPUBLIC bool myth_nice(int val);
MPUBLIC void myth_yield(void);

MPUBLIC bool myth_FileIsDVD(const QString &filename);
MPUBLIC bool myth_FileIsBD(const QString &filename);

// CPU Tick timing function
#ifdef MMX
#ifdef _WIN32
Expand Down
17 changes: 15 additions & 2 deletions mythtv/libs/libmythbluray/bluray.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@
#include <stdlib.h>
#include <inttypes.h>
#include <string.h>
#include <sys/types.h>

#include "mythiowrapper.h"

typedef int (*fptr_int)();
typedef int32_t (*fptr_int32)();
Expand Down Expand Up @@ -207,6 +210,7 @@ static void _close_m2ts(BD_STREAM *st)
static int _open_m2ts(BLURAY *bd, BD_STREAM *st)
{
char *f_name;
struct stat buf;

_close_m2ts(st);

Expand All @@ -217,8 +221,17 @@ static int _open_m2ts(BLURAY *bd, BD_STREAM *st)
st->clip_block_pos = (st->clip_pos / 6144) * 6144;

if ((st->fp = file_open(f_name, "rb"))) {
file_seek(st->fp, 0, SEEK_END);
if ((st->clip_size = file_tell(st->fp))) {
// Original libbluray code
// file_seek(st->fp, 0, SEEK_END);
// if ((st->clip_size = file_tell(st->fp))) {
// New 'stat' and modified 'if' to minimize RingBuffer seeking
// Optimize here for now until we can optimize in the RingBuffer itself
if (mythfile_stat(f_name, &buf) == 0)
st->clip_size = buf.st_size;
else
st->clip_size = 0;

if (st->clip_size) {
file_seek(st->fp, st->clip_block_pos, SEEK_SET);
st->int_buf_off = 6144;
X_FREE(f_name);
Expand Down
56 changes: 56 additions & 0 deletions mythtv/libs/libmythbluray/file/dir_mythiowrapper.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#if HAVE_CONFIG_H
#include "config.h"
#endif

#include "file.h"
#include "util/macro.h"
#include "util/logging.h"

#include "mythiowrapper.h"

static void dir_close_mythiowrapper(BD_DIR_H *dir)
{
if (dir) {
mythdir_closedir((int)dir->internal);

DEBUG(DBG_DIR, "Closed mythdir dir (%p)\n", dir);

X_FREE(dir);
}
}

static int dir_read_mythiowrapper(BD_DIR_H *dir, BD_DIRENT *entry)
{
char *filename = mythdir_readdir((int)dir->internal);
if (filename)
{
strncpy(entry->d_name, filename, 256);
free(filename);
return 0;
}

return 1;
}

BD_DIR_H *dir_open_mythiowrapper(const char* dirname)
{
BD_DIR_H *dir = malloc(sizeof(BD_DIR_H));

DEBUG(DBG_DIR, "Opening mythdir dir %s... (%p)\n", dirname, dir);
dir->close = dir_close_mythiowrapper;
dir->read = dir_read_mythiowrapper;

int dirID = 0;
if ((dirID = mythdir_opendir(dirname))) {
dir->internal = (void *)dirID;

return dir;
}

DEBUG(DBG_DIR, "Error opening dir! (%p)\n", dir);

X_FREE(dir);

return NULL;
}

4 changes: 4 additions & 0 deletions mythtv/libs/libmythbluray/file/dir_posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#endif

#include "file.h"
#include "file_mythiowrapper.h"
#include "util/macro.h"
#include "util/logging.h"
#include "util/strutl.h"
Expand Down Expand Up @@ -90,6 +91,9 @@ static int dir_read_posix(BD_DIR_H *dir, BD_DIRENT *entry)

static BD_DIR_H *dir_open_posix(const char* dirname)
{
if (strncmp(dirname, "myth://", 7) == 0)
return dir_open_mythiowrapper(dirname);

BD_DIR_H *dir = malloc(sizeof(BD_DIR_H));

DEBUG(DBG_DIR, "Opening POSIX dir %s... (%p)\n", dirname, dir);
Expand Down
83 changes: 83 additions & 0 deletions mythtv/libs/libmythbluray/file/file_mythiowrapper.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#if HAVE_CONFIG_H
#include "config.h"
#endif

#include <fcntl.h>

#include "file.h"
#include "util/macro.h"
#include "util/logging.h"

#include "mythiowrapper.h"

static void file_close_mythiowrapper(BD_FILE_H *file)
{
if (file) {
mythfile_close((int)file->internal);

DEBUG(DBG_FILE, "Closed mythfile file (%p)\n", file);

X_FREE(file);
}
}

static int64_t file_seek_mythiowrapper(BD_FILE_H *file, int64_t offset, int32_t origin)
{
return mythfile_seek((int)file->internal, offset, origin);
}

static int64_t file_tell_mythiowrapper(BD_FILE_H *file)
{
return mythfile_tell((int)file->internal);
}

static int file_eof_mythiowrapper(BD_FILE_H *file)
{
// FIXME
// return mythfile_eof((FILE *)file->internal);

fprintf(stderr, "file_eof_mythiowrapper() ERROR UNIMPLEMENTED\n");
return 0;
}

static int64_t file_read_mythiowrapper(BD_FILE_H *file, uint8_t *buf, int64_t size)
{
return mythfile_read((int)file->internal, buf, size);
}

static int64_t file_write_mythiowrapper(BD_FILE_H *file, const uint8_t *buf, int64_t size)
{
return mythfile_write((int)file->internal, buf, size);
}

BD_FILE_H *file_open_mythiowrapper(const char* filename, const char *mode)
{
FILE *fp = NULL;
BD_FILE_H *file = malloc(sizeof(BD_FILE_H));

DEBUG(DBG_FILE, "Opening mythfile file %s... (%p)\n", filename, file);
file->close = file_close_mythiowrapper;
file->seek = file_seek_mythiowrapper;
file->read = file_read_mythiowrapper;
file->write = file_write_mythiowrapper;
file->tell = file_tell_mythiowrapper;
file->eof = file_eof_mythiowrapper;

int fd;
int intMode = O_RDONLY;
if (!strcasecmp(mode, "wb"))
intMode = O_WRONLY;

if ((fd = mythfile_open(filename, intMode)) >= 0) {
file->internal = (void *)fd;

return file;
}

DEBUG(DBG_FILE, "Error opening file! (%p)\n", file);

X_FREE(file);

return NULL;
}

10 changes: 10 additions & 0 deletions mythtv/libs/libmythbluray/file/file_mythiowrapper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef __FILE_MYTHIOWRAPPER__
#define __FILE_MYTHIOWRAPPER__

#include "file.h"

BD_FILE_H *file_open_mythiowrapper(const char* filename, const char *mode);
BD_DIR_H *dir_open_mythiowrapper(const char* dirname);

#endif

4 changes: 4 additions & 0 deletions mythtv/libs/libmythbluray/file/file_posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#endif

#include "file.h"
#include "file_mythiowrapper.h"
#include "util/macro.h"
#include "util/logging.h"

Expand Down Expand Up @@ -80,6 +81,9 @@ static int64_t file_write_linux(BD_FILE_H *file, const uint8_t *buf, int64_t siz

static BD_FILE_H *file_open_linux(const char* filename, const char *mode)
{
if (strncmp(filename, "myth://", 7) == 0)
return file_open_mythiowrapper(filename, mode);

FILE *fp = NULL;
BD_FILE_H *file = malloc(sizeof(BD_FILE_H));

Expand Down
1 change: 1 addition & 0 deletions mythtv/libs/libmythbluray/libmythbluray.pro
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ target.path = $${LIBDIR}
INCLUDEPATH += . ../../
INCLUDEPATH += ./bdnav
INCLUDEPATH += ../libmythdb
INCLUDEPATH += ../libmythtv

DEFINES += HAVE_CONFIG_H DLOPEN_CRYPTO_LIBS HAVE_PTHREAD_H HAVE_DIRENT_H

Expand Down
4 changes: 2 additions & 2 deletions mythtv/libs/libmythdb/mythversion.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
/// Update this whenever the plug-in API changes.
/// Including changes in the libmythdb, libmyth, libmythtv, libmythav* and
/// libmythui class methods used by plug-ins.
#define MYTH_BINARY_VERSION "0.23.20100825-1"
#define MYTH_BINARY_VERSION "0.23.20100826-1"

/** \brief Increment this whenever the MythTV network protocol changes.
*
Expand All @@ -30,7 +30,7 @@
* mythtv/bindings/python/MythTV/static.py (version number)
* mythtv/bindings/python/MythTV/mythproto.py (layout)
*/
#define MYTH_PROTO_VERSION "58"
#define MYTH_PROTO_VERSION "59"

MPUBLIC const char *GetMythSourceVersion();

Expand Down
25 changes: 25 additions & 0 deletions mythtv/libs/libmythdb/remotefile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,12 @@ bool RemoteFile::DeleteFile(const QString &url)
}

bool RemoteFile::Exists(const QString &url)
{
struct stat fileinfo;
return Exists(url, &fileinfo);
}

bool RemoteFile::Exists(const QString &url, struct stat *fileinfo)
{
bool result = false;
QUrl qurl(url);
Expand All @@ -256,7 +262,26 @@ bool RemoteFile::Exists(const QString &url)
gCoreContext->SendReceiveStringList(strlist);

if (strlist[0] == "1")
{
result = true;
if (fileinfo)
{
int pos = 2;
fileinfo->st_dev = strlist[pos++].toLongLong();
fileinfo->st_ino = strlist[pos++].toLongLong();
fileinfo->st_mode = strlist[pos++].toLongLong();
fileinfo->st_nlink = strlist[pos++].toLongLong();
fileinfo->st_uid = strlist[pos++].toLongLong();
fileinfo->st_gid = strlist[pos++].toLongLong();
fileinfo->st_rdev = strlist[pos++].toLongLong();
fileinfo->st_size = strlist[pos++].toLongLong();
fileinfo->st_blksize = strlist[pos++].toLongLong();
fileinfo->st_blocks = strlist[pos++].toLongLong();
fileinfo->st_atime = strlist[pos++].toLongLong();
fileinfo->st_mtime = strlist[pos++].toLongLong();
fileinfo->st_ctime = strlist[pos++].toLongLong();
}
}

return result;
}
Expand Down
Loading

0 comments on commit 3af3489

Please sign in to comment.