summaryrefslogtreecommitdiffstats
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
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
-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
+