📄 mpg_sys.c
字号:
/* systems.c, systems-specific routines */
#include <stdio.h>
#include <stdlib.h>
#include "mpg_config.h"
#include "mpg_global.h"
/* initialize buffer, call once before first getbits or showbits */
static unsigned int mpeg_get_pts(layer_data *laydat, int c)
{
unsigned int temp, pts;
temp = c < 0 ? Get_Byte(laydat) : c;
pts = (temp & 0x0e) << 29;
temp = Get_Word(laydat);
pts |= (temp >> 1) << 15;
temp = Get_Word(laydat);
pts |= (temp >> 1);
return pts;
}
/* parse system layer, ignore everything we don't need */
void Next_Packet(int bskip)
{
unsigned int code, len;
int l;
unsigned short temp, flags;
unsigned int dts, pts;
while (1)
{
code = Get_Long(ld);
/* remove system layer byte stuffing */
while ((code & 0xffffff00) != 0x100)
{
code = (code << 8) | Get_Byte(ld);
if (Fault_Flag)
return;
}
if (Fault_Flag)
return;
switch (code)
{
case PACK_START_CODE: /* pack header */
/* skip pack header (system_clock_reference and mux_rate) */
ld->Rdptr += 8;
break;
case VIDEO_ELEMENTARY_STREAM:
code = Get_Word(ld); /* packet_length */
ld->Rdmax = ld->Rdptr + code;
code = Get_Byte(ld);
pts = 0xffffffff;
if ((code >> 6) == 0x02)
{
flags = Get_Byte(ld);
//ld->Rdptr++;
len = Get_Byte(ld); /* parse PES_header_data_length */
if (flags&0x80)
{
pts = dts = mpeg_get_pts(ld, -1);
len -= 5;
}
if (flags&0x40)
{
dts = mpeg_get_pts(ld, -1);
len -= 5;
}
ld->Rdptr += len; /* advance pointer by PES_header_data_length */
//printf("MPEG-2 PES packet\n");
goto pts_return;
}
else if (code == 0xff)
{
/* parse MPEG-1 packet header */
while ((code = Get_Byte(ld)) == 0xFF);
}
/* stuffing bytes */
if (code >= 0x40)
{
if (code >= 0x80)
{
Fault_Flag = 1;
}
/* skip STD_buffer_scale */
ld->Rdptr++;
code = Get_Byte(ld);
}
if (code >= 0x30)
{
if (code >= 0x40)
{
Fault_Flag = 1;
}
/* skip presentation and decoding time stamps */
pts = dts = mpeg_get_pts(ld, code);
if (code&0x10)
{
dts = mpeg_get_pts(ld, -1);
}
}
else if (code >= 0x20)
{
/* skip presentation time stamps */
pts = dts = mpeg_get_pts(ld, code);
//ld->Rdptr += 4;
}
else if (code != 0x0f)
{
Fault_Flag = 1;
}
pts_return:
if (pts != 0xffffffff)
{
if (pts_dts_orig_flag == 0)
{
pts_dts_orig_flag = 1;
//pts_orig = pts;
mpeg.startTime = pts / 90;
//dts_orig = dts;
}
//mpeg.curTime = (pts-pts_orig)/90;
if (((pts / 90) > mpeg.curTime) || (!mpeg.curTime))
mpeg.curTime = pts / 90;
}
return;
case ISO_END_CODE: /* end */
/* simulate a buffer full of sequence end codes */
l = 0;
while (l < 2048)
{
ld->Rdbfr[l++] = SEQUENCE_END_CODE >> 24;
ld->Rdbfr[l++] = SEQUENCE_END_CODE >> 16;
ld->Rdbfr[l++] = SEQUENCE_END_CODE >> 8;
ld->Rdbfr[l++] = SEQUENCE_END_CODE & 0xff;
}
ld->Rdptr = ld->Rdbfr;
ld->Rdmax = ld->Rdbfr + 2048;
return;
default:
if ((code >= SYSTEM_START_CODE) && (code <= AUDIO_ELEMENTARY_STREAM))
{
/* skip system headers and non-video packets*/
code = Get_Word(ld);
ld->Rdptr += code;
if (ld->Rdptr > (ld->Rdbfr + 2048))
{
fseek(ld->Infile, ld->Rdptr - (ld->Rdbfr + 2048), SEEK_CUR);
ld->Rdptr = (ld->Rdbfr + 2048);
}
}
/*else if(code < SYSTEM_START_CODE)
{
fprintf(stderr,"Unexpected startcode %08x in system layer\n",code);
exit(1);
}*/
break;
}
}
}
void Next_PacketAudio()
{
int code, len, c, flags, header_len, pes_ext, ext2_len, id_ext, skip;
int l, cnt = 0;
unsigned short temp;
unsigned int dts, pts;
while (1)
{
code = Get_Long(ld2);
/* remove system layer byte stuffing */
while ((code & 0xffffff00) != 0x100)
{
code = (code << 8) | Get_Byte(ld2);
if (Fault_Flag)
return;
}
if (Fault_Flag)
return;
if (code == PACK_START_CODE) /* pack header */
{
/* skip pack header (system_clock_reference and mux_rate) */
ld2->Rdptr += 8;
}
else if (code == ISO_END_CODE) /* end */
{
/* simulate a buffer full of sequence end codes */
l = 0;
while (l < 2048)
{
ld2->Rdbfr[l++] = SEQUENCE_END_CODE >> 24;
ld2->Rdbfr[l++] = SEQUENCE_END_CODE >> 16;
ld2->Rdbfr[l++] = SEQUENCE_END_CODE >> 8;
ld2->Rdbfr[l++] = SEQUENCE_END_CODE & 0xff;
}
ld2->Rdptr = ld2->Rdbfr;
ld2->Rdmax = ld2->Rdbfr + 2048;
return;
}
else if ((code >= 0x1c0 && code <= 0x1df) || (code == 0x1bd) || (code == 0x1fd))
{
pts = 0xffffffff;
len = Get_Word(ld2);
ld2->Rdmax = ld2->Rdptr + len;
for (;;)
{
if (len < 1) break;
c = Get_Byte(ld2);
len--;
if (c != 0xff) break;
}
if ((c & 0xc0) == 0x40)
{
// buffer scale & size
Get_Byte(ld2);
c = Get_Byte(ld2);
len -= 2;
}
if ((c & 0xe0) == 0x20)
{
dts = pts = mpeg_get_pts(ld2, c);
len -= 4;
if (c & 0x10)
{
dts = mpeg_get_pts(ld2, -1);
len -= 5;
}
}
else if ((c & 0xc0) == 0x80)
{
flags = Get_Byte(ld2);
header_len = Get_Byte(ld2);
len -= 2;
if (header_len > len)
break;
len -= header_len;
if (flags & 0x80)
{
dts = pts = mpeg_get_pts(ld2, -1);
header_len -= 5;
if (flags & 0x40)
{
dts = mpeg_get_pts(ld2, -1);
header_len -= 5;
}
}
if (flags & 0x3f && header_len == 0)
{
flags &= 0xC0;
printf("Further flags set but no bytes left\n");
}
if (flags & 0x01)
{ // PES extension
pes_ext = Get_Byte(ld2);
header_len--;
if (pes_ext & 0x40)
{ // pack header - should be zero in PS
break;
}
// Skip PES private data, program packet sequence counter and P-STD buffer
skip = (pes_ext >> 4) & 0xb;
skip += skip & 0x9;
ld2->Rdptr += skip;
header_len -= skip;
if (pes_ext & 0x01)
{ // PES extension 2
ext2_len = Get_Byte(ld2);
header_len--;
if ((ext2_len & 0x7f) > 0)
{
id_ext = Get_Byte(ld2);
if ((id_ext & 0x80) == 0)
code = ((code & 0xff) << 8) | id_ext;
header_len--;
}
}
}
if (header_len < 0)
break;
ld2->Rdptr += header_len;
}
if (pts != 0xffffffff)
{
mpeg.auCurTime = pts / 90;
}
if (code == PRIVATE_STREAM_1)
{
code = Get_Byte(ld2);
len--;
if (code >= 0x80 && code <= 0xcf)
{
// audio: skip header /
Get_Byte(ld2);
Get_Byte(ld2);
Get_Byte(ld2);
len -= 3;
if (code >= 0xb0 && code <= 0xbf)
{
// MLP/TrueHD audio has a 4-byte header //
Get_Byte(ld2);
len--;
}
}
}
#if 0
if (code == 0x80) //&& code <= 0x87)
{
mpeg.auCodec = CODEC_AC3_DEC;
return;
}
if (code == 0xc0)// && code <= 0xcf)
{
mpeg.auCodec = CODEC_AC3_DEC;
return;
}
if (code == 0x1c0)//&& code <= 0x1df)
{
mpeg.auCodec = CODEC_MP2;
return;
}
#else
if ((code >= 0x80 && code <= 0x87) || code == 0xc0 || code == 0x1c0) /* audio stream */
{
mpeg.auCodec = code;
if ((mpeg.auCodec & 0x78) == 0)
mpeg.auCodec = 0x80;
return;
}
else if ((!mpeg.auCodec) && (cnt >= 2))
{
mpeg.auCurTime = 0;
mpeg.auCodec = 0;
return;
}
else
{
cnt ++;
continue;
}
#endif
if (ld2->Rdmax > (ld2->Rdbfr + 2048))
{
fseek(ld2->Infile, ld2->Rdmax - (ld2->Rdbfr + 2048), SEEK_CUR);
ld2->Rdptr = (ld2->Rdbfr + 2048);
}
}
else if (((code >= SYSTEM_START_CODE) && (code < AUDIO_ELEMENTARY_STREAM)) || (code == VIDEO_ELEMENTARY_STREAM))
{
// skip system headers and non-audio packets//
code = Get_Word(ld2);
ld2->Rdptr += code;
if (ld2->Rdptr > (ld2->Rdbfr + 2048))
{
fseek(ld2->Infile, ld2->Rdptr - (ld2->Rdbfr + 2048), SEEK_CUR);
ld2->Rdptr = (ld2->Rdbfr + 2048);
}
}
/*else if(code < SYSTEM_START_CODE){
exit(1);
} */
}
}
void Flush_Buffer32(layer_data *laydat)
{
int Incnt;
laydat->Bfr = 0;
Incnt = laydat->Incnt;
Incnt -= 32;
if (System_Stream_Flag && (laydat->Rdptr >= laydat->Rdmax - 4))
{
while (Incnt <= 24)
{
if (laydat->Rdptr >= laydat->Rdmax)
if (laydat == ld)
Next_Packet(0);
else
Next_PacketAudio();
laydat->Bfr |= Get_Byte(laydat) << (24 - Incnt);
Incnt += 8;
}
}
else
{
while (Incnt <= 24)
{
if (laydat->Rdptr >= laydat->Rdbfr + 2048)
Fill_Buffer(laydat);
laydat->Bfr |= *laydat->Rdptr++ << (24 - Incnt);
Incnt += 8;
}
}
laydat->Incnt = Incnt;
#ifdef VERIFY
laydat->Bitcnt += 32;
#endif /* VERIFY */
}
unsigned int Get_Bits32(layer_data *laydat)
{
unsigned int l;
l = Show_Bits(laydat, 32);
Flush_Buffer32(laydat);
return l;
}
long Get_Long(layer_data *laydat)
{
int i;
i = Get_Word(laydat);
return (i << 16) | Get_Word(laydat);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -