通过RTMP play分析FLV格式详解
最近做了一个rtmp中转服务程序,通过实践,熟悉rtmp play和push中各类格式,这里总结一下。
程序github地址: https://github.com/runner365/rtmp_relay
rtmp play接收报文分析
第一帧收到的报文:

1) 0x46 4c 56:可参考文后:参考一
字符FLV头
2) 0x01 05
Version TypeFlagsReserved TypeFlagsAudio TypeFlagsReserved TypeFlagsVideo
这个解析的时候,一般不用管
3)0x00 00 00 09
FLV header offset: 也就是从开头9字节后,才是FLV真正的报文头。
4)0x00 00 00 00
这个是第1帧的PreviousTagSize0(前帧长度),因为是第一帧,所以肯定是0;
5)0x08 可参考文后:参考二,参考三
帧开头第一字节:0x08表示音频,0x09表示视频
6)0x00 00 04
帧payload长度:因为音频第一帧是ASC,所以只有4字节。
7) 0x 00 00 00 00
timestamp,时间戳
8) 0x 00 00 00
streamid,流ID
9) 0x AF 00 13 90
音频payload: 0xaf00开头的后面是asc flag, 0xaf01开头的后面是真正的音频数据
0x13 90,也就是0b0001 0011 1001 0000,
ASC flag格式:xxxx xyyy yzzz z000
x字符: aac type,类型2表示AAC-LC,5是SBR, 29是ps,5和29比较特殊ascflag的长度会变成4;
y字符: sample rate, 采样率, 7表示22050采样率
z字符: 通道数,2是双通道
10) 0x 00 00 00 0F
这个还是PreviousTagSize1,上一帧长度15bytes
11) 0x09 视频类型,新的一帧
12)0x00 00 22
视频帧payload长度
13) 0x00 00 0a 00
时间戳:这个地方有个大坑,顺序是:a[3] a[0] a[1] a[2],最后一位是最高位。
14) 0x00 00 00
streamid, 流id。
15) 0x 17 00
视频帧开头2字节:
0x17 00: 表示内容是SPS和PPS
0x17 01: 表示内容是I-FRAME
0x27: 表示内容是P-FRAME
16)
0000002bh: 17 00 00 00 00 01 42 C0 1F FF E1 00 0E 67 42 C0 ; ......B??.gB?
0000003bh: 1F 8C 8D 40 F0 28 90 0F 08 84 6A 01 00 04 68 CE ; .實@??.刯...h?
0000004bh: 3C 80 ; <€
第12, 13字节: 0x00 0E是spslen,也就是14字节长度
跳过14字节后,0x01是pps开始的标识,跳过它。
0x00 04是ppslen,也就是4个字节,最后0x68 ce 3c 80就是pps。
参考:
1, The FLV header
| Type | Comment | |
| Signature | UI8 | Signature byte always 'F' (0x46) |
| Signature | UI8 | Signature byte always 'L' (0x4C) |
| Signature | UI8 | Signature byte always 'V' (0x56) |
| Version | UI8 | File version (for example, 0x01 for FLV version 1) |
| TypeFlagsReserved | UB [5] | Shall be 0 |
| TypeFlagsAudio | UB [1] | 1 = Audio tags are present |
| TypeFlagsReserved | UB [1] | Shall be 0 |
| TypeFlagsVideo | UB [1] | 1 = Video tags are present |
| DataOffset | UI32 | The 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,FLV body整体
| Field | Type | Comment |
| PreviousTagSize0 | UI32 | Always 0 |
| Tag1 | FLVTAG | First tag |
| PreviousTagSize1 | UI32 |
Size of previous tag, including its header, in bytes. For FLV version1, this value is 11 plus the DataSize of the previous tag. |
| Tag2 | FLVTAG | Second tag |
| ... | ... | ... |
| PreviousTagSizeN-1 | UI32 | Size of second-to-last tag, including its header, in bytes. |
| TagN | FLVTAG | Last tag |
| PreviousTagSizeN | UI32 | Size of last tag, including its header, in bytes |
FLV header之后,就是 FLV File Body.
FLV File Body是由一连串的back-pointers + tags构成.back-pointers就是4个字节数据,表示前一个tag的size.
3,FLV body细节
| Field | Type | Comment |
| Reserved | UB [2] | Reserved for FMS, should be 0 |
| Filter | UB [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. |
| TagType | UB [5] |
Type of contents in this tag. The following types are |
| DataSize | UI24 | Length of the message. Number of bytes after StreamID to end of tag (Equal to length of the tag – 11) |
| Timestamp | UI24 | Time 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. |
| TimestampExtended | UI8 | Extension 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. |
| StreamID | UI24 | Always 0. |
| AudioTagHeader | IF TagType == 8 AudioTagHeader |
|
| VideoTagHeader | IF TagType == 9 VideoTagHeader |
|
| EncryptionHeader | IF Filter == 1 EncryptionTagHeader |
|
| FilterParams | IF Filter == 1 FilterParams |
|
| Data | IF TagType == 8 AUDIODATA IF TagType == 9 VIDEODATA IF TagType == 18 SCRIPTDATA |
Data specific for each media t |
通过RTMP play分析FLV格式详解的更多相关文章
- flv格式详解+实例剖析
简介 FLV(Flash Video)是现在非常流行的流媒体格式,由于其视频文件体积轻巧.封装播放简单等特点,使其很适合在网络上进行应用,目前主流的视频网站无一例外地使用了FLV格式.另外由于当前浏览 ...
- FLV格式详解
Overview Flash Video(简称FLV),是一种流行的网络格式.目前国内外大部分视频分享网站都是采用的这种格式. File Structure 从整个文件上开看,FLV是由The FLV ...
- FLV视频封装格式详解
FLV视频封装格式详解 分类: FFMpeg编解码 2012-04-04 21:13 1378人阅读 评论(2) 收藏 举报 flvheaderaudiovideocodecfile 目录(?)[-] ...
- PNG,JPEG,BMP,JIF图片格式详解及其对比
原文地址:http://blog.csdn.net/u012611878/article/details/52215985 图片格式详解 不知道大家有没有注意过网页里,手机里,平板里的图片,事实上,图 ...
- binlog之四:mysql中binlog_format模式与配置详解,binlog的日志格式详解
mysql复制主要有三种方式:基于SQL语句的复制(statement-based replication, SBR),基于行的复制(row-based replication, RBR),混合模式复 ...
- 以太网帧格式、IP数据报格式、TCP段格式+UDP段格式 详解
转载:http://www.cnblogs.com/lifan3a/articles/6649970.html 以太网帧格式.IP数据报格式.TCP段格式+UDP段格式 详解 1.ISO开放系统有 ...
- BMP格式详解
BMP格式详解 BMP文件格式详解(BMP file format) BMP文件格式,又称为Bitmap(位图)或是DIB(Device-Independent Device,设备无关位图),是Win ...
- java分享第十五天(log4j 格式详解)
log4j 格式详解 log4j.rootLogger=日志级别,appender1, appender2, -. 日志级别:ALL<DEBUG<INFO<WARN<ERRO ...
- php 序列化(serialize)格式详解
1.前言 PHP (从 PHP 3.05 开始)为保存对象提供了一组序列化和反序列化的函数:serialize.unserialize.不过在 PHP 手册中对这两个函数的说明仅限于如何使用,而对序列 ...
随机推荐
- .Net语言 APP开发平台——Smobiler学习日志:如何在手机上显示类似EXCEL表格
最前面的话:Smobiler是一个在VS环境中使用.Net语言来开发APP的开发平台,也许比Xamarin更方便 样式一 一.目标样式 我们要实现上图中的效果,需要如下的操作: 1.从工具栏上的&qu ...
- .NET 对象生命周期
GC 垃圾回收 .NET Framework 的垃圾回收器管理应用程序的内存分配和释放.每次您使用 new 运算符创建对象时,运行库都从托管堆为该对象分配内存.只要托管堆中有地址空间可用,运 ...
- Tomcat指定的服务已存在
解压Tomcat8.0后,运行service.bat install,结果安装未成功,进入logs文件夹,查看错误日志,提示: 指定的服务已存在. Failed to install service ...
- Guava学习-目录
备份一下地址: 目录 1. 基本工具 [Basic utilities] 让使用Java语言变得更舒适 1.1 使用和避免null:null是模棱两可的,会引起令人困惑的错误,有些时候它让人很不舒服. ...
- 第 31 章 项目实战-PC 端固定布局[5]
学习要点: 1.底部区域 2.说明区域 3.版权及证件区 主讲教师:李炎恢 本章主要开始使用学习用 HTML5 和 CSS3 来构建 Web 页面,第一个项目采用 PC 端固定布局来实现. 一.底部区 ...
- ASP.NET MVC搭建项目后台UI框架—4、tab多页签支持
目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...
- 学习.NET是因为热爱 or 兴趣 or 挣钱?
看到最近园子里掀起了“.NET快不行了”.“.NET工资太低了”.“转行做XX”等一系列之风,不由得想说点什么,我只是基于自己的观点,你认同或者不认同,我就是这样认为,无所谓对与错,写文章就是为了交流 ...
- Hibernate(十)__缓存机制
为什么需要缓存? 缓存的作用主要用来提高性能,可以简单的理解成一个Map: 使 用缓存涉及到三个操作:把数据放入缓存.从缓存中获取数据. 删除缓存中的无效数据. 从上图看出: 当我们去查询对象的时候, ...
- less
//:此注释不会被编译 /**/:会被编译 变量:以@开头,exp:@test_width:100px; 混合: 匹配: 运算: 嵌套: arguments:将所有的变量带进去
- 【小贴士】探一探javascript中的replace
javascript字符串与数组有很多精巧的方法,比如splice.indexOf,而replace在字符串处理中偶尔会产生让人愉悦的效果 比如underscore中的模板引擎替换部分,又如信用卡分割 ...