AVI文件结构分析及举例验证

一、AVI文件简介

  AVI英文全称为Audio Video Interleaved,即音频视频交错格式,是微软公司于1992年11月推出、作为其Windows视频软件一部分的一种多媒体容器格式。
  AVI文件将音频(语音)和视频(影像)数据包含在一个文件容器中,允许音视频同步回放。类似DVD视频格式,AVI文件支持多个音视频流。AVI信息主要应用在多媒体光盘上,用来保存电视、电影等各种影像信息。

AVI文件格式是基于RIFF(资源交换文件格式)文档格式。RIFF文件由RIFF标头组成,后跟零个或多个列表和区块

  • RIFF标头具有以下形式:

    'RIFF' fileSize fileType (data)

    其中,“RIFF"是文本 FOURCC 代码"RIFF”,是一个 4 字节值,表示文件中数据的大小,是标识特定文件类型的fileSize fileType FOURCC。 的值包括 FOURCC 的大小以及以下数据的大小,但不包括 fileSize fileType "RIFF"FOURCC 的大小或 的大小 fileSize 。 文件数据按任何顺序由区块和列表组成。

  • RIFF区块具有以下形式:

    ckID ckSize ckData

    其中,“ckID”是标识区块中包含的数据的 FOURCC,是一个 4 字节值,表示 中数据的大小,是 ckID ckSize ckData ckData 零个或多个数据字节。 数据始终填充到最近的 WORD 边界。 ckSize 提供区块中有效数据的大小;它不包括填充、的大小 ckID 或 的大小 ckSize

  • RIFF列表具有以下形式:

    'LIST' listSize listType listData

    其中,“LIST"是文本 FOURCC 代码"LIST”,是提供列表大小的 4 字节值,是 FOURCC 代码,由区块或列表组成( listSize listType 按任何 listData 顺序)。"LIST"的值包括 listSize 的大小加上 的大小 listType listData ;它不包括 “LIST” FOURCC 或 的大小 listSize

本部分的其余部分使用下列表示法来描述 RIFF 区块:

ckID ( ckData )

其中区块大小是隐式的。 使用此表示法,列表可以表示为:

'LIST' ( listType ( listData ) )

可选元素位于方括号中: [ optional element ]

AVI文件结构

RIFF ('AVI '
      LIST ('hdrl'
            'avih'(<Main AVI Header>)
            LIST ('strl'
                  'strh'(<Stream header>)
                  'strf'(<Stream format>)
                  [ 'strd'(<Additional header data>) ]
                  [ 'strn'(<Stream name>) ]
                  ...
                 )
             ...
           )
      LIST ('movi'
            {SubChunk | LIST ('rec '
                              SubChunk1
                              SubChunk2
                              ...
                             )
               ...
            }
            ...
           )
      ['idx1' (<AVI Index>) ]
     )

二、RIFF头

  结构

  1. "RIFF"表示字符串
  2. RIFF大小
  3. 形式类型或者列表类型
  4. 数据
名称字节数说明
FOURCC 代码40x52 49 46 46“RIFF”
大小4大小=实际数据长度+4
形式类型或列表类型40x41 56 49 20“AVI”
数据

验证:

image-20220411092441885

三、LIST列表

结构

  1. “LIST”表示字符串
  2. LIST列表大小
  3. 形式类型或者列表类型
  4. LIST实际数据
名称字节数说明
FOURCC 代码40x4C 49 53 54“LIST”
列表大小4大小=实际列表数据长度+4
形式类型或列表类型40x68 64 72 6C

0x6D 6F 76 69
“hdrl”

”movi“
数据里面可能包含LIST嵌套
LIST里面音频视频分开存放

"hdrl"列表: 用于描述AVI文件中各个流的格式信息(AVI文件中的每一路媒体数据都称为一个流)。此列表里嵌套了一系列块和子列表。块中包含一个avih块,用于记录AVI文件的全局信息。子列表中包含一个或多个strl子列表。文件中有多少流,就对应多少个strl子列表,一般有视频流和音频流。

"movi"列表: 用于保存真正的媒体流数据,视频图像帧数据或音频采样数据等

验证

image-20220411092619102

image-20220411101104703

3.1 hdrl列表

3.1.1 avih块

avih块用于记录AVI文件的全局信息,比如流的数量、视频图像的宽和高等。

avih块结构: AVIMAINHEADER数据结构

typedef struct _avimainheader {undefined
    FOURCC fcc;   // 必须为‘avih’
    DWORD  cb;    // 本数据结构的大小,不包括最初的8个字节(fcc和cb两个域)
    DWORD  dwMicroSecPerFrame;   // 视频帧间隔时间(以毫秒为单位)
    DWORD  dwMaxBytesPerSec;     // 这个AVI文件的最大数据率
    DWORD  dwPaddingGranularity; // 数据填充的粒度
    DWORD  dwFlags;         // AVI文件的全局标记,比如是否含有索引块等
    DWORD  dwTotalFrames;   // 总帧数
    DWORD  dwInitialFrames; // 为交互格式指定初始帧数(非交互格式应该指定为0)
    DWORD  dwStreams;       // 本文件包含的流的个数
    DWORD  dwSuggestedBufferSize; // 建议读取本文件的缓存大小(应能容纳最大的块)
    DWORD  dwWidth;         // 视频图像的宽(以像素为单位)
    DWORD  dwHeight;        // 视频图像的高(以像素为单位)
    DWORD  dwReserved[4];   // 保留
} AVIMAINHEADER;

验证

image-20220411102222688

3.1.2 strl子列表

每个strl子列表至少包含一个strh块和一个strf块,还可以包含strd块(保存编解码器需要的一些配置信息)和strn块(保存流的名字)。

3.1.2.1 strh块

strh块主要是说明流的头信息。

strh块结构: AVISTREAMHEADER数据结构

typedef struct _avistreamheader {undefined
     FOURCC fcc;  // 必须为‘strh’
     DWORD  cb;   // 本数据结构的大小,不包括最初的8个字节(fcc和cb两个域)
     FOURCC fccType;    // 流的类型:‘auds’(音频流)、‘vids’(视频流)、
                   //‘mids’(MIDI流)、‘txts’(文字流)
     FOURCC fccHandler; // 指定流的处理者,对于音视频来说就是解码器
     DWORD  dwFlags;    // 标记:是否允许这个流输出?调色板是否变化?
     WORD   wPriority;  // 流的优先级(当有多个相同类型的流时优先级最高的为默认流)
     WORD   wLanguage;
     DWORD  dwInitialFrames; // 为交互格式指定初始帧数
     DWORD  dwScale;   // 这个流使用的时间尺度
     DWORD  dwRate;
     DWORD  dwStart;   // 流的开始时间
     DWORD  dwLength;  // 流的长度(单位与dwScale和dwRate的定义有关)
     DWORD  dwSuggestedBufferSize; // 读取这个流数据建议使用的缓存大小
     DWORD  dwQuality;    // 流数据的质量指标(0 ~ 10,000)
     DWORD  dwSampleSize; // Sample的大小
     struct {undefined
         short int left;
         short int top;
         short int right;
         short int bottom;
}  rcFrame;  // 指定这个流(视频流或文字流)在视频主窗口中的显示位置
             // 视频主窗口由AVIMAINHEADER结构中的dwWidth和dwHeight决定
} AVISTREAMHEADER;
3.1.2.2 strf块

strf块用于说明流的具体格式,分为视频流,音频流。

strf块结构:

  • 视频流结构: BITMAPINFO数据结构

    typedef struct tagBITMAPINFO{
     BITMAPINFOHEADER bmiHeader;
     RGBQUAD bmiColors[1]; //颜色表
    }BITMAPINFO;
    
    typedef struct tagBITMAPINFOHEADER{   
        DWORD biSize;	//本结构的长度,为40个字节。
        LONG biWidth;	//位图的宽度,以像素为单位。   
        LONG biHeight;	//位图的高度,以像素为单位。   
        WORD biPlanes;	//目标设备的级别,必须是1。   
        WORD biBitCount;	//每个像素所占的位数(bit),其值必须为1(黑白图像)、4(16色图)、8(256色)、24(真彩色图),新的BMP格式支持32位色。   
        DWORD biCompression;	//位图压缩类型,有效的值为BI_RGB(未经压缩)、BI_RLE8、BI_RLE4、BI_BITFILEDS(均为Windows定义常量)。   
        DWORD biSizeImage;	//实际的位图数据占用的字节数   
        LONG biXPelsPerMeter;	//指定目标设备的水平分辨率   
        LONG biYPelsPerMeter;	//指定目标设备的垂直分辨率   
        DWORD biClrUsed;	//位图实际用到的颜色数,如果该值为零,则用到的颜色数为2的biBitCount次幂   
        DWORD biClrImportant;	//位图显示过程中重要的颜色数,如果该值为零,则认为所有的颜色都是重要的。   
    } BITMAPINFOHEADER;  
    
  • 音频流结构: WAVEFORMATEX数据结构

    typedef struct
    {undefined
      WORD  wFormatTag;	//设置波形声音的格式,更多的信息请参考说明部分。
      WORD  nChannels;	//设置音频文件的通道数量,对于单声道的声音,此此值为1。对于立体声,此值为2.
      DWORD  nSamplesPerSec;	//设置每个声道播放和记录时的样本频率。
      DWORD  nAvgBytesPerSec;	//设置请求的平均数据传输率,单位byte/s。这个值对于创建缓冲大小是很有用的。
      WORD  nBlockAlign;	//以字节为单位设置块对齐。块对齐是指最小数据的原子大小。
      WORD  wBitsPerSample;	//根据wFormatTag的类型设置每个样本的位深(即每次采样样本的大小,以bit为单位)。
      WORD  cbSize;	//额外信息的大小,以字节为单位,额外信息添加在WAVEFORMATEX结构的结尾。
    } WAVEFORMATEX; *PWAVEFORMATEX;
    

3.2 movi列表

movi列表保存的是真正的媒体流数据,其数据组织方式有两种。可以将数据块直接嵌在movi列表里面,也可以将几个数据块分组成一个rec 列表后再编排进movi列表。

​ 数据块使用了一个四字符码来表征它的类型,这个四字符码由2个字节的类型码和2个字节的流编号组成。标准的类型码定义如下:db(非压缩视频帧)、dc(压缩视频帧)、pc(改用新的调色板)、wb(音缩视频)。比如第一个流(Stream 0)是音频,则表征音频数据块的四字符码为00wb;第二个流(Stream 1)是视频,则表征视频数据块的四字符码为00db00dc

四、AVI索引块

AVI索引块 使用idx1来表征。

索引块结构: AVIOLDINDEX数据结构

typedef struct _avioldindex {undefined
   FOURCC  fcc;  // 必须为‘idx1’
   DWORD   cb;   // 本数据结构的大小,不包括最初的8个字节(fcc和cb两个域)
   struct _avioldindex_entry {undefined
      DWORD   dwChunkId;   // 表征本数据块的四字符码
      DWORD   dwFlags;     // 说明本数据块是不是关键帧、是不是‘rec’列表等信息
      DWORD   dwOffset;    // 本数据块在文件中的偏移量
      DWORD   dwSize;      // 本数据块的大小
  } aIndex[]; // 这是一个数组!为每个媒体数据块都定义一个索引信息
} AVIOLDINDEX;

课程问题

  • 音频和视频的数据是如何放置的?交织放置 or连续放置?

    答:AVI文件中,音频和视频的数据是交织放置。

  • 一个视频帧大约占据多少字节?一个音频数据块大约占用多少字节?

image-20220411113628066

​ 视频帧长为0x0001D4C0,即为120000字节。

image-20220411114947817

​ 音频帧长为0x0002D5B8,即为185784字节。

参考资料

[1] : http://t.csdn.cn/zpOgP
[2] : http://t.csdn.cn/Uatey
[3] : https://docs.microsoft.com/zh-cn/windows/win32/directshow/avi-riff-file-reference

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值