nginx_rtmp_module 之 ngx_rtmp_live_module模块

news2024/9/19 6:24:47

模块作用

直播模块代码 ngx_rtmp_live_module.c,主要作用是:当客户端推流或者拉流的时候,创建的rtmp session会加入到 live 模块的存储链表中。

模块配置命令

static ngx_command_t  ngx_rtmp_live_commands[] = {

    { ngx_string("live"),
      NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_flag_slot,
      NGX_RTMP_APP_CONF_OFFSET,
      offsetof(ngx_rtmp_live_app_conf_t, live),
      NULL },
    // 表示开启直播

    { ngx_string("stream_buckets"),
      NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_str_slot,
      NGX_RTMP_APP_CONF_OFFSET,
      offsetof(ngx_rtmp_live_app_conf_t, nbuckets),
      NULL },
    // 录制流名hash桶的大小

    { ngx_string("buffer"),
      NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_msec_slot,
      NGX_RTMP_APP_CONF_OFFSET,
      offsetof(ngx_rtmp_live_app_conf_t, buflen),
      NULL },
	// 设置默认缓冲区长度。通常客户端set_buflen在播放之前发送RTMP 命令,并重置此设置。默认是1000 ms。
    
    { ngx_string("sync"),
      NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
      ngx_rtmp_live_set_msec_slot,
      NGX_RTMP_APP_CONF_OFFSET,
      offsetof(ngx_rtmp_live_app_conf_t, sync),
      NULL },
    // 同步音频和视频流。如果订阅者带宽不足以以发布者速率接收数据,则服务器会丢弃一些帧。这就导致了同步问题。当时间戳差异超过sync参数指定的值时,将发送一个绝对帧来修复它。默认值是300ms。
    
    { ngx_string("interleave"),
      NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_flag_slot,
      NGX_RTMP_APP_CONF_OFFSET,
      offsetof(ngx_rtmp_live_app_conf_t, interleave),
      NULL },
	// 切换交错模式。在这种模式下,音频和视频数据在相同的RTMP块流上传输。默认为关闭。
    
    { ngx_string("wait_key"),
      NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_flag_slot,
      NGX_RTMP_APP_CONF_OFFSET,
      offsetof(ngx_rtmp_live_app_conf_t, wait_key),
      NULL },
	// 使视频流开始于关键帧。在某些情况下才会触发
    
    { ngx_string("wait_video"),
      NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_flag_slot,
      NGX_RTMP_APP_CONF_OFFSET,
      offsetof(ngx_rtmp_live_app_conf_t, wait_video),
      NULL },

    { ngx_string("publish_notify"),
      NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_flag_slot,
      NGX_RTMP_APP_CONF_OFFSET,
      offsetof(ngx_rtmp_live_app_conf_t, publish_notify),
      NULL },

    { ngx_string("play_restart"),
      NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_flag_slot,
      NGX_RTMP_APP_CONF_OFFSET,
      offsetof(ngx_rtmp_live_app_conf_t, play_restart),
      NULL },

    { ngx_string("idle_streams"),
      NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_flag_slot,
      NGX_RTMP_APP_CONF_OFFSET,
      offsetof(ngx_rtmp_live_app_conf_t, idle_streams),
      NULL },
    // 如果关闭,nginx-rtmp会阻止订阅用户连接到空闲/不存在的直播流,并在流发布者断开连接时断开所有订阅用户。默认为开启。

    { ngx_string("drop_idle_publisher"),
      NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
      ngx_rtmp_live_set_msec_slot,
      NGX_RTMP_APP_CONF_OFFSET,
      offsetof(ngx_rtmp_live_app_conf_t, idle_timeout),
      NULL },
    // 在指定时间内删除已空闲(无音频/视频数据)的发布者连接。默认为关闭。注意,这仅在连接处于发布模式(在发送发布命令之后)时有效。

      ngx_null_command
};

代码流程模块

1. 定义live_module 模块,加载模块的时候,会调用相应的函数进行初始化操作
 

static ngx_rtmp_module_t  ngx_rtmp_live_module_ctx = {
    NULL,                                   /* preconfiguration */
    ngx_rtmp_live_postconfiguration,        /* postconfiguration */
    NULL,                                   /* create main configuration */
    NULL,                                   /* init main configuration */
    NULL,                                   /* create server configuration */
    NULL,                                   /* merge server configuration */
    ngx_rtmp_live_create_app_conf,          /* create app configuration */
    ngx_rtmp_live_merge_app_conf            /* merge app configuration */
};

2. 配置文件初始化

static void * ngx_rtmp_live_create_app_conf(ngx_conf_t *cf)
{
    ngx_rtmp_live_app_conf_t      *lacf;

    // 从pool内存池中分配 ngx_rtmp_live_app_conf_t 对象
    lacf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_live_app_conf_t));
    if (lacf == NULL) {
        return NULL;
    }

    lacf->live = NGX_CONF_UNSET;
    lacf->nbuckets = NGX_CONF_UNSET;
    lacf->buflen = NGX_CONF_UNSET_MSEC;
    lacf->sync = NGX_CONF_UNSET_MSEC;
    lacf->idle_timeout = NGX_CONF_UNSET_MSEC;
    lacf->interleave = NGX_CONF_UNSET;
    lacf->wait_key = NGX_CONF_UNSET;
    lacf->wait_video = NGX_CONF_UNSET;
    lacf->publish_notify = NGX_CONF_UNSET;
    lacf->play_restart = NGX_CONF_UNSET;
    lacf->idle_streams = NGX_CONF_UNSET;

    return lacf;
}

3. 解析配置文件,如果配置文件没有配置指定命令,则取默认值,配置值则直接赋值

static char *
ngx_rtmp_live_merge_app_conf(ngx_conf_t *cf, void *parent, void *child)
{
    ngx_rtmp_live_app_conf_t *prev = parent;
    ngx_rtmp_live_app_conf_t *conf = child;

    ngx_conf_merge_value(conf->live, prev->live, 0);
    ngx_conf_merge_value(conf->nbuckets, prev->nbuckets, 1024);
    ngx_conf_merge_msec_value(conf->buflen, prev->buflen, 0);
    ngx_conf_merge_msec_value(conf->sync, prev->sync, 300);
    ngx_conf_merge_msec_value(conf->idle_timeout, prev->idle_timeout, 0);
    ngx_conf_merge_value(conf->interleave, prev->interleave, 0);
    ngx_conf_merge_value(conf->wait_key, prev->wait_key, 1);
    ngx_conf_merge_value(conf->wait_video, prev->wait_video, 0);
    ngx_conf_merge_value(conf->publish_notify, prev->publish_notify, 0);
    ngx_conf_merge_value(conf->play_restart, prev->play_restart, 0);
    ngx_conf_merge_value(conf->idle_streams, prev->idle_streams, 1);

    conf->pool = ngx_create_pool(4096, &cf->cycle->new_log);
    if (conf->pool == NULL) {
        return NGX_CONF_ERROR;
    }

    conf->streams = ngx_pcalloc(cf->pool,
            sizeof(ngx_rtmp_live_stream_t *) * conf->nbuckets);

    return NGX_CONF_OK;
}

4. ngx_rtmp_live_av:音视频数据到来的时候会回调ngx_rtmp_live_av,进行处理数据
   ngx_rtmp_live_publish onpublish 时间回调此函数
   ngx_rtmp_live_play  onplay 事件回调此函数
   ngx_rtmp_live_close_stream 流关闭回到次函数

5. 当客户端推流或者拉流,会通过ngx_rtmp_live_join,把推流或者拉流的rtmp session 加入到流的hash 桶中,hash桶的大小可以通过配置,如果发生hash 冲突,则通过桶对应的链表进行解决,访问的时候通过name进行比较确定是哪一路stream。下面一图表示流的存储数据结构


6. 超时会断开流

static void
ngx_rtmp_live_idle(ngx_event_t *pev)
{
    ngx_connection_t           *c;
    ngx_rtmp_session_t         *s;

    c = pev->data;
    s = c->data;

    ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
                  "live: drop idle publisher");

    ngx_rtmp_finalize_session(s);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1317033.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java SSM兼职平台系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 java SSM兼职平台系统是一套完善的web设计系统(系统采用SSM框架进行设计开发,springspringMVCmybatis),对理解JSP java编程开发语言有帮助,系统具有完整的源代码和 数据库,系统主要采用B/…

【ArkTS】样式复用

如下代码,可以发现每个元素的样式一致,这时就可以将公共样式封装起来 此时可以使用Styles修饰符将公共样式进行封装 Styles修饰符 Entry Component struct Index{build() {Column(){Text(我是Text).ComStyle()Button(我是Button).ComStyle()Image().Co…

在Node.js中MongoDB的连接查询操作

本文主要介绍在Node.js中MongoDB的连接查询操作。 目录 Node.js中MongoDB的连接查询操作使用原生的mongodb驱动程序进行连接查询操作使用Mongoose库进行连接查询操作注意项 Node.js中MongoDB的连接查询操作 在Node.js中使用MongoDB进行连接操作,可以使用原生的mong…

时序预测 | Python实现CNN电力需求预测

时序预测 | Python实现CNN电力需求预测 目录 时序预测 | Python实现CNN电力需求预测预测效果基本描述程序设计参考资料预测效果 基本描述 该数据集因其每小时的用电量数据以及 TSO 对消耗和定价的相应预测而值得注意,从而可以将预期预测与当前最先进的行业预测进行比较。使用该…

Win7系统桌面出现白色透明框的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

边缘分布函数

以二维随机变量说明。 二维随机变量的分布函数为,随机变量的分布函数为,随机变量的分布函数为。 称为二维随机变量关于的边缘分布函数。 称为二维随机变量关于的边缘分布函数。

会声会影怎么使用? 会声会影2024快速掌握入门技巧

一听说视频剪辑我们就不由得联想到电影、电视等一些高端的视频剪辑技术,大家都觉得视频剪辑是一个非常复杂而且需要很昂贵的设备才可以完成的技术活,这对很多“门外汉”来说都可望而不可及。实际上,使用会声会影剪辑视频不仅是很多人都可以操…

《Linux C编程实战》笔记:目录操作

目录的创建和删除 mkdir函数 #include <sys/stat.h> #include <sys/types.h> int mkdir(const char *pathname, mode_t mode); mkdir创建一个新的空目录。空目录中会自动创建.和..目录项。所创建的目录的存取许可权由mode (mode &~umask)指定。 新创建目录的…

MuMu模拟器12如何连接adb?

一、MuMu模拟器12端口查看 MuMu模拟器12现已支持adb同时连接多个模拟器进行调试的操作&#xff0c;可以参考以下步骤操作&#xff0c;查看MuMu模拟器12本体以及多开模拟器的adb端口&#xff1a; 单开的MUMU模拟器12可通过模拟器右上角菜单-问题诊断&#xff0c;获取ADB调试端…

医药行业的数据安全革新者:上海迅软DSE成功案例揭秘

随着网络化办公在医药企业中不断的深入应用&#xff0c;企业内部的药品保密配方、研发成果、技术资料等重要信息都散布在电脑或流转于网络之中&#xff0c;同时各种内部系统又集中存放着大量的敏感数据&#xff0c;一旦这些数据资产发生泄密&#xff0c;将对企业的持续运营造成…

消息队列有哪些应用场景?

分布式系统不同模块之间的通信&#xff0c;除了远程服务调用以外&#xff0c;消息中间件是另外一个重要的手段&#xff0c;在各种互联网系统设计中&#xff0c;消息队列有着广泛的应用。从本文开始&#xff0c;专栏进入分布式消息的模块&#xff0c;将讨论消息队列使用中的高频…

前端如何设置模板参数

1.背景&#xff1a; 最近接到一个需求&#xff0c;在一个类似chatGpt的聊天工具中&#xff0c;要在对话框中设置模板&#xff0c;后端提供了很多模板参数&#xff0c;然后要求将后端返回的特殊字符转成按钮&#xff0c;编辑完成后在相应的位置拼接成字符串。 2.效果&#xff1a…

Java 并发编程(六)-Fork/Join异步回调

一、并发编程 1、Fork/Join分支合并框架 Fork/Join它可以将一个大的任务拆分成多个子任务进行并行处理&#xff0c;最后将子任务结果合并成最后的计算结果&#xff0c;并进行输出。Fork/Join框架要完成两件事情&#xff1a; Fork&#xff1a;把一个复杂任务进行分拆&#xff0…

嵌入式系统基础

嵌入式系统学习的3条路线 路线差别 单片机入门&#xff08;HAL&#xff09; 简单、快速&#xff0c;实际上工作中涉及单片机编程时&#xff0c;也提倡使用HAL库。对于学习来说&#xff0c;HAL库封装了很多技术细节&#xff0c;对技术成长帮助不大。 比如&#xff0c;可能接触…

前后端开发鄙视链的真相,希望对从事前后端开发的小伙伴有些帮助

一、常规的工资对比 前后端的工资情况怎么样?过来人可以负责任的告诉大家:据我所知,至少在杭的网易、阿里,前端跟后端是一个批发价。

探索泰勒级数在机器学习中的作用:从函数逼近到模型优化

一、介绍 泰勒级数是数学中的一个基本概念&#xff0c;在机器学习领域有着重要的应用。本文将探讨泰勒级数的基础知识、它在机器学习中的相关性以及一些具体应用。 揭开复杂性&#xff1a;利用泰勒级数增强机器学习应用的理解和效率。 二、理解泰勒级数 在数学中&#xff0c;泰…

excel手撕神经网络(只需高中数学基础)

神经网络最基础部分是由神经元组成&#xff0c;一个神经元相当于是一个一次函数&#xff0c;yaxb 即在已知x&#xff0c;和y情况下&#xff0c;怎么使用神经网络求解a和b 如下是使用excel求解的神经网络&#xff0c;可以方便理解神经网络运行原理 excel玩具神经网络下载地址 百…

swing快速入门(十五)

注释很详细&#xff0c;直接上代码 上一篇 新增内容 1.文件对话框&#xff08;保存文件&#xff09; 2.文件对话框&#xff08;打开文件&#xff09; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;public class swing_tes…

软实力篇---第五篇

系列文章目录 文章目录 系列文章目录前言一、HR 最喜欢问程序员的 20 个问题二、面试中的礼仪与举止前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 一、HR 最喜欢…

tomcat启动异常:子容器启动失败(a child container failed during start)

最近在使用eclipse启动Tomcat时&#xff0c;发现一个问题&#xff0c;启动以前的项目突然报子容器启动异常。 异常信息如下&#xff1a; 严重: 子容器启动失败 java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: 无法启动组件[org.apache.…