众所周知的原因原生的RTMP只支持H264 并不支持H265的传输,之前的项目基于海思3531DV200平台的多路输入 多路输出 基于FFMpeg 拉RTSP的流 然后通过海思硬件解码然后在编码成较小的分辨率 通过RTMP推流到服务器端 项目已经基本结束。
然后领导 要求要实现RTMP H265的实现。从上周五2021.12.03 接到这个任务,到今天12.10正好一星期 已经基本上实现。中间穿插了一些其他的杂事。下面来说说这个过程吧 。
之前测试的都是3531拉流推流 到Nginx 或者SRS服务器 然后用VLC测试播放 H264的时候,一点问题都没有。
换成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 直接下载下来 参考说明文件编译即可
加速连接 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源码 以便于支持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
首先 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了说明正常