changeset 40:a049c3753f32 src

Added some packaging patches from Philipp Matthias Hahn <pmhahn@titan.lahn.de> and an initial (non-working) multi-threaded read-ahead cache.
author richwareham
date Sat, 01 Jun 2002 12:00:40 +0000
parents 2433a5a8069e
children 50e0855a2017
files Makefile.am decoder.h read_cache.c vmcmd.h
diffstat 4 files changed, 251 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.am	Thu May 30 23:15:14 2002 +0000
+++ b/Makefile.am	Sat Jun 01 12:00:40 2002 +0000
@@ -5,7 +5,7 @@
 libdvdnav_la_SOURCES = decoder.c dvdnav.c vm.c vmcmd.c \
 		       read_cache.c navigation.c highlight.c \
 		       searching.c settings.c
-libdvdnav_la_LDFLAGS = $(DVDREAD_LIBS) -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
+libdvdnav_la_LDFLAGS = $(DVDREAD_LIBS) $(THREAD_LIBS) -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
 	-release $(LT_RELEASE) 
 
 include_HEADERS = decoder.h dvdnav.h dvdnav_events.h \
--- a/decoder.h	Thu May 30 23:15:14 2002 +0000
+++ b/decoder.h	Sat Jun 01 12:00:40 2002 +0000
@@ -25,7 +25,6 @@
 #ifndef DECODER_H_INCLUDED
 #define DECODER_H_INCLUDED
 
-#include "config.h"
 #include <inttypes.h>
 #include <sys/time.h>
 
--- a/read_cache.c	Thu May 30 23:15:14 2002 +0000
+++ b/read_cache.c	Sat Jun 01 12:00:40 2002 +0000
@@ -27,16 +27,31 @@
 
 #include "dvdnav.h"
 #include "read_cache.h"
+#include <pthread.h>
 
 /* Read-ahead cache structure. */
 #if _MULTITHREAD_
-struct read_cache_s {
+
+/* For the multithreaded cache, the cache is a ring buffer + writing
+ * thread that continuously reads data into the buffer until it is
+ * full or the 'upper-bound' has been reached.
+ */
+
+#define CACHE_BUFFER_SIZE 1024 /* Cache this number of blocks at a time */
 
-  /* Bounds on read ahead buffer */
-  off_t      low_bound;
-  off_t      high_bound;
-
-  /* Where we are currently 'reading' from */
+struct read_cache_s {
+  pthread_mutex_t cache_lock;
+  pthread_t read_thread;
+   
+  /* Buffer */
+  uint8_t   *buffer;
+  
+  /* Where we are currently 'reading' from (blocks) */
+  int32_t    pos;
+  /* Location of 'start-point' in buffer */
+  int32_t    start;
+  /* How much is in buffer? */
+  int        size;
   
   /* Bit of strange cross-linking going on here :) -- Gotta love C :) */
   dvdnav_t    *dvd_self;
@@ -56,6 +71,234 @@
 };
 #endif
 
+#if _MULTITHREAD_
+
+void * read_cache_read_thread (void * this_gen) {
+  int cont = 1;
+  int32_t diff, start;
+  uint32_t s,c;
+  uint8_t *at;
+  read_cache_t *self = (read_cache_t*)this_gen;
+
+  while(cont) {
+   
+    pthread_mutex_lock(&self->cache_lock);
+    if((self->size >= 0) && (self->size < CACHE_BUFFER_SIZE/3)) {
+      printf("Rad thread -- current state pos=%i, size=%i\n", self->pos, self->size);
+      /* Attempt to fill buffer */
+      diff = CACHE_BUFFER_SIZE - self->size;
+      if(diff > 0) {
+	start = (self->start + self->size) % CACHE_BUFFER_SIZE;
+
+	c = 0; s = self->pos + self->size;
+	if(start != 0) {
+	  s = self->pos + self->size; c = CACHE_BUFFER_SIZE - start;
+	  at = self->buffer + (start * DVD_VIDEO_LB_LEN);
+	  pthread_mutex_unlock(&self->cache_lock);
+	  DVDReadBlocks( self->dvd_self->file, s,c,at);
+	  pthread_mutex_lock(&self->cache_lock);
+	}
+	
+	s += c; c = diff - c;
+	at = self->buffer;
+	pthread_mutex_unlock(&self->cache_lock);
+	DVDReadBlocks( self->dvd_self->file, s,c,at);
+	pthread_mutex_lock(&self->cache_lock);
+
+	// end = (self->start + self->size + diff) % CACHE_BUFFER_SIZE;
+	/*if(end > start) {
+	  printf("Reading %i from sector %i\n",diff, self->pos+self->size);
+	  pthread_mutex_unlock(&self->cache_lock);
+	  DVDReadBlocks( self->dvd_self->file, self->pos + self->size, diff, 
+			 self->buffer + (start * DVD_VIDEO_LB_LEN));
+	  pthread_mutex_lock(&self->cache_lock);
+	} else {*/
+	/*
+	  if(start != CACHE_BUFFER_SIZE-1) {
+	    printf(" -- Reading %i from %i to %i ", CACHE_BUFFER_SIZE - start,
+		   self->pos + self->size, start);
+	    s = self->pos + self->size; c = CACHE_BUFFER_SIZE - start;
+	    at = self->buffer + (start * DVD_VIDEO_LB_LEN);
+	    pthread_mutex_unlock(&self->cache_lock);
+	    DVDReadBlocks( self->dvd_self->file, s,c,at);
+	    pthread_mutex_lock(&self->cache_lock);
+	  }
+	  if(end != 0) {
+	    printf(" -- Reading %i from %i to %i ", diff - CACHE_BUFFER_SIZE + start,
+		   self->pos + self->size + CACHE_BUFFER_SIZE - start,
+		   0);
+	    s = self->pos + self->size + CACHE_BUFFER_SIZE - start;
+	    c = diff - CACHE_BUFFER_SIZE + start; at = self->buffer;
+	    pthread_mutex_unlock(&self->cache_lock);
+	    DVDReadBlocks( self->dvd_self->file, s, c, at);
+	    pthread_mutex_lock(&self->cache_lock);
+	  }
+	  printf("::\n");
+	  */
+	// }
+
+	self->size += diff;
+      }
+    }
+   
+    pthread_mutex_unlock(&self->cache_lock);
+    cont = (self->buffer != NULL);
+    usleep(100);
+  }
+
+  return NULL;
+}
+					   
+read_cache_t *dvdnav_read_cache_new(dvdnav_t* dvd_self) {
+  read_cache_t *me;
+
+  me = (read_cache_t*)malloc(sizeof(struct read_cache_s));
+
+  if(me) {
+    int err;
+    
+    me->dvd_self = dvd_self;
+    me->buffer = (uint8_t*)malloc(CACHE_BUFFER_SIZE * DVD_VIDEO_LB_LEN);
+    me->start = 0;
+    me->pos = 0;
+    me->size = -1;
+
+    /* Initialise the mutex */
+    pthread_mutex_init(&me->cache_lock, NULL);
+
+    if ((err = pthread_create (&me->read_thread,
+			       NULL, read_cache_read_thread, me)) != 0) {
+      fprintf(stderr,"read_cache: can't create new thread (%s)\n",strerror(err));
+    }
+  }
+  
+  return me;
+}
+
+void dvdnav_read_cache_free(read_cache_t* self) {
+  pthread_mutex_lock(&self->cache_lock);
+		   
+  if(self->buffer) {
+    free(self->buffer);
+    self->buffer = NULL;
+    self->size = -2;
+  }
+
+  pthread_mutex_unlock(&self->cache_lock);
+
+  pthread_join(self->read_thread, NULL);
+  
+  pthread_mutex_destroy(&self->cache_lock);
+
+  free(self);
+}
+
+/* This function MUST be called whenever self->file changes. */
+void dvdnav_read_cache_clear(read_cache_t *self) {
+  if(!self)
+   return;
+  
+  pthread_mutex_lock(&self->cache_lock);
+  self->size = 0;
+  self->start = 0;
+  self->pos = 0;
+  pthread_mutex_unlock(&self->cache_lock);
+}
+
+/* This function is called just after reading the NAV packet. */
+void dvdnav_pre_cache_blocks(read_cache_t *self, int sector, size_t block_count) {
+  if(!self)
+   return;
+  
+  if(!self->dvd_self->use_read_ahead) {
+    return;
+  }
+ 
+  pthread_mutex_lock(&self->cache_lock);
+  printf("Requested pre-cache.\n");
+  
+  /* Are the contents of the buffer in any way relevant? */
+  if((sector < self->pos+self->size) && (sector >= self->pos)) {
+    int32_t diff = sector - self->pos;
+
+    printf("Contents relevant ... adjusting by %i\n", diff);
+    self->size -= diff;
+    self->start = (self->start + diff) % CACHE_BUFFER_SIZE;
+  } else {
+    /* Flush the cache as its not much use */
+    pthread_mutex_unlock(&self->cache_lock);
+    printf("Contents irrelevent... flushing\n");
+    dvdnav_read_cache_clear(self);
+    pthread_mutex_lock(&self->cache_lock);
+  }
+  
+  self->pos = sector;
+
+  pthread_mutex_unlock(&self->cache_lock);
+}
+
+/* This function will do the cache read once implemented */
+int dvdnav_read_cache_block( read_cache_t *self, int sector, size_t block_count, uint8_t *buf) {
+  int result;
+ 
+  if(!self)
+   return 0;
+
+  pthread_mutex_lock(&self->cache_lock);
+  if((self->size > 0) && (sector >= self->pos) && (sector + block_count <= self->pos + self->size)) {
+    /* Hit */
+
+    //printf("Read from %i -> +%i (buffer pos=%i, size=%i)... ", sector, block_count,
+	//   self->pos, self->size);
+    
+    /* Drop any skipped blocks */
+     {
+      int diff = sector - self->pos;
+
+      self->pos += diff;
+      self->size -= diff;
+      self->start = (self->start + diff) % CACHE_BUFFER_SIZE;
+     }
+
+    if(self->start + block_count <= CACHE_BUFFER_SIZE) {
+      // printf("Single read\n");
+      memcpy(buf, self->buffer + ((self->start) * DVD_VIDEO_LB_LEN), block_count * DVD_VIDEO_LB_LEN);
+      self->start = (self->start + block_count) % CACHE_BUFFER_SIZE;
+      self->pos += block_count;
+      self->size --;
+      pthread_mutex_unlock(&self->cache_lock);
+
+      return (int)block_count;
+    } else {
+      int32_t boundary = CACHE_BUFFER_SIZE - self->start - 1;
+
+      printf("************** Multiple read\n");
+      memcpy(buf, self->buffer + ((self->start) * DVD_VIDEO_LB_LEN), boundary  * DVD_VIDEO_LB_LEN);
+      memcpy(buf + (boundary  * DVD_VIDEO_LB_LEN), self->buffer, (block_count-boundary) * DVD_VIDEO_LB_LEN);
+      self->start = (self->start + block_count) % CACHE_BUFFER_SIZE;
+      self->pos += block_count;
+      self->size --;
+      pthread_mutex_unlock(&self->cache_lock);
+
+      return (int)block_count;      
+    }
+  } else {
+    /* Miss */
+
+    fprintf(stderr,"DVD read cache miss! sector=%d\n", sector); 
+    result = DVDReadBlocks( self->dvd_self->file, sector, block_count, buf);
+    self->pos = sector + block_count;
+    usleep(200);
+    pthread_mutex_unlock(&self->cache_lock);
+    return result;
+  }
+  
+  /* Should never get here */
+  return 0;
+}
+
+#else
+
 read_cache_t *dvdnav_read_cache_new(dvdnav_t* dvd_self) {
   read_cache_t *me;
 
@@ -147,3 +390,4 @@
 }
 
 
+#endif
--- a/vmcmd.h	Thu May 30 23:15:14 2002 +0000
+++ b/vmcmd.h	Sat Jun 01 12:00:40 2002 +0000
@@ -25,7 +25,6 @@
 #ifndef VMCMD_H_INCLUDED
 #define VMCMD_H_INCLUDED
 
-#include "config.h"
 #include <inttypes.h>
 #include <dvdread/ifo_types.h> /*  Only for vm_cmd_t  */
 #include "decoder.h"