SRS代码目录
代码目录:
src/目录下核心代码:

- core:核心功能模块,包括日志、配置、错误处理等;
- protocol:实现RTMP、HTTP-FLV、HLS等协议的模块;
- app:应用层的实现,包括流的发布、播放、转码等功能;
- kernel:底层实现,包括网络I/O、多线程处理等;
- main:主层序入口
SRS启动:
main:
// src/main/srs_main_server.cpp
main()
{do_main();
}do_main()
{// 初始化,new创建各种server和实例srs_global_initialize();// 启动线程池?SrsThreadPool::setup_thread_locals();// 加载conf配置_srs_config->parse_options(argc, argv);// 运行主程序run_directly_or_daemon();
}
srs_global_initialize: 初始化各种server
// src/app/srs_app_threads.cpp
srs_global_initialize()
{...// 全局变量 _srs_hybrid:// SrsHybridServer* _srs_hybrid = NULL;_srs_hybrid = new SrsHybridServer();...
}
run_directly_or_daemon: 开始运行
run_directly_or_daemon()
{// 我们没有配置为daemon...int pid = fork();if (pid > 0) {// 父进程直接退出exit(0);}// 继续第二次fork()pid = fork();if (pid > 0) {// 父进程退出exit(0);}// 在子进程中开启执行run_in_thread_pool();
}
run_in_thread_pool
run_in_thread_pool()
{// 初始化线程池_srs_thread_pool->initialize();// 创建run_hybrid_server 工作线程,用于RTMP、RTC server_srs_thread_pool->execute("hybrid", run_hybrid_server, (void*)NULL)// 循环执行线程池中的每个线程:_srs_thread_pool->run();
}
SRS中的线程:
SrsThreadPool 线程池类:
// src/app/srs_app_threads.hpp
class SrsThreadPool {//std::vector<SrsThreadEntry*> threads_;//std::vector<SrsThreadEntry*> hybrids_;
};// 线程池构造函数中,先指定主线程(primordial thread)
// primordial thread并不是调用pthread_create()单独创建的,而是指向了当前调用线程
SrsThreadPool::SrsThreadPool() {entry_ = NULL;lock_ = new SrsThreadMutex();hybrid_ = NULL;// Add primordial thread, current thread itself.SrsThreadEntry* entry = new SrsThreadEntry();threads_.push_back(entry); // 插入到线程池中entry_ = entry;entry->pool = this;entry->label = "primordial";entry->start = NULL;entry->arg = NULL;entry->num = 1;entry->trd = pthread_self(); // 获取当前线程的tidentry->tid = gettid();char buf[256];snprintf(buf, sizeof(buf), "srs-master-%d", entry->num);entry->name = buf;pid_fd = -1;
}
SrsThreadEntry 线程类:
// src/app/srs_app_threads.hpp
class SrsThreadEntry {SrsThreadPool* pool; // 此线程所在的线程池pid_t tid;pthread_t trd;string name;srs_error_t (*start)(void* arg); // 线程入口函数void* arg; // 线程入参
};
_srs_thread_pool是一个全局变量,启动时初始化:
SrsThreadPool* _srs_thread_pool = new SrsThreadPool();
SRS中的Server:
hybrid_server:
// 虚基类,为不同的server子类提供接口
// The hyrid server interfaces, we could register many servers.
class ISrsHybridServer {
public:ISrsHybridServer();virtual ~ISrsHybridServer();
public:virtual srs_error_t initialize() = 0;virtual srs_error_t run(SrsWaitGroup* wg) = 0;virtual void stop() = 0;
};// 管理hybrid server的类
// The hybrid server manager.
class SrsHybridServer : public ISrsFastTimer {
private:std::vector<ISrsHybridServer*> servers; // 管理所有hybrid serverSrsFastTimer* timer20ms_;...virtual void register_server(ISrsHybridServer* svr);
};
SRS中hybrid server类型:
// The SRS server adapter, the master server.
class SrsServerAdapter : public ISrsHybridServer;
// The RTC server adapter.
class RtcServerAdapter : public ISrsHybridServer;
// The srt server adapter, the master server.
class SrsSrtServerAdapter : public ISrsHybridServer;
正如其类名中的“Adapter”所示,这些类是适配类,核心类型是其中真正的server,如SrsServerAdapter中的SrsServer成员、RtcServerAdapter中的SrsRtcServer成员。
SrsServer:
class SrsServerAdapter : public ISrsHybridServer {
private:SrsServer* srs;
public:SrsServerAdapter(); // new创建SrsServervirtual ~SrsServerAdapter();
public:virtual srs_error_t initialize();// 调用SrsServer中的initialize等函数完成初始化,并调用SrsServer->start()virtual srs_error_t run(SrsWaitGroup* wg); virtual void stop();
public:virtual SrsServer* instance();
}; SrsServerAdapter::SrsServerAdapter()
{srs = new SrsServer();
}
SrsServer:
class SrsServer : public ISrsReloadHandler, public ISrsLiveSourceHandler, public ISrsTcpHandler, public ISrsResourceManager, public ISrsCoroutineHandler, public ISrsHourGlass
{
private:SrsHttpServer* http_server; // SrsServer中包含一个HttpServerSrsTcpListener* api_listener_;SrsTcpListener* http_listener_;SrsTcpListener* webrtc_listener_;...
};
SrsRtcServer:
class RtcServerAdapter : public ISrsHybridServer {
private:SrsRtcServer* rtc;
};
gdb:
使用 GDB 调试程序并传递命令行参数:
gdb --args ./objs/srs -c conf/srs.conf
禁用 LeakSanitizer(设置环境变量):
export LSAN_OPTIONS=detect_leaks=0
gdb与fork:
当程序中调用for()创建子进程时,gdb默认只会继续调试父进程,而会“分离”或忽略子进程。
这是因为gdb通常只调试一个进程。
如果需要控制gdb调试指定父进程或子进程,需要通过特定的调试设置来改变这一行为:
(gdb) set follow-fork-mode child # 调试子进程
(gdb) set follow-fork-mode parent # 调试父进程
查看当前follow-fork-mode的值:
(gdb) show follow-fork-mode
常用gdb命令:
c:continue,跳到下一个断点
n:next,调到下一个函数(不进入函数内部)
s:step,进入函数内部
finish:完成函数
r:从头开始
info threads: 查看当前有多少个线程
info inferiors: 查看当前有多少个进程
相关文章:
SRS代码目录
代码目录: src/目录下核心代码: core:核心功能模块,包括日志、配置、错误处理等;protocol:实现RTMP、HTTP-FLV、HLS等协议的模块;app:应用层的实现,包括流的发布、播放…...
C++STL(一)——string类
目录 一、string的定义方式二、 string类对象的容量操作三、string类对象的访问及遍历操作四、string类对象的修改操作五、string类非成员函数 一、string的定义方式 string是个管理字符数组的类,其实就是字符数组的顺序表。 它的接口也是非常多的。本章介绍一些常…...
机器学习--1.KNN机器学习入门
1、机器学习概述 1.1、什么是机器学习 机器学习(Machine Learning)是人工智能(Artificial Intelligence)领域的一个子集,它主要关注如何让计算机系统通过经验学习(数据)并自动改进性能。机器学…...
Adaptive LLM Transformer²
看到了一个不错的论文https://arxiv.org/pdf/2501.06252 TRANSFORMER-SQUARED: SELF-ADAPTIVE LLMS 挺有意思的,是一家日本AI公司SakanaAI的论文(我以前写过他们的不训练提升模型的能力的文章,感兴趣可以去翻)它家有Lion Jones坐镇…...
三路排序算法
三路排序算法 引言 排序算法是计算机科学中基础且重要的算法之一。在数据分析和处理中,排序算法的效率直接影响着程序的执行速度和系统的稳定性。本文将深入探讨三路排序算法,包括其原理、实现和应用场景。 一、三路排序算法的原理 三路排序算法是一…...
代码随想录day27
669. /** lc appleetcode.cn id669 langcpp** [669] 修剪二叉搜索树*/// lc codestart /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}…...
基于LabVIEW的Modbus-RTU设备通信失败问题分析与解决
在使用 LabVIEW 通过 Modbus-RTU 协议与工业设备进行通信时,可能遇到无法正常发送或接收指令的问题。常见原因包括协议参数配置错误、硬件连接问题、数据帧格式不正确等。本文以某 RGBW 控制器调光失败为例,提出了一种通用的排查思路,帮助开发…...
1. 【.NET 8 实战--孢子记账--从单体到微服务--转向微服务】--前言
在我们的专栏《单体开发》中,我们实现了一个简单的记账软件的服务端,并且成功上线。随着用户数量的不断增长,问题逐渐开始显现。访问量逐渐增加,服务端的压力也随之加大。随着访问量的攀升,服务端的响应时间变得越来越…...
直方图:摄影中的视觉数据指南
目录 一、直方图基础:揭开它的神秘面纱 二、解读直方图类型:亮度与色彩的密码 (一)亮度直方图 (二)RGB 直方图 三、拍摄中巧用直方图:优化曝光与效果 (一)精准判断曝…...
一份完整系统化提升信息输出密度与逻辑严谨性的训练素材
一、方法 1. 理论基础与核心概念 1.1 信息输出密度 定义 信息输出密度可以理解为单位表达中所包含的有效信息量。它要求在有限的篇幅或时间内传递更多有价值、低冗余的信息。衡量指标 信息熵(Shannon Entropy):在信息论中,信息…...
CommonJS 和 ES6module 的区别
动态与静态 CommonJS 与 ES6 Module 最本质的区别在于前者对模块依赖的解决是“动态的”,而后者是“静态的”。在这里“动态”的含义是,模块依赖关系的建立发生在代码运行阶段:而“静态”则表示模块依赖关系的建立发生在代码编译阶段。 看一…...
IM 即时通讯系统-51-MPush开源实时消息推送系统
IM 开源系列 IM 即时通讯系统-41-开源 野火IM 专注于即时通讯实时音视频技术,提供优质可控的IMRTC能力 IM 即时通讯系统-42-基于netty实现的IM服务端,提供客户端jar包,可集成自己的登录系统 IM 即时通讯系统-43-简单的仿QQ聊天安卓APP IM 即时通讯系统-44-仿QQ即…...
前端 | JavaScript中的reduce方法
1. 什么是reduce reduce 方法是 JavaScript 中数组的重要方法之一,用于对数组中的元素进行累积计算。它接收一个回调函数作为参数,并返回一个最终计算结果。reduce 在许多场景下都非常有用,比如求和、数组扁平化、对象计数、数据转换等。 2…...
【Linux】从硬件到软件了解进程
个人主页~ 从硬件到软件了解进程 一、冯诺依曼体系结构二、操作系统三、操作系统进程管理1、概念2、PCB和task_struct3、查看进程4、通过系统调用fork创建进程(1)简述(2)系统调用生成子进程的过程〇提出问题①fork函数②父子进程关…...
2024-我的学习成长之路
因为热爱,无畏山海...
机试题——到邻国目标城市的最短距离
题目描述 A国与B国是相邻的两个国家,每个国家都有很多城市。国家内部有很多连接城市的公路,国家之间也有很多跨国公路,连接两个国家的边界城市。两个国家一共有N个城市,编号从1到N,一共有M条公路,包括国内…...
连续预测、
一、连续预测 调用模型遍历需要预测文件夹中的图片: image_ids open(‘VOCdevkit/VOC2007/ImageSets/Main/test.txt’).read().strip().split() for image_id in tqdm(image_ids): # 遍历测试图像 image_path “./VOCdevkit/VOC2007/JPEGImages/” image_id …...
Kamailio 不通过 dmq 实现注册复制功能
春节期间找到一篇文章,需要 fg 才能看到: https://medium.com/tumalevich/kamailio-registration-replication-without-dmq-65e225f9a8a7 kamailio1 192.168.56.115 kamailio2 192.168.56.116 kamailio3 192.168.56.117 route[HANDLE_REPLICATION] {i…...
002 mapper代理开发方式-xml方式
文章目录 代理xml方式UserMapper.javaUser.javadb.propertiesSqlMapConfig.xmlUserMapper.xmlUserMapperTest.javapom.xml 代理 此处使用的是JDK的动态代理方式,延迟加载使用的cglib动态代理方式 代理分为静态代理和动态代理。此处先不说静态代理,因为…...
大模型系列21-AI聊天机器人
聊天机器人 背景机器学习基础监督学习(Supervised Learning)概念应用场景主要问题 无监督学习(Unsupervised Learning)概念常见方法应用场景 强化学习(Reinforcement Learning)概念关键要素应用场景 模型优…...
Apache Iceberg数据湖技术在海量实时数据处理、实时特征工程和模型训练的应用技术方案和具体实施步骤及代码
Apache Iceberg在处理海量实时数据、支持实时特征工程和模型训练方面的强大能力。Iceberg支持实时特征工程和模型训练,特别适用于需要处理海量实时数据的机器学习工作流。 Iceberg作为数据湖,以支持其机器学习平台中的特征存储。Iceberg的分层结构、快照…...
25.2.3 【洛谷】作为栈的复习不错(学习记录)
今天学习的东西不算多,放了一个星期假,感觉不少东西都没那么清楚,得复习一下才行。今天搞个栈题写,把栈复习一下,明天进入正轨,边复习边学习新东西,应该会有二叉树的学习等等... 【洛谷】P1449 …...
Windows 中的 WSL:开启你的 Linux 之旅
今天在安装windows上安装Docker Desktop的时候,遇到了WSL。下面咱们就学习下。 欢迎来到涛涛聊AI 一、什么是 WSL? WSL,全称为 Windows Subsystem for Linux,是微软为 Windows 系统开发的一个兼容层,它允许用户在 Win…...
二维前缀和:高效求解矩阵区域和问题
在处理二维矩阵时,频繁计算某一子矩阵的和是一个常见的操作。传统的做法是直接遍历该子矩阵,时间复杂度较高。当矩阵非常大且有大量的查询时,直接计算将变得低效。为了提高效率,我们可以通过 二维前缀和 技巧在常数时间内解决这个…...
音视频入门基础:RTP专题(5)——FFmpeg源码中,解析SDP的实现
一、引言 FFmpeg源码中通过ff_sdp_parse函数解析SDP。该函数定义在libavformat/rtsp.c中: int ff_sdp_parse(AVFormatContext *s, const char *content) {const char *p;int letter, i;char buf[SDP_MAX_SIZE], *q;SDPParseState sdp_parse_state { { 0 } }, *s1…...
Android开发工作经历整理
一.无人机应用软件开发 集成大疆官网的DJIMobileSDK到AS中编写软件,操控无人机执行多个航点任务。集成OpenCV库进行图像识别,通过获取参数,根据算法执行sdk,使无人机降落到机库,并执行后续的换电操作。待无人机就绪后…...
C++中常用的十大排序方法之4——希尔排序
成长路上不孤单😊😊😊😊😊😊 【😊///计算机爱好者😊///持续分享所学😊///如有需要欢迎收藏转发///😊】 今日分享关于C中常用的排序方法之4——希尔排序的相…...
解决注入线程池的栈溢出问题
文章目录 1.问题产生2.问题解决 1.问题产生 在使用sleuth的时候,需要注入线程池,他才会自动包装,实现traceId的传递,但是突然启动时出现了栈溢出的问题 2.问题解决 根据报错,发现是Gson序列化相关的问题,…...
自动驾驶---两轮自行车的自主导航
1 背景 无人驾驶汽车最早出现在DARPA的比赛中,从那个时刻开始,逐渐引起全球学者的注意,于是从上个世纪开始各大高校院所开始了无人汽车的研发。直到这两年,无人驾驶汽车才开始走进寻常百姓家,虽然目前市面上的乘用车还…...
哈夫曼树并查集
(1)哈夫曼树 特殊概念: 1.结点的权:表示结点树的重要性 2.带权路径长度:从树的根到该节点的路径长度(经过的边数)与该节点上权值的乘积 2.树的带权路径长度:该树的所有叶子节点的…...
