10 #include "mpeg3private.h"
11 #include "mpeg3protos.h"
15 // Bytes relative to start of stream.
18 // Used in final table
20 // Used in cell play info
22 // Used in cell addresses
29 mpeg3ifo_cell_t
*cells
;
32 } mpeg3ifo_celltable_t
;
35 #define CADDR_HDR_LEN 8
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
44 u_int foo
: 16; // ???
45 u_int num
: 16; // number of subchannels
48 #define AUDIO_HDR_LEN 4
51 u_short id
: 16; // Language
52 u_short
: 16; // don't know
53 u_int start
: 32; // Start of unit
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)
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))
105 static int ifo_vmg(ifo_t
*ifo
)
107 if(!strncmp((char*)ifo
->data
[ID_MAT
], "DVDVIDEO-VMG", 12))
113 static int ifo_table(ifo_t
*ifo
, int64_t offset
, unsigned long tbl_id
)
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)
132 case ID_TITLE_VOBU_ADDR_MAP
:
133 case ID_MENU_VOBU_ADDR_MAP
:
134 len
= get4bytes(data
) + 1;
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
);
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
;
156 for (i
= 0; i
< len
; i
++)
157 ptr
[i
] = bswap_32(ptr
[i
]);
162 static ifo_t
* ifo_open(int fd
, long pos
)
166 ifo
= (ifo_t
*)calloc(sizeof(ifo_t
), 1);
168 ifo
->data
[ID_MAT
] = (unsigned char *)calloc(DVD_VIDEO_LB_LEN
, 1);
173 if(ifo_read(fd
, pos
, DVD_VIDEO_LB_LEN
, ifo
->data
[ID_MAT
]) < 0)
176 free(ifo
->data
[ID_MAT
]);
181 ifo
->num_menu_vobs
= get4bytes(ifo
->data
[ID_MAT
] + 0xC0);
182 ifo
->vob_start
= get4bytes(ifo
->data
[ID_MAT
] + 0xC4);
185 printf ("num of vobs: %x vob_start %x\n", ifo
->num_menu_vobs
, ifo
->vob_start
);
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
);
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
);
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
]);
230 static int ifo_audio(char *_hdr
, char **ptr
)
232 audio_hdr_t
*hdr
= (audio_hdr_t
*)_hdr
;
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
;
250 if(title
> hdr
->num
) return -1;
254 pgci_sub
= (pgci_sub_t
*)*ptr
+ title
;
256 *ptr
= (char *)hdr
+ bswap_32(pgci_sub
->start
);
261 static int program_map(char *pgc
, char **ptr
)
273 *ptr
+= 8 * 2; // AUDIO
274 *ptr
+= 32 * 4; // SUBPICTURE
276 *ptr
+= 16 * PGCI_COLOR_LEN
; // CLUT
279 *ptr
= get2bytes((unsigned char*)*ptr
) + pgc
;
285 static u_int
get_cellplayinfo(u_char
*pgc
, u_char
**ptr
)
297 *ptr
+= 8 * 2; // AUDIO
298 *ptr
+= 32 * 4; // SUBPICTURE
300 *ptr
+= 16 * PGCI_COLOR_LEN
; // CLUT
303 *ptr
= get2bytes(*ptr
) + pgc
;
308 static void get_ifo_playlist(mpeg3_t
*file
, mpeg3_demuxer_t
*demuxer
)
311 char directory
[MPEG3_STRLEN
];
312 char filename
[MPEG3_STRLEN
];
313 char complete_path
[MPEG3_STRLEN
];
314 char title_path
[MPEG3_STRLEN
];
315 char vob_prefix
[MPEG3_STRLEN
];
316 struct dirent
*new_filename
;
318 int64_t total_bytes
= 0;
321 // Get titles matching ifo file
322 mpeg3io_complete_path(complete_path
, file
->fs
->path
);
323 mpeg3io_get_directory(directory
, complete_path
);
324 mpeg3io_get_filename(filename
, complete_path
);
325 strncpy(vob_prefix
, filename
, 6);
327 dirstream
= opendir(directory
);
328 while(new_filename
= readdir(dirstream
))
330 if(!strncasecmp(new_filename
->d_name
, vob_prefix
, 6))
332 ptr
= strrchr(new_filename
->d_name
, '.');
333 if(ptr
&& !strncasecmp(ptr
, ".vob", 4))
336 if(atol(&new_filename
->d_name
[7]) > 0)
338 mpeg3_title_t
*title
;
340 mpeg3io_joinpath(title_path
, directory
, new_filename
->d_name
);
341 title
= demuxer
->titles
[demuxer
->total_titles
++] =
342 mpeg3_new_title(file
, title_path
);
343 title
->total_bytes
= mpeg3io_path_total_bytes(title_path
);
344 title
->start_byte
= total_bytes
;
345 title
->end_byte
= total_bytes
+ title
->total_bytes
;
346 total_bytes
+= title
->total_bytes
;
348 mpeg3_new_cell(title
,
355 //printf("%s\n", title_path);
363 // Alphabetize titles. Only problematic for guys who rip entire DVD's
364 // to their hard drives while retaining the file structure.
368 for(i
= 0; i
< demuxer
->total_titles
- 1; i
++)
370 if(strcmp(demuxer
->titles
[i
]->fs
->path
, demuxer
->titles
[i
+ 1]->fs
->path
) > 0)
372 mpeg3_title_t
*temp
= demuxer
->titles
[i
];
373 demuxer
->titles
[i
] = demuxer
->titles
[i
+ 1];
374 demuxer
->titles
[i
+ 1] = temp
;
387 static void get_ifo_header(mpeg3_demuxer_t
*demuxer
, ifo_t
*ifo
)
391 demuxer
->vstream_table
[0] = 1;
398 // Doesn't detect number of tracks.
399 int atracks
= ifo_audio((char*)ifo
->data
[ID_MAT
] + IFO_OFFSET_AUDIO
, (char**)&audio
);
400 int atracks_empirical
= 0;
402 // Collect stream id's
403 #define TEST_START 0x1000000
404 #define TEST_LEN 0x1000000
405 mpeg3demux_open_title(demuxer
, 0);
406 mpeg3demux_seek_byte(demuxer
, TEST_START
);
408 !mpeg3demux_eof(demuxer
) &&
409 mpeg3demux_tell_byte(demuxer
) < TEST_START
+ TEST_LEN
)
411 result
= mpeg3_read_next_packet(demuxer
);
413 mpeg3demux_seek_byte(demuxer
, 0);
415 for(i
= 0; i
< MPEG3_MAX_STREAMS
; i
++)
417 if(demuxer
->astream_table
[i
]) atracks_empirical
++;
420 // Doesn't detect PCM audio or total number of tracks
422 * if(atracks && !atracks_empirical)
423 * for(i = 0; i < atracks; i++)
425 * int audio_mode = AUDIO_AC3;
426 * switch(audio->coding_mode)
428 * case 0: audio_mode = AUDIO_AC3; break;
429 * case 1: audio_mode = AUDIO_MPEG; break;
430 * case 2: audio_mode = AUDIO_MPEG; break;
431 * case 3: audio_mode = AUDIO_PCM; break;
433 * if(!demuxer->astream_table[i + 0x80]) demuxer->astream_table[i + 0x80] = audio_mode;
443 static mpeg3ifo_cell_t
* append_cell(mpeg3ifo_celltable_t
*table
)
445 if(!table
->cells
|| table
->total_cells
>= table
->cells_allocated
)
448 mpeg3ifo_cell_t
*new_cells
;
450 new_allocation
= table
->cells_allocated
? table
->cells_allocated
* 2 : 64;
451 new_cells
= calloc(1, sizeof(mpeg3ifo_cell_t
) * new_allocation
);
454 memcpy(new_cells
, table
->cells
, sizeof(mpeg3ifo_cell_t
) * table
->total_cells
);
457 table
->cells
= new_cells
;
458 table
->cells_allocated
= new_allocation
;
461 return &table
->cells
[table
->total_cells
++];
464 static void delete_celltable(mpeg3ifo_celltable_t
*table
)
466 if(table
->cells
) free(table
->cells
);
470 static void cellplayinfo(ifo_t
*ifo
, mpeg3ifo_celltable_t
*cells
)
473 char *cell_hdr
, *cell_hdr_start
, *cell_info
;
474 ifo_hdr_t
*hdr
= (ifo_hdr_t
*)ifo
->data
[ID_TITLE_PGCI
];
475 int program_chains
= bswap_16(hdr
->num
);
478 //printf("cellplayinfo\n");
479 for(j
= 0; j
< program_chains
; j
++)
482 pgci(hdr
, j
, &cell_hdr
);
483 cell_hdr_start
= cell_hdr
;
493 for(i
= 0; i
< 8; i
++) cell_hdr
+= 2;
495 for(i
= 0; i
< 32; i
++) cell_hdr
+= 4;
497 for(i
= 0; i
< 8; i
++) cell_hdr
++;
501 if(program_map(cell_hdr_start
, &cell_hdr
))
505 if(total_cells
= get_cellplayinfo((unsigned char*)cell_hdr_start
, (unsigned char**)&cell_hdr
))
507 //printf("cellplayinfo %d %d\n", j, total_cells);
508 cell_info
= cell_hdr
;
509 for(i
= 0; i
< total_cells
; i
++)
511 ifo_pgci_cell_addr_t
*cell_addr
= (ifo_pgci_cell_addr_t
*)cell_info
;
512 int64_t start_byte
= bswap_32(cell_addr
->vobu_start
);
513 int64_t end_byte
= bswap_32(cell_addr
->vobu_last_end
);
514 int cell_type
= cell_addr
->chain_info
;
516 if(!cells
->total_cells
&& start_byte
> 0)
519 if(!cells
->total_cells
||
520 end_byte
>= cells
->cells
[cells
->total_cells
- 1].end_byte
)
522 mpeg3ifo_cell_t
*cell
= append_cell(cells
);
524 cell
->start_byte
= start_byte
;
525 cell
->end_byte
= end_byte
;
526 cell
->cell_type
= cell_type
;
527 //printf("cellplayinfo start: %llx end: %llx type: %x\n",
528 // (int64_t)cell->start_byte * 0x800, (int64_t)cell->end_byte * 0x800, cell->cell_type);
530 cell_info
+= PGCI_CELL_ADDR_LEN
;
536 static void celladdresses(ifo_t
*ifo
, mpeg3ifo_celltable_t
*cell_addresses
)
539 char *ptr
= (char*)ifo
->data
[ID_TITLE_CELL_ADDR
];
541 cell_addr_hdr_t
*cell_addr_hdr
= (cell_addr_hdr_t
*)ptr
;
542 ifo_cell_addr_t
*cell_addr
= (ifo_cell_addr_t
*)(ptr
+ CADDR_HDR_LEN
);
544 //printf("celladdresses\n");
546 if(total_addresses
= bswap_32(cell_addr_hdr
->len
) / sizeof(ifo_cell_addr_t
))
548 for(i
= 0; i
< total_addresses
; i
++)
550 mpeg3ifo_cell_t
*cell
;
551 cell
= append_cell(cell_addresses
);
552 cell
->start_byte
= (int64_t)bswap_32(cell_addr
->start
);
553 cell
->end_byte
= (int64_t)bswap_32(cell_addr
->end
);
554 cell
->vob_id
= bswap_16(cell_addr
->vob_id
);
555 cell
->cell_id
= cell_addr
->cell_id
;
560 // Sort addresses by address instead of vob id
565 for(i
= 0; i
< total_addresses
- 1; i
++)
567 mpeg3ifo_cell_t
*cell1
, *cell2
;
568 cell1
= &cell_addresses
->cells
[i
];
569 cell2
= &cell_addresses
->cells
[i
+ 1];
571 if(cell1
->start_byte
> cell2
->start_byte
)
573 mpeg3ifo_cell_t temp
= *cell1
;
582 for(i
= 0; i
< total_addresses
; i
++)
584 mpeg3ifo_cell_t
*cell
= &cell_addresses
->cells
[i
];
588 static void finaltable(mpeg3ifo_celltable_t
*final_cells
,
589 mpeg3ifo_celltable_t
*cells
,
590 mpeg3ifo_celltable_t
*cell_addresses
)
592 int input_cell
= 0, current_address
= 0;
597 // Start and end bytes of programs
598 int64_t program_start_byte
[256], program_end_byte
[256];
600 final_cells
->total_cells
= 0;
601 final_cells
->cells_allocated
= cell_addresses
->total_cells
;
602 final_cells
->cells
= calloc(1, sizeof(mpeg3ifo_cell_t
) * final_cells
->cells_allocated
);
604 // Assign programs to cells
606 for(i
= cell_addresses
->total_cells
- 1; i
>= 0; i
--)
608 mpeg3ifo_cell_t
*input
= &cell_addresses
->cells
[i
];
609 mpeg3ifo_cell_t
*output
= &final_cells
->cells
[i
];
610 if(current_vobid
< 0) current_vobid
= input
->vob_id
;
613 // Reduce current vobid
614 if(input
->vob_id
< current_vobid
)
615 current_vobid
= input
->vob_id
;
617 // Get the current program number
618 if(input
->vob_id
> current_vobid
)
620 int current_program
= input
->vob_id
- current_vobid
;
621 output
->program
= current_program
;
623 // Get the last interleave by brute force
625 j
< cell_addresses
->total_cells
&& cell_addresses
->cells
[i
].cell_id
== cell_addresses
->cells
[j
].cell_id
;
628 int new_program
= final_cells
->cells
[j
].vob_id
- current_vobid
;
629 if(new_program
<= current_program
)
630 final_cells
->cells
[j
].program
= new_program
;
634 final_cells
->total_cells
++;
637 // Expand byte position and remove duplicates
638 for(i
= 0; i
< final_cells
->total_cells
; i
++)
640 if(i
< final_cells
->total_cells
- 1 &&
641 final_cells
->cells
[i
].start_byte
== final_cells
->cells
[i
+ 1].start_byte
)
643 for(j
= i
; j
< final_cells
->total_cells
- 1; j
++)
644 final_cells
->cells
[j
] = final_cells
->cells
[j
+ 1];
646 final_cells
->total_cells
--;
649 final_cells
->cells
[i
].start_byte
*= (int64_t)2048;
650 final_cells
->cells
[i
].end_byte
*= (int64_t)2048;
651 // End index seems to be inclusive
652 final_cells
->cells
[i
].end_byte
+= 2048;
657 printf("finaltable\n");
658 for(i
= 0; i
< final_cells
->total_cells
; i
++)
660 printf(" vob id: %x cell id: %x start: %llx end: %llx program: %x\n",
661 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
);
668 /* Read the title information from a ifo */
669 int mpeg3_read_ifo(mpeg3_t
*file
,
672 int64_t last_ifo_byte
= 0, first_ifo_byte
= 0;
673 mpeg3ifo_celltable_t
*cells
, *cell_addresses
, *final_cells
;
674 mpeg3_demuxer_t
*demuxer
= file
->demuxer
;
675 int current_title
= 0, current_cell
= 0;
678 int fd
= mpeg3io_get_fd(file
->fs
);
679 int64_t title_start_byte
= 0;
682 if(!(ifo
= ifo_open(fd
, 0)))
684 fprintf(stderr
, "read_ifo: Error decoding ifo.\n");
688 demuxer
->read_all
= 1;
689 cells
= calloc(1, sizeof(mpeg3ifo_celltable_t
));
690 cell_addresses
= calloc(1, sizeof(mpeg3ifo_celltable_t
));
691 final_cells
= calloc(1, sizeof(mpeg3ifo_celltable_t
));
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
,
701 // Get maximum program for program_bytes table
702 int total_programs
= 0;
705 for(i
= 0; i
< final_cells
->total_cells
; i
++)
707 mpeg3ifo_cell_t
*cell
= &final_cells
->cells
[i
];
708 if(cell
->program
> total_programs
- 1)
709 total_programs
= cell
->program
+ 1;
712 int64_t *program_bytes
= calloc(total_programs
, sizeof(int64_t));
715 // Clear out old cells
716 for(i
= 0; i
< demuxer
->total_titles
; i
++)
718 mpeg3_title_t
*title
= demuxer
->titles
[i
];
719 if(title
->cell_table
)
721 for(j
= 0; j
< title
->cell_table_size
; j
++)
723 free(title
->cell_table
);
724 title
->cell_table
= 0;
730 // Assign new cells to titles
731 while(final_cells
&& current_cell
< final_cells
->total_cells
)
733 mpeg3_title_t
*title
;
734 mpeg3ifo_cell_t
*cell
;
735 int64_t cell_start
, cell_end
;
738 title
= demuxer
->titles
[current_title
];
739 cell
= &final_cells
->cells
[current_cell
];
740 cell_start
= cell
->start_byte
;
741 cell_end
= cell
->end_byte
;
743 // Cell may be split by a title so handle in fragments.
744 while(cell_start
< cell_end
&& length
> 0)
746 length
= cell_end
- cell_start
;
748 // Clamp length to end of current title
749 if(cell_start
+ length
- title_start_byte
> title
->total_bytes
)
750 length
= title
->total_bytes
- cell_start
+ title_start_byte
;
752 //printf("%llx %llx %llx %llx\n", cell_end, cell_start, title_start_byte, length);
754 // Should never fail. If it does it means the length of the cells and the
755 // length of the titles don't match. The title lengths must match or else
756 // the cells won't line up.
759 int64_t program_start
= program_bytes
[cell
->program
];
760 int64_t program_end
= program_start
+ length
;
761 int64_t title_start
= cell_start
- title_start_byte
;
762 int64_t title_end
= title_start
+ length
;
763 mpeg3_new_cell(title
,
769 cell_start
+= length
;
770 program_bytes
[cell
->program
] += length
;
775 "read_ifo: cell length and title length don't match! title=%d cell=%d cell_start=%llx cell_end=%llx.\n",
778 cell_start
- title_start_byte
,
779 cell_end
- title_start_byte
);
781 // Try this out. It works for Contact where one VOB is 0x800 bytes longer than
782 // the cells in it but the next cell aligns perfectly with the next VOB.
783 if(current_title
< demuxer
->total_titles
- 1) current_cell
--;
787 if(cell_start
- title_start_byte
>= title
->total_bytes
&&
788 current_title
< demuxer
->total_titles
- 1)
790 title_start_byte
+= title
->total_bytes
;
791 title
= demuxer
->titles
[++current_title
];
798 delete_celltable(cells
);
799 delete_celltable(cell_addresses
);
800 delete_celltable(final_cells
);