nginx-rtmp-module 支持 Enhancing RTMP HEVC(H.265)

2024-01-25 23:36

本文主要是介绍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)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/644990

相关文章

SpringKafka消息发布之KafkaTemplate与事务支持功能

《SpringKafka消息发布之KafkaTemplate与事务支持功能》通过本文介绍的基本用法、序列化选项、事务支持、错误处理和性能优化技术,开发者可以构建高效可靠的Kafka消息发布系统,事务支... 目录引言一、KafkaTemplate基础二、消息序列化三、事务支持机制四、错误处理与重试五、性能优

如何自定义Nginx JSON日志格式配置

《如何自定义NginxJSON日志格式配置》Nginx作为最流行的Web服务器之一,其灵活的日志配置能力允许我们根据需求定制日志格式,本文将详细介绍如何配置Nginx以JSON格式记录访问日志,这种... 目录前言为什么选择jsON格式日志?配置步骤详解1. 安装Nginx服务2. 自定义JSON日志格式各

Python中ModuleNotFoundError: No module named ‘timm’的错误解决

《Python中ModuleNotFoundError:Nomodulenamed‘timm’的错误解决》本文主要介绍了Python中ModuleNotFoundError:Nomodulen... 目录一、引言二、错误原因分析三、解决办法1.安装timm模块2. 检查python环境3. 解决安装路径问题

Nginx指令add_header和proxy_set_header的区别及说明

《Nginx指令add_header和proxy_set_header的区别及说明》:本文主要介绍Nginx指令add_header和proxy_set_header的区别及说明,具有很好的参考价... 目录Nginx指令add_header和proxy_set_header区别如何理解反向代理?proxy

Nginx配置location+rewrite实现隐性域名配置

《Nginx配置location+rewrite实现隐性域名配置》本文主要介绍了Nginx配置location+rewrite实现隐性域名配置,包括基于根目录、条件和反向代理+rewrite配置的隐性... 目录1、配置基于根目录的隐性域名(就是nginx反向代理)2、配置基于条件的隐性域名2.1、基于条件

Ubuntu中Nginx虚拟主机设置的项目实践

《Ubuntu中Nginx虚拟主机设置的项目实践》通过配置虚拟主机,可以在同一台服务器上运行多个独立的网站,本文主要介绍了Ubuntu中Nginx虚拟主机设置的项目实践,具有一定的参考价值,感兴趣的可... 目录简介安装 Nginx创建虚拟主机1. 创建网站目录2. 创建默认索引文件3. 配置 Nginx4

Nginx如何进行流量按比例转发

《Nginx如何进行流量按比例转发》Nginx可以借助split_clients指令或通过weight参数以及Lua脚本实现流量按比例转发,下面小编就为大家介绍一下两种方式具体的操作步骤吧... 目录方式一:借助split_clients指令1. 配置split_clients2. 配置后端服务器组3. 配

Nginx实现前端灰度发布

《Nginx实现前端灰度发布》灰度发布是一种重要的策略,它允许我们在不影响所有用户的情况下,逐步推出新功能或更新,通过灰度发布,我们可以测试新版本的稳定性和性能,下面就来介绍一下前端灰度发布的使用,感... 目录前言一、基于权重的流量分配二、基于 Cookie 的分流三、基于请求头的分流四、基于请求参数的分

一文教你解决Python不支持中文路径的问题

《一文教你解决Python不支持中文路径的问题》Python是一种广泛使用的高级编程语言,然而在处理包含中文字符的文件路径时,Python有时会表现出一些不友好的行为,下面小编就来为大家介绍一下具体的... 目录问题背景解决方案1. 设置正确的文件编码2. 使用pathlib模块3. 转换路径为Unicod

一文详解Nginx的强缓存和协商缓存

《一文详解Nginx的强缓存和协商缓存》这篇文章主要为大家详细介绍了Nginx中强缓存和协商缓存的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、强缓存(Strong Cache)1. 定义2. 响应头3. Nginx 配置示例4. 行为5. 适用场景二、协商缓存(协