当前位置: 首页 > news >正文

nginx_rtmp_module 之 ngx_rtmp_live_module模块

模块作用

直播模块代码 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);
}

相关文章:

  • Vue3源码梳理:响应式系统的前世今生
  • YOLO v8 目标检测识别翻栏
  • IDEA之设置项目包的结构层级为eclipse默认样式
  • NoSQL 数据库有哪些典型应用?
  • 【产品经理】产品的实现,需要做好战略规划
  • Next.js加载异步组件 骨架屏
  • 【Vue原理解析】之响应式系统
  • 黑马头条--day01.环境搭建
  • 流量分析基础
  • 【MySQL】启动 和 连接 MySQL
  • Docker构建镜像时空间不足:/var/lib/docker,no space left on device
  • 智能优化算法应用:基于引力搜索算法3D无线传感器网络(WSN)覆盖优化 - 附代码
  • QT----第三天,Visio stdio自定义封装控件,鼠标事件,定时器,事件分发器过滤器,绘图事件
  • K8s投射数据卷
  • 【Docker】离线一键式安装docker、docker-compose
  • 《网管员必读——网络组建》(第2版)电子课件下载
  • 【EOS】Cleos基础
  • 78. Subsets
  • Brief introduction of how to 'Call, Apply and Bind'
  • HTML5新特性总结
  • Java 11 发布计划来了,已确定 3个 新特性!!
  • Laravel 菜鸟晋级之路
  • nfs客户端进程变D,延伸linux的lock
  • QQ浏览器x5内核的兼容性问题
  • spring boot下thymeleaf全局静态变量配置
  • Vue实战(四)登录/注册页的实现
  • 闭包,sync使用细节
  • 前端路由实现-history
  • 如何邀请好友注册您的网站(模拟百度网盘)
  • 使用API自动生成工具优化前端工作流
  • 使用SAX解析XML
  • 为物联网而生:高性能时间序列数据库HiTSDB商业化首发!
  • ​​​​​​​​​​​​​​汽车网络信息安全分析方法论
  • ​LeetCode解法汇总307. 区域和检索 - 数组可修改
  • ​如何使用ArcGIS Pro制作渐变河流效果
  • (3)选择元素——(17)练习(Exercises)
  • (BFS)hdoj2377-Bus Pass
  • (LeetCode 49)Anagrams
  • (poj1.3.2)1791(构造法模拟)
  • (第9篇)大数据的的超级应用——数据挖掘-推荐系统
  • (定时器/计数器)中断系统(详解与使用)
  • (二)WCF的Binding模型
  • (附源码)springboot社区居家养老互助服务管理平台 毕业设计 062027
  • (附源码)springboot太原学院贫困生申请管理系统 毕业设计 101517
  • (免费领源码)Python#MySQL图书馆管理系统071718-计算机毕业设计项目选题推荐
  • (三)docker:Dockerfile构建容器运行jar包
  • (一)基于IDEA的JAVA基础1
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • (转)菜鸟学数据库(三)——存储过程
  • **PyTorch月学习计划 - 第一周;第6-7天: 自动梯度(Autograd)**
  • *Algs4-1.5.25随机网格的倍率测试-(未读懂题)
  • .NET Core中Emit的使用
  • .NET设计模式(8):适配器模式(Adapter Pattern)
  • .NET使用HttpClient以multipart/form-data形式post上传文件及其相关参数
  • .net网站发布-允许更新此预编译站点