当前位置: 代码迷 >> Web前端 >> WebRTC源码分析4_AVI资料读写
  详细解决方案

WebRTC源码分析4_AVI资料读写

热度:126   发布时间:2012-08-31 12:55:03.0
WebRTC源码分析4_AVI文件读写

来源:http://blog.csdn.net/lezhiyong
接口路径:
webrtc\trunk\src\modules\media_file\source\avi_file.h
代码模块:media_file
对avi文件的存储方式,可以google了解一下,或参考《AVI文件格式图表描述》点击打开链接
先对webRTC 的avi文件读写使用到几个结构体注释一下:

struct AVISTREAMHEADER
{
    AVISTREAMHEADER();
WebRtc_UWord32 fcc; //4字节,表示数据流的种类 vids 表示视频数据流,RIFF文件结构的块标志,个人觉得不应该放在AVISTREAMHEADER中
//auds 音频数据流
//‘txts’(文字流)
    WebRtc_UWord32 cb;//RIFF文件结构的数据块大小描述,个人觉得不应该放在AVISTREAMHEADER中,long120819
    WebRtc_UWord32 fccType;//RIFF文件结构的数据块类型描述,个人觉得不应该放在AVISTREAMHEADER中,long120819
WebRtc_UWord32 fccHandler; //4字节 ,表示数据流解压缩的驱动程序代号
// 指定流的处理者,对于音视频来说就是解码器

    WebRtc_UWord32 dwFlags; //数据流属性// 标记:是否允许这个流输出?调色板是否变化?
    WebRtc_UWord16 wPriority; //此数据流的播放优先级//(当有多个相同类型的流时优先级最高的为默认流)
    WebRtc_UWord16 wLanguage; //音频的语言代号
    WebRtc_UWord32 dwInitialFrames; //说明在开始播放前需要多少桢// 为交互格式指定初始帧数
    WebRtc_UWord32 dwScale; //数据量,视频每桢的大小或者音频的采样大小// 这个流使用的时间尺度
    WebRtc_UWord32 dwRate; //dwScale /dwRate = 每秒的采样数
    WebRtc_UWord32 dwStart; //数据流开始播放的位置,以dwScale为单位// 流的开始时间
    WebRtc_UWord32 dwLength; //数据流的数据量,以dwScale为单位// 流的长度(单位与dwScale和dwRate的定义有关)
    WebRtc_UWord32 dwSuggestedBufferSize; // 读取这个流数据建议使用的缓存大小
    WebRtc_UWord32 dwQuality; //解压缩质量参数,值越大,质量越好// 流数据的质量指标(0 ~ 10,000)
    WebRtc_UWord32 dwSampleSize; //音频的采样大小 // Sample的大小
    struct
    {
        WebRtc_Word16 left;
        WebRtc_Word16 top;
        WebRtc_Word16 right;
        WebRtc_Word16 bottom;
    } rcFrame; //视频图像所占的矩形// 指定这个流(视频流或文字流)在视频主窗口中的显示位置// 视//频主窗口由AVIMAINHEADER结构中的dwWidth和dwHeight决定
};

struct BITMAPINFOHEADER //参考bmp文件格式描述中的定义
{
    BITMAPINFOHEADER();
    WebRtc_UWord32 biSize;
    WebRtc_UWord32 biWidth;
    WebRtc_UWord32 biHeight;
    WebRtc_UWord16 biPlanes;
    WebRtc_UWord16 biBitCount;
    WebRtc_UWord32 biCompression;
    WebRtc_UWord32 biSizeImage;
    WebRtc_UWord32 biXPelsPerMeter;
    WebRtc_UWord32 biYPelsPerMeter;
    WebRtc_UWord32 biClrUsed;
    WebRtc_UWord32 biClrImportant;
};
struct AVIMAINHEADER
    {
        AVIMAINHEADER();
        WebRtc_UWord32 fcc;//RIFF文件结构的块标志,个人觉得不应该放在AVIMAINHEADER中,下面的cb(块大小)也一样,long120819
        WebRtc_UWord32 cb;
        WebRtc_UWord32 dwMicroSecPerFrame; //显示每桢所需的时间ns,定义avi的显示速率
        WebRtc_UWord32 dwMaxBytesPerSec; // 最大的数据传输率
        WebRtc_UWord32 dwPaddingGranularity; //记录块的长度需为此值的倍数,通常是2048
        WebRtc_UWord32 dwFlags; //AVI文件的特殊属性,如是否包含索引块,音视频数据是否交叉存储
        WebRtc_UWord32 dwTotalFrames; //文件中的总桢数
        WebRtc_UWord32 dwInitialFrames; //说明在开始播放前需要多少桢 // 为交互格式指定初始帧数(非交互格式应该指定为0)
        WebRtc_UWord32 dwStreams; //文件中包含的数据流种类// 本文件包含的流的个数
        WebRtc_UWord32 dwSuggestedBufferSize; //建议使用的缓冲区的大小,
 //通常为存储一桢图像以及同步声音所需要的数据之和
        WebRtc_UWord32 dwWidth; //图像宽(以像素为单位)
        WebRtc_UWord32 dwHeight; //图像高(以像素为单位)
        WebRtc_UWord32 dwReserved[4]; //保留值
    };

struct WAVEFORMATEX
{
    WAVEFORMATEX();
    WebRtc_UWord16 wFormatTag; //设置波形声音的格式
    WebRtc_UWord16 nChannels; //设置音频文件的通道数量,对于单声道的声音,此此值为1。对于立体声,此值为2.
    WebRtc_UWord32 nSamplesPerSec; //设置每个声道播放和记录时的样本频率。
//如果wFormatTag = WAVE_FORMAT_PCM,那么nSamplesPerSec通常为8.0 kHz, 11.025 kHz, 22.05 kHz和44.1 kHz。例如对于采样率为11.025 kHz的音频, //nSamplesPerSec 将被设为11025。对于非PCM格式的,请根据厂商的设定计算
    WebRtc_UWord32 nAvgBytesPerSec; //设置请求的平均数据传输率,单位byte/s。这个值对于创建缓冲大小是很有用的
    WebRtc_UWord16 nBlockAlign; //以字节为单位设置块对齐。块对齐是指最小数据的原子大小。如果wFormatTag= WAVE_FORMAT_PCM,nBlockAlign 为(nChannels*wBitsPerSample)/8。//对于非PCM格式请根据厂商的说明计算。
    WebRtc_UWord16 wBitsPerSample; //根据wFormatTag的类型设置每个样本的位深(即每次采样样本的大小,以bit为单位)。
//如果wFormatTag = WAVE_FORMAT_PCM,此值应该设为8或16,对于非PCM格式,根据厂商的说明设置。一些压缩的架构不能设置此值,此时wBitsPerSample应该为零。
//WebRtc_UWord16 cbSize; 额外信息的大小,以字节为单位,额外信息添加在WAVEFORMATEX结构的结尾。这个信息可以作为非PCM格式的wFormatTag额外属性,
//如果wFormatTag不需要额外的信息,此值必需为0,对于PCM格式此值被忽略。
};
2、特点:

支持写avi文件和读avi文件以及循环读取

3、类AviFile的使用方法(可参考ModuleFileUtility类中三个成员变量  AviFile* _aviAudioInFile;AviFile* _aviVideoInFile;AviFile* _aviOutFile;的使用方法)
写文件操作:

 AviFile* _aviOutFile;
_aviOutFile = new AviFile( );
//视频头结构体初始化
 AVISTREAMHEADER videoStreamHeader;
    videoStreamHeader.fccType = AviFile::MakeFourCc('v', 'i', 'd', 's');
 videoStreamHeader.fccHandler = AviFile::MakeFourCc('I','4','2','0');
 videoStreamHeader.dwScale = 1;

 BITMAPINFOHEADER bitMapInfoHeader;
    bitMapInfoHeader.biSize         = sizeof(BITMAPINFOHEADER);
    bitMapInfoHeader.biHeight       = videoCodecInst.height;
    bitMapInfoHeader.biWidth        = videoCodecInst.width;
    bitMapInfoHeader.biPlanes       = 1;
    bitMapInfoHeader.biBitCount     = 12;
    bitMapInfoHeader.biClrImportant = 0;
    bitMapInfoHeader.biClrUsed      = 0;
    bitMapInfoHeader.biCompression  = videoStreamHeader.fccHandler;
    bitMapInfoHeader.biSizeImage    = bitMapInfoHeader.biWidth *
        bitMapInfoHeader.biHeight * bitMapInfoHeader.biBitCount / 8;
    videoStreamHeader.dwRate                 = videoCodecInst.maxFramerate;
    videoStreamHeader.dwSuggestedBufferSize  = videoCodecInst.height *
        (videoCodecInst.width >> 1) * 3;
    videoStreamHeader.dwQuality              = (WebRtc_UWord32)-1;
    videoStreamHeader.dwSampleSize           = 0;
    videoStreamHeader.rcFrame.top            = 0;
    videoStreamHeader.rcFrame.bottom         = videoCodecInst.height;
    videoStreamHeader.rcFrame.left           = 0;
    videoStreamHeader.rcFrame.right          = videoCodecInst.width;
  //从代码看支持写入I420、VP8,
  //视频格式通过videoStreamHeader.fccHandler = AviFile::MakeFourCc('I','4','2','0'); 
  //bitMapInfoHeader.biCompression  = videoStreamHeader.fccHandler;设置
    if(_aviOutFile->CreateVideoStream(
            videoStreamHeader,
            bitMapInfoHeader,
            videoCodecInst.codecSpecific.MPEG4.configParameters,
            videoCodecInst.codecSpecific.MPEG4.configParametersSize) != 0)
        {
            return -1;
        }
  //音频头结构体初始化
  AVISTREAMHEADER audioStreamHeader;
        audioStreamHeader.fccType = AviFile::MakeFourCc('a', 'u', 'd', 's');
        // fccHandler is the FOURCC of the codec for decoding the stream.
        // It's an optional parameter that is not used by audio streams.
        audioStreamHeader.fccHandler   = 0;
        audioStreamHeader.dwScale      = 1;


        WAVEFORMATEX waveFormatHeader;
        waveFormatHeader.cbSize          = 0;
        waveFormatHeader.nChannels       = 1;

if (strncmp(audioCodecInst.plname, "PCMA", 4) == 0)
        {
            audioStreamHeader.dwSampleSize = 1;
            audioStreamHeader.dwRate       = 8000;
            audioStreamHeader.dwQuality    = (WebRtc_UWord32)-1;
            audioStreamHeader.dwSuggestedBufferSize = 80;


            waveFormatHeader.nAvgBytesPerSec = 8000;
            waveFormatHeader.nSamplesPerSec  = 8000;
            waveFormatHeader.wBitsPerSample  = 8;
            waveFormatHeader.nBlockAlign     = 1;
            waveFormatHeader.wFormatTag      = kWaveFormatALaw;


        } 
//其他逻辑略,从代码看支持写入的音频格式为PCMA(ALOW),PCMU(MULAW) ,PCM,通过waveFormatHeader.wFormatTag = kWaveFormatPcm;设置
 if(_aviOutFile->CreateAudioStream(
            audioStreamHeader,
            waveFormatHeader) != 0)
        {
            return -1;
        }

 _aviOutFile->Create(filename);
//写音频数据
_aviOutFile->WriteAudio(reinterpret_cast<const WebRtc_UWord8*>(buffer),bufferLengthInBytes);
//写视频数据
_aviOutFile->WriteVideo( reinterpret_cast<const WebRtc_UWord8*>(buffer), bufferLengthInBytes);

读文件中音频操作:
 AviFile* _aviAudioInFile;
  _aviAudioInFile = new AviFile();
 _aviAudioInFile->Open(AviFile::AVI_AUDIO, filename, loop);
  WAVEFORMATEX waveHeader;
        if(_aviAudioInFile->GetAudioStreamInfo(waveHeader) != 0)
        {
            return -1;
        }
//从代码看,只支持读取音频数据为PCM ,ALOW, MULOW 的文件
//读取音频数据
if(_aviAudioInFile->ReadAudio(
        reinterpret_cast<WebRtc_UWord8*>(outBuffer),
        length) != 0)
    {
        return -1;
    }

读文件中视频操作:
 AviFile* _aviVideoInFile;
_aviVideoInFile = new AviFile( );
 _aviVideoInFile->Open(AviFile::AVI_VIDEO,
                                                        filename, loop)
  AVISTREAMHEADER videoInStreamHeader;
    BITMAPINFOHEADER bitmapInfo;
    char codecConfigParameters[AviFile::CODEC_CONFIG_LENGTH] = {};
    WebRtc_Word32 configLength = 0;
    if( _aviVideoInFile->GetVideoStreamInfo(videoInStreamHeader, bitmapInfo,
                                            codecConfigParameters,
                                            configLength) != 0)
{
        return -1;
}
//从读取的bitmapInfo.biCompression看文件封装的视频格式,判断方式if (bitmapInfo.biCompression ==AviFile::MakeFourCc('V', 'P', '8', '0'))
//代码现在支持读取文件的视频格式为MP4V-ES,I420,H263,VP8
//读取视频数据
 if( _aviVideoInFile->ReadVideo( reinterpret_cast<WebRtc_UWord8*>(outBuffer),length) != 0)
 {
     return -1;
 }