-> 概述

日常生活中,看到的视频文件的后缀名如 .mp4、.avi、.rmvb 都是属于视频文件的封装格式。所谓封装格式,就是以怎样的方式将视频轨、音频轨、字幕轨等信息组合在一起。说得通俗点,视频轨相当于饭,而音频轨相当于菜,封装格式就是一个碗或者一个锅,是用来盛放饭菜的容器。

视频文件的封装格式并不影响视频的画质,影响视频画面质量的是视频的编码格式。

下面介绍常见的视频封装格式 -AVI。

1 AVI

容器 AVI(Audio Video Interleaved)即音视频交错格式是一门成熟的老技术,尽管国际学术界公认 AVI 已经属于被淘汰的技术,但是简单易懂的开发 API,还在被广泛使用。

AVI 符合 RIFF(Resource Interchange File Format)文件规范,使用四字符码 FOURCC(four-character code)来表征数据类型。AVI 的文件结构分为头部、主体和索引三部分。 主体中图像数据和声音数据是交互存放的,从尾部的索引可以索引跳到自己想放的位置。

AVI 本身只是提供了这么一个框架,内部的图像数据和声音数据格式可以是任意的编码形式。因为索引放在了文件尾部,所以在播网络流媒体时已属力不从心。一个很简单的例子,从网络上下载 AVI 文件,如果没有下载完成,是很难正常播放出来。

1.1 基本数据单元

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

Chunks
typedef struct {DWORD dwFourCCDWORD dwSize      //dataBYTE data[dwSize] // contains headers or video/audio data
} CHUNK;Lists
typedef struct {DWORD dwListDWORD dwSize        //dwFourcc + dataDWORD dwFourCCBYTE data[dwSize-4] // contains Lists and Chunks
} LIST;

如上可知,Chunks 数据块由一个四字符码、4 字节 data size(指下面的数据大小)以及数据组成

List 由四部分组成,四个字节四字符码(“list”)、4 字节数据大小(指后面列的两部分数据大小)、四字节 list 类型以及数据组成,与 Chunk 数据块不同的是,List 数据内容可以包含字块(Chunk 或 List)。

1.2 AVI 文件结构

AVI 文件采用 RIFF 文件结构方式,使用四字符码 FOURCC(four-character code)来表征数据类型,比如 ‘RIFF’、‘AVI’、‘LIST’ 等,通常我们称四字符码为数据块 ID。因此首先我们需要了解一个标准 RIFF 文件结构。

  1. RIFF 文件的基本单元叫做数据块(Chunk),如上面基本数据单元的介绍,由数据块四字符码(数据块 ID) + 数据长度 + 数据组成。
  2. 整个 RIFF 文件可以看成一个数据块,其数据块 ID 为 “RIFF”,称为 RIFF 块。一个 RIFF 文件中只允许存在一个 RIFF 块。
  3. RIFF 块中包含一系列其他子块,其中 ID 为 “LIST” 称为 LIST 块,LIST 块中可以再包含一系列其他子块,但除了 LIST 块外的其他所有的子块都不能再包含子块。

有了 RIFF 文件结构的了解,下面这张 AVI 文件结构图就比较好理解了。需要说明的是,一个 AVI 通常都包含以下几个字块:

  • ID 为 “hdrl” 的 list 块,包含了音视频信息,描述媒体流信息
  • ID 为 “info” 的 list 块,包含编码该 AVI 的程序信息
  • ID 为 “junk” 的 chunk 数据块,无用数据,用于填充
  • ID 为 “movi” 的 list 块,包含了交错排列的音视频数据
  • ID为 “idxl” 的 chunk 块,包含音视频排列的索引数据(可选块)

图:AVI 文件结构

1.3 AVI 结构详解

AVI 文件直接用文本编辑如(UltraEdit)打开分析其结构即可,下面以一个 AVI 文件为例,逐字节往下分析。

★ 1. RIFF 文件头

用 UltraEdit 打开一个 AVI 文件

可以看到前四个字节为 “RIFF”,在接着四个字节为 RIFF 文件大小(0x01526E34 即 22176380 字节),22176380 字节只包含 "AVI " RIFF 文件类型四字符码及 RIFF 块数据长度,因此 22176380 + 8 是整个 RIFF 文件的大小。再接着 4 字节为 RIFF 文件类型 "avi "。

★★ 2. hdrl list

1)hdrl list 头部

AVI 文件中必需的第一个 list 就是 hdrl list,用于描述 AVI 文件中各个流的格式信息(AVI 文件中的每一路媒体数据都称为一个流)。hdrl list 中嵌套了一系列块和子列表,首先是一个 “avih” 块,用于记录 AVI 文件的全局信息,比如流的数量、视频图像的宽和高等。

可以看到首先是 4 字节的 “list”,然后是 4 字节的 list size,接着是 4 字节 list 类型 “hdrl”,接着是 list 数据内容。

2)avih 块

avih 即 avi_header,该数据块是主信息头,这意外着该 header 数据块之后就是文件多媒体流信息。

4 字节的 “avih” 标识码,4 字节大小(0x38 即 56),接下来是 56 个字节数据。该块可以用如下结构体表示:

typedef struct {FourCC fcc;                  // "avih" 特征码DWORD 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 头部

一个 strl list 中至少包含一个 strh 块和一个 strf 块。文件中有多少个流,就对应有多少个 strl list。

上图可知,依次为 4 字节 “list”,4 字节数据大小,4 字节 “strl” 四字符码标识符。

4)strh 块

用于描述流的头信息

4 字节 “strh”,4 字节 “strh” 块大小(0x38 即 56),后面是 56 字节大小数据。该块用如下结构体表示,由上面 strh 块可知,该 AVI 第一个流是视频流(vids)。

// AVI流头部
typedef struct
{FourCC fcc;                 // "strh"DWORD 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;               // 指定这个流(视频流或文字流)在视频主窗口中的显示位置
} AVIStreamHeader;

5)strf 块

该块用于描述流的具体信息。如果是视频流(vids,由 strh 块得知),用一个 BitmapInfo 结构体表示,如果是音频流(auds),用 WaveFormatEx 结构体表示。

// 位图头
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 块与strh 块

  • strd:保存编解码器需要的一些配置信息
  • strn:保存流的名字

这两个块是可选的,一个 strl list 可以不包含,不加分析。

★★ 3. info list

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

★★ 4. movi list

movi list 用于保存真正的媒体流数据,音视频数据块在该 list 中交错方式存放着。

当 AVI 文件中包含有多个流时,数据块与数据块之间如何来区别呢?

同样的,这些数据块使用了一个四字符码来表征它的类型,这个四字符码由 2 个字节的类型码和 2 个字节的流编号组成。

可用类型码有:

  1. db:未压缩的视频帧
  2. dc:压缩的视频帧
  3. wb:音频数据
  4. pc:改用新的调色板

比如第一个流(Stream 0)是音频,则表征音频数据块的四字符码为 “00wb” ,第二个流(Stream 1)是视频,则表征视频数据块的四字符码为 “01db” 或 “01dc”。

★★ 5. idx1 块

最后,紧跟在 hdrl list 和 movi list 之后的,就是 AVI 文件的索引块(可选),这个索引块为 AVI 文件中每一个媒体数据块进行索引,并且记录它们在文件中的偏移(可能相对于 movi list,也可能相对于 AVI 文件开头)。索引块使用一个四字符码 “idx1” 来表征,索引信息使用一个数据结构来 AVIOLDINDEX 定义。

typedef struct _avioldindex {FOURCC  fcc;         // "idx1"DWORD   cb;          // 数据大小struct _avioldindex_entry {DWORD   dwChunkId; // 数据块 idDWORD   dwFlags;DWORD   dwOffset; // 数据块偏移DWORD   dwSize;   // 数据块大小} aIndex[];
} AVIOLDINDEX;

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

3. 总结

RIFF ('AVI'LIST('hdrl''avih'(主 AVI 信息头数据)LIST('strl''strh' (流的头信息数据)'strf' (流的格式信息数据)['strd' (可选的额外的头信息数据)]['strn' (可选的流的名字) ])... // 其他流信息)LIST('movi'{ // 媒体流数据SubChunk | LIST ('rec'SubChunk1SubChunk2...})['idx1' (可选的 AVI 索引块数据) ]
)

常见视频封装格式(1) — AVI相关推荐

  1. 在直播软件开发过程中,常用的几种视频封装格式

    1.AVI格式 AVI(Audio Video Interleaved).此格式的中文译名为音频视频交错格式,这种视频格式的优点是图像质量好,无损AVI可以保存alpha通道.缺点也不少,体积过于庞大 ...

  2. AVI音视频封装格式学习(三)——AVI 数据结构解析

    这里介绍AVI会使用到的数据结构,为了避免翻译引入歧义,决定该部分还是使用英文原文,如后续有时间再进行翻译. AVIMAINHEADER structure The AVIMAINHEADER str ...

  3. AVI音视频封装格式学习(四)——linux系统C语言AVI格式音视频封装应用

    拖了很久的AVI音视频封装实例,花了一天时间终于调完了,兼容性不是太好,但作为参考学习使用应该没有问题.RIFF和AVI以及WAV格式,可以参考前面的一些文章.这里详细介绍将一个H264视频流和一个2 ...

  4. AVI音视频封装格式学习(五)——h265与PCM合成AVI文件

    不知道是处于版权收费问题还是什么原因,H265现在也并没有非常广泛的被普及.将h265数据合成AVI的资料现在在网上也基本上没有.使用格式化工厂工具将h265数据封装成AVI格式,发现它在封装的时候其 ...

  5. AVI音视频封装格式学习(二)——AVI RIFF文件参考

    AVI RIFF文件参考 AVI RIFF File Reference 微软AVI文件格式是与捕获,编辑和播放音视频流的应用程序一起使用的RIFF文件规范.通常,AVI文件包含多个不同类型的数据流. ...

  6. 走进音视频的世界——视频封装格式

    音视频的时长怎么获取,音视频的封面怎么获取,音视频的格式怎么获取呢?这些信息都以特定格式存储在文件开头或者结尾,称为多媒体信息或者多媒体元数据.通用的封装格式由:文件标识头+多媒体信息+音视频(字幕) ...

  7. FFmpeg之视频封装格式、流媒体协议、视频编解码协议和传输流格式、时间戳和时间基、视频像素数据

    通用视频分析工具:Mediainfo.Elecard StreamEye(视频编码分析工具); 视频封装格式: ********************MP4****************** MP ...

  8. 音视频封装格式、编码格式

    音视频封装格式.编码格式 概述 常见的AVI.RMVB.MKV.ASF.WMV.MP4.3GP.FLV等文件其实只能算是一种封装标准. 一个完整的视频文件是由音频和视频2部分组成的.H264.Xvid ...

  9. OpenCV视频篇——视频文件格式--视频封装格式--视频编码格式区分

    目录 一.前言 二.视频文件格式(文件格式) 三.视频封装格式(视频格式) 1.AVI 2.QuickTime 3.高级流格式文件 4.RealVideo 5.NAVI 6.DivX 7.MPEG 四 ...

  10. 详解视频封装格式之MP4

    在我之前的一篇文章(什么是视频封装格式和编码格式)中有整理了一下常见的视频封装格式.在上一篇文章(详解视频封装格式之FLV)中重点剖析了FLV格式.在这篇文章中,我们重点剖析一下MP4这种视频封装格式 ...

最新文章

  1. 深蓝学院第三章:基于卷积神经网络(CNN)的手写数字识别实践
  2. 二分类神经网络的特征光谱---1-2至1-9
  3. 转移的目的地址在指令中的jmp指令 转移地址在寄存器中的jmp指令
  4. rsync的基本操作
  5. yum清缓存_linux yum清除var目录下缓存的方法
  6. 构建一个ASP.NET Wiki来解释TDD
  7. 重磅!李航《统计学习方法》最新资源,笔记、Python 代码一应俱全!
  8. open cv python_Open CV非常牛逼!众所周知!今天就来见识一下它究竟有多牛逼!
  9. 不加群提取群成员_QQ群排名优化技术教程
  10. python贴吧顶贴_Python实现百度贴吧自动顶贴机
  11. 中發白——企业软件公司的战略大三元
  12. 5G NR 随机接入 总结
  13. 交互式电子白板与计算机通过什么链接,交互式电子白板的作用详细介绍
  14. 电压源 电流源 置零时的作用
  15. ubuntu系统损坏修复_修复损坏的ubuntu gui
  16. No tests found for given includes: [xxx.xxx.testList](filter.includeTestsMatching)
  17. 图像mnf正变换_PCA和MNF变换
  18. 计算机毕业设计php+vue基于微信小程序的房屋租赁小程序
  19. 物理隔离与数据交换-网闸的设计原理
  20. 三星 android 调试模式设置,三星盖世4 usb调试怎么打开?安卓4.2怎样打开USB调试...

热门文章

  1. [经典力学]牛顿自然哲学的数学原理论文解读
  2. matlab怎么训练神经网络,matlab神经网络训练方法
  3. [附源码]java毕业设计户籍管理系统
  4. Google--PageRank(网页级别)技术解密[转]
  5. 一款比PowerDesigner好用的uml建模工具chiner
  6. linux+ipv6免流量下载,Ubuntu 12.04 校园网下使用IPv6源 免流量更新
  7. MATLAB(四) 图像处理--对象分析与属性
  8. 微型计算机系统的层次关系图,1.2 计算机系统层次结构
  9. 概率论与随机过程难题整理复习
  10. 欧姆龙HOSTLINK协议,上位机软件欧姆龙HOSTLINK协议,适合欧姆龙全系列PLC