⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpeg3ifo.c

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 C
📖 第 1 页 / 共 2 页
字号:
#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 8

typedef 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 4

typedef 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 4


static u_int get4bytes(u_char *buf)
{
	return B2N_32(*((u_int32_t *)buf));
}

static u_int get2bytes(u_char *buf)
{
	return B2N_16(*((u_int16_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;
	u_int32_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 = (u_int32_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 parsing
static 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 + -