众所周知的原因原生的RTMP只支持H264 并不支持H265的传输,之前的项目基于海思3531DV200平台的多路输入 多路输出 基于FFMpeg 拉RTSP的流 然后通过海思硬件解码然后在编码成较小的分辨率 通过RTMP推流到服务器端 项目已经基本结束。
然后领导 要求要实现RTMP H265的实现。从上周五2021.12.03 接到这个任务,到今天12.10正好一星期 已经基本上实现。中间穿插了一些其他的杂事。下面来说说这个过程吧 。
之前测试的都是3531拉流推流 到Nginx 或者SRS服务器 然后用VLC测试播放 H264的时候,一点问题都没有。
提示:不想折腾的可以直接点击下面 已经改好的 源代码 直接下下来编译就可以
播放端ffplay 需要SDL的支持 需要安装SDL ubunt可以直接apt安装 windows下需要 编译安装
下载完之后有三个文件夹 对应推流端 服务器端 播放端
1.ffmpeg 直接执行./build.sh脚本 之后 install make install(需要提前安装SDL)
2.SRS 直接执行trunk目录下的build.sh脚本 make 之后 需要的操作如下:
让配置生效
./objs/srs -c conf/srs.conf
srs 运行
./etc/init.d/srs start
在运行过程中查看log
tail -f ./objs/srs.log
停止srs服务器
./etc/init.d/srs stop
重新打开srs服务器
./etc/init.d/srs restart
3.推流端需要打开宏 QMCY_ADD_H265_SUPPORT
然后直接调用srs_h265_write_raw_frames 函数就可以
如有问题 可以留言讨论
先看效果图 ubunt 直接用ffplay播放 h265的rtmp流
换成H265之后都有问题了
1.首先是推流端 用的是srs_librtmp.cpp那个开源库
H264发送的时候很简单 调用如下代码即可
nRet = srs_h264_write_raw_frames(rtmp_handle, packet.data, packet.size, video_dts, video_dts);
H265就要自己扩展了 网上搜了下 参考
实现如下接口
nRet = srs_h265_write_raw_frames(rtmp_handle, packet.data, packet.size, video_dts, video_dts);
基本上是参照 别人的代码来修改的 别人的是 很多个源文件的代码 ,我这只有一个源文件,所以需要自己慢慢搜索 慢慢添加进来 。做完这一步之后 并不知道 有没有问题 。需要最终能播放出来没问题 才能验证。修改地方挺多的 但是感觉很多地方没有用到 因为 我们只需要推流
2.服务器端。现在服务器基本上就是nginx和srs两种,网上搜了下有个PingOS 已经实现nginx支持H265的RTMP 直接下载下来 参考说明文件编译即可
github地址如下
GitHub - pingostack/pingos: Based on the NGINX/RTMP/HTTP-FLV/HTTP-TS/HLS/HLS+/DASH/H.264/H.265/AAC/MP3/Live/Record/VOD/Push/Pull/Multiple Processes/Dynamic Configuration/Configuration Variables/Console Interface/Notify
加速连接 mirrors / pingostack / pingos · CODE CHINA (gitcode.net)
下载完如下操作 即可
./release.sh -i # 启动服务 cd /usr/local/pingos/ ./sbin/nginx
由于我的服务器端都是装在虚拟机上的 后来测试发现,nginx的话,正常推流过程中 我把虚拟机suspend挂起 注意不是关机 ,过一段时间再打开,发现推流虽然正常 但是 流不能正常播放。
查看logs目录下的error.log会打印live:already publishing 网上搜了下说要做如下修改
(借用另一位博主的图片)
加上这个so_keepalive 但是我试了没有用 不知道为啥 但是srs就不会
后来就尝试srs 需要修改srs源码 以便于支持h265的rmtp 我用的版本是4.0 差别应该不大
修改就两个文件 一个是 srs_kernel_codec.cpp 和srs_kernel_codec.hpp
头文件增加如下定义
cpp中修改如下
很简单这样就可以了
3.播放端 。网上搜了很多关于rmpt支持h265的文章 播放端基本上都是说要用大牛的播放器
由于大牛的播放器在github 我下了四五次 每次下载的大小都不一样 ,最后 加速站点下下来,发现有1个多G ,之前 github直接下的时候 有的 几十MB 有的时候100多MB 反正每次提示成功 但是大小都不一样 。
我下下来之后 反正 不能用 无论是 推流那个exe 还是播放器那个exe 都不能用 ,后来顺着软件上的联系方式 加了QQ群 ,说是要 付费的 具体我也不太清楚原因 ,总之 大牛的播放器 这条路失败。
然后不知道怎么想的 还是 搜什么搜到的 发现 可以直接修改FFMpeg 源码 ,测试发现可行 。
当然过程肯定会遇到各种坑 。下面 我就直接贴修改的地方吧 我的FFMpeg版本是4.3.2
重要提示:ffplay需要SDL的支持,所以如果要编译出来ffplay 需要先安装或者编译SDL之后再进行此操作。另外这里编译出来的ffplay只能在ubuntu系统系播放,windows系统的话请参考我的另一边文章:
windows下支持H265的rtmp ffmpeg播放器 ffmpeg的编译_baoecit的博客-CSDN博客
回归正题
首先 ffmpeg下建一个脚本build.sh什么的 (我有时候需要编译arm版本,这样便于管理)
比如 arm版本我会这么写
ubuntu修改版本我会这么写(enable-rtmp_h265 是我自己为了给修改的地方增加宏自己定义的)
修改方式为打开configure文件。找到CONFIG_LIST关键字 添加自己定义的名字 如下图
保存 之后 配置的时候添加 --enable-rtmp_h265 或者--disable-rtmp_h265
执行build.sh脚本之后可以去ffbuild目录下查看 我的就是如下了 之后可以在代码里面使用这个宏就可以
涉及到修改的文件如下 flv.h flvdec.c flvenc.c
头文件修改的地方 增加
flvdec.c文件修改如下
flv_set_video_codec函数
flv_read_packet函数
接下来是flvenc.c文件
flv_write_codec_header函数修改如下
flv_write_trailer函数修改如下:
接下来是flv_write_packet函数
修改完毕 直接 编译就可以 没问题的话 生成的ffmpeg 就可以推送 支持h265rtmp ffplay用来播放
由于推送端我使用3531板子来做的 所以我只需要ffplay就可以
看下结果吧 :可以发现 stream video 那里的编码已经是hevc了说明正常