📄 libmpeg3.c
字号:
#include "libmpeg3.h"
#include "mpeg3protos.h"
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
mpeg3_t* mpeg3_new(const char *path)
{
int i;
mpeg3_t *file = calloc(1, sizeof(mpeg3_t));
file->cpus = 1;
file->fs = mpeg3_new_fs(path);
file->demuxer = mpeg3_new_demuxer(file, 0, 0, -1);
file->seekable = 1;
return file;
}
int mpeg3_delete(mpeg3_t *file)
{
int i;
for(i = 0; i < file->total_vstreams; i++)
mpeg3_delete_vtrack(file, file->vtrack[i]);
for(i = 0; i < file->total_astreams; i++)
mpeg3_delete_atrack(file, file->atrack[i]);
mpeg3_delete_fs(file->fs);
mpeg3_delete_demuxer(file->demuxer);
if(file->frame_offsets)
{
for(i = 0; i < file->total_vstreams; i++)
{
free(file->frame_offsets[i]);
free(file->keyframe_numbers[i]);
}
free(file->frame_offsets);
free(file->keyframe_numbers);
free(file->total_frame_offsets);
free(file->total_keyframe_numbers);
}
if(file->sample_offsets)
{
for(i = 0; i < file->total_astreams; i++)
free(file->sample_offsets[i]);
free(file->sample_offsets);
free(file->total_sample_offsets);
}
free(file);
return 0;
}
int mpeg3_check_sig(const char *path)
{
mpeg3_fs_t *fs;
u_int32_t bits;
char *ext;
int result = 0;
fs = mpeg3_new_fs(path);
if(mpeg3io_open_file(fs))
{
/* File not found */
return 0;
}
bits = mpeg3io_read_int32(fs);
/* Test header */
if(bits == MPEG3_TOC_PREFIX)
{
result = 1;
}
else
if((((bits >> 24) & 0xff) == MPEG3_SYNC_BYTE) ||
(bits == MPEG3_PACK_START_CODE) ||
((bits & 0xfff00000) == 0xfff00000) ||
((bits & 0xffff0000) == 0xffe30000) ||
(bits == MPEG3_SEQUENCE_START_CODE) ||
(bits == MPEG3_PICTURE_START_CODE) ||
(((bits & 0xffff0000) >> 16) == MPEG3_AC3_START_CODE) ||
((bits >> 8) == MPEG3_ID3_PREFIX) ||
(bits == MPEG3_RIFF_CODE) ||
(bits == MPEG3_IFO_PREFIX))
{
result = 1;
ext = strrchr(path, '.');
if(ext)
{
/* Test file extension. */
if(strncasecmp(ext, ".ifo", 4) &&
strncasecmp(ext, ".mp2", 4) &&
strncasecmp(ext, ".mp3", 4) &&
strncasecmp(ext, ".m1v", 4) &&
strncasecmp(ext, ".m2v", 4) &&
strncasecmp(ext, ".m2s", 4) &&
strncasecmp(ext, ".mpg", 4) &&
strncasecmp(ext, ".vob", 4) &&
strncasecmp(ext, ".mpeg", 4) &&
strncasecmp(ext, ".ac3", 4))
result = 0;
}
}
mpeg3io_close_file(fs);
mpeg3_delete_fs(fs);
return result;
}
static uint32_t read_int32(unsigned char *buffer, int *position)
{
uint32_t temp;
if(MPEG3_LITTLE_ENDIAN)
{
((unsigned char*)&temp)[3] = buffer[(*position)++];
((unsigned char*)&temp)[2] = buffer[(*position)++];
((unsigned char*)&temp)[1] = buffer[(*position)++];
((unsigned char*)&temp)[0] = buffer[(*position)++];
}
else
{
((unsigned char*)&temp)[0] = buffer[(*position)++];
((unsigned char*)&temp)[1] = buffer[(*position)++];
((unsigned char*)&temp)[2] = buffer[(*position)++];
((unsigned char*)&temp)[3] = buffer[(*position)++];
}
return temp;
}
static uint64_t read_int64(unsigned char *buffer, int *position)
{
uint64_t temp;
if(MPEG3_LITTLE_ENDIAN)
{
((unsigned char*)&temp)[7] = buffer[(*position)++];
((unsigned char*)&temp)[6] = buffer[(*position)++];
((unsigned char*)&temp)[5] = buffer[(*position)++];
((unsigned char*)&temp)[4] = buffer[(*position)++];
((unsigned char*)&temp)[3] = buffer[(*position)++];
((unsigned char*)&temp)[2] = buffer[(*position)++];
((unsigned char*)&temp)[1] = buffer[(*position)++];
((unsigned char*)&temp)[0] = buffer[(*position)++];
}
else
{
((unsigned char*)&temp)[0] = buffer[(*position)++];
((unsigned char*)&temp)[1] = buffer[(*position)++];
((unsigned char*)&temp)[2] = buffer[(*position)++];
((unsigned char*)&temp)[3] = buffer[(*position)++];
((unsigned char*)&temp)[4] = buffer[(*position)++];
((unsigned char*)&temp)[5] = buffer[(*position)++];
((unsigned char*)&temp)[6] = buffer[(*position)++];
((unsigned char*)&temp)[7] = buffer[(*position)++];
}
return temp;
}
static int read_toc(mpeg3_t *file)
{
unsigned char *buffer;
int file_type;
int position = 4;
int stream_type;
int atracks;
int vtracks;
int i, j;
buffer = malloc(mpeg3io_total_bytes(file->fs));
mpeg3io_seek(file->fs, 0);
mpeg3io_read_data(buffer, mpeg3io_total_bytes(file->fs), file->fs);
//printf("read_toc %lld\n", mpeg3io_total_bytes(file->fs));
// File type
file_type = buffer[position++];
switch(file_type)
{
case FILE_TYPE_PROGRAM:
file->is_program_stream = 1;
break;
case FILE_TYPE_TRANSPORT:
file->is_transport_stream = 1;
break;
case FILE_TYPE_AUDIO:
file->is_audio_stream = 1;
break;
case FILE_TYPE_VIDEO:
file->is_video_stream = 1;
break;
}
// Stream ID's
while((stream_type = buffer[position]) != TITLE_PATH)
{
int offset;
int stream_id;
//printf("read_toc %d %x\n", position, buffer[position]);
position++;
offset = read_int32(buffer, &position);
stream_id = read_int32(buffer, &position);
if(stream_type == STREAM_AUDIO)
{
file->demuxer->astream_table[offset] = stream_id;
}
if(stream_type == STREAM_VIDEO)
{
file->demuxer->vstream_table[offset] = stream_id;
}
}
// Titles
while(buffer[position] == TITLE_PATH)
{
char string[MPEG3_STRLEN];
int string_len = 0;
mpeg3_title_t *title;
position++;
while(buffer[position] != 0) string[string_len++] = buffer[position++];
string[string_len++] = 0;
position++;
title =
file->demuxer->titles[file->demuxer->total_titles++] =
mpeg3_new_title(file, string);
title->total_bytes = read_int64(buffer, &position);
// Cells
title->timecode_table_size =
title->timecode_table_allocation =
read_int32(buffer, &position);
title->timecode_table = calloc(title->timecode_table_size, sizeof(mpeg3demux_timecode_t));
for(i = 0; i < title->timecode_table_size; i++)
{
title->timecode_table[i].start_byte = read_int64(buffer, &position);
title->timecode_table[i].end_byte = read_int64(buffer, &position);
title->timecode_table[i].program = read_int32(buffer, &position);
}
}
// Audio streams
// Skip ATRACK_COUNT
position++;
atracks = read_int32(buffer, &position);
// Skip VTRACK_COUNT
position++;
vtracks = read_int32(buffer, &position);
if(atracks)
{
file->sample_offsets = malloc(sizeof(int64_t*) * atracks);
file->total_sample_offsets = malloc(sizeof(int*) * atracks);
for(i = 0; i < atracks; i++)
{
file->total_sample_offsets[i] = read_int32(buffer, &position);
file->sample_offsets[i] = malloc(file->total_sample_offsets[i] * sizeof(int64_t));
for(j = 0; j < file->total_sample_offsets[i]; j++)
{
file->sample_offsets[i][j] = read_int64(buffer, &position);
//printf("samples %llx\n", file->sample_offsets[i][j]);
}
}
}
if(vtracks)
{
file->frame_offsets = malloc(sizeof(int64_t*) * vtracks);
file->total_frame_offsets = malloc(sizeof(int*) * vtracks);
file->keyframe_numbers = malloc(sizeof(int64_t*) * vtracks);
file->total_keyframe_numbers = malloc(sizeof(int*) * vtracks);
for(i = 0; i < vtracks; i++)
{
file->total_frame_offsets[i] = read_int32(buffer, &position);
file->frame_offsets[i] = malloc(file->total_frame_offsets[i] * sizeof(int64_t));
for(j = 0; j < file->total_frame_offsets[i]; j++)
{
file->frame_offsets[i][j] = read_int64(buffer, &position);
//printf("frame %llx\n", file->frame_offsets[i][j]);
}
file->total_keyframe_numbers[i] = read_int32(buffer, &position);
file->keyframe_numbers[i] = malloc(file->total_keyframe_numbers[i] * sizeof(int64_t));
for(j = 0; j < file->total_keyframe_numbers[i]; j++)
{
file->keyframe_numbers[i][j] = read_int64(buffer, &position);
}
}
}
free(buffer);
//printf("read_toc 1\n");
mpeg3demux_open_title(file->demuxer, 0);
//printf("read_toc 2 %llx\n", mpeg3demux_tell(file->demuxer));
return 0;
}
mpeg3_t* mpeg3_open_copy(const char *path, mpeg3_t *old_file)
{
mpeg3_t *file = 0;
unsigned int bits;
int i, done;
/* Initialize the file structure */
file = mpeg3_new(path);
//printf("mpeg3_open_copy %s\n", path);
/* Need to perform authentication before reading a single byte. */
if(mpeg3io_open_file(file->fs))
{
mpeg3_delete(file);
return 0;
}
/* =============================== Create the title objects ========================= */
bits = mpeg3io_read_int32(file->fs);
//printf("mpeg3_open 1 %p %d %d %d %d\n", old_file, file->is_transport_stream, file->is_program_stream, file->is_video_stream, file->is_audio_stream);
if(bits == MPEG3_TOC_PREFIX) /* TOC */
{
/* Table of contents for another title set */
if(!old_file)
{
//printf("libmpeg3 1\n");
if(read_toc(file))
{
//printf("libmpeg3 1\n");
mpeg3io_close_file(file->fs);
mpeg3_delete(file);
return 0;
}
//printf("libmpeg3 1\n");
}
mpeg3io_close_file(file->fs);
}
else
// IFO file
#ifndef _WIN32
if(bits == MPEG3_IFO_PREFIX)
{
//printf("libmpeg3 1\n");
if(!old_file)
{
//printf("libmpeg3 2\n");
if(mpeg3_read_ifo(file, 0))
{
mpeg3_delete(file);
mpeg3io_close_file(file->fs);
return 0;
}
//printf("libmpeg3 3\n");
}
file->is_ifo_file = 1;
mpeg3io_close_file(file->fs);
}
else
#endif
if(((bits >> 24) & 0xff) == MPEG3_SYNC_BYTE)
{
/* Transport stream */
//printf("libmpeg3 2\n");
file->is_transport_stream = 1;
}
else
if(bits == MPEG3_PACK_START_CODE)
{
/* Program stream */
/* Determine packet size empirically */
//printf("libmpeg3 3\n");
file->is_program_stream = 1;
}
else
if((bits & 0xfff00000) == 0xfff00000 ||
(bits & 0xffff0000) == 0xffe30000 ||
((bits >> 8) == MPEG3_ID3_PREFIX) ||
(bits == MPEG3_RIFF_CODE))
{
/* MPEG Audio only */
//printf("libmpeg3 4\n");
file->is_audio_stream = 1;
}
else
if(bits == MPEG3_SEQUENCE_START_CODE ||
bits == MPEG3_PICTURE_START_CODE)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -