【编解码:AVI格式解析】

【编解码:AVI格式解析】

编解码:AVI格式解析

1 音视频及AVI知识2 最基本的数据单元3 AVI主要结构介绍4 AVI主要结构解析5 总结

1 音视频及AVI知识

一个完整的音视频文件格式有mp4、mov、flv、avi、rmvb、mkv、ts等,它们是封装数据的容器,包括音频、视频、字幕、基础元信息等,通过一些特定的编码算法,对各种信息进行编码压缩过后得到的。视频文件的封装格式并不影响视频的画质,影响视频画面质量的是视频的编码格式。

H264、HEVC、VP9、AV1等就是视频编码格式,MP3、AAC、AC-3等就是音频编码格式,SRT、SSA等就是字幕编码格式。

例如:将一个视频流以Xvid格式编码、一个音频流以MP3格式编码、一个字幕流以SRT格式进行编码,按AVI封装标准封装以后,就得到一个AVI视频文件。

AVI即Audio Video Interleaved,音视频交错格式,基于RIFF文件结构。多用于音视频捕捉、编辑、回放等应用程序中。通常情况下,一个AVI文件可以包含多个不同类型的媒体流(典型的情况下有一个音频流和一个视频流),不过含有单一音频流或单一视频流的AVI文件也是合法的。AVI可以算是Windows操作系统上最基本的、也是最常用的一种媒体文件格式。

RIFF即Resource Interchange File Format,资源交互文件格式 。是由Microsoft提出的一种多媒体文件存储方式,不同编码的视频、音频文件按照RIFF保存,当提取文件时,可以根据RIFF的规则解析文件。常见的RIFF文件有:WAV、AVI等。

2 最基本的数据单元

//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;

Chunks由三部分组成:4字节的数据流格式ID,4字节的数据大小,数据。 Lists由四部分组成:4字节LIST(LIST块中可以再包含一系列的子块),4字节数据加fourCC大小,4字节数据流格式ID,数据。

3 AVI主要结构介绍

一个AVI文件通常有如下几个子块组成:

ID为"AVI"的RIFF,文件头ID为"hdrl"的list,信息块,包含了音视频信息,描述媒体流信息ID为"info"的list,包含编码该AVI的程序信息ID为"junk"的chunk,无用的数据,用于字节对齐ID为"movi"的list,数据块,包含了交错排列的音视频数据ID为"idxl"的chunk,索引块,包含音视频排列的索引数据(可选块,不存在时seek会慢很多)

文件信息: 分析工具分别是MediaInfo以及MediaConch。

4 AVI主要结构解析

1.RIFF文件头 4个字节的"RIFF",4字节的RIFF文件大小(342872字节),4字节为RIFF文件类型"AVI"

2.hdrl列表 1)hdrl列表头 4字节的"LIST"描述信息,4字节list大小(8952字节),4字节list类型"hdrl"

2)avih块 用于描述主信息,该块可以用如下结构体表示

typedef struct

{

DWORD dwMicroSecPerFrame; //显示每帧所需的时间ns,定义avi的显示速率

DWORD dwMaxBytesPerSec; // 最大数据传输率

DWORD dwPaddingGranularity; //记录块的长度须为此值的倍数,通常是2048

DWORD dwFlags; // AVI文件的特殊属性,包含文件中的任何标志字。如:有无索引块,是否是interlaced,是否含版权信息等

DWORD dwTotalFrames; // 数据帧的总数

DWORD dwInitialFrames; // 在开始播放前需要的帧数

DWORD dwStreams; //文件中包含的数据流种类

DWORD dwSuggestedBufferSize;//建议使用的缓冲区的大小,通常为存储一帧图像以及同步声音所需要的数据之和,大于最大的CHUNK的大小

DWORD dwWidth; //图像宽,像素

DWORD dwHeight; //图像高,像素

DWORD dwReserved[4]; //保留值dwScale,dwRate,dwStart,dwLength

} MainAVIHeader;

3)strl list头部 一个strl list中至少包含一个strh块和一个strf块。文件中有多少个流,就对应有多少个strl list。 上图可知存在两个流,Stream info 0,Stream info 1。

4)strh块

// 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块

该块用于描述流的具体信息

视频流,fccType = “vids”

// 位图头

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;

音频流,fccType = “auds”

// 音频波形信息

typedef struct

{

WORD wFormatTag;

WORD nChannels; // 声道数

DWORD nSamplesPerSec; // 采样率

DWORD nAvgBytesPerSec; // 每秒的数据量

WORD nBlockAlign; // 数据块对齐标志

WORD wBitsPerSample; // 每次采样的数据量

WORD cbSize; // 大小

} WaveFormatEx;

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

3.info列表 该list用于描述编码该AVI文件的程序信息,包含一个isft块。

4.junk块 一些垃圾填充数据,用于内部数据的队齐(填充),直接跳过。

5.movi列表 存储音视频数据,音视频数据在其中以交错方式存放着,视频clip,n音频clip,视频clip,n音频clip…方便seek。 音视频数据子块的种类有:##db,##dc,##pc,##wb。 –##:数据所属的流的序号,视频是00dc或00db,音频是01wb。 –db:未压缩的视频帧 –dc:压缩的视频帧 –wb:音频数据 –pc:改用新的调色板

6.idx1块 该块是可选的,描述音视频数据的索引块信息,在AVIMainHeader的dwFlags中指出是否包含索引块。有了索引块可以方便文件快进,如果没有索引块,在对AVI进行快进时需要计算位置,会很耗时。索引块可用如下结构体表示:

// 索引节点信息

typedef struct

{

DWORD dwChunkId; // 本数据块的四字符码(00dc 01wb)

DWORD dwFlags; // 说明本数据块是不是关键帧、是不是‘rec ’列表等信息

DWORD dwOffset; // 本数据块在文件中的偏移量

DWORD dwSize; // 本数据块的大小

} AVIIndexEntry;

5 总结

可以编译FFmpeg源码,对AVI文件进行解码,在分离器Demuxer中进一步研究其格式,会有更清晰的认识。

RIFF ('AVI'

LIST('hdrl'

'avih'(主 AVI 信息头数据)

LIST('strl'

'strh' (流的头信息数据)

'strf' (流的格式信息数据)

['strd' (可选的额外的头信息数据)]

['strn' (可选的流的名字) ]

)

... // 其他流信息

)

LIST('movi'

{

// 媒体流数据

SubChunk | LIST ('rec'

SubChunk1

SubChunk2

...

}

)

['idx1' (可选的 AVI 索引块数据) ]

)

相关推荐

杰字的成语有哪些
365bet体育网站

杰字的成语有哪些

🕒 07-02 👀 8952
为什么要有堆栈
线上365bet

为什么要有堆栈

🕒 08-31 👀 120
未知暗殿打宝玄学老玩家总结的刷新时间规律
best365提现到账慢

未知暗殿打宝玄学老玩家总结的刷新时间规律

🕒 06-27 👀 4354