[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