多媒体文件格式之FLV

1. 概述

FLV(Flash Video) 是 Adobe 公司设计开发的一种流媒体格式,其封装格式的文件后缀通常为 ".flv"。总体上看,FLV 包括文件头(File Header)和文件体(File Body)两部分,其中文件体由一系列的 Tag 组成。一个 FLV 文件,每种类型的 Tag 都属于一个流,也就是一个 FLV 文件最多只有一个音频流,一个视频流,不存在多个独立的音频流/视频流在一个文件中的情况。

注:FLV 文件格式用大端字节序。

FLV 整体文件格式图

image
注:Header 下面的 4 个字节是 PreviousTagSize 0,因为前面的 Header 不是一个 Tag,所以值为 0。

2. FLV Header

header 部分记录了 flv 的类型、版本等信息,占 9bytes。具体格式如下:

文件类型      3bytes    一般为 "FLV" (0x46, 0x4c, 0x66)
-------------------------------------------------------------------------------------------
版本          1byte     一般为 0x01
-------------------------------------------------------------------------------------------
流信息        1byte     前5位和第7位保留,为0。第6位和第8位分别表示是否存在音频 Tag 和视频 Tag
-------------------------------------------------------------------------------------------
header大小    4bytes    整个header的长度,一般为 9;大于 9 表示下面还有扩展信息
-------------------------------------------------------------------------------------------

3. FLV Body

body 部分由一个个 Tag 组成,每个 Tag 的下面有一个 4bytes 的空间,用来记录这个 Tag 的大小,这个后置是用于逆向读取处理。

3.1 Tag

每个 Tag 也是由两部分组成:Tag Header 和 Tag Data。Tag Header 里存放的是当前 Tag 的类型、数据区(Tag Data)的大小等信息,具体格式如下:

Field               type                    Comment
-------------------------------------------------------------------------------------------
                                8: audio
Tag类型             UI8         9: video
                                18: script data——这里是一些描述信息。
                                all others: reserved其他所有值未使用。
-------------------------------------------------------------------------------------------
数据大小            UI24        数据区的大小,不包括Tag Header。Tag Header总大小是11个字节。
-------------------------------------------------------------------------------------------
时戳                UI24        当前帧时戳,单位是毫秒。相对于FLV文件的第一个Tag时戳。
                                第一个tag的时戳总是0。注:不是时戳增量,rtmp中是时戳增量。
-------------------------------------------------------------------------------------------
时戳扩展字段        UI8         如果时戳大于0xFFFFFF,将会使用这个字节。这个字节是时戳的高8位,
                                上面的三个字节是低24位。
-------------------------------------------------------------------------------------------
流ID                U24         总是 0
-------------------------------------------------------------------------------------------
数据区              UI8[n]  

数据区根据 Tag 类型的不同可以分为:Audio Tag,Video Tag,Script Tag。

4. Script Data

该类型 Tag 又通常被称为 Metadata Tag,会放一些关于 FLV 视频和音频的元数据信息如:duration、width、height 等。通常该类型 Tag 会跟在 File Header 后面作为第一个 Tag 出现,而且只有一个。结构如下图所示:
image

  • 第一个 AMF 包:
    • 第 1 个字节表示 AMF 包类型,一般总是 0x02,表示 string;
    • 第 2~3 字节为 UI16 类型值,标识字符串的长度,一般总是 0x000A("onMetadata" 的长度);
    • 后面的字节为具体的字符串,一般总为 "onMetadata" (6F,6E,4D,65,74,61,44,61,74,61)。
  • 第二个 AMF 包:
    • 第 1 个字节表示 AMF 包类型,一般总是 0x08,表示 ECMA array 类型;
    • 第 2~5 个字节为 UI32 类型值,表示数组元素的个数;
    • 后面即为每个数组元素的封装,数据元素为元素名称和值组成对。常见的数组元素如下所示。
      • duration:时长
      • width:视频宽度
      • height:视频高度
      • videodatarate:视频码率
      • framerate:视频帧率
      • videocodecid:视频编码方式
      • audiosamplerate:音频采样率
      • audiosamplesize:音频采样精度
      • stereo:是否为立体声
      • audiocodecid:音频编码方式
      • fileSize:文件大小

如下图,为通过 obs 推送 FLV 文件到 RTMP 服务器上抓到的 FLV Script Tag 数据:

5. Audio Data

音频 Tag 的数据区开始的第 1 个字节包含了音频数据参数信息,从第 2 个字节开始为音频流数据。结构如下图所示:
image

  • 音频格式(4bits):
    • 0 = Linear PCM, platform endian
    • 1 = ADPCM
    • 2 = MP3
    • 3 = Linear PCM, little endian
    • 4 = Nellymoser 16-kHz mono
    • 5 = Nellymoser 8-kHz mono
    • 6 = Nellymoser
    • 7 = G.711 A-law logarithmic PCM
    • 8 = G.711 mu-law logarithmic PCM
    • 9 = reserved
    • 10 = AAC
    • 11 = Speex
    • 14 = MP3 8-Khz
    • 15 = Device-specific sound
    • 7, 8, 14, and 15:内部保留使用
    • flv 是不支持 g711a 的,如果要用,可能要用线性音频
  • 采样率(2bits):
    • 0 = 5.5-kHz
    • 1 = 11-kHz
    • 2 = 22-kHz
    • 3 = 44-kHz,For AAC: always 3
  • 采样大小(1bit):
    • 0 = snd8Bit
    • 1 = snd16Bit
    • 压缩过的音频都是 16bit
  • 声道(1bit):
    • 0 = 单声道
    • 1 = 立体声,即双声道。AAC 永远是 1
  • AACPacketType(1byte):实际上,若为 AAC 数据,则还有一个字节表示 AACPacketType,否则没有这个字节。这个字段表示 AACAudioData 的类型:
    • 0 = AAC sequence header,类似 H.264 的 sps,pps,在 FLV 文件头部中出现一次
    • 1 = AAC raw
  • 数据:如果是 PCM 线性数据,存储的时候每个 16bits 小端存储,有符号。如果音频格式是 AAC,则存储的数据是 AAC AUDIO DATA,否则为线性数组。

下面针对存储的为 AAC 音频数据进行分析。

5.1 AAC sequence header

AAC sequence header 这个音频包有些 FLV 文件里面没有也可以正确解码。但对于 RTMP 播放,必须要在发送第一个 AAC raw 包之前发送这个 AAC sequence header 包。

AAC Sequence header 定义为 Audio Specific Config,Audio Specific Config 包含着一些更加详细的音频信息,它的定义在 ISO14496-3 中的 1.6.2.1。具体可以参考 MPEG-4 Audio

Audio Specific Config 音频包数据区的格式如下:

5 bits: object type
if (object type == 31)
    6 bits + 32: object type
4 bits: frequency index
if (frequency index == 15)
    24 bits: frequency
4 bits: channel configuration
var bits: AOT Specific Config

简化版的 Audio Specific Config 的 2 字节定义如下:

AAC Profile 5bits | 采样率表索引 4bits | 声道数 4bits | 其他 3bits |
  • audio object type,即 AAC Profile(5bits):下面列举常用的
    • 1:Main,主规格,包含了除增益控制之外的全部功能,其音质最好
    • 2:LC,低复杂度规格(Low Complexity),现在的手机比较常见的 MP4 文件中的音频部分就包括了该规格音频文件
    • 3:SSR
    • 5:AAC HE = LC + SBR,高效率规格(High Efficiency),这种规格适合用于低码率编码,有 Nero AAC 编码器支持
    • 29:AAC HEv2 = LC + SBR + PS
  • Sampling Frequency Index(4bits):用来表示采样率表中的索引号
    • 0x00: 96000 Hz
    • 0x01: 88200 Hz
    • 0x02: 64000 Hz
    • 0x03: 48000 Hz
    • 0x04: 44100 Hz
    • 0x05: 32000 Hz
    • 0x06: 24000 Hz
    • 0x07: 22050 Hz
    • 0x08: 16000 Hz
    • 0x09: 12000 Hz
    • 0x0A: 11025 Hz
    • 0x0B: 8000 Hz
    • 0x0C: 7350 Hz
  • channel configuraion(4bits):声道数
    • 0: Defined in AOT Specifc Config
    • 1: 1 channel: front-center
    • 2: 2 channels: front-left, front-right
    • 3: 3 channels: front-center, front-left, front-right
    • 4: 4 channels: front-center, front-left, front-right, back-center
    • 5: 5 channels: front-center, front-left, front-right, back-left, back-right
    • 6: 6 channels: front-center, front-left, front-right, back-left, back-right, LFE-channel
    • 7: 8 channels: front-center, front-left, front-right, side-left, side-right, back-left, back-right, LFE-channel
    • 8-15: Reserved
  • 其他 3bits 设置为 0 即可

SRS 中对 Audio Specific Config(即 AAC Sequence header)的解码如下:

u_int8_t profile_ObjectType = stream->read_1bytes();
u_int8_t samplingFrequencyIndex = stream->read_1bytes();
    
aac_channels = (samplingFrequencyIndex >> 3) & 0x0f;
samplingFrequencyIndex = ((profile_ObjectType << 1) & 0x0e) | 
                         ((samplingFrequencyIndex >> 7) & 0x01);
profile_ObjectType = (profile_ObjectType >> 3) & 0x1f;

下图是通过 obs 推 FLV 到 RTMP 服务器后抓包到的第一个 Audio Tag,即 AAC Sequence header:

注:如上图所示,0xaf 接下来的 0x00 即为 AACPacketType,为 0 表示这是 AAC Sequence header。

5.2 AAC raw

如下图,为抓包得到的一个 obs 推 FLV 文件到 RTMP 服务器的 video raw 音频包:

6. Video Data

猜你喜欢

转载自www.cnblogs.com/jimodetiantang/p/8992425.html