FLV视频封装格式详解

news2024/12/27 14:28:22


 

目录(?)[-]

  1. Overview
  2. File Structure
    1. The FLV header
    2. The FLV File Body
  3. FLV Tag Definition
    1. FLVTAG
  4. Audio Tags
  5. Video Tags
  6. SCRIPTDATA
    1. onMetaData
    2. keyframes

Overview

Flash Video(简称FLV),是一种流行的网络格式。目前国内外大部分视频分享网站都是采用的这种格式.

File Structure

从整个文件上开看,FLV是由The FLV header 和 The FLV File Body 组成.

1.The FLV header

FieldTypeComment
SignatureUI8Signature byte always 'F' (0x46)
SignatureUI8Signature byte always 'L' (0x4C)
SignatureUI8Signature byte always 'V' (0x56)
VersionUI8File version (for example, 0x01 for FLV version 1)
TypeFlagsReservedUB [5]Shall be 0
TypeFlagsAudioUB [1]1 = Audio tags are present
TypeFlagsReservedUB [1]Shall be 0
TypeFlagsVideoUB [1]1 = Video tags are present
DataOffsetUI32The length of this header in bytes

Signature: FLV 文件的前3个字节为固定的‘F’‘L’‘V’,用来标识这个文件是flv格式的.在做格式探测的时候,

如果发现前3个字节为“FLV”,就认为它是flv文件.

Version: 第4个字节表示flv版本号.

Flags: 第5个字节中的第0位和第2位,分别表示 video 与 audio 存在的情况.(1表示存在,0表示不存在)

DataOffset : 最后4个字节表示FLV header 长度.

2.The FLV File Body

FieldTypeComment
PreviousTagSize0UI32Always 0
Tag1FLVTAGFirst tag
PreviousTagSize1UI32

Size of previous tag, including its header, in bytes. For FLV version1,

this value is 11 plus the DataSize of the previous tag.

Tag2FLVTAGSecond tag
.........
PreviousTagSizeN-1UI32Size of second-to-last tag, including its header, in bytes.
TagNFLVTAGLast tag
PreviousTagSizeNUI32Size of last tag, including its header, in bytes

FLV header之后,就是 FLV File Body.

FLV File Body是由一连串的back-pointers + tags构成.back-pointers就是4个字节数据,表示前一个tag的size.

FLV Tag Definition

FLV文件中的数据都是由一个个TAG组成,TAG里面的数据可能是video、audio、scripts.

下表是TAG的结构:

1.FLVTAG

FieldTypeComment
ReservedUB [2]Reserved for FMS, should be 0
FilterUB [1]Indicates if packets are filtered.
0 = No pre-processing required.
1 = Pre-processing (such as decryption) of the packet is
required before it can be rendered.
Shall be 0 in unencrypted files, and 1 for encrypted tags.
See Annex F. FLV Encryption for the use of filters.
TagTypeUB [5]

Type of contents in this tag. The following types are
defined:
8 = audio
9 = video
18 = script data

DataSizeUI24Length of the message. Number of bytes after StreamID to
end of tag (Equal to length of the tag – 11)
TimestampUI24Time in milliseconds at which the data in this tag applies.
This value is relative to the first tag in the FLV file, which
always has a timestamp of 0.
TimestampExtendedUI8Extension of the Timestamp field to form a SI32 value. This
field represents the upper 8 bits, while the previous
Timestamp field represents the lower 24 bits of the time in
milliseconds.
StreamIDUI24Always 0.
AudioTagHeaderIF TagType == 8
AudioTagHeader
VideoTagHeaderIF TagType == 9
VideoTagHeader
EncryptionHeaderIF Filter == 1
EncryptionTagHeader
FilterParamsIF Filter == 1
FilterParams
DataIF TagType == 8
AUDIODATA
IF TagType == 9
VIDEODATA
IF TagType == 18
SCRIPTDATA
Data specific for each media type.

TagType: TAG中第1个字节中的前5位表示这个TAG中包含数据的类型,8 = audio,9 = video,18 = script data.

DataSize:StreamID之后的数据长度.

Timestamp和TimestampExtended组成了这个TAG 包数据的PTS信息,记得刚开始做FVL demux的时候,并没有考虑TimestampExtended的值,直接就把Timestamp默认为是PTS,后来发生的现 象就是画面有跳帧的现象,后来才仔细看了一下文档发现真正数据的PTS是PTS= Timestamp | TimestampExtended<<24.

StreamID之后的数据就是每种格式的情况不一样了,接下格式进行详细的介绍.

Audio Tags

如果TAG包中的TagType==8时,就表示这个TAG是audio。

StreamID之后的数据就表示是AudioTagHeader,AudioTagHeader结构如下:

FieldTypeComment
SoundFormatUB [4]Format of SoundData. The following values are defined:
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
Formats 7, 8, 14, and 15 are reserved.
AAC is supported in Flash Player 9,0,115,0 and higher.
Speex is supported in Flash Player 10 and higher.
SoundRateUB [2]Sampling rate. The following values are defined:
0 = 5.5 kHz
1 = 11 kHz
2 = 22 kHz
3 = 44 kHz
SoundSizeUB [1]

Size of each audio sample. This parameter only pertains to
uncompressed formats. Compressed formats always decode
to 16 bits internally.
0 = 8-bit samples
1 = 16-bit samples

SoundTypeUB [1]Mono or stereo sound
0 = Mono sound
1 = Stereo sound
AACPacketTypeIF SoundFormat == 10
UI8
The following values are defined:
0 = AAC sequence header
1 = AAC raw

AudioTagHeader的头1个字节,也就是接跟着StreamID的1个字节包含着音频类型、采样率等的基本信息.表里列的十分清楚.

AudioTagHeader之后跟着的就是AUDIODATA数据了,也就是audio payload 但是这里有个特例,如果音频格式(SoundFormat)是10 = AAC,AudioTagHeader中会多出1个字节的数据AACPacketType,这个字段来表示AACAUDIODATA的类型:0 = AAC sequence header,1 = AAC raw。

FieldTypeComment
Data

IF AACPacketType ==0 AudioSpecificConfig

The AudioSpecificConfig is defined in ISO14496-3. Note that this is not the same as the contents of the esds box from an MP4/F4V file.

ELSE IF AACPacketType == 1 Raw AAC frame data in UI8 [ ]

audio payload

AAC sequence header也就是包含了AudioSpecificConfig,AudioSpecificConfig包含着一些更加详细音频的信息,AudioSpecificConfig的定义在ISO14496-3中1.6.2.1 AudioSpecificConfig,这里就不详细贴了。而且在ffmpeg中有对AudioSpecificConfig解析的函数,ff_mpeg4audio_get_config(),可以对比的看一下,理解更深刻。

AAC raw 这种包含的就是音频ES流了,也就是audio payload.

在FLV的文件中,一般情况下 AAC sequence header 这种包只出现1次,而且是第一个audio tag,为什么要提到这种tag,因为当时在做FLVdemux的时候,如果是AAC的音频,需要在每帧AAC ES流前边添加7个字节ADST头,ADST在音频的格式中会详细解读,这是解码器通用的格式,就是AAC的纯ES流要打包成ADST格式的AAC文件,解码器才能正常播放.就是在打包ADST的时候,需要samplingFrequencyIndex这个信息,samplingFrequencyIndex最准确的信息是在AudioSpecificConfig中,所以就对AudioSpecificConfig进行解析并得到了samplingFrequencyIndex。

到这步你就完全可以把FLV 文件中的音频信息及数据提取出来,送给音频解码器正常播放了。

Video Tags

如果TAG包中的TagType==9时,就表示这个TAG是video.

StreamID之后的数据就表示是VideoTagHeader,VideoTagHeader结构如下:

FieldTypeComment
Frame TypeUB [4]Type of video frame. The following values are defined:
1 = key frame (for AVC, a seekable frame)
2 = inter frame (for AVC, a non-seekable frame)
3 = disposable inter frame (H.263 only)
4 = generated key frame (reserved for server use only)
5 = video info/command frame
CodecIDUB [4]Codec Identifier. The following values are defined:
2 = Sorenson H.263
3 = Screen video
4 = On2 VP6
5 = On2 VP6 with alpha channel
6 = Screen video version 2
7 = AVC
AVCPacketTypeIF CodecID == 7
UI8

The following values are defined:
0 = AVC sequence header
1 = AVC NALU
2 = AVC end of sequence (lower level NALU sequence ender is not required or supported)

CompositionTimeIF CodecID == 7
SI24
IF AVCPacketType == 1
Composition time offset
ELSE
0
See ISO 14496-12, 8.15.3 for an explanation of composition
times. The offset in an FLV file is always in milliseconds.

VideoTagHeader的头1个字节,也就是接跟着StreamID的1个字节包含着视频帧类型及视频CodecID最基本信息.表里列的十分清楚.

VideoTagHeader之后跟着的就是VIDEODATA数据了,也就是video payload.当然就像音频AAC一样,这里也有特例就是如果视频的格式是AVC(H.264)的话,VideoTagHeader会多出4个字节的信息.

AVCPacketType 和 CompositionTime。AVCPacketType 表示接下来 VIDEODATA (AVCVIDEOPACKET)的内容:

IF AVCPacketType == 0 AVCDecoderConfigurationRecord(AVC sequence header)
IF AVCPacketType == 1 One or more NALUs (Full frames are required)

AVCDecoderConfigurationRecord.包含着是H.264解码相关比较重要的sps和pps信息,再给AVC解码器送数据 流之前一定要把sps和pps信息送出,否则的话解码器不能正常解码。而且在解码器stop之后再次start之前,如seek、快进快退状态切换等,都 需要重新送一遍sps和pps的信息.AVCDecoderConfigurationRecord在FLV文件中一般情况也是出现1次,也就是第一个 video tag.

AVCDecoderConfigurationRecord的定义在ISO 14496-15, 5.2.4.1中,这里不在详细贴,

SCRIPTDATA

如果TAG包中的TagType==18时,就表示这个TAG是SCRIPT.

SCRIPTDATA 结构十分复杂,定义了很多格式类型,每个类型对应一种结构.

FieldTypeComment
TypeUI8Type of the ScriptDataValue.
The following types are defined:
0 = Number
1 = Boolean
2 = String
3 = Object
4 = MovieClip (reserved, not supported)
5 = Null
6 = Undefined
7 = Reference
8 = ECMA array
9 = Object end marker
10 = Strict array
11 = Date
12 = Long string
ScriptDataValueIF Type == 0
DOUBLE
IF Type == 1
UI8
IF Type == 2
SCRIPTDATASTRING
IF Type == 3
SCRIPTDATAOBJECT
IF Type == 7
UI16
IF Type == 8
SCRIPTDATAECMAARRAY
IF Type == 10
SCRIPTDATASTRICTARRAY
IF Type == 11
SCRIPTDATADATE
IF Type == 12
SCRIPTDATALONGSTRING
Script data value.
The Boolean value is (ScriptDataValue ≠ 0).

类型在FLV的官方文档中都有详细介绍.

onMetaData

onMetaData 是SCRIPTDATA中对我们来说十分重要的信息,结构如下表:

Property NameTypeComment
audiocodecidNumberAudio codec ID used in the file (see E.4.2.1 for available SoundFormat values)
audiodatarateNumberAudio bit rate in kilobits per second
audiodelayNumberDelay introduced by the audio codec in seconds
audiosamplerateNumberFrequency at which the audio stream is replayed
audiosamplesizeNumberResolution of a single audio sample
canSeekToEndBooleanIndicating the last video frame is a key frame
creationdateStringCreation date and time
durationNumberTotal duration of the file in seconds
filesizeNumberTotal size of the file in bytes
framerateNumberNumber of frames per second
heightNumberHeight of the video in pixels
stereoBooleanIndicating stereo audio
videocodecidNumberVideo codec ID used in the file (see E.4.3.1 for available CodecID values)
videodatarateNumberVideo bit rate in kilobits per second
widthNumberWidth of the video in pixels

这里面的duration、filesize、视频的width、height等这些信息对我们来说很有用.

keyframes

当时在做flv demux的时候,发现官方的文档中并没有对keyframes index做描述,但是flv的这种结构每个tag又不像TS有同步头,如果没有keyframes index 的话,seek及快进快退的效果会非常差,因为需要一个tag一个tag的顺序读取。后来通过网络查一些资料,发现了一个keyframes的信息藏在SCRIPTDATA中。

keyframes几乎是一个非官方的标准,也就是民间标准.在网上已经很 难看到flv文件格式,但是metadata里面不包含 keyframes项目的视频 . 两个常用的操作metadata的工具是flvtool2和FLVMDI,都是把keyframes作为一个默认的元信息项目.在FLVMDI的主页 (http://www.buraks.com/flvmdi/)上有描述:

keyframes: (Object) This object is added only if you specify the /k switch. 'keyframes' is known to FLVMDI and if /k switch is not specified, 'keyframes' object will be deleted.
'keyframes' object has 2 arrays: 'filepositions' and 'times'. Both arrays have the same number of elements, which is equal to the number of key frames in the FLV. Values in times array are in 'seconds'. Each correspond to the timestamp of the n'th key frame. Values in filepositions array are in 'bytes'. Each correspond to the fileposition of the nth key frame video tag (which starts with byte tag type 9).

也就是说keyframes中包含着2个内容 'filepositions' and 'times'分别指的是关键帧的文件位置和关键帧的PTS.通过keyframes可以建立起自己的Index,然后再seek和快进快退的操作中,快速有效的跳转到你想要找的关键帧的位置进行处理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2266441.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何从 0 到 1 ,打造全新一代分布式数据架构

导读&#xff1a;本文从 DIKW&#xff08;数据、信息、知识、智慧&#xff09; 模型视角出发&#xff0c;探讨数字世界中数据的重要性问题。接着站在业务视角&#xff0c;讨论了在不断满足业务诉求&#xff08;特别是 AI 需求&#xff09;的过程中&#xff0c;数据系统是如何一…

elementPlus消息组件多按钮案例

let customClass zsl-el-message-box efb.messageBox({title: 操作提示,showConfirmButton: false,customClass,message: efb.VNode(div, null, [efb.VNode(style, null, .${customClass} .el-message-box__message {width: 100%;}),efb.VNode(div, null, hello world),efb.VN…

MATLAB符号计算-符号表达式基础运算操作

1.1.2符号变量取值域的限定 默认复数域 【例1-1-2】解不等式 1.1.3创建符号表达式 对符号对象进行各种运算&#xff08;算术运算、关系运算、逻辑运算&#xff09;&#xff0c;即可创建符号表达式。 1.算术运算与转置 【例1-1-3】 f5是f4的共轭转置 f6是f4的转置 2.关系…

使用Excel制作通达信自定义外部数据,安排!!!

Excel相信大家电脑上都有这个工具&#xff0c;相比敲编程代码&#xff0c;用这个去做自定义数据对大多数人&#xff0c;应该是比较友好的。自定义数据分为外部序列数据&#xff0c;看了一下内容理解起来比较多&#xff0c;分两期给大家介绍。为了照顾电脑基础薄弱的朋友&#x…

SwiftUI 入门趣谈:在文本框(TextField)内限制数字的输入

概述 虽然 SwiftUI 本身提供了海量内置的原生视图供我们使用&#xff0c;但对于某些情况我们还需要根据实际需求“量体裁衣、专属定制”。 在日常的撸码场景中&#xff0c;我们有时需要限制文本框&#xff08;TextField&#xff09;中数字内容的输入&#xff0c;如何又简单又快…

深入浅出 MyBatis | CRUD 操作、配置解析

3、CRUD 3.1 namespace namespace 中的包名要和 Dao/Mapper 接口的包名一致&#xff01; 比如将 UserDao 改名为 UserMapper 运行发现抱错&#xff0c;这是因为 UserMapper.xml 中没有同步更改 namespace 成功运行 给出 UserMapper 中的所有接口&#xff0c;接下来一一对…

基于c语言的union、字符串、格式化输入输出

结构体之共用体union 共用体也叫联合体&#xff0c;其关键词为union 与结构体不同的是&#xff0c;共用体所开辟的存储空间仅仅为其中最长类型变量的存储空间而不是全部变量的存储空间&#xff0c;由于同一内存单元在同一时间内只能存放其中一种的数据类型&#xff0c;因此在每…

IntelliJ Idea常用快捷键详解

文章目录 IntelliJ Idea常用快捷键详解一、引言二、文本编辑与导航1、文本编辑2、代码折叠与展开 三、运行和调试四、代码编辑1、代码补全 五、重构与优化1、重构 六、使用示例代码注释示例代码补全示例 七、总结 IntelliJ Idea常用快捷键详解 一、引言 在Java开发中&#xff…

AI开发:使用支持向量机(SVM)进行文本情感分析训练 - Python

支持向量机是AI开发中最常见的一种算法。之前我们已经一起初步了解了它的概念和应用&#xff0c;今天我们用它来进行一次文本情感分析训练。 一、概念温习 支持向量机&#xff08;SVM&#xff09;是一种监督学习算法&#xff0c;广泛用于分类和回归问题。 它的核心思想是通过…

Linux-----进程处理(子进程创建)

【尚硅谷嵌入式Linux应用层开发&#xff0c;linux网络编程&#xff0c;linux进程线程&#xff0c;linux文件io】https://www.bilibili.com/video/BV1DJ4m1M77z?p35&vd_source342079de7c07f82982956aad8662b467 main函数 fork创建进程 fork()参数 /*** brief 创建一个子进…

一种寻路的应用

应用背景 利用长途车进行货物转运的寻路计算。例如从深圳到大连。可以走有很多条长途车的路线。需要根据需求计算出最合适路线。不同的路线的总里程数、总价、需要的时间不一样。客户根据需求进行选择。主要有一些细节&#xff1a; 全国的长途车车站的数据的更新&#xff1a; …

2. FPGA基础了解--全局网络

前言 引入扇出的概念介绍FPGA中的全局网络为后续时序优化埋下伏笔 扇出 在FPGA设计中扇出是一个重要的概念&#xff0c;所谓的扇出就是一个控制信号所能控制的数据信号的总个数&#xff0c;比如ctrl信号的扇出就是16 reg ctrl 0; reg [15:0] out 0; always (posedge c…

Excel中一次查询返回多列

使用Excel或wps的时候&#xff0c;有时候需要一次查询返回多列内容&#xff0c;这种情况可以选择多次vlookup或者多次xlookup&#xff0c;但是这种做法费时费力不说&#xff0c;效率还有些低下&#xff0c;特别是要查询的列数过多时。我放了3种查询方法&#xff0c;效果图&…

智能化军事【五】精确制导武器智能化实现

文章目录 前言精确制导武器智能化实现基于深度学习实现的智能化功能基于强化学习实现的智能化功能强化学习深度强化学习 网络模型轻量化网络剪枝&#xff08;通道剪枝&#xff09;技术层剪枝权值量化技术低秩近似技术知识蒸馏技术强化学习联合训练 解决有效训练样本不足或获取困…

解锁高效密码:适当休息,让学习状态满格

一、“肝帝” 的困境 在当今竞争激烈的职场中&#xff0c;“肝帝” 现象屡见不鲜。超长工时仿佛成为了许多行业的 “标配”&#xff0c;从互联网企业的 “996”“007”&#xff0c;到传统制造业的轮班倒、无休无止的加班&#xff0c;员工们的工作时间被不断拉长。清晨&#xff…

asp.net 高校学生勤工俭学系统设计与实现

博主介绍&#xff1a;专注于Java&#xff08;springboot ssm 等开发框架&#xff09; vue .net php python(flask Django) 小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设&#xff0c;从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不然下次找…

WebRTC服务质量(12)- Pacer机制(04) 向Pacer中插入数据

WebRTC服务质量&#xff08;01&#xff09;- Qos概述 WebRTC服务质量&#xff08;02&#xff09;- RTP协议 WebRTC服务质量&#xff08;03&#xff09;- RTCP协议 WebRTC服务质量&#xff08;04&#xff09;- 重传机制&#xff08;01) RTX NACK概述 WebRTC服务质量&#xff08;…

RTMW:实时多人2D和3D 全人体姿态估计

单位&#xff1a;上海AI实验室 代码&#xff1a;mmpose/tree/main/projects/rtmpose 系列文章目录 RTMO: 面向高性能单阶段的实时多人姿态估计 目录 系列文章目录摘要一、背景二、相关工作2.1 自上而下的方法。2.2 坐标分类。2.3 3D Pose 3 实验方法3.1.1 任务限制3.1.3训练技…

AI智能养站神器-SEO助理原创文章批量生成发布工具

很多站长最头疼的就是网站每天的内容更新&#xff0c;因为不知道写什么&#xff0c;采集被人的文章又会被定义为抄袭&#xff0c;而且现在伪原创已经没有多大的效果了&#xff0c;所以今天给大家分享的就是一款AI智能养战神器-SEO助理原创文章批量生成发布工具。 这款工具支持…

用Python开启人工智能之旅(三)常用的机器学习算法与实现

第三部分&#xff1a;常用的机器学习算法与实现 用Python开启人工智能之旅&#xff08;一&#xff09;Python简介与安装 用Python开启人工智能之旅&#xff08;二&#xff09;Python基础 用Python开启人工智能之旅&#xff08;三&#xff09;常用的机器学习算法与实现 用Pyt…