[libdvdnav-devel] [PATCH 1/1] add dvdnav_open_stream
Thomas Guillem
tom at gllm.fr
Fri Oct 17 17:45:46 CEST 2014
open a DVD Device using external read/seek callbacks (see libdvdcss).
---
src/dvdnav.c | 26 ++++++++++++++++++++------
src/dvdnav/dvdnav.h | 23 +++++++++++++++++------
src/vm/vm.c | 12 ++++++++----
src/vm/vm.h | 3 ++-
4 files changed, 47 insertions(+), 17 deletions(-)
diff --git a/src/dvdnav.c b/src/dvdnav.c
index a5fac25..3b931e7 100644
--- a/src/dvdnav.c
+++ b/src/dvdnav.c
@@ -145,7 +145,9 @@ dvdnav_status_t dvdnav_free_dup(dvdnav_t *this) {
return DVDNAV_STATUS_OK;
}
-dvdnav_status_t dvdnav_open(dvdnav_t** dest, const char *path) {
+static dvdnav_status_t dvdnav_open_common(dvdnav_t** dest, const char *path,
+ void *stream,
+ dvdnav_stream_cb *stream_cb) {
dvdnav_t *this;
struct timeval time;
@@ -167,15 +169,18 @@ dvdnav_status_t dvdnav_open(dvdnav_t** dest, const char *path) {
printerr("Error initialising the DVD VM.");
goto fail;
}
- if(!vm_reset(this->vm, path)) {
+ if(!vm_reset(this->vm, path, stream, stream_cb)) {
printerr("Error starting the VM / opening the DVD device.");
goto fail;
}
/* Set the path. */
- this->path = strdup(path);
- if(!this->path)
- goto fail;
+ if(path != NULL)
+ {
+ this->path = strdup(path);
+ if(!this->path)
+ goto fail;
+ }
/* Pre-open and close a file so that the CSS-keys are cached. */
this->file = DVDOpenFile(vm_get_dvd_reader(this->vm), 0, DVD_READ_MENU_VOBS);
@@ -203,6 +208,15 @@ fail:
return DVDNAV_STATUS_ERR;
}
+dvdnav_status_t dvdnav_open(dvdnav_t** dest, const char *path) {
+ return dvdnav_open_common(dest, path, NULL, NULL);
+}
+
+dvdnav_status_t dvdnav_open_stream(dvdnav_t** dest,
+ void *stream, dvdnav_stream_cb *stream_cb) {
+ return dvdnav_open_common(dest, NULL, stream, stream_cb);
+}
+
dvdnav_status_t dvdnav_close(dvdnav_t *this) {
#ifdef LOG_DEBUG
@@ -250,7 +264,7 @@ dvdnav_status_t dvdnav_reset(dvdnav_t *this) {
#ifdef LOG_DEBUG
fprintf(MSG_OUT, "libdvdnav: reseting vm\n");
#endif
- if(!vm_reset(this->vm, NULL)) {
+ if(!vm_reset(this->vm, NULL, NULL, NULL)) {
printerr("Error restarting the VM.");
pthread_mutex_unlock(&this->vm_lock);
return DVDNAV_STATUS_ERR;
diff --git a/src/dvdnav/dvdnav.h b/src/dvdnav/dvdnav.h
index 4254534..660ad00 100644
--- a/src/dvdnav/dvdnav.h
+++ b/src/dvdnav/dvdnav.h
@@ -55,6 +55,14 @@ typedef struct dvdnav_s dvdnav_t;
/* Status as reported by most of libdvdnav's functions */
typedef int32_t dvdnav_status_t;
+struct dvdnav_stream_cb
+{
+ int ( *pf_seek ) ( void *p_stream, uint64_t i_pos);
+ int ( *pf_read ) ( void *p_stream, void* buffer, int i_read);
+ int ( *pf_readv ) ( void *p_stream, void *p_iovec, int i_blocks);
+};
+typedef struct dvdnav_stream_cb dvdnav_stream_cb;
+
/*
* Unless otherwise stated, all functions return DVDNAV_STATUS_OK if
* they succeeded, otherwise DVDNAV_STATUS_ERR is returned and the error may
@@ -73,15 +81,18 @@ typedef int32_t dvdnav_status_t;
*/
/*
- * Attempts to open the DVD drive at the specified path and pre-cache
- * the CSS-keys. libdvdread is used to access the DVD, so any source
- * supported by libdvdread can be given with "path". Currently,
- * libdvdread can access: DVD drives, DVD image files, DVD file-by-file
- * copies.
+ * Attempts to open the DVD drive at the specified path or using external
+ * seek/read functions (dvdnav_open_stream) and pre-cache the CSS-keys.
+ * libdvdread is used to access the DVD, so any source supported by libdvdread
+ * can be given with "path" or "stream_cb". Currently, using dvdnav_open,
+ * libdvdread can access : DVD drives, DVD image files, DVD file-by-file
+ * copies. Using dvdnav_open_stream, libdvdread can access any kind of DVD
+ * storage via custom implementation of seek/read functions.
*
* The resulting dvdnav_t handle will be written to *dest.
*/
-dvdnav_status_t dvdnav_open(dvdnav_t **dest, const char *path);
+dvdnav_status_t dvdnav_open(dvdnav_t **dest, const char *path); dvdnav_status_t
+dvdnav_open_stream(dvdnav_t **dest, void *stream, dvdnav_stream_cb *stream_cb);
dvdnav_status_t dvdnav_dup(dvdnav_t **dest, dvdnav_t *src);
dvdnav_status_t dvdnav_free_dup(dvdnav_t * _this);
diff --git a/src/vm/vm.c b/src/vm/vm.c
index 7e4d594..3fd5be5 100644
--- a/src/vm/vm.c
+++ b/src/vm/vm.c
@@ -292,7 +292,7 @@ dvd_reader_t *vm_get_dvd_reader(vm_t *vm) {
int vm_start(vm_t *vm) {
if (vm->stopped) {
- if (!vm_reset(vm, NULL))
+ if (!vm_reset(vm, NULL, NULL, NULL))
return 0;
vm->stopped = 0;
@@ -325,7 +325,8 @@ static void vm_close(vm_t *vm) {
vm->stopped = 1;
}
-int vm_reset(vm_t *vm, const char *dvdroot) {
+int vm_reset(vm_t *vm, const char *dvdroot,
+ void *stream, dvdnav_stream_cb *stream_cb) {
/* Setup State */
memset(vm->state.registers.SPRM, 0, sizeof(vm->state.registers.SPRM));
memset(vm->state.registers.GPRM, 0, sizeof(vm->state.registers.GPRM));
@@ -362,12 +363,15 @@ int vm_reset(vm_t *vm, const char *dvdroot) {
vm->hop_channel = 0;
- if (vm->dvd && dvdroot) {
+ if (vm->dvd && (dvdroot || (stream && stream_cb))) {
/* a new dvd device has been requested */
vm_close(vm);
}
if (!vm->dvd) {
- vm->dvd = DVDOpen(dvdroot);
+ if(dvdroot)
+ vm->dvd = DVDOpen(dvdroot);
+ else if(stream && stream_cb)
+ vm->dvd = DVDOpenStream(stream, (dvd_reader_stream_cb *)stream_cb);
if(!vm->dvd) {
fprintf(MSG_OUT, "libdvdnav: vm: failed to open/read the DVD\n");
return 0;
diff --git a/src/vm/vm.h b/src/vm/vm.h
index 57498d2..e4b01c2 100644
--- a/src/vm/vm.h
+++ b/src/vm/vm.h
@@ -114,7 +114,8 @@ dvd_reader_t *vm_get_dvd_reader(vm_t *vm);
/* Basic Handling */
int vm_start(vm_t *vm);
void vm_stop(vm_t *vm);
-int vm_reset(vm_t *vm, const char *dvdroot);
+int vm_reset(vm_t *vm, const char *dvdroot, void *stream,
+ dvdnav_stream_cb *stream_cb);
/* copying and merging - useful for try-running an operation */
vm_t *vm_new_copy(vm_t *vm);
--
2.1.0
More information about the libdvdnav-devel
mailing list