r553: Modern gccs require __attribute__((used)) for variables used only in assembly.
[cinelerra_cv/mob.git] / libmpeg3 / mpeg3ifo.c
blob3c987aa259bd79e00928ecc959e85e25f77c6f67
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 title->start_byte = total_bytes;
343 title->end_byte = total_bytes + title->total_bytes;
344 total_bytes += title->total_bytes;
345 //printf("%s\n", title_path);
350 closedir(dirstream);
353 // Alphabetize titles. Only problematic for guys who rip entire DVD's
354 // to their hard drives while retaining the file structure.
355 while(!done)
357 done = 1;
358 for(i = 0; i < demuxer->total_titles - 1; i++)
360 if(strcmp(demuxer->titles[i]->fs->path, demuxer->titles[i + 1]->fs->path) > 0)
362 mpeg3_title_t *temp = demuxer->titles[i];
363 demuxer->titles[i] = demuxer->titles[i + 1];
364 demuxer->titles[i + 1] = temp;
365 done = 0;
376 // IFO parsing
377 static void get_ifo_header(mpeg3_demuxer_t *demuxer, ifo_t *ifo)
379 int i;
380 // Video header
381 demuxer->vstream_table[0] = 1;
383 // Audio header
384 if(!ifo_vts(ifo))
386 ifo_audio_t *audio;
387 int result = 0;
388 // Doesn't detect number of tracks.
389 int atracks = ifo_audio((char*)ifo->data[ID_MAT] + IFO_OFFSET_AUDIO, (char**)&audio);
390 int atracks_empirical = 0;
392 // Collect stream id's
393 #define TEST_START 0x1000000
394 #define TEST_LEN 0x1000000
395 mpeg3demux_open_title(demuxer, 0);
396 mpeg3demux_seek_byte(demuxer, TEST_START);
397 while(!result &&
398 !mpeg3demux_eof(demuxer) &&
399 mpeg3demux_tell_byte(demuxer) < TEST_START + TEST_LEN)
401 result = mpeg3_read_next_packet(demuxer);
403 mpeg3demux_seek_byte(demuxer, 0);
405 for(i = 0; i < MPEG3_MAX_STREAMS; i++)
407 if(demuxer->astream_table[i]) atracks_empirical++;
410 // Doesn't detect PCM audio or total number of tracks
412 * if(atracks && !atracks_empirical)
413 * for(i = 0; i < atracks; i++)
415 * int audio_mode = AUDIO_AC3;
416 * switch(audio->coding_mode)
418 * case 0: audio_mode = AUDIO_AC3; break;
419 * case 1: audio_mode = AUDIO_MPEG; break;
420 * case 2: audio_mode = AUDIO_MPEG; break;
421 * case 3: audio_mode = AUDIO_PCM; break;
423 * if(!demuxer->astream_table[i + 0x80]) demuxer->astream_table[i + 0x80] = audio_mode;
427 else
428 if(!ifo_vmg(ifo))
433 static mpeg3ifo_cell_t* append_cell(mpeg3ifo_celltable_t *table)
435 if(!table->cells || table->total_cells >= table->cells_allocated)
437 long new_allocation;
438 mpeg3ifo_cell_t *new_cells;
440 new_allocation = table->cells_allocated ? table->cells_allocated * 2 : 64;
441 new_cells = calloc(1, sizeof(mpeg3ifo_cell_t) * new_allocation);
442 if(table->cells)
444 memcpy(new_cells, table->cells, sizeof(mpeg3ifo_cell_t) * table->total_cells);
445 free(table->cells);
447 table->cells = new_cells;
448 table->cells_allocated = new_allocation;
451 return &table->cells[table->total_cells++];
454 static void delete_celltable(mpeg3ifo_celltable_t *table)
456 if(table->cells) free(table->cells);
457 free(table);
460 static void cellplayinfo(ifo_t *ifo, mpeg3ifo_celltable_t *cells)
462 int i, j;
463 char *cell_hdr, *cell_hdr_start, *cell_info;
464 ifo_hdr_t *hdr = (ifo_hdr_t*)ifo->data[ID_TITLE_PGCI];
465 int program_chains = bswap_16(hdr->num);
466 long total_cells;
468 //printf("cellplayinfo\n");
469 for(j = 0; j < program_chains; j++)
471 // Cell header
472 pgci(hdr, j, &cell_hdr);
473 cell_hdr_start = cell_hdr;
474 // Unknown
475 cell_hdr += 2;
476 // Num programs
477 cell_hdr += 2;
478 // Chain Time
479 cell_hdr += 4;
480 // Unknown
481 cell_hdr += 4;
482 // Subaudio streams
483 for(i = 0; i < 8; i++) cell_hdr += 2;
484 // Subpictures
485 for(i = 0; i < 32; i++) cell_hdr += 4;
486 // Unknown
487 for(i = 0; i < 8; i++) cell_hdr++;
488 // Skip CLUT
489 // Skip PGC commands
490 // Program map
491 if(program_map(cell_hdr_start, &cell_hdr))
494 // Cell Positions
495 if(total_cells = get_cellplayinfo((unsigned char*)cell_hdr_start, (unsigned char**)&cell_hdr))
497 //printf("cellplayinfo %d %d\n", j, total_cells);
498 cell_info = cell_hdr;
499 for(i = 0; i < total_cells; i++)
501 ifo_pgci_cell_addr_t *cell_addr = (ifo_pgci_cell_addr_t *)cell_info;
502 long start_byte = bswap_32(cell_addr->vobu_start);
503 long end_byte = bswap_32(cell_addr->vobu_last_end);
504 int cell_type = cell_addr->chain_info;
506 if(!cells->total_cells && start_byte > 0)
507 start_byte = 0;
509 if(!cells->total_cells ||
510 end_byte >= cells->cells[cells->total_cells - 1].end_byte)
512 mpeg3ifo_cell_t *cell = append_cell(cells);
514 cell->start_byte = start_byte;
515 cell->end_byte = end_byte;
516 cell->cell_type = cell_type;
517 //printf("cellplayinfo start: %llx end: %llx type: %x\n",
518 // (int64_t)cell->start_byte * 0x800, (int64_t)cell->end_byte * 0x800, cell->cell_type);
520 cell_info += PGCI_CELL_ADDR_LEN;
526 static void celladdresses(ifo_t *ifo, mpeg3ifo_celltable_t *cell_addresses)
528 int i;
529 char *ptr = (char*)ifo->data[ID_TITLE_CELL_ADDR];
530 int total_addresses;
531 cell_addr_hdr_t *cell_addr_hdr = (cell_addr_hdr_t*)ptr;
532 ifo_cell_addr_t *cell_addr = (ifo_cell_addr_t*)(ptr + CADDR_HDR_LEN);
533 int done = 0;
534 //printf("celladdresses\n");
536 if(total_addresses = bswap_32(cell_addr_hdr->len) / sizeof(ifo_cell_addr_t))
538 for(i = 0; i < total_addresses; i++)
540 mpeg3ifo_cell_t *cell;
541 cell = append_cell(cell_addresses);
542 cell->start_byte = (int64_t)bswap_32(cell_addr->start);
543 cell->end_byte = (int64_t)bswap_32(cell_addr->end);
544 cell->vob_id = bswap_16(cell_addr->vob_id);
545 cell->cell_id = cell_addr->cell_id;
547 * printf("celladdresses vob id: %x cell id: %x start: %ld end: %ld\n",
548 * bswap_16(cell_addr->vob_id), cell_addr->cell_id, (long)cell->start_byte, (long)cell->end_byte);
550 cell_addr++;
554 // Sort addresses by address instead of vob id
555 done = 0;
556 while(!done)
558 done = 1;
559 for(i = 0; i < total_addresses - 1; i++)
561 mpeg3ifo_cell_t *cell1, *cell2;
562 cell1 = &cell_addresses->cells[i];
563 cell2 = &cell_addresses->cells[i + 1];
565 if(cell1->start_byte > cell2->start_byte)
567 mpeg3ifo_cell_t temp = *cell1;
568 *cell1 = *cell2;
569 *cell2 = temp;
570 done = 0;
571 break;
576 for(i = 0; i < total_addresses; i++)
578 mpeg3ifo_cell_t *cell = &cell_addresses->cells[i];
579 //printf("celladdresses vob id: %x cell id: %x start: %ld end: %ld\n",
580 // cell->vob_id, cell->cell_id, (long)cell->start_byte, (long)cell->end_byte);
584 static void finaltable(mpeg3ifo_celltable_t *final_cells,
585 mpeg3ifo_celltable_t *cells,
586 mpeg3ifo_celltable_t *cell_addresses)
588 int input_cell = 0, current_address = 0;
589 int output_cell = 0;
590 int done;
591 int i, j;
592 int current_vobid;
593 // Start and end bytes of programs
594 long program_start_byte[256], program_end_byte[256];
596 final_cells->total_cells = 0;
597 final_cells->cells_allocated = cell_addresses->total_cells;
598 final_cells->cells = calloc(1, sizeof(mpeg3ifo_cell_t) * final_cells->cells_allocated);
600 // Assign programs to cells
601 current_vobid = -1;
602 for(i = cell_addresses->total_cells - 1; i >= 0; i--)
604 mpeg3ifo_cell_t *input = &cell_addresses->cells[i];
605 mpeg3ifo_cell_t *output = &final_cells->cells[i];
606 if(current_vobid < 0) current_vobid = input->vob_id;
608 *output = *input;
609 // Reduce current vobid
610 if(input->vob_id < current_vobid)
611 current_vobid = input->vob_id;
612 else
613 // Get the current program number
614 if(input->vob_id > current_vobid)
616 int current_program = input->vob_id - current_vobid;
617 output->program = current_program;
619 // Get the last interleave by brute force
620 for(j = i;
621 j < cell_addresses->total_cells && cell_addresses->cells[i].cell_id == cell_addresses->cells[j].cell_id;
622 j++)
624 int new_program = final_cells->cells[j].vob_id - current_vobid;
625 if(new_program <= current_program)
626 final_cells->cells[j].program = new_program;
630 final_cells->total_cells++;
633 // Expand byte position and remove duplicates
634 for(i = 0; i < final_cells->total_cells; i++)
636 if(i < final_cells->total_cells - 1 &&
637 final_cells->cells[i].start_byte == final_cells->cells[i + 1].start_byte)
639 for(j = i; j < final_cells->total_cells - 1; j++)
640 final_cells->cells[j] = final_cells->cells[j + 1];
642 final_cells->total_cells--;
645 final_cells->cells[i].start_byte *= (int64_t)2048;
646 final_cells->cells[i].end_byte *= (int64_t)2048;
647 // End index seems to be inclusive
648 final_cells->cells[i].end_byte += 2048;
651 return;
652 // Debug
653 printf("finaltable\n");
654 for(i = 0; i < final_cells->total_cells; i++)
656 printf(" vob id: %x cell id: %x start: %llx end: %llx program: %x\n",
657 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);
664 /* Read the title information from a ifo */
665 static int read_ifo(mpeg3_t *file,
666 mpeg3_demuxer_t *demuxer,
667 int read_cells)
669 int64_t last_ifo_byte = 0, first_ifo_byte = 0;
670 mpeg3ifo_celltable_t *cells, *cell_addresses, *final_cells;
671 int current_title = 0, current_cell = 0;
672 int i;
673 ifo_t *ifo;
674 int fd = mpeg3io_get_fd(file->fs);
675 int64_t title_start_byte = 0;
676 int result;
678 //printf("read_ifo 1\n");
679 if(!(ifo = ifo_open(fd, 0)))
681 fprintf(stderr, "read_ifo: Error decoding ifo.\n");
682 return 1;
685 //printf("read_ifo 1\n");
686 // file->packet_size = 2048;
687 demuxer->read_all = 1;
688 cells = calloc(1, sizeof(mpeg3ifo_celltable_t));
689 cell_addresses = calloc(1, sizeof(mpeg3ifo_celltable_t));
690 final_cells = calloc(1, sizeof(mpeg3ifo_celltable_t));
692 //printf("read_ifo 1\n");
693 get_ifo_playlist(file, demuxer);
694 get_ifo_header(demuxer, ifo);
695 cellplayinfo(ifo, cells);
696 celladdresses(ifo, cell_addresses);
697 finaltable(final_cells,
698 cells,
699 cell_addresses);
701 //printf("read_ifo 2\n");
702 // Assign cells to titles
703 while(final_cells && current_cell < final_cells->total_cells)
705 mpeg3_title_t *title;
706 mpeg3ifo_cell_t *cell;
707 int64_t cell_start, cell_end;
708 int64_t length = 1;
710 title = demuxer->titles[current_title];
711 cell = &final_cells->cells[current_cell];
712 cell_start = cell->start_byte;
713 cell_end = cell->end_byte;
715 //printf("read_ifo 1 %d %llx %llx %d\n", current_cell, (int64_t)cell->start_byte, (int64_t)cell->end_byte, cell->program);
716 while(cell_start < cell_end && length)
718 length = cell_end - cell_start;
720 if(cell_start + length - title_start_byte > title->total_bytes)
721 length = title->total_bytes - cell_start + title_start_byte;
724 // Should never fail. If it does it means the length of the cells and the
725 // length of the titles don't match. The title lengths must match or else
726 // the cells won't line up.
727 if(length)
730 * printf("read_ifo title=%d start=%lx end=%lx\n",
731 * current_title,
732 * (long)(cell_start - title_start_byte),
733 * (long)(cell_start - title_start_byte + length));
735 mpeg3_new_cell(title,
736 (long)(cell_start - title_start_byte),
738 (long)(cell_start - title_start_byte + length),
740 cell->program);
742 cell_start += length;
744 else
746 fprintf(stderr,
747 "read_ifo: cell length and title length don't match! title=%d cell=%d cell_start=%llx cell_end=%llx.\n",
748 current_title,
749 current_cell,
750 cell_start - title_start_byte,
751 cell_end - title_start_byte);
753 // Try this out. It works for Contact where one VOB is 0x800 bytes longer than
754 // the cells in it but the next cell aligns perfectly with the next VOB.
755 if(current_title < demuxer->total_titles - 1) current_cell--;
758 // Advance title
759 if(cell_start - title_start_byte >= title->total_bytes &&
760 current_title < demuxer->total_titles - 1)
762 title_start_byte += title->total_bytes;
763 title = demuxer->titles[++current_title];
766 current_cell++;
769 //printf("read_ifo 4\n");
770 // Look up time values for the cells
771 // Should only be used for building a TOC
773 * if(read_cells)
775 * for(current_title = 0; current_title < demuxer->total_titles; current_title++)
777 * mpeg3_title_t *title = demuxer->titles[current_title];
778 * mpeg3demux_open_title(demuxer, current_title);
780 * for(i = 0; i < title->cell_table_size; i++)
782 * mpeg3demux_cell_t *cell = &title->cell_table[i];
784 * mpeg3io_seek(title->fs, cell->start_byte);
785 * mpeg3_read_next_packet(demuxer);
786 * cell->start_time = demuxer->time;
788 * mpeg3io_seek(title->fs, cell->end_byte);
789 * if(cell->end_byte >= title->total_bytes)
790 * mpeg3_read_prev_packet(demuxer);
791 * else
792 * mpeg3_read_next_packet(demuxer);
794 * cell->end_time = demuxer->time;
797 * mpeg3demux_open_title(demuxer, 0);
801 //for(i = 0; i < demuxer->total_titles; i++) mpeg3_dump_title(demuxer->titles[i]);
803 delete_celltable(cells);
804 delete_celltable(cell_addresses);
805 delete_celltable(final_cells);
806 ifo_close(ifo);
808 //printf("read_ifo 5\n");
809 mpeg3demux_assign_programs(demuxer);
810 //printf("read_ifo 6\n");
811 return 0;
814 int mpeg3_read_ifo(mpeg3_t *file, int read_cells)
816 file->is_program_stream = 1;
818 read_ifo(file, file->demuxer, read_cells);
819 return 0;