⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flvfile.c

📁 瑞星微公司RK27XX系列芯片的SDK开发包
💻 C
📖 第 1 页 / 共 2 页
字号:
/********************************************************************************************
 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 + -