10 #include "mpeg3private.h"
11 #include "mpeg3protos.h"
17 // Used in final table
19 // Used in cell play info
21 // Used in cell addresses
28 mpeg3ifo_cell_t
*cells
;
31 } mpeg3ifo_celltable_t
;
34 #define CADDR_HDR_LEN 8
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
43 u_int foo
: 16; // ???
44 u_int num
: 16; // number of subchannels
47 #define AUDIO_HDR_LEN 4
50 u_short id
: 16; // Language
51 u_short
: 16; // don't know
52 u_int start
: 32; // Start of unit
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)
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))
104 static int ifo_vmg(ifo_t
*ifo
)
106 if(!strncmp((char*)ifo
->data
[ID_MAT
], "DVDVIDEO-VMG", 12))
112 static int ifo_table(ifo_t
*ifo
, unsigned long offset
, unsigned long tbl_id
)
115 unsigned long len
= 0;
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)
131 case ID_TITLE_VOBU_ADDR_MAP
:
132 case ID_MENU_VOBU_ADDR_MAP
:
133 len
= get4bytes(data
) + 1;
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
);
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
;
155 for (i
= 0; i
< len
; i
++)
156 ptr
[i
] = bswap_32(ptr
[i
]);
161 static ifo_t
* ifo_open(int fd
, long pos
)
165 ifo
= (ifo_t
*)calloc(sizeof(ifo_t
), 1);
167 ifo
->data
[ID_MAT
] = (unsigned char *)calloc(DVD_VIDEO_LB_LEN
, 1);
172 if(ifo_read(fd
, pos
, DVD_VIDEO_LB_LEN
, ifo
->data
[ID_MAT
]) < 0)
175 free(ifo
->data
[ID_MAT
]);
180 ifo
->num_menu_vobs
= get4bytes(ifo
->data
[ID_MAT
] + 0xC0);
181 ifo
->vob_start
= get4bytes(ifo
->data
[ID_MAT
] + 0xC4);
184 printf ("num of vobs: %x vob_start %x\n", ifo
->num_menu_vobs
, ifo
->vob_start
);
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
);
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
);
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
]);
229 static int ifo_audio(char *_hdr
, char **ptr
)
231 audio_hdr_t
*hdr
= (audio_hdr_t
*)_hdr
;
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
;
249 if(title
> hdr
->num
) return -1;
253 pgci_sub
= (pgci_sub_t
*)*ptr
+ title
;
255 *ptr
= (char *)hdr
+ bswap_32(pgci_sub
->start
);
260 static int program_map(char *pgc
, char **ptr
)
272 *ptr
+= 8 * 2; // AUDIO
273 *ptr
+= 32 * 4; // SUBPICTURE
275 *ptr
+= 16 * PGCI_COLOR_LEN
; // CLUT
278 *ptr
= get2bytes((unsigned char*)*ptr
) + pgc
;
284 static u_int
get_cellplayinfo(u_char
*pgc
, u_char
**ptr
)
296 *ptr
+= 8 * 2; // AUDIO
297 *ptr
+= 32 * 4; // SUBPICTURE
299 *ptr
+= 16 * PGCI_COLOR_LEN
; // CLUT
302 *ptr
= get2bytes(*ptr
) + pgc
;
307 static void get_ifo_playlist(mpeg3_t
*file
, mpeg3_demuxer_t
*demuxer
)
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
;
317 int64_t total_bytes
= 0;
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))
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);
351 // Alphabetize titles. Only problematic for guys who rip entire DVD's
352 // to their hard drives while retaining the file structure.
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
;
375 static void get_ifo_header(mpeg3_demuxer_t
*demuxer
, ifo_t
*ifo
)
379 demuxer
->vstream_table
[0] = 1;
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
);
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;
432 static mpeg3ifo_cell_t
* append_cell(mpeg3ifo_celltable_t
*table
)
434 if(!table
->cells
|| table
->total_cells
>= table
->cells_allocated
)
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
);
443 memcpy(new_cells
, table
->cells
, sizeof(mpeg3ifo_cell_t
) * table
->total_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
);
459 static void cellplayinfo(ifo_t
*ifo
, mpeg3ifo_celltable_t
*cells
)
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
);
467 //printf("cellplayinfo\n");
468 for(j
= 0; j
< program_chains
; j
++)
471 pgci(hdr
, j
, &cell_hdr
);
472 cell_hdr_start
= cell_hdr
;
482 for(i
= 0; i
< 8; i
++) cell_hdr
+= 2;
484 for(i
= 0; i
< 32; i
++) cell_hdr
+= 4;
486 for(i
= 0; i
< 8; i
++) cell_hdr
++;
490 if(program_map(cell_hdr_start
, &cell_hdr
))
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)
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
)
528 char *ptr
= (char*)ifo
->data
[ID_TITLE_CELL_ADDR
];
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
);
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);
553 // Sort addresses by address instead of vob id
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
;
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;
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
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
;
608 // Reduce current vobid
609 if(input
->vob_id
< current_vobid
)
610 current_vobid
= input
->vob_id
;
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
620 j
< cell_addresses
->total_cells
&& cell_addresses
->cells
[i
].cell_id
== cell_addresses
->cells
[j
].cell_id
;
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;
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
,
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;
671 int fd
= mpeg3io_get_fd(file
->fs
);
672 int64_t title_start_byte
= 0;
675 //printf("read_ifo 1\n");
676 if(!(ifo
= ifo_open(fd
, 0)))
678 fprintf(stderr
, "read_ifo: Error decoding ifo.\n");
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
,
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
;
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.
727 * printf("read_ifo title=%d start=%lx end=%lx\n",
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
),
739 cell_start
+= length
;
744 "read_ifo: cell length and title length don't match! title=%d cell_start=%llx cell_end=%llx.\n",
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.
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
];
765 //printf("read_ifo 4\n");
766 // Look up time values for the timecodes
767 // Should only be used for building a TOC
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
);
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
);
802 //printf("read_ifo 5\n");
803 mpeg3demux_assign_programs(demuxer
);
804 //printf("read_ifo 6\n");
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
);