diff options
author | aurel <aurel@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2005-06-30 22:48:26 +0000 |
---|---|---|
committer | aurel <aurel@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2005-06-30 22:48:26 +0000 |
commit | eb3c1b5cedfc1b7d35a2d261780979b00170946e (patch) | |
tree | ccc33eb81679684b7f2ca3d7c610d721375c4ea5 /libmpdvdkit2/ifo_read.c | |
parent | c8fbf4405d7b433f0dc622bc9dcf81d0ceb5ef36 (diff) | |
download | mpv-eb3c1b5cedfc1b7d35a2d261780979b00170946e.tar.bz2 mpv-eb3c1b5cedfc1b7d35a2d261780979b00170946e.tar.xz |
update libdvdread to v0.9.4
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@15875 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'libmpdvdkit2/ifo_read.c')
-rw-r--r-- | libmpdvdkit2/ifo_read.c | 498 |
1 files changed, 359 insertions, 139 deletions
diff --git a/libmpdvdkit2/ifo_read.c b/libmpdvdkit2/ifo_read.c index a01ba7e04f..60ce748199 100644 --- a/libmpdvdkit2/ifo_read.c +++ b/libmpdvdkit2/ifo_read.c @@ -1,10 +1,7 @@ /* - * Copyright (C) 2000, 2001, 2002 Björn Englund <d4bjorn@dtek.chalmers.se>, - * Håkan Hjort <d95hjort@dtek.chalmers.se> - * - * Modified for use with MPlayer, changes contained in libdvdread_changes.diff. - * detailed CVS changelog at http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/ - * $Id$ + * Copyright (C) 2000, 2001, 2002, 2003 + * Björn Englund <d4bjorn@dtek.chalmers.se>, + * Håkan Hjort <d95hjort@dtek.chalmers.se> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,25 +18,29 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "config.h" + #include <stdio.h> #include <stdlib.h> -#include <unistd.h> #include <inttypes.h> #include <string.h> -//#include <assert.h> - -#include "dvd_reader.h" -#include "config.h" // Needed for WORDS_BIGENDIAN #include "bswap.h" #include "ifo_types.h" #include "ifo_read.h" +#include "dvd_reader.h" +#include "dvdread_internal.h" #ifndef DVD_BLOCK_LEN #define DVD_BLOCK_LEN 2048 #endif #ifndef NDEBUG +#define CHECK_ZERO0(arg) \ + if(arg != 0) { \ + fprintf(stderr, "*** Zero check failed in %s:%i\n for %s = 0x%x\n", \ + __FILE__, __LINE__, # arg, arg); \ + } #define CHECK_ZERO(arg) \ if(memcmp(my_friendly_zeros, &arg, sizeof(arg))) { \ unsigned int i_CZ; \ @@ -51,6 +52,7 @@ } static const uint8_t my_friendly_zeros[2048]; #else +#define CHECK_ZERO0(arg) (void)(arg) #define CHECK_ZERO(arg) (void)(arg) #endif @@ -87,7 +89,7 @@ static void ifoFree_PGC_COMMAND_TBL(pgc_command_tbl_t *cmd_tbl); static void ifoFree_PGCIT_internal(pgcit_t *pgcit); -static int DVDFileSeek_( dvd_file_t *dvd_file, uint32_t offset ) { +static inline int DVDFileSeek_( dvd_file_t *dvd_file, uint32_t offset ) { return (DVDFileSeek(dvd_file, (int)offset) == (int)offset); } @@ -102,6 +104,8 @@ ifo_handle_t *ifoOpen(dvd_reader_t *dvd, int title) { memset(ifofile, 0, sizeof(ifo_handle_t)); ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_FILE); + if(!ifofile->file) /* Should really catch any error and try to fallback */ + ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_BACKUP_FILE); if(!ifofile->file) { if(title) { fprintf(stderr, "libdvdread: Can't open file VTS_%02d_0.IFO.\n", title); @@ -150,6 +154,7 @@ ifo_handle_t *ifoOpen(dvd_reader_t *dvd, int title) { ifoRead_PGCI_UT(ifofile); + ifoRead_VTS_TMAPT(ifofile); ifoRead_C_ADT(ifofile); ifoRead_VOBU_ADMAP(ifofile); @@ -184,6 +189,8 @@ ifo_handle_t *ifoOpenVMGI(dvd_reader_t *dvd) { memset(ifofile, 0, sizeof(ifo_handle_t)); ifofile->file = DVDOpenFile(dvd, 0, DVD_READ_INFO_FILE); + if(!ifofile->file) /* Should really catch any error and try to fallback */ + ifofile->file = DVDOpenFile(dvd, 0, DVD_READ_INFO_BACKUP_FILE); if(!ifofile->file) { fprintf(stderr, "libdvdread: Can't open file VIDEO_TS.IFO.\n"); free(ifofile); @@ -215,6 +222,8 @@ ifo_handle_t *ifoOpenVTSI(dvd_reader_t *dvd, int title) { } ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_FILE); + if(!ifofile->file) /* Should really catch any error and try to fallback */ + ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_BACKUP_FILE); if(!ifofile->file) { fprintf(stderr, "libdvdread: Can't open file VTS_%02d_0.IFO.\n", title); free(ifofile); @@ -320,33 +329,33 @@ static int ifoRead_VMG(ifo_handle_t *ifofile) { CHECK_ZERO(vmgi_mat->zero_8); CHECK_ZERO(vmgi_mat->zero_9); CHECK_ZERO(vmgi_mat->zero_10); - assert(vmgi_mat->vmg_last_sector != 0); - assert(vmgi_mat->vmgi_last_sector != 0); - assert(vmgi_mat->vmgi_last_sector * 2 <= vmgi_mat->vmg_last_sector); - assert(vmgi_mat->vmg_nr_of_volumes != 0); - assert(vmgi_mat->vmg_this_volume_nr != 0); - assert(vmgi_mat->vmg_this_volume_nr <= vmgi_mat->vmg_nr_of_volumes); - assert(vmgi_mat->disc_side == 1 || vmgi_mat->disc_side == 2); - assert(vmgi_mat->vmg_nr_of_title_sets != 0); - assert(vmgi_mat->vmgi_last_byte >= 341); - assert(vmgi_mat->vmgi_last_byte / DVD_BLOCK_LEN <= + CHECK_VALUE(vmgi_mat->vmg_last_sector != 0); + CHECK_VALUE(vmgi_mat->vmgi_last_sector != 0); + CHECK_VALUE(vmgi_mat->vmgi_last_sector * 2 <= vmgi_mat->vmg_last_sector); + CHECK_VALUE(vmgi_mat->vmgi_last_sector * 2 <= vmgi_mat->vmg_last_sector); + CHECK_VALUE(vmgi_mat->vmg_nr_of_volumes != 0); + CHECK_VALUE(vmgi_mat->vmg_this_volume_nr != 0); + CHECK_VALUE(vmgi_mat->vmg_this_volume_nr <= vmgi_mat->vmg_nr_of_volumes); + CHECK_VALUE(vmgi_mat->disc_side == 1 || vmgi_mat->disc_side == 2); + CHECK_VALUE(vmgi_mat->vmg_nr_of_title_sets != 0); + CHECK_VALUE(vmgi_mat->vmgi_last_byte >= 341); + CHECK_VALUE(vmgi_mat->vmgi_last_byte / DVD_BLOCK_LEN <= vmgi_mat->vmgi_last_sector); - /* It seems that first_play_pgc might be optional. */ - assert(vmgi_mat->first_play_pgc != 0 && - vmgi_mat->first_play_pgc < vmgi_mat->vmgi_last_byte); - assert(vmgi_mat->vmgm_vobs == 0 || + /* It seems that first_play_pgc is optional. */ + CHECK_VALUE(vmgi_mat->first_play_pgc < vmgi_mat->vmgi_last_byte); + CHECK_VALUE(vmgi_mat->vmgm_vobs == 0 || (vmgi_mat->vmgm_vobs > vmgi_mat->vmgi_last_sector && vmgi_mat->vmgm_vobs < vmgi_mat->vmg_last_sector)); - assert(vmgi_mat->tt_srpt <= vmgi_mat->vmgi_last_sector); - assert(vmgi_mat->vmgm_pgci_ut <= vmgi_mat->vmgi_last_sector); - assert(vmgi_mat->ptl_mait <= vmgi_mat->vmgi_last_sector); - assert(vmgi_mat->vts_atrt <= vmgi_mat->vmgi_last_sector); - assert(vmgi_mat->txtdt_mgi <= vmgi_mat->vmgi_last_sector); - assert(vmgi_mat->vmgm_c_adt <= vmgi_mat->vmgi_last_sector); - assert(vmgi_mat->vmgm_vobu_admap <= vmgi_mat->vmgi_last_sector); + CHECK_VALUE(vmgi_mat->tt_srpt <= vmgi_mat->vmgi_last_sector); + CHECK_VALUE(vmgi_mat->vmgm_pgci_ut <= vmgi_mat->vmgi_last_sector); + CHECK_VALUE(vmgi_mat->ptl_mait <= vmgi_mat->vmgi_last_sector); + CHECK_VALUE(vmgi_mat->vts_atrt <= vmgi_mat->vmgi_last_sector); + CHECK_VALUE(vmgi_mat->txtdt_mgi <= vmgi_mat->vmgi_last_sector); + CHECK_VALUE(vmgi_mat->vmgm_c_adt <= vmgi_mat->vmgi_last_sector); + CHECK_VALUE(vmgi_mat->vmgm_vobu_admap <= vmgi_mat->vmgi_last_sector); - assert(vmgi_mat->nr_of_vmgm_audio_streams <= 1); - assert(vmgi_mat->nr_of_vmgm_subp_streams <= 1); + CHECK_VALUE(vmgi_mat->nr_of_vmgm_audio_streams <= 1); + CHECK_VALUE(vmgi_mat->nr_of_vmgm_subp_streams <= 1); return 1; } @@ -422,34 +431,44 @@ static int ifoRead_VTS(ifo_handle_t *ifofile) { CHECK_ZERO(vtsi_mat->zero_18); CHECK_ZERO(vtsi_mat->zero_19); CHECK_ZERO(vtsi_mat->zero_20); - assert(vtsi_mat->vtsi_last_sector*2 <= vtsi_mat->vts_last_sector); - assert(vtsi_mat->vtsi_last_byte/DVD_BLOCK_LEN <= vtsi_mat->vtsi_last_sector); - assert(vtsi_mat->vtsm_vobs == 0 || - (vtsi_mat->vtsm_vobs > vtsi_mat->vtsi_last_sector && + CHECK_ZERO(vtsi_mat->zero_21); + CHECK_VALUE(vtsi_mat->vtsi_last_sector*2 <= vtsi_mat->vts_last_sector); + CHECK_VALUE(vtsi_mat->vtsi_last_byte/DVD_BLOCK_LEN <= vtsi_mat->vtsi_last_sector); + CHECK_VALUE(vtsi_mat->vtsm_vobs == 0 || + (vtsi_mat->vtsm_vobs > vtsi_mat->vtsi_last_sector && vtsi_mat->vtsm_vobs < vtsi_mat->vts_last_sector)); - assert(vtsi_mat->vtstt_vobs == 0 || + CHECK_VALUE(vtsi_mat->vtstt_vobs == 0 || (vtsi_mat->vtstt_vobs > vtsi_mat->vtsi_last_sector && vtsi_mat->vtstt_vobs < vtsi_mat->vts_last_sector)); - assert(vtsi_mat->vts_ptt_srpt <= vtsi_mat->vtsi_last_sector); - assert(vtsi_mat->vts_pgcit <= vtsi_mat->vtsi_last_sector); - assert(vtsi_mat->vtsm_pgci_ut <= vtsi_mat->vtsi_last_sector); - assert(vtsi_mat->vts_tmapt <= vtsi_mat->vtsi_last_sector); - assert(vtsi_mat->vtsm_c_adt <= vtsi_mat->vtsi_last_sector); - assert(vtsi_mat->vtsm_vobu_admap <= vtsi_mat->vtsi_last_sector); - assert(vtsi_mat->vts_c_adt <= vtsi_mat->vtsi_last_sector); - assert(vtsi_mat->vts_vobu_admap <= vtsi_mat->vtsi_last_sector); - - assert(vtsi_mat->nr_of_vtsm_audio_streams <= 1); - assert(vtsi_mat->nr_of_vtsm_subp_streams <= 1); - - assert(vtsi_mat->nr_of_vts_audio_streams <= 8); + CHECK_VALUE(vtsi_mat->vts_ptt_srpt <= vtsi_mat->vtsi_last_sector); + CHECK_VALUE(vtsi_mat->vts_pgcit <= vtsi_mat->vtsi_last_sector); + CHECK_VALUE(vtsi_mat->vtsm_pgci_ut <= vtsi_mat->vtsi_last_sector); + CHECK_VALUE(vtsi_mat->vts_tmapt <= vtsi_mat->vtsi_last_sector); + CHECK_VALUE(vtsi_mat->vtsm_c_adt <= vtsi_mat->vtsi_last_sector); + CHECK_VALUE(vtsi_mat->vtsm_vobu_admap <= vtsi_mat->vtsi_last_sector); + CHECK_VALUE(vtsi_mat->vts_c_adt <= vtsi_mat->vtsi_last_sector); + CHECK_VALUE(vtsi_mat->vts_vobu_admap <= vtsi_mat->vtsi_last_sector); + + CHECK_VALUE(vtsi_mat->nr_of_vtsm_audio_streams <= 1); + CHECK_VALUE(vtsi_mat->nr_of_vtsm_subp_streams <= 1); + + CHECK_VALUE(vtsi_mat->nr_of_vts_audio_streams <= 8); for(i = vtsi_mat->nr_of_vts_audio_streams; i < 8; i++) CHECK_ZERO(vtsi_mat->vts_audio_attr[i]); - assert(vtsi_mat->nr_of_vts_subp_streams <= 32); + CHECK_VALUE(vtsi_mat->nr_of_vts_subp_streams <= 32); for(i = vtsi_mat->nr_of_vts_subp_streams; i < 32; i++) CHECK_ZERO(vtsi_mat->vts_subp_attr[i]); - + + for(i = 0; i < 8; i++) { + CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero1); + CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero2); + CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero3); + CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero4); + CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero5); + CHECK_ZERO(vtsi_mat->vts_mu_audio_attr[i].zero6); + } + return 1; } @@ -470,7 +489,7 @@ static int ifoRead_PGC_COMMAND_TBL(ifo_handle_t *ifofile, B2N_16(cmd_tbl->nr_of_post); B2N_16(cmd_tbl->nr_of_cell); - assert(cmd_tbl->nr_of_pre + cmd_tbl->nr_of_post + cmd_tbl->nr_of_cell<= 255); + CHECK_VALUE(cmd_tbl->nr_of_pre + cmd_tbl->nr_of_post + cmd_tbl->nr_of_cell<= 255); if(cmd_tbl->nr_of_pre != 0) { unsigned int pre_cmds_size = cmd_tbl->nr_of_pre * COMMAND_DATA_SIZE; @@ -572,9 +591,9 @@ static int ifoRead_CELL_PLAYBACK_TBL(ifo_handle_t *ifofile, B2N_32(cell_playback[i].last_sector); /* Changed < to <= because this was false in the movie 'Pi'. */ - assert(cell_playback[i].last_vobu_start_sector <= + CHECK_VALUE(cell_playback[i].last_vobu_start_sector <= cell_playback[i].last_sector); - assert(cell_playback[i].first_sector <= + CHECK_VALUE(cell_playback[i].first_sector <= cell_playback[i].last_vobu_start_sector); } @@ -627,7 +646,7 @@ static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset) { B2N_32(pgc->palette[i]); CHECK_ZERO(pgc->zero_1); - assert(pgc->nr_of_programs <= pgc->nr_of_cells); + CHECK_VALUE(pgc->nr_of_programs <= pgc->nr_of_cells); /* verify time (look at print_time) */ for(i = 0; i < 8; i++) @@ -641,13 +660,13 @@ static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset) { if(pgc->nr_of_programs == 0) { CHECK_ZERO(pgc->still_time); CHECK_ZERO(pgc->pg_playback_mode); // ?? - assert(pgc->program_map_offset == 0); - assert(pgc->cell_playback_offset == 0); - assert(pgc->cell_position_offset == 0); + CHECK_VALUE(pgc->program_map_offset == 0); + CHECK_VALUE(pgc->cell_playback_offset == 0); + CHECK_VALUE(pgc->cell_position_offset == 0); } else { - assert(pgc->program_map_offset != 0); - assert(pgc->cell_playback_offset != 0); - assert(pgc->cell_position_offset != 0); + CHECK_VALUE(pgc->program_map_offset != 0); + CHECK_VALUE(pgc->cell_playback_offset != 0); + CHECK_VALUE(pgc->cell_position_offset != 0); } if(pgc->command_tbl_offset != 0) { @@ -728,11 +747,10 @@ int ifoRead_FP_PGC(ifo_handle_t *ifofile) { if(!ifofile->vmgi_mat) return 0; - /* It seems that first_play_pgc might be optional after all. */ - if(ifofile->vmgi_mat->first_play_pgc == 0) { /* mandatory */ - ifofile->first_play_pgc = 0; - return 0; /* change this to a 1 if it's optional. */ - } + /* It seems that first_play_pgc is optional after all. */ + ifofile->first_play_pgc = 0; + if(ifofile->vmgi_mat->first_play_pgc == 0) + return 1; ifofile->first_play_pgc = (pgc_t *)malloc(sizeof(pgc_t)); if(!ifofile->first_play_pgc) @@ -825,22 +843,22 @@ int ifoRead_TT_SRPT(ifo_handle_t *ifofile) { CHECK_ZERO(tt_srpt->zero_1); - assert(tt_srpt->nr_of_srpts != 0); - assert(tt_srpt->nr_of_srpts < 100); // ?? - assert((int)tt_srpt->nr_of_srpts * sizeof(title_info_t) <= info_length); + CHECK_VALUE(tt_srpt->nr_of_srpts != 0); + CHECK_VALUE(tt_srpt->nr_of_srpts < 100); // ?? + CHECK_VALUE((int)tt_srpt->nr_of_srpts * sizeof(title_info_t) <= info_length); for(i = 0; i < tt_srpt->nr_of_srpts; i++) { - assert(tt_srpt->title[i].pb_ty.zero_1 == 0); - assert(tt_srpt->title[i].nr_of_angles != 0); - assert(tt_srpt->title[i].nr_of_angles < 10); - //assert(tt_srpt->title[i].nr_of_ptts != 0); + CHECK_VALUE(tt_srpt->title[i].pb_ty.zero_1 == 0); + CHECK_VALUE(tt_srpt->title[i].nr_of_angles != 0); + CHECK_VALUE(tt_srpt->title[i].nr_of_angles < 10); + //CHECK_VALUE(tt_srpt->title[i].nr_of_ptts != 0); // XXX: this assertion breaks Ghostbusters: - assert(tt_srpt->title[i].nr_of_ptts < 1000); // ?? - assert(tt_srpt->title[i].title_set_nr != 0); - assert(tt_srpt->title[i].title_set_nr < 100); // ?? - assert(tt_srpt->title[i].vts_ttn != 0); - assert(tt_srpt->title[i].vts_ttn < 100); // ?? - //assert(tt_srpt->title[i].title_set_sector != 0); + CHECK_VALUE(tt_srpt->title[i].nr_of_ptts < 1000); // ?? + CHECK_VALUE(tt_srpt->title[i].title_set_nr != 0); + CHECK_VALUE(tt_srpt->title[i].title_set_nr < 100); // ?? + CHECK_VALUE(tt_srpt->title[i].vts_ttn != 0); + CHECK_VALUE(tt_srpt->title[i].vts_ttn < 100); // ?? + //CHECK_VALUE(tt_srpt->title[i].title_set_sector != 0); } // Make this a function @@ -906,8 +924,8 @@ int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) { B2N_32(vts_ptt_srpt->last_byte); CHECK_ZERO(vts_ptt_srpt->zero_1); - assert(vts_ptt_srpt->nr_of_srpts != 0); - assert(vts_ptt_srpt->nr_of_srpts < 100); // ?? + CHECK_VALUE(vts_ptt_srpt->nr_of_srpts != 0); + CHECK_VALUE(vts_ptt_srpt->nr_of_srpts < 100); // ?? info_length = vts_ptt_srpt->last_byte + 1 - VTS_PTT_SRPT_SIZE; @@ -931,8 +949,10 @@ int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) { Magic Knight Rayearth Daybreak is mastered very strange and has Titles with 0 PTTs. They all have a data[i] offsets beyond the end of of the vts_ptt_srpt structure. */ - assert(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1 + 4); + CHECK_VALUE(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1 + 4); } + + vts_ptt_srpt->ttu_offset = data; vts_ptt_srpt->title = malloc(vts_ptt_srpt->nr_of_srpts * sizeof(ttu_t)); if(!vts_ptt_srpt->title) { @@ -951,7 +971,7 @@ int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) { Magic Knight Rayearth Daybreak is mastered very strange and has Titles with 0 PTTs. */ if(n < 0) n = 0; - assert(n % 4 == 0); + CHECK_VALUE(n % 4 == 0); vts_ptt_srpt->title[i].nr_of_ptts = n / 4; vts_ptt_srpt->title[i].ptt = malloc(n * sizeof(ptt_info_t)); @@ -965,14 +985,13 @@ int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) { } for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) { /* The assert placed here because of Magic Knight Rayearth Daybreak */ - assert(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1); + CHECK_VALUE(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1); vts_ptt_srpt->title[i].ptt[j].pgcn = *(uint16_t*)(((char *)data) + data[i] + 4*j - VTS_PTT_SRPT_SIZE); vts_ptt_srpt->title[i].ptt[j].pgn = *(uint16_t*)(((char *)data) + data[i] + 4*j + 2 - VTS_PTT_SRPT_SIZE); } } - free(data); for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) { @@ -982,12 +1001,12 @@ int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) { } for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { - assert(vts_ptt_srpt->title[i].nr_of_ptts < 1000); // ?? + CHECK_VALUE(vts_ptt_srpt->title[i].nr_of_ptts < 1000); // ?? for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) { - assert(vts_ptt_srpt->title[i].ptt[j].pgcn != 0 ); - assert(vts_ptt_srpt->title[i].ptt[j].pgcn < 1000); // ?? - assert(vts_ptt_srpt->title[i].ptt[j].pgn != 0); - assert(vts_ptt_srpt->title[i].ptt[j].pgn < 100); // ?? + CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn != 0 ); + CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn < 1000); // ?? + CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn != 0); + CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn < 100); // ?? } } @@ -1003,6 +1022,7 @@ void ifoFree_VTS_PTT_SRPT(ifo_handle_t *ifofile) { int i; for(i = 0; i < ifofile->vts_ptt_srpt->nr_of_srpts; i++) free(ifofile->vts_ptt_srpt->title[i].ptt); + free(ifofile->vts_ptt_srpt->ttu_offset); free(ifofile->vts_ptt_srpt->title); free(ifofile->vts_ptt_srpt); ifofile->vts_ptt_srpt = 0; @@ -1013,7 +1033,7 @@ void ifoFree_VTS_PTT_SRPT(ifo_handle_t *ifofile) { int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) { ptl_mait_t *ptl_mait; int info_length; - unsigned int i; + unsigned int i, j; if(!ifofile) return 0; @@ -1024,8 +1044,7 @@ int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) { if(ifofile->vmgi_mat->ptl_mait == 0) return 1; - if(!DVDFileSeek_(ifofile->file, - ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN)) + if(!DVDFileSeek_(ifofile->file, ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN)) return 0; ptl_mait = (ptl_mait_t *)malloc(sizeof(ptl_mait_t)); @@ -1044,26 +1063,29 @@ int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) { B2N_16(ptl_mait->nr_of_vtss); B2N_32(ptl_mait->last_byte); - info_length = ptl_mait->last_byte + 1 - PTL_MAIT_SIZE; - - assert(ptl_mait->nr_of_countries != 0); - assert(ptl_mait->nr_of_countries < 100); // ?? - assert(ptl_mait->nr_of_vtss != 0); - assert(ptl_mait->nr_of_vtss < 100); // ?? - assert(ptl_mait->nr_of_countries * PTL_MAIT_COUNTRY_SIZE <= info_length); + CHECK_VALUE(ptl_mait->nr_of_countries != 0); + CHECK_VALUE(ptl_mait->nr_of_countries < 100); // ?? + CHECK_VALUE(ptl_mait->nr_of_vtss != 0); + CHECK_VALUE(ptl_mait->nr_of_vtss < 100); // ?? + CHECK_VALUE(ptl_mait->nr_of_countries * PTL_MAIT_COUNTRY_SIZE + <= ptl_mait->last_byte + 1 - PTL_MAIT_SIZE); - /* Change this to read and 'translate' the tables too. - I.e don't read so much here */ + info_length = ptl_mait->nr_of_countries * sizeof(ptl_mait_country_t); ptl_mait->countries = (ptl_mait_country_t *)malloc(info_length); if(!ptl_mait->countries) { free(ptl_mait); ifofile->ptl_mait = 0; return 0; } - if(!(DVDReadBytes(ifofile->file, ptl_mait->countries, info_length))) { - fprintf(stderr, "libdvdread: Unable to read PTL_MAIT.\n"); - ifoFree_PTL_MAIT(ifofile); - return 0; + + for(i = 0; i < ptl_mait->nr_of_countries; i++) { + if(!(DVDReadBytes(ifofile->file, &ptl_mait->countries[i], PTL_MAIT_COUNTRY_SIZE))) { + fprintf(stderr, "libdvdread: Unable to read PTL_MAIT.\n"); + free(ptl_mait->countries); + free(ptl_mait); + ifofile->ptl_mait = 0; + return 0; + } } for(i = 0; i < ptl_mait->nr_of_countries; i++) { @@ -1074,25 +1096,221 @@ int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) { for(i = 0; i < ptl_mait->nr_of_countries; i++) { CHECK_ZERO(ptl_mait->countries[i].zero_1); CHECK_ZERO(ptl_mait->countries[i].zero_2); - assert(ptl_mait->countries[i].pf_ptl_mai_start_byte + - 8 * (ptl_mait->nr_of_vtss + 1) * 2 <= ptl_mait->last_byte + 1); + CHECK_VALUE(ptl_mait->countries[i].pf_ptl_mai_start_byte + + 8*2 * (ptl_mait->nr_of_vtss + 1) <= ptl_mait->last_byte + 1); } + for(i = 0; i < ptl_mait->nr_of_countries; i++) { + uint16_t *pf_temp; + + if(!DVDFileSeek_(ifofile->file, + ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN + + ptl_mait->countries[i].pf_ptl_mai_start_byte)) { + fprintf(stderr, "libdvdread: Unable to seak PTL_MAIT table.\n"); + free(ptl_mait->countries); + free(ptl_mait); + return 0; + } + info_length = (ptl_mait->nr_of_vtss + 1) * sizeof(pf_level_t); + pf_temp = (uint16_t *)malloc(info_length); + if(!pf_temp) { + for(j = 0; j < i ; j++) { + free(ptl_mait->countries[j].pf_ptl_mai); + } + free(ptl_mait->countries); + free(ptl_mait); + return 0; + } + if(!(DVDReadBytes(ifofile->file, pf_temp, info_length))) { + fprintf(stderr, "libdvdread: Unable to read PTL_MAIT table.\n"); + free(pf_temp); + for(j = 0; j < i ; j++) { + free(ptl_mait->countries[j].pf_ptl_mai); + } + free(ptl_mait->countries); + free(ptl_mait); + return 0; + } + for (j = 0; j < ((ptl_mait->nr_of_vtss + 1) * 8); j++) { + B2N_16(pf_temp[j]); + } + ptl_mait->countries[i].pf_ptl_mai = (pf_level_t *)malloc(info_length); + if(!ptl_mait->countries[i].pf_ptl_mai) { + free(pf_temp); + for(j = 0; j < i ; j++) { + free(ptl_mait->countries[j].pf_ptl_mai); + } + free(ptl_mait->countries); + free(ptl_mait); + return 0; + } + { /* Transpose the array so we can use C indexing. */ + int level, vts; + for(level = 0; level < 8; level++) { + for(vts = 0; vts <= ptl_mait->nr_of_vtss; vts++) { + ptl_mait->countries[i].pf_ptl_mai[vts][level] = + pf_temp[(7-level)*(ptl_mait->nr_of_vtss+1) + vts]; + } + } + free(pf_temp); + } + } return 1; } - void ifoFree_PTL_MAIT(ifo_handle_t *ifofile) { + unsigned int i; + if(!ifofile) return; if(ifofile->ptl_mait) { + for(i = 0; i < ifofile->ptl_mait->nr_of_countries; i++) { + free(ifofile->ptl_mait->countries[i].pf_ptl_mai); + } free(ifofile->ptl_mait->countries); free(ifofile->ptl_mait); ifofile->ptl_mait = 0; } } +int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) { + vts_tmapt_t *vts_tmapt; + uint32_t *vts_tmap_srp; + unsigned int offset; + int info_length; + unsigned int i, j; + + if(!ifofile) + return 0; + + if(!ifofile->vtsi_mat) + return 0; + + if(ifofile->vtsi_mat->vts_tmapt == 0) { /* optional(?) */ + ifofile->vts_tmapt = NULL; + fprintf(stderr,"Please send bug report - no VTS_TMAPT ?? \n"); + return 1; + } + + offset = ifofile->vtsi_mat->vts_tmapt * DVD_BLOCK_LEN; + + if(!DVDFileSeek_(ifofile->file, offset)) + return 0; + + vts_tmapt = (vts_tmapt_t *)malloc(sizeof(vts_tmapt_t)); + if(!vts_tmapt) + return 0; + + ifofile->vts_tmapt = vts_tmapt; + + if(!(DVDReadBytes(ifofile->file, vts_tmapt, VTS_TMAPT_SIZE))) { + fprintf(stderr, "libdvdread: Unable to read VTS_TMAPT.\n"); + free(vts_tmapt); + ifofile->vts_tmapt = NULL; + return 0; + } + + B2N_16(vts_tmapt->nr_of_tmaps); + B2N_32(vts_tmapt->last_byte); + + CHECK_ZERO(vts_tmapt->zero_1); + + info_length = vts_tmapt->nr_of_tmaps * 4; + + vts_tmap_srp = (uint32_t *)malloc(info_length); + if(!vts_tmap_srp) { + free(vts_tmapt); + ifofile->vts_tmapt = NULL; + return 0; + } + + vts_tmapt->tmap_offset = vts_tmap_srp; + + if(!(DVDReadBytes(ifofile->file, vts_tmap_srp, info_length))) { + fprintf(stderr, "libdvdread: Unable to read VTS_TMAPT.\n"); + free(vts_tmap_srp); + free(vts_tmapt); + ifofile->vts_tmapt = NULL; + return 0; + } + + for (i = 0; i < vts_tmapt->nr_of_tmaps; i++) { + B2N_32(vts_tmap_srp[i]); + } + + + info_length = vts_tmapt->nr_of_tmaps * sizeof(vts_tmap_t); + + vts_tmapt->tmap = (vts_tmap_t *)malloc(info_length); + if(!vts_tmapt->tmap) { + free(vts_tmap_srp); + free(vts_tmapt); + ifofile->vts_tmapt = NULL; + return 0; + } + + memset(vts_tmapt->tmap, 0, info_length); /* So ifoFree_VTS_TMAPT works. */ + + for(i = 0; i < vts_tmapt->nr_of_tmaps; i++) { + if(!DVDFileSeek_(ifofile->file, offset + vts_tmap_srp[i])) { + ifoFree_VTS_TMAPT(ifofile); + return 0; + } + + if(!(DVDReadBytes(ifofile->file, &vts_tmapt->tmap[i], VTS_TMAP_SIZE))) { + fprintf(stderr, "libdvdread: Unable to read VTS_TMAP.\n"); + ifoFree_VTS_TMAPT(ifofile); + return 0; + } + + B2N_16(vts_tmapt->tmap[i].nr_of_entries); + CHECK_ZERO(vts_tmapt->tmap[i].zero_1); + + if(vts_tmapt->tmap[i].nr_of_entries == 0) { /* Early out if zero entries */ + vts_tmapt->tmap[i].map_ent = NULL; + continue; + } + + info_length = vts_tmapt->tmap[i].nr_of_entries * sizeof(map_ent_t); + + vts_tmapt->tmap[i].map_ent = (map_ent_t *)malloc(info_length); + if(!vts_tmapt->tmap[i].map_ent) { + ifoFree_VTS_TMAPT(ifofile); + return 0; + } + + if(!(DVDReadBytes(ifofile->file, vts_tmapt->tmap[i].map_ent, info_length))) { + fprintf(stderr, "libdvdread: Unable to read VTS_TMAP_ENT.\n"); + ifoFree_VTS_TMAPT(ifofile); + return 0; + } + + for(j = 0; j < vts_tmapt->tmap[i].nr_of_entries; j++) + B2N_32(vts_tmapt->tmap[i].map_ent[j]); + } + + return 1; +} + +void ifoFree_VTS_TMAPT(ifo_handle_t *ifofile) { + unsigned int i; + + if(!ifofile) + return; + + if(ifofile->vts_tmapt) { + for(i = 0; i < ifofile->vts_tmapt->nr_of_tmaps; i++) + if(ifofile->vts_tmapt->tmap[i].map_ent) + free(ifofile->vts_tmapt->tmap[i].map_ent); + free(ifofile->vts_tmapt->tmap); + free(ifofile->vts_tmapt->tmap_offset); + free(ifofile->vts_tmapt); + ifofile->vts_tmapt = NULL; + } +} + + int ifoRead_TITLE_C_ADT(ifo_handle_t *ifofile) { if(!ifofile) @@ -1168,7 +1386,7 @@ static int ifoRead_C_ADT_internal(ifo_handle_t *ifofile, /* assert(c_adt->nr_of_vobs > 0); Magic Knight Rayearth Daybreak is mastered very strange and has Titles with a VOBS that has no cells. */ - assert(info_length % sizeof(cell_adr_t) == 0); + CHECK_VALUE(info_length % sizeof(cell_adr_t) == 0); /* assert(info_length / sizeof(cell_adr_t) >= c_adt->nr_of_vobs); Enemy of the State region 2 (de) has Titles where nr_of_vobs field @@ -1194,10 +1412,10 @@ static int ifoRead_C_ADT_internal(ifo_handle_t *ifofile, B2N_32(c_adt->cell_adr_table[i].last_sector); CHECK_ZERO(c_adt->cell_adr_table[i].zero_1); - assert(c_adt->cell_adr_table[i].vob_id > 0); - assert(c_adt->cell_adr_table[i].vob_id <= c_adt->nr_of_vobs); - assert(c_adt->cell_adr_table[i].cell_id > 0); - assert(c_adt->cell_adr_table[i].start_sector < + CHECK_VALUE(c_adt->cell_adr_table[i].vob_id > 0); + CHECK_VALUE(c_adt->cell_adr_table[i].vob_id <= c_adt->nr_of_vobs); + CHECK_VALUE(c_adt->cell_adr_table[i].cell_id > 0); + CHECK_VALUE(c_adt->cell_adr_table[i].start_sector < c_adt->cell_adr_table[i].last_sector); } @@ -1301,7 +1519,7 @@ static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile, /* assert(info_length > 0); Magic Knight Rayearth Daybreak is mastered very strange and has Titles with a VOBS that has no VOBUs. */ - assert(info_length % sizeof(uint32_t) == 0); + CHECK_VALUE(info_length % sizeof(uint32_t) == 0); vobu_admap->vobu_start_sectors = (uint32_t *)malloc(info_length); if(!vobu_admap->vobu_start_sectors) { @@ -1387,7 +1605,7 @@ static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit, /* assert(pgcit->nr_of_pgci_srp != 0); Magic Knight Rayearth Daybreak is mastered very strange and has Titles with 0 PTTs. */ - assert(pgcit->nr_of_pgci_srp < 10000); // ?? seen max of 1338 + CHECK_VALUE(pgcit->nr_of_pgci_srp < 10000); // ?? seen max of 1338 info_length = pgcit->nr_of_pgci_srp * PGCI_SRP_SIZE; data = malloc(info_length); @@ -1410,12 +1628,12 @@ static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit, ptr += PGCI_LU_SIZE; B2N_16(pgcit->pgci_srp[i].ptl_id_mask); B2N_32(pgcit->pgci_srp[i].pgc_start_byte); - assert(pgcit->pgci_srp[i].unknown1 == 0); + CHECK_VALUE(pgcit->pgci_srp[i].unknown1 == 0); } free(data); for(i = 0; i < pgcit->nr_of_pgci_srp; i++) - assert(pgcit->pgci_srp[i].pgc_start_byte + PGC_SIZE <= pgcit->last_byte+1); + CHECK_VALUE(pgcit->pgci_srp[i].pgc_start_byte + PGC_SIZE <= pgcit->last_byte+1); for(i = 0; i < pgcit->nr_of_pgci_srp; i++) { pgcit->pgci_srp[i].pgc = malloc(sizeof(pgc_t)); @@ -1507,9 +1725,9 @@ int ifoRead_PGCI_UT(ifo_handle_t *ifofile) { B2N_32(pgci_ut->last_byte); CHECK_ZERO(pgci_ut->zero_1); - assert(pgci_ut->nr_of_lus != 0); - assert(pgci_ut->nr_of_lus < 100); // ?? 3-4 ? - assert((uint32_t)pgci_ut->nr_of_lus * PGCI_LU_SIZE < pgci_ut->last_byte); + CHECK_VALUE(pgci_ut->nr_of_lus != 0); + CHECK_VALUE(pgci_ut->nr_of_lus < 100); // ?? 3-4 ? + CHECK_VALUE((uint32_t)pgci_ut->nr_of_lus * PGCI_LU_SIZE < pgci_ut->last_byte); info_length = pgci_ut->nr_of_lus * PGCI_LU_SIZE; data = malloc(info_length); @@ -1542,7 +1760,6 @@ int ifoRead_PGCI_UT(ifo_handle_t *ifofile) { free(data); for(i = 0; i < pgci_ut->nr_of_lus; i++) { - CHECK_ZERO(pgci_ut->lu[i].zero_1); // Maybe this is only defined for v1.1 and later titles? /* If the bits in 'lu[i].exists' are enumerated abcd efgh then: VTS_x_yy.IFO VIDEO_TS.IFO @@ -1552,7 +1769,7 @@ int ifoRead_PGCI_UT(ifo_handle_t *ifofile) { d == 0x86 "Angle" e == 0x87 "PTT" */ - assert((pgci_ut->lu[i].exists & 0x07) == 0); + CHECK_VALUE((pgci_ut->lu[i].exists & 0x07) == 0); } for(i = 0; i < pgci_ut->nr_of_lus; i++) { @@ -1634,21 +1851,21 @@ static int ifoRead_VTS_ATTRIBUTES(ifo_handle_t *ifofile, CHECK_ZERO(vts_attributes->zero_5); CHECK_ZERO(vts_attributes->zero_6); CHECK_ZERO(vts_attributes->zero_7); - assert(vts_attributes->nr_of_vtsm_audio_streams <= 1); - assert(vts_attributes->nr_of_vtsm_subp_streams <= 1); - assert(vts_attributes->nr_of_vtstt_audio_streams <= 8); + CHECK_VALUE(vts_attributes->nr_of_vtsm_audio_streams <= 1); + CHECK_VALUE(vts_attributes->nr_of_vtsm_subp_streams <= 1); + CHECK_VALUE(vts_attributes->nr_of_vtstt_audio_streams <= 8); for(i = vts_attributes->nr_of_vtstt_audio_streams; i < 8; i++) CHECK_ZERO(vts_attributes->vtstt_audio_attr[i]); - assert(vts_attributes->nr_of_vtstt_subp_streams <= 32); + CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= 32); { unsigned int nr_coded; - assert(vts_attributes->last_byte + 1 >= VTS_ATTRIBUTES_MIN_SIZE); + CHECK_VALUE(vts_attributes->last_byte + 1 >= VTS_ATTRIBUTES_MIN_SIZE); nr_coded = (vts_attributes->last_byte + 1 - VTS_ATTRIBUTES_MIN_SIZE)/6; // This is often nr_coded = 70, how do you know how many there really are? if(nr_coded > 32) { // We haven't read more from disk/file anyway nr_coded = 32; } - assert(vts_attributes->nr_of_vtstt_subp_streams <= nr_coded); + CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= nr_coded); for(i = vts_attributes->nr_of_vtstt_subp_streams; i < nr_coded; i++) CHECK_ZERO(vts_attributes->vtstt_subp_attr[i]); } @@ -1692,9 +1909,9 @@ int ifoRead_VTS_ATRT(ifo_handle_t *ifofile) { B2N_32(vts_atrt->last_byte); CHECK_ZERO(vts_atrt->zero_1); - assert(vts_atrt->nr_of_vtss != 0); - assert(vts_atrt->nr_of_vtss < 100); //?? - assert((uint32_t)vts_atrt->nr_of_vtss * (4 + VTS_ATTRIBUTES_MIN_SIZE) + + CHECK_VALUE(vts_atrt->nr_of_vtss != 0); + CHECK_VALUE(vts_atrt->nr_of_vtss < 100); //?? + CHECK_VALUE((uint32_t)vts_atrt->nr_of_vtss * (4 + VTS_ATTRIBUTES_MIN_SIZE) + VTS_ATRT_SIZE < vts_atrt->last_byte + 1); info_length = vts_atrt->nr_of_vtss * sizeof(uint32_t); @@ -1704,6 +1921,9 @@ int ifoRead_VTS_ATRT(ifo_handle_t *ifofile) { ifofile->vts_atrt = 0; return 0; } + + vts_atrt->vts_atrt_offsets = data; + if(!(DVDReadBytes(ifofile->file, data, info_length))) { free(data); free(vts_atrt); @@ -1713,7 +1933,7 @@ int ifoRead_VTS_ATRT(ifo_handle_t *ifofile) { for(i = 0; i < vts_atrt->nr_of_vtss; i++) { B2N_32(data[i]); - assert(data[i] + VTS_ATTRIBUTES_MIN_SIZE < vts_atrt->last_byte + 1); + CHECK_VALUE(data[i] + VTS_ATTRIBUTES_MIN_SIZE < vts_atrt->last_byte + 1); } info_length = vts_atrt->nr_of_vtss * sizeof(vts_attributes_t); @@ -1735,10 +1955,9 @@ int ifoRead_VTS_ATRT(ifo_handle_t *ifofile) { } // This assert cant be in ifoRead_VTS_ATTRIBUTES - assert(offset + vts_atrt->vts[i].last_byte <= vts_atrt->last_byte + 1); + CHECK_VALUE(offset + vts_atrt->vts[i].last_byte <= vts_atrt->last_byte + 1); // Is this check correct? } - free(data); return 1; } @@ -1750,6 +1969,7 @@ void ifoFree_VTS_ATRT(ifo_handle_t *ifofile) { if(ifofile->vts_atrt) { free(ifofile->vts_atrt->vts); + free(ifofile->vts_atrt->vts_atrt_offsets); free(ifofile->vts_atrt); ifofile->vts_atrt = 0; } |