📄 mpeg3ifo.c
字号:
#include <mpeg4ip.h>#ifdef HAVE_BYTESWAP_H#include <byteswap.h>#endif#include <mpeg4ip_byteswap.h>#include <dirent.h>#include <fcntl.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <unistd.h>#include "ifo.h"#include "mpeg3private.h"#include "mpeg3protos.h"typedef struct{ int64_t start_byte; int64_t end_byte;// Used in final table int program;// Used in cell play info int cell_type;// Used in cell addresses int vob_id; int cell_id;} mpeg3ifo_cell_t;typedef struct{ mpeg3ifo_cell_t *cells; long total_cells; long cells_allocated;} mpeg3ifo_celltable_t;#define CADDR_HDR_LEN 8typedef struct { u_short num : 16; // Number of Video Objects u_short unknown : 16; // don't know u_int len : 32; // length of table} cell_addr_hdr_t;typedef struct { u_int foo : 16; // ??? u_int num : 16; // number of subchannels} audio_hdr_t;#define AUDIO_HDR_LEN 4typedef struct { u_short id : 16; // Language u_short : 16; // don't know u_int start : 32; // Start of unit} pgci_sub_t;#define PGCI_SUB_LEN 8#define PGCI_COLOR_LEN 4static u_int get4bytes(u_char *buf){ return B2N_32(*((uint32_t *)buf));}static u_int get2bytes(u_char *buf){ return B2N_16(*((uint16_t *)buf));}static int ifo_read(int fd, long pos, long count, unsigned char *data){ if((pos = lseek(fd, pos, SEEK_SET)) < 0) { perror("ifo_read"); return -1; } return read(fd, data, count); }#define OFF_PTT get4bytes (ifo->data[ID_MAT] + 0xC8)#define OFF_TITLE_PGCI get4bytes (ifo->data[ID_MAT] + 0xCC)#define OFF_MENU_PGCI get4bytes (ifo->data[ID_MAT] + 0xD0)#define OFF_TMT get4bytes (ifo->data[ID_MAT] + 0xD4)#define OFF_MENU_CELL_ADDR get4bytes (ifo->data[ID_MAT] + 0xD8)#define OFF_MENU_VOBU_ADDR_MAP get4bytes (ifo->data[ID_MAT] + 0xDC)#define OFF_TITLE_CELL_ADDR get4bytes (ifo->data[ID_MAT] + 0xE0)#define OFF_TITLE_VOBU_ADDR_MAP get4bytes (ifo->data[ID_MAT] + 0xE4)#define OFF_VMG_TSP get4bytes (ifo->data[ID_MAT] + 0xC4)#define OFF_VMG_MENU_PGCI get4bytes (ifo->data[ID_MAT] + 0xC8)#define OFF_VMG_TMT get4bytes (ifo->data[ID_MAT] + 0xD0)static int ifo_vts(ifo_t *ifo){ if(!strncmp((char*)ifo->data[ID_MAT], "DVDVIDEO-VTS", 12)) return 0; return -1;}static int ifo_vmg(ifo_t *ifo){ if(!strncmp((char*)ifo->data[ID_MAT], "DVDVIDEO-VMG", 12)) return 0; return -1;}static int ifo_table(ifo_t *ifo, unsigned long offset, unsigned long tbl_id){ unsigned char *data; unsigned long len = 0; int i; uint32_t *ptr; if(!offset) return -1; data = (u_char *)calloc(1, DVD_VIDEO_LB_LEN); if(ifo_read(ifo->fd, ifo->pos + offset * DVD_VIDEO_LB_LEN, DVD_VIDEO_LB_LEN, data) <= 0) { perror("ifo_table"); return -1; } switch(tbl_id) { case ID_TITLE_VOBU_ADDR_MAP: case ID_MENU_VOBU_ADDR_MAP: len = get4bytes(data) + 1; break; default: { ifo_hdr_t *hdr = (ifo_hdr_t *)data; len = B2N_32(hdr->len) + 1; } } if(len > DVD_VIDEO_LB_LEN) { data = (u_char *)realloc((void *)data, len); bzero(data, len); ifo_read(ifo->fd, ifo->pos + offset * DVD_VIDEO_LB_LEN, len, data); } ifo->data[tbl_id] = data; ptr = (uint32_t*)data; len /= 4; if(tbl_id == ID_TMT) for (i = 0; i < len; i++) ptr[i] = B2N_32(ptr[i]); return 0;}static ifo_t* ifo_open(int fd, long pos){ ifo_t *ifo; ifo = (ifo_t *)calloc(sizeof(ifo_t), 1); ifo->data[ID_MAT] = (unsigned char *)calloc(DVD_VIDEO_LB_LEN, 1); ifo->pos = pos; ifo->fd = fd; if(ifo_read(fd, pos, DVD_VIDEO_LB_LEN, ifo->data[ID_MAT]) < 0) { perror("ifo_open"); free(ifo->data[ID_MAT]); free(ifo); return NULL; } ifo->num_menu_vobs = get4bytes(ifo->data[ID_MAT] + 0xC0); ifo->vob_start = get4bytes(ifo->data[ID_MAT] + 0xC4);#ifdef DEBUG printf ("num of vobs: %x vob_start %x\n", ifo->num_menu_vobs, ifo->vob_start);#endif if(!ifo_vts(ifo)) { ifo_table(ifo, OFF_PTT, ID_PTT); ifo_table(ifo, OFF_TITLE_PGCI, ID_TITLE_PGCI); ifo_table(ifo, OFF_MENU_PGCI, ID_MENU_PGCI); ifo_table(ifo, OFF_TMT, ID_TMT); ifo_table(ifo, OFF_MENU_CELL_ADDR, ID_MENU_CELL_ADDR); ifo_table(ifo, OFF_MENU_VOBU_ADDR_MAP, ID_MENU_VOBU_ADDR_MAP); ifo_table(ifo, OFF_TITLE_CELL_ADDR, ID_TITLE_CELL_ADDR); ifo_table(ifo, OFF_TITLE_VOBU_ADDR_MAP, ID_TITLE_VOBU_ADDR_MAP); } else if(!ifo_vmg(ifo)) { ifo_table(ifo, OFF_VMG_TSP, ID_TSP); ifo_table(ifo, OFF_VMG_MENU_PGCI, ID_MENU_PGCI); ifo_table(ifo, OFF_VMG_TMT, ID_TMT); ifo_table(ifo, OFF_TITLE_CELL_ADDR, ID_TITLE_CELL_ADDR); ifo_table(ifo, OFF_TITLE_VOBU_ADDR_MAP, ID_TITLE_VOBU_ADDR_MAP); } return ifo;}static int ifo_close(ifo_t *ifo){ if(ifo->data[ID_MAT]) free(ifo->data[ID_MAT]); if(ifo->data[ID_PTT]) free(ifo->data[ID_PTT]); if(ifo->data[ID_TITLE_PGCI]) free(ifo->data[ID_TITLE_PGCI]); if(ifo->data[ID_MENU_PGCI]) free(ifo->data[ID_MENU_PGCI]); if(ifo->data[ID_TMT]) free(ifo->data[ID_TMT]); if(ifo->data[ID_MENU_CELL_ADDR]) free(ifo->data[ID_MENU_CELL_ADDR]); if(ifo->data[ID_MENU_VOBU_ADDR_MAP]) free(ifo->data[ID_MENU_VOBU_ADDR_MAP]); if(ifo->data[ID_TITLE_CELL_ADDR]) free(ifo->data[ID_TITLE_CELL_ADDR]); if(ifo->data[ID_TITLE_VOBU_ADDR_MAP]) free(ifo->data[ID_TITLE_VOBU_ADDR_MAP]); free(ifo); return 0;}static int ifo_audio(char *_hdr, char **ptr){ audio_hdr_t *hdr = (audio_hdr_t *)_hdr; if(!_hdr) return -1; *ptr = _hdr + AUDIO_HDR_LEN; return B2N_16(hdr->num);}static int pgci(ifo_hdr_t *hdr, int title, char **ptr){ pgci_sub_t *pgci_sub; uint32_t temp; *ptr = (char *) hdr; if(!*ptr) return -1; if(title > hdr->num) return -1; *ptr += IFO_HDR_LEN; pgci_sub = (pgci_sub_t *)*ptr + title; temp = pgci_sub->start; temp = B2N_32(temp); *ptr = (char *)hdr + temp; return 0;}static int program_map(char *pgc, char **ptr){ int num; *ptr = pgc; if (!pgc) return -1; *ptr += 2; num = **ptr; *ptr += 10; *ptr += 8 * 2; // AUDIO *ptr += 32 * 4; // SUBPICTURE *ptr += 8; *ptr += 16 * PGCI_COLOR_LEN; // CLUT *ptr += 2; *ptr = get2bytes((unsigned char*)*ptr) + pgc; return num;}static u_int get_cellplayinfo(u_char *pgc, u_char **ptr){ u_int num; *ptr = pgc; if (!pgc) return -1; *ptr += 3; num = **ptr; *ptr += 9; *ptr += 8 * 2; // AUDIO *ptr += 32 * 4; // SUBPICTURE *ptr += 8; *ptr += 16 * PGCI_COLOR_LEN; // CLUT *ptr += 4; *ptr = get2bytes(*ptr) + pgc; return num;}static void get_ifo_playlist(mpeg3_t *file, mpeg3_demuxer_t *demuxer){ DIR *dirstream; char directory[MPEG3_STRLEN]; char filename[MPEG3_STRLEN]; char complete_path[MPEG3_STRLEN]; char title_path[MPEG3_STRLEN]; char vob_prefix[MPEG3_STRLEN]; struct dirent *new_filename; char *ptr; int64_t total_bytes = 0; int done = 0, i;// Get titles matching ifo file mpeg3io_complete_path(complete_path, file->fs->path); mpeg3io_get_directory(directory, complete_path); mpeg3io_get_filename(filename, complete_path); strncpy(vob_prefix, filename, 6); dirstream = opendir(directory); while(new_filename = readdir(dirstream)) { if(!strncasecmp(new_filename->d_name, vob_prefix, 6)) { ptr = strrchr(new_filename->d_name, '.'); if(ptr && !strncasecmp(ptr, ".vob", 4)) {// Got a title if(atol(&new_filename->d_name[7]) > 0) { mpeg3_title_t *title; mpeg3io_joinpath(title_path, directory, new_filename->d_name); title = demuxer->titles[demuxer->total_titles++] = mpeg3_new_title(file, title_path); title->total_bytes = mpeg3io_path_total_bytes(title_path); total_bytes += title->total_bytes;//printf("%s\n", title_path); } } } }// Alphabetize titles. Only problematic for guys who rip entire DVD's// to their hard drives while retaining the file structure. while(!done) { done = 1; for(i = 0; i < demuxer->total_titles - 1; i++) { if(strcmp(demuxer->titles[i]->fs->path, demuxer->titles[i + 1]->fs->path) > 0) { mpeg3_title_t *temp = demuxer->titles[i]; demuxer->titles[i] = demuxer->titles[i + 1]; demuxer->titles[i + 1] = temp; done = 0; } } } }// IFO parsingstatic void get_ifo_header(mpeg3_demuxer_t *demuxer, ifo_t *ifo){ int i;// Video header demuxer->vstream_table[0] = 1;// Audio header if(!ifo_vts(ifo)) { ifo_audio_t *audio; int result = 0;// Doesn't detect number of tracks. int atracks = ifo_audio((char*)ifo->data[ID_MAT] + IFO_OFFSET_AUDIO, (char**)&audio); int atracks_empirical = 0;// Construct audio stream id's#define TEST_START 0x600000#define TEST_LEN 0x100000 mpeg3demux_open_title(demuxer, 0); mpeg3demux_seek_byte(demuxer, TEST_START); while(!result && !mpeg3demux_eof(demuxer) && mpeg3demux_tell(demuxer) < TEST_START + TEST_LEN) { result = mpeg3_read_next_packet(demuxer);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -