OSDN Git Service

handle duplicate language units and pgc's more gracefully
[handbrake-jp/handbrake-jp-git.git] / contrib / libdvdread / A04-dup-lut-pgc.patch
1 --- libdvdread.orig/src/ifo_read.c      2009-10-29 09:11:32.066743831 -0700
2 +++ libdvdread/src/ifo_read.c   2009-11-13 10:27:49.293174360 -0800
3 @@ -87,9 +87,9 @@
4  static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit,
5                                    unsigned int offset);
6  
7 -static void ifoFree_PGC(pgc_t *pgc);
8 +static void ifoFree_PGC(pgc_t **pgc);
9  static void ifoFree_PGC_COMMAND_TBL(pgc_command_tbl_t *cmd_tbl);
10 -static void ifoFree_PGCIT_internal(pgcit_t *pgcit);
11 +static void ifoFree_PGCIT_internal(pgcit_t **pgcit);
12  
13  static inline int DVDFileSeekForce_( dvd_file_t *dvd_file, uint32_t offset, int force_size ) {
14    return (DVDFileSeekForce(dvd_file, (int)offset, force_size) == (int)offset);
15 @@ -870,7 +870,6 @@
16  
17      if(!ifoRead_PGC_COMMAND_TBL(ifofile, pgc->command_tbl,
18                                  offset + pgc->command_tbl_offset)) {
19 -      free(pgc->command_tbl);
20        return 0;
21      }
22    } else {
23 @@ -880,13 +879,10 @@
24    if(pgc->program_map_offset != 0 && pgc->nr_of_programs>0) {
25      pgc->program_map = malloc(pgc->nr_of_programs * sizeof(pgc_program_map_t));
26      if(!pgc->program_map) {
27 -      ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
28        return 0;
29      }
30      if(!ifoRead_PGC_PROGRAM_MAP(ifofile, pgc->program_map,pgc->nr_of_programs,
31                                  offset + pgc->program_map_offset)) {
32 -      ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
33 -      free(pgc->program_map);
34        return 0;
35      }
36    } else {
37 @@ -896,18 +892,11 @@
38    if(pgc->cell_playback_offset != 0 && pgc->nr_of_cells>0) {
39      pgc->cell_playback = malloc(pgc->nr_of_cells * sizeof(cell_playback_t));
40      if(!pgc->cell_playback) {
41 -      ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
42 -      if(pgc->program_map)
43 -        free(pgc->program_map);
44        return 0;
45      }
46      if(!ifoRead_CELL_PLAYBACK_TBL(ifofile, pgc->cell_playback,
47                                    pgc->nr_of_cells,
48                                    offset + pgc->cell_playback_offset)) {
49 -      ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
50 -      if(pgc->program_map)
51 -        free(pgc->program_map);
52 -      free(pgc->cell_playback);
53        return 0;
54      }
55    } else {
56 @@ -917,13 +906,11 @@
57    if(pgc->cell_position_offset != 0 && pgc->nr_of_cells>0) {
58      pgc->cell_position = malloc(pgc->nr_of_cells * sizeof(cell_position_t));
59      if(!pgc->cell_position) {
60 -      ifoFree_PGC(pgc);
61        return 0;
62      }
63      if(!ifoRead_CELL_POSITION_TBL(ifofile, pgc->cell_position,
64                                    pgc->nr_of_cells,
65                                    offset + pgc->cell_position_offset)) {
66 -      ifoFree_PGC(pgc);
67        return 0;
68      }
69    } else {
70 @@ -946,29 +933,33 @@
71    if(ifofile->vmgi_mat->first_play_pgc == 0)
72      return 1;
73  
74 -  ifofile->first_play_pgc = (pgc_t *)malloc(sizeof(pgc_t));
75 +  ifofile->first_play_pgc = (pgc_t *)calloc(1, sizeof(pgc_t));
76    if(!ifofile->first_play_pgc)
77      return 0;
78  
79 +  ifofile->first_play_pgc->ref_count = 1;
80    if(!ifoRead_PGC(ifofile, ifofile->first_play_pgc,
81                    ifofile->vmgi_mat->first_play_pgc)) {
82 -    free(ifofile->first_play_pgc);
83 -    ifofile->first_play_pgc = 0;
84 +    ifoFree_PGC(&ifofile->first_play_pgc);
85      return 0;
86    }
87  
88    return 1;
89  }
90  
91 -static void ifoFree_PGC(pgc_t *pgc) {
92 -  if(pgc) {
93 -    ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
94 -    if(pgc->program_map)
95 -      free(pgc->program_map);
96 -    if(pgc->cell_playback)
97 -      free(pgc->cell_playback);
98 -    if(pgc->cell_position)
99 -      free(pgc->cell_position);
100 +static void ifoFree_PGC(pgc_t **pgc) {
101 +  if(pgc && *pgc && (--(*pgc)->ref_count) <= 0) {
102 +    ifoFree_PGC_COMMAND_TBL((*pgc)->command_tbl);
103 +    if((*pgc)->program_map)
104 +      free((*pgc)->program_map);
105 +    if((*pgc)->cell_playback)
106 +      free((*pgc)->cell_playback);
107 +    if((*pgc)->cell_position)
108 +      free((*pgc)->cell_position);
109 +    free(*pgc);
110 +  }
111 +  if (pgc) {
112 +    *pgc = NULL;
113    }
114  }
115  
116 @@ -977,9 +968,7 @@
117      return;
118  
119    if(ifofile->first_play_pgc) {
120 -    ifoFree_PGC(ifofile->first_play_pgc);
121 -    free(ifofile->first_play_pgc);
122 -    ifofile->first_play_pgc = 0;
123 +    ifoFree_PGC(&ifofile->first_play_pgc);
124    }
125  }
126  
127 @@ -1202,6 +1191,13 @@
128        CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn < 1000); /* ?? */
129        CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn != 0);
130        CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn < 100); /* ?? */
131 +      if (vts_ptt_srpt->title[i].ptt[j].pgcn == 0 ||
132 +          vts_ptt_srpt->title[i].ptt[j].pgcn >= 1000 ||
133 +          vts_ptt_srpt->title[i].ptt[j].pgn == 0 ||
134 +          vts_ptt_srpt->title[i].ptt[j].pgn >= 100) {
135 +        return 0;
136 +      }
137 +
138      }
139    }
140  
141 @@ -1372,7 +1368,6 @@
142  
143    if(ifofile->vtsi_mat->vts_tmapt == 0) { /* optional(?) */
144      ifofile->vts_tmapt = NULL;
145 -    fprintf(stderr,"Please send bug report - no VTS_TMAPT ?? \n");
146      return 1;
147    }
148  
149 @@ -1756,10 +1751,11 @@
150    if(ifofile->vtsi_mat->vts_pgcit == 0) /* mandatory */
151      return 0;
152  
153 -  ifofile->vts_pgcit = (pgcit_t *)malloc(sizeof(pgcit_t));
154 +  ifofile->vts_pgcit = (pgcit_t *)calloc(1, sizeof(pgcit_t));
155    if(!ifofile->vts_pgcit)
156      return 0;
157  
158 +  ifofile->vts_pgcit->ref_count = 1;
159    if(!ifoRead_PGCIT_internal(ifofile, ifofile->vts_pgcit,
160                               ifofile->vtsi_mat->vts_pgcit * DVD_BLOCK_LEN)) {
161      free(ifofile->vts_pgcit);
162 @@ -1770,6 +1766,17 @@
163    return 1;
164  }
165  
166 +static int find_dup_pgc(pgci_srp_t *pgci_srp, uint32_t start_byte, int count) {
167 +  int i;
168 +
169 +  for(i = 0; i < count; i++) {
170 +    if(pgci_srp[i].pgc_start_byte == start_byte) {
171 +      return i;
172 +    }
173 +  }
174 +  return -1;
175 +}
176 +
177  static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit,
178                                    unsigned int offset) {
179    int i, info_length;
180 @@ -1818,21 +1825,26 @@
181      CHECK_VALUE(pgcit->pgci_srp[i].pgc_start_byte + PGC_SIZE <= pgcit->last_byte+1);
182  
183    for(i = 0; i < pgcit->nr_of_pgci_srp; i++) {
184 -    pgcit->pgci_srp[i].pgc = malloc(sizeof(pgc_t));
185 +    int dup;
186 +    if((dup = find_dup_pgc(pgcit->pgci_srp, pgcit->pgci_srp[i].pgc_start_byte, i)) >= 0) {
187 +      pgcit->pgci_srp[i].pgc = pgcit->pgci_srp[dup].pgc;
188 +      pgcit->pgci_srp[i].pgc->ref_count++;
189 +      continue;
190 +    }
191 +    pgcit->pgci_srp[i].pgc = calloc(1, sizeof(pgc_t));
192      if(!pgcit->pgci_srp[i].pgc) {
193        int j;
194        for(j = 0; j < i; j++) {
195 -        ifoFree_PGC(pgcit->pgci_srp[j].pgc);
196 -        free(pgcit->pgci_srp[j].pgc);
197 +        ifoFree_PGC(&pgcit->pgci_srp[j].pgc);
198        }
199        goto fail;
200      }
201 +    pgcit->pgci_srp[i].pgc->ref_count = 1;
202      if(!ifoRead_PGC(ifofile, pgcit->pgci_srp[i].pgc,
203                      offset + pgcit->pgci_srp[i].pgc_start_byte)) {
204        int j;
205 -      for(j = 0; j < i; j++) {
206 -        ifoFree_PGC(pgcit->pgci_srp[j].pgc);
207 -        free(pgcit->pgci_srp[j].pgc);
208 +      for(j = 0; j <= i; j++) {
209 +        ifoFree_PGC(&pgcit->pgci_srp[j].pgc);
210        }
211        goto fail;
212      }
213 @@ -1845,12 +1857,16 @@
214    return 0;
215  }
216  
217 -static void ifoFree_PGCIT_internal(pgcit_t *pgcit) {
218 -  if(pgcit) {
219 +static void ifoFree_PGCIT_internal(pgcit_t **pgcit) {
220 +  if(pgcit && *pgcit && (--(*pgcit)->ref_count <= 0)) {
221      int i;
222 -    for(i = 0; i < pgcit->nr_of_pgci_srp; i++)
223 -      ifoFree_PGC(pgcit->pgci_srp[i].pgc);
224 -    free(pgcit->pgci_srp);
225 +    for(i = 0; i < (*pgcit)->nr_of_pgci_srp; i++)
226 +      ifoFree_PGC(&(*pgcit)->pgci_srp[i].pgc);
227 +    free((*pgcit)->pgci_srp);
228 +    free(*pgcit);
229 +  }
230 +  if (pgcit) {
231 +    *pgcit = NULL;
232    }
233  }
234  
235 @@ -1859,12 +1875,20 @@
236      return;
237  
238    if(ifofile->vts_pgcit) {
239 -    ifoFree_PGCIT_internal(ifofile->vts_pgcit);
240 -    free(ifofile->vts_pgcit);
241 -    ifofile->vts_pgcit = 0;
242 +    ifoFree_PGCIT_internal(&ifofile->vts_pgcit);
243    }
244  }
245  
246 +static int find_dup_lut(pgci_lu_t *lu, uint32_t start_byte, int count) {
247 +  int i;
248 +
249 +  for(i = 0; i < count; i++) {
250 +    if(lu[i].lang_start_byte == start_byte) {
251 +      return i;
252 +    }
253 +  }
254 +  return -1;
255 +}
256  
257  int ifoRead_PGCI_UT(ifo_handle_t *ifofile) {
258    pgci_ut_t *pgci_ut;
259 @@ -1958,27 +1982,31 @@
260    }
261  
262    for(i = 0; i < pgci_ut->nr_of_lus; i++) {
263 +    int dup;
264 +    if((dup = find_dup_lut(pgci_ut->lu, pgci_ut->lu[i].lang_start_byte, i)) >= 0) {
265 +      pgci_ut->lu[i].pgcit = pgci_ut->lu[dup].pgcit;
266 +      pgci_ut->lu[i].pgcit->ref_count++;
267 +      continue;
268 +    }
269      pgci_ut->lu[i].pgcit = malloc(sizeof(pgcit_t));
270      if(!pgci_ut->lu[i].pgcit) {
271        unsigned int j;
272        for(j = 0; j < i; j++) {
273 -        ifoFree_PGCIT_internal(pgci_ut->lu[j].pgcit);
274 -        free(pgci_ut->lu[j].pgcit);
275 +        ifoFree_PGCIT_internal(&pgci_ut->lu[j].pgcit);
276        }
277        free(pgci_ut->lu);
278        free(pgci_ut);
279        ifofile->pgci_ut = 0;
280        return 0;
281      }
282 +    pgci_ut->lu[i].pgcit->ref_count = 1;
283      if(!ifoRead_PGCIT_internal(ifofile, pgci_ut->lu[i].pgcit,
284                                 sector * DVD_BLOCK_LEN
285                                 + pgci_ut->lu[i].lang_start_byte)) {
286        unsigned int j;
287 -      for(j = 0; j < i; j++) {
288 -        ifoFree_PGCIT_internal(pgci_ut->lu[j].pgcit);
289 -        free(pgci_ut->lu[j].pgcit);
290 +      for(j = 0; j <= i; j++) {
291 +        ifoFree_PGCIT_internal(&pgci_ut->lu[j].pgcit);
292        }
293 -      free(pgci_ut->lu[i].pgcit);
294        free(pgci_ut->lu);
295        free(pgci_ut);
296        ifofile->pgci_ut = 0;
297 @@ -2000,8 +2028,7 @@
298  
299    if(ifofile->pgci_ut) {
300      for(i = 0; i < ifofile->pgci_ut->nr_of_lus; i++) {
301 -      ifoFree_PGCIT_internal(ifofile->pgci_ut->lu[i].pgcit);
302 -      free(ifofile->pgci_ut->lu[i].pgcit);
303 +      ifoFree_PGCIT_internal(&ifofile->pgci_ut->lu[i].pgcit);
304      }
305      free(ifofile->pgci_ut->lu);
306      free(ifofile->pgci_ut);
307 --- libdvdread.orig/src/dvdread/ifo_types.h     2009-10-29 09:11:32.161557143 -0700
308 +++ libdvdread/src/dvdread/ifo_types.h  2009-11-13 09:13:10.255237710 -0800
309 @@ -301,6 +301,7 @@
310    pgc_program_map_t  *program_map;
311    cell_playback_t *cell_playback;
312    cell_position_t *cell_position;
313 +  int      ref_count;
314  } ATTRIBUTE_PACKED pgc_t;
315  #define PGC_SIZE 236U
316  
317 @@ -326,6 +327,7 @@
318    uint16_t zero_1;
319    uint32_t last_byte;
320    pgci_srp_t *pgci_srp;
321 +  int      ref_count;
322  } ATTRIBUTE_PACKED pgcit_t;
323  #define PGCIT_SIZE 8U
324