📄 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 + -