r996: add renderprofiles.C to POTFILES.in
[cinelerra_cv/mob.git] / libmpeg3 / mpeg3ifo.c
blobf0dd85eb54ee0418504c58fd68c6e5fa19bde5bd
1 #include <byteswap.h>
2 #include <dirent.h>
3 #include <fcntl.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <sys/types.h>
7 #include <unistd.h>
9 #include "ifo.h"
10 #include "mpeg3private.h"
11 #include "mpeg3protos.h"
13 typedef struct
15 // Bytes relative to start of stream.
16 int64_t start_byte;
17 int64_t end_byte;
18 // Used in final table
19 int program;
20 // Used in cell play info
21 int cell_type;
22 // Used in cell addresses
23 int vob_id;
24 int cell_id;
25 } mpeg3ifo_cell_t;
27 typedef struct
29 mpeg3ifo_cell_t *cells;
30 long total_cells;
31 long cells_allocated;
32 } mpeg3ifo_celltable_t;
35 #define CADDR_HDR_LEN 8
37 typedef struct {
38 u_short num : 16; // Number of Video Objects
39 u_short unknown : 16; // don't know
40 u_int len : 32; // length of table
41 } cell_addr_hdr_t;
43 typedef struct {
44 u_int foo : 16; // ???
45 u_int num : 16; // number of subchannels
46 } audio_hdr_t;
48 #define AUDIO_HDR_LEN 4
50 typedef struct {
51 u_short id : 16; // Language
52 u_short : 16; // don't know
53 u_int start : 32; // Start of unit
54 } pgci_sub_t;
56 #define PGCI_SUB_LEN 8
58 #define PGCI_COLOR_LEN 4
61 static u_int get4bytes(u_char *buf)
63 return bswap_32 (*((u_int32_t *)buf));
66 static u_int get2bytes(u_char *buf)
68 return bswap_16 (*((u_int16_t *)buf));
71 static int ifo_read(int fd, long pos, long count, unsigned char *data)
73 if((pos = lseek(fd, pos, SEEK_SET)) < 0)
75 perror("ifo_read");
76 return -1;
79 return read(fd, data, count);
82 #define OFF_PTT get4bytes (ifo->data[ID_MAT] + 0xC8)
83 #define OFF_TITLE_PGCI get4bytes (ifo->data[ID_MAT] + 0xCC)
84 #define OFF_MENU_PGCI get4bytes (ifo->data[ID_MAT] + 0xD0)
85 #define OFF_TMT get4bytes (ifo->data[ID_MAT] + 0xD4)
86 #define OFF_MENU_CELL_ADDR get4bytes (ifo->data[ID_MAT] + 0xD8)
87 #define OFF_MENU_VOBU_ADDR_MAP get4bytes (ifo->data[ID_MAT] + 0xDC)
88 #define OFF_TITLE_CELL_ADDR get4bytes (ifo->data[ID_MAT] + 0xE0)
89 #define OFF_TITLE_VOBU_ADDR_MAP get4bytes (ifo->data[ID_MAT] + 0xE4)
91 #define OFF_VMG_TSP get4bytes (ifo->data[ID_MAT] + 0xC4)
92 #define OFF_VMG_MENU_PGCI get4bytes (ifo->data[ID_MAT] + 0xC8)
93 #define OFF_VMG_TMT get4bytes (ifo->data[ID_MAT] + 0xD0)
96 static int ifo_vts(ifo_t *ifo)
98 if(!strncmp((char*)ifo->data[ID_MAT], "DVDVIDEO-VTS", 12))
99 return 0;
101 return -1;
105 static int ifo_vmg(ifo_t *ifo)
107 if(!strncmp((char*)ifo->data[ID_MAT], "DVDVIDEO-VMG", 12))
108 return 0;
110 return -1;
113 static int ifo_table(ifo_t *ifo, int64_t offset, unsigned long tbl_id)
115 unsigned char *data;
116 int64_t len = 0;
117 int i;
118 u_int32_t *ptr;
120 if(!offset) return -1;
122 data = (u_char *)calloc(1, DVD_VIDEO_LB_LEN);
124 if(ifo_read(ifo->fd, ifo->pos + offset * DVD_VIDEO_LB_LEN, DVD_VIDEO_LB_LEN, data) <= 0)
126 perror("ifo_table");
127 return -1;
130 switch(tbl_id)
132 case ID_TITLE_VOBU_ADDR_MAP:
133 case ID_MENU_VOBU_ADDR_MAP:
134 len = get4bytes(data) + 1;
135 break;
137 default:
139 ifo_hdr_t *hdr = (ifo_hdr_t *)data;
140 len = bswap_32(hdr->len) + 1;
144 if(len > DVD_VIDEO_LB_LEN)
146 data = (u_char *)realloc((void *)data, len);
147 bzero(data, len);
148 ifo_read(ifo->fd, ifo->pos + offset * DVD_VIDEO_LB_LEN, len, data);
151 ifo->data[tbl_id] = data;
152 ptr = (u_int32_t*)data;
153 len /= 4;
155 if(tbl_id == ID_TMT)
156 for (i = 0; i < len; i++)
157 ptr[i] = bswap_32(ptr[i]);
159 return 0;
162 static ifo_t* ifo_open(int fd, long pos)
164 ifo_t *ifo;
166 ifo = (ifo_t *)calloc(sizeof(ifo_t), 1);
168 ifo->data[ID_MAT] = (unsigned char *)calloc(DVD_VIDEO_LB_LEN, 1);
170 ifo->pos = pos;
171 ifo->fd = fd;
173 if(ifo_read(fd, pos, DVD_VIDEO_LB_LEN, ifo->data[ID_MAT]) < 0)
175 perror("ifo_open");
176 free(ifo->data[ID_MAT]);
177 free(ifo);
178 return NULL;
181 ifo->num_menu_vobs = get4bytes(ifo->data[ID_MAT] + 0xC0);
182 ifo->vob_start = get4bytes(ifo->data[ID_MAT] + 0xC4);
184 #ifdef DEBUG
185 printf ("num of vobs: %x vob_start %x\n", ifo->num_menu_vobs, ifo->vob_start);
186 #endif
188 if(!ifo_vts(ifo))
190 ifo_table(ifo, OFF_PTT, ID_PTT);
191 ifo_table(ifo, OFF_TITLE_PGCI, ID_TITLE_PGCI);
192 ifo_table(ifo, OFF_MENU_PGCI, ID_MENU_PGCI);
193 ifo_table(ifo, OFF_TMT, ID_TMT);
194 ifo_table(ifo, OFF_MENU_CELL_ADDR, ID_MENU_CELL_ADDR);
195 ifo_table(ifo, OFF_MENU_VOBU_ADDR_MAP, ID_MENU_VOBU_ADDR_MAP);
196 ifo_table(ifo, OFF_TITLE_CELL_ADDR, ID_TITLE_CELL_ADDR);
197 ifo_table(ifo, OFF_TITLE_VOBU_ADDR_MAP, ID_TITLE_VOBU_ADDR_MAP);
199 else
200 if(!ifo_vmg(ifo))
202 ifo_table(ifo, OFF_VMG_TSP, ID_TSP);
203 ifo_table(ifo, OFF_VMG_MENU_PGCI, ID_MENU_PGCI);
204 ifo_table(ifo, OFF_VMG_TMT, ID_TMT);
205 ifo_table(ifo, OFF_TITLE_CELL_ADDR, ID_TITLE_CELL_ADDR);
206 ifo_table(ifo, OFF_TITLE_VOBU_ADDR_MAP, ID_TITLE_VOBU_ADDR_MAP);
209 return ifo;
213 static int ifo_close(ifo_t *ifo)
215 if(ifo->data[ID_MAT]) free(ifo->data[ID_MAT]);
216 if(ifo->data[ID_PTT]) free(ifo->data[ID_PTT]);
217 if(ifo->data[ID_TITLE_PGCI]) free(ifo->data[ID_TITLE_PGCI]);
218 if(ifo->data[ID_MENU_PGCI]) free(ifo->data[ID_MENU_PGCI]);
219 if(ifo->data[ID_TMT]) free(ifo->data[ID_TMT]);
220 if(ifo->data[ID_MENU_CELL_ADDR]) free(ifo->data[ID_MENU_CELL_ADDR]);
221 if(ifo->data[ID_MENU_VOBU_ADDR_MAP]) free(ifo->data[ID_MENU_VOBU_ADDR_MAP]);
222 if(ifo->data[ID_TITLE_CELL_ADDR]) free(ifo->data[ID_TITLE_CELL_ADDR]);
223 if(ifo->data[ID_TITLE_VOBU_ADDR_MAP]) free(ifo->data[ID_TITLE_VOBU_ADDR_MAP]);
225 free(ifo);
227 return 0;
230 static int ifo_audio(char *_hdr, char **ptr)
232 audio_hdr_t *hdr = (audio_hdr_t *)_hdr;
234 if(!_hdr) return -1;
236 *ptr = _hdr + AUDIO_HDR_LEN;
238 return bswap_16(hdr->num);
242 static int pgci(ifo_hdr_t *hdr, int title, char **ptr)
244 pgci_sub_t *pgci_sub;
246 *ptr = (char *) hdr;
248 if(!*ptr) return -1;
250 if(title > hdr->num) return -1;
252 *ptr += IFO_HDR_LEN;
254 pgci_sub = (pgci_sub_t *)*ptr + title;
256 *ptr = (char *)hdr + bswap_32(pgci_sub->start);
258 return 0;
261 static int program_map(mpeg3_t *file, char *pgc, unsigned char **ptr)
263 int num;
264 int i;
265 *ptr = pgc;
267 if (!pgc)
268 return -1;
270 *ptr += 2;
271 num = **ptr;
273 *ptr += 10;
274 *ptr += 8 * 2; // AUDIO
275 *ptr += 32 * 4; // SUBPICTURE
276 *ptr += 8;
277 // subtitle color palette
278 // *ptr += 16 * PGCI_COLOR_LEN;
280 if(!file->have_palette)
282 for(i = 0; i < 16; i++)
284 int r = (int)*(*ptr)++;
285 int g = (int)*(*ptr)++;
286 int b = (int)*(*ptr)++;
287 (*ptr)++;
289 int y = (int)(0.29900 * r + 0.58700 * g + 0.11400 * b);
290 int u = (int)(-0.16874 * r + -0.33126 * g + 0.50000 * b + 0x80);
291 int v = (int)(0.50000 * r + -0.41869 * g + -0.08131 * b + 0x80);
292 CLAMP(y, 0, 0xff);
293 CLAMP(u, 0, 0xff);
294 CLAMP(v, 0, 0xff);
296 file->palette[i * 4] = y;
297 file->palette[i * 4 + 1] = u;
298 file->palette[i * 4 + 2] = v;
299 //printf("color %02d: 0x%02x 0x%02x 0x%02x\n", i, y, u, v);
302 file->have_palette = 1;
306 else
308 (*ptr) += 16 * 4;
311 *ptr += 2;
313 *ptr = get2bytes((unsigned char*)*ptr) + pgc;
315 return num;
319 static u_int get_cellplayinfo(u_char *pgc, u_char **ptr)
321 u_int num;
322 *ptr = pgc;
324 if (!pgc)
325 return -1;
327 *ptr += 3;
328 num = **ptr;
330 *ptr += 9;
331 *ptr += 8 * 2; // AUDIO
332 *ptr += 32 * 4; // SUBPICTURE
333 *ptr += 8;
334 *ptr += 16 * PGCI_COLOR_LEN; // CLUT
335 *ptr += 4;
337 *ptr = get2bytes(*ptr) + pgc;
339 return num;
342 static void get_ifo_playlist(mpeg3_t *file, mpeg3_demuxer_t *demuxer)
344 DIR *dirstream;
345 char directory[MPEG3_STRLEN];
346 char filename[MPEG3_STRLEN];
347 char complete_path[MPEG3_STRLEN];
348 char title_path[MPEG3_STRLEN];
349 char vob_prefix[MPEG3_STRLEN];
350 struct dirent *new_filename;
351 char *ptr;
352 int64_t total_bytes = 0;
353 int done = 0, i;
355 // Get titles matching ifo file
356 mpeg3io_complete_path(complete_path, file->fs->path);
357 mpeg3io_get_directory(directory, complete_path);
358 mpeg3io_get_filename(filename, complete_path);
359 strncpy(vob_prefix, filename, 6);
361 dirstream = opendir(directory);
362 while(new_filename = readdir(dirstream))
364 if(!strncasecmp(new_filename->d_name, vob_prefix, 6))
366 ptr = strrchr(new_filename->d_name, '.');
367 if(ptr && !strncasecmp(ptr, ".vob", 4))
369 // Got a title
370 if(atol(&new_filename->d_name[7]) > 0)
372 mpeg3_title_t *title;
374 mpeg3io_joinpath(title_path, directory, new_filename->d_name);
375 title = demuxer->titles[demuxer->total_titles++] =
376 mpeg3_new_title(file, title_path);
377 title->total_bytes = mpeg3io_path_total_bytes(title_path);
378 title->start_byte = total_bytes;
379 title->end_byte = total_bytes + title->total_bytes;
380 total_bytes += title->total_bytes;
382 mpeg3_new_cell(title,
384 title->end_byte,
386 title->end_byte,
389 //printf("%s\n", title_path);
394 closedir(dirstream);
397 // Alphabetize titles. Only problematic for guys who rip entire DVD's
398 // to their hard drives while retaining the file structure.
399 while(!done)
401 done = 1;
402 for(i = 0; i < demuxer->total_titles - 1; i++)
404 if(strcmp(demuxer->titles[i]->fs->path, demuxer->titles[i + 1]->fs->path) > 0)
406 mpeg3_title_t *temp = demuxer->titles[i];
407 demuxer->titles[i] = demuxer->titles[i + 1];
408 demuxer->titles[i + 1] = temp;
409 done = 0;
420 // IFO parsing
421 static void get_ifo_header(mpeg3_demuxer_t *demuxer, ifo_t *ifo)
423 int i;
424 // Video header
425 demuxer->vstream_table[0] = 1;
427 // Audio header
428 if(!ifo_vts(ifo))
430 ifo_audio_t *audio;
431 int result = 0;
432 // Doesn't detect number of tracks.
433 int atracks = ifo_audio((char*)ifo->data[ID_MAT] + IFO_OFFSET_AUDIO, (char**)&audio);
434 int atracks_empirical = 0;
436 // Collect stream id's
437 #define TEST_START 0x1000000
438 #define TEST_LEN 0x1000000
439 mpeg3demux_open_title(demuxer, 0);
440 mpeg3demux_seek_byte(demuxer, TEST_START);
441 while(!result &&
442 !mpeg3demux_eof(demuxer) &&
443 mpeg3demux_tell_byte(demuxer) < TEST_START + TEST_LEN)
445 result = mpeg3_read_next_packet(demuxer);
447 mpeg3demux_seek_byte(demuxer, 0);
449 for(i = 0; i < MPEG3_MAX_STREAMS; i++)
451 if(demuxer->astream_table[i]) atracks_empirical++;
454 // Doesn't detect PCM audio or total number of tracks
456 * if(atracks && !atracks_empirical)
457 * for(i = 0; i < atracks; i++)
459 * int audio_mode = AUDIO_AC3;
460 * switch(audio->coding_mode)
462 * case 0: audio_mode = AUDIO_AC3; break;
463 * case 1: audio_mode = AUDIO_MPEG; break;
464 * case 2: audio_mode = AUDIO_MPEG; break;
465 * case 3: audio_mode = AUDIO_PCM; break;
467 * if(!demuxer->astream_table[i + 0x80]) demuxer->astream_table[i + 0x80] = audio_mode;
471 else
472 if(!ifo_vmg(ifo))
477 static mpeg3ifo_cell_t* append_cell(mpeg3ifo_celltable_t *table)
479 if(!table->cells || table->total_cells >= table->cells_allocated)
481 long new_allocation;
482 mpeg3ifo_cell_t *new_cells;
484 new_allocation = table->cells_allocated ? table->cells_allocated * 2 : 64;
485 new_cells = calloc(1, sizeof(mpeg3ifo_cell_t) * new_allocation);
486 if(table->cells)
488 memcpy(new_cells, table->cells, sizeof(mpeg3ifo_cell_t) * table->total_cells);
489 free(table->cells);
491 table->cells = new_cells;
492 table->cells_allocated = new_allocation;
495 return &table->cells[table->total_cells++];
498 static void delete_celltable(mpeg3ifo_celltable_t *table)
500 if(table->cells) free(table->cells);
501 free(table);
504 static void cellplayinfo(mpeg3_t *file, ifo_t *ifo, mpeg3ifo_celltable_t *cells)
506 int i, j;
507 char *cell_hdr, *cell_hdr_start, *cell_info;
508 ifo_hdr_t *hdr = (ifo_hdr_t*)ifo->data[ID_TITLE_PGCI];
509 int program_chains = bswap_16(hdr->num);
510 long total_cells;
512 //printf("cellplayinfo\n");
513 for(j = 0; j < program_chains; j++)
515 // Cell header
516 // Program Chain Information
517 pgci(hdr, j, &cell_hdr);
519 cell_hdr_start = cell_hdr;
520 // Unknown
521 cell_hdr += 2;
522 // Num programs
523 cell_hdr += 2;
524 // Chain Time
525 cell_hdr += 4;
526 // Unknown
527 cell_hdr += 4;
528 // Subaudio streams
529 for(i = 0; i < 8; i++) cell_hdr += 2;
530 // Subpictures
531 for(i = 0; i < 32; i++) cell_hdr += 4;
532 // Unknown
533 for(i = 0; i < 8; i++) cell_hdr++;
534 // Skip CLUT
535 // Skip PGC commands
536 // Program map
537 if(program_map(file, cell_hdr_start, &cell_hdr))
540 // Cell Positions
541 if(total_cells = get_cellplayinfo((unsigned char*)cell_hdr_start, (unsigned char**)&cell_hdr))
543 //printf("cellplayinfo %d %d\n", j, total_cells);
544 cell_info = cell_hdr;
545 for(i = 0; i < total_cells; i++)
547 ifo_pgci_cell_addr_t *cell_addr = (ifo_pgci_cell_addr_t *)cell_info;
548 int64_t start_byte = bswap_32(cell_addr->vobu_start);
549 int64_t end_byte = bswap_32(cell_addr->vobu_last_end);
550 int cell_type = cell_addr->chain_info;
552 if(!cells->total_cells && start_byte > 0)
553 start_byte = 0;
555 if(!cells->total_cells ||
556 end_byte >= cells->cells[cells->total_cells - 1].end_byte)
558 mpeg3ifo_cell_t *cell = append_cell(cells);
560 cell->start_byte = start_byte;
561 cell->end_byte = end_byte;
562 cell->cell_type = cell_type;
563 //printf("cellplayinfo start: %llx end: %llx type: %x\n",
564 // (int64_t)cell->start_byte * 0x800, (int64_t)cell->end_byte * 0x800, cell->cell_type);
566 cell_info += PGCI_CELL_ADDR_LEN;
572 static void celladdresses(ifo_t *ifo, mpeg3ifo_celltable_t *cell_addresses)
574 int i;
575 char *ptr = (char*)ifo->data[ID_TITLE_CELL_ADDR];
576 int total_addresses;
577 cell_addr_hdr_t *cell_addr_hdr = (cell_addr_hdr_t*)ptr;
578 ifo_cell_addr_t *cell_addr = (ifo_cell_addr_t*)(ptr + CADDR_HDR_LEN);
579 int done = 0;
580 //printf("celladdresses\n");
582 if(total_addresses = bswap_32(cell_addr_hdr->len) / sizeof(ifo_cell_addr_t))
584 for(i = 0; i < total_addresses; i++)
586 mpeg3ifo_cell_t *cell;
587 cell = append_cell(cell_addresses);
588 cell->start_byte = (int64_t)bswap_32(cell_addr->start);
589 cell->end_byte = (int64_t)bswap_32(cell_addr->end);
590 cell->vob_id = bswap_16(cell_addr->vob_id);
591 cell->cell_id = cell_addr->cell_id;
592 cell_addr++;
596 // Sort addresses by address instead of vob id
597 done = 0;
598 while(!done)
600 done = 1;
601 for(i = 0; i < total_addresses - 1; i++)
603 mpeg3ifo_cell_t *cell1, *cell2;
604 cell1 = &cell_addresses->cells[i];
605 cell2 = &cell_addresses->cells[i + 1];
607 if(cell1->start_byte > cell2->start_byte)
609 mpeg3ifo_cell_t temp = *cell1;
610 *cell1 = *cell2;
611 *cell2 = temp;
612 done = 0;
613 break;
618 for(i = 0; i < total_addresses; i++)
620 mpeg3ifo_cell_t *cell = &cell_addresses->cells[i];
624 static void finaltable(mpeg3ifo_celltable_t *final_cells,
625 mpeg3ifo_celltable_t *cells,
626 mpeg3ifo_celltable_t *cell_addresses)
628 int input_cell = 0, current_address = 0;
629 int output_cell = 0;
630 int done;
631 int i, j;
632 int current_vobid;
633 // Start and end bytes of programs
634 int64_t program_start_byte[256], program_end_byte[256];
636 final_cells->total_cells = 0;
637 final_cells->cells_allocated = cell_addresses->total_cells;
638 final_cells->cells = calloc(1, sizeof(mpeg3ifo_cell_t) * final_cells->cells_allocated);
640 // Assign programs to cells
641 current_vobid = -1;
642 for(i = cell_addresses->total_cells - 1; i >= 0; i--)
644 mpeg3ifo_cell_t *input = &cell_addresses->cells[i];
645 mpeg3ifo_cell_t *output = &final_cells->cells[i];
646 if(current_vobid < 0) current_vobid = input->vob_id;
648 *output = *input;
649 // Reduce current vobid
650 if(input->vob_id < current_vobid)
651 current_vobid = input->vob_id;
652 else
653 // Get the current program number
654 if(input->vob_id > current_vobid)
656 int current_program = input->vob_id - current_vobid;
657 output->program = current_program;
659 // Get the last interleave by brute force
660 for(j = i;
661 j < cell_addresses->total_cells && cell_addresses->cells[i].cell_id == cell_addresses->cells[j].cell_id;
662 j++)
664 int new_program = final_cells->cells[j].vob_id - current_vobid;
665 if(new_program <= current_program)
666 final_cells->cells[j].program = new_program;
670 final_cells->total_cells++;
673 // Expand byte position and remove duplicates
674 for(i = 0; i < final_cells->total_cells; i++)
676 if(i < final_cells->total_cells - 1 &&
677 final_cells->cells[i].start_byte == final_cells->cells[i + 1].start_byte)
679 for(j = i; j < final_cells->total_cells - 1; j++)
680 final_cells->cells[j] = final_cells->cells[j + 1];
682 final_cells->total_cells--;
685 final_cells->cells[i].start_byte *= (int64_t)2048;
686 final_cells->cells[i].end_byte *= (int64_t)2048;
687 // End index seems to be inclusive
688 final_cells->cells[i].end_byte += 2048;
691 return;
692 // Debug
693 printf("finaltable\n");
694 for(i = 0; i < final_cells->total_cells; i++)
696 printf(" vob id: %x cell id: %x start: %llx end: %llx program: %x\n",
697 final_cells->cells[i].vob_id, final_cells->cells[i].cell_id, (int64_t)final_cells->cells[i].start_byte, (int64_t)final_cells->cells[i].end_byte, final_cells->cells[i].program);
704 /* Read the title information from an ifo */
705 int mpeg3_read_ifo(mpeg3_t *file,
706 int read_cells)
708 int64_t last_ifo_byte = 0, first_ifo_byte = 0;
709 mpeg3ifo_celltable_t *cells, *cell_addresses, *final_cells;
710 mpeg3_demuxer_t *demuxer = file->demuxer;
711 int current_title = 0, current_cell = 0;
712 int i, j;
713 ifo_t *ifo;
714 int fd = mpeg3io_get_fd(file->fs);
715 int64_t title_start_byte = 0;
716 int result;
718 if(!(ifo = ifo_open(fd, 0)))
720 fprintf(stderr, "read_ifo: Error decoding ifo.\n");
721 return 1;
724 demuxer->read_all = 1;
725 cells = calloc(1, sizeof(mpeg3ifo_celltable_t));
726 cell_addresses = calloc(1, sizeof(mpeg3ifo_celltable_t));
727 final_cells = calloc(1, sizeof(mpeg3ifo_celltable_t));
729 get_ifo_playlist(file, demuxer);
730 get_ifo_header(demuxer, ifo);
731 cellplayinfo(file, ifo, cells);
732 celladdresses(ifo, cell_addresses);
733 finaltable(final_cells,
734 cells,
735 cell_addresses);
737 // Get maximum program for program_bytes table
738 int total_programs = 0;
739 if(final_cells)
741 for(i = 0; i < final_cells->total_cells; i++)
743 mpeg3ifo_cell_t *cell = &final_cells->cells[i];
744 if(cell->program > total_programs - 1)
745 total_programs = cell->program + 1;
748 int64_t *program_bytes = calloc(total_programs, sizeof(int64_t));
751 // Clear out old cells
752 for(i = 0; i < demuxer->total_titles; i++)
754 mpeg3_title_t *title = demuxer->titles[i];
755 if(title->cell_table)
757 for(j = 0; j < title->cell_table_size; j++)
759 free(title->cell_table);
760 title->cell_table = 0;
766 // Assign new cells to titles
767 while(final_cells && current_cell < final_cells->total_cells)
769 mpeg3_title_t *title;
770 mpeg3ifo_cell_t *cell;
771 int64_t cell_start, cell_end;
772 int64_t length = 1;
774 title = demuxer->titles[current_title];
775 cell = &final_cells->cells[current_cell];
776 cell_start = cell->start_byte;
777 cell_end = cell->end_byte;
779 // Cell may be split by a title so handle in fragments.
780 while(cell_start < cell_end && length > 0)
782 length = cell_end - cell_start;
784 // Clamp length to end of current title
785 if(cell_start + length - title_start_byte > title->total_bytes)
786 length = title->total_bytes - cell_start + title_start_byte;
788 //printf("%llx %llx %llx %llx\n", cell_end, cell_start, title_start_byte, length);
790 // Should never fail. If it does it means the length of the cells and the
791 // length of the titles don't match. The title lengths must match or else
792 // the cells won't line up.
793 if(length > 0)
795 int64_t program_start = program_bytes[cell->program];
796 int64_t program_end = program_start + length;
797 int64_t title_start = cell_start - title_start_byte;
798 int64_t title_end = title_start + length;
799 mpeg3_new_cell(title,
800 program_start,
801 program_end,
802 title_start,
803 title_end,
804 cell->program);
805 cell_start += length;
806 program_bytes[cell->program] += length;
808 else
810 fprintf(stderr,
811 "read_ifo: cell length and title length don't match! title=%d cell=%d cell_start=%llx cell_end=%llx.\n",
812 current_title,
813 current_cell,
814 cell_start - title_start_byte,
815 cell_end - title_start_byte);
817 // Try this out. It works for Contact where one VOB is 0x800 bytes longer than
818 // the cells in it but the next cell aligns perfectly with the next VOB.
819 if(current_title < demuxer->total_titles - 1) current_cell--;
822 // Advance title
823 if(cell_start - title_start_byte >= title->total_bytes &&
824 current_title < demuxer->total_titles - 1)
826 title_start_byte += title->total_bytes;
827 title = demuxer->titles[++current_title];
830 current_cell++;
833 free(program_bytes);
834 delete_celltable(cells);
835 delete_celltable(cell_addresses);
836 delete_celltable(final_cells);
837 ifo_close(ifo);
838 return 0;