ffmpeg扩展支持H265视频流的flv封装
由于Adobe暂停了对RTMP/FLV标准的更新,所以目前标准中没有支持HEVC视频编码格式。为避免各终端和服务器间的兼容性问题,FFmpeg也没有在RTMP/FLV的协议实现中进行HEVC的相关扩展。CDN联盟制定了相关的协议扩展规范,并在FFmpeg中完成了相关代码实现,本文主要介绍如何让ffmpeg扩展支持HEVC视频编码格式的HTTP-FLV流媒体协议。
flv协议扩展支持HEVC
有关FLV协议介绍参照文章:HTTP FLV交互流程及实例解析
有关ffmpeg介绍参照文章:音视频领域强大的辅助工具-ffmpeg常用操作介绍
为推进HEVC视频编码格式在直播方案中的落地,CDN联盟规范了HEVC在RTMP/FLV中的扩展,在支持HEVC的VideoTagHeader
FLV协议扩展支持HEVC
- 支持HEVC的VideoTagHeader扩展,扩展后的格式如下图所示:
其中修改了如下部分:
- CodecID :定义HEVC格式的值为12
- HEVCPacketType :当CodecID=12时,AVCPacketType改为HEVCPacketType;其中HEVCPacketType=0,表示HEVCVIDEOPACKET中存放的是HEVC sequence header;HEVCPacketType=1,表示HEVCVIDEOPACKET中存放的是HEVC NALU;HEVCPacketType=2,表示HEVCVIDEPACKET中存放的是HEVC end of sequence,即HEVCDecoderConfigurationRecord
- CompositionTime:当CodecID=12时,也需要CompositionTime
- 支持HEVC的VideoTagBody扩展,扩展后的格式如下:
当CodecID为12时,VideoTagBody中存放的就是HEVC视频帧内容
ffmpeg扩展支持HEVC flv封装源码修改
FLV的解复用和复用功能代码分别在libavformt/flvdec.c和libavformat/flvenc.c中,扩展后的修改也都集中在这两个文件。
- 编码类型的枚举扩展
修改文件libavformat/flv.h,修改如下,CodecId增加FLV_CODECID_HEVC:
enum {
FLV_CODECID_H263 = 2,
FLV_CODECID_SCREEN = 3,
FLV_CODECID_VP6 = 4,
FLV_CODECID_VP6A = 5,
FLV_CODECID_SCREEN2 = 6,
FLV_CODECID_H264 = 7,
FLV_CODECID_REALH263= 8,
FLV_CODECID_MPEG4 = 9,
FLV_CODECID_HEVC = 12,
};
- flv解复用修改
HEVCPacketType=0时,表示HEVCVIDEOPACKET中存放的是HEVC sequence header,也就是HEVCDecoderConfigurationRecord,解码时需设置HEVCDecoderConfigurationRecord方能正确解码,在读取Video Tag的地方增加AV_CODEC_ID_HEVC的判断条件。
修改文件libavformt/flvdec.c,修改内容如下,
if (st->codecpar->codec_id == AV_CODEC_ID_AAC ||
st->codecpar->codec_id == AV_CODEC_ID_H264 ||
st->codecpar->codec_id == AV_CODEC_ID_HEVC ||
st->codecpar->codec_id == AV_CODEC_ID_MPEG4) {
int type = avio_r8(s->pb);
size--;
if (st->codecpar->codec_id == AV_CODEC_ID_H264 ||
st->codecpar->codec_id == AV_CODEC_ID_HEVC ||
st->codecpar->codec_id == AV_CODEC_ID_MPEG4) {
// sign extension
int32_t cts = (avio_rb24(s->pb) + 0xff800000) ^ 0xff800000;
pts = dts + cts;
if (cts< 0) { // dts might be wrong
if (!flv->wrong_dts)
av_log(s, AV_LOG_WARNING,
"Negative cts, previous timestamps might be wrong.\n");
flv->wrong_dts = 1;
} else if (FFABS(dts - pts) > 1000*60*15) {
av_log(s, AV_LOG_WARNING,
"invalid timestamps %"PRId64" %"PRId64"\n", dts, pts);
dts = pts = AV_NOPTS_VALUE;
}
}
if (type == 0 &&(!st->codecpar->extradata ||
st->codecpar->codec_id == AV_CODEC_ID_AAC ||
st->codecpar->codec_id == AV_CODEC_ID_HEVC ||
st->codecpar->codec_id == AV_CODEC_ID_H264)) {
AVDictionaryEntry *t;
if (st->codecpar->extradata) {
if ((ret = flv_queue_extradata(flv, s->pb, stream_type, size)) < 0)
return ret;
ret = FFERROR_REDO;
goto leave;
}
if ((ret = flv_get_extradata(s, st, size)) < 0)
return ret;
……
}
}
3.flv复用修改
主要修改header、packet、trailer,修改文件libavformat/flvenc.c,改动就多,需改后文件直接从如下连接获取:
https://github.com/ksvc/FFmpeg
本文也是基于他们整理的资料进行编译打包。
ffmpeg扩展修改后编译安装步骤
测试环境为:centos 7 x86-64
- 下载x265并编译:
wget http://ftp.videolan.org/pub/videolan/x265/x265_3.2.tar.gz
tar -zxvf x265_3.2.tar.gz
./make-Makefiles.bash
make
make install
pkg-config --list-all #查看x265是否安装成功
- 编译修改后的ffmpeg
从上面的github中下在源码,编译过程如下:
#下载修改后的ffmpeg,解压,https://github.com/ksvc/FFmpeg/archive/refs/tags/n3.3.2.tar.gz
# 编译步骤如下:
./configure --enable-shared --enable-libx264 --enable-gpl --enable-libx265
make&make install
ffmpeg version # 查看是否编译成功
- 测试验证
通过如下命令测试,看是否能够成功,参照文章《使用nginx搭建HTTP FLV流媒体服务器》搭建http-flv服务器。
找到一个HEVC的rtsp视频连接,输入如下命令,看是否能够正常打包flv。
ffmpeg -i rtsp://admin:@******@10.45.13.236/h265/ch1/main/av_stream -vcodec copy -acodec copy -f flv rtmp://127.0.0.1:1935/live/test
(备注,nginx的rtmp扩展模块开源版本并不支持H265的HTTP-FLV协议,需要花钱向开源的作者购买补丁才行,如需要测试,可安装SRS流媒体服务器,这个已经支持了,后续文章会介绍)
后话
今天早上(2023-11-11)看到ffmpeg发布最新的版本6.1,已经增加了对flv h265的支持,有兴趣的可以直接下载官方最新的版本,试试是否已经支持flv h265格式,ffmpeg6.1版本安装包也可用过关注公众号:壹零**仓,发送消息:软件工具 获取。
安装步骤如下:
tar -jxvf ffmpeg-6.1.tar.gz
./configure --enable-shared --prefix=/usr/ffmpeg
make & make install
vi /etc/profile
# 增加ffmpeg执行路径的环境变量:
PATH=$PATH:/usr/ffmpeg/bin
export PATH
# 使环境变量生效:
source /etc/profile
vi /etc/ld.so.conf
# 增加系统连接库路径:/usr/ffmpeg/lib/
# 生效
ldconfig
ffmpeg version
最新版本更新说明如下:
增加了 libaribcaption 解码器
增加 Playdate 视频 Decoder 和 Demuxer
增加了 afireqsrc 音频源滤镜
增加了 arls 音频滤镜
增加了 zoneplate 视频源滤镜
在 Windows 上扩展对 libva-win32 的 VAAPI 支持
在 setpts 和 asetpts 滤镜中支持命令
完善 Vulkan 解码硬件加速,支持 H264、HEVC 和 AV1
增加了 color_vulkan 滤镜
增加了 bwdif_vulkan 滤镜
增加了 nlmeans_vulkan 滤镜
增加了 RivaTuner 视频解码器
增加了 xfade_vulkan 滤镜
增加了 vMix 视频解码器
增加了 Essential Video Coding parser、muxer 和 demuxer
增加了 Essential Video Coding 帧合并 bsf
增加了 bwdif_cuda 滤镜
实现了 apsnr 和 asisdr 音频滤镜
增加了 Microsoft RLE 视频编码器
Raw AC-4 Muxer 和 Demuxer
Raw VVC bitstream parser、Muxer 和 Demuxer
增加了 用于编辑 VVC 流中metadata的bsf
将 VVC 从 MP4 转换为 Annex B 的 bitstream 滤镜
实现了 apsnr 和 asisdr 音频滤镜
实现了 videotoolbox 的 scale_vt 滤镜
实现了 videotoolbox 的 transpose_vt 滤镜
支持 P_SKIP 提示以加速 libx264 编码
在增强的 flv 格式中支持 HEVC、VP9、AV1 编解码器
实现了 OSQ复用器和解码器
在增强的rtmp协议中支持HEVC、VP9、AV1编解码器的fourcclist
实现了 CRI USM复用器
ffmpeg CLI的'-top'选项已弃用,推荐使用setfield过滤器
ffmpeg CLI选项:-readrate_initial_burst
完善了 VAAPI AV1编码器
ffprobe XML 输出模式已更改,以适应同一父元素内的多个可变字段元素
添加了ffprobe -output_format 选项,作为 -of 的别名
关注公众号:壹零仓,发送:flv,获取更多flv文章。