Bring in a whole bunch of bug fixes from microe's git repo on github.

ok sthen@
This commit is contained in:
brad 2012-09-26 00:04:09 +00:00
parent e4e676be98
commit c0760c8d2a
8 changed files with 828 additions and 5 deletions

View File

@ -1,18 +1,18 @@
# $OpenBSD: Makefile,v 1.18 2012/09/05 08:09:27 ajacoutot Exp $
# $OpenBSD: Makefile,v 1.19 2012/09/26 00:04:09 brad Exp $
SHARED_ONLY= Yes
COMMENT= DVD navigation library
DISTNAME= libdvdnav-4.2.0
REVISION= 1
REVISION= 2
EPOCH= 0
CATEGORIES= multimedia
MASTER_SITES= ${HOMEPAGE}releases/
EXTRACT_SUFX= .tar.bz2
SHARED_LIBS= dvdnav 6.1 \
dvdnavmini 6.1
SHARED_LIBS= dvdnav 6.2 \
dvdnavmini 6.2
HOMEPAGE= http://dvdnav.mplayerhq.hu/
@ -22,7 +22,7 @@ PERMIT_DISTFILES_FTP= Yes
PERMIT_PACKAGE_CDROM= Yes
PERMIT_PACKAGE_FTP= Yes
WANTLIB += dvdread pthread
WANTLIB= dvdread pthread
AUTOCONF_VERSION= 2.61
AUTOMAKE_VERSION= 1.10

View File

@ -0,0 +1,159 @@
$OpenBSD: patch-src_dvdnav_c,v 1.1 2012/09/26 00:04:09 brad Exp $
- Check that a VOB is open in case we need to open one
- Add a function to create a dpu of a dvdnav handle
- Prevent overflow by pre-casting to int64_t
- Remove unneeded address-of of CLUT
- Make sure we get nav packets for all cells in multi angle features
- Test still like a boolean value and not an integer value
- Always check whether a still is being handled
--- src/dvdnav.c.orig Wed Sep 5 14:23:55 2012
+++ src/dvdnav.c Wed Sep 5 14:24:07 2012
@@ -71,6 +71,67 @@ static dvdnav_status_t dvdnav_clear(dvdnav_t * this) {
return DVDNAV_STATUS_OK;
}
+dvdnav_status_t dvdnav_dup(dvdnav_t **dest, dvdnav_t *src) {
+ dvdnav_t *this;
+
+ (*dest) = NULL;
+ this = (dvdnav_t*)malloc(sizeof(dvdnav_t));
+ if(!this)
+ return DVDNAV_STATUS_ERR;
+
+ memcpy(this, src, sizeof(dvdnav_t));
+ this->file = NULL;
+
+ pthread_mutex_init(&this->vm_lock, NULL);
+
+ this->vm = vm_new_copy(src->vm);
+ if(!this->vm) {
+ printerr("Error initialising the DVD VM.");
+ pthread_mutex_destroy(&this->vm_lock);
+ free(this);
+ return DVDNAV_STATUS_ERR;
+ }
+
+ /* Start the read-ahead cache. */
+ this->cache = dvdnav_read_cache_new(this);
+
+ (*dest) = this;
+ return DVDNAV_STATUS_OK;
+}
+
+dvdnav_status_t dvdnav_free_dup(dvdnav_t *this) {
+
+#ifdef LOG_DEBUG
+ fprintf(MSG_OUT, "libdvdnav: free_dup:called\n");
+#endif
+
+ if (this->file) {
+ pthread_mutex_lock(&this->vm_lock);
+ DVDCloseFile(this->file);
+#ifdef LOG_DEBUG
+ fprintf(MSG_OUT, "libdvdnav: close:file closing\n");
+#endif
+ this->file = NULL;
+ pthread_mutex_unlock(&this->vm_lock);
+ }
+
+ /* Free the VM */
+ if(this->vm)
+ vm_free_copy(this->vm);
+
+ pthread_mutex_destroy(&this->vm_lock);
+
+ /* We leave the final freeing of the entire structure to the cache,
+ * because we don't know, if there are still buffers out in the wild,
+ * that must return first. */
+ if(this->cache)
+ dvdnav_read_cache_free(this->cache);
+ else
+ free(this);
+
+ return DVDNAV_STATUS_OK;
+}
+
dvdnav_status_t dvdnav_open(dvdnav_t** dest, const char *path) {
dvdnav_t *this;
struct timeval time;
@@ -203,12 +264,12 @@ int64_t dvdnav_convert_time(dvd_time_t *time) {
int64_t result;
int64_t frames;
- result = (time->hour >> 4 ) * 10 * 60 * 60 * 90000;
- result += (time->hour & 0x0f) * 60 * 60 * 90000;
- result += (time->minute >> 4 ) * 10 * 60 * 90000;
- result += (time->minute & 0x0f) * 60 * 90000;
- result += (time->second >> 4 ) * 10 * 90000;
- result += (time->second & 0x0f) * 90000;
+ result = ((int64_t)(time->hour >> 4 )) * 10 * 60 * 60 * 90000;
+ result += ((int64_t)(time->hour & 0x0f)) * 60 * 60 * 90000;
+ result += ((int64_t)(time->minute >> 4 )) * 10 * 60 * 90000;
+ result += ((int64_t)(time->minute & 0x0f)) * 60 * 90000;
+ result += ((int64_t)(time->second >> 4 )) * 10 * 90000;
+ result += ((int64_t)(time->second & 0x0f)) * 90000;
frames = ((time->frame_u & 0x30) >> 4) * 10;
frames += ((time->frame_u & 0x0f) ) ;
@@ -336,9 +397,10 @@ static int32_t dvdnav_get_vobu(dvdnav_t *this, dsi_t *
dvdnav_angle_change(this, 1);
}
#endif
+ /* only use ILVU information if we are at the last vobunit in ILVU */
+ /* otherwise we will miss nav packets from vobunits inbetween */
+ if(num_angle != 0 && (nav_dsi->sml_pbi.category & DSI_ILVU_MASK) == (DSI_ILVU_BLOCK | DSI_ILVU_LAST)) {
- if(num_angle != 0) {
-
if((next = nav_pci->nsml_agli.nsml_agl_dsta[angle-1]) != 0) {
if((next & 0x3fffffff) != 0) {
if(next & 0x80000000)
@@ -518,8 +580,10 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *
return DVDNAV_STATUS_OK;
}
- /* Check to see if we need to change the currently opened VOB */
- if((this->position_current.vts != this->position_next.vts) ||
+ /* Check to see if we need to change the currently opened VOB or open
+ * a new one because we don't currently have an opened VOB. */
+ if((this->file == NULL) ||
+ (this->position_current.vts != this->position_next.vts) ||
(this->position_current.domain != this->position_next.domain)) {
dvd_read_domain_t domain;
int32_t vtsN;
@@ -655,7 +719,7 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *
fprintf(MSG_OUT, "libdvdnav: SPU_CLUT_CHANGE\n");
#endif
(*len) = 16 * sizeof(uint32_t);
- memcpy(*buf, &(state->pgc->palette), 16 * sizeof(uint32_t));
+ memcpy(*buf, state->pgc->palette, sizeof(state->pgc->palette));
this->spu_clut_changed = 0;
pthread_mutex_unlock(&this->vm_lock);
return DVDNAV_STATUS_OK;
@@ -731,16 +795,15 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *
/* we are about to leave a cell, so a lot of state changes could occur;
* under certain conditions, the application should get in sync with us before this,
* otherwise it might show stills or menus too shortly */
- if ((this->position_current.still || this->pci.hli.hl_gi.hli_ss) && !this->sync_wait_skip) {
+ if ((this->position_current.still || this->pci.hli.hl_gi.hli_ss) && !this->sync_wait_skip)
this->sync_wait = 1;
- } else {
- if( this->position_current.still == 0 || this->skip_still ) {
- /* no active cell still -> get us to the next cell */
- vm_get_next_cell(this->vm);
- this->position_current.still = 0; /* still gets activated at end of cell */
- this->skip_still = 0;
- this->sync_wait_skip = 0;
- }
+
+ if(!this->position_current.still || this->skip_still ) {
+ /* no active cell still -> get us to the next cell */
+ vm_get_next_cell(this->vm);
+ this->position_current.still = 0; /* still gets activated at end of cell */
+ this->skip_still = 0;
+ this->sync_wait_skip = 0;
}
/* handle related state changes in next iteration */
(*event) = DVDNAV_NOP;

View File

@ -0,0 +1,36 @@
$OpenBSD: patch-src_dvdnav_dvdnav_h,v 1.1 2012/09/26 00:04:09 brad Exp $
- Add a function to create a dpu of a dvdnav handle
- Fix C++ compatibility broken in r1208
- Allow backward search for SEEK_CUR
--- src/dvdnav/dvdnav.h.orig Sat Feb 26 15:32:32 2011
+++ src/dvdnav/dvdnav.h Tue Sep 11 20:35:47 2012
@@ -89,6 +89,9 @@ typedef int32_t dvdnav_status_t;
*/
dvdnav_status_t dvdnav_open(dvdnav_t **dest, const char *path);
+dvdnav_status_t dvdnav_dup(dvdnav_t **dest, dvdnav_t *src);
+dvdnav_status_t dvdnav_free_dup(dvdnav_t *this);
+
/*
* Closes a dvdnav_t previously opened with dvdnav_open(), freeing any
* memory associated with it.
@@ -281,7 +284,7 @@ dvdnav_status_t dvdnav_part_play(dvdnav_t *self, int32
/*
* Plays the specified title, starting from the specified program
*/
-dvdnav_status_t dvdnav_program_play(dvdnav_t *this, int32_t title, int32_t pgcn, int32_t pgn);
+dvdnav_status_t dvdnav_program_play(dvdnav_t *self, int32_t title, int32_t pgcn, int32_t pgn);
/*
* Stores in *times an array (that the application *must* free) of
@@ -370,7 +373,7 @@ dvdnav_status_t dvdnav_part_search(dvdnav_t *self, int
* fcntl.h.
*/
dvdnav_status_t dvdnav_sector_search(dvdnav_t *self,
- uint64_t offset, int32_t origin);
+ int64_t offset, int32_t origin);
/*
returns the current stream time in PTS ticks as reported by the IFO structures

View File

@ -0,0 +1,21 @@
$OpenBSD: patch-src_dvdnav_internal_h,v 1.1 2012/09/26 00:04:09 brad Exp $
Bit fields for ILVU
--- src/dvdnav_internal.h.orig Wed Sep 5 14:23:14 2012
+++ src/dvdnav_internal.h Wed Sep 5 14:23:26 2012
@@ -76,6 +76,14 @@ static inline int _private_gettimeofday( struct timeva
#define DVD_VIDEO_LB_LEN 2048
#endif
+typedef enum {
+ DSI_ILVU_PRE = 1 << 15, /* set during the last 3 VOBU preceeding an interleaved block. */
+ DSI_ILVU_BLOCK = 1 << 14, /* set for all VOBU in an interleaved block */
+ DSI_ILVU_FIRST = 1 << 13, /* set for the first VOBU for a given angle or scene within a ILVU, or the first VOBU in the preparation (PREU) sequence */
+ DSI_ILVU_LAST = 1 << 12, /* set for the last VOBU for a given angle or scene within a ILVU, or the last VOBU in the preparation (PREU) sequence */
+ DSI_ILVU_MASK = 0xf000
+} DSI_ILVU;
+
typedef struct read_cache_s read_cache_t;
/*

View File

@ -0,0 +1,34 @@
$OpenBSD: patch-src_highlight_c,v 1.1 2012/09/26 00:04:09 brad Exp $
Pointer validation fixing
--- src/highlight.c.orig Wed Sep 5 14:21:14 2012
+++ src/highlight.c Wed Sep 5 14:21:20 2012
@@ -242,8 +242,13 @@ static btni_t *get_current_button(dvdnav_t *this, pci_
}
static dvdnav_status_t button_auto_action(dvdnav_t *this, pci_t *pci) {
- if (get_current_button(this, pci)->auto_action_mode)
+ btni_t *button_ptr;
+ if ((button_ptr = get_current_button(this, pci)) == NULL)
+ return DVDNAV_STATUS_ERR;
+
+ if (button_ptr->auto_action_mode)
return dvdnav_button_activate(this, pci);
+
return DVDNAV_STATUS_OK;
}
@@ -366,7 +371,11 @@ dvdnav_status_t dvdnav_button_activate(dvdnav_t *this,
return DVDNAV_STATUS_ERR;
}
- button_ptr = get_current_button(this, pci);
+ if ((button_ptr = get_current_button(this, pci)) == NULL) {
+ pthread_mutex_unlock(&this->vm_lock);
+ return DVDNAV_STATUS_ERR;
+ }
+
/* Finally, make the VM execute the appropriate code and probably
* schedule a jump */
#ifdef BUTTON_TESTING

View File

@ -0,0 +1,67 @@
$OpenBSD: patch-src_remap_c,v 1.1 2012/09/26 00:04:09 brad Exp $
- Initialize epos
- Pointer validation fixing
--- src/remap.c.orig Wed Sep 5 14:20:01 2012
+++ src/remap.c Wed Sep 5 14:20:08 2012
@@ -62,6 +62,9 @@ struct remap_s {
static remap_t* remap_new( char *title) {
remap_t *map = malloc( sizeof(remap_t));
+ if (map == NULL)
+ return NULL;
+
map->title = strdup(title);
map->maxblocks = 0;
map->nblocks = 0;
@@ -139,8 +142,10 @@ static void remap_add_node( remap_t *map, block_t bloc
} else {
/* new block */
if (map->nblocks >= map->maxblocks) {
+ if ((map->blocks = realloc( map->blocks, sizeof( block_t)*( map->maxblocks + 20))) == NULL)
+ return;
+
map->maxblocks += 20;
- map->blocks = realloc( map->blocks, sizeof( block_t)*map->maxblocks);
}
n = map->nblocks++;
while (n > 0 && compare_block( &block, &map->blocks[ n-1]) < 0) {
@@ -155,10 +160,12 @@ static int parseblock(char *buf, int *dom, int *tt, in
unsigned long *start, unsigned long *end) {
long tmp;
char *tok;
- char *epos;
+ char *epos = NULL;
char *marker[]={"domain", "title", "program", "start", "end"};
int st = 0;
- tok = strtok( buf, " ");
+ if ((tok = strtok( buf, " ")) == NULL)
+ return st;
+
while (st < 5) {
if (strcmp(tok, marker[st])) return -st-1000;
tok = strtok( NULL, " ");
@@ -183,7 +190,7 @@ static int parseblock(char *buf, int *dom, int *tt, in
break;
}
st++;
- tok = strtok( NULL, " ");
+ if (!(tok = strtok( NULL, " "))) return -st-2000;
}
return st;
}
@@ -214,7 +221,12 @@ remap_t* remap_loadmap( char *title) {
}
/* Load the map file */
- map = remap_new( title);
+ if ((map = remap_new( title)) == NULL) {
+ fprintf(MSG_OUT, "libdvdnav: Unable to load map '%s'\n", title);
+ fclose(fp);
+ return NULL;
+ }
+
while (fgets( buf, sizeof(buf), fp) != NULL) {
if (buf[0] == '\n' || buf[0] == '#' || buf[0] == 0) continue;
if (strncasecmp( buf, "debug", 5) == 0) {

View File

@ -0,0 +1,182 @@
$OpenBSD: patch-src_searching_c,v 1.1 2012/09/26 00:04:09 brad Exp $
- Skip PGCs w/ a cell number of 0
- Ignore parts where the pgc start byte is above the last byte
- Make sure pgc is valid before dereferencing
- Check cell new row before using it to index into cell_playback
- Initialize next_vobu
- Rework functions that call vm_copy_vm()
- Fix calculation for multi-angle DVDs
- Allow backward search for SEEK_CUR
--- src/searching.c.orig Fri Oct 7 13:06:24 2011
+++ src/searching.c Tue Sep 11 20:38:00 2012
@@ -73,7 +73,7 @@ static dvdnav_status_t dvdnav_scan_admap(dvdnav_t *thi
}
if(admap) {
uint32_t address = 0;
- uint32_t vobu_start, next_vobu;
+ uint32_t vobu_start, next_vobu = 0;
int admap_entries = (admap->last_byte + 1 - VOBU_ADMAP_SIZE)/VOBU_ADMAP_SIZE;
/* Search through ADMAP for best sector */
@@ -182,7 +182,7 @@ dvdnav_status_t dvdnav_time_search(dvdnav_t *this,
}
dvdnav_status_t dvdnav_sector_search(dvdnav_t *this,
- uint64_t offset, int32_t origin) {
+ int64_t offset, int32_t origin) {
uint32_t target = 0;
uint32_t current_pos;
uint32_t cur_sector;
@@ -213,7 +213,7 @@ dvdnav_status_t dvdnav_sector_search(dvdnav_t *this,
return DVDNAV_STATUS_ERR;
}
#ifdef LOG_DEBUG
- fprintf(MSG_OUT, "libdvdnav: seeking to offset=%lu pos=%u length=%u\n", offset, target, length);
+ fprintf(MSG_OUT, "libdvdnav: seeking to offset=%lld pos=%u length=%u\n", offset, target, length);
fprintf(MSG_OUT, "libdvdnav: Before cellN=%u blockN=%u\n", state->cellN, state->blockN);
#endif
@@ -231,11 +231,16 @@ dvdnav_status_t dvdnav_sector_search(dvdnav_t *this,
target = offset;
break;
case SEEK_CUR:
- if(target + offset >= length) {
+ if((signed)target + offset >= length) {
printerr("Request to seek behind end.");
pthread_mutex_unlock(&this->vm_lock);
return DVDNAV_STATUS_ERR;
}
+ if((signed)target + offset < 0) {
+ printerr("Request to seek before start.");
+ pthread_mutex_unlock(&this->vm_lock);
+ return DVDNAV_STATUS_ERR;
+ }
target += offset;
break;
case SEEK_END:
@@ -403,8 +408,7 @@ dvdnav_status_t dvdnav_next_pg_search(dvdnav_t *this)
pthread_mutex_lock(&this->vm_lock);
if(!this->vm->state.pgc) {
printerr("No current PGC.");
- pthread_mutex_unlock(&this->vm_lock);
- return DVDNAV_STATUS_ERR;
+ goto fail;
}
#ifdef LOG_DEBUG
@@ -412,17 +416,25 @@ dvdnav_status_t dvdnav_next_pg_search(dvdnav_t *this)
#endif
/* make a copy of current VM and try to navigate the copy to the next PG */
try_vm = vm_new_copy(this->vm);
+ if (try_vm == NULL) {
+ printerr("Unable to copy the VM.");
+ goto fail;
+ }
+
if (!vm_jump_next_pg(try_vm) || try_vm->stopped) {
vm_free_copy(try_vm);
/* next_pg failed, try to jump at least to the next cell */
try_vm = vm_new_copy(this->vm);
+ if (try_vm == NULL) {
+ printerr("Unable to copy the VM.");
+ goto fail;
+ }
vm_get_next_cell(try_vm);
if (try_vm->stopped) {
vm_free_copy(try_vm);
fprintf(MSG_OUT, "libdvdnav: next chapter failed.\n");
printerr("Skip to next chapter failed.");
- pthread_mutex_unlock(&this->vm_lock);
- return DVDNAV_STATUS_ERR;
+ goto fail;
}
}
this->cur_cell_time = 0;
@@ -437,6 +449,10 @@ dvdnav_status_t dvdnav_next_pg_search(dvdnav_t *this)
pthread_mutex_unlock(&this->vm_lock);
return DVDNAV_STATUS_OK;
+
+fail:
+ pthread_mutex_unlock(&this->vm_lock);
+ return DVDNAV_STATUS_ERR;
}
dvdnav_status_t dvdnav_menu_call(dvdnav_t *this, DVDMenuID_t menu) {
@@ -445,13 +461,17 @@ dvdnav_status_t dvdnav_menu_call(dvdnav_t *this, DVDMe
pthread_mutex_lock(&this->vm_lock);
if(!this->vm->state.pgc) {
printerr("No current PGC.");
- pthread_mutex_unlock(&this->vm_lock);
- return DVDNAV_STATUS_ERR;
+ goto fail;
}
this->cur_cell_time = 0;
/* make a copy of current VM and try to navigate the copy to the menu */
try_vm = vm_new_copy(this->vm);
+ if (try_vm == NULL) {
+ printerr("Unable to copy VM.");
+ goto fail;
+ }
+
if ( (menu == DVD_MENU_Escape) && (this->vm->state.domain != VTS_DOMAIN)) {
/* Try resume */
if (vm_jump_resume(try_vm) && !try_vm->stopped) {
@@ -477,9 +497,12 @@ dvdnav_status_t dvdnav_menu_call(dvdnav_t *this, DVDMe
} else {
vm_free_copy(try_vm);
printerr("No such menu or menu not reachable.");
- pthread_mutex_unlock(&this->vm_lock);
- return DVDNAV_STATUS_ERR;
+ goto fail;
}
+
+fail:
+ pthread_mutex_unlock(&this->vm_lock);
+ return DVDNAV_STATUS_ERR;
}
dvdnav_status_t dvdnav_get_position(dvdnav_t *this, uint32_t *pos,
@@ -530,6 +553,8 @@ dvdnav_status_t dvdnav_get_position(dvdnav_t *this, ui
*len = 0;
for (cell_nr = first_cell_nr; cell_nr <= last_cell_nr; cell_nr++) {
cell = &(state->pgc->cell_playback[cell_nr-1]);
+ if(cell->block_type == BLOCK_TYPE_ANGLE_BLOCK && cell->block_mode != BLOCK_MODE_FIRST_CELL)
+ continue;
if (cell_nr == state->cellN) {
/* the current sector is in this cell,
* pos is length of PG up to here + sector's offset in this cell */
@@ -616,13 +641,29 @@ uint32_t dvdnav_describe_title_chapters(dvdnav_t *this
length = 0;
for(i=0; i<parts; i++) {
uint32_t cellnr, endcellnr;
+ if (ifo->vts_pgcit->pgci_srp[ptt[i].pgcn-1].pgc_start_byte >= ifo->vts_pgcit->last_byte) {
+ printerr("PGC start out of bounds");
+ continue;
+ }
pgc = ifo->vts_pgcit->pgci_srp[ptt[i].pgcn-1].pgc;
+ if (pgc == NULL) {
+ printerr("PGC missing.");
+ continue;
+ }
if(ptt[i].pgn > pgc->nr_of_programs) {
printerr("WRONG part number.");
goto fail;
}
- cellnr = pgc->program_map[ptt[i].pgn-1];
+ if (pgc->nr_of_cells == 0) {
+ printerr("Number of cells cannot be 0");
+ continue;
+ }
+ if ((cellnr = pgc->program_map[ptt[i].pgn-1]) == 0) {
+ printerr("Cell new row cannot be 0");
+ continue;
+ }
+
if(ptt[i].pgn < pgc->nr_of_programs)
endcellnr = pgc->program_map[ptt[i].pgn];
else

View File

@ -0,0 +1,324 @@
$OpenBSD: patch-src_vm_vm_c,v 1.1 2012/09/26 00:04:09 brad Exp $
- Reset the vm if necessary
- Use vm_close() w/in vm.c where appropriate
- Add the static function vm_close()
- Check the return value of dvd_read_name
- Rewrite dvd_read_name to return a value
- Prevent general CPP macro from causing strange behavior
- Replace assert w/ a conditional and a null return
- Initialize link_values
- Pointer validation fixing
- Return 0 instead of an assert
--- src/vm/vm.c.orig Wed Sep 5 14:18:33 2012
+++ src/vm/vm.c Wed Sep 5 14:18:50 2012
@@ -59,7 +59,7 @@
#endif
/*
-#define STRICT
+#define DVDNAV_STRICT
*/
/* Local prototypes */
@@ -101,8 +101,8 @@ static int get_PGCN(vm_t *vm);
static pgcit_t* get_MENU_PGCIT(vm_t *vm, ifo_handle_t *h, uint16_t lang);
static pgcit_t* get_PGCIT(vm_t *vm);
-
/* Helper functions */
+static void vm_close(vm_t *vm);
#ifdef TRACE
static void vm_print_current_domain_state(vm_t *vm) {
@@ -162,64 +162,86 @@ static int os2_open(const char *name, int oflag)
}
#endif
-static void dvd_read_name(char *name, char *serial, const char *device) {
- /* Because we are compiling with _FILE_OFFSET_BITS=64
- * all off_t are 64bit.
- */
- off_t off;
- int fd, i;
- uint8_t data[DVD_VIDEO_LB_LEN];
+static int dvd_read_name(char *name, char *serial, const char *device) {
+ /* Because we are compiling with _FILE_OFFSET_BITS=64
+ * all off_t are 64bit.
+ */
+ off_t off;
+ ssize_t read_size = 0;
+ int fd = -1, i;
+ uint8_t data[DVD_VIDEO_LB_LEN];
- /* Read DVD name */
- fd = open(device, O_RDONLY);
- if (fd > 0) {
- off = lseek( fd, 32 * (off_t) DVD_VIDEO_LB_LEN, SEEK_SET );
- if( off == ( 32 * (off_t) DVD_VIDEO_LB_LEN ) ) {
- off = read( fd, data, DVD_VIDEO_LB_LEN );
- close(fd);
- if (off == ( (off_t) DVD_VIDEO_LB_LEN )) {
- fprintf(MSG_OUT, "libdvdnav: DVD Title: ");
- for(i=25; i < 73; i++ ) {
- if((data[i] == 0)) break;
- if((data[i] > 32) && (data[i] < 127)) {
- fprintf(MSG_OUT, "%c", data[i]);
- } else {
- fprintf(MSG_OUT, " ");
- }
- }
- strncpy(name, (char*) &data[25], 48);
- name[48] = 0;
- fprintf(MSG_OUT, "\nlibdvdnav: DVD Serial Number: ");
- for(i=73; i < 89; i++ ) {
- if((data[i] == 0)) break;
- if((data[i] > 32) && (data[i] < 127)) {
- fprintf(MSG_OUT, "%c", data[i]);
- } else {
- fprintf(MSG_OUT, " ");
- }
- }
- strncpy(serial, (char*) &data[73], (i-73));
- serial[14] = 0;
- fprintf(MSG_OUT, "\nlibdvdnav: DVD Title (Alternative): ");
- for(i=89; i < 128; i++ ) {
- if((data[i] == 0)) break;
- if((data[i] > 32) && (data[i] < 127)) {
- fprintf(MSG_OUT, "%c", data[i]);
- } else {
- fprintf(MSG_OUT, " ");
- }
- }
- fprintf(MSG_OUT, "\n");
- } else {
- fprintf(MSG_OUT, "libdvdnav: Can't read name block. Probably not a DVD-ROM device.\n");
- }
- } else {
- fprintf(MSG_OUT, "libdvdnav: Can't seek to block %u\n", 32 );
- }
- close(fd);
+ /* Read DVD name */
+ if (device == NULL) {
+ fprintf(MSG_OUT, "libdvdnav: Device name string NULL\n");
+ goto fail;
+ }
+ if ((fd = open(device, O_RDONLY)) == -1) {
+ fprintf(MSG_OUT, "libdvdnav: Unable to open device file %s.\n", device);
+ goto fail;
+ }
+
+ if ((off = lseek( fd, 32 * (off_t) DVD_VIDEO_LB_LEN, SEEK_SET )) == (off_t) - 1) {
+ fprintf(MSG_OUT, "libdvdnav: Unable to seek to the title block %u.\n", 32);
+ goto fail;
+ }
+
+ if( off != ( 32 * (off_t) DVD_VIDEO_LB_LEN ) ) {
+ fprintf(MSG_OUT, "libdvdnav: Can't seek to block %u\n", 32 );
+ goto fail;
+ }
+
+ if ((read_size = read( fd, data, DVD_VIDEO_LB_LEN )) == -1) {
+ fprintf(MSG_OUT, "libdvdnav: Can't read name block. Probably not a DVD-ROM device.\n");
+ goto fail;
+ }
+
+ close(fd);
+ fd = -1;
+ if (read_size != DVD_VIDEO_LB_LEN) {
+ fprintf(MSG_OUT, "libdvdnav: Can't read name block. Probably not a DVD-ROM device.\n");
+ goto fail;
+ }
+
+ fprintf(MSG_OUT, "libdvdnav: DVD Title: ");
+ for(i=25; i < 73; i++ ) {
+ if((data[i] == 0)) break;
+ if((data[i] > 32) && (data[i] < 127)) {
+ fprintf(MSG_OUT, "%c", data[i]);
} else {
- fprintf(MSG_OUT, "NAME OPEN FAILED\n");
+ fprintf(MSG_OUT, " ");
+ }
}
+ strncpy(name, (char*) &data[25], 48);
+ name[48] = 0;
+ fprintf(MSG_OUT, "\nlibdvdnav: DVD Serial Number: ");
+ for(i=73; i < 89; i++ ) {
+ if((data[i] == 0)) break;
+ if((data[i] > 32) && (data[i] < 127)) {
+ fprintf(MSG_OUT, "%c", data[i]);
+ } else {
+ fprintf(MSG_OUT, " ");
+ }
+ }
+ strncpy(serial, (char*) &data[73], (i-73));
+ serial[14] = 0;
+ fprintf(MSG_OUT, "\nlibdvdnav: DVD Title (Alternative): ");
+ for(i=89; i < 128; i++ ) {
+ if((data[i] == 0)) break;
+ if((data[i] > 32) && (data[i] < 127)) {
+ fprintf(MSG_OUT, "%c", data[i]);
+ } else {
+ fprintf(MSG_OUT, " ");
+ }
+ }
+ fprintf(MSG_OUT, "\n");
+ return 1;
+
+fail:
+ if (fd >= 0)
+ close(fd);
+
+ return 0;
}
static int ifoOpenNewVTSI(vm_t *vm, dvd_reader_t *dvd, int vtsN) {
@@ -268,7 +290,7 @@ vm_t* vm_new_vm() {
}
void vm_free_vm(vm_t *vm) {
- vm_stop(vm);
+ vm_close(vm);
free(vm);
}
@@ -294,6 +316,12 @@ dvd_reader_t *vm_get_dvd_reader(vm_t *vm) {
/* Basic Handling */
int vm_start(vm_t *vm) {
+ if (vm->stopped) {
+ if (!vm_reset(vm, NULL))
+ return 0;
+
+ vm->stopped = 0;
+ }
/* Set pgc to FP (First Play) pgc */
set_FP_PGC(vm);
process_command(vm, play_PGC(vm));
@@ -301,6 +329,10 @@ int vm_start(vm_t *vm) {
}
void vm_stop(vm_t *vm) {
+ vm->stopped = 1;
+}
+
+static void vm_close(vm_t *vm) {
if(vm->vmgi) {
ifoClose(vm->vmgi);
vm->vmgi=NULL;
@@ -352,7 +384,7 @@ int vm_reset(vm_t *vm, const char *dvdroot) {
if (vm->dvd && dvdroot) {
/* a new dvd device has been requested */
- vm_stop(vm);
+ vm_close(vm);
}
if (!vm->dvd) {
vm->dvd = DVDOpen(dvdroot);
@@ -390,8 +422,8 @@ int vm_reset(vm_t *vm, const char *dvdroot) {
/* return 0; Not really used for now.. */
}
/* ifoRead_TXTDT_MGI(vmgi); Not implemented yet */
- dvd_read_name(vm->dvd_name, vm->dvd_serial, dvdroot);
- vm->map = remap_loadmap(vm->dvd_name);
+ if (dvd_read_name(vm->dvd_name, vm->dvd_serial, dvdroot) == 1)
+ vm->map = remap_loadmap(vm->dvd_name);
}
if (vm->vmgi) {
int i, mask;
@@ -414,7 +446,8 @@ vm_t *vm_new_copy(vm_t *source) {
int pgcN = get_PGCN(source);
int pgN = (source->state).pgN;
- assert(pgcN);
+ if (target == NULL || pgcN == 0)
+ goto fail;
memcpy(target, source, sizeof(vm_t));
@@ -424,15 +457,22 @@ vm_t *vm_new_copy(vm_t *source) {
if (vtsN > 0) {
(target->state).vtsN = 0;
if (!ifoOpenNewVTSI(target, target->dvd, vtsN))
- assert(0);
+ goto fail;
/* restore pgc pointer into the new vtsi */
if (!set_PGCN(target, pgcN))
- assert(0);
+ goto fail;
+
(target->state).pgN = pgN;
}
return target;
+
+fail:
+ if (target != NULL)
+ vm_free_vm(target);
+
+ return NULL;
}
void vm_merge(vm_t *target, vm_t *source) {
@@ -1050,7 +1090,7 @@ static link_t play_PGC_PG(vm_t *vm, int pgN) {
}
static link_t play_PGC_post(vm_t *vm) {
- link_t link_values;
+ link_t link_values = { LinkNoLink, 0, 0, 0 };
#ifdef TRACE
fprintf(MSG_OUT, "libdvdnav: play_PGC_post:\n");
@@ -1129,7 +1169,7 @@ static link_t play_Cell(vm_t *vm) {
case 1: /* Angle block */
/* Loop and check each cell instead? So we don't get outside the block? */
(vm->state).cellN += (vm->state).AGL_REG - 1;
-#ifdef STRICT
+#ifdef DVDNAV_STRICT
assert((vm->state).cellN <= (vm->state).pgc->nr_of_cells);
assert((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode != 0);
assert((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_type == 1);
@@ -1187,15 +1227,6 @@ static link_t play_Cell_post(vm_t *vm) {
if(cell->cell_cmd_nr != 0) {
link_t link_values;
-/* These asserts are now not needed.
- * Some DVDs have no cell commands listed in the PGC,
- * but the Cell itself points to a cell command that does not exist.
- * For this situation, just ignore the cell command and continue.
- *
- * assert((vm->state).pgc->command_tbl != NULL);
- * assert((vm->state).pgc->command_tbl->nr_of_cell >= cell->cell_cmd_nr);
- */
-
if ((vm->state).pgc->command_tbl != NULL &&
(vm->state).pgc->command_tbl->nr_of_cell >= cell->cell_cmd_nr) {
#ifdef TRACE
@@ -1762,7 +1793,8 @@ static int set_PGCN(vm_t *vm, int pgcN) {
pgcit_t *pgcit;
pgcit = get_PGCIT(vm);
- assert(pgcit != NULL); /* ?? Make this return -1 instead */
+ if (pgcit == NULL)
+ return 0;
if(pgcN < 1 || pgcN > pgcit->nr_of_pgci_srp) {
#ifdef TRACE
@@ -1797,12 +1829,11 @@ static int set_PGN(vm_t *vm) {
(vm->state).pgN = new_pgN;
if((vm->state).domain == VTS_DOMAIN) {
- playback_type_t *pb_ty;
if((vm->state).TTN_REG > vm->vmgi->tt_srpt->nr_of_srpts)
return 0; /* ?? */
- pb_ty = &vm->vmgi->tt_srpt->title[(vm->state).TTN_REG - 1].pb_ty;
- vm_get_current_title_part(vm, &dummy, &part);
- (vm->state).PTTN_REG = part;
+
+ vm_get_current_title_part(vm, &dummy, &part);
+ (vm->state).PTTN_REG = part;
}
return 1;
}