AVI文件格式分析

因为接下来要分析的漏洞CVE-2010-2553,涉及到AVI文件格式。
所以,有必要详细了解一下AVI文件格式,这样,才能知道怎样构造出能达到漏洞利用的样本。
                            ——当你的才华还配不上你的野心时,请静下来好好努力!

1、AVI简介

1.1、AVI基本概念

  AVI是音频视频交错(Audio Video Interleaved)的缩写,它是Microsoft于1992年11月开发的一种符合RIFF文件规范的多媒体容器格式,作为其Windows视频软件的一部分。AVI文件可以在文件容器中同时包含音频视频数据,该文件容器允许同步播放音频和视频。

  许多AVI文件使用1996年2月由Matrox OpenDML组开发的文件格式扩展名。这些文件受Microsoft支持,并且被非正式地称为“AVI 2.0”。2010年,美国政府国家档案记录管理局将AVI定义为官方文件格式,用于保存数字视频

  AVI文件格式是Resource Interchange File Format(RIFF:资源交换文件格式)的子格式RIFF是一种通用文件容器格式,用于将数据存储在带标签的块中。它主要用于存储多媒体,例如声音视频,尽管它也可以用于存储任意数据RIFF文件所包含的数据类型由该文件的扩展名来标识,能以RIFF文件存储的数据包括:音频视频交错格式数据(.AVI)、波形格式数据(.WAV)、位图格式数据(.RDI)、MIDI格式数据(.RMI)、调色板格式数据(.PAL)、多媒体电影格式数据(.RMN)、动画光标格式数据(.ANI)、其它RIFF文件(.BND)。

可以查看AVI文件结构的软件:
1、RIFF File Viewer - RIFFPad v0.73 by Menasoft
2、AtomicBrowser Version 2.0, Written by David Mojdehi

1.2、AVI文件类型

  基本上,有3种类型的AVI文件:

  • AVI1.0: 原始的,旧的AVI文件。
  • Open-DML(AVI2.0): AVI文件格式的扩展,版本1.02已在1996年2月28日推出。最重要的改进是:
    • 文件大小几乎没有限制(例如,比NTFS所允许的要多得多)
    • 减少了33%的开销
  • Hybride-Files(混合文件): 出于兼容性原因,Open-DML文件包含附加的旧版索引。这不是那些文件的“官方”词汇,但它很好地描述了那种文件类型。仅包含一个RIFF列表的Hybride文件可以被视为任一文件类型

  AVI 1.0是最基本的格式,由于索引地址大小4字节表示,所以最大支持4G容量,而且与文件系统类型有关,如下:

1
2
3
4
5
6
-- Video for Windows (AVI 1.0)
- FAT (FAT16): 4GB (2GB practical, safe)
- FAT32: 4GB (2GB practical, safe)
- NTFS: 4GB (2GB practical, safe)

为了安全一般限制为2G。

1.3、基本数据结构

1.3.1、RIFF文件的基本数据结构

  Chunk是组成RIFF文件的基本单元,其基本结构如下:

1
2
3
4
5
struct chunk{
u32 id; //块标志
u32 size; //块大小
u8 data[size]; //块内容
}
  • id: 此块的标识符,由4个ASCII字符组成的FourCC数据格式标识符,用以识别块中所包含的数据。如:“RIFF”“LIST”“AVI ”“WAVE”等等。
  • size: 存储在data域中的数据的长度idsize域的大小不包括在该值内。
  • data: 块内容,具有前一个字段中给定大小的数据。其中的数据是以字(Word)为单位排列的,如果该数据长度为奇数,则在最后添加一个空字节(Null)

  两个块标识符“RIFF”“LIST”引入了可以包含子块的块。而其它块仅能含有数据“RIFF”“LIST”类型的Chunk结构如下:

1
2
3
4
5
6
struct chunk{
u32 id; //块标志
u32 size; //块大小
u32 type; //块类型
u8 restdata[size-4]; //data中除type所占的4个字节后剩余的数据
}

  可以看出“RIFF”“LIST”也是Chunk,只是它的datatyperestdata两部分组成。

  • type: 由4个ASCII字符组成的FourCC数据格式标识符,代表“RIFF”文件的类型,如:“WAVE”“AVI ”;或者是“LIST”块的类型,如AVI文件中的列表“hdrl”“movi”
  • restdata: data中除type所占的4个字节后剩余的数据,包括块内容,包含若干“Chunk”“LIST”

FourCC:
  FourCC(“four-character code”)是四个字节(通常为ASCII)的序列,用于唯一标识数据格式。在RIFF文件格式中,FourCC非常普遍,struct chunk中的id成员,“RIFF”“LIST”type成员,起始标识等信息都是用FourCC表示的。FourCC一般是四个字符,如'abcd'这样的形式,也可以三个字符包含一个空格,如'abc '这样的形式。AVI文件格式使用FourCC编码标识流类型数据块索引条目和其他信息。

1.3.2、AVI文件的基本数据结构

  在AVI文件中,有两种基本单元“Chunks”“Lists”,与RIFF文件中的基本单元差别不大,就是字段名称稍有不同,其结构如下:

Chunks:

1
2
3
4
5
typedef struct {
DWORD dwFourCC;
DWORD dwSize; //data
BYTE data[dwSize]; //contains headers or video/audio data
}CHUNK;

  • dwFourCC: 标识本“CHUNK”所包含的数据类型,如:“avih”(AVI Header)、“strh”(Stream Header)、“strf”(Stream Format)、“00dc”(编号为00的视频数据块)。
  • dwSize: 本CHUNK所包含数据的大小,不包括dwFourCCdwSize所占的8个字节。
  • data: 本CHUNK所包含的数据,大小由上一个字段dwSize指定。可以为Header视频/音频数据。

Lists:

1
2
3
4
5
6
typedef struct {
DWORD dwList;
DWORD dwSize; //dwFourCC+data
DWORD dwFourCC;
BYTE data[dwSize-4]; //contains Lists and Chunks
}LIST;

  • dwList: LIST的类型,其值可以为“RIFF”(“RIFF-List”)或“LIST”(“List”)。
  • dwSize: 本LIST所包含数据的大小,嵌套ListChunk数据大小之和。包含dwFourCCdata
  • dwFourCC: 由4个ASCII字符组成的FourCC数据格式标识符,代表“RIFF”文件的类型,如:“WAVE”“AVI ”;或者是“LIST”块的类型,如AVI文件中的列表“hdrl”“movi”
  • data: 本LIST所包含的数据,其大小为dwSize-4数据内容可以是若干个ListChunk

2、AVI文件结构

2.1、AVI文件整体布局

  我们用如下的方式来表示一个LIST块(dwSize省略):

1
2
LIST (dwFourCC (data))
LIST ('hdrl' ...)

  可选块我们用“[]”括起来:

1
['idx1' (<AVI Index>) ]

  AVI文件格式将文件的数据分为一个一个“Chunk”,每个“Chunk”都由FourCC标签标识。AVI文件格式采用RIFF格式的文件中单个“Chunk”的形式,然后细分为两个必须的“List Chunk”(“hdrl”和“movi”)和一个可选的“Index Chunk”(“idx1”)。下面是一个简化的AVI文件布局:

1
2
3
4
5
RIFF ('AVI '
LIST ('hdrl' ... )
LIST ('movi' ... )
['idx1' (<AVI Index>) ]
)

  “hdrl”列表定义了本AVI文件所保存的数据的格式,是第一个必须的LIST块“movi”列表保存的是AVI的音频/视频序列数据,是第二个必须的LIST块“idx1”“movi”列表中包含的音频/视频序列数据块文件中位置列表

  AVI文件的实际数据中,使用了列表(List)块(Chunk)的形式来组织。列表(List)可以嵌套列表(List)块(Chunk)整个AVI文件可以看成一个List数据块,其dwList“RIFF”,称为“RIFF-List”块,其dwFourCC“AVI”。一个AVI文件中只允许存在一个RIFF块。RIFF块中包含一系列的子块,其中有一种子块的dwList“LIST”,称为LIST块LIST块中可以再包含一系列的子块,但除了LIST块外的其他所有的子块都不能再包含子块。

  “hdrl”“movi”LIST块使用子块作为它们的数据,我们将其展开,以下示例显示了一个较为完整的AVI文件的布局:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
RIFF ('AVI '
LIST ('hdrl'
'avih'(<Main AVI Header>)
LIST ('strl'
'strh'(<Stream header>)
'strf'(<Stream format>)
[ 'strd'(<Additional header data>) ]
[ 'strn'(<Stream name>) ]
...
)
...
)
LIST ('INFO' INAM("Two Trees"Z)
ICMT("A picture for the opening screen"Z)
)
LIST ('movi'
{SubChunk | LIST ('rec '
SubChunk1
SubChunk2
...
)
...
}
...
)
['idx1' (<AVI Index>) ]
)

  每个AVI文件都具有以下布局

1
2
RIFF AVI    //强制
{RIFF AVIX} //仅适用于Open-DML文件

  将其中dwFourCC ='AVI'的RIFF-List称为'RIFF-AVI-List',将其中dwFourCC ='AVIX'的RIFF-List称为'RIFF-AVIX-List'

  与uint32(4字节)的表示范围不同,这些列表的大小限制不是4GB,而是

  • 对于AVI 1.0:大小(RIFF-AVI) < 2GB
  • 对于Open-DML
    • size(RIFF-AVI) < 1GB (假设某些混合应用程序(例如VirtualDub!)为2GB)
    • size(RIFF-AVIX) < 2GB

  由于Windows XP会在未找到旧索引的情况下坚持读取整个第一个RIFF AVI列表,并且由于旧索引会导致开销,因此建议创建尽可能小RIFF-AVI-List

2.2、hdrl List(Headerlist)

  “hdrl List”是AVI文件的文件头,其中包含的数据是有关视频的MetaData(元数据),例如其宽度高度帧频“hdrl List”块包含两种子块,一种是dwFourCC“avih”Chunk,另一种是dwFourCC“strl”List

2.2.1、avih Chunk(AVI Header)

  “avih”块用于存储AVI文件的全局信息,如:流的数量、视频的宽度高度等。此结构定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
typedef struct {
DWORD dwFourCC; // 必须为'avih'
DWORD dwSize; // 本数据结构的大小,不包括最初的8个字节(dwFourCC和dwSize两个字段)
BYTE data[dwSize]; // AVIMainHeader struct
}CHUNK;

typedef struct {
DWORD dwMicroSecPerFrame; // 每帧的持续时间(以毫秒ms为单位),定义avi的显示速率
DWORD dwMaxBytesPerSec; // 最大的数据传输率
DWORD dwPaddingGranularity; // 数据填充的粒度
DWORD dwFlages; // AVI文件的特殊属性,如是否包含索引块,音视频数据是否交叉存储
DWORD dwTotalFrame; // 文件中的总帧数
DWORD dwInitialFrames; // 说明在开始播放前需要多少桢
DWORD dwStreams; // 文件中包含的数据流个数
DWORD dwSuggestedBufferSize; // 建议使用的缓冲区的大小,
// 通常为存储一桢图像以及同步声音所需要的数据之和
DWORD dwWidth; // 图像宽
DWORD dwHeight; // 图像高
DWORD dwReserved[4]; // 保留值
} AVIMainHeader;

  • dwFourCC: 标识此块为“avih”,用于存储AVIMainHeader结构体数据。
  • dwSize: AVIMainHeader结构体的字节数
  • dwMicroSecPerFrame: 一个视频帧持续时间(以微秒为单位)。可以忽略此值(请参阅Stream Header),但任何AVI编写器均应正确写入该值。
    • 重要说明:某些AVI修改软件,例如AVIFrate,会将帧速率值写入Stream Header,而不是dwMicroSecPerFrame。 因此,dwMicroSecPerFrame不应该被认为是可靠的
  • dwMaxBytesPerSec: 指定文件的大致最大数据速率。这个值表示系统每秒必须处理的字节数,以显示AVI序列,该序列由Main HeaderStream Header块中包含的其他参数指定。该值也不重要。其可靠性不应被高估。
  • dwPaddingGranularity: 指定数据对齐方式(以字节为单位)。将数据填充为该值的倍数
  • dwFlages: 见下文。
  • dwTotalFrame: 指定文件中数据帧的总数。包含在RIFF-AVI列表中的视频帧数(如果存在RIFF-AVIX-List,则不应包含整个文件中的帧总数。某些声称处理AVI文件的工具甚至假定了这一点,但它显然违反了Open-DML文件格式规范。此类应用程序已损坏。)。由于某些AVI文件muxer在此处写入了错误的值,因此不应认为此值是可靠的。
  • dwInitialFrames: 为交错格式指定初始帧数(非交错格式应该指定为0)。如果要创建交错文件,请在该成员中的AVI序列的初始帧之前指定文件中的帧数。要为音频驱动程序提供足够的音频以供使用,必须将交错文件中的音频数据相对于视频数据倾斜。通常,音频数据向前移动足够的帧,以允许大约0.75秒音频数据预加载dwInitialRecords成员应设置为音频向前的帧数。还要在音频流头中为AVIStreamHeader结构的dwInitialFrames成员设置相同的值。
  • dwStreams: 文件中包含的数据流个数。例如,一个带有音频视频的文件有两个流
  • dwSuggestedBufferSize: 指定用于读取文件的建议缓冲区大小。通常,此大小应足够大以包含文件中最大的块。如果设置为,或者设置得太小,则播放软件将不得不在播放过程重新分配内存,这会降低性能。对于交错文件,缓冲区大小应足够大以读取整个记录,而不仅仅是
  • dwWidth: 视频流宽度。以像素为单位。
  • dwHeight: 视频流高度。以像素为单位。
  • dwReserved: 保留。将这个数组设置为0

  dwFlages中有效的Flags:

  • AVIF_HASINDEX: 该文件有索引
  • AVIF_MUSTUSEINDEX: 指示应用程序应该使用索引,而不是文件中块的物理顺序,来确定数据表示的顺序。例如,这个标志可以用来创建一个帧列表来编辑。
  • AVIF_ISINTERLEAVED: Stream适当的相互交错。
  • AVIF_WASCAPTUREFILE: 表示AVI文件是专门分配的用于实时视频采集的文件。应用程序在对设置了该标志的文件进行写入之前应该警告用户,因为用户可能会对该文件进行整理
  • AVIF_COPYRIGHTED: 表示AVI文件包含有版权的数据和软件。当使用这个标志时,软件不应该允许复制数据
  • AVIF_TRUSTCKTYPE(Open-DML only!): 该标志表示索引中的关键帧标志(AVIIF_KEYFRAME)是可靠的。如果未在Open-DML文件中设置此标志,则关键帧标志可能存在缺陷,而不会从技术上使文件无效。

2.2.2、strl List(Stream Header List)

  “strl List”用于存储AVI文件中的数据流(音频流视频流字幕流)的相关信息。在“hdrl List”中的“avih Chunk”之后,有一个或多个“strl List”

  • 1、AVI文件中有多少个数据流(视频流、音频流、字幕流),这里就对应有多少个“strl List”。每个“strl List”都包含AVI文件中一个数据流的相关信息。
  • 2、每个“strl List”中至少包含一个“strh Chunk”和一个“strf Chunk”
  • 3、“strd Chunk”“strn Chunk”是可选的。
  • 4、根据“strl List”“hdrl List”中的顺序,“hdrl List”中的Stream Header“movi List”中的Stream Data是一一对应的。第一个“strl List”应用于Stream 0,第二个“strl List”应用于Stream 1,以此类推。
2.2.2.1、strh Chunk(Stream Header)

  “strh Chunk”用于描述“strl List”对应的数据流的相关信息。此Chunk中的data中存储的是AVIStreamHeader结构体数据,其结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
typedef struct {
DWORD dwFourCC; // 必须为'strh'
DWORD dwSize; // 本数据结构的大小,不包括最初的8个字节(dwFourCC和dwSize两个字段)
BYTE data[dwSize]; // AVIStreamHeader struct
}CHUNK;

typedef struct {
FOURCC fccType; // 4字节,表示数据流的种类,vids表示视频数据流,auds表示音频数据流
FOURCC fccHandler; // 4字节 ,表示数据流解压缩的驱动程序代号
DWORD dwFlags; // 数据流属性
WORD wPriority; // 此数据流的播放优先级
WORD wLanguage; // 音频的语言代号
DWORD dwInitalFrames; // 说明在开始播放前需要多少桢
DWORD dwScale; // 数据量,视频每桢的大小或者音频的采样大小
DWORD dwRate; // dwScale/dwRate = 每秒的采样数
DWORD dwStart; // 数据流开始播放的位置,以dwScale为单位
DWORD dwLength; // 数据流的数据量,以dwScale为单位
DWORD dwSuggestedBufferSize; // 建议缓冲区的大小
DWORD dwQuality; // 解压缩质量参数,值越大,质量越好
DWORD dwSampleSize; // 音频的采样大小
RECT rcFrame; // 视频图像所占的矩形
}AVIStreamHeader;

typedef struct {
short int left;
short int top;
short int right;
short int bottom;
}RECT;
  • dwFourCC: 标识此块为“strh”,用于存储AVIStreamHeader结构体数据。
  • dwSize: AVIStreamHeader结构体的字节数
  • fccType: 表示数据流的种类“vids”(视频流)、“auds”(音频流)、“mids”(MIDI流)、“txts”(字幕流)。
  • fccHandler: 要使用的编解码器FourCC
  • dwFlags: 数据流属性,定义了以下标志:
    • AVISF_DISABLED: 默认情况下不应激活此数据流。
    • AVISF_VIDEO_PALCHANGES: Stream是使用调色板视频流,其中在播放过程调色板会发生变化。
  • wPriority: 此数据流的播放优先级,当有多个相同类型的流优先级最高的为默认流
  • wLanguage: 音频的语言代号
  • dwInitalFrames: 指定交错文件音频数据视频帧之前的偏移量。通常,这是大约0.75秒。如果要创建交错文件,请在该成员的AVI序列的初始帧之前指定文件中的帧数。有关更多信息,请参见AVIMainHeader结构的dwInitialFrames成员的备注。
  • dwScale: 数据量视频每桢的大小或者音频采样大小。与dwRate一起使用以指定此流将使用的时间尺度。将dwRate除以dwScale可得出每秒的采样数。对于视频流,这是帧速率。对于音频流,此速率对应于播放音频的nBlockAlign字节所需的时间,而对于PCM音频,这只是采样速率。dwScale和dwRate应该互质。测试表明,例如10000000/400000代替25/1会导致文件在某些硬件MPEG4播放器上不起作用。
  • dwRate: 参考dwScale。
  • dwStart: 指定此流的开始时间。单位由AVIStreamHeader中的dwRatedwScale成员定义。通常,它是0,但是它可以为不与文件同时启动的流指定延迟时间。对于VBR音频,此值指示在流开始之前要播放的无声帧数
  • dwLength: 指定流的长度,以dwRatedwScale定义的单位为单位。
  • dwSuggestedBufferSize: 指定应使用多大的缓冲区读取此流。通常,它包含一个与流中存在的最大块相对应的值。使用正确的缓冲区大小可使播放效率更高。如果您不知道正确的缓冲区大小,请使用可以为0(在这种情况下,应用程序必须猜测),但不应该为0,因为MicrosoftAVI解析器在某些情况下无法正确处理此情况(例如,Open-DML文件中的MP3-CBR)。
  • dwQuality: 指定流中数据质量的指示符。质量表示为0到10000之间的数字。对于压缩数据,这通常表示传递给压缩软件的质量参数的值。如果设置为–1,驱动程序将使用默认质量值
  • dwSampleSize: 指定单个数据样本的大小。如果样本大小不同,则将其设置为0。如果该数字不为0,则可以将多个数据样本分组到文件内的单个块中。如果为0,则每个数据样本(例如视频帧)必须位于单独的块中。对于视频流,此数字通常为0,但如果所有视频帧的大小相同,则可以为非0。对于音频流,此数字应与描述音频的WAVEFORMATEX结构的nBlockAlign成员相同。
  • rcFrame: 指定由AVIMainHeader结构的dwWidthdwHeight成员指定的影片矩形内的字幕视频流的目标矩形rcFrame成员通常用于支持多个视频流。将此矩形设置为与影片矩形对应的坐标,以更新整个影片矩形。该成员的单位是像素目标矩形的左上角相对于影片矩形的左上角。

  该结构的某些成员也存在于AVIMainHeader结构中。AVIMainHeader结构中的数据应用于整个文件,而AVIStreamHeader结构中的数据应用于一个流

2.2.2.2、strf Chunk(Stream Format)

  “strf Chunk”紧跟在“strh Chunk”之后,其描述了数据流中数据的格式。此Chunk中包含的数据取决于数据流的类型。对于视频流,该信息是BITMAPINFO结构,包括适当的调色板信息。对于音频流,该信息是WAVEFORMATEX结构。

视频流(BITMAPINFO)

  BITMAPINFO结构定义了一个DIB(Device-Independent Bitmap:设备无关位图)的尺寸颜色信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
typedef struct {
DWORD dwFourCC; // 必须为'strf'
DWORD dwSize; // 本数据结构的大小,不包括最初的8个字节(dwFourCC和dwSize两个字段)
BYTE data[dwSize]; // BITMAPINFO struct
}CHUNK;

// 位图信息
typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
} BITMAPINFO;

// 位图信息头
typedef struct tagBITMAPINFOHEADER {
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER;

typedef struct tagRGBQUAD {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;
  • dwFourCC: 标识此块为“strf”,用于存储BITMAPINFO结构体数据。
  • dwSize: BITMAPINFO结构体的字节数
  • bmiHeader: 一个BITMAPINFOHEADER结构,包含关于DIB的尺寸颜色格式的信息。
  • bmiColors: bmiColors成员包含以下之一:
    • RGBQUAD的数组。数组元素组成了颜色表
    • 一个16位无符号整数数组,用于指定当前实现的逻辑调色板中的索引。对于使用DIB函数,可以使用bmiColors。数组中的条目数取决于BITMAPINFOHEADER结构的biBitCountbiClrUsed成员的值。bmiColors表中的颜色按重要性顺序显示。

  DIB(Device-Independent Bitmap:设备无关位图)由两个不同的部分组成:描述位图的尺寸颜色BITMAPINFO结构体,以及定义位图像素字节数组数组中的位打包在一起,但是每条扫描线必须用0填充,以在LONG数据类型边界上结束。如果位图的高度为正,则位图为自下而上的DIB,其原点为左下角。如果高度为负,则位图为自上而下的DIB,其原点为左上角

  当位图数组紧跟在BITMAPINFO头之后时,位图被压缩。压缩的位图由单个指针引用。对于压缩位图,在使用DIB_PAL_COLORS模式时,必须将biClrUsed成员设置为偶数,以使DIB位图数组DWORD边界开始(对齐)。

  BITMAPINFOHEADER结构体包含了设备无关位图(DIB)尺寸颜色格式的信息。

  • biSize: 指定此结构所需的字节数。如果它们被附加到此结构的末尾,则此值不包括颜色表的大小或颜色掩码的大小。
  • biWidth: 指定位图的宽度,以像素为单位。
  • biHeight: 指定位图的高度,以像素为单位。
    • 对于未压缩RGB位图,如果biHeight为正,则该位图是自下而上的DIB,其原点位于左下角。如果biHeight为负,则位图是自上而下的DIB,其原点位于左上角
    • 对于YUV位图,无论biHeight的符号如何,位图始终是自顶向下的。解码器应提供具有正biHeightYUV格式,但为了向后兼容,它们应接受具有正或负biHeightYUV格式。
    • 对于压缩格式,biHeight必须为,无论图像方向如何。
  • biPlanes: 指定目标设备平面数。此值必须设置为1
  • biBitCount: 指定每个像素的位数(bits per pixel:bpp)。对于未压缩格式,此值为每个像素的平均位数。对于压缩格式,此值是在解码图像后未压缩图像隐含位深度
  • biCompression:
    • 对于压缩视频YUV格式,此成员是FourCC代码,指定为以小端序排列的DWORD。例如,YUYV视频的FourCC“VYUY”0x56595559
    • 对于未压缩RGB格式,可以使用以下值:BI_RGB(未压缩的RGB)、BI_BITFIELDS(带颜色掩码的未压缩RGB。适用于16位和32位的位图。)
    • 对于16-bpp位图,如果biCompression等于BI_RGB,则格式始终为RGB555。如果biCompression等于BI_BITFIELDS,则格式为RGB555RGB565。使用AM_MEDIA_TYPE结构中的子类型GUID确定特定的RGB类型
  • biSizeImage: 指定图像的大小(以字节为单位)。对于未压缩RGB位图,可以将其设置为0
  • biXPelsPerMeter: 指定位图目标设备的水平分辨率(以像素每米为单位)。
  • biYPelsPerMeter: 指定位图目标设备的垂直分辨率(以像素每米为单位)。
  • biClrUsed: 指定颜色表中位图实际使用的颜色索引数
  • biClrImportant: 指定被认为对显示位图很重要颜色索引数。如果该值为,则所有颜色都很重要

  RGBQUAD结构体成员含义:

  • rgbBlue: 颜色中蓝色的强烈程度。
  • rgbGreen: 颜色中绿色的强烈程度。
  • rgbRed: 颜色中红色的强烈程度。
  • rgbReserved: 该成员是保留的,并且必须为零
音频流(WAVEFORMATEX)

  WAVEFORMATEX结构定义了波形音频数据的格式。 该结构仅包括所有波形音频数据格式共有的格式信息。 对于需要附加信息的格式,此结构作为附加信息包括在另一个结构中作为第一个成员

  支持两个以上通道超过16位的样本大小(更高的采样分辨率)的格式可以用WAVEFORMATEXTENSIBLE结构来描述,该结构包括WAVEFORMATEX结构。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
typedef struct {
DWORD dwFourCC; // 必须为'strf'
DWORD dwSize; // 本数据结构的大小,不包括最初的8个字节(dwFourCC和dwSize两个字段)
BYTE data[dwSize]; // WAVEFORMATEX struct或WAVEFORMATEXTENSIBLE struct
} CHUNK;

typedef struct tWAVEFORMATEX {
WORD wFormatTag;
WORD nChannels;
DWORD nSamplesPerSec;
DWORD nAvgBytesPerSec;
WORD nBlockAlign;
WORD wBitsPerSample;
WORD cbSize;
} WAVEFORMATEX;

typedef struct {
WAVEFORMATEX Format;
union {
WORD wValidBitsPerSample;
WORD wSamplesPerBlock;
WORD wReserved;
} Samples;
DWORD dwChannelMask;
GUID SubFormat;
} WAVEFORMATEXTENSIBLE;

  WAVEFORMATEX结构体成员含义:

  • wFormatTag: 波形音频格式类型。格式标签已向Microsoft Corporation注册用于许多压缩算法。可以在Mmreg.h头文件中找到格式标签的完整列表。 对于一个或两个通道PCM数据,此值应为WAVE_FORMAT_PCM。当此结构包含在WAVEFORMATEXTENSIBLE结构中时,此值必须为WAVE_FORMAT_EXTENSIBLE
  • nChannels: 波形音频数据中的通道数单声道数据使用一个通道立体声数据使用两个通道
  • nSamplesPerSec: 采样率,以每秒采样数(赫兹:hz)为单位。如果wFormatTagWAVE_FORMAT_PCM,则nSamplesPerSec的常用值为8.0kHz11.025kHz22.05kHz44.1kHz。对于非PCM格式,必须根据制造商格式标签规范来计算此成员。
  • nAvgBytesPerSec: 格式标签所需的平均数据传输速率,以字节每秒为单位。如果wFormatTagWAVE_FORMAT_PCM,则nAvgBytesPerSec应该等于nSamplesPerSecnBlockAlign的乘积。对于非PCM格式,必须根据制造商格式标签规范来计算此成员。
  • nBlockAlign: 块对齐,以字节为单位。块对齐是wFormatTag格式类型的最小数据原子单位。如果wFormatTagWAVE_FORMAT_PCMWAVE_FORMAT_EXTENSIBLE,则nBlockAlign必须等于nChannelswBitsPerSample乘积除以8(位/字节)。对于非PCM格式,必须根据制造商格式标签规范来计算此成员。软件必须一次处理多个nBlockAlign字节数据。对设备的读写数据必须始终从块的开头开始。例如,在样本中间(即在非块对齐边界上)开始播放PCM数据非法的。
  • wBitsPerSample: wFormatTag格式类型的每个样本位数。如果wFormatTagWAVE_FORMAT_PCM,则wBitsPerSample应该等于8或16。对于非PCM格式,必须根据制造商格式标签规范设置此成员。如果wFormatTagWAVE_FORMAT_EXTENSIBLE,则此值可以是8的任何整数倍,并表示容器的大小,不一定是样本的大小;例如,一个20位样本24位容器中。某些压缩方案无法为wBitsPerSample定义值,因此该成员可以为0
  • cbSize: 附加在WAVEFORMATEX结构末尾的额外格式信息的大小(以字节为单位)。非PCM格式可以使用此信息来存储wFormatTag其他属性。如果wFormatTag不需要其他信息,则必须将此成员设置为0。对于WAVE_FORMAT_PCM格式(仅WAVE_FORMAT_PCM格式),将忽略此成员。当此结构包含在WAVEFORMATEXTENSIBLE结构中时,该值必须至少为22

  使用额外信息的格式的一个示例是Microsoft自适应增量脉冲编码调制(MS-ADPCM)格式。 MS-ADPCMwFormatTagWAVE_FORMAT_ADPCMcbSize成员通常将设置为32。为WAVE_FORMAT_ADPCM存储的额外信息是编码和解码波形音频数据所需的系数对

  WAVEFORMATEXTENSIBLE结构体成员含义:

  • Format: 指定基本格式的WAVEFORMATEX结构。wFormatTag成员必须为WAVE_FORMAT_EXTENSIBLEcbSize成员必须至少为22
  • Samples: 描述样本格式的联合体(union)。
    • Samples.wValidBitsPerSample: 信号中的精度位数。通常等于WAVEFORMATEX.wBitsPerSample。但是,wBitsPerSample容器大小,并且必须是8的倍数,而wValidBitsPerSample可以是不超过容器大小的任何值。例如,如果格式使用20位样本,则wBitsPerSample必须至少为24,而wValidBitsPerSample20
    • Samples.wSamplesPerBlock: 一个音频数据压缩块中包含的样本数。此值用于缓冲区估计。该值与压缩格式一起使用,该压缩格式在每个块中具有固定数量的样本。如果每个压缩音频数据块中包含可变数量的样本,则可以将该值设置为0。在这种情况下,需要以其他方式获得缓冲区估计位置信息
    • Samples.wReserved: 保留给操作系统内部使用。设置为0
  • dwChannelMask: 通道掩码位掩码,指定将流中的通道分配给扬声器的位置
  • SubFormat: 数据的子格式,例如KSDATAFORMAT_SUBTYPE_PCM。子格式信息类似于WAVEFORMATEX结构的wFormatTag成员中的标签所提供的信息。

  WAVEFORMATEXTENSIBLE可以描述WAVEFORMATEX可以描述的任何格式,但可以为两个以上的通道提供额外的支持,为了使每个样本的位数更精确,并支持新的压缩方案

  WAVEFORMATEXTENSIBLE可以安全地强制转换为WAVEFORMATEX,因为它仅配置WAVEFORMATEX.cbSize指定的额外字节。

  dwChannelMask成员指定多通道流中存在哪些通道最低有效位对应于左前扬声器下一个最低有效位对应于右前扬声器,依此类推。这些位按意义顺序定义如下。

Speaker Position Flag Bit Description
SPEAKER_FRONT_LEFT 0x1 左前扬声器
SPEAKER_FRONT_RIGHT 0x2 右前扬声器
SPEAKER_FRONT_CENTER 0x4 前中扬声器
SPEAKER_LOW_FREQUENCY 0x8 低频扬声器
SPEAKER_BACK_LEFT 0x10 左后扬声器
SPEAKER_BACK_RIGHT 0x20 右后扬声器
SPEAKER_FRONT_LEFT_OF_CENTER 0x40 左前中置扬声器
SPEAKER_FRONT_RIGHT_OF_CENTER 0x80 右前中置扬声器
SPEAKER_BACK_CENTER 0x100 后中扬声器
SPEAKER_SIDE_LEFT 0x200 左侧扬声器
SPEAKER_SIDE_RIGHT 0x400 右侧扬声器
SPEAKER_TOP_CENTER 0x800 上层中置扬声器
SPEAKER_TOP_FRONT_LEFT 0x1000 上层左前扬声器
SPEAKER_TOP_FRONT_CENTER 0x2000 上层前中扬声器
SPEAKER_TOP_FRONT_RIGHT 0x4000 上层右前扬声器
SPEAKER_TOP_BACK_LEFT 0x8000 上层左后扬声器
SPEAKER_TOP_BACK_CENTER 0x10000 上层后中扬声器
SPEAKER_TOP_BACK_RIGHT 0x20000 上层右后扬声器

  dwChannelMask中指定的通道必须以规定的顺序显示(从最低有效位开始)。例如,如果仅指定SPEAKER_FRONT_LEFTSPEAKER_FRONT_RIGHT,则左前扬声器的采样必须首先出现在交错流中。dwChannelMask中设置的位数应与WAVEFORMATEX.nChannels中指定的通道数相同。

  为了向后兼容,任何可以由独立的WAVEFORMATEX结构指定的波形格式也可以由WAVEFORMATEXTENSIBLE结构定义。因此,mmreg.h中的每个波形格式标签都具有一个对应的SubFormat GUID。下表显示了一些典型的波形格式标签及其相应的SubFormat GUID。这些GUID在Ksmedia.h中定义。

Wave-Format Tag SubFormat GUID
WAVE_FORMAT_PCM KSDATAFORMAT_SUBTYPE_PCM
WAVE_FORMAT_IEEE_FLOAT KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
WAVE_FORMAT_DRM KSDATAFORMAT_SUBTYPE_DRM
WAVE_FORMAT_ALAW KSDATAFORMAT_SUBTYPE_ALAW
WAVE_FORMAT_MULAW KSDATAFORMAT_SUBTYPE_MULAW
WAVE_FORMAT_ADPCM KSDATAFORMAT_SUBTYPE_ADPCM

  由于WAVEFORMATEXTENSIBLEWAVEFORMATEX的扩展版本,因此它可以描述其他WAVEFORMATEX无法单独描述的格式。供应商可以自由定义自己的SubFormat GUID,以标识没有波形格式标签专有格式

  对于特定的扩展格式,以下结构定义为WAVEFORMATEXTENSIBLE

Definition Value of SubFormat
WAVEFORMATIEEEFLOATEX KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
WAVEFORMATPCMEX KSDATAFORMAT_SUBTYPE_PCM
2.2.2.3、strd Chunk(Stream Header Data / Additional Header Data)

  “strd Chunk”紧跟在“strf Chunk”之后,保存的是可选的额外的流的头信息数据。如果存在Stream Header Data(“strd”)块,则其遵循Stream Format(“strf”)块。该块的格式和内容编解码器驱动程序定义。通常,驱动程序使用此信息进行配置读取和写入AVI文件的应用程序不需要解释此信息。他们简单地将其作为存储块驱动程序之间来回传输。

2.2.2.4、strn Chunk(Stream Name)

  可选的“strn”块包含描述该流的以null结尾文本字符串。该块包含流的名称。该流名称仅应使用纯ASCII,尤其不能使用UTF-8

2.2.2.5、indx Chunk(Super Index Chunk)

  只有符合Open-DML(AVI2.0)规范的AVI文件才可能存在此块。每个流在其Stream Header List(“strl”)中都包含一个“indx”块。该块是超级索引块(Upper Level Index Chunk或Super Index Chunk),索引的索引

  Upper Level Index(“Super Index”)指向其他索引块,并具有以下结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
typedef struct _avisuperindex {
FOURCC fcc;
UINT cb;
WORD wLongsPerEntry;
BYTE bIndexSubType;
BYTE bIndexType;
DWORD nEntriesInUse;
DWORD dwChunkId;
DWORD dwReserved[3];
struct _avisuperindex_entry {
__int64 qwOffset;
DWORD dwSize;
DWORD dwDuration;
} aIndex[];
} AVISUPERINDEX;
  • fcc: FourCC代码。与Chunk结构体中的dwFourCC相同。该值必须为'indx'
  • cb: 此结构体的大小,与Chunk结构体中的dwSize相同。不包括初始的8个字节(fcc和cb)。
  • wLongsPerEntry: 每个索引项的大小,以4字节为单位。此值必须为4。每个aIndex[i]的大小为4*wLongsPerEntry个字节。(每个aIndex[i]的结构取决于特定类型的索引)
  • bIndexSubType: 索引子类型。必须为0AVI_INDEX_SUB_2FIELD
  • bIndexType: 索引类型。必须为AVI_INDEX_OF_INDEXES
  • nEntriesInUse: aIndex数组中有效的条目数aIndex[0]..aIndex[nEntriesInUse-1]有效。
  • dwChunkId: 标识被索引的对象的FourCC索引指向的流的ID,例如“00dc”。因此,一个这样的索引块只能指向同一个流的数据。
  • dwReserved: 保留。将数组元素设置为0
  • aIndex: 包含下列成员的结构体数组。数组中的元素数量是根据cb的值计算的。
    • qwOffset: 从文件开头到该条目所指向的子索引块偏移量,以字节为单位。
    • dwSize: 子索引块大小(该条目指向的标准索引块的大小),以字节为单位。
    • dwDuration: 子索引所覆盖的文件的持续时间,以流节拍(stream ticks)为测量单位,如在AVI Stream Header中指出的(dwScale/dwRate)。对于视频VBR音频,通常指帧数

  “indx Chunk”(Super Index Chunk)的示意图如下:

Super Index Chunk(indx)

2.3、INFO List

  “INFO”列表是已注册的全局表单类型,可以存储有助于识别块内容的信息。此信息很有用,但不会影响程序解释文件的方式;例如版权信息注释“INFO”列表是列表类型为“INFO”“LIST”块。以下示例显示了示例“INFO”列表块:

1
2
3
LIST('INFO' INAM("Two Trees"Z)
ICMT("A picture for the opening screen"Z)
)

  “INFO”列表应仅包含以下块。可以定义新的块,但是应用程序应忽略不理解的任何块。下面列出的块可能仅出现在“INFO”列表中。每个块都包含一个ZSTR以null结尾的文本字符串(所有文本字符串必须对齐)。

Chunk ID Description
IARL 存档位置(Archival Location)。指示文件主题的存档位置。
IART 艺术家(Artist)。列出文件原始主题的艺术家;例如,“Michaelangelo.”。
ICMS 受委托的(Commissioned)。列出受委托的文件主题的人员或组织的名称;例如“Pope Julian II.”。
ICMT 注释(Comments)。提供有关文件或文件主题的一般注释。如果注释长几个句子,请以句号结尾每个句子。不要包含换行符。
ICOP 版权(Copyright)。记录文件的版权信息;例如,“Copyright Encyclopedia International 1991.”。如果有多个版权,请用分号和空格隔开。
ICRD 创建日期(Creation date)。指定创建文件主题的日期。以年-月-日格式列出日期,左边用0填充一位数的月和日;例如1553年5月3日的“1553-05-03”。
ICRP 裁剪(Cropped)。描述图像是否已裁剪,如果已裁剪,则如何裁剪;例如“lower-right corner.”。
IDIM 大小(Dimensions)。指定文件原始主题的大小;例如,“8.5 in h,11 in w”
IDPI 每英寸点数(Dots Per Inch)。存储用于生成文件的数字化转换器的每英寸点数设置,例如“300”。
IENG 工程师(Engineer)。存储处理文件的工程师的姓名。如果有多个工程师,请用分号和空格分隔名称;例如,“Smith, John; Adams, Joe.”
IGNR 类型(Genre)。描述原始作品,例如“landscape,”、“portrait,”、“still life,”等。
IKEY 关键字(Keywords)。提供引用文件或文件主题的关键字列表。用分号和空格分隔多个关键字;例如,“Seattle; aerial view; scenery.”
ILGT 亮度(Lightness)。描述生成文件所需的数字化转换器的亮度设置的更改。请注意,此信息的格式取决于所使用的硬件。
IMED 媒介(Medium)。描述文件的原始主题,例如“computer image,”(计算机图片)、“drawing,”(绘画)、“lithograph,”(石板画)等。
INAM 名称(Name)。存储文件主题的标题,例如“Seattle From Above.”
IPLT 调色板设置(Palette Setting)。指定数字化图像时要求的颜色数量,例如“256”。
IPRD 产物(Product)。指定文件最初打算使用的标题的名称,例如“Encyclopedia of Pacific Northwest Geography.”。
ISBJ 主题(Subject)。描述文件的内容,例如“Aerial view of Seattle.”。
ISFT 软件(Software)。标识用于创建文件的软件包的名称,例如“Microsoft WaveEdit.”。
ISHP 清晰度(Sharpness)。标识生成文件所需的数字化转换器的清晰度变化(格式取决于所使用的硬件)。
ISRC 源(Source)。标识提供文件原始主题的人员或组织的名称;例如“Trey Research.”。
ISRF 原始形式(Source Form)。标识被数字化的材料的原始形式,例如“slide,”、“paper,”、“map,”等。这不一定与IMED相同。
ITCH 技术员(Technician)。标识将主题文件数字化的技术人员;例如“Smith, John.”。

2.4、movi List

  头信息(hdrl List)之后是一个“movi”列表,其中包含流中的实际数据,即视频帧音频样本。数据块可以直接驻留“movi”列表中,或者它们可能会被归类“rec”列表中。“rec”分组意味着应该一次性从磁盘读取分组的块,并且该块旨在用于从CD-ROM交错播放的文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
LIST movi
LIST rec
01wb
01wb
02wb
03wb
03wb
03wb
00dc
00dc
LIST rec
01wb
02wb
LIST rec
...
...
ix01
ix02
ix03
....
....

  将块分组为rec-Lists可防止在使用Microsoft AVI Splitter进行重放时过多的搜索,但不允许在某些独立的重放设备上进行播放。

  流的最大块大小应小于相应的dwSuggestedBufferSize值。否则,某些播放器,尤其是Microsoft AVI Splitter,可能会发生故障

  标识每个数据块的FourCC包含一个两位数字流编号,后面跟着的是一个用于定义块中信息的类型两个字符的编码

Two-Character Code Description
..db 未压缩视频帧数据块
..dc 压缩视频帧数据块
..wb 音频数据块
..tx 字幕数据块
ix.. 标准索引块
..pc 调色板更换数据块

  例如,如果Stream0包含音频,则该流的数据块将具有“00wb”形式的FourCC。如果Stream1包含视频,则该流的数据块将具有“01db”“01dc”形式的FourCC视频数据块还可以定义新的调色板条目,以便在AVI序列期间更新调色板。每个调色板更换数据块(“..pc”)都包含一个AVIPALCHANGE结构。如果流包含调色板更换数据块(“..pc”),请在该流的AVISTREAMHEADER结构的dwFlags成员中设置AVISF_VIDEO_PALCHANGES标志。文本流可以使用任意Two-Character Code

  AVIPALCHANGE结构体定义了AVI文件中的调色板更换的相关信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
typedef struct {
BYTE bFirstEntry;
BYTE bNumEntries;
WORD wFlags;
PALETTEENTRY peNew[];
} AVIPALCHANGE;

typedef struct tagPALETTEENTRY {
BYTE peRed;
BYTE peGreen;
BYTE peBlue;
BYTE peFlags;
} PALETTEENTRY;

typedef struct tagLOGPALETTE {
WORD palVersion;
WORD palNumEntries;
PALETTEENTRY palPalEntry[1];
} LOGPALETTE;
  • bFirstEntry: 指定要更改的第一个调色板条目的索引。
  • bNumEntries: 指定要更改的调色板条目数,或者指定零以更改所有256个调色板条目。
  • wFlags: 保留。
  • peNew: 指定大小为bNumEntriesPALETTEENTRY结构的数组。

  PALETTEENTRY结构指定逻辑调色板中条目的颜色用法。逻辑调色板由LOGPALETTE结构定义。

  • peRed: 调色板条目的红色强度值。
  • peGreen: 调色板条目的绿色强度值。
  • peBlue: 调色板条目的蓝色强度值。
  • peFlags: 指示如何使用调色板条目。

  peFlags可以设置为0以下值之一

Value Meaning
PC_EXPLICIT 说明逻辑调色板条目的低位字指定的是硬件调色板索引。该标志允许应用程序显示显示设备面板的内容。
PC_NOCOLLAPSE 说明将颜色放置在系统调色板中的未使用条目中,而不是与系统调色板中的现有颜色匹配的条目中。如果系统调色板中没有未使用的条目,则颜色将正常匹配。一旦此颜色出现在系统调色板中,其他逻辑调色板中的颜色就可以与此颜色匹配。
PC_RESERVED 说明将逻辑调色板条目用于调色板动画。该标志可防止其他窗口将颜色与调色板条目匹配,因为颜色经常变化。如果有未使用的系统调色板条目可用,则将颜色放置在该条目中。否则,该颜色不可用于动画。

  LOGPALETTE结构定义了一个逻辑调色板

  • palVersion: 系统的版本号
  • palNumEntries: 逻辑面板中条目的数量
  • palPalEntry: 指定一组PALETTEENTRY结构,这些结构定义逻辑调色板中每个条目的颜色用法

  调色板条目表中的颜色应按重要性顺序显示,因为逻辑调色板较前的条目最有可能放置在系统调色板中。

2.5、idx1 Chunk

2.5.1、AVI 1.0 index

  可选索引块(“idx1”)可以位于“movi”列表之后。索引包含数据块及其在文件中的位置列表。它由一个AVIOLDINDEX结构组成,该结构具有每个数据块的条目(包括“rec”块)。如果文件包含索引,请在AVIMAINHEADER结构的dwFlags成员中设置AVIF_HASINDEX标志。

  AVIOLDINDEX结构由初始RIFF块(Chunk结构体:fcc和cb成员)和“movi”列表中每个数据块的一个索引条目组成。AVIOLDINDEX结构体的定义如下:

1
2
3
4
5
6
7
8
9
10
11
typedef struct _avioldindex {
FOURCC fcc;
DWORD cb;
struct {
DWORD dwChunkId;
DWORD dwFlags;
DWORD dwOffset;
DWORD dwSize;
} _avioldindex_entry;
_avioldindex_entry aIndex[];
} AVIOLDINDEX;
  • fcc: 指定FourCC代码。必须为“idx1”
  • cb: 指定本结构体的大小,与Chunk结构体中的dwSize相同。不包括初始的8个字节(fcc和cb)。
  • aIndex: 包含下列成员的结构体的数组。
    • dwChunkId: 指定用于标识AVI文件中流的FourCCFourCC的格式必须为“xxyy”,其中xx流编号,而yy是两个字符的代码,用于标识流的内容。请看前面介绍“movi List”时的内容。
    • dwFlags: 请看下文。
    • dwOffset: 指定数据块在文件中的位置。该值应指定为距“movi”列表开头偏移量(以字节为单位);但是,在某些AVI文件中,它是距文件开头偏移量AVI文件解析器必须能够处理两个版本
    • dwSize: 指定数据块的大小,以字节为单位。

  dwFlags指定以下标志的0个多个按位组合:

Value Meaning
AVIIF_KEYFRAME 此条目所指的数据块是关键帧。
AVIIF_LIST 此条目所指的数据块是一个“rec”列表。不是一个Chunk。
AVIIF_FIRSTPART 此条目所指的数据块需要使用其后的帧;它不能单独存在。
AVIIF_LASTPART 此条目所指的数据块需要使用其之前的帧;它不能单独存在。
AVIIF_NO_TIME 此条目所指的数据块不影响流的计时。例如,应该为调色板更换数据块(“..pc”)设置这个标志。

  如果既未设置AVIIF_FIRSTPART也未设置AVIIF_LASTPART,则该块可以单独使用,换句话说,其相应的流至少有一个数据包。这对于将VBR音频流存储在AVI文件中非常重要。

  “idx1 Chunk”的标准形式示意图:

idx1 Chunk标准形式

2.5.2、AVI 2.0 index(Open-DML)

  AVI2.0索引可以显示为单个块(“idx1”)。或者,可以在“movi”块中插入索引段(“ix..”)。如果将索引段(“ix..”)放置在“movi”块中,则超级索引(“Super Index Chunk”或“indx Chunk”)包含索引段(“ix..”)的索引AVIMETAINDEX结构是索引段(“ix..”)超级索引(“indx”)的基础结构。

  AVIMETAINDEX结构体是AVI2.0索引的基本结构(“indx”格式)。AVIMETAINDEX结构体的定义如下(可参考“indx Chunk”节):

1
2
3
4
5
6
7
8
9
10
11
typedef struct _avimetaindex {
FOURCC fcc;
UINT cb;
WORD wLongsPerEntry;
BYTE bIndexSubType;
BYTE bIndexType;
DWORD nEntriesInUse;
DWORD dwChunkId;
DWORD dwReserved[3];
DWORD adwIndex[];
} AVIMETAINDEX;
  • fcc: FourCC代码。取值为“indx”“ix..”,其中“..”流编号
  • cb: 指示此结构体的大小,不包括初始的8个字节(fcc和cb)。
  • wLongsPerEntry: 每个索引项的大小,以4字节为单位。
  • bIndexSubType: 索引子类型。含义取决于bIndexType的值。
  • bIndexType: 请看下文。
  • nEntriesInUse: adwIndex数组中有效的条目数
  • dwChunkId: 标识被索引的对象的FourCC。如果索引的对象是一个,则该成员与AVIOLDINDEX结构的dwChunkId成员具有相同的含义
  • dwReserved: 该成员的含义取决于索引类型
  • adwIndex: 索引项的数组。该数据的格式取决于索引类型

  bIndexType可以具有以下值:

Value Meaning
AVI_INDEX_OF_INDEXES
0x00
每个索引条目都指向另一个索引。将AVIMETAINDEX结构视为AVISUPERINDEX结构。bIndexSubType的值必须为0。
AVI_INDEX_OF_CHUNKS
0x01
每个索引条目指向文件中的一个数据块。
1、如果bIndexSubType为0,将AVIMETAINDEX结构视为AVISTDINDEX结构。每个索引条目都是一个AVISTDINDEX_ENTRY结构。
2、如果bIndexSubType为AVI_INDEX_SUB_2FIELD,则该索引是一个域索引块(Field Index)。
DirectShow不支持域索引(Field Index)。
AVI_INDEX_IS_DATA
0x80
adwIndex数组包含一个数据表,而不是一个索引项列表。

2.6、JUNK Chunk

  根据需要插入“JUNK”块,可以在AVI文件中对齐数据。应用程序应忽略“JUNK”块的内容。

Reference

文章目录
  1. 1、AVI简介
    1. 1.1、AVI基本概念
    2. 1.2、AVI文件类型
    3. 1.3、基本数据结构
      1. 1.3.1、RIFF文件的基本数据结构
      2. 1.3.2、AVI文件的基本数据结构
  2. 2、AVI文件结构
    1. 2.1、AVI文件整体布局
    2. 2.2、hdrl List(Headerlist)
      1. 2.2.1、avih Chunk(AVI Header)
      2. 2.2.2、strl List(Stream Header List)
        1. 2.2.2.1、strh Chunk(Stream Header)
        2. 2.2.2.2、strf Chunk(Stream Format)
          1. 视频流(BITMAPINFO)
          2. 音频流(WAVEFORMATEX)
        3. 2.2.2.3、strd Chunk(Stream Header Data / Additional Header Data)
        4. 2.2.2.4、strn Chunk(Stream Name)
        5. 2.2.2.5、indx Chunk(Super Index Chunk)
    3. 2.3、INFO List
    4. 2.4、movi List
    5. 2.5、idx1 Chunk
      1. 2.5.1、AVI 1.0 index
      2. 2.5.2、AVI 2.0 index(Open-DML)
    6. 2.6、JUNK Chunk
  3. Reference