r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / libmpeg3 / mpeg3ifo.c
blob5afafbc711d09178d12b87d152cb3af916fc5269
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 int64_t start_byte;
16 int64_t end_byte;
17 // Used in final table
18 int program;
19 // Used in cell play info
20 int cell_type;
21 // Used in cell addresses
22 int vob_id;
23 int cell_id;
24 } mpeg3ifo_cell_t;
26 typedef struct
28 mpeg3ifo_cell_t *cells;
29 long total_cells;
30 long cells_allocated;
31 } mpeg3ifo_celltable_t;
34 #define CADDR_HDR_LEN 8
36 typedef struct {
37 u_short num : 16; // Number of Video Objects
38 u_short unknown : 16; // don't know
39 u_int len : 32; // length of table
40 } cell_addr_hdr_t;
42 typedef struct {
43 u_int foo : 16; // ???
44 u_int num : 16; // number of subchannels
45 } audio_hdr_t;
47 #define AUDIO_HDR_LEN 4
49 typedef struct {
50 u_short id : 16; // Language
51 u_short : 16; // don't know
52 u_int start : 32; // Start of unit
53 } pgci_sub_t;
55 #define PGCI_SUB_LEN 8
57 #define PGCI_COLOR_LEN 4
60 static u_int get4bytes(u_char *buf)
62 return bswap_32 (*((u_int32_t *)buf));
65 static u_int get2bytes(u_char *buf)
67 return bswap_16 (*((u_int16_t *)buf));
70 static int ifo_read(int fd, long pos, long count, unsigned char *data)
72 if((pos = lseek(fd, pos, SEEK_SET)) < 0)
74 perror("ifo_read");
75 return -1;
78 return read(fd, data, count);
81 #define OFF_PTT get4bytes (ifo->data[ID_MAT] + 0xC8)
82 #define OFF_TITLE_PGCI get4bytes (ifo->data[ID_MAT] + 0xCC)
83 #define OFF_MENU_PGCI get4bytes (ifo->data[ID_MAT] + 0xD0)
84 #define OFF_TMT get4bytes (ifo->data[ID_MAT] + 0xD4)
85 #define OFF_MENU_CELL_ADDR get4bytes (ifo->data[ID_MAT] + 0xD8)
86 #define OFF_MENU_VOBU_ADDR_MAP get4bytes (ifo->data[ID_MAT] + 0xDC)
87 #define OFF_TITLE_CELL_ADDR get4bytes (ifo->data[ID_MAT] + 0xE0)
88 #define OFF_TITLE_VOBU_ADDR_MAP get4bytes (ifo->data[ID_MAT] + 0xE4)
90 #define OFF_VMG_TSP get4bytes (ifo->data[ID_MAT] + 0xC4)
91 #define OFF_VMG_MENU_PGCI get4bytes (ifo->data[ID_MAT] + 0xC8)
92 #define OFF_VMG_TMT get4bytes (ifo->data[ID_MAT] + 0xD0)
95 static int ifo_vts(ifo_t *ifo)
97 if(!strncmp((char*)ifo->data[ID_MAT], "DVDVIDEO-VTS", 12))
98 return 0;
100 return -1;
104 static int ifo_vmg(ifo_t *ifo)
106 if(!strncmp((char*)ifo->data[ID_MAT], "DVDVIDEO-VMG", 12))
107 return 0;
109 return -1;
112 static int ifo_table(ifo_t *ifo, unsigned long offset, unsigned long tbl_id)
114 unsigned char *data;
115 unsigned long len = 0;
116 int i;
117 u_int32_t *ptr;
119 if(!offset) return -1;
121 data = (u_char *)calloc(1, DVD_VIDEO_LB_LEN);
123 if(ifo_read(ifo->fd, ifo->pos + offset * DVD_VIDEO_LB_LEN, DVD_VIDEO_LB_LEN, data) <= 0)
125 perror("ifo_table");
126 return -1;
129 switch(tbl_id)
131 case ID_TITLE_VOBU_ADDR_MAP:
132 case ID_MENU_VOBU_ADDR_MAP:
133 len = get4bytes(data) + 1;
134 break;
136 default:
138 ifo_hdr_t *hdr = (ifo_hdr_t *)data;
139 len = bswap_32(hdr->len) + 1;
143 if(len > DVD_VIDEO_LB_LEN)
145 data = (u_char *)realloc((void *)data, len);
146 bzero(data, len);
147 ifo_read(ifo->fd, ifo->pos + offset * DVD_VIDEO_LB_LEN, len, data);
150 ifo->data[tbl_id] = data;
151 ptr = (u_int32_t*)data;
152 len /= 4;
154 if(tbl_id == ID_TMT)
155 for (i = 0; i < len; i++)
156 ptr[i] = bswap_32(ptr[i]);
158 return 0;
161 static ifo_t* ifo_open(int fd, long pos)
163 ifo_t *ifo;
165 ifo = (ifo_t *)calloc(sizeof(ifo_t), 1);
167 ifo->data[ID_MAT] = (unsigned char *)calloc(DVD_VIDEO_LB_LEN, 1);
169 ifo->pos = pos;
170 ifo->fd = fd;
172 if(ifo_read(fd, pos, DVD_VIDEO_LB_LEN, ifo->data[ID_MAT]) < 0)
174 perror("ifo_open");
175 free(ifo->data[ID_MAT]);
176 free(ifo);
177 return NULL;
180 ifo->num_menu_vobs = get4bytes(ifo->data[ID_MAT] + 0xC0);
181 ifo->vob_start = get4bytes(ifo->data[ID_MAT] + 0xC4);
183 #ifdef DEBUG
184 printf ("num of vobs: %x vob_start %x\n", ifo->num_menu_vobs, ifo->vob_start);
185 #endif
187 if(!ifo_vts(ifo))
189 ifo_table(ifo, OFF_PTT, ID_PTT);
190 ifo_table(ifo, OFF_TITLE_PGCI, ID_TITLE_PGCI);
191 ifo_table(ifo, OFF_MENU_PGCI, ID_MENU_PGCI);
192 ifo_table(ifo, OFF_TMT, ID_TMT);
193 ifo_table(ifo, OFF_MENU_CELL_ADDR, ID_MENU_CELL_ADDR);
194 ifo_table(ifo, OFF_MENU_VOBU_ADDR_MAP, ID_MENU_VOBU_ADDR_MAP);
195 ifo_table(ifo, OFF_TITLE_CELL_ADDR, ID_TITLE_CELL_ADDR);
196 ifo_table(ifo, OFF_TITLE_VOBU_ADDR_MAP, ID_TITLE_VOBU_ADDR_MAP);
198 else
199 if(!ifo_vmg(ifo))
201 ifo_table(ifo, OFF_VMG_TSP, ID_TSP);
202 ifo_table(ifo, OFF_VMG_MENU_PGCI, ID_MENU_PGCI);
203 ifo_table(ifo, OFF_VMG_TMT, ID_TMT);
204 ifo_table(ifo, OFF_TITLE_CELL_ADDR, ID_TITLE_CELL_ADDR);
205 ifo_table(ifo, OFF_TITLE_VOBU_ADDR_MAP, ID_TITLE_VOBU_ADDR_MAP);
208 return ifo;
212 static int ifo_close(ifo_t *ifo)
214 if(ifo->data[ID_MAT]) free(ifo->data[ID_MAT]);
215 if(ifo->data[ID_PTT]) free(ifo->data[ID_PTT]);
216 if(ifo->data[ID_TITLE_PGCI]) free(ifo->data[ID_TITLE_PGCI]);
217 if(ifo->data[ID_MENU_PGCI]) free(ifo->data[ID_MENU_PGCI]);
218 if(ifo->data[ID_TMT]) free(ifo->data[ID_TMT]);
219 if(ifo->data[ID_MENU_CELL_ADDR]) free(ifo->data[ID_MENU_CELL_ADDR]);
220 if(ifo->data[ID_MENU_VOBU_ADDR_MAP]) free(ifo->data[ID_MENU_VOBU_ADDR_MAP]);
221 if(ifo->data[ID_TITLE_CELL_ADDR]) free(ifo->data[ID_TITLE_CELL_ADDR]);
222 if(ifo->data[ID_TITLE_VOBU_ADDR_MAP]) free(ifo->data[ID_TITLE_VOBU_ADDR_MAP]);
224 free(ifo);
226 return 0;
229 static int ifo_audio(char *_hdr, char **ptr)
231 audio_hdr_t *hdr = (audio_hdr_t *)_hdr;
233 if(!_hdr) return -1;
235 *ptr = _hdr + AUDIO_HDR_LEN;
237 return bswap_16(hdr->num);
241 static int pgci(ifo_hdr_t *hdr, int title, char **ptr)
243 pgci_sub_t *pgci_sub;
245 *ptr = (char *) hdr;
247 if(!*ptr) return -1;
249 if(title > hdr->num) return -1;
251 *ptr += IFO_HDR_LEN;
253 pgci_sub = (pgci_sub_t *)*ptr + title;
255 *ptr = (char *)hdr + bswap_32(pgci_sub->start);
257 return 0;
260 static int program_map(char *pgc, char **ptr)
262 int num;
263 *ptr = pgc;
265 if (!pgc)
266 return -1;
268 *ptr += 2;
269 num = **ptr;
271 *ptr += 10;
272 *ptr += 8 * 2; // AUDIO
273 *ptr += 32 * 4; // SUBPICTURE
274 *ptr += 8;
275 *ptr += 16 * PGCI_COLOR_LEN; // CLUT
276 *ptr += 2;
278 *ptr = get2bytes((unsigned char*)*ptr) + pgc;
280 return num;
284 static u_int get_cellplayinfo(u_char *pgc, u_char **ptr)
286 u_int num;
287 *ptr = pgc;
289 if (!pgc)
290 return -1;
292 *ptr += 3;
293 num = **ptr;
295 *ptr += 9;
296 *ptr += 8 * 2; // AUDIO
297 *ptr += 32 * 4; // SUBPICTURE
298 *ptr += 8;
299 *ptr += 16 * PGCI_COLOR_LEN; // CLUT
300 *ptr += 4;
302 *ptr = get2bytes(*ptr) + pgc;
304 return num;
307 static void get_ifo_playlist(mpeg3_t *file, mpeg3_demuxer_t *demuxer)
309 DIR *dirstream;
310 char directory[MPEG3_STRLEN];
311 char filename[MPEG3_STRLEN];
312 char complete_path[MPEG3_STRLEN];
313 char title_path[MPEG3_STRLEN];
314 char vob_prefix[MPEG3_STRLEN];
315 struct dirent *new_filename;
316 char *ptr;
317 int64_t total_bytes = 0;
318 int done = 0, i;
320 // Get titles matching ifo file
321 mpeg3io_complete_path(complete_path, file->fs->path);
322 mpeg3io_get_directory(directory, complete_path);
323 mpeg3io_get_filename(filename, complete_path);
324 strncpy(vob_prefix, filename, 6);
326 dirstream = opendir(directory);
327 while(new_filename = readdir(dirstream))
329 if(!strncasecmp(new_filename->d_name, vob_prefix, 6))
331 ptr = strrchr(new_filename->d_name, '.');
332 if(ptr && !strncasecmp(ptr, ".vob", 4))
334 // Got a title
335 if(atol(&new_filename->d_name[7]) > 0)
337 mpeg3_title_t *title;
339 mpeg3io_joinpath(title_path, directory, new_filename->d_name);
340 title = demuxer->titles[demuxer->total_titles++] = mpeg3_new_title(file, title_path);
341 title->total_bytes = mpeg3io_path_total_bytes(title_path);
342 total_bytes += title->total_bytes;
343 //printf("%s\n", title_path);
348 closedir(dirstream);
351 // Alphabetize titles. Only problematic for guys who rip entire DVD's
352 // to their hard drives while retaining the file structure.
353 while(!done)
355 done = 1;
356 for(i = 0; i < demuxer->total_titles - 1; i++)
358 if(strcmp(demuxer->titles[i]->fs->path, demuxer->titles[i + 1]->fs->path) > 0)
360 mpeg3_title_t *temp = demuxer->titles[i];
361 demuxer->titles[i] = demuxer->titles[i + 1];
362 demuxer->titles[i + 1] = temp;
363 done = 0;
374 // IFO parsing
375 static void get_ifo_header(mpeg3_demuxer_t *demuxer, ifo_t *ifo)
377 int i;
378 // Video header
379 demuxer->vstream_table[0] = 1;
381 // Audio header
382 if(!ifo_vts(ifo))
384 ifo_audio_t *audio;
385 int result = 0;
386 // Doesn't detect number of tracks.
387 int atracks = ifo_audio((char*)ifo->data[ID_MAT] + IFO_OFFSET_AUDIO, (char**)&audio);
388 int atracks_empirical = 0;
390 // Construct audio stream id's
391 #define TEST_START 0x600000
392 #define TEST_LEN 0x100000
393 mpeg3demux_open_title(demuxer, 0);
394 mpeg3demux_seek_byte(demuxer, TEST_START);
395 while(!result &&
396 !mpeg3demux_eof(demuxer) &&
397 mpeg3demux_tell(demuxer) < TEST_START + TEST_LEN)
399 result = mpeg3_read_next_packet(demuxer);
401 mpeg3demux_seek_byte(demuxer, 0);
403 for(i = 0; i < MPEG3_MAX_STREAMS; i++)
405 //printf("%x %d\n", i, demuxer->astream_table[i]);
406 if(demuxer->astream_table[i]) atracks_empirical++;
409 // Doesn't detect PCM audio or total number of tracks
411 * if(atracks && !atracks_empirical)
412 * for(i = 0; i < atracks; i++)
414 * int audio_mode = AUDIO_AC3;
415 * switch(audio->coding_mode)
417 * case 0: audio_mode = AUDIO_AC3; break;
418 * case 1: audio_mode = AUDIO_MPEG; break;
419 * case 2: audio_mode = AUDIO_MPEG; break;
420 * case 3: audio_mode = AUDIO_PCM; break;
422 * if(!demuxer->astream_table[i + 0x80]) demuxer->astream_table[i + 0x80] = audio_mode;
426 else
427 if(!ifo_vmg(ifo))
432 static mpeg3ifo_cell_t* append_cell(mpeg3ifo_celltable_t *table)
434 if(!table->cells || table->total_cells >= table->cells_allocated)
436 long new_allocation;
437 mpeg3ifo_cell_t *new_cells;
439 new_allocation = table->cells_allocated ? table->cells_allocated * 2 : 64;
440 new_cells = calloc(1, sizeof(mpeg3ifo_cell_t) * new_allocation);
441 if(table->cells)
443 memcpy(new_cells, table->cells, sizeof(mpeg3ifo_cell_t) * table->total_cells);
444 free(table->cells);
446 table->cells = new_cells;
447 table->cells_allocated = new_allocation;
450 return &table->cells[table->total_cells++];
453 static void delete_celltable(mpeg3ifo_celltable_t *table)
455 if(table->cells) free(table->cells);
456 free(table);
459 static void cellplayinfo(ifo_t *ifo, mpeg3ifo_celltable_t *cells)
461 int i, j;
462 char *cell_hdr, *cell_hdr_start, *cell_info;
463 ifo_hdr_t *hdr = (ifo_hdr_t*)ifo->data[ID_TITLE_PGCI];
464 int program_chains = bswap_16(hdr->num);
465 long total_cells;
467 //printf("cellplayinfo\n");
468 for(j = 0; j < program_chains; j++)
470 // Cell header
471 pgci(hdr, j, &cell_hdr);
472 cell_hdr_start = cell_hdr;
473 // Unknown
474 cell_hdr += 2;
475 // Num programs
476 cell_hdr += 2;
477 // Chain Time
478 cell_hdr += 4;
479 // Unknown
480 cell_hdr += 4;
481 // Subaudio streams
482 for(i = 0; i < 8; i++) cell_hdr += 2;
483 // Subpictures
484 for(i = 0; i < 32; i++) cell_hdr += 4;
485 // Unknown
486 for(i = 0; i < 8; i++) cell_hdr++;
487 // Skip CLUT
488 // Skip PGC commands
489 // Program map
490 if(program_map(cell_hdr_start, &cell_hdr))
493 // Cell Positions
494 if(total_cells = get_cellplayinfo((unsigned char*)cell_hdr_start, (unsigned char**)&cell_hdr))
496 //printf("cellplayinfo %d %d\n", j, total_cells);
497 cell_info = cell_hdr;
498 for(i = 0; i < total_cells; i++)
500 ifo_pgci_cell_addr_t *cell_addr = (ifo_pgci_cell_addr_t *)cell_info;
501 long start_byte = bswap_32(cell_addr->vobu_start);
502 long end_byte = bswap_32(cell_addr->vobu_last_end);
503 int cell_type = cell_addr->chain_info;
505 if(!cells->total_cells && start_byte > 0)
506 start_byte = 0;
508 if(!cells->total_cells ||
509 end_byte >= cells->cells[cells->total_cells - 1].end_byte)
511 mpeg3ifo_cell_t *cell = append_cell(cells);
513 cell->start_byte = start_byte;
514 cell->end_byte = end_byte;
515 cell->cell_type = cell_type;
516 //printf("cellplayinfo start: %llx end: %llx type: %x\n",
517 // (int64_t)cell->start_byte * 0x800, (int64_t)cell->end_byte * 0x800, cell->cell_type);
519 cell_info += PGCI_CELL_ADDR_LEN;
525 static void celladdresses(ifo_t *ifo, mpeg3ifo_celltable_t *cell_addresses)
527 int i;
528 char *ptr = (char*)ifo->data[ID_TITLE_CELL_ADDR];
529 int total_addresses;
530 cell_addr_hdr_t *cell_addr_hdr = (cell_addr_hdr_t*)ptr;
531 ifo_cell_addr_t *cell_addr = (ifo_cell_addr_t*)(ptr + CADDR_HDR_LEN);
532 int done = 0;
533 //printf("celladdresses\n");
535 if(total_addresses = bswap_32(cell_addr_hdr->len) / sizeof(ifo_cell_addr_t))
537 for(i = 0; i < total_addresses; i++)
539 mpeg3ifo_cell_t *cell;
540 cell = append_cell(cell_addresses);
541 cell->start_byte = (int64_t)bswap_32(cell_addr->start);
542 cell->end_byte = (int64_t)bswap_32(cell_addr->end);
543 cell->vob_id = bswap_16(cell_addr->vob_id);
544 cell->cell_id = cell_addr->cell_id;
546 * printf("celladdresses vob id: %x cell id: %x start: %ld end: %ld\n",
547 * bswap_16(cell_addr->vob_id), cell_addr->cell_id, (long)cell->start_byte, (long)cell->end_byte);
549 cell_addr++;
553 // Sort addresses by address instead of vob id
554 done = 0;
555 while(!done)
557 done = 1;
558 for(i = 0; i < total_addresses - 1; i++)
560 mpeg3ifo_cell_t *cell1, *cell2;
561 cell1 = &cell_addresses->cells[i];
562 cell2 = &cell_addresses->cells[i + 1];
564 if(cell1->start_byte > cell2->start_byte)
566 mpeg3ifo_cell_t temp = *cell1;
567 *cell1 = *cell2;
568 *cell2 = temp;
569 done = 0;
570 break;
575 for(i = 0; i < total_addresses; i++)
577 mpeg3ifo_cell_t *cell = &cell_addresses->cells[i];
578 //printf("celladdresses vob id: %x cell id: %x start: %ld end: %ld\n",
579 // cell->vob_id, cell->cell_id, (long)cell->start_byte, (long)cell->end_byte);
583 static void finaltable(mpeg3ifo_celltable_t *final_cells,
584 mpeg3ifo_celltable_t *cells,
585 mpeg3ifo_celltable_t *cell_addresses)
587 int input_cell = 0, current_address = 0;
588 int output_cell = 0;
589 int done;
590 int i, j;
591 int current_vobid;
592 // Start and end bytes of programs
593 long program_start_byte[256], program_end_byte[256];
595 final_cells->total_cells = 0;
596 final_cells->cells_allocated = cell_addresses->total_cells;
597 final_cells->cells = calloc(1, sizeof(mpeg3ifo_cell_t) * final_cells->cells_allocated);
599 // Assign programs to cells
600 current_vobid = -1;
601 for(i = cell_addresses->total_cells - 1; i >= 0; i--)
603 mpeg3ifo_cell_t *input = &cell_addresses->cells[i];
604 mpeg3ifo_cell_t *output = &final_cells->cells[i];
605 if(current_vobid < 0) current_vobid = input->vob_id;
607 *output = *input;
608 // Reduce current vobid
609 if(input->vob_id < current_vobid)
610 current_vobid = input->vob_id;
611 else
612 // Get the current program number
613 if(input->vob_id > current_vobid)
615 int current_program = input->vob_id - current_vobid;
616 output->program = current_program;
618 // Get the last interleave by brute force
619 for(j = i;
620 j < cell_addresses->total_cells && cell_addresses->cells[i].cell_id == cell_addresses->cells[j].cell_id;
621 j++)
623 int new_program = final_cells->cells[j].vob_id - current_vobid;
624 if(new_program <= current_program)
625 final_cells->cells[j].program = new_program;
629 final_cells->total_cells++;
632 // Expand byte position and remove duplicates
633 for(i = 0; i < final_cells->total_cells; i++)
635 if(i < final_cells->total_cells - 1 &&
636 final_cells->cells[i].start_byte == final_cells->cells[i + 1].start_byte)
638 for(j = i; j < final_cells->total_cells - 1; j++)
639 final_cells->cells[j] = final_cells->cells[j + 1];
641 final_cells->total_cells--;
644 final_cells->cells[i].start_byte *= (int64_t)2048;
645 final_cells->cells[i].end_byte *= (int64_t)2048;
648 return;
649 // Debug
650 printf("finaltable\n");
651 for(i = 0; i < final_cells->total_cells; i++)
653 printf(" vob id: %x cell id: %x start: %llx end: %llx program: %x\n",
654 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);
661 /* Read the title information from a ifo */
662 static int read_ifo(mpeg3_t *file,
663 mpeg3_demuxer_t *demuxer,
664 int read_timecodes)
666 int64_t last_ifo_byte = 0, first_ifo_byte = 0;
667 mpeg3ifo_celltable_t *cells, *cell_addresses, *final_cells;
668 int current_title = 0, current_cell = 0;
669 int i;
670 ifo_t *ifo;
671 int fd = mpeg3io_get_fd(file->fs);
672 int64_t title_start_byte = 0;
673 int result;
675 //printf("read_ifo 1\n");
676 if(!(ifo = ifo_open(fd, 0)))
678 fprintf(stderr, "read_ifo: Error decoding ifo.\n");
679 return 1;
682 //printf("read_ifo 1\n");
683 // file->packet_size = 2048;
684 demuxer->read_all = 1;
685 cells = calloc(1, sizeof(mpeg3ifo_celltable_t));
686 cell_addresses = calloc(1, sizeof(mpeg3ifo_celltable_t));
687 final_cells = calloc(1, sizeof(mpeg3ifo_celltable_t));
689 //printf("read_ifo 1\n");
690 get_ifo_playlist(file, demuxer);
691 get_ifo_header(demuxer, ifo);
692 cellplayinfo(ifo, cells);
693 celladdresses(ifo, cell_addresses);
694 finaltable(final_cells,
695 cells,
696 cell_addresses);
698 //printf("read_ifo 2\n");
699 // Assign cells to titles
700 while(final_cells && current_cell < final_cells->total_cells)
702 mpeg3_title_t *title;
703 mpeg3ifo_cell_t *cell;
704 int64_t cell_start, cell_end;
705 int64_t length = 1;
707 title = demuxer->titles[current_title];
708 cell = &final_cells->cells[current_cell];
709 cell_start = cell->start_byte;
710 cell_end = cell->end_byte;
712 //printf("read_ifo 1 %d %llx %llx %d\n", current_cell, (int64_t)cell->start_byte, (int64_t)cell->end_byte, cell->program);
713 while(cell_start < cell_end && length)
715 length = cell_end - cell_start;
717 if(cell_start + length - title_start_byte > title->total_bytes)
718 length = title->total_bytes - cell_start + title_start_byte;
721 // Should never fail. If it does it means the length of the cells and the
722 // length of the titles don't match. The title lengths must match or else
723 // the cells won't line up.
724 if(length)
727 * printf("read_ifo title=%d start=%lx end=%lx\n",
728 * current_title,
729 * (long)(cell_start - title_start_byte),
730 * (long)(cell_start - title_start_byte + length));
732 mpeg3_new_timecode(title,
733 (long)(cell_start - title_start_byte),
735 (long)(cell_start - title_start_byte + length),
737 cell->program);
739 cell_start += length;
741 else
743 fprintf(stderr,
744 "read_ifo: cell length and title length don't match! title=%d cell_start=%llx cell_end=%llx.\n",
745 current_title,
746 cell_start - title_start_byte,
747 cell_end - title_start_byte);
749 // Try this out. It works for Contact where one VOB is 0x800 bytes longer than
750 // the cells in it but the next cell aligns perfectly with the next VOB.
751 current_cell--;
754 // Advance title
755 if(cell_start - title_start_byte >= title->total_bytes &&
756 current_title < demuxer->total_titles - 1)
758 title_start_byte += title->total_bytes;
759 title = demuxer->titles[++current_title];
762 current_cell++;
765 //printf("read_ifo 4\n");
766 // Look up time values for the timecodes
767 // Should only be used for building a TOC
768 if(read_timecodes)
770 for(current_title = 0; current_title < demuxer->total_titles; current_title++)
772 mpeg3_title_t *title = demuxer->titles[current_title];
773 mpeg3demux_open_title(demuxer, current_title);
775 for(i = 0; i < title->timecode_table_size; i++)
777 mpeg3demux_timecode_t *timecode = &title->timecode_table[i];
779 mpeg3io_seek(title->fs, timecode->start_byte);
780 mpeg3_read_next_packet(demuxer);
781 timecode->start_time = demuxer->time;
783 mpeg3io_seek(title->fs, timecode->end_byte);
784 if(timecode->end_byte >= title->total_bytes)
785 mpeg3_read_prev_packet(demuxer);
786 else
787 mpeg3_read_next_packet(demuxer);
789 timecode->end_time = demuxer->time;
792 mpeg3demux_open_title(demuxer, 0);
795 //for(i = 0; i < demuxer->total_titles; i++) mpeg3_dump_title(demuxer->titles[i]);
797 delete_celltable(cells);
798 delete_celltable(cell_addresses);
799 delete_celltable(final_cells);
800 ifo_close(ifo);
802 //printf("read_ifo 5\n");
803 mpeg3demux_assign_programs(demuxer);
804 //printf("read_ifo 6\n");
805 return 0;
808 int mpeg3_read_ifo(mpeg3_t *file, int read_timecodes)
810 file->is_program_stream = 1;
812 read_ifo(file, file->demuxer, read_timecodes);
813 return 0;