From 051f44db01a38d4f3e04631864353579925bb29b Mon Sep 17 00:00:00 2001 From: jstebbins Date: Fri, 13 Nov 2009 19:02:25 +0000 Subject: [PATCH] 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://localhost/HandBrake/trunk@2924 b64f7644-9d1e-0410-96f1-a4d463321fa5 --- contrib/libdvdread/A01-check-nr_of_lus.patch | 17 -- contrib/libdvdread/A04-dup-lut-pgc.patch | 324 +++++++++++++++++++++++++++ 2 files changed, 324 insertions(+), 17 deletions(-) delete mode 100644 contrib/libdvdread/A01-check-nr_of_lus.patch create mode 100644 contrib/libdvdread/A04-dup-lut-pgc.patch 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 d49fb949..00000000 --- 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 00000000..cf34419f --- /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 + -- 2.11.0