# HG changeset patch # User richwareham # Date 1022932840 0 # Node ID a049c3753f32412ca57ee56694b4707e8ab44009 # Parent 2433a5a8069ee9c552740077fdc3474386532e59 Added some packaging patches from Philipp Matthias Hahn and an initial (non-working) multi-threaded read-ahead cache. diff -r 2433a5a8069e -r a049c3753f32 Makefile.am --- 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 \ diff -r 2433a5a8069e -r a049c3753f32 decoder.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 #include diff -r 2433a5a8069e -r a049c3753f32 read_cache.c --- 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 /* 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 diff -r 2433a5a8069e -r a049c3753f32 vmcmd.h --- 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 #include /* Only for vm_cmd_t */ #include "decoder.h"