mediakit 源码 轻微微 学习总结
mediakit 源码 轻微微 学习总结
概要
项目地址:https://github.com/ZLMediaKit/ZLMediaKit
此项目我们把他做为一个流媒体服务器,我们会有srt和rtsp的流推到mediakit,然后网页使用webrtc播放。
还有使用一些web hook来支持按需推流、不中断录像等,更多功能不再赘述。
虽然我不是专业的流媒体开发人员,但是我们稍微学习一下这个项目,以下是我对这个项目的浅显认识。
环境准备
windows11
wsl ubuntu22.04
vscode
项目结构

第三方库 3rdpart
他这个第三方库是依赖很深的,tcp/udp服务器,各种协议(rtmp,rtsp,hls等)对接都是他们做的,noticeCenter等。
对于这些服务器,如果你要使用http请求,那么你需要创建一个http服务器。如果你要使用rtmp,那么你就创建一个rtmp服务器。只是监听的端口不同。
对于http请求我们都很熟悉,是一请求一响应回答即可。
对于流媒体服务器,比如说我们要实现一个最简的rtmp服务器,首先他仍然是一个tcp服务器,我们监听1935端口。假如我们使用ffmpeg将一个mp4文件推rtmp流到我们rtmp服务器,rtmp服务器收到了数据包,然后我们是有库去解析的,比如ffmpeg库libavcodec,libavformat等等,这些库能讲数据解析成一个格式比如说叫AVFormat这样一个类。接着无论是我们向将他转成rtsp,hls或者其他的什么格式的协议,都是有相应的库去掉用的。比如我们想将他转成rtsp协议推出去,rtspFormatData=rtspLibFunction(AVFormatData, url ) 基本上就是这样一个函数. 这时有rtsp拉流请求,那么rtsp服务器监听到后,看看有没有这个url的数据文件,有就给拉流的播放器。
以上是我的猜想。哈哈,下面是GPT的一个回答:
I ask:
Now i have a rtmp server, server receive a rtmp stream, then convert to rtsp stream to push a url. How to do it ? Show me c++ code.
GPT answer:
To design a streaming media server that receives an RTMP stream and converts it to an RTSP stream to push a URL, you can follow the steps below:
1. **Server Architecture**:
- Create a central server application that listens for incoming RTMP connections.
- Use a multi-threaded or asynchronous model to handle multiple RTMP connections simultaneously.
- Consider using a library like libevent or Boost Asio for network operations.
2. **RTMP Server**:
- Implement an RTMP server class, such as `RtmpServer`, to handle incoming RTMP connections.
- Use a library like librtmp or RTMPDump to parse and process RTMP packets.
- Handle RTMP handshake, metadata, and audio/video streams.
3. **RTSP Server**:
- Implement an RTSP server class, such as `RtspServer`, to handle outgoing RTSP connections.
- Use a library like live555 or GStreamer to generate RTSP streams.
- Convert the incoming RTMP stream to an RTSP stream using appropriate codecs and formats.
Here's an example of how the code for the above design may look like in C++:
```cpp
#include <iostream>
#include <thread>
#include <boost/asio.hpp>
class RtmpServer {
public:
void start() {
// Start listening for RTMP connections
// Handle incoming RTMP packets
// Parse and process handshake, metadata, and audio/video streams
// Convert RTMP stream to RTSP stream
}
};
class RtspServer {
public:
void start() {
// Start listening for RTSP connections
// Generate RTSP streams using appropriate codecs and formats
// Push the RTSP stream to a URL
}
};
int main() {
// Create and start the RTMP server
RtmpServer rtmpServer;
std::thread rtmpThread([&]() {
rtmpServer.start();
});
// Create and start the RTSP server
RtspServer rtspServer;
std::thread rtspThread([&]() {
rtspServer.start();
});
// Wait for the servers to finish
rtmpThread.join();
rtspThread.join();
return 0;
}
```
Please note that the above code is just a basic outline and you would need to implement the specific functionality for RTMP and RTSP handling, as well as handle threading, network operations, error handling, and other details as per your requirements.
It's important to consider that developing a full-fledged streaming media server involves much more complexity and considerations than can be covered in a simple code example. This code serves as a starting point and you may need to use additional libraries, implement error handling, logging, and other features to create a robust and reliable streaming media server.
你还可以接着问:
How to Implement an RTMP server?
And i have a media player , I want get rtmp stream from the rtmp server , how to implementing the RTMP server?
但是这里就不贴回答了。大家可以自己去GPT~
上面说的是tcp服务器和media-server,接着还有一个重要的是ZLToolKit中的noticeCenter,这个是消息中心,比如有新的流推到mediakit或者推流停止、录像开启、录像关闭等等,都会发送通知到noticeCenter,然后这个noticeCenter再将消息发送的监听此消息的listener。
比如说有新的流推到mediakit,那么会向noticeCenter发送流注册消息,那么有个web hook函数就是监听此消息的listener
api 文件夹
C API,文档说是给嵌入式设备用的
docker
docker镜像构建,构建之后的镜像大小6百多MB,挺夸张的。
src
这里面很多涉及音视频协议解析,看不太懂,我只debug了一下,大概说说我看到的。
我的切入点是这个流媒体服务器是可以进行协议转换的,我想看看他是怎么转换的,对于一条流要转换成哪些协议,可以通过他的配置文件进行配置,那么沿着这个配置文件的相关字段,比如enable_rtmp, enable_rtsp等,找代码中用到的,最终只在MultiMediaSourceMuxer这个类的构造方法中发现if判断。那我在此打断点。
if (option.enable_rtmp) {
_rtmp = std::make_shared<RtmpMediaSourceMuxer>(_tuple, option, std::make_shared<TitleMeta>(dur_sec));
}
if (option.enable_rtsp) {
_rtsp = std::make_shared<RtspMediaSourceMuxer>(_tuple, option, std::make_shared<TitleSdp>(dur_sec));
}
if (option.enable_hls) {
_hls = dynamic_pointer_cast<HlsRecorder>(Recorder::createRecorder(Recorder::type_hls, _tuple, option));
}
if (option.enable_hls_fmp4) {
_hls_fmp4 = dynamic_pointer_cast<HlsFMP4Recorder>(Recorder::createRecorder(Recorder::type_hls_fmp4, _tuple, option));
}
if (option.enable_mp4) {
_mp4 = Recorder::createRecorder(Recorder::type_mp4, _tuple, option);
}
if (option.enable_ts) {
_ts = dynamic_pointer_cast<TSMediaSourceMuxer>(Recorder::createRecorder(Recorder::type_ts, _tuple, option));
}
if (option.enable_fmp4) {
_fmp4 = dynamic_pointer_cast<FMP4MediaSourceMuxer>(Recorder::createRecorder(Recorder::type_fmp4, _tuple, option));
}
我用ffmpeg推送一条rtmp流到mediakit,然后代码执行到断点处。然后我们从头看调用栈,首先rtmp server监听到请求,然后一路执行到Rtmpsession,他接受数据并缓存缓存到一个容器中。
第二个,他发送一条消息到noticeCenter,然后这个noticeCenter将消息通知到listener。
第三个,就是我们打断点的地方,这里有个option,就是根据配置文件来判断是否创建相应协议的Muxer。
server
这里是入口程序,查看main文件
根据程序启动日志,找到对应代码:
try {
auto secret = mINI::Instance()[API::kSecret];
// if (secret == "035c73f7-bb6b-4889-a715-d9eb2d1925cc" || secret.empty()) {
// // 使用默认secret被禁止启动
// throw std::invalid_argument("please modify the configuration named " + API::kSecret + " in " + g_ini_file);
// }
//rtsp服务器,端口默认554
if (rtspPort) { rtspSrv->start<RtspSession>(rtspPort); }
//rtsps服务器,端口默认322
if (rtspsPort) { rtspSSLSrv->start<RtspSessionWithSSL>(rtspsPort); }
//rtmp服务器,端口默认1935
if (rtmpPort) { rtmpSrv->start<RtmpSession>(rtmpPort); }
//rtmps服务器,端口默认19350
if (rtmpsPort) { rtmpsSrv->start<RtmpSessionWithSSL>(rtmpsPort); }
//http服务器,端口默认80
if (httpPort) { httpSrv->start<HttpSession>(httpPort); }
//https服务器,端口默认443
if (httpsPort) { httpsSrv->start<HttpsSession>(httpsPort); }
//telnet远程调试服务器
if (shellPort) { shellSrv->start<ShellSession>(shellPort); }
#if defined(ENABLE_RTPPROXY)
//创建rtp服务器
if (rtpPort) { rtpServer->start(rtpPort); }
#endif//defined(ENABLE_RTPPROXY)
#if defined(ENABLE_WEBRTC)
//webrtc udp服务器
if (rtcPort) { rtcSrv_udp->start<WebRtcSession>(rtcPort);}
if (rtcTcpPort) { rtcSrv_tcp->start<WebRtcSession>(rtcTcpPort);}
#endif//defined(ENABLE_WEBRTC)
#if defined(ENABLE_SRT)
// srt udp服务器
if(srtPort) { srtSrv->start<SRT::SrtSession>(srtPort); }
#endif//defined(ENABLE_SRT)
} catch (std::exception &ex) {
ErrorL << "Start server failed: " << ex.what();
sleep(1);
#if !defined(_WIN32)
if (pid != getpid() && kill_parent_if_failed) {
//杀掉守护进程
kill(pid, SIGINT);
}
#endif
return -1;
}
installWebApi();
InfoL << "已启动http api 接口";
installWebHook();
InfoL << "已启动http hook 接口";
可以看到首先是根据端口创建各个服务器。
接着installWebApi(); 这个就是注册http api的地方,是一个map,然后key是url,value是一个函数,这里就是这么做的。如果向看一个http api的实现,就可以在webApi.cpp 文件中找对应url,然后找对应的函数。
installWebHook(); 是添加listener到noticeCenter
CMakeLists.txt
他在这里定义了一些宏,其中有一个Enable MP4这个宏定义,我咋都找不到怎么实现的。希望c++的老师指点下。
option(ENABLE_MP4 "Enable MP4" ON)
ok,如果有音视频专业的c++,写一篇更深入的mediakit的分析,带我学习学习~~~
mediakit 源码 轻微微 学习总结的更多相关文章
- [源码解析] 深度学习分布式训练框架 horovod (14) --- 弹性训练发现节点 & State
[源码解析] 深度学习分布式训练框架 horovod (14) --- 弹性训练发现节点 & State 目录 [源码解析] 深度学习分布式训练框架 horovod (14) --- 弹性训练 ...
- [源码解析] 深度学习分布式训练框架 horovod (15) --- 广播 & 通知
[源码解析] 深度学习分布式训练框架 horovod (15) --- 广播 & 通知 目录 [源码解析] 深度学习分布式训练框架 horovod (15) --- 广播 & 通知 0 ...
- [源码解析] 深度学习分布式训练框架 horovod (16) --- 弹性训练之Worker生命周期
[源码解析] 深度学习分布式训练框架 horovod (16) --- 弹性训练之Worker生命周期 目录 [源码解析] 深度学习分布式训练框架 horovod (16) --- 弹性训练之Work ...
- [源码解析] 深度学习分布式训练框架 horovod (17) --- 弹性训练之容错
[源码解析] 深度学习分布式训练框架 horovod (17) --- 弹性训练之容错 目录 [源码解析] 深度学习分布式训练框架 horovod (17) --- 弹性训练之容错 0x00 摘要 0 ...
- [源码解析] 深度学习分布式训练框架 horovod (19) --- kubeflow MPI-operator
[源码解析] 深度学习分布式训练框架 horovod (19) --- kubeflow MPI-operator 目录 [源码解析] 深度学习分布式训练框架 horovod (19) --- kub ...
- DICOM医学图形处理:storescp.exe与storescu.exe源码剖析,学习C-STORE请求(续)
转载:http://blog.csdn.net/zssureqh/article/details/39237649 背景: 上一篇博文中,在对storescp工具源文件storescp.cc和DcmS ...
- DICOM医学图像处理:storescp.exe与storescu.exe源码剖析,学习C-STORE请求
转载:http://blog.csdn.net/zssureqh/article/details/39213817 背景: 上一篇专栏博文中针对PACS终端(或设备终端,如CT设备)与RIS系统之间w ...
- 《STL源码剖析》学习之traits编程
侯捷老师在<STL源码剖析>中说到:了解traits编程技术,就像获得“芝麻开门”的口诀一样,从此得以一窥STL源码的奥秘.如此一说,其重要性就不言而喻了. 之前已经介绍过迭代器 ...
- [源码解析] 深度学习分布式训练框架 Horovod (1) --- 基础知识
[源码解析] 深度学习分布式训练框架 Horovod --- (1) 基础知识 目录 [源码解析] 深度学习分布式训练框架 Horovod --- (1) 基础知识 0x00 摘要 0x01 分布式并 ...
- [源码解析] 深度学习分布式训练框架 horovod (2) --- 从使用者角度切入
[源码解析] 深度学习分布式训练框架 horovod (2) --- 从使用者角度切入 目录 [源码解析] 深度学习分布式训练框架 horovod (2) --- 从使用者角度切入 0x00 摘要 0 ...
随机推荐
- 如何修改电脑的BIOS密码?
本文介绍设置.修改Windows电脑BIOS模式密码的具体方法. 一般的,电脑默认都是不含有BIOS密码的,可以直接在开机时不输入任何密码进入BIOS模式:而在某些特定的场合,我们可能需要对其 ...
- Blazor中如何呈现富文本/HTML
将需要显示字符串转换成MarkupString类型 @((MarkupString)htmlString) 参考文献 https://stackoverflow.com/questions/60167 ...
- Redis 备忘录
redis是什么 Redis 是一个高性能的key-value数据库 常用操作 下载 官网:https://redis.io/ Linux版:https://redis.io/download Win ...
- Linux 标准目录结构 FHS ——原文链接https://www.cnblogs.com/woider/p/6618295.html
因为利用 Linux 来开发产品或 distribution 的团队实在太多了,如果每个人都用自己的想法来配置文件放置的目录,那么将可能造成很多管理上的困扰.所以,后来就有了 Filesystem H ...
- JavaScript代码片段精选
今天,我在职坐标的微信公众号里面看到了关于 JavaScript代码片段精选 的 微信软文.在实际开发中,我们经常会使用的JS来实现某些功能.今天,就在此总结一下. 1.浮点数取整 const x ...
- VScode 中golang 单元测试,解决单元测试超时timeout30s
目的:单元测试的主要目的是验证代码的每个单元(函数.方法)是否按照预期工作. 提示:解决单元测试超时30s的问题在序号4 1 准备以_test.go结尾文件和导入testing包 在命名文件时需要让文 ...
- 【opencv】传统图像识别:hog+svm行人识别实战
实战工具:python3.7+pycharm+opencv4.6算法知识:HOG特征提取.SVM模型构建实战目的:本次实战的目的是熟悉HOG+SVM工作流算法,初步掌握图像分类的传统算法.实战记录:本 ...
- java与es8实战之三:Java API Client有关的知识点串讲
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本篇是<java与es8实战>系 ...
- Storm整合Kafka Java API源码
1.Maven项目的pom.xml源码如下: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=&qu ...
- 「codeforces - 1394C」Boboniu and String
link. 注意到 BN-string 长成什么样根本不重要,我们把它表述为 BN-pair \((x, y)\) 即可,两个 BN-strings 相似的充要条件即两者分别映射得到的 BN-pair ...