📄 mpeg3demux.c
字号:
clock_ref |= ((i & 0x000003ff) << 5);
clock_ref |= ((j & 0xf800) >> 11);
clock_ref_ext = (j >> 1) & 0x1ff;
demuxer->time = (double)(clock_ref + clock_ref_ext / 300) / 90000;
/* Skip 3 bytes */
mpeg3io_read_int24(title->fs);
i = mpeg3io_read_char(title->fs) & 0x7;
/* stuffing */
mpeg3io_seek_relative(title->fs, i);
}
}
else
{
mpeg3io_seek_relative(title->fs, 2);
}
return 0;
}
/* Program packet reading core */
static int get_ps_pes_packet(mpeg3_demuxer_t *demuxer, unsigned int header)
{
unsigned long pts = 0, dts = 0;
int stream_id;
int pes_packet_length;
long pes_packet_start;
long decryption_offset;
int i;
mpeg3_t *file = demuxer->file;
mpeg3_title_t *title = demuxer->titles[demuxer->current_title];
int scrambling = 0;
stream_id = header & 0xff;
pes_packet_length = mpeg3io_read_int16(title->fs);
pes_packet_start = mpeg3io_tell(title->fs);
if(stream_id != MPEG3_PRIVATE_STREAM_2 &&
stream_id != MPEG3_PADDING_STREAM)
{
if((mpeg3io_next_char(title->fs) >> 6) == 0x02)
{
/* Get MPEG-2 packet */
int pes_header_bytes = 0;
int pts_dts_flags;
int pes_header_data_length;
demuxer->last_packet_decryption = mpeg3io_tell(title->fs);
scrambling = mpeg3io_read_char(title->fs) & 0x30;
//scrambling = 1;
/* Reset scrambling bit for the mpeg3cat utility */
// if(scrambling) demuxer->raw_data[demuxer->raw_offset - 1] &= 0xcf;
pts_dts_flags = (mpeg3io_read_char(title->fs) >> 6) & 0x3;
pes_header_data_length = mpeg3io_read_char(title->fs);
/* Get Presentation and Decoding Time Stamps */
if(pts_dts_flags == 2)
{
pts = (mpeg3io_read_char(title->fs) >> 1) & 7; /* Only low 4 bits (7==1111) */
pts <<= 15;
pts |= (mpeg3io_read_int16(title->fs) >> 1);
pts <<= 15;
pts |= (mpeg3io_read_int16(title->fs) >> 1);
pes_header_bytes += 5;
}
else
if(pts_dts_flags == 3)
{
pts = (mpeg3io_read_char(title->fs) >> 1) & 7; /* Only low 4 bits (7==1111) */
pts <<= 15;
pts |= (mpeg3io_read_int16(title->fs) >> 1);
pts <<= 15;
pts |= (mpeg3io_read_int16(title->fs) >> 1);
dts = (mpeg3io_read_char(title->fs) >> 1) & 7; /* Only low 4 bits (7==1111) */
dts <<= 15;
dts |= (mpeg3io_read_int16(title->fs) >> 1);
dts <<= 15;
dts |= (mpeg3io_read_int16(title->fs) >> 1);
pes_header_bytes += 10;
}
/* Skip unknown */
mpeg3io_seek_relative(title->fs,
pes_header_data_length - pes_header_bytes);
}
else
{
int pts_dts_flags;
/* Get MPEG-1 packet */
while(mpeg3io_next_char(title->fs) == 0xff)
{
mpeg3io_read_char(title->fs);
}
/* Skip STD buffer scale */
if((mpeg3io_next_char(title->fs) & 0x40) == 0x40)
{
mpeg3io_seek_relative(title->fs, 2);
}
/* Decide which timestamps are available */
pts_dts_flags = mpeg3io_next_char(title->fs);
if(pts_dts_flags >= 0x30)
{
/* Get the presentation and decoding time stamp */
pts = get_timestamp(demuxer);
dts = get_timestamp(demuxer);
}
else
if(pts_dts_flags >= 0x20)
{
/* Get just the presentation time stamp */
pts = get_timestamp(demuxer);
}
else
if(pts_dts_flags == 0x0f)
{
/* End of timestamps */
mpeg3io_read_char(title->fs);
}
else
{
return 1; /* Error */
}
}
/* Now extract the payload. */
if((stream_id >> 4) == 0xc || (stream_id >> 4) == 0xd)
{
/* Audio data */
/* Take first stream ID if -1 */
pes_packet_length -= mpeg3io_tell(title->fs) - pes_packet_start;
if(demuxer->read_all)
demuxer->astream_table[stream_id & 0x0f] = AUDIO_MPEG;
else
if(demuxer->astream == -1)
demuxer->astream = stream_id & 0x0f;
demuxer->pes_audio_time = demuxer->time;
if(pts) demuxer->pes_audio_time = pts;
if((stream_id & 0x0f) == demuxer->astream && demuxer->do_audio)
{
decryption_offset = mpeg3io_tell(title->fs) - demuxer->last_packet_start;
mpeg3io_read_data(demuxer->data_buffer + demuxer->data_size,
pes_packet_length,
title->fs);
demuxer->data_size += pes_packet_length;
}
else
{
mpeg3io_seek_relative(title->fs, pes_packet_length);
}
}
else
if((stream_id >> 4) == 0xe)
{
/* Video data */
/* Take first stream ID if -1 */
pes_packet_length -= mpeg3io_tell(title->fs) - pes_packet_start;
if(demuxer->read_all)
demuxer->vstream_table[stream_id & 0x0f] = 1;
else
if(demuxer->vstream == -1)
demuxer->vstream = stream_id & 0x0f;
demuxer->pes_video_time = demuxer->time;;
if(pts) demuxer->pes_video_time = pts;
if((stream_id & 0x0f) == demuxer->vstream && demuxer->do_video)
{
//printf(__FUNCTION__ " stream_id=%x size=%x\n", stream_id, pes_packet_length);
decryption_offset = mpeg3io_tell(title->fs) - demuxer->last_packet_start;
mpeg3io_read_data(demuxer->data_buffer + demuxer->data_size,
pes_packet_length,
title->fs);
demuxer->data_size += pes_packet_length;
}
else
{
mpeg3io_seek_relative(title->fs, pes_packet_length);
}
}
else
if((stream_id == 0xbd || stream_id == 0xbf) &&
mpeg3io_next_char(title->fs) != 0xff &&
((mpeg3io_next_char(title->fs) & 0xf0) != 0x20))
{
/* DVD audio data */
/* Get the audio format */
int format;
//printf("get_ps_pes_packet 5 %x\n", packet_next_char(demuxer) & 0xf0);
if((mpeg3io_next_char(title->fs) & 0xf0) == 0xa0)
format = AUDIO_PCM;
else
format = AUDIO_AC3;
// Picks up bogus data if (& 0xf) or (& 0x7f)
stream_id = mpeg3io_next_char(title->fs);
demuxer->pes_audio_time = demuxer->time;
if(pts) demuxer->pes_audio_time = pts;
//printf("get_ps_pes_packet %x\n", stream_id);
/* Take first stream ID if not building TOC. */
if(demuxer->read_all)
demuxer->astream_table[stream_id] = format;
else
if(demuxer->astream == -1)
demuxer->astream = stream_id;
if(stream_id == demuxer->astream && demuxer->do_audio)
{
demuxer->aformat = format;
mpeg3io_read_int32(title->fs);
pes_packet_length -= mpeg3io_tell(title->fs) - pes_packet_start;
decryption_offset = mpeg3io_tell(title->fs) - demuxer->last_packet_start;
mpeg3io_read_data(demuxer->data_buffer + demuxer->data_size,
pes_packet_length,
title->fs);
demuxer->data_size += pes_packet_length;
}
else
{
pes_packet_length -= mpeg3io_tell(title->fs) - pes_packet_start;
mpeg3io_seek_relative(title->fs, pes_packet_length);
}
//printf("get_ps_pes_packet 6 %d\n", demuxer->astream_table[0x20]);
}
else
if(stream_id == 0xbc || 1)
{
pes_packet_length -= mpeg3io_tell(title->fs) - pes_packet_start;
mpeg3io_seek_relative(title->fs, pes_packet_length);
}
}
else
if(stream_id == MPEG3_PRIVATE_STREAM_2 || stream_id == MPEG3_PADDING_STREAM)
{
pes_packet_length -= mpeg3io_tell(title->fs) - pes_packet_start;
mpeg3io_seek_relative(title->fs, pes_packet_length);
}
// Advance 2048 bytes if scrambled. We might pick up a spurrius
// packet start code in the scrambled data otherwise.
if(scrambling &&
demuxer->last_packet_start + 0x800 > mpeg3io_tell(title->fs))
{
mpeg3io_seek_relative(title->fs,
demuxer->last_packet_start + 0x800 - mpeg3io_tell(title->fs));
}
// Descramble if desired
if(demuxer->data_size && scrambling)
{
//printf(__FUNCTION__ " data_size=%x decryption_offset=%x\n", demuxer->data_size, decryption_offset);
if(mpeg3_decrypt_packet(title->fs->css,
demuxer->data_buffer,
decryption_offset))
{
fprintf(stderr, "get_ps_pes_packet: Decryption not available\n");
return 1;
}
}
//if(mpeg3io_tell(title->fs) - demuxer->last_packet_start != 0x800)
// printf(__FUNCTION__ " packet size == %d\n", mpeg3io_tell(title->fs) - demuxer->last_packet_start);
return 0;
}
int mpeg3demux_read_program(mpeg3_demuxer_t *demuxer)
{
int result = 0;
int count = 0;
mpeg3_t *file = demuxer->file;
mpeg3_title_t *title = demuxer->titles[demuxer->current_title];
unsigned int header = 0;
int pack_count = 0;
demuxer->data_size = 0;
//printf("mpeg3demux_read_program 1 %d %x %llx\n", result, title->fs->current_byte, title->fs->total_bytes);
if(mpeg3io_eof(title->fs)) return 1;
//printf("mpeg3demux_read_program 2 %d %x %llx\n", result, title->fs->current_byte, title->fs->total_bytes);
/* Search for next header */
/* Parse packet until the next packet start code */
while(!result && !mpeg3io_eof(title->fs))
{
header = mpeg3io_read_int32(title->fs);
if(header == MPEG3_PACK_START_CODE)
{
// Start of next packet
if(pack_count)
{
mpeg3io_seek_relative(title->fs, -4);
break;
}
demuxer->last_packet_start = mpeg3io_tell(title->fs) - 4;
result = get_pack_header(demuxer);
//printf("mpeg3demux_read_program MPEG3_PACK_START_CODE %d\n", result);
pack_count++;
}
else
if(header == MPEG3_SYSTEM_START_CODE && pack_count)
{
result = get_system_header(demuxer);
//printf("mpeg3demux_read_program MPEG3_SYSTEM_START_CODE %d\n", result);
}
else
if((header >> 8) == MPEG3_PACKET_START_CODE_PREFIX && pack_count)
{
result = get_ps_pes_packet(demuxer, header);
//printf("mpeg3demux_read_program MPEG3_PACKET_START_CODE_PREFIX %d %08x\n", result, header);
}
else
{
// Try again.
mpeg3io_seek_relative(title->fs, -3);
}
}
//printf("mpeg3demux_read_program 3 %d %x %llx\n", result, title->fs->current_byte, title->fs->total_bytes);
// Ignore errors in the parsing. Just quit if eof.
result = 0;
demuxer->last_packet_end = mpeg3io_tell(title->fs);
/*
* if(demuxer->last_packet_end - demuxer->last_packet_start != 0x800)
* printf(__FUNCTION__ " packet_size=%x data_size=%x packet_start=%x\n",
* demuxer->last_packet_end - demuxer->last_packet_start,
* demuxer->data_size,
* demuxer->last_packet_start);
*/
//printf("mpeg3demux_read_program 5 %d\n", result);
//printf("read_program 3\n");
// if(!result) result = mpeg3io_eof(title->fs);
return result;
}
static double lookup_time_offset(mpeg3_demuxer_t *demuxer, long byte)
{
int i;
mpeg3_title_t *title = demuxer->titles[demuxer->current_title];
if(!title->timecode_table_size) return 0;
for(i = title->timecode_table_size - 1;
i >= 0 && title->timecode_table[i].start_byte > byte;
i--)
;
if(i < 0) i = 0;
return title->timecode_table[i].absolute_start_time - title->timecode_table[i].start_time;
}
int mpeg3_advance_timecode(mpeg3_demuxer_t *demuxer)
{
mpeg3_title_t *title = demuxer->titles[demuxer->current_title];
int result = 0;
int do_seek = 0;
int last_timecode = demuxer->current_timecode;
//printf("mpeg3_advance_timecode 0\n");fflush(stdout);
/* Don't do anything when constructing timecode table */
if(!title->timecode_table ||
!title->timecode_table_size ||
demuxer->read_all) return 0;
//printf("mpeg3_advance_timecode 1\n");fflush(stdout);
if(!demuxer->reverse)
{
/* Get inside the current timecode */
if(mpeg3io_tell(title->fs) < title->timecode_table[demuxer->current_timecode].start_byte)
{
mpeg3io_seek(title->fs,
title->timecode_table[demuxer->current_timecode].start_byte);
}
/* Get the next timecode */
while(!result &&
(mpeg3io_tell(title->fs) >= title->timecode_table[demuxer->current_timecode].end_byte ||
demuxer->current_program != title->timecode_table[demuxer->current_timecode].program))
{
demuxer->current_timecode++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -