#include "MFlvParse.h"
int main( int argc, char * argv[] )
{
FILE * file = NULL;
char cBuf[MBUF_SIZE] = {2,1,0x1f,06,05};
long ret = 0;
long lCount = 0;
long lPos = 0;
long lLength = 0;
long index = 0;
long timestamp = 0;
long fileSize = 0;
long ltemp = 0;
char videoPType = 0;
char * pFilepath = NULL;
long type = -1;
long count = 58;
int oldTime = 0;
////////////////
DWORD s_dwT = 0;
/////////////////
if ( argc < 2 )
{
__HELP:
printf ( "************************* MFlvParse 0.1 *************************\r\n");
printf( "MFlvParse Version:0.1v [By inpilen].\r\n" );
printf( "Email: inpilen@foxmail.com.\r\n\r\n" );
printf( "MFlvParse usage:\r\n" );
printf( "-h MFlvParse usage.\r\n" );
printf( " Ex: -h \r\n\r\n" );
printf( "-i parse file path.\r\n" );
printf( " Ex: -i c:\\filename.flv\r\n\r\n" );
printf( "-t parse tag type. [v:video, a:audio, s:script, n:not parse tag].\r\n" );
printf( " Ex: -t sva or -t v or -n. defaul value: sva.\r\n\r\n" );
printf( "-c parse tag count. -1 parse all file data.\r\n" );
printf( " Ex: -c 20 or -c -1. default value: 58.\r\n\r\n" );
printf( "[End]\r\n\r\n" );
printf ( "************************* By Inpilen. *************************\r\n");
system( "pause" );
return -1;
}
for ( lPos = 1; lPos < argc; lPos++ )
{
if ( '-' == argv[lPos][0] && strlen( argv[lPos] ) >= 2 )
{
switch ( argv[lPos][1] )
{
case 'i':
if ( lPos + 1 <= argc )
{
pFilepath = argv[++lPos];
}
break;
case 't':
type = 0;
if ( ++lPos >= argc )
{
break;
}
if ( strchr( argv[lPos], 'v' ) )
{
type |= 0x1;
}
if ( strchr( argv[lPos], 'a' ) )
{
type |= 0x2;
}
if ( strchr( argv[lPos], 's' ) )
{
type |= 0x4;
}
if ( strchr( argv[lPos], 'n' ) )
{
type = 0;
}
break;
case 'c':
if ( ++lPos >= argc )
{
break;
}
count = atoi( argv[lPos] );
break;
case 'h':
goto __HELP;
break;
}
}
}
printf ( "************************* MFlvParse 0.1 *************************\r\n");
printf( "[Input params:]" );
for ( lPos = 1; lPos < argc; lPos++ )
{
printf( " %s", argv[lPos] );
}
printf( "\r\n" );
lPos = 0;
file = fopen( pFilepath, "rb+" );
if ( !file )
{
return -1;
}
fseek( file, 0, SEEK_END );
fileSize = ftell( file );
UlongTo3Dot( fileSize, cBuf, sizeof( cBuf ) );
printf( "[File: %s]=>file size:%sB\r\n", pFilepath, cBuf );
printf ( "************************* By Inpilen. *************************\r\n");
fseek( file, 0, SEEK_SET );
ret = fread( cBuf, 13, 1, file );
if ( -1 == ParseHead( cBuf, 13 ) )
{
fclose( file );
file = NULL;
return -1;
}
lCount = 13;
while ( lCount < fileSize && index < ( unsigned long )count )
{
memset( cBuf, NULL, 15 );
lPos = 0;
lLength = 0;
ret = fread( cBuf + lLength, sizeof( char ), 11, file );
if ( -1 == ret )
{
printf( "unknowable error. parse terminate.error:%d length:%d\r\n", ret, lCount );
return -1;
}
lLength = 0;
( ( char * )&lLength )[0] = cBuf[3];
( ( char * )&lLength )[1] = cBuf[2];
( ( char * )&lLength )[2] = cBuf[1];
( ( char * )×tamp )[0] = cBuf[6];
( ( char * )×tamp )[1] = cBuf[5];
( ( char * )×tamp )[2] = cBuf[4];
( ( char * )×tamp )[3] = cBuf[7];
switch ( cBuf[0] )
{
case 0x08:
lCount += lLength + 11;
if ( type & 0x2 )
{
index++;
printf( "[index:%06d]=>[auido tag:%06d] timestamp:%08d %s\r\n", index, lLength, timestamp, oldTime > timestamp ? "Exception" : "" );
}
break;
case 0x09:
if ( type & 0x1 )
{
index++;
/////////////
//timestamp = s_dwT;
//cBuf[6] = ( ( char * )×tamp )[0];
//cBuf[5] = ( ( char * )×tamp )[1];
//cBuf[4] = ( ( char * )×tamp )[2];
//cBuf[7] = ( ( char * )×tamp )[3];
//fseek( file, lCount, SEEK_SET );
//fwrite( cBuf, sizeof( char ), 11, file );
//s_dwT += 57;
/////////////
printf( "[index:%06d]=>[video tag:%06d] timestamp:%08d ", index, lLength, timestamp );
if ( 1 )
{
ret = fread( (void *)&videoPType, 1, 1, file );
if ( 1 == ret )
{
switch ( videoPType & 0x0F )
{
case 0x02:
ParseH263( file, ftell( file ) );
break;
case 0x07:
ParseH264( file, ftell( file ) );
break;
default:
break;
}
}
}
printf( " %s\r\n", oldTime > timestamp ? "Exception" : "" );
}
lCount += lLength + 11;
break;
case 0x12:
lCount += lLength + 11;
if ( type & 0x4 )
{
index++;
printf( "[index:%06d]=>[script tag:%06d] timestamp:%08d\r\n", index, lLength, timestamp );
}
break;
default:
printf( "unknowable error. parse terminate.error:%d length:%d\r\n", ret, lCount );
return -1;
}
oldTime = timestamp;
lCount += 4;
fseek( file, lCount, SEEK_SET );
}
fclose( file );
file = NULL;
return 0;
}
int ParseH263( FILE * file, long lOffset )
{
long lTemp;
unsigned char p[10];
long width = 0;
long height = 0;
char videoType = 0;
lOffset += 3;
fseek( file, lOffset, SEEK_SET );
fread( ( void * )p, 1, 2, file );
lTemp = p[0] << 1 | p[1] >> 7;
switch ( lTemp )
{
case 0:
p[0] = p[1];
fread( ( void * )(p + 1), 1, 3, file );
width = p[0] << 1 | p[1] >> 7;
height = p[1] << 1 | p[2] >> 7;
videoType = p[2] >> 5 & ~0x04;
break;
case 1:
p[0] = p[1];
fread( ( void * )(p + 1), 1, 5, file );
width = p[0] << 1 & 0xFF | p[1] >> 7;
width <<= 8;
width |= p[1] << 1 & 0xFF | p[2] >> 7;
height = p[2] << 1 & 0xFF | p[3] >> 7;
height <<= 8;
height |= p[3] << 1 & 0xFF | p[4] >> 7;
videoType = p[7] >> 5 & ~0x04;
break;
case 2:
width = 352;
height = 288;
break;
case 3:
width = 176;
height = 144;
break;
case 4:
width = 128;
height = 96;
break;
case 5:
width = 320;
height = 240;
break;
case 6:
width = 160;
height = 120;
break;
}
if ( lTemp > 1 )
{
videoType = p[1] >> 5 & ~0x04;
}
printf ( "[H263:%s %02d*%02d]",
videoType == 0 ? "intra frame" :
videoType == 1 ? "inter frame" : "disposable inter frame",
width, height );
return;
}
int ParseH264( FILE * file, long lOffset )
{
unsigned char p[10];
long naluType = 0;
fread( ( void * )p, 1, 10, file );
printf( "[H264:%s ", p[0] == 0 ? "Sequence header" : p[0] == 1 ? "NALUs" : "End of sequence" );
switch ( p[0] )
{
case 0:
break;
case 1:
printf( " {T:0x%X} ", p[8] );
break;
case 2:
break;
}
printf( "]" );
return 0;
}
void UlongTo3Dot( unsigned long lValue, char * p, long lLen )
{
char cTemp[20];
long lReal = 0;
long lNeedLen = 0;
int iSrcPos = 0;
int iDstPos = 0;
long lTemp = 0;
memset( cTemp, NULL, sizeof( cTemp ) );
sprintf( cTemp, "%d", lValue );
lReal = strlen( cTemp );
lNeedLen = 0 == lReal / 3 ? 0 : lReal % 3 ? lReal / 3 : lReal / 3 - 1;
lNeedLen += lReal;
lLen--;
iDstPos = lLen > lNeedLen ? lNeedLen : lLen;
iSrcPos = lReal;
lTemp = 0;
while ( iDstPos > 0 )
{
if ( ++lTemp % 4 )
{
p[--iDstPos] = cTemp[--iSrcPos];
continue;
}
p[--iDstPos] = ',';
}
return;
}
int ParseHead( char * pBuf, long len )
{
long lPos = 0;
while ( lPos < FLV_HEAD_SIZE )
{
switch ( lPos )
{
case 0:
if ( 'F' != pBuf[lPos] )
{
printf( "file head error:FLV signature error.\r\n" );
return -1