summaryrefslogtreecommitdiffstats
path: root/contrib/libdvdread
diff options
context:
space:
mode:
authorjstebbins <[email protected]>2009-11-13 19:02:25 +0000
committerjstebbins <[email protected]>2009-11-13 19:02:25 +0000
commit02319f0ceea9851fea57862f371dffc4efd031b4 (patch)
tree2744c8330436eb59982768a7d625edc8bb987b15 /contrib/libdvdread
parent72b19f8fa2bae0e1e08fc0cb883d335b382b8173 (diff)
handle duplicate language units and pgc's more gracefully
some discs have large numbers of repeated language units and pgc's that cause memory consumption and file i/o issues. detect such repeats and ref-count the data structures to avoid reading and storing duplicate info. git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@2924 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'contrib/libdvdread')
-rw-r--r--contrib/libdvdread/A01-check-nr_of_lus.patch17
-rw-r--r--contrib/libdvdread/A04-dup-lut-pgc.patch324
2 files changed, 324 insertions, 17 deletions
diff --git a/contrib/libdvdread/A01-check-nr_of_lus.patch b/contrib/libdvdread/A01-check-nr_of_lus.patch
deleted file mode 100644
index d49fb9499..000000000
--- a/contrib/libdvdread/A01-check-nr_of_lus.patch
+++ /dev/null
@@ -1,17 +0,0 @@
-diff -Naur libdvdread.orig/src/ifo_read.c libdvdread/src/ifo_read.c
---- libdvdread.orig/src/ifo_read.c 2009-01-08 14:57:10.000000000 -0800
-+++ libdvdread/src/ifo_read.c 2009-06-27 13:22:27.940241400 -0700
-@@ -1914,6 +1914,13 @@
- 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);
-
-+ if (pgci_ut->nr_of_lus == 0 || pgci_ut->nr_of_lus >= 100)
-+ {
-+ free(pgci_ut);
-+ ifofile->pgci_ut = 0;
-+ return 0;
-+ }
-+
- info_length = pgci_ut->nr_of_lus * PGCI_LU_SIZE;
- data = malloc(info_length);
- if(!data) {
diff --git a/contrib/libdvdread/A04-dup-lut-pgc.patch b/contrib/libdvdread/A04-dup-lut-pgc.patch
new file mode 100644
index 000000000..cf34419f7
--- /dev/null
+++ b/contrib/libdvdread/A04-dup-lut-pgc.patch
@@ -0,0 +1,324 @@
+--- libdvdread.orig/src/ifo_read.c 2009-10-29 09:11:32.066743831 -0700
++++ libdvdread/src/ifo_read.c 2009-11-13 10:27:49.293174360 -0800
+@@ -87,9 +87,9 @@
+ static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit,
+ unsigned int offset);
+
+-static void ifoFree_PGC(pgc_t *pgc);
++static void ifoFree_PGC(pgc_t **pgc);
+ static void ifoFree_PGC_COMMAND_TBL(pgc_command_tbl_t *cmd_tbl);
+-static void ifoFree_PGCIT_internal(pgcit_t *pgcit);
++static void ifoFree_PGCIT_internal(pgcit_t **pgcit);
+
+ static inline int DVDFileSeekForce_( dvd_file_t *dvd_file, uint32_t offset, int force_size ) {
+ return (DVDFileSeekForce(dvd_file, (int)offset, force_size) == (int)offset);
+@@ -870,7 +870,6 @@
+
+ if(!ifoRead_PGC_COMMAND_TBL(ifofile, pgc->command_tbl,
+ offset + pgc->command_tbl_offset)) {
+- free(pgc->command_tbl);
+ return 0;
+ }
+ } else {
+@@ -880,13 +879,10 @@
+ if(pgc->program_map_offset != 0 && pgc->nr_of_programs>0) {
+ pgc->program_map = malloc(pgc->nr_of_programs * sizeof(pgc_program_map_t));
+ if(!pgc->program_map) {
+- ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
+ return 0;
+ }
+ if(!ifoRead_PGC_PROGRAM_MAP(ifofile, pgc->program_map,pgc->nr_of_programs,
+ offset + pgc->program_map_offset)) {
+- ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
+- free(pgc->program_map);
+ return 0;
+ }
+ } else {
+@@ -896,18 +892,11 @@
+ if(pgc->cell_playback_offset != 0 && pgc->nr_of_cells>0) {
+ pgc->cell_playback = malloc(pgc->nr_of_cells * sizeof(cell_playback_t));
+ if(!pgc->cell_playback) {
+- ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
+- if(pgc->program_map)
+- free(pgc->program_map);
+ return 0;
+ }
+ if(!ifoRead_CELL_PLAYBACK_TBL(ifofile, pgc->cell_playback,
+ pgc->nr_of_cells,
+ offset + pgc->cell_playback_offset)) {
+- ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
+- if(pgc->program_map)
+- free(pgc->program_map);
+- free(pgc->cell_playback);
+ return 0;
+ }
+ } else {
+@@ -917,13 +906,11 @@
+ if(pgc->cell_position_offset != 0 && pgc->nr_of_cells>0) {
+ pgc->cell_position = malloc(pgc->nr_of_cells * sizeof(cell_position_t));
+ if(!pgc->cell_position) {
+- ifoFree_PGC(pgc);
+ return 0;
+ }
+ if(!ifoRead_CELL_POSITION_TBL(ifofile, pgc->cell_position,
+ pgc->nr_of_cells,
+ offset + pgc->cell_position_offset)) {
+- ifoFree_PGC(pgc);
+ return 0;
+ }
+ } else {
+@@ -946,29 +933,33 @@
+ if(ifofile->vmgi_mat->first_play_pgc == 0)
+ return 1;
+
+- ifofile->first_play_pgc = (pgc_t *)malloc(sizeof(pgc_t));
++ ifofile->first_play_pgc = (pgc_t *)calloc(1, sizeof(pgc_t));
+ if(!ifofile->first_play_pgc)
+ return 0;
+
++ ifofile->first_play_pgc->ref_count = 1;
+ if(!ifoRead_PGC(ifofile, ifofile->first_play_pgc,
+ ifofile->vmgi_mat->first_play_pgc)) {
+- free(ifofile->first_play_pgc);
+- ifofile->first_play_pgc = 0;
++ ifoFree_PGC(&ifofile->first_play_pgc);
+ return 0;
+ }
+
+ return 1;
+ }
+
+-static void ifoFree_PGC(pgc_t *pgc) {
+- if(pgc) {
+- ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
+- if(pgc->program_map)
+- free(pgc->program_map);
+- if(pgc->cell_playback)
+- free(pgc->cell_playback);
+- if(pgc->cell_position)
+- free(pgc->cell_position);
++static void ifoFree_PGC(pgc_t **pgc) {
++ if(pgc && *pgc && (--(*pgc)->ref_count) <= 0) {
++ ifoFree_PGC_COMMAND_TBL((*pgc)->command_tbl);
++ if((*pgc)->program_map)
++ free((*pgc)->program_map);
++ if((*pgc)->cell_playback)
++ free((*pgc)->cell_playback);
++ if((*pgc)->cell_position)
++ free((*pgc)->cell_position);
++ free(*pgc);
++ }
++ if (pgc) {
++ *pgc = NULL;
+ }
+ }
+
+@@ -977,9 +968,7 @@
+ return;
+
+ if(ifofile->first_play_pgc) {
+- ifoFree_PGC(ifofile->first_play_pgc);
+- free(ifofile->first_play_pgc);
+- ifofile->first_play_pgc = 0;
++ ifoFree_PGC(&ifofile->first_play_pgc);
+ }
+ }
+
+@@ -1202,6 +1191,13 @@
+ 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); /* ?? */
++ if (vts_ptt_srpt->title[i].ptt[j].pgcn == 0 ||
++ vts_ptt_srpt->title[i].ptt[j].pgcn >= 1000 ||
++ vts_ptt_srpt->title[i].ptt[j].pgn == 0 ||
++ vts_ptt_srpt->title[i].ptt[j].pgn >= 100) {
++ return 0;
++ }
++
+ }
+ }
+
+@@ -1372,7 +1368,6 @@
+
+ if(ifofile->vtsi_mat->vts_tmapt == 0) { /* optional(?) */
+ ifofile->vts_tmapt = NULL;
+- fprintf(stderr,"Please send bug report - no VTS_TMAPT ?? \n");
+ return 1;
+ }
+
+@@ -1756,10 +1751,11 @@
+ if(ifofile->vtsi_mat->vts_pgcit == 0) /* mandatory */
+ return 0;
+
+- ifofile->vts_pgcit = (pgcit_t *)malloc(sizeof(pgcit_t));
++ ifofile->vts_pgcit = (pgcit_t *)calloc(1, sizeof(pgcit_t));
+ if(!ifofile->vts_pgcit)
+ return 0;
+
++ ifofile->vts_pgcit->ref_count = 1;
+ if(!ifoRead_PGCIT_internal(ifofile, ifofile->vts_pgcit,
+ ifofile->vtsi_mat->vts_pgcit * DVD_BLOCK_LEN)) {
+ free(ifofile->vts_pgcit);
+@@ -1770,6 +1766,17 @@
+ return 1;
+ }
+
++static int find_dup_pgc(pgci_srp_t *pgci_srp, uint32_t start_byte, int count) {
++ int i;
++
++ for(i = 0; i < count; i++) {
++ if(pgci_srp[i].pgc_start_byte == start_byte) {
++ return i;
++ }
++ }
++ return -1;
++}
++
+ static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit,
+ unsigned int offset) {
+ int i, info_length;
+@@ -1818,21 +1825,26 @@
+ 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));
++ int dup;
++ if((dup = find_dup_pgc(pgcit->pgci_srp, pgcit->pgci_srp[i].pgc_start_byte, i)) >= 0) {
++ pgcit->pgci_srp[i].pgc = pgcit->pgci_srp[dup].pgc;
++ pgcit->pgci_srp[i].pgc->ref_count++;
++ continue;
++ }
++ pgcit->pgci_srp[i].pgc = calloc(1, sizeof(pgc_t));
+ if(!pgcit->pgci_srp[i].pgc) {
+ int j;
+ for(j = 0; j < i; j++) {
+- ifoFree_PGC(pgcit->pgci_srp[j].pgc);
+- free(pgcit->pgci_srp[j].pgc);
++ ifoFree_PGC(&pgcit->pgci_srp[j].pgc);
+ }
+ goto fail;
+ }
++ pgcit->pgci_srp[i].pgc->ref_count = 1;
+ if(!ifoRead_PGC(ifofile, pgcit->pgci_srp[i].pgc,
+ offset + pgcit->pgci_srp[i].pgc_start_byte)) {
+ int j;
+- for(j = 0; j < i; j++) {
+- ifoFree_PGC(pgcit->pgci_srp[j].pgc);
+- free(pgcit->pgci_srp[j].pgc);
++ for(j = 0; j <= i; j++) {
++ ifoFree_PGC(&pgcit->pgci_srp[j].pgc);
+ }
+ goto fail;
+ }
+@@ -1845,12 +1857,16 @@
+ return 0;
+ }
+
+-static void ifoFree_PGCIT_internal(pgcit_t *pgcit) {
+- if(pgcit) {
++static void ifoFree_PGCIT_internal(pgcit_t **pgcit) {
++ if(pgcit && *pgcit && (--(*pgcit)->ref_count <= 0)) {
+ int i;
+- for(i = 0; i < pgcit->nr_of_pgci_srp; i++)
+- ifoFree_PGC(pgcit->pgci_srp[i].pgc);
+- free(pgcit->pgci_srp);
++ for(i = 0; i < (*pgcit)->nr_of_pgci_srp; i++)
++ ifoFree_PGC(&(*pgcit)->pgci_srp[i].pgc);
++ free((*pgcit)->pgci_srp);
++ free(*pgcit);
++ }
++ if (pgcit) {
++ *pgcit = NULL;
+ }
+ }
+
+@@ -1859,12 +1875,20 @@
+ return;
+
+ if(ifofile->vts_pgcit) {
+- ifoFree_PGCIT_internal(ifofile->vts_pgcit);
+- free(ifofile->vts_pgcit);
+- ifofile->vts_pgcit = 0;
++ ifoFree_PGCIT_internal(&ifofile->vts_pgcit);
+ }
+ }
+
++static int find_dup_lut(pgci_lu_t *lu, uint32_t start_byte, int count) {
++ int i;
++
++ for(i = 0; i < count; i++) {
++ if(lu[i].lang_start_byte == start_byte) {
++ return i;
++ }
++ }
++ return -1;
++}
+
+ int ifoRead_PGCI_UT(ifo_handle_t *ifofile) {
+ pgci_ut_t *pgci_ut;
+@@ -1958,27 +1982,31 @@
+ }
+
+ for(i = 0; i < pgci_ut->nr_of_lus; i++) {
++ int dup;
++ if((dup = find_dup_lut(pgci_ut->lu, pgci_ut->lu[i].lang_start_byte, i)) >= 0) {
++ pgci_ut->lu[i].pgcit = pgci_ut->lu[dup].pgcit;
++ pgci_ut->lu[i].pgcit->ref_count++;
++ continue;
++ }
+ pgci_ut->lu[i].pgcit = malloc(sizeof(pgcit_t));
+ if(!pgci_ut->lu[i].pgcit) {
+ unsigned int j;
+ for(j = 0; j < i; j++) {
+- ifoFree_PGCIT_internal(pgci_ut->lu[j].pgcit);
+- free(pgci_ut->lu[j].pgcit);
++ ifoFree_PGCIT_internal(&pgci_ut->lu[j].pgcit);
+ }
+ free(pgci_ut->lu);
+ free(pgci_ut);
+ ifofile->pgci_ut = 0;
+ return 0;
+ }
++ pgci_ut->lu[i].pgcit->ref_count = 1;
+ if(!ifoRead_PGCIT_internal(ifofile, pgci_ut->lu[i].pgcit,
+ sector * DVD_BLOCK_LEN
+ + pgci_ut->lu[i].lang_start_byte)) {
+ unsigned int j;
+- for(j = 0; j < i; j++) {
+- ifoFree_PGCIT_internal(pgci_ut->lu[j].pgcit);
+- free(pgci_ut->lu[j].pgcit);
++ for(j = 0; j <= i; j++) {
++ ifoFree_PGCIT_internal(&pgci_ut->lu[j].pgcit);
+ }
+- free(pgci_ut->lu[i].pgcit);
+ free(pgci_ut->lu);
+ free(pgci_ut);
+ ifofile->pgci_ut = 0;
+@@ -2000,8 +2028,7 @@
+
+ if(ifofile->pgci_ut) {
+ for(i = 0; i < ifofile->pgci_ut->nr_of_lus; i++) {
+- ifoFree_PGCIT_internal(ifofile->pgci_ut->lu[i].pgcit);
+- free(ifofile->pgci_ut->lu[i].pgcit);
++ ifoFree_PGCIT_internal(&ifofile->pgci_ut->lu[i].pgcit);
+ }
+ free(ifofile->pgci_ut->lu);
+ free(ifofile->pgci_ut);
+--- libdvdread.orig/src/dvdread/ifo_types.h 2009-10-29 09:11:32.161557143 -0700
++++ libdvdread/src/dvdread/ifo_types.h 2009-11-13 09:13:10.255237710 -0800
+@@ -301,6 +301,7 @@
+ pgc_program_map_t *program_map;
+ cell_playback_t *cell_playback;
+ cell_position_t *cell_position;
++ int ref_count;
+ } ATTRIBUTE_PACKED pgc_t;
+ #define PGC_SIZE 236U
+
+@@ -326,6 +327,7 @@
+ uint16_t zero_1;
+ uint32_t last_byte;
+ pgci_srp_t *pgci_srp;
++ int ref_count;
+ } ATTRIBUTE_PACKED pgcit_t;
+ #define PGCIT_SIZE 8U
+