summaryrefslogtreecommitdiff
path: root/src/input/libdvdnav/read_cache.c
diff options
context:
space:
mode:
authorMichael Roitzsch <mroi@users.sourceforge.net>2004-03-16 11:43:38 +0000
committerMichael Roitzsch <mroi@users.sourceforge.net>2004-03-16 11:43:38 +0000
commit50a26e7dabcb36c002f8527c8364c67439adbb11 (patch)
treed79ee798b6681d0fc8e8a3c93c845d34cfdb92e4 /src/input/libdvdnav/read_cache.c
parentb323267b7a8f5592c66158376a1ce25e2bdfefd5 (diff)
downloadxine-lib-50a26e7dabcb36c002f8527c8364c67439adbb11.tar.gz
xine-lib-50a26e7dabcb36c002f8527c8364c67439adbb11.tar.bz2
sync to latest libdvdnav
* fixes a menu problem (German RC2 of "Anatomie", chapter menu) * addresses some compilation problems on Windows (Could someone try cygwin, mingw builds, please? It should work with the standalone libdvdnav, but who knows if the integration breaks anything...) * turns some abort()s into assert(0)s, where we really can try to continue CVS patchset: 6269 CVS date: 2004/03/16 11:43:38
Diffstat (limited to 'src/input/libdvdnav/read_cache.c')
-rw-r--r--src/input/libdvdnav/read_cache.c328
1 files changed, 30 insertions, 298 deletions
diff --git a/src/input/libdvdnav/read_cache.c b/src/input/libdvdnav/read_cache.c
index c17e38634..5d0515260 100644
--- a/src/input/libdvdnav/read_cache.c
+++ b/src/input/libdvdnav/read_cache.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2000 Rich Wareham <richwareham@users.sourceforge.net>
+ * 2001-2004 the dvdnav project
*
* This file is part of libdvdnav, a DVD navigation library.
*
@@ -17,56 +18,25 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: read_cache.c,v 1.11 2004/02/19 02:50:25 rockyb Exp $
+ * $Id: read_cache.c,v 1.12 2004/03/16 11:43:38 mroi Exp $
*
*/
+/*
+ * There was a multithreaded read ahead cache in here for some time, but
+ * it had only been used for a short time. If you want to have a look at it,
+ * search the CVS attic.
+ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "dvdnav.h"
+#include "dvdnav_internal.h"
#include "read_cache.h"
-#include <pthread.h>
#include <sys/time.h>
#include <time.h>
-
-#define DVDNAV_PROFILE
-
-
-/* Read-ahead cache structure. */
-#if _MULTITHREAD_
-
-/* 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 2048 /* Cache this number of blocks at a time */
-
-struct read_cache_s {
- pthread_mutex_t cache_lock;
- pthread_t read_thread;
-
- /* Buffer */
- uint8_t *buffer;
-
- /* Size of buffer */
- int32_t size;
- /* block offset from sector start of buffer 'head' */
- uint32_t pos;
- /* block offset from sector start of read point */
- uint32_t read_point;
- /* block offset from buffer start to ring-boundary */
- uint32_t start;
-
- /* Bit of strange cross-linking going on here :) -- Gotta love C :) */
- dvdnav_t *dvd_self;
-};
-
-#else
-
#define READ_CACHE_CHUNKS 10
/* all cache chunks must be memory aligned to allow use of raw devices */
@@ -98,7 +68,6 @@ struct read_cache_s {
/* Bit of strange cross-linking going on here :) -- Gotta love C :) */
dvdnav_t *dvd_self;
};
-#endif
/*
#define READ_CACHE_TRACE 0
@@ -122,241 +91,6 @@ struct read_cache_s {
# endif
#endif
-#if _MULTITHREAD_
-
-void * read_cache_read_thread (void * this_gen) {
- int cont = 1;
- int32_t diff, start;
- uint32_t pos, size, startp, endp;
- 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) {
- diff = self->read_point - self->pos;
- if(diff >= self->size/2) {
- dprintf("(II) Read thread -- ");
-
- startp = (self->start) % CACHE_BUFFER_SIZE;
- endp = abs((self->start + diff - 1) % CACHE_BUFFER_SIZE);
- dprintf("startp = %i, endp = %i -- ",startp, endp);
-
- pos = self->pos + diff;
- size = self->size - diff;
- start = (self->start + diff) % CACHE_BUFFER_SIZE;
-
- /* Fill remainder of buffer */
-
- if(startp > endp) {
- s = pos + size; c = CACHE_BUFFER_SIZE - startp;
- at = self->buffer + (startp * DVD_VIDEO_LB_LEN);
- if(c > 0) {
- dprintf("(1) Reading from %i to %i to %i ", s, s+c-1, startp);
- pthread_mutex_unlock(&self->cache_lock);
- DVDReadBlocks(self->dvd_self->file, s,c, at);
- pthread_mutex_lock(&self->cache_lock);
- }
-
- s = pos + size + c; c = CACHE_BUFFER_SIZE - size - c;
- at = self->buffer;
- if(c > 0) {
- dprintf("(2) Reading from %i to %i to %i ", s, s+c-1, 0);
- pthread_mutex_unlock(&self->cache_lock);
- DVDReadBlocks(self->dvd_self->file, s,c, at);
- pthread_mutex_lock(&self->cache_lock);
- }
- } else {
- s = pos + size; c = CACHE_BUFFER_SIZE - size;
- at = self->buffer + (startp * DVD_VIDEO_LB_LEN);
- if(c > 0) {
- dprintf("(3) Reading from %i to %i to %i ", s, s+c-1, startp);
- pthread_mutex_unlock(&self->cache_lock);
- DVDReadBlocks(self->dvd_self->file, s,c, at);
- pthread_mutex_lock(&self->cache_lock);
- }
- }
-
- dprintf("\n");
-
- self->pos = pos;
- self->start = start; self->size = CACHE_BUFFER_SIZE;
- }
- }
-
- 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->read_point = 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) {
- dprintf("read_cache: can't create new thread (%s)\n",strerror(err));
- }
- }
-
- return me;
-}
-
-void dvdnav_read_cache_free(read_cache_t* self) {
- dvdnav_t *tmp;
-
- 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);
-
- tmp = self->dvd_self;
- free(self);
-
- /* We free the main structure, too, because we have no buffers out there. */
- free(tmp);
-}
-
-/* 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 = -1;
- self->start = 0;
- self->pos = 0;
- self->read_point = 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);
- dprintf("Requested pre-cache (%i -> +%i) : current state pos=%i, size=%i.\n",
- sector, block_count, self->pos, self->size);
-
- /* Are the contents of the buffer in any way relevant? */
- if((self->size > 0) && (sector >= self->pos) && (sector <= self->pos+self->size)) {
- dprintf("Contents relevant ... adjusting\n");
- self->read_point = sector;
- } else {
- /* Flush the cache as its not much use */
- dprintf("Contents irrelevent... flushing\n");
- self->size = 0;
- self->start = 0;
- self->pos = sector;
- self->read_point = sector;
- }
-
- pthread_mutex_unlock(&self->cache_lock);
-}
-
-/* This function will do the cache read */
-int dvdnav_read_cache_block( read_cache_t *self, int sector, size_t block_count, uint8_t **buf) {
- int result, diff;
-
- if(!self)
- return 0;
-
- pthread_mutex_lock(&self->cache_lock);
- dprintf("Read from %i -> +%i (buffer pos=%i, read_point=%i, size=%i)... ", sector, block_count,
- self->pos, self->read_point, self->size);
- if((self->size > 0) && (sector >= self->read_point) &&
- (sector + block_count <= self->pos + self->size)) {
- /* Hit */
-
- /* Drop any skipped blocks */
- diff = sector - self->read_point;
- if(diff > 0)
- self->read_point += diff;
-
- diff = self->read_point - self->pos;
-
- if(((self->start + diff) % CACHE_BUFFER_SIZE) + block_count <= CACHE_BUFFER_SIZE) {
- dprintf("************** Single read\n");
- memcpy(*buf, self->buffer + (((self->start + diff) % CACHE_BUFFER_SIZE) * DVD_VIDEO_LB_LEN),
- block_count * DVD_VIDEO_LB_LEN);
- self->read_point += block_count;
- pthread_mutex_unlock(&self->cache_lock);
-
- return (int)block_count;
- } else {
- int32_t boundary = CACHE_BUFFER_SIZE - self->start;
-
- dprintf("************** Multiple read\n");
- memcpy(*buf, self->buffer + (((self->start + diff) % CACHE_BUFFER_SIZE) * 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->read_point += block_count;
- pthread_mutex_unlock(&self->cache_lock);
-
- return (int)block_count;
- }
- } else {
- /* Miss */
-
- fprintf(MSG_OUT, "libdvdnav: DVD read cache miss! (not bad but a performance hit) sector=%d\n", sector);
- result = DVDReadBlocks( self->dvd_self->file, sector, block_count, *buf);
- self->read_point = sector+block_count;
- if(self->read_point > self->pos + self->size) {
- /* Flush the cache as its not much use */
- dprintf("Contents irrelevent... flushing\n");
- self->size = 0;
- self->start = 0;
- self->pos = sector+block_count;
- }
- pthread_mutex_unlock(&self->cache_lock);
- usleep(300);
- return result;
- }
-
- /* Should never get here */
- return 0;
-}
-
-dvdnav_status_t dvdnav_free_cache_block(dvdnav_t *self, unsigned char *buf) {
- return DVDNAV_STATUS_OK;
-}
-
-#else
read_cache_t *dvdnav_read_cache_new(dvdnav_t* dvd_self) {
read_cache_t *self;
@@ -520,7 +254,8 @@ int dvdnav_read_cache_block(read_cache_t *self, int sector, size_t block_count,
/* Increment read-ahead size if sector follows the last sector */
if (sector == (self->last_sector + 1)) {
- self->read_ahead_incr++;
+ if (self->read_ahead_incr < READ_AHEAD_SIZE_MAX)
+ self->read_ahead_incr++;
} else {
self->read_ahead_size = READ_AHEAD_SIZE_MIN;
self->read_ahead_incr = 0;
@@ -539,34 +274,33 @@ int dvdnav_read_cache_block(read_cache_t *self, int sector, size_t block_count,
chunk->usage_count++;
pthread_mutex_unlock(&self->lock);
- /* Read blocks if needed */
- if (sector >= (chunk->cache_start_sector + chunk->cache_read_count)) {
+ dprintf("libdvdnav: sector=%d, start_sector=%d, last_sector=%d\n", sector, chunk->cache_start_sector, chunk->cache_start_sector + chunk->cache_block_count);
- dprintf("libdvdnav: sector=%d, start_sector=%d, last_sector=%d\n", sector, chunk->cache_start_sector, chunk->cache_start_sector + chunk->cache_block_count);
-
- /* read_ahead_size */
- incr = self->read_ahead_incr >> 1;
- if ((self->read_ahead_size + incr) > READ_AHEAD_SIZE_MAX) {
- self->read_ahead_size = READ_AHEAD_SIZE_MAX;
- } else {
- self->read_ahead_size = self->read_ahead_size + incr;
- }
- self->read_ahead_incr = 0;
+ /* read_ahead_size */
+ incr = self->read_ahead_incr >> 1;
+ if ((self->read_ahead_size + incr) > READ_AHEAD_SIZE_MAX) {
+ self->read_ahead_size = READ_AHEAD_SIZE_MAX;
+ } else {
+ self->read_ahead_size += incr;
+ }
- /* real read size */
- start = chunk->cache_start_sector + chunk->cache_read_count;
- if (chunk->cache_read_count + self->read_ahead_size > chunk->cache_block_count) {
- size = chunk->cache_block_count - chunk->cache_read_count;
- } else {
- size = self->read_ahead_size;
- }
- dprintf("libdvdnav: read_ahead_size=%d, size=%d\n", self->read_ahead_size, size);
+ /* real read size */
+ start = chunk->cache_start_sector + chunk->cache_read_count;
+ if (chunk->cache_read_count + self->read_ahead_size > chunk->cache_block_count) {
+ size = chunk->cache_block_count - chunk->cache_read_count;
+ } else {
+ size = self->read_ahead_size;
+ /* ensure that the sector we want will be read */
+ if (sector >= chunk->cache_start_sector + chunk->cache_read_count + size)
+ size = sector - chunk->cache_start_sector - chunk->cache_read_count;
+ }
+ dprintf("libdvdnav: read_ahead_size=%d, size=%d\n", self->read_ahead_size, size);
+ if (size)
chunk->cache_read_count += DVDReadBlocks(self->dvd_self->file,
start,
size,
read_ahead_buf);
- }
res = DVD_VIDEO_LB_LEN * block_count;
@@ -611,5 +345,3 @@ dvdnav_status_t dvdnav_free_cache_block(dvdnav_t *self, unsigned char *buf) {
return DVDNAV_STATUS_OK;
}
-
-#endif