📄 flvfile.c
字号:
/********************************************************************************************
Copyright (C), 2007, Fuzhou Rockchip Co.,Ltd.
File:
FlvFile.c
Description:
Flv file demuxer.
Note:
None.
Author:
ljn
$Log: FlvFile.c,v $
Revision 1.3 2008/06/19 04:42:31 Administrator
代码整理!
Revision 1.2 2008/05/20 12:03:00 HZF
flv文件播放提交
Revision 1.1.1.1 2008/05/07 04:14:52 Administrator
no message
Revision 1.1.1.1 2008/03/06 13:28:26 Lingzhaojun
no message
********************************************************************************************/
#define _IN_FLVFILE_H
#include "system.h"
#include "FlvFile.h"
char frmHdr[8] = {0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00};
/********************************************************************************************
Func:
FlvGetFlvInfo()
Description:
Get flv video/audio stream information.
Param:
FlvDemux *flv - Flv demux struct.
Return:
0: Success.
-1: Failed.
Author:
ljn
Date:
2008-1-10
Log:
********************************************************************************************/
int FlvGetFlvInfo(FlvDemux *flv)
{
unsigned char readBuf[16], resolution;
unsigned int horizontal_size, vertical_size;
int lastSize;
FlvFseek(flv->audioStr, flv->start, SEEK_SET);
FlvFseek(flv->videoStr, flv->start, SEEK_SET);
/****************************************
[1] Check streams and get format.
****************************************/
/* check if audio is included */
if (FlvAudioGetNextFrmInfo(flv))
{
flv->audioFlag = 0;
}
else
{
flv->audioFlag = 1;
flv->aFormat = flv->curAudio.type >> 4;
}
/* check if video is included */
if (FlvVideoGetNextFrmInfo(flv))
{
flv->videoFlag = 0;
}
else
{
flv->videoFlag = 1;
flv->vFormat = flv->curVideo.type & 0x0f;
}
if ((!flv->videoFlag) && (!flv->audioFlag)) /* neither video nor audio stream in this file */
return -1;
/****************************************
[2] Get frame rate.
****************************************/
/* skip first video packet */
FlvFseek(flv->videoStr, flv->curVideo.size, SEEK_CUR);
flv->curVideo.read = flv->curVideo.size;
if (FlvVideoGetNextFrmInfo(flv))
return -1;
if (!flv->curVideo.time)
return -1;
flv->frameRate = (1000 + flv->curVideo.time / 2) / flv->curVideo.time;
if ((flv->frameRate > 50) || (flv->frameRate < 10))
flv->frameRate = 20;
//FlvFseek(flv->videoStr, flv->start + 16, SEEK_SET);
/****************************************
[3] Get resolution.
****************************************/
FlvFread(readBuf, sizeof(unsigned char), 9, flv->videoStr);
if (((unsigned long)readBuf[0] << 14) | ((unsigned long)readBuf[1] << 6) | ((unsigned long)readBuf[2] >> 2) == 33)
{
resolution = ((readBuf[3] & 3) << 1) | (readBuf[4] >> 7);
switch (resolution)
{
case(4):
horizontal_size = 128;
vertical_size = 96;
break;
case(3):
horizontal_size = 176;
vertical_size = 144;
break;
case(2):
horizontal_size = 352;
vertical_size = 288;
break;
case(5):
horizontal_size = 320;
vertical_size = 240;
break;
case(6):
horizontal_size = 160;
vertical_size = 120;
break;
case(0):
horizontal_size = (((unsigned int)readBuf[4] << 1) | ((unsigned int)readBuf[5] >> 7)) & 0xff;
vertical_size = (((unsigned int)readBuf[5] << 1) | ((unsigned int)readBuf[6] >> 7)) & 0xff;
break;
case(1):
horizontal_size = (((unsigned int)readBuf[4] << 9) | ((unsigned int)readBuf[5] << 1) | ((unsigned int)readBuf[6] >> 7)) & 0xffff;
vertical_size = (((unsigned int)readBuf[6] << 9) | ((unsigned int)readBuf[7] << 1) | ((unsigned int)readBuf[8] >> 7)) & 0xffff;
break;
default:
break;
}
flv->width = horizontal_size;
flv->height = vertical_size;
}
else
{
flv->width = 0;
flv->height = 0;
}
/****************************************
[3] Get length.
****************************************/
FlvFseek(flv->videoStr, flv->videoStr->FileSize - 4, SEEK_SET);
if (FlvFread(readBuf, 1, 4, flv->videoStr) != 4)
return -1;
lastSize = ((unsigned int)readBuf[3]) | ((unsigned int)readBuf[2] << 8) | ((unsigned int)readBuf[1] << 16) | ((unsigned int)readBuf[0] << 24);
FlvFseek(flv->videoStr, flv->videoStr->FileSize - lastSize - 4, SEEK_SET);
if ((FlvFread(readBuf, 1, 15, flv->videoStr)) != 15) //[0]~[3]:PreviousTagSize
return -1;
if ((readBuf[0] == FLV_TAG_TYPE_VIDEO) || (readBuf[0] == FLV_TAG_TYPE_AUDIO))
{
/* time stamp */
flv->length = ((unsigned long)readBuf[7] << 24) | ((unsigned long)readBuf[4] << 16) | ((unsigned long)readBuf[5] << 8) | (unsigned long)readBuf[6];
}
else
{
flv->length = 0xffffffff;
if (flv->videoStr->FileSize < 20*1024*1024) /* bug fix, ljn, 08-05-07 */
{
FlvFseek(flv->videoStr, flv->start, SEEK_SET);
flv->curVideo.read = 0;
flv->curVideo.type = 0;
flv->curVideo.size = 0;
while (FlvVideoGetNextFrmInfo(flv) == 0);
flv->length = flv->curVideo.time;
}
}
return 0;
}
/********************************************************************************************
Func:
FlvFileParsing()
Description:
Flv file parse.
Param:
FlvDemux *flv - Flv demux struct.
Return:
0: Success.
-1: Error.
Author:
ljn
Date:
2008-1-9
Log:
********************************************************************************************/
int FlvFileParsing(FlvDemux *flv)
{
char tempBuf[16];
FLVFILE *file = flv->audioStr;
//read FLV header
FlvFseek(file, 0, SEEK_SET);
if (FlvFread(tempBuf, 1, 9, file) != 9)
return -1;
if ((tempBuf[0] != 'F') || (tempBuf[1] != 'L') || (tempBuf[2] != 'V')) /* It is a flv file? */
return -1;
//flv->version = tempBuf[3];
flv->videoFlag = tempBuf[4] & 0x01;
flv->audioFlag = (tempBuf[4] >> 2) & 0x01;
flv->start = ((unsigned long)tempBuf[5] << 24) | ((unsigned long)tempBuf[6] << 16) | ((unsigned long)tempBuf[7] << 8) | (unsigned long)tempBuf[8];
if (FlvGetFlvInfo(flv))
return -1;
/* check video codec */
if (flv->videoFlag)
{
switch (flv->vFormat)
{
case FLV_VIDEO_FORMAT_FLV1:
break;
case FLV_VIDEO_FORMAT_SCREEN:
case FLV_VIDEO_FORMAT_VP6:
case FLV_VIDEO_FORMAT_VP6A:
case FLV_VIDEO_FORMAT_SCREEN2:
default:
flv->videoFlag = 0;
}
}
/* check audio codec */
if (flv->audioFlag)
{
switch (flv->aFormat)
{
case FLV_SOUND_FORMAT_MP3:
break;
case FLV_SOUND_FORMAT_PCM_BE:
case FLV_SOUND_FORMAT_ADPCM:
case FLV_SOUND_FORMAT_PCM_LE:
case FLV_SOUND_FORMAT_NELLY8:
case FLV_SOUND_FORMAT_NELLY:
default:
flv->audioFlag = 0;
}
}
/* check resolution */
if ((flv->width > 640) || (flv->height > 640) || (!(flv->height * flv->width)))
return -1;
if ((!flv->videoFlag) && (!flv->audioFlag)) /* neither video nor audio stream is supported. */
return -1;
if (!flv->videoFlag)
{
flv->frameRate = 0;
flv->width = 0;
flv->height = 0;
return -1;
}
FlvFseek(flv->videoStr, flv->start, SEEK_SET);
FlvFseek(flv->audioStr, flv->start, SEEK_SET);
//flv->length = 0;
flv->curVideo.read = 0;
flv->curVideo.type = 0;
flv->curVideo.size = 0;
flv->curAudio.read = 0;
flv->curAudio.type = 0;
flv->curAudio.size = 0;
flv->videoFrmNum = 0;
flv->keyFrmNum = 0;
flv->skipFlag = 0;
flv->lastSkipPos = 0;
flv->destTime = 0;
flv->keyFrm[0].offset = flv->start + 16;
flv->keyFrm[0].frmID = 0;
return 0;
}
/********************************************************************************************
Func:
FlvVideoGetNextFrmInfo()
Description:
Get next video frame.
Param:
FlvDemux *flv - Flv demux struct.
Return:
0: Success.
-1: Failed.
Author:
ljn
Date:
2008-1-9
Log:
********************************************************************************************/
int FlvVideoGetNextFrmInfo(FlvDemux *flv)
{
char tempBuf[16];
int size;
if (flv->curVideo.size > flv->curVideo.read)
{
FlvFseek(flv->videoStr, flv->curVideo.size - flv->curVideo.read, SEEK_CUR);
flv->curVideo.read = flv->curVideo.size;
}
while (1)
{
if ((FlvFread(tempBuf, 1, 16, flv->videoStr)) != 16) //[0]~[3]:PreviousTagSize
return -1;
size = ((unsigned long)tempBuf[5] << 16) | ((unsigned long)tempBuf[6] << 8) | ((unsigned long)tempBuf[7]);
size -= 1;
if (tempBuf[4] == FLV_TAG_TYPE_VIDEO)
{
/* video time stamp */
flv->curVideo.time = ((unsigned long)tempBuf[11] << 24) | ((unsigned long)tempBuf[8] << 16) | ((unsigned long)tempBuf[9] << 8) | (unsigned long)tempBuf[10];
//if (FlvFread(tempBuf, 1, 1, flv->videoStr) != 1) {
// return -1;
//}
flv->videoFrmNum ++;
if ((tempBuf[15] >> 4) == 0x01) /* check if it is a key frame. */
{
flv->keyFrmNum ++;
flv->keyFrm[flv->keyFrmNum].offset = flv->videoStr->Offset;
flv->keyFrm[flv->keyFrmNum].frmID = flv->videoFrmNum;
}
flv->curVideo.type = tempBuf[15];
flv->curVideo.size = size;
flv->curVideo.read = 0;
return 0;
}
else
{
if ((tempBuf[4] != FLV_TAG_TYPE_AUDIO) && (tempBuf[4] != FLV_TAG_TYPE_SCRIPT))
return -1;
FlvFseek(flv->videoStr, size, SEEK_CUR);
}
}
}
/********************************************************************************************
Func:
FlvAudioGetNextFrmInfo()
Description:
Get next audio frame.
Param:
FlvDemux *flv - Flv demux struct.
Return:
0: Success.
-1: Failed.
Author:
ljn
Date:
2008-1-9
Log:
********************************************************************************************/
int FlvAudioGetNextFrmInfo(FlvDemux *flv)
{
char tempBuf[16];
int size;
if (flv->curAudio.size > flv->curAudio.read)
{
FlvFseek(flv->audioStr, flv->curAudio.size - flv->curAudio.read, SEEK_CUR);
flv->curAudio.read = flv->curAudio.size;
}
while (1)
{
if ((FlvFread(tempBuf, 1, 16, flv->audioStr)) != 16) //[0]~[3]:PreviousTagSize
return -1;
size = ((unsigned long)tempBuf[5] << 16) | ((unsigned long)tempBuf[6] << 8) | ((unsigned long)tempBuf[7]);
size -= 1;
if (tempBuf[4] == FLV_TAG_TYPE_AUDIO)
{
/* video time stamp */
flv->curAudio.time = ((unsigned long)tempBuf[11] << 24) | ((unsigned long)tempBuf[8] << 16) | ((unsigned long)tempBuf[9] << 8) | (unsigned long)tempBuf[10];
//FlvFseek(flv->audioStr, 1, SEEK_CUR);
flv->curAudio.type = (tempBuf[15]);
flv->curAudio.size = size; //size-1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -