📄 mpeg3ifo.c
字号:
}
mpeg3demux_seek_byte(demuxer, 0);
for(i = 0; i < MPEG3_MAX_STREAMS; i++)
{
//printf("%x %d\n", i, demuxer->astream_table[i]);
if(demuxer->astream_table[i]) atracks_empirical++;
}
// Doesn't detect PCM audio or total number of tracks
/*
* if(atracks && !atracks_empirical)
* for(i = 0; i < atracks; i++)
* {
* int audio_mode = AUDIO_AC3;
* switch(audio->coding_mode)
* {
* case 0: audio_mode = AUDIO_AC3; break;
* case 1: audio_mode = AUDIO_MPEG; break;
* case 2: audio_mode = AUDIO_MPEG; break;
* case 3: audio_mode = AUDIO_PCM; break;
* }
* if(!demuxer->astream_table[i + 0x80]) demuxer->astream_table[i + 0x80] = audio_mode;
* }
*/
}
else
if(!ifo_vmg(ifo))
{
}
}
static mpeg3ifo_cell_t* append_cell(mpeg3ifo_celltable_t *table)
{
if(!table->cells || table->total_cells >= table->cells_allocated)
{
long new_allocation;
mpeg3ifo_cell_t *new_cells;
new_allocation = table->cells_allocated ? table->cells_allocated * 2 : 64;
new_cells = calloc(1, sizeof(mpeg3ifo_cell_t) * new_allocation);
if(table->cells)
{
memcpy(new_cells, table->cells, sizeof(mpeg3ifo_cell_t) * table->total_cells);
free(table->cells);
}
table->cells = new_cells;
table->cells_allocated = new_allocation;
}
return &table->cells[table->total_cells++];
}
static void delete_celltable(mpeg3ifo_celltable_t *table)
{
if(table->cells) free(table->cells);
free(table);
}
static void cellplayinfo(ifo_t *ifo, mpeg3ifo_celltable_t *cells)
{
int i, j;
char *cell_hdr, *cell_hdr_start, *cell_info;
ifo_hdr_t *hdr = (ifo_hdr_t*)ifo->data[ID_TITLE_PGCI];
int program_chains = B2N_16(hdr->num);
long total_cells;
//printf("cellplayinfo\n");
for(j = 0; j < program_chains; j++)
{
// Cell header
pgci(hdr, j, &cell_hdr);
cell_hdr_start = cell_hdr;
// Unknown
cell_hdr += 2;
// Num programs
cell_hdr += 2;
// Chain Time
cell_hdr += 4;
// Unknown
cell_hdr += 4;
// Subaudio streams
for(i = 0; i < 8; i++) cell_hdr += 2;
// Subpictures
for(i = 0; i < 32; i++) cell_hdr += 4;
// Unknown
for(i = 0; i < 8; i++) cell_hdr++;
// Skip CLUT
// Skip PGC commands
// Program map
if(program_map(cell_hdr_start, &cell_hdr))
;
// Cell Positions
if(total_cells = get_cellplayinfo((unsigned char*)cell_hdr_start, (unsigned char**)&cell_hdr))
{
//printf("cellplayinfo %d %d\n", j, total_cells);
cell_info = cell_hdr;
for(i = 0; i < total_cells; i++)
{
ifo_pgci_cell_addr_t *cell_addr = (ifo_pgci_cell_addr_t *)cell_info;
long start_byte = B2N_32(cell_addr->vobu_start);
long end_byte = B2N_32(cell_addr->vobu_last_end);
int cell_type = cell_addr->chain_info;
if(!cells->total_cells && start_byte > 0)
start_byte = 0;
if(!cells->total_cells ||
end_byte >= cells->cells[cells->total_cells - 1].end_byte)
{
mpeg3ifo_cell_t *cell = append_cell(cells);
cell->start_byte = start_byte;
cell->end_byte = end_byte;
cell->cell_type = cell_type;
//printf("cellplayinfo start: %llx end: %llx type: %x\n",
// (int64_t)cell->start_byte * 0x800, (int64_t)cell->end_byte * 0x800, cell->cell_type);
}
cell_info += PGCI_CELL_ADDR_LEN;
}
}
}
}
static void celladdresses(ifo_t *ifo, mpeg3ifo_celltable_t *cell_addresses)
{
int i;
char *ptr = (char*)ifo->data[ID_TITLE_CELL_ADDR];
int total_addresses;
cell_addr_hdr_t *cell_addr_hdr = (cell_addr_hdr_t*)ptr;
ifo_cell_addr_t *cell_addr = (ifo_cell_addr_t*)(ptr + CADDR_HDR_LEN);
int done = 0;
//printf("celladdresses\n");
if(total_addresses = B2N_32(cell_addr_hdr->len) / sizeof(ifo_cell_addr_t))
{
for(i = 0; i < total_addresses; i++)
{
mpeg3ifo_cell_t *cell;
cell = append_cell(cell_addresses);
cell->start_byte = (int64_t)B2N_32(cell_addr->start);
cell->end_byte = (int64_t)B2N_32(cell_addr->end);
cell->vob_id = B2N_16(cell_addr->vob_id);
cell->cell_id = cell_addr->cell_id;
/*
* printf("celladdresses vob id: %x cell id: %x start: %ld end: %ld\n",
* B2N_16(cell_addr->vob_id), cell_addr->cell_id, (long)cell->start_byte, (long)cell->end_byte);
*/
cell_addr++;
}
}
// Sort addresses by address instead of vob id
done = 0;
while(!done)
{
done = 1;
for(i = 0; i < total_addresses - 1; i++)
{
mpeg3ifo_cell_t *cell1, *cell2;
cell1 = &cell_addresses->cells[i];
cell2 = &cell_addresses->cells[i + 1];
if(cell1->start_byte > cell2->start_byte)
{
mpeg3ifo_cell_t temp = *cell1;
*cell1 = *cell2;
*cell2 = temp;
done = 0;
break;
}
}
}
for(i = 0; i < total_addresses; i++)
{
mpeg3ifo_cell_t *cell = &cell_addresses->cells[i];
//printf("celladdresses vob id: %x cell id: %x start: %ld end: %ld\n",
// cell->vob_id, cell->cell_id, (long)cell->start_byte, (long)cell->end_byte);
}
}
static void finaltable(mpeg3ifo_celltable_t *final_cells,
mpeg3ifo_celltable_t *cells,
mpeg3ifo_celltable_t *cell_addresses)
{
int input_cell = 0, current_address = 0;
int output_cell = 0;
int done;
int i, j;
int current_vobid;
// Start and end bytes of programs
long program_start_byte[256], program_end_byte[256];
final_cells->total_cells = 0;
final_cells->cells_allocated = cell_addresses->total_cells;
final_cells->cells = calloc(1, sizeof(mpeg3ifo_cell_t) * final_cells->cells_allocated);
// Assign programs to cells
current_vobid = -1;
for(i = cell_addresses->total_cells - 1; i >= 0; i--)
{
mpeg3ifo_cell_t *input = &cell_addresses->cells[i];
mpeg3ifo_cell_t *output = &final_cells->cells[i];
if(current_vobid < 0) current_vobid = input->vob_id;
*output = *input;
// Reduce current vobid
if(input->vob_id < current_vobid)
current_vobid = input->vob_id;
else
// Get the current program number
if(input->vob_id > current_vobid)
{
int current_program = input->vob_id - current_vobid;
output->program = current_program;
// Get the last interleave by brute force
for(j = i;
j < cell_addresses->total_cells && cell_addresses->cells[i].cell_id == cell_addresses->cells[j].cell_id;
j++)
{
int new_program = final_cells->cells[j].vob_id - current_vobid;
if(new_program <= current_program)
final_cells->cells[j].program = new_program;
}
}
final_cells->total_cells++;
}
// Expand byte position and remove duplicates
for(i = 0; i < final_cells->total_cells; i++)
{
if(i < final_cells->total_cells - 1 &&
final_cells->cells[i].start_byte == final_cells->cells[i + 1].start_byte)
{
for(j = i; j < final_cells->total_cells - 1; j++)
final_cells->cells[j] = final_cells->cells[j + 1];
final_cells->total_cells--;
}
final_cells->cells[i].start_byte *= (int64_t)2048;
final_cells->cells[i].end_byte *= (int64_t)2048;
}
return;
// Debug
printf("finaltable\n");
for(i = 0; i < final_cells->total_cells; i++)
{
printf(" vob id: %x cell id: %x start: %llx end: %llx program: %x\n",
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);
}
}
/* Read the title information from a ifo */
static int read_ifo(mpeg3_t *file,
mpeg3_demuxer_t *demuxer,
int read_timecodes)
{
int64_t last_ifo_byte = 0, first_ifo_byte = 0;
mpeg3ifo_celltable_t *cells, *cell_addresses, *final_cells;
int current_title = 0, current_cell = 0;
int i;
ifo_t *ifo;
int fd = mpeg3io_get_fd(file->fs);
int64_t title_start_byte = 0;
int result;
//printf("read_ifo 1\n");
if(!(ifo = ifo_open(fd, 0)))
{
fprintf(stderr, "read_ifo: Error decoding ifo.\n");
return 1;
}
//printf("read_ifo 1\n");
// file->packet_size = 2048;
demuxer->read_all = 1;
cells = calloc(1, sizeof(mpeg3ifo_celltable_t));
cell_addresses = calloc(1, sizeof(mpeg3ifo_celltable_t));
final_cells = calloc(1, sizeof(mpeg3ifo_celltable_t));
//printf("read_ifo 1\n");
get_ifo_playlist(file, demuxer);
get_ifo_header(demuxer, ifo);
cellplayinfo(ifo, cells);
celladdresses(ifo, cell_addresses);
finaltable(final_cells,
cells,
cell_addresses);
//printf("read_ifo 2\n");
// Assign cells to titles
while(final_cells && current_cell < final_cells->total_cells)
{
mpeg3_title_t *title;
mpeg3ifo_cell_t *cell;
int64_t cell_start, cell_end;
int64_t length = 1;
title = demuxer->titles[current_title];
cell = &final_cells->cells[current_cell];
cell_start = cell->start_byte;
cell_end = cell->end_byte;
//printf("read_ifo 1 %d %llx %llx %d\n", current_cell, (int64_t)cell->start_byte, (int64_t)cell->end_byte, cell->program);
while(cell_start < cell_end && length)
{
length = cell_end - cell_start;
if(cell_start + length - title_start_byte > title->total_bytes)
length = title->total_bytes - cell_start + title_start_byte;
//printf("read_ifo 3 %llx - %llx + %llx = %llx\n", title->total_bytes, cell_start, title_start_byte, length);
// Should never fail. If it does it means the length of the cells and the
// length of the titles don't match. The title lengths must match or else
// the cells won't line up.
if(length)
{
mpeg3_new_timecode(title,
(long)(cell_start - title_start_byte),
0,
(long)(cell_start - title_start_byte + length),
0,
cell->program);
cell_start += length;
}
else
{
fprintf(stderr, "read_ifo: cell length and title length don't match.\n");
}
// Advance title
if(cell_start - title_start_byte >= title->total_bytes &&
current_title < demuxer->total_titles - 1)
{
title_start_byte += title->total_bytes;
title = demuxer->titles[++current_title];
}
}
current_cell++;
}
//printf("read_ifo 4\n");
// Look up time values for the timecodes
// Should only be used for building a TOC
if(read_timecodes)
{
for(current_title = 0; current_title < demuxer->total_titles; current_title++)
{
mpeg3_title_t *title = demuxer->titles[current_title];
mpeg3demux_open_title(demuxer, current_title);
for(i = 0; i < title->timecode_table_size; i++)
{
mpeg3demux_timecode_t *timecode = &title->timecode_table[i];
mpeg3io_seek(title->fs, timecode->start_byte);
mpeg3_read_next_packet(demuxer);
timecode->start_time = demuxer->time;
mpeg3io_seek(title->fs, timecode->end_byte);
if(timecode->end_byte >= title->total_bytes)
mpeg3_read_prev_packet(demuxer);
else
mpeg3_read_next_packet(demuxer);
timecode->end_time = demuxer->time;
}
}
mpeg3demux_open_title(demuxer, 0);
}
//for(i = 0; i < demuxer->total_titles; i++) mpeg3_dump_title(demuxer->titles[i]);
delete_celltable(cells);
delete_celltable(cell_addresses);
delete_celltable(final_cells);
ifo_close(ifo);
//printf("read_ifo 5\n");
mpeg3demux_assign_programs(demuxer);
//printf("read_ifo 6\n");
return 0;
}
int mpeg3_read_ifo(mpeg3_t *file, int read_timecodes)
{
file->is_program_stream = 1;
read_ifo(file, file->demuxer, read_timecodes);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -