ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【编解码:AVI格式解析】

2021-11-27 17:00:36  阅读:319  来源: 互联网

标签:编解码 字节 音视频 AVI 格式 DWORD 解析 数据


编解码:AVI格式解析

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。
媒体信息
结构信息
avi结构

4 AVI主要结构解析

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

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

2)avih块
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
一个strl list中至少包含一个strh块和一个strf块。文件中有多少个流,就对应有多少个strl list。
上图可知存在两个流,Stream info 0,Stream info 1。

4)strh块
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”
    strf
// 位图头
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”
    strf1
// 音频波形信息
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列表
info
该list用于描述编码该AVI文件的程序信息,包含一个isft块。

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

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

6.idx1块
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 索引块数据) ]
)

标签:编解码,字节,音视频,AVI,格式,DWORD,解析,数据
来源: https://blog.csdn.net/weixin_47852035/article/details/121577751

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有