rtmp 时间戳_音视频基础: RTMP协议

RTMP 基础

RTMP概念

与HTTP(超文本传输协议)同样是一个基于TCP的Real Time Messaging Protocol(实时消息传输协议)。由Adobe Systems公司为Flash播放器和服务器之间音频、视频和数据传输开发的一种开放协议 。在国内被广泛的应用于直播 领域。HTTP默认端口为80,RTMP则为1935。
我们通过阅读Adobe的协议规范,通过与服务器建立TCP通信,根据协议格式生成与解析数据即可使用RTMP进行 直播。当然我们也可以借助一些实现了RTMP协议的开源库来完成这一过程。

RTMPDump

RTMPDump 是一个用来处理RTMP流媒体的开源工具包。它能够单独使用进行 RTMP的通信,也可以集成到FFmpeg中通过FFmpeg接口来使用RTMPDump。 RTMPDump源码下载

交叉编译

在Android中可以直接借助NDK在JNI层调用RTMPDump来完成RTMP通信。但是首先必须得进行交叉编译。 RTMPDump源码结构如下:

4a281b27e244fbb74d514eecb80a7e92.png

在根目录下提供了一个 Makefile 与一些 源文件。这里的源文件将会编译出一系列的可执行文件。然后我们需 要的并不是可执行文件,真正的对RTMP的实现都在librtmp子目录中。
在这个子目录中同样包含了一个 Makefile 文件。通过阅读 发现,它的源码并不多: OBJS=rtmp.o log.o amf.o hashswf.o parseurl.o 。因此我们 不进行预编译,即直接放入AS中借助 CMakeLists.txt 来进行编译。
这么做可以让我们方便的对库本身进行调试或 修改(实际上我们确实会稍微修改这个库的源码)。 在AS中复制librtmp置于: ,并为其编写CMakeLists.txt

# 预编译宏 
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNO_CRYPTO" )
# 所有源文件放入 rtmp_source 变量 
file(GLOB rtmp_source *.c)
# 编译静态库 
add_library(rtmp STATIC ${rtmp_source} )

在 中导入这个CMakeLists.txt

cmake_minimum_required(VERSION 3.4.1) 
# 导 入 其 他 目 录 
cmakelist add_subdirectory(src/main/cpp/librtmp) add_library(XXX SHARED ...) 
#XXX需要链接rtmp库 
target_link_libraries(XXX rtmp ...)

RTMP视频数据

RTMP视频流格式与FLV很相似,通过查看FLV的格式文档,就能够知道RTMP视频数据应该怎么拼接。

RTMP中的数据就是由FLV的TAG中的数据区构成。

4d63f7d72bb60ac1141c5df51dc8d175.png

FLV tags 结构

字段字节描述

bfe780f2a3ec3af3ad8c9266d0a69da6.png
如上图,第一个字节0x09 表示此段数据为视频,数据大小为0x00,0x00,0x2F即47,时间戳为 0x00,0x00,0x00,时间戳扩展也为0x00。(第二行)流ID:0x00,0x00,0x00。
接下来就是视频数据,通过此处的 数据大小字段得知,数据长为47字节。
则从0x17开始,一直到最后一行的0xC0,就是数据区域,而最后的 0x00,0x00,0x00,0x3A 即58,表示的是这个数据块除最后4个字节的总大小。
本处为视频数据,那么从0x17 开始,数据内容则为下面的部分。

视频数据

字段占位描述

AVCVIDEOPACKET

字段字节描述

2242c1d192d11577f4a4430932922c9b.png
视频数据中 0x17则表示了1:关键帧与7:高级视频编码 AVC,如果是普通帧,则此数据为0x27。
而类型为: 0x00表示这段数据为AVC序列头(avc sequence header)。
最后三个字节为合成时间。
而如果类型为AVC序列 头接下来的数据就是下面的内容:

AVC 序列头

在AVCVIDEOPACKET 中如果类型为0,则后续数据为:

类型字节说明

cf1611a55954a87fd469925d2eea86e0.png
0x01为版本,后续数据按照上表记录,最后四字节上面说过:为这个数据块除最后4个字节的总大小。其中 SPS与PPS是编码器在编码H.264视频时,在关键帧前会编码出的关于这个关键帧与需要参考该关键帧的B/P 帧如何解码的内容,如:宽、高等信息。

其他

类型字节说明

一般情况下,组装的RTMPPacket(RTMPDump中的结构体)为:

8aed5f1e3f78d393d7ccc09d5da4a0e5.png
这里的sps与pps表示 AVC序列头

5544a6f23b48c505ce3a925e2de12e8f.png

所以对于视频的数据封装,AVC序列头为:

4ecc1d0af92f18007fef4b18ccba945d.png

H.264数据

H.264码流在网络中传输时实际是以NALU的形式进行传输的。
NALU就是NAL UNIT,NAL单元。
NAL全称Network Abstract Layer, 即网络抽象层。在H.264/AVC视频编码标准中,整个系统框架被分为了两个层面:视频编码层面 (VCL)和网络抽象层面(NAL)。
其中,前者负责有效表示视频数据的内容,而后者则负责格式化数据并提供头 信息,以保证数据适合各种信道和存储介质上的传输。
我们平时的每帧数据就是一个NAL单元。
往RTMP包中填充的就是NAL数据,但不是直接将编码出来的数据填充进去。
一段包含了N个图像的H.264裸数据,每个NAL之间由: 00 00 00 01 或者 00 00 01 进行分割。
在分割符之后的第一个字节,就是表示这个nal的类型。

  • 0x67:sps
  • 0x68: pps
  • 0x65: IDR 在将数据加入RTMPPacket的时候是需要去除分割符的。

b1f07a4246973cc632160d9b24755546.png

所以完整的封包代码为:

e195dd85db48308845cd246fff08da74.png

NALU

NALU就是NAL UNIT,nal单元。NAL全称Network Abstract Layer, 即网络抽象层,H.264在网络上传输的结构。一 帧图片经过 H.264编码器之后,就被编码为一个或多个片(slice),而装载着这些片(slice)的载体,就是 NALU 了 。

音频数据

RTMP的音频数据相对视频比较简单,只需要根据是否为音频audio specific config(记录音频的格式)。
如果为 audio specific config拼接0xAF,0x00,否则就只需要添加0xAF,0x00。

c06ef7552aeb5170ba107fd8152ad17b.png

0xAF的由来:

16abd0621ffb3c6be2a181fd2eafe8e8.png

我们的编码为:

  • 10:AAC,3:44100采样率
  • 1:采样长度
  • 1:声道。
  • 按照位数表示数据就为:0xAF

9f812ea214bb26592a5a50f331808f46.png

而audio specific config只需要在发起推流时,发送音频数据之前发起一次即可。其数据为两字节:

459ef0bad9672e655ac4aaf283edb8c3.png

fd6e6db8f42f605c541a0ac2a8ea56c6.png
  • 第一个数据:AAC-LC值为2,占用5位,则数据为: 0001 0
  • 第二个数据:采样率44100值为4,占用4位,则数据为:0100
  • 第三个数据:声道,双声道为2,单声道为1,则数据为:0010(双声道),0001(单声道) 最后三位为0,这样组成的数据5+4+4+3=16位,两字节。
  • 双声道:0x12 ,0x10
  • 单声道:0x12 ,0x08

5db9d99cad5c8fb79ba0140a4a0315f7.png

Nginx-RTMP 服务器搭建

Linux操作:
下载nginx wget http://nginx.org/download/nginx-1.15.3.tar.gz
解压
tar xvf nginx-1.15.3.tar.gz
下载nginx rtmp模块
wget https://codeload.github.com/arut/nginx-rtmp-module/tar.gz/v1.2.1
解压
tar xvf v1.2.1
进入nginx目录
cd nginx-1.15.3
执行:

afbfad4f959587c24915f6c86b2df681.png

在这个过程中可能因为环境不同而出现不同错误,比如缺少pcre、openssl等,这时候就需要安装这些库。

https://blog.csdn.net/z920954494/article/details/52132125

编译完成后,安装在当前目录的bin目录下。

cd bin/conf

vim nginx.conf 修改为:

0dc14503fb84aabe6c67779f8208af8a.png

bfc533c0b089e0389ae73191bebc6598.png

其实就是从 nginx-rtmp-module-1.2.1/test/nginx.conf 中拷贝

端口占用检查: lsof -i:8080

需要注意的是目录与端口是否被占用,比如8080端口被占用,可以改为了8081,然后需要开放端口。

如果使用的阿里云服务器可以进入阿里云控制台开放

c71014338840617dda39887f3178edc8.png

然后点击 配置规则 ,在新页面点击添加 安全组规则 ,开放8081端口,然后确定,就可以了。

9eab155e1279b6ee9ae2dda7721a7097.png

配置完成后,就可以启动nginx了
在nginx-1.15.3目录 执行 bin/sbin/nginx 即可启动
bin/sbin/nginx -s stop 停止
一定要在nginx-1.15.3目录启动,因为上面的配置 error_log logs/error.log debug; 会去执行命令的目录下查找 logs。
如果error_log 改成一个绝对路径 那就没关系了。
在浏览器输入 【IP】:8081/stat ,能访问就表示配置完成了。
此时一旦有播放器或者推流器连接到搭建的服务器刷新 此界面就能够看到如下界面:(手机推流,ffplay、网页、potplayer播放)

9ca65f84b82a69474b20976f467ddfa6.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值