首先,我们回顾一下avi文件的文件结构。下图就是一个典型的avi文件的文件结构图。
以我们录制的一个avi文件为例,其RIFF Tree结构为:
RIFF AVI 84,532,876 0
LIST hdrl 292 12
avih 56 24
dwMicroSecPerFrame : 33,000
dwMaxBytesPerSec : 0
dwTotalFrames : 1,321
dwSuggestedBufferSize: 0
dwStreams : 2
dwFlags : 0x00000110
dwWidth : 640
dwHeight : 480
dwInitialFrames : 0
dwPaddingGranularity : 8,192
LIST strl 116 88
strh 56 100
fccType : vids
fccHandler : MJPG
dwFlags : 0x00000000
dwInitialFrames : 0
dwLength : 1,321
dwQuality : 1
dwRate : 30
dwScale : 1
dwSampleSize : 0
dwStart : 0
dwSuggestedBufferSize: 0
wLanguage : 0
wPriority : 0
rcFrame : 0,0 - 640,480
strf 40 164
LIST strl 92 212
strh 56 224
fccType : auds
fccHandler :
dwFlags : 0x00000000
dwInitialFrames : 0
dwLength : 352,256
dwQuality : 4,294,967,295
dwRate : 32,000
dwScale : 4
dwSampleSize : 4
dwStart : 0
dwSuggestedBufferSize: 16,000
wLanguage : 0
wPriority : 0
rcFrame : 0,0 - 0,0
strf 16 288
LIST movi 84,510,044 312
00dc 140,900 324
00dc 64,188 141,232
...
00dc 64,412 84,382,792
00dc 63,144 84,447,212
idx1 22,512 84,510,364
一、录制一个avi文件的第一步就是准备好一个结构体,用以保存除了数据块和索引块以外的其它文件信息。我们定义了结构体AVI_HEADER_INFO,用来完成这个功能。
AVI_HEADER_INFO具体结构如下,后面的值为其初始化的值,表示我们要录一个mjpg(视频格式)+pcm(音频格式)的AVI文件。(初始化在函数avi_record_init中完成)。
typedef struct tagAVI_FILE_HEADER
{
FOURCC riff_fcc; =AVI_RIFF_TAG //"RIFF"
DWORD avi_file_length; =0 //文件长度
FOURCC avi_fcc; =AVI_AVI_TAG //“AVI”
FOURCC list_fcc; =AVI_LIST_TAG, // " LIST"
DWORD package_length; =sizeof(AVI_HEADER_INFO) - 8*sizeof(DWORD), 、
// 信息块LIST 表的大小
FOURCC hdrl_fcc; =AVI_HDRL_TAG, // " hdrl "
_AVIMAINHEADER main_header;
{
FOURCC fcc; =AVI_AVIH_TAG, // "avih"
DWORD cb; =sizeof(_AVIMAINHEADER) - (2 * sizeof(DWORD)),
// sizeof(AVIMAINHEADER)
DWORD dwMicroSecPerFrame; =1000000/30, //30帧/s的avi文件,每帧的现实时间,以us为单位
DWORD dwMaxBytesPerSec; =0 //最大的数据传输率
DWORD dwPaddingGranularity; =(2048*4), //纪录块的长度需为此值的倍数 ,通常为2048
DWORD dwFlags; =AVIF_ISINTERLEAVED|AVIF_HASINDEX
DWORD dwTotalFrames; =0 // 文件的总帧数
DWORD dwInitialFrames; =0 // 说明在开始播放前需要多少帧
DWORD dwStreams; =2, // 文件中包含的数据流的种类,2表示只有音频和视频
DWORD dwSuggestedBufferSize; =0, // 建议使用的缓冲区的大小,通常为存储一帧图像以及同步声音所需要的数据的大小
DWORD dwWidth; =AVI_VIDEO_DEFAULT_WIDTH, // 图像宽
DWORD dwHeight; =AVI_VIDEO_DEFAULT_HEIGHT, // 图像高
DWORD dwReserved[4]; ={0,0,0,0}, // 16个字节的保留字
}
_AVI_VideoStreamHeader video_stream;
{
FOURCC list_fcc; =AVI_LIST_TAG //"LIST"
DWORD package_length; =sizeof(_AVI_VideoStreamHeader)-(2 * sizeof(DWORD)),
FOURCC strl_fcc; =AVI_STRL_TAG //"strl"
_AVISTREAMHEADER stream_header;
{
FOURCC fcc; =AVI_STRH_TAG //"strh"
DWORD cb; =sizeof(_AVISTREAMHEADER) - (2 * sizeof(DWORD)),
FOURCC fccType; =AVI_STREAM_VIDEO //"vids" 数据流种类,vids表示视频流
FOURCC fccHandler; =AVI_VIDEO_CODEC_TAG //"MJPG" 4字节,表示数据流解压缩的类型
DWORD dwFlags; =0, // 数据流属性
WORD wPriority; =0, // 此数据流的播放优先级
WORD wLanguage; =0, // 音频的语言代号
DWORD dwInitialFrames; =0, // 在开始播放需要多少帧
DWORD dwScale; =1, // 数据量,视频每帧的大小或者音频的采样大小
DWORD dwRate; =AVI_VIDEO_DEFAULT_FPS, // dwScale / dwRate = 每秒的采样数
DWORD dwStart; =0, // 数据流开始播放的位置,以dwScale 为单位
DWORD dwLength; =0, // 数据流的数据量,以dwScale 为单位
DWORD dwSuggestedBufferSize; =0, // 建议缓冲区的大小,
DWORD dwQuality; =1, // 解压缩质量参数,值越大质量越好
DWORD dwSampleSize; =0, // 音频采样的大小
struct
{ //视频图像所占的矩形
short int left; =0
short int top; =0
short int right; =AVI_VIDEO_DEFAULT_WIDTH
short int bottom; =AVI_VIDEO_DEFAULT_HEIGHT
}rcFrame;
}
FOURCC strf_fcc; =AVI_STRF_TAG //”strf“
DWORD strf_length; =sizeof(_BITMAPINFOHEADER)
_BITMAPINFOHEADER bmp_info; //视频格式的结构体
}
_AVI_AudioStreamHeader audio_stream;
{
FOURCC list_fcc; =AVI_LIST_TAG //"LIST"
DWORD package_length; =sizeof(_AVI_VideoStreamHeader)-(2 * sizeof(DWORD)),
FOURCC strl_fcc; =AVI_STRL_TAG //"strl"
_AVISTREAMHEADER stream_header;
{
FOURCC fcc; =AVI_STRH_TAG //"strh"
DWORD cb; =sizeof(_AVISTREAMHEADER) - (2 * sizeof(DWORD)),
FOURCC fccType; =AVI_STREAM_AUDIO //"auds" 数据流种类,auds表示音频流
FOURCC fccHandler; =1, // 指定流的处理者,对于音视频来说就是解码器
DWORD dwFlags; =0, // 标记:是否允许这个流输出?调色板是否变化?
WORD wPriority; =0, // 流的优先级(当有多个相同类型的流时优先级最高的为默认流)
WORD wLanguage; =0, // 音频的语言代号
DWORD dwInitialFrames; =0, // 为交互格式指定初始帧数
DWORD dwScale; =4, // 这个流使用的时间尺度
DWORD dwRate; =0, // DWORD dwRate; //SampleRate!!!
DWORD dwStart; =0, // 流的开始时间
DWORD dwLength; =0, // 流的长度(单位与dwScale和dwRate的定义有关)
DWORD dwSuggestedBufferSize; =0, // 读取这个流数据建议使用的缓存大小
DWORD dwQuality; =-1, // 流数据的质量指标(0 ~ 10,000)
DWORD dwSampleSize; =4, // Sample的大小
struct
{ //视频图像所占的矩形
short int left; =0
short int top; =0
short int right; =0
short int bottom; =0
}rcFrame;
}
FOURCC strf_fcc; =AVI_STRF_TAG //“strf”
DWORD strf_length; =sizeof(_WAVEFORMATEX),
_WAVEFORMATEX wtx; //音频格式的结构体
}
FOURCC data_list_fcc; =AVI_LIST_TAG //“LIST”
DWORD data_package_length; // 数据块大小
FOURCC movi_fcc; =AVI_MOVI_TAG, // 数据块move 标志(紧接着是数据)
}AVI_HEADER_INFO;