nginx-rtmp-module 支持 Enhancing RTMP HEVC(H.265)
Enhancing RTMP, FLV 2023年7月31号正式发布,主要支持了HEVC(H.265)、VP9、AV1视频编码,发布差不多半年了,很多开源项目已支持,最近打算播放和推送端也支持下,想找个支持的rtmp server方便测试用,但没找到合适的。干脆自己改改nginx-rtmp-module代码,做个基本的支持,能正常推送和播放Enhancing RTMP H265就好。
Enhancing RTMP细节直接看标准文档,网上能下载到,关键信息就几页, 看起来也快,这里就不再重复说细节了,直接贴下我改的nginx-rtmp-module代码:
/**
** ngx_rtmp_codec_module.h
** 这个文件要改,修改的地方我加了注释,方便参考,问题沟通qq:1130758427, 微信:ldxevt
**//** Copyright (C) Roman Arutyunyan*/#ifndef _NGX_RTMP_CODEC_H_INCLUDED_
#define _NGX_RTMP_CODEC_H_INCLUDED_#include <ngx_config.h>
#include <ngx_core.h>
#include "ngx_rtmp.h"/* Audio codecs */
enum {/* Uncompressed codec id is actually 0,* but we use another value for consistency */NGX_RTMP_AUDIO_UNCOMPRESSED = 16,NGX_RTMP_AUDIO_ADPCM = 1,NGX_RTMP_AUDIO_MP3 = 2,NGX_RTMP_AUDIO_LINEAR_LE = 3,NGX_RTMP_AUDIO_NELLY16 = 4,NGX_RTMP_AUDIO_NELLY8 = 5,NGX_RTMP_AUDIO_NELLY = 6,NGX_RTMP_AUDIO_G711A = 7,NGX_RTMP_AUDIO_G711U = 8,NGX_RTMP_AUDIO_AAC = 10,NGX_RTMP_AUDIO_SPEEX = 11,NGX_RTMP_AUDIO_MP3_8 = 14,NGX_RTMP_AUDIO_DEVSPEC = 15,
};/* Video codecs */
enum {NGX_RTMP_VIDEO_JPEG = 1,NGX_RTMP_VIDEO_SORENSON_H263 = 2,NGX_RTMP_VIDEO_SCREEN = 3,NGX_RTMP_VIDEO_ON2_VP6 = 4,NGX_RTMP_VIDEO_ON2_VP6_ALPHA = 5,NGX_RTMP_VIDEO_SCREEN2 = 6,NGX_RTMP_VIDEO_H264 = 7,
};/**********************************************/
/***下面是Enhancing RTMP加的, 2024-01-25****/#define FLV_EX_VIDEO_HEADER_MASK (0x80)
#define FLV_EX_VIDEO_FRAME_TYPE_MASK (0x70)
#define FLV_EX_VIDEO_PACKET_TYPE_MASK (0xf)enum {FLV_EX_VIDEO_PACKET_TYPE_SEQUENCE_START = 0,FLV_EX_VIDEO_PACKET_TYPE_CODED_FRAMES = 1,FLV_EX_VIDEO_PACKET_TYPE_SEQUENCE_END = 2,FLV_EX_VIDEO_PACKET_TYPE_CODED_FRAMESX = 3,FLV_EX_VIDEO_PACKET_TYPE_META_DATA = 4,FLV_EX_VIDEO_PACKET_TYPE_MPEG2TS_SEQUENCE_START = 5,
};#define FLV_EX_VIDEO_FOURCC_AV1 NT_MAKE_FOURCC('a', 'v', '0', '1')
#define FLV_EX_VIDEO_FOURCC_VP9 NT_MAKE_FOURCC('v', 'p', '0', '9')
#define FLV_EX_VIDEO_FOURCC_HEVC NT_MAKE_FOURCC('h', 'v', 'c', '1')static ngx_inline ngx_int_t
ngx_rtmp_get_ex_video_packet_type(ngx_chain_t *in) {return in->buf->pos[0] & FLV_EX_VIDEO_PACKET_TYPE_MASK;
}static ngx_inline ngx_int_t
ngx_rtmp_is_ex_video_codec_header(ngx_chain_t *in) {return FLV_EX_VIDEO_PACKET_TYPE_SEQUENCE_START == ngx_rtmp_get_ex_video_packet_type(in);
}static ngx_inline ngx_int_t
ngx_rtmp_get_ex_video_frame_type(ngx_chain_t *in) {const uint8_t v = in->buf->pos[0];const uint8_t packet_type = v&FLV_EX_VIDEO_PACKET_TYPE_MASK;if (FLV_EX_VIDEO_PACKET_TYPE_META_DATA == packet_type)return 0;return (v&FLV_EX_VIDEO_FRAME_TYPE_MASK) >> 4;
}/***上面是Enhancing RTMP加的, 2024-01-25****/
/**********************************************/u_char * ngx_rtmp_get_audio_codec_name(ngx_uint_t id);
u_char * ngx_rtmp_get_video_codec_name(ngx_uint_t id);typedef struct {ngx_uint_t width;ngx_uint_t height;ngx_uint_t duration;ngx_uint_t frame_rate;ngx_uint_t video_data_rate;ngx_uint_t video_codec_id;ngx_uint_t audio_data_rate;ngx_uint_t audio_codec_id;ngx_uint_t aac_profile;ngx_uint_t aac_chan_conf;ngx_uint_t aac_sbr;ngx_uint_t aac_ps;ngx_uint_t avc_profile;ngx_uint_t avc_compat;ngx_uint_t avc_level;ngx_uint_t avc_nal_bytes;ngx_uint_t avc_ref_frames;ngx_uint_t sample_rate; /* 5512, 11025, 22050, 44100 */ngx_uint_t sample_size; /* 1=8bit, 2=16bit */ngx_uint_t audio_channels; /* 1, 2 */u_char profile[32];u_char level[32];ngx_chain_t *hevc_header; /*这里HEVC Enhancing RTMP 2024-01-25*/ngx_chain_t *avc_header;ngx_chain_t *aac_header;ngx_chain_t *meta;ngx_uint_t meta_version;
} ngx_rtmp_codec_ctx_t;extern ngx_module_t ngx_rtmp_codec_module;#endif /* _NGX_RTMP_LIVE_H_INCLUDED_ *//***** ngx_rtmp_codec_module.h 文件结束****//**
** ngx_rtmp_codec_module.c
** 这个文件代码较多,就贴下改过的地方,问题沟通qq:1130758427, 微信:ldxevt
**//** Copyright (C) Roman Arutyunyan*/static ngx_int_t
ngx_rtmp_codec_disconnect(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,ngx_chain_t *in)
{ngx_rtmp_codec_ctx_t *ctx;ngx_rtmp_core_srv_conf_t *cscf;ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);if (ctx == NULL) {return NGX_OK;}cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module);/*** Enhancing RTMP 修改 2024-01-25***/if (ctx->hevc_header) {ngx_rtmp_free_shared_chain(cscf, ctx->hevc_header);ctx->hevc_header = NULL;}if (ctx->avc_header) {ngx_rtmp_free_shared_chain(cscf, ctx->avc_header);ctx->avc_header = NULL;}if (ctx->aac_header) {ngx_rtmp_free_shared_chain(cscf, ctx->aac_header);ctx->aac_header = NULL;}if (ctx->meta) {ngx_rtmp_free_shared_chain(cscf, ctx->meta);ctx->meta = NULL;}return NGX_OK;
}static ngx_int_t
ngx_rtmp_codec_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,ngx_chain_t *in)
{ngx_rtmp_core_srv_conf_t *cscf;ngx_rtmp_codec_ctx_t *ctx;ngx_chain_t **header;uint8_t fmt;ngx_int_t is_ex_video_header; /*Enhancing RTMP 2024-01-25*/static ngx_uint_t sample_rates[] ={ 5512, 11025, 22050, 44100 };if (h->type != NGX_RTMP_MSG_AUDIO && h->type != NGX_RTMP_MSG_VIDEO) {return NGX_OK;}ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);if (ctx == NULL) {ctx = ngx_pcalloc(s->connection->pool, sizeof(ngx_rtmp_codec_ctx_t));ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_codec_module);}/* save codec */if (in->buf->last - in->buf->pos < 1) {return NGX_OK;}fmt = in->buf->pos[0];if (h->type == NGX_RTMP_MSG_AUDIO) {is_ex_video_header = 0; /*Enhancing RTMP 2024-01-25*/ctx->audio_codec_id = (fmt & 0xf0) >> 4;ctx->audio_channels = (fmt & 0x01) + 1;ctx->sample_size = (fmt & 0x02) ? 2 : 1;if (ctx->sample_rate == 0) {ctx->sample_rate = sample_rates[(fmt & 0x0c) >> 2];}} else {/*Enhancing RTMP 2024-01-25*/if (fmt & FLV_EX_VIDEO_HEADER_MASK)is_ex_video_header = 1;else {is_ex_video_header = 0;ctx->video_codec_id = (fmt & 0x0f);}}/*Enhancing RTMP 2024-01-25*/if (!is_ex_video_header) {/* save AVC/AAC header */if (in->buf->last - in->buf->pos < 3) {return NGX_OK;}} else {if (in->buf->last - in->buf->pos < 5)return NGX_OK;const uint8_t* pos = in->buf->pos + 1;ctx->video_codec_id = NT_MAKE_FOURCC(pos[0], pos[1], pos[2], pos[3]);}/*Enhancing RTMP 2024-01-25*//* no conf */if (!is_ex_video_header) {if (!ngx_rtmp_is_codec_header(in))return NGX_OK;} else {if (!ngx_rtmp_is_ex_video_codec_header(in))return NGX_OK;}cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module);header = NULL;if (h->type == NGX_RTMP_MSG_AUDIO) {if (ctx->audio_codec_id == NGX_RTMP_AUDIO_AAC) {header = &ctx->aac_header;ngx_rtmp_codec_parse_aac_header(s, in);}} else {/*Enhancing RTMP 2024-01-25*/const ngx_uint_t codec_id = ctx->video_codec_id;if (NGX_RTMP_VIDEO_H264 == codec_id) {header = &ctx->avc_header;ngx_rtmp_codec_parse_avc_header(s, in);}else if (FLV_EX_VIDEO_FOURCC_HEVC == codec_id) {header = &ctx->hevc_header;ngx_rtmp_codec_parse_hevc_header(s, in);}else if (FLV_EX_VIDEO_FOURCC_AV1 == codec_id) {}else if (FLV_EX_VIDEO_FOURCC_VP9 == codec_id) {}}if (header == NULL) {return NGX_OK;}if (*header) {ngx_rtmp_free_shared_chain(cscf, *header);}*header = ngx_rtmp_append_shared_bufs(cscf, NULL, in);return NGX_OK;
}u_char *
ngx_rtmp_get_video_codec_name(ngx_uint_t id)
{/*Enhancing RTMP 2024-01-25*/if (FLV_EX_VIDEO_FOURCC_HEVC == id)return (u_char*)"HEVC";else if (FLV_EX_VIDEO_FOURCC_AV1 == id)return (u_char*)"AV1";else if (FLV_EX_VIDEO_FOURCC_VP9 == id)return (u_char*)"VP9";return (u_char *)(id < sizeof(video_codecs) / sizeof(video_codecs[0])? video_codecs[id]: "");
}/***** ngx_rtmp_codec_module.c 文件结束****/
另外rtmp直播还要修改ngx_rtmp_live_module.c, flv录像支持需修改ngx_rtmp_record_module.c, 支持转hls要修改ngx_rtmp_hls_module.c和ngx_rtmp_mpegts.c,根据实际需求改下代码就好。
改好重新编译运行,推送播放效果:

简单改改已经满足我的测试需求, 有问题请联系qq: 1130758427, 微信:ldxevt。
相关文章:
nginx-rtmp-module 支持 Enhancing RTMP HEVC(H.265)
Enhancing RTMP, FLV 2023年7月31号正式发布,主要支持了HEVC(H.265)、VP9、AV1视频编码,发布差不多半年了,很多开源项目已支持,最近打算播放和推送端也支持下,想找个支持的rtmp server方便测试用,但没找到合…...
2024最新JDK1.8+JDK17+JDK21安装包下载+文档
2024年更新,JDK8的64位和32位安装包都有,Java8最新文档也有,JDK17和JDK21的最新安装包也有 因为网上的安装包都不是最新的,所以自己去Oracle官网登录下载保存了一份,需要的朋友下面网盘链接下载 JDK8—64位安装程序&…...
如何利用chatgpt提升工作效率
chatgpt全领域小助手 项目管理:制定项目计划、跟踪进度、分配任务和记录里程碑。客户服务:回答常见问题、提供产品支持和处理客户投诉,提升客户满意度。销售支持:提供销售培训、销售脚本和客户资料,辅助销售团队进行销…...
WinSCP下载安装并实现远程SSH本地服务器上传文件
文章目录 1. 简介2. 软件下载安装:3. SSH链接服务器4. WinSCP使用公网TCP地址链接本地服务器5. WinSCP使用固定公网TCP地址访问服务器 1. 简介 Winscp是一个支持SSH(Secure SHell)的可视化SCP(Secure Copy)文件传输软件,它的主要功能是在本地与远程计…...
QEMU搭建arm虚拟机开发环境
获取QEMU代码 git clone https://gitlab.com/qemu-project/qemu.git 切换对应的工程分支 使用git指令切换到对应的分支上,我这里使用的是stable-4.0的分支 git checkout -b stable-4.0 remotes/origin/stable-4.0 配置&编译 在工程的根目录下执行 ./conf…...
web 应用常见的安全问题
一xss攻击 人们经常将跨站脚本攻击(Cross Site Scripting)缩写为CSS,但这会与层叠样式表(Cascading Style Sheets,CSS)的缩写混淆。因此,有人将跨站脚本攻击缩写为XSS。 跨站脚本攻击ÿ…...
502. IPO
502. IPO 题目链接:502. IPO 代码如下: //堆的使用 class Solution { public:int findMaximizedCapital(int k, int w, vector<int>& profits, vector<int>& capital) {vector<pair<int,int>> mp;//优先队列默认的是大…...
如何安装MeterSphere并实现无公网ip远程访问服务管理界面
文章目录 前言1. 安装MeterSphere2. 本地访问MeterSphere3. 安装 cpolar内网穿透软件4. 配置MeterSphere公网访问地址5. 公网远程访问MeterSphere6. 固定MeterSphere公网地址 正文开始前给大家推荐个网站,前些天发现了一个巨牛的 人工智能学习网站, 通…...
做FP独立站怎么引流?这个引流法宝收好了!
近年来,由于卖家数量飙升导致平台竞争持续升级,卖家之间的恶性循环竞争以及平台政策的不断调整等,造成了众多亚马逊等跨境卖家纷纷从平台转向独立站。可是,转型做独立站前要先考虑清楚独立站与平台二者之间的区别。 如果在第三方平…...
幻兽帕鲁PalWorld服务器搭建教程,1分钟开服,纯小白教程,无需基础
雨云面板服快速开幻兽帕鲁PalWorld服务器的教程,配置文件修改方法和配置项中文注释。 最近这游戏挺火,很多人想跟朋友联机,如果有专用服务器,就不需要房主一直开着电脑,稳定性也好得多。 幻兽帕鲁简介 《幻兽帕鲁》…...
算法小抄01
1. 计数排序是一种基于 统计 的排序算法 2. 基于比较的排序算法有:(1)直接插入排序;(2)冒泡排序;(3)简单选择排序;(4)希尔排序&#…...
Spring Boot 集成 API 文档 - Swagger、Knife4J、Smart-Doc
文章目录 1.OpenAPI 规范2.Swagger: 接口管理的利器3.Swagger 与 SpringFox:理念与实现4.Swagger 与 Knife4J:增强与创新5.案例:Spring Boot 整合 Swagger35.1 引入 Swagger3 依赖包5.2 优化路径匹配策略兼容 SpringFox5.3 配置 Swagger5.4 S…...
2024年软考报名时间及条件,小白必看
不少考生开始准备报名2024年软件水平考试,那么报名软考有没有学历、专业以及工作经验等方面的限制呢?今天就给大家梳理下2024年软考考试,若有变更,也会及时更新内容。 免费送备考资料。联系我 2024年软考考试时间 2024年软考有两次考试&a…...
vue 跨域XMLHttpRequest
vue 跨域 使用XMLHttpRequest 亲测好使 let url=http://127.0.0.1:9000/pssnotifyyb?b=1//url=https://api.j4u.ink/v1/store/other/proxy/remote/moyu.jsonvar xhr=new XMLHttpRequest()xhr.open(GET,url,true)//第三个参数是是否异步请求,默认true xhr.onreadyst…...
【正点原子STM32】STM32基础知识(F1F4F7H7 STM32系统框架、寻址范围、存储器映射的存储器功能划分、寄存器映射)
一、STM32系统框架 1.1、Cortex M内核 & 芯片1.2、F1系统架构1.3、F4系统架构1.4、F7系统架构1.5、H7系统架构 二、STM32的寻址范围? 三、存储器映射 存储器功能划分(F1为例)STM32F1存储器映射图 四、寄存器映射 寄存器基础知识STM3…...
Oracle、MySQL数据库常规命令语法-简易记录(非常规持续更新)
前言:呈现的是非常基础必备命令以及常规关联语法,因涉及到不同数据库其表达都会有所区别,此篇纯属做个仓库记录更非常规持续更新,专业人士可忽略,且看且珍惜… MySQL: 关系型数据库、重点开源、支持大型规模、标准SQL数据语言、多平台多架构、高可用集群、可定制开发等等、…...
用react搞定一个大模型对话效果
怎么用react实现一个类似文心一言那样的对话效果呢? 最近AI盛行,关注几个大模型网站都能发现,跟AI对话的时候,返回的文本是逐字展示的,就给人一种AI边解析边返回的感觉(不知道是为了装X还是真的需要这样&a…...
DP读书:在常工院的2023年度总结
DarrenPig的年度总结 这是最好的时代,这是最坏的时代。——狄更斯 这是最好的时代,这是最坏的时代。——狄更斯 这是最好的时代,这是最坏的时代。——狄更斯 一、2023我的感受 不就是2023吗,不就是一年的经历吗,大家…...
2023-2024年重庆职业院校技能大赛“信息安全管理与评估”比赛样题
2023 年重庆职业院校技能大赛(高等职业教育) “信息安全管理与评估”样题任务书 第一阶段:任务 1 网络平台搭建(50 分)任务 2 网络安全设备配置与防护(250 分) 第二阶段:第一部分 网…...
【Ubuntu】systemctl 命令
systemctl 是一个用于检视和控制 systemd 系统和服务管理器的命令行工具。systemd 是用于启动、停止和管理 Linux 系统中的服务的守护进程。以下是一些常用的 systemctl 命令及其说明: systemctl start <unit>: 启动指定的服务单元 systemctl start sshd sy…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
tomcat指定使用的jdk版本
说明 有时候需要对tomcat配置指定的jdk版本号,此时,我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...
CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!
本文介绍了一种名为AnomalyAny的创新框架,该方法利用Stable Diffusion的强大生成能力,仅需单个正常样本和文本描述,即可生成逼真且多样化的异常样本,有效解决了视觉异常检测中异常样本稀缺的难题,为工业质检、医疗影像…...
通过MicroSip配置自己的freeswitch服务器进行调试记录
之前用docker安装的freeswitch的,启动是正常的, 但用下面的Microsip连接不上 主要原因有可能一下几个 1、通过下面命令可以看 [rootlocalhost default]# docker exec -it freeswitch fs_cli -x "sofia status profile internal"Name …...
