音视频基础(网络传输): RTMP封包 mp4封装是什么意思
itomcoil 2024-12-19 13:43 15 浏览
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。
交叉编译
在 Android 中可以直接借助 NDK 在 JNI 层调用 RTMPDump 来完成 RTMP 通信。但是首先必须得进行交叉编译。 RTMPDump 源码结构如下:
在根目录下提供了一个 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 ...)
C++音视频开发学习资料:点击领取→音视频开发(资料文档+视频教程+面试题)(FFmpeg+WebRTC+RTMP+RTSP+HLS+RTP)
RTMP 视频数据
RTMP 视频流格式与 FLV 很相似,通过查看 FLV 的格式文档,就能够知道 RTMP 视频数据应该怎么拼接。
RTMP 中的数据就是由 FLV 的 TAG 中的数据区构成。
FLV tags 结构
如上图,第一个字节 0x09 表示此段数据为视频,数据大小为 0x00,0x00,0x2F 即 47,时间戳为 0x00,0x00,0x00,时间戳扩展也为 0x00。(第二行)流 ID:0x00,0x00,0x00。
接下来就是视频数据,通过此处的 数据大小字段得知,数据长为 47 字节。
则从 0x17 开始,一直到最后一行的 0xC0,就是数据区域,而最后的 0x00,0x00,0x00,0x3A 即 58,表示的是这个数据块除最后 4 个字节的总大小。
本处为视频数据,那么从 0x17 开始,数据内容则为下面的部分。
视频数据
AVCVIDEOPACKET
视频数据中 0x17 则表示了 1:关键帧与 7:高级视频编码 AVC,如果是普通帧,则此数据为 0x27。
而类型为: 0x00 表示这段数据为 AVC 序列头(avc sequence header)。
最后三个字节为合成时间。
而如果类型为 AVC 序列 头接下来的数据就是下面的内容:
C++音视频开发学习资料:点击领取→音视频开发(资料文档+视频教程+面试题)(FFmpeg+WebRTC+RTMP+RTSP+HLS+RTP)
AVC 序列头
在 AVCVIDEOPACKET 中如果类型为 0,则后续数据为:
0x01 为版本,后续数据按照上表记录,最后四字节上面说过:为这个数据块除最后 4 个字节的总大小。其中 SPS 与 PPS 是编码器在编码 H.264 视频时,在关键帧前会编码出的关于这个关键帧与需要参考该关键帧的 B/P 帧如何解码的内容,如:宽、高等信息。
其他
一般情况下,组装的 RTMPPacket(RTMPDump 中的结构体)为:
这里的 sps 与 pps 表示 AVC 序列头
所以对于视频的数据封装,AVC 序列头为:
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 的时候是需要去除分割符的。
所以完整的封包代码为:
NALU
NALU 就是 NAL UNIT,nal 单元。NAL 全称 Network Abstract Layer, 即网络抽象层,H.264 在网络上传输的结构。一 帧图片经过 H.264 编码器之后,就被编码为一个或多个片(slice),而装载着这些片(slice)的载体,就是 NALU 了 。
C++音视频开发学习资料:点击领取→音视频开发(资料文档+视频教程+面试题)(FFmpeg+WebRTC+RTMP+RTSP+HLS+RTP)
音频数据
RTMP 的音频数据相对视频比较简单,只需要根据是否为音频 audio specific config(记录音频的格式)。
如果为 audio specific config 拼接 0xAF,0x00,否则就只需要添加 0xAF,0x00。
0xAF 的由来:
我们的编码为:
- 10:AAC,3:44100 采样率
- 1:采样长度
- 1:声道。
- 按照位数表示数据就为:0xAF
而 audio specific config 只需要在发起推流时,发送音频数据之前发起一次即可。其数据为两字节:
第一个数据:AAC-LC 值为 2,占用 5 位,则数据为: 0001 0
第二个数据:采样率 44100 值为 4,占用 4 位,则数据为:0100
第三个数据:声道,双声道为 2,单声道为 1,则数据为:0010(双声道),0001(单声道) 最后三位为 0,这样组成的数据 5+4+4+3=16 位,两字节。
双声道:0x12 ,0x10
单声道:0x12 ,0x08
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
执行:
在这个过程中可能因为环境不同而出现不同错误,比如缺少 pcre、openssl 等,这时候就需要安装这些库。
https://blog.csdn.net/z920954494/article/details/52132125
编译完成后,安装在当前目录的 bin 目录下。
cd bin/conf
vim nginx.conf 修改为:
其实就是从 nginx-rtmp-module-1.2.1/test/nginx.conf 中拷贝
端口占用检查: lsof -i:8080
需要注意的是目录与端口是否被占用,比如 8080 端口被占用,可以改为了 8081,然后需要开放端口。
C++音视频开发学习资料:点击领取→音视频开发(资料文档+视频教程+面试题)(FFmpeg+WebRTC+RTMP+RTSP+HLS+RTP)
如果使用的阿里云服务器可以进入阿里云控制台开放
然后点击 配置规则 ,在新页面点击添加 安全组规则 ,开放 8081 端口,然后确定,就可以了。
配置完成后,就可以启动 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 播放)
相关推荐
- Excel新函数TEXTSPLIT太强大了,轻松搞定数据拆分!
-
我是【桃大喵学习记】,欢迎大家关注哟~,每天为你分享职场办公软件使用技巧干货!最近我把WPS软件升级到了版本号:12.1.0.15990的最新版本,最版本已经支持文本拆分函数TEXTSPLIT了,并...
- Excel超强数据拆分函数TEXTSPLIT,从入门到精通!
-
我是【桃大喵学习记】,欢迎大家关注哟~,每天为你分享职场办公软件使用技巧干货!今天跟大家分享的是Excel超强数据拆分函数TEXTSPLIT,带你从入门到精通!TEXTSPLIT函数真是太强大了,轻松...
- 看完就会用的C++17特性总结(c++11常用新特性)
-
作者:taoklin,腾讯WXG后台开发一、简单特性1.namespace嵌套C++17使我们可以更加简洁使用命名空间:2.std::variant升级版的C语言Union在C++17之前,通...
- plsql字符串分割浅谈(plsql字符集设置)
-
工作之中遇到的小问题,在此抛出问题,并给出解决方法。一方面是为了给自己留下深刻印象,另一方面给遇到相似问题的同学一个解决思路。如若其中有写的不好或者不对的地方也请不加不吝赐教,集思广益,共同进步。遇到...
- javascript如何分割字符串(javascript切割字符串)
-
javascript如何分割字符串在JavaScript中,您可以使用字符串的`split()`方法来将一个字符串分割成一个数组。`split()`方法接收一个参数,这个参数指定了分割字符串的方式。如...
- TextSplit函数的使用方法(入门+进阶+高级共八种用法10个公式)
-
在Excel和WPS新增的几十个函数中,如果按实用性+功能性排名,textsplit排第二,无函数敢排第一。因为它不仅使用简单,而且解决了以前用超复杂公式才能搞定的难题。今天小编用10个公式,让你彻底...
- Python字符串split()方法使用技巧
-
在Python中,字符串操作可谓是基础且关键的技能,而今天咱们要重点攻克的“堡垒”——split()方法,它能将看似浑然一体的字符串,按照我们的需求进行拆分,极大地便利了数据处理与文本解析工作。基本语...
- go语言中字符串常用的系统函数(golang 字符串)
-
最近由于工作比较忙,视频有段时间没有更新了,在这里跟大家说声抱歉了,我尽快抽些时间整理下视频今天就发一篇关于go语言的基础知识吧!我这我工作中用到的一些常用函数,汇总出来分享给大家,希望对...
- 无规律文本拆分,这些函数你得会(没有分隔符没规律数据拆分)
-
今天文章来源于表格学员训练营群内答疑,混合文本拆分。其实拆分不难,只要规则明确就好办。就怕规则不清晰,或者规则太多。那真是,Oh,mygod.如上图所示进行拆分,文字表达实在是有点难,所以小熊变身灵...
- Python之文本解析:字符串格式化的逆操作?
-
引言前面的文章中,提到了关于Python中字符串中的相关操作,更多地涉及到了字符串的格式化,有些地方也称为字符串插值操作,本质上,就是把多个字符串拼接在一起,以固定的格式呈现。关于字符串的操作,其实还...
- 忘记【分列】吧,TEXTSPLIT拆分文本好用100倍
-
函数TEXTSPLIT的作用是:按分隔符将字符串拆分为行或列。仅ExcelM365版本可用。基本应用将A2单元格内容按逗号拆分。=TEXTSPLIT(A2,",")第二参数设置为逗号...
- Excel365版本新函数TEXTSPLIT,专攻文本拆分
-
Excel中字符串的处理,拆分和合并是比较常见的需求。合并,当前最好用的函数非TEXTJOIN不可。拆分,Office365于2022年3月更新了一个专业函数:TEXTSPLIT语法参数:【...
- 站长在线Python精讲使用正则表达式的split()方法分割字符串详解
-
欢迎你来到站长在线的站长学堂学习Python知识,本文学习的是《在Python中使用正则表达式的split()方法分割字符串详解》。使用正则表达式分割字符串在Python中使用正则表达式的split(...
- Java中字符串分割的方法(java字符串切割方法)
-
技术背景在Java编程中,经常需要对字符串进行分割操作,例如将一个包含多个信息的字符串按照特定的分隔符拆分成多个子字符串。常见的应用场景包括解析CSV文件、处理网络请求参数等。实现步骤1.使用Str...
- 因为一个函数strtok踩坑,我被老工程师无情嘲笑了
-
在用C/C++实现字符串切割中,strtok函数经常用到,其主要作用是按照给定的字符集分隔字符串,并返回各子字符串。但是实际上,可不止有strtok(),还有strtok、strtok_s、strto...
- 一周热门
- 最近发表
- 标签列表
-
- ps像素和厘米换算 (32)
- ps图案在哪里 (33)
- super().__init__ (33)
- python 获取日期 (34)
- 0xa (36)
- super().__init__()详解 (33)
- python安装包在哪里找 (33)
- linux查看python版本信息 (35)
- python怎么改成中文 (35)
- php文件怎么在浏览器运行 (33)
- eval在python中的意思 (33)
- python安装opencv库 (35)
- python div (34)
- sticky css (33)
- python中random.randint()函数 (34)
- python去掉字符串中的指定字符 (33)
- python入门经典100题 (34)
- anaconda安装路径 (34)
- yield和return的区别 (33)
- 1到10的阶乘之和是多少 (35)
- python安装sklearn库 (33)
- dom和bom区别 (33)
- js 替换指定位置的字符 (33)
- python判断元素是否存在 (33)
- sorted key (33)