JCHub

  • Home
  • Category
    • A/V
    • WebRTC
    • Beauty of Programming
    • Linux
    • Windows
    • Moments of Life
    • Campus Life
  • Reference
    • API Reference
    • Utilities
    • AV Test
    • Doc
  • Message Board
  • About
JCHub
Code as My Sword, Lost in Obsession
  1. Main page
  2. A/V
  3. Main content

AVI文件详细解析

2016年2月23日 7294hotness 3likes 7comments

最近在做视频文件的解析,需要将视频文件中封装的视频与音频解析出来,然后用自己的解码器解码。这个过程专业点叫做叫做Demultiplex,视频播放器中负责这部分的叫做Demuxer。我们平时看到的各种格式视频,比如:avi,mp4,mkv等相当于一种容器,里面包含了音视频,字幕的信息以及数据,Demuxer的工作就是解析视频文件,取出里面的音视频或者字幕送到指定的解码器解码。

我刚开始接触的avi文件的解析。首先介绍下AVI文件。AVI英文全称为Audio Video Interleaved,即音视频交错格式,AVI基于RIFF文件结构。

一.基本数据单元

在AVI中有两种最基本的数据单元,一个是chunk,一个是list。这两种结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Chunks
typedef struct {
DWORD dwFourCC
DWORD dwSize      //data
BYTE data[dwSize] // contains headers or video/audio data
} CHUNK;
 
Lists
typedef struct {
DWORD dwList
DWORD dwSize        //dwFourcc + data
DWORD dwFourCC
BYTE data[dwSize-4] // contains Lists and Chunks
} LIST;

可知chunk由三部分组成:4字节的标记ID,4字节大小(指数据大小),以及数据。
list由四部分组成,4字节“list”,4字节大小(指后面两部分),4字节列表类型,数据。

二.AVI文件类型

1.AVI 1.0 最基本的格式,由于索引地址与大小用4字节表示,所以最大支持4G容量,而且与文件系统类型有关,如下:
--Video for Windows (AVI 1.0)
-FAT (FAT16): 4 GB (2 GB practical, safe)
-FAT32: 4 GB (2 GB practical, safe)
-NTFS: 4 GB (2 GB practical, safe)
为了安全一般限制为2G(参考链接1)
2.AVI 2.0(Open—DML) AVI的扩展格式,解决AVI 1.0大小限制(AVI2.0详细资料见参考链接2)

本文主要讨论AVI 1.0,AVI2.0解析后续再做研究。

三.AVI结构

一个AVI文件通常有如下几个子块组成:
1)ID为"hdrl"的list,包含了音视频信息,描述媒体流信息
2)ID为"info"的list,包含编码该AVI的程序信息
3)ID为"junk"的chunk,都是些无用的数据
4)ID为"movi"的list,包含了交错排列的音视频数据
5)ID为"idxl"的chunk,包含音视频排列的索引数据(可选块)

四.详细解析

1.RIFF文件头

用UltraEdit(或者其他文本编辑器)打开一个AVI文件(本文分析用到的avi文件下载地址)
avi解析
可以看到前4个字节为"RIFF",接着4字节RIFF文件大小(0x01811050即25235536字节,因为AVI文件以小端方式存储数据),再接着4字节为RIFF文件类型"avi"

2.hdrl列表

1)hdrl list头部
avi解析
可以看到接下来为hdrl list。首先是4字节的"list",然后4字节list大小,接着是4字节list类型"hdrl"。

2)avih块
avi解析
用于描述主信息头。
4字节的"avih"标识,4字节大小(0x38即56),接下来是56个字节数据。该块可以用如下结构体表示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// AVI主头部
typedef struct
{
    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;

3)strl list头部
avi解析
一个strl list中至少包含一个strh块和一个strf块。文件中有多少个流,就对应有多少个strl list。
上图可知依次为4字节"list",4字节的list大小,4字节"strl"标识。

4)strh块
avi解析
用于描述流的头信息。
4字节"strh",4字节"strh"块大小(0x38即56),后面是56字节大小数据。该块用如下结构体表示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// AVI流头部
typedef struct
{
    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;               // dwScale/dwRate,每秒采样率
    DWORD dwStart;              // 流的开始时间
    DWORD dwLength;             // 流的长度(单位与dwScale和dwRate的定义有关)
    DWORD dwSuggestedBufferSize;// 读取这个流数据建议使用的缓存大小
    DWORD dwQuality;            // 流数据的质量指标(0 ~ 10,000)
    DWORD dwSampleSize;         // Sample的大小
    RECT rcFrame;               // 指定这个流(视频流或文字流)在视频主窗口中的显示位置,视频主窗口由AVIMAINHEADER结构中的dwWidth和dwHeight决定
} AVIStreamHeader;

5)strf块
avi解析
该块用于描述流的具体信息。如果是视频流(vids,由strh块得知),用一个BitmapInfo结构体表示,如果是音频流(auds),用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
27
28
29
30
31
32
33
34
// 位图头
typedef struct
{
    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
{
    BitmapInfoHeader bmiHeader;   // 位图头
    RGBQUAD bmiColors[1];         // 调色板
} BitmapInfo;
 
// 音频波形信息
typedef struct
{
    WORD wFormatTag;
    WORD nChannels;               // 声道数
    DWORD nSamplesPerSec;         // 采样率
    DWORD nAvgBytesPerSec;        // 每秒的数据量
    WORD nBlockAlign;             // 数据块对齐标志
    WORD wBitsPerSample;          // 每次采样的数据量
    WORD cbSize;                  // 大小
} WaveFormatEx;

该块首先4字节"strf"标识,4字节大小0x28即40,接着的数据用一个40字节大小的BitmapInfo结构体表示。

6)strd块与strn块
strd:可选的额外的头信息数据
strn:可选的流的名字
这两个块是可选的,本AVI文件不包含,故不分析。

7)strl list
avi解析
由于该AVI文件有两个流,所以有两个strl list。该strl list用于描述音频流信息。具体分析同上。

3.info list

avi 解析
该list用于描述编码该AVI文件的程序信息,包含一个isft块。

4.junk块

avi解析
该块都是一些垃圾填充数据,用于内部数据的队齐(填充),直接跳过。

5.movi list

avi解析
该list存储音视频数据块,音视频数据块在该list中交错方式存放着。
movi lst中音视频数据子块的种类有:##db,##dc,##pc,##wb。
--##表示数据所属的流的序号(由于第一个流是视频(第一个hdrl list描述视频),故音频用01wb表示,视频用00dc或00db)
--db:未压缩的视频帧
--dc:压缩的视频帧
--wb:音频数据
--pc:改用新的调色板

6.idx1块

avi解析
该块是可选的,描述音视频数据的索引块信息。索引块可用如下结构体表示:

1
2
3
4
5
6
7
8
// 索引节点信息
typedef struct
{
    DWORD dwChunkId;   // 本数据块的四字符码(00dc 01wb)
    DWORD dwFlags;     // 说明本数据块是不是关键帧、是不是‘rec ’列表等信息
    DWORD dwOffset;    // 本数据块在文件中的偏移量
    DWORD dwSize;      // 本数据块的大小
} AVIIndexEntry;

在AVIMainHeader的dwFlags中指出是否包含索引块。有了索引块可以方便文件快进,如果没有索引块,在对AVI进行快进时需要计算位置,会很耗时。

五.程序编写

通过如上分析对AVI结构有了清楚了解。在这基础上自己写了个AVI解析程序,可以解析AVI1.0格式文件,同时生成对应的视频与音频文件。
我用ffmpeg自带的ffplay测试解析生成的h264视频文件,可以正常播放。
avi解析

参考链接
1)http://www.myvideoproblems.com/Tutorials/dv-aviFiles.htm
2)odmlff2.pdf:https://pan.baidu.com/s/1CXiargLfspQwaWoRYjqHqw 提取码: haj8

This article is licensed with Creative Commons Attribution-NonCommercial-No Derivatives 4.0 International License
Tag: 音视频
Last updated:2020年8月22日

Jeff

管理员——代码为剑,如痴如醉

Tip the author Like
< Last article
Next article >

Comments

  • 陈群

    楼主。。您好。。最近在分析AVI文件格式。。有文中提到的AVI2.0相关的文档参考下嘛??请给我一份。。谢谢了。。

    2016年9月9日
    Reply
    • Jianchihu

      @陈群 这是官方文档OpenDML AVI File Format Extensions:http://jchblog.u.qiniudn.com/doc/odmlff2.pdf 你可以参考下

      2016年9月10日
      Reply
      • 陈群

        @Jianchihu 恩恩。。好的谢谢楼主。。

        2016年9月14日
        Reply
  • 樊聪

    楼主你好,请问能否发一份你的AVI解析程序我啊?我这边想参考一下,麻烦了,谢谢!

    2018年1月8日
    Reply
    • Jianchihu

      @樊聪 这个给不了,公司写的代码。你可以参考ffmepg或vlc源码。

      2018年1月17日
      Reply
  • 没有昵称

    博主你好,最近在研究avi格式,看了你的文章很受启发。
    但是发现文章中有几处错误。
    1.首先是第一幅avi结构的那个图,信息块中,那个avih和下面的LIST,应该是并列关系,而不是包含。因为chunk不可能再包含LIST
    2.还是那幅图,数据块中的LIST,标识应该是“movi”,而不是图中的“move”
    3.在“四.详细解析”的“6)strd块与strh块”,目测应该是 strn,而不是strh,应该是笔误。

    2020年8月22日
    Reply
    • Jeff

      @没有昵称 感谢指正,那张图是网上盗的图,为了不误导人家,我还是删了吧。

      2020年8月22日
      Reply
  • razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
    Cancel

    This site uses Akismet to reduce spam. Learn how your comment data is processed.

    文章目录
    • 一.基本数据单元
    • 二.AVI文件类型
    • 三.AVI结构
    • 四.详细解析
      • 1.RIFF文件头
      • 2.hdrl列表
      • 3.info list
      • 4.junk块
      • 5.movi list
      • 6.idx1块
    • 五.程序编写
    Related Posts
    • 告别CapCut收费!开源视频剪辑工具OpenCut 来了
    • 音视频开发入门:视频基础
    • 大话WebRTC
    • WebRTC音视频传输基础:NAT穿透
    • Intel平台硬件加速视频编解码开发
    Categories

    COPYRIGHT © 2026 jianchihu.net. ALL RIGHTS RESERVED.

    Theme Kratos Made By Seaton Jiang