summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/input/libdvdnav/read_cache.c261
-rw-r--r--src/input/libdvdnav/searching.c26
-rw-r--r--src/input/libdvdnav/vm.c9
3 files changed, 180 insertions, 116 deletions
diff --git a/src/input/libdvdnav/read_cache.c b/src/input/libdvdnav/read_cache.c
index 5a0177128..2029881c7 100644
--- a/src/input/libdvdnav/read_cache.c
+++ b/src/input/libdvdnav/read_cache.c
@@ -1,23 +1,23 @@
-/*
+/*
* Copyright (C) 2000 Rich Wareham <richwareham@users.sourceforge.net>
- *
+ *
* This file is part of libdvdnav, a DVD navigation library.
- *
+ *
* libdvdnav is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* libdvdnav is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* 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.4 2002/10/24 15:04:41 jkeil Exp $
+ * $Id: read_cache.c,v 1.5 2002/11/18 12:41:16 mroi Exp $
*
*/
@@ -31,9 +31,9 @@
#include <sys/time.h>
#include <time.h>
-/*
+
#define DVDNAV_PROFILE
-*/
+
/* Read-ahead cache structure. */
#if _MULTITHREAD_
@@ -48,10 +48,10 @@
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' */
@@ -60,7 +60,7 @@ struct read_cache_s {
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;
};
@@ -72,11 +72,15 @@ struct read_cache_s {
/* all cache chunks must be memory aligned to allow use of raw devices */
#define ALIGNMENT 2048
+#define READ_AHEAD_SIZE_MIN 4
+#define READ_AHEAD_SIZE_MAX 512
+
typedef struct read_cache_chunk_s {
uint8_t *cache_buffer;
uint8_t *cache_buffer_base; /* used in malloc and free for alignment */
int32_t cache_start_sector; /* -1 means cache invalid */
- size_t cache_block_count;
+ int32_t cache_read_count; /* this many sectors are already read */
+ size_t cache_block_count; /* this many sectors will go in this chunk */
size_t cache_malloc_size;
int cache_valid;
int usage_count; /* counts how many buffers where issued from this chunk */
@@ -86,6 +90,9 @@ struct read_cache_s {
read_cache_chunk_t chunk[READ_CACHE_CHUNKS];
int current;
int freeing; /* is set to one when we are about to dispose the cache */
+ int read_ahead_size;
+ int read_ahead_incr;
+ int last_sector;
pthread_mutex_t lock;
/* Bit of strange cross-linking going on here :) -- Gotta love C :) */
@@ -93,17 +100,19 @@ struct read_cache_s {
};
#endif
+/*
#define READ_CACHE_TRACE 0
+*/
#ifdef __GNUC__
# if READ_CACHE_TRACE
-# define dprintf(fmt, args...) fprintf(MSG_OUT, "libdvdnav: %s: "fmt, __func__ , ## args);
+# define dprintf(fmt, args...) fprintf(MSG_OUT, "libdvdnav: %s: "fmt, __func__ , ## arg
# else
# define dprintf(fmt, args...) /* Nowt */
# endif
#else
# if READ_CACHE_TRACE
-# define dprintf(fmt, ...) fprintf(MSG_OUT, "libdvdnav: %s: "fmt, __func__ , __VA_ARGS__);
+# define dprintf(fmt, ...) fprintf(MSG_OUT, "libdvdnav: %s: "fmt, __func__ , __VA_ARGS_
# else
# define dprintf(fmt, ...) /* Nowt */
# endif
@@ -120,9 +129,9 @@ void * read_cache_read_thread (void * this_gen) {
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) {
@@ -131,11 +140,11 @@ void * read_cache_read_thread (void * this_gen) {
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) {
@@ -147,7 +156,7 @@ void * read_cache_read_thread (void * this_gen) {
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) {
@@ -168,12 +177,12 @@ void * read_cache_read_thread (void * this_gen) {
}
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);
@@ -181,7 +190,7 @@ void * read_cache_read_thread (void * this_gen) {
return NULL;
}
-
+
read_cache_t *dvdnav_read_cache_new(dvdnav_t* dvd_self) {
read_cache_t *me;
@@ -189,7 +198,7 @@ read_cache_t *dvdnav_read_cache_new(dvdnav_t* dvd_self) {
if(me) {
int err;
-
+
me->dvd_self = dvd_self;
me->buffer = (uint8_t*)malloc(CACHE_BUFFER_SIZE * DVD_VIDEO_LB_LEN);
me->start = 0;
@@ -205,15 +214,15 @@ read_cache_t *dvdnav_read_cache_new(dvdnav_t* dvd_self) {
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;
@@ -223,12 +232,12 @@ void dvdnav_read_cache_free(read_cache_t* self) {
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);
}
@@ -237,7 +246,7 @@ void dvdnav_read_cache_free(read_cache_t* self) {
void dvdnav_read_cache_clear(read_cache_t *self) {
if(!self)
return;
-
+
pthread_mutex_lock(&self->cache_lock);
self->size = -1;
self->start = 0;
@@ -250,15 +259,15 @@ void dvdnav_read_cache_clear(read_cache_t *self) {
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",
+ 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");
@@ -271,24 +280,24 @@ void dvdnav_pre_cache_blocks(read_cache_t *self, int sector, size_t block_count)
self->pos = sector;
self->read_point = 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, 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) &&
+ 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)
@@ -298,7 +307,7 @@ int dvdnav_read_cache_block( read_cache_t *self, int sector, size_t block_count,
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),
+ 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);
@@ -308,19 +317,19 @@ int dvdnav_read_cache_block( read_cache_t *self, int sector, size_t block_count,
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),
+ 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,
+ 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;
+ return (int)block_count;
}
} else {
/* Miss */
- fprintf(MSG_OUT, "libdvdnav: DVD read cache miss! (not bad but a performance hit) sector=%d\n", sector);
+ 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) {
@@ -334,7 +343,7 @@ int dvdnav_read_cache_block( read_cache_t *self, int sector, size_t block_count,
usleep(300);
return result;
}
-
+
/* Should never get here */
return 0;
}
@@ -355,6 +364,9 @@ read_cache_t *dvdnav_read_cache_new(dvdnav_t* dvd_self) {
self->current = 0;
self->freeing = 0;
self->dvd_self = dvd_self;
+ self->last_sector = 0;
+ self->read_ahead_size = READ_AHEAD_SIZE_MIN;
+ self->read_ahead_incr = 0;
pthread_mutex_init(&self->lock, NULL);
dvdnav_read_cache_clear(self);
for (i = 0; i < READ_CACHE_CHUNKS; i++) {
@@ -362,14 +374,14 @@ read_cache_t *dvdnav_read_cache_new(dvdnav_t* dvd_self) {
self->chunk[i].usage_count = 0;
}
}
-
+
return self;
}
void dvdnav_read_cache_free(read_cache_t* self) {
dvdnav_t *tmp;
int i;
-
+
pthread_mutex_lock(&self->lock);
self->freeing = 1;
for (i = 0; i < READ_CACHE_CHUNKS; i++)
@@ -378,7 +390,7 @@ void dvdnav_read_cache_free(read_cache_t* self) {
self->chunk[i].cache_buffer = NULL;
}
pthread_mutex_unlock(&self->lock);
-
+
for (i = 0; i < READ_CACHE_CHUNKS; i++)
if (self->chunk[i].cache_buffer) return;
@@ -395,35 +407,20 @@ void dvdnav_read_cache_clear(read_cache_t *self) {
if(!self)
return;
-
+
pthread_mutex_lock(&self->lock);
for (i = 0; i < READ_CACHE_CHUNKS; i++)
self->chunk[i].cache_valid = 0;
pthread_mutex_unlock(&self->lock);
}
-#ifdef DVDNAV_PROFILE
-//#ifdef ARCH_X86
-__inline__ unsigned long long int dvdnav_rdtsc()
-{
- unsigned long long int x;
- __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
- return x;
-}
-//#endif
-#endif
-
/* 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) {
- int i, use, result;
-#ifdef DVDNAV_PROFILE
- struct timeval tv1, tv2, tv3;
- unsigned long long p1, p2, p3;
-#endif
-
+ int i, use;
+
if(!self)
return;
-
+
if(!self->dvd_self->use_read_ahead)
return;
@@ -436,7 +433,7 @@ void dvdnav_pre_cache_blocks(read_cache_t *self, int sector, size_t block_count)
self->chunk[i].cache_malloc_size >= block_count &&
(use == -1 || self->chunk[use].cache_malloc_size > self->chunk[i].cache_malloc_size))
use = i;
-
+
if (use == -1) {
/* we haven't found a cache chunk, so we try to reallocate an existing one */
for (i = 0; i < READ_CACHE_CHUNKS; i++)
@@ -461,99 +458,153 @@ void dvdnav_pre_cache_blocks(read_cache_t *self, int sector, size_t block_count)
/* We start with a sensible figure for the first malloc of 500 blocks.
* Some DVDs I have seen venture to 450 blocks.
* This is so that fewer realloc's happen if at all.
- */
+ */
self->chunk[i].cache_buffer_base =
malloc((block_count > 500 ? block_count : 500) * DVD_VIDEO_LB_LEN + ALIGNMENT);
self->chunk[i].cache_buffer =
(uint8_t *)(((int)self->chunk[i].cache_buffer_base & ~(ALIGNMENT - 1)) + ALIGNMENT);
self->chunk[i].cache_malloc_size = block_count > 500 ? block_count : 500;
dprintf("pre_cache DVD read malloc %d blocks\n",
- (block_count > 500 ? block_count : 500 ));
+ (block_count > 500 ? block_count : 500 ));
}
}
}
-
+
if (use >= 0) {
self->chunk[use].cache_start_sector = sector;
self->chunk[use].cache_block_count = block_count;
- self->current = use;
-#ifdef DVDNAV_PROFILE
- gettimeofday(&tv1, NULL);
- p1 = dvdnav_rdtsc();
-#endif
- result = DVDReadBlocks (self->dvd_self->file, sector, block_count, self->chunk[use].cache_buffer);
-#ifdef DVDNAV_PROFILE
- p2 = dvdnav_rdtsc();
- gettimeofday(&tv2, NULL);
- timersub(&tv2, &tv1, &tv3);
- dprintf("pre_cache DVD read %ld us, profile = %lld, block_count = %d\n",
- tv3.tv_usec, p2-p1, block_count);
-#endif
+ self->chunk[use].cache_read_count = 0;
self->chunk[use].cache_valid = 1;
- } else
+ self->current = use;
+ } else {
dprintf("pre_caching was impossible, no cache chunk available\n");
-
+ }
pthread_mutex_unlock(&self->lock);
}
int dvdnav_read_cache_block(read_cache_t *self, int sector, size_t block_count, uint8_t **buf) {
int i, use;
-
+ int start;
+ int size;
+ int incr;
+ uint8_t *read_ahead_buf;
+ int32_t res;
+
if(!self)
return 0;
-
- pthread_mutex_lock(&self->lock);
-
+
use = -1;
+
if(self->dvd_self->use_read_ahead) {
/* first check, if sector is in current chunk */
read_cache_chunk_t cur = self->chunk[self->current];
if (cur.cache_valid && sector >= cur.cache_start_sector &&
+ sector <= (cur.cache_start_sector + cur.cache_read_count) &&
sector + block_count <= cur.cache_start_sector + cur.cache_block_count)
use = self->current;
else
for (i = 0; i < READ_CACHE_CHUNKS; i++)
- if (self->chunk[i].cache_valid && sector >= self->chunk[i].cache_start_sector &&
- sector + block_count <= self->chunk[i].cache_start_sector + self->chunk[i].cache_block_count)
- use = i;
+ if (self->chunk[i].cache_valid &&
+ sector >= self->chunk[i].cache_start_sector &&
+ sector <= (self->chunk[i].cache_start_sector + self->chunk[i].cache_read_count) &&
+ sector + block_count <= self->chunk[i].cache_start_sector + self->chunk[i].cache_block_count)
+ use = i;
}
-
+
if (use >= 0) {
- self->chunk[use].usage_count++;
- *buf = &self->chunk[use].cache_buffer[(sector - self->chunk[use].cache_start_sector) *
- DVD_VIDEO_LB_LEN * block_count];
+ read_cache_chunk_t *chunk;
+
+ /* Increment read-ahead size if sector follows the last sector */
+ if (sector == (self->last_sector + 1)) {
+ self->read_ahead_incr++;
+ } else {
+ self->read_ahead_size = READ_AHEAD_SIZE_MIN;
+ self->read_ahead_incr = 0;
+ }
+ self->last_sector = sector;
+
+ /* The following resources need to be protected by a mutex :
+ * self->chunk[*].cache_buffer
+ * self->chunk[*].cache_malloc_size
+ * self->chunk[*].usage_count
+ */
+ pthread_mutex_lock(&self->lock);
+ chunk = &self->chunk[use];
+ read_ahead_buf = chunk->cache_buffer + chunk->cache_read_count * DVD_VIDEO_LB_LEN;
+ *buf = chunk->cache_buffer + (sector - chunk->cache_start_sector) * DVD_VIDEO_LB_LEN;
+ chunk->usage_count++;
pthread_mutex_unlock(&self->lock);
- return DVD_VIDEO_LB_LEN * block_count;
+
+ /* 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);
+
+ /* 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;
+
+ /* 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);
+
+ chunk->cache_read_count += DVDReadBlocks(self->dvd_self->file,
+ start,
+ size,
+ read_ahead_buf);
+ }
+
+ res = DVD_VIDEO_LB_LEN * block_count;
+
} else {
+
if (self->dvd_self->use_read_ahead)
dprintf("cache miss on sector %d\n", sector);
- pthread_mutex_unlock(&self->lock);
- return DVDReadBlocks(self->dvd_self->file, sector, block_count, *buf);
+
+ res = DVDReadBlocks(self->dvd_self->file,
+ sector,
+ block_count,
+ *buf) * DVD_VIDEO_LB_LEN;
}
+
+ return res;
+
}
dvdnav_status_t dvdnav_free_cache_block(dvdnav_t *self, unsigned char *buf) {
read_cache_t *cache;
int i;
-
+
if (!self)
return DVDNAV_STATUS_ERR;
-
+
cache = self->cache;
if (!cache)
return DVDNAV_STATUS_ERR;
-
+
pthread_mutex_lock(&cache->lock);
- for (i = 0; i < READ_CACHE_CHUNKS; i++)
+ for (i = 0; i < READ_CACHE_CHUNKS; i++) {
if (cache->chunk[i].cache_buffer && buf >= cache->chunk[i].cache_buffer &&
- buf < cache->chunk[i].cache_buffer + cache->chunk[i].cache_malloc_size * DVD_VIDEO_LB_LEN)
+ buf < cache->chunk[i].cache_buffer + cache->chunk[i].cache_malloc_size * DVD_VIDEO_LB_LEN) {
cache->chunk[i].usage_count--;
+ }
+ }
pthread_mutex_unlock(&cache->lock);
if (cache->freeing)
/* when we want to dispose the cache, try freeing it now */
dvdnav_read_cache_free(cache);
-
+
return DVDNAV_STATUS_OK;
}
diff --git a/src/input/libdvdnav/searching.c b/src/input/libdvdnav/searching.c
index 503b9925d..6a9e73029 100644
--- a/src/input/libdvdnav/searching.c
+++ b/src/input/libdvdnav/searching.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: searching.c,v 1.5 2002/09/04 11:07:47 mroi Exp $
+ * $Id: searching.c,v 1.6 2002/11/18 12:41:16 mroi Exp $
*
*/
@@ -112,16 +112,13 @@ dvdnav_status_t dvdnav_sector_search(dvdnav_t *this,
dvd_state_t *state;
dvdnav_status_t result;
- if((!this) || (!this->vm) )
+ if((!this) || (!this->vm) || (!this->started))
return -1;
state = &(this->vm->state);
if((!state) || (!state->pgc) )
return -1;
- if(offset == 0)
- return -1;
-
if(this->position_current.still != 0)
/* Cannot do seeking in a still frame. */
return -1;
@@ -158,6 +155,7 @@ dvdnav_status_t dvdnav_sector_search(dvdnav_t *this,
return -1;
}
target = length - offset;
+ break;
default:
/* Error occured */
pthread_mutex_unlock(&this->vm_lock);
@@ -179,6 +177,7 @@ dvdnav_status_t dvdnav_sector_search(dvdnav_t *this,
if((cell->first_sector <= target) && (cell->last_sector >= target)) {
state->cellN = cell_nr;
state->blockN = 0;
+ state->cell_restart++;
found = 1;
fnd_cell_nr = cell_nr;
fnd_cell = cell;
@@ -238,15 +237,19 @@ dvdnav_status_t dvdnav_prev_pg_search(dvdnav_t *this) {
if((!state) || (!state->pgc) )
return S_ERR;
+ pthread_mutex_lock(&this->vm_lock);
/* Make sure this is not the first chapter */
if(state->pgN <= 1 ) {
fprintf(MSG_OUT, "libdvdnav: at first chapter. prev chapter failed.\n");
+ pthread_mutex_unlock(&this->vm_lock);
return S_ERR;
}
fprintf(MSG_OUT, "libdvdnav: previous chapter\n");
vm_jump_prog(this->vm, state->pgN - 1);
+ this->position_current.still = 0;
this->vm->hop_channel++;
fprintf(MSG_OUT, "libdvdnav: previous chapter done\n");
+ pthread_mutex_unlock(&this->vm_lock);
return S_OK;
}
@@ -271,15 +274,20 @@ dvdnav_status_t dvdnav_next_pg_search(dvdnav_t *this) {
if((!state) || (!state->pgc) )
return S_ERR;
+ pthread_mutex_lock(&this->vm_lock);
/* Make sure this is not the last chapter */
if(state->pgN >= state->pgc->nr_of_programs) {
- fprintf(MSG_OUT, "libdvdnav: at last chapter. next chapter failed.\n");
- return S_ERR;
+ fprintf(MSG_OUT, "libdvdnav: at last chapter. jumping to end of last cell.\n");
+ this->vm->state.cellN = this->vm->state.pgc->nr_of_cells;
+ vm_get_next_cell(this->vm);
+ } else {
+ fprintf(MSG_OUT, "libdvdnav: next chapter\n");
+ vm_jump_prog(this->vm, state->pgN + 1);
}
- fprintf(MSG_OUT, "libdvdnav: next chapter\n");
- vm_jump_prog(this->vm, state->pgN + 1);
+ this->position_current.still = 0;
this->vm->hop_channel++;
fprintf(MSG_OUT, "libdvdnav: next chapter done\n");
+ pthread_mutex_unlock(&this->vm_lock);
return S_OK;
}
diff --git a/src/input/libdvdnav/vm.c b/src/input/libdvdnav/vm.c
index c3fa9a282..5d668c6fa 100644
--- a/src/input/libdvdnav/vm.c
+++ b/src/input/libdvdnav/vm.c
@@ -19,7 +19,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: vm.c,v 1.8 2002/10/22 17:18:24 jkeil Exp $
+ * $Id: vm.c,v 1.9 2002/11/18 12:41:16 mroi Exp $
*
*/
@@ -541,7 +541,7 @@ int vm_get_current_title_part(vm_t *vm, int *title_result, int *part_result)
part++;
if (found == 1) {
fprintf(MSG_OUT, "libdvdnav: ************ this chapter FOUND!\n");
- printf("VTS_PTT_SRPT - Title %3i part %3i: PGC: %3i PG: %3i\n",
+ fprintf(MSG_OUT, "libdvdnav: VTS_PTT_SRPT - Title %3i part %3i: PGC: %3i PG: %3i\n",
title, part,
vts_ptt_srpt->title[title-1].ptt[part-1].pgcn ,
vts_ptt_srpt->title[title-1].ptt[part-1].pgn );
@@ -1988,6 +1988,11 @@ static pgcit_t* get_PGCIT(vm_t *vm) {
/*
* $Log: vm.c,v $
+ * Revision 1.9 2002/11/18 12:41:16 mroi
+ * sync to libdvdnav cvs
+ * * fix read cache and improve it for slower drives
+ * * improve chapter skipping
+ *
* Revision 1.8 2002/10/22 17:18:24 jkeil
* Recursive comments, picked up via CVS $Log keyword. Trying to fix...
*