OSDN Git Service

handle duplicate language units and pgc's more gracefully
authorjstebbins <jstebbins@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Fri, 13 Nov 2009 19:02:25 +0000 (19:02 +0000)
committerjstebbins <jstebbins@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Fri, 13 Nov 2009 19:02:25 +0000 (19:02 +0000)
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 [deleted file]
contrib/libdvdread/A04-dup-lut-pgc.patch [new file with mode: 0644]

diff --git a/contrib/libdvdread/A01-check-nr_of_lus.patch b/contrib/libdvdread/A01-check-nr_of_lus.patch
deleted file mode 100644 (file)
index d49fb94..0000000
+++ /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 (file)
index 0000000..cf34419
--- /dev/null
@@ -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