AVI 格式分析 笔记

3 阅读8分钟

AVI(Audio Video Interleaved)是微软于1992年推出的多媒体容器格式,是Windows平台最经典的音视频封装格式之一。其名称“交错”直指核心设计思想:将音频数据与视频数据交替存储,使得播放器在读取时能够连续、低延迟地回放。下面从格式结构、数据组织、局限性与扩展、工程实践等方面详细分析。


1. 文件结构基础:RIFF 与 AVI

AVI 基于 RIFF(Resource Interchange File Format) 体系,这是微软为多媒体数据定义的一种通用容器规范。RIFF 文件由若干 块(Chunk) 组成,每个块包含:

  • 块标识(4字节 ASCII)
  • 块大小(4字节,小端序)
  • 块数据(长度由块大小指定)

AVI 文件整体是一个 RIFF 块,其类型标识为 'AVI '(注意空格),结构如下:

RIFF ('AVI '
      hdrl LIST ...
      movi LIST ...
      idx1      (可选)
)

即:

  • 一个 RIFF 头部,类型为 AVI
  • 包含三个主要子块:hdrl 列表、movi 列表、可选的 idx1

2. 主要块详解

2.1 hdrl 列表(Header List)

hdrl 是存放所有元数据的列表,其子块包括:

2.1.1 avih —— AVI 主头部

一个固定大小的结构体(56字节),定义文件全局属性:

字段类型说明
dwMicroSecPerFrameDWORD每帧的微秒数,决定了视频帧率
dwMaxBytesPerSecDWORD最大数据传输率(字节/秒)
dwPaddingGranularityDWORD填充粒度(通常为0)
dwFlagsDWORD标志位(如是否包含索引、是否交错等)
dwTotalFramesDWORD视频总帧数
dwInitialFramesDWORD初始帧数(用于音视频同步,通常为0)
dwStreamsDWORD文件中的流数量(至少1个视频流)
dwSuggestedBufferSizeDWORD建议的解码缓冲区大小
dwWidth / dwHeightDWORD视频宽高(像素)
dwReservedDWORD[4]保留字段

2.1.2 strl 列表(Stream List)

每个媒体流对应一个 strl 列表,包含流的头部、格式、名称等子块。

  • strh(Stream Header):定义流类型(视频 vids、音频 auds、文本等)、处理方式、缓冲区大小、帧率(对于视频)等。关键字段:

    • fccType:流类型(如 vidsauds
    • fccHandler:编解码器四字符码(如 'DIB ''H264''XVID'
    • dwScale / dwRate:定义时间刻度(如视频为 dwRate/dwScale = 帧率
    • dwStart / dwLength:起始帧和总帧数(对于音频为样本数)
  • strf(Stream Format):流格式结构,直接存放编解码器所需的数据结构:

    • 对于视频流:通常是 BITMAPINFOHEADER(包含宽、高、位深度、压缩类型等)
    • 对于音频流:通常是 WAVEFORMATEX(包含采样率、声道数、比特率等)
  • strn(可选):流的名称

2.1.3 其他可选子块

  • odml:用于 OpenDML 扩展,支持大于4GB的文件(见后文)。
  • vprp:视频属性(如逐行/隔行)。

2.2 movi 列表(Movie Data)

movi 列表存放所有实际的音视频数据。其内部由一系列 数据块(data chunk) 组成,每个数据块具有如下格式:

字段大小说明
块标识4字节00dc(视频帧)、00wb(音频帧)
块大小4字节数据长度(不含块标识和大小字段)
数据可变编码后的帧数据(如 H.264 NAL 单元、PCM 数据)

块标识规则

  • 前两个字符表示流索引(00 表示第一个流,01 表示第二个,依此类推)
  • 后两个字符表示数据类型:
    • dc:视频压缩数据(compressed video)
    • db:视频未压缩数据(uncompressed video)
    • wb:音频压缩/未压缩数据
    • pc:调色板数据(palette change)

交错存储:AVI 的核心特性。在 movi 中,音频和视频数据块按照时间顺序交替放置,例如:

00dc (视频帧1)
00wb (音频数据块对应视频帧1)
00dc (视频帧2)
00wb (音频数据块对应视频帧2)
...

这种交错使得播放器在读取时,无需大量缓冲即可实现音视频同步,也适合 CD-ROM 等顺序读取设备。

2.3 idx1 块(Index)

idx1 是可选的索引块,位于文件末尾(或 movi 之后),为每个数据块记录其在文件中的位置、大小和类型,用于快速随机访问。索引条目结构:

字段类型说明
ckidDWORD数据块的标识(如 00dc
dwFlagsDWORD标志位(指示该块是否为关键帧)
dwChunkOffsetDWORD数据块相对于文件起始的偏移
dwChunkLengthDWORD数据块的大小

如果 AVI 文件没有索引,播放器只能顺序播放,无法快进快退。


3. 数据组织与播放流程

一个典型的 AVI 文件播放流程如下:

  1. 解析 hdrl 列表,获取流数量、编解码器信息、全局参数。
  2. 初始化解码器(使用 strf 中的格式结构)。
  3. 定位到 movi 列表,开始顺序读取数据块:
    • 根据块标识判断流类型,将数据送入对应解码器。
    • 解码后的帧按时间戳(根据 dwScale/dwRate 计算)送显/播放。
  4. 如果存在 idx1,支持跳转到任意帧(通过索引查找该帧的数据块位置)。
  5. 播放结束。

由于 AVI 没有显式的 PTS/DTS 字段(只有帧序号),且缺乏对 B 帧的明确支持,因此早期编码器通常避免使用 B 帧,或者通过特殊约定来处理。


4. 局限性及 OpenDML 扩展

4.1 标准 AVI 的局限

  • 文件大小限制:由于使用 32 位块大小字段,单个 RIFF 块最大为 4GB(实际可用约 2GB 左右),无法存储大型视频。
  • 时间戳不精确:仅依靠帧序号和帧率计算时间,无法精确表示可变帧率或复杂的 DTS/PTS 关系。
  • B 帧支持差:缺少显式的解码/显示时间戳,导致 B 帧处理困难(需依赖解码器约定)。
  • 不支持流媒体:头部必须在文件开头,且需要完整索引才能随机访问,不适合流式传输。
  • 编解码器配置受限strf 只能容纳有限的格式结构,对于现代编解码器(如 H.265)需要额外扩展。

4.2 OpenDML(AVI 2.0)

为了解决大文件问题,微软联合 IBM 于 1996 年推出 OpenDML 扩展(即 AVI 2.0)。主要改进:

  • 引入 dmlh 块(位于 hdrl 中),提供 64 位索引支持。
  • 允许使用多个 movi 块,或使用 ixxx 索引块代替 idx1,使文件可以突破 4GB 限制。
  • 增强时间戳和 B 帧支持(但仍不如 MP4 完善)。

目前大多数现代 AVI 文件(尤其是超过 2GB 的)实际都是 OpenDML AVI。


5. 与 MP4、ASF 的对比

特性AVIMP4ASF
设计初衷本地播放(尤其是 Windows 平台)通用存储与流媒体流媒体传输
文件结构RIFF 块 + movi 数据列表ISO BMFF(盒子嵌套)对象(GUID)
交错方式数据块按时间顺序交错样本按时间顺序存放,索引表单独固定大小数据包,可交错
索引idx1 或 OpenDML 索引stbl 系列表简单索引对象
时间戳支持基于帧序号,无独立 DTS/PTS精确 DTS/PTS数据包内嵌时间戳
B 帧支持弱(依赖解码器约定)完整支持完整支持
文件大小限制标准 AVI <4GB,OpenDML 无限制无限制无限制
流媒体友好差(需完整索引)一般(需 moov 前置)优秀
编解码器支持通过 strf 扩展(有限)通过 avcChvcC 等盒子通过流属性对象
现代应用老旧设备、数字摄像机、游戏录屏通用 Web/移动端传统 Windows 生态

6. 工程实践

6.1 FFmpeg 中的 AVI 支持

FFmpeg 通过 libavformat/avidec.clibavformat/avienc.c 实现 AVI 的读写。

常用命令:

# 封装为 AVI
ffmpeg -i input.mp4 -c copy output.avi

# 生成带索引的 AVI(默认)
ffmpeg -i input.mp4 -c copy -write_idx 1 output.avi

# 强制使用 OpenDML(支持大文件)
ffmpeg -i input.mkv -c copy -f avi -openglobal 1 output.avi

6.2 生成兼容性最好的 AVI

为了让 AVI 在老旧播放器上兼容,通常建议:

  • 使用简单视频编解码器(如 MJPEG、DivX、Xvid)
  • 音频使用 PCM 或 MP3
  • 避免 B 帧(使用 -bf 0
  • 使用 -packetsize 控制数据块大小

6.3 工具与库

  • Avilib:一个轻量级 C 库,专门用于读写 AVI 文件,常被嵌入到游戏或嵌入式设备中。
  • VirtualDub:经典的 AVI 处理工具,支持滤镜、重编码、索引修复等。
  • Windows 原生 API:如 AVIFile 系列函数(avifile.dll),用于创建和读取 AVI。

6.4 现代应用场景

尽管 AVI 在 Web 和移动端已基本被 MP4 取代,但在以下场景仍有应用:

  • 数字摄像机/采集卡:许多设备仍输出 AVI 格式(尤其是未压缩 AVI)
  • 游戏录屏:一些游戏录制软件默认使用 AVI(如 Fraps)
  • 教学视频/光盘:部分老旧教学光盘使用 AVI 格式
  • 简单嵌入式系统:资源受限的设备使用 avilib 等轻量库处理 AVI

7. 总结

AVI 作为多媒体容器格式的先行者,其“音频视频交错”的设计思想深刻影响了后续容器(如 MP4、MKV)。尽管在现代互联网流媒体环境中已不再主流,但它结构简单、实现容易,在特定领域(如嵌入式、遗留系统)仍具生命力。理解 AVI 的结构,有助于掌握 RIFF 体系、数据交错原理以及早期多媒体开发的技术脉络。

对于今天的音视频工程师,当需要处理老旧 AVI 文件或为嵌入式设备设计封装格式时,AVI 依然是一个值得熟练掌握的格式。