#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "demux_mpg.h"
#if 0
int main()
{
FILE *fin, *fout;
int len, ret, ret2;
char *buffer;
int count;
char name[128];
MPEG_DEMUX mpg_demux;
fin = fopen("test.mp4", "rb");
fseek(fin, 0, SEEK_END);
len = ftell(fin);
fseek(fin, -len, SEEK_END);
buffer = (char *)malloc(len);
fread(buffer, 1, len, fin);
fclose(fin);
mpg_demux.status = MPEG_DEMUX_UNSYNC;
mpg_demux.head = 0xffffffff;
mpg_demux.pack_start = 0;
mpg_demux.buffer = (unsigned char *)buffer;
mpg_demux.buf_len = len;
count = 0;
fout = NULL;
while(1)
{
ret = demux_mpg_parse_stream(&mpg_demux);
if(ret == MPEG_DEMUX_RET_PSC)
{
printf("Pack Start Code\n");
// skip it
mpg_demux.status = MPEG_DEMUX_UNSYNC;
mpg_demux.head = 0xffffffff;
if(fout != NULL)
fclose(fout);
sprintf(name, "t%04d.jpg", count++);
fout = fopen(name, "wb");
}
if(ret == MPEG_DEMUX_RET_PES)
{
printf("PES\n");
mpg_demux.status = MPEG_DEMUX_PES_PKTLEN;
mpg_demux.wait_num = 2;
mpg_demux.pkt_len = 0;
ret2 = demux_mpg_parse_PES(&mpg_demux);
if(ret2 > 0)
{
fwrite(mpg_demux.buffer, 1, mpg_demux.pkt_len, fout);
mpg_demux.buffer += mpg_demux.pkt_len;
mpg_demux.buf_len -= mpg_demux.pkt_len;
// resync
mpg_demux.status = MPEG_DEMUX_UNSYNC;
mpg_demux.head = 0xffffffff;
}
}
if(ret == MPEG_DEMUX_RET_EOF)
{
printf("End of Stream\n");
break;
}
}
if(fout != NULL)
fclose(fout);
#if 0
do
{
ret = demux_mpg_parse_PES(&mpg_demux);
} while(ret != 1);
fwrite(mpg_demux.buffer, 1, mpg_demux.pkt_len, fout);
mpg_demux.buffer += mpg_demux.pkt_len;
mpg_demux.buf_len -= mpg_demux.pkt_len;
mpg_demux.status = MPEG_DEMUX_UNSYNC;
mpg_demux.head = 0xffffffff;
do
{
ret = demux_mpg_parse_stream(&mpg_demux);
} while(ret != 1);
do
{
ret = demux_mpg_parse_PES(&mpg_demux);
} while(ret != 1);
fwrite(mpg_demux.buffer, 1, mpg_demux.pkt_len, fout);
fclose(fout);
#endif
free(buffer);
}
#endif
/*
* Return MPEG_DEMUX_RET_EOF: end of buffer
* Return MPEG_DEMUX_RET_PSC: find Pack Start Code
* Return MPEG_DEMUX_RET_PES: find PES
*/
int demux_mpg_parse_stream(MPEG_DEMUX *demux)
{
int c, ret = MPEG_DEMUX_RET_NULL;
do
{
// sync
if(demux->status == MPEG_DEMUX_UNSYNC)
{
while(demux->buf_len > 0)
{
c = (int)*demux->buffer++;
demux->buf_len--;
demux->head <<= 8;
if(demux->head != 0x100)
{
demux->head |= c;
continue;
}
demux->head |= c;
demux->status = MPEG_DEMUX_SYNCED;
break;
}
}
if(demux->status == MPEG_DEMUX_SYNCED)
{
switch(demux->head)
{
case 0x1BA: // pack start code
demux->pack_start = 1; // mark start
ret = MPEG_DEMUX_RET_PSC;
break;
case 0x1E0: // video
if(demux->pack_start == 1)
{
ret = MPEG_DEMUX_RET_PES;
}
else
{
demux->status = MPEG_DEMUX_UNSYNC; // skip it
demux->head = 0xffffffff;
}
break;
//case 0x1BC: // psm, skip it
default:
demux->status = MPEG_DEMUX_UNSYNC;
demux->head = 0xffffffff;
}
}
if((demux->buf_len <= 0) && (demux->status == MPEG_DEMUX_UNSYNC))
{
ret = MPEG_DEMUX_RET_EOF;
}
} while(ret == MPEG_DEMUX_RET_NULL);
return ret;
}
/*
* Return 1: find data
* Return 0: Run out of buffer
* Return <0: parse error
*/
int demux_mpg_parse_PES(MPEG_DEMUX *demux)
{
int c, ret = 0;
do
{
// Read packet length
if(demux->status == MPEG_DEMUX_PES_PKTLEN)
{
while(demux->buf_len > 0)
{
c = (int)*demux->buffer++;
demux->buf_len--;
demux->pkt_len <<= 8;
demux->pkt_len |= c;
demux->wait_num--;
if(demux->wait_num > 0)
{
continue;
}
if(demux->pkt_len != 0)
{
demux->status = MPEG_DEMUX_PES_SKIP_STUFFING;
}
else
{
ret = -2; // bad format
}
break;
}
}
// Skip stuFFing bytes
if(demux->status == MPEG_DEMUX_PES_SKIP_STUFFING)
{
while((demux->buf_len > 0) && (demux->pkt_len > 0))
{
c = (int)*demux->buffer++;
demux->buf_len--;
demux->pkt_len--;
if(c != 0xff)
{
demux->status = MPEG_DEMUX_PES_SKIP_TIME_FLAG;
break;
}
}
}
// Skip time flag
if(demux->status == MPEG_DEMUX_PES_SKIP_TIME_FLAG)
{
if((c>>6) != 2)
{
ret = -1; // unsupported!
break;
}
else
{
demux->status = MPEG_DEMUX_PES_SKIP_PTS_FLAG;
}
}
// Skip PTS flag
if(demux->status == MPEG_DEMUX_PES_SKIP_PTS_FLAG)
{
if((demux->buf_len > 0) && (demux->pkt_len > 0))
{
demux->buffer++;
demux->buf_len--;
demux->pkt_len--;
demux->status = MPEG_DEMUX_PES_HDRLEN;
}
}
// read header len
if(demux->status == MPEG_DEMUX_PES_HDRLEN)
{
if((demux->buf_len > 0) && (demux->pkt_len > 0))
{
c = (int)*demux->buffer++;
demux->buf_len--;
demux->pkt_len--;
if(c > demux->pkt_len)
{
ret = -2; // bad format
break;
}
else
{
if(c > 0)
{
demux->status = MPEG_DEMUX_PES_SKIP_HDR;
demux->wait_num = c;
}
else
{
demux->status = MPEG_DEMUX_PES_DATA;
}
}
}
}
// skip header
if(demux->status == MPEG_DEMUX_PES_SKIP_HDR)
{
while((demux->buf_len > 0) && (demux->pkt_len > 0))
{
demux->buffer++;
demux->buf_len--;
demux->pkt_len--;
demux->wait_num--;
if(demux->wait_num > 0)
{
continue;
}
demux->status = MPEG_DEMUX_PES_DATA;
break;
}
}