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 源码 轻微微 学习总结的更多相关文章

  1. [源码解析] 深度学习分布式训练框架 horovod (14) --- 弹性训练发现节点 & State

    [源码解析] 深度学习分布式训练框架 horovod (14) --- 弹性训练发现节点 & State 目录 [源码解析] 深度学习分布式训练框架 horovod (14) --- 弹性训练 ...

  2. [源码解析] 深度学习分布式训练框架 horovod (15) --- 广播 & 通知

    [源码解析] 深度学习分布式训练框架 horovod (15) --- 广播 & 通知 目录 [源码解析] 深度学习分布式训练框架 horovod (15) --- 广播 & 通知 0 ...

  3. [源码解析] 深度学习分布式训练框架 horovod (16) --- 弹性训练之Worker生命周期

    [源码解析] 深度学习分布式训练框架 horovod (16) --- 弹性训练之Worker生命周期 目录 [源码解析] 深度学习分布式训练框架 horovod (16) --- 弹性训练之Work ...

  4. [源码解析] 深度学习分布式训练框架 horovod (17) --- 弹性训练之容错

    [源码解析] 深度学习分布式训练框架 horovod (17) --- 弹性训练之容错 目录 [源码解析] 深度学习分布式训练框架 horovod (17) --- 弹性训练之容错 0x00 摘要 0 ...

  5. [源码解析] 深度学习分布式训练框架 horovod (19) --- kubeflow MPI-operator

    [源码解析] 深度学习分布式训练框架 horovod (19) --- kubeflow MPI-operator 目录 [源码解析] 深度学习分布式训练框架 horovod (19) --- kub ...

  6. DICOM医学图形处理:storescp.exe与storescu.exe源码剖析,学习C-STORE请求(续)

    转载:http://blog.csdn.net/zssureqh/article/details/39237649 背景: 上一篇博文中,在对storescp工具源文件storescp.cc和DcmS ...

  7. DICOM医学图像处理:storescp.exe与storescu.exe源码剖析,学习C-STORE请求

    转载:http://blog.csdn.net/zssureqh/article/details/39213817 背景: 上一篇专栏博文中针对PACS终端(或设备终端,如CT设备)与RIS系统之间w ...

  8. 《STL源码剖析》学习之traits编程

    侯捷老师在<STL源码剖析>中说到:了解traits编程技术,就像获得“芝麻开门”的口诀一样,从此得以一窥STL源码的奥秘.如此一说,其重要性就不言而喻了.      之前已经介绍过迭代器 ...

  9. [源码解析] 深度学习分布式训练框架 Horovod (1) --- 基础知识

    [源码解析] 深度学习分布式训练框架 Horovod --- (1) 基础知识 目录 [源码解析] 深度学习分布式训练框架 Horovod --- (1) 基础知识 0x00 摘要 0x01 分布式并 ...

  10. [源码解析] 深度学习分布式训练框架 horovod (2) --- 从使用者角度切入

    [源码解析] 深度学习分布式训练框架 horovod (2) --- 从使用者角度切入 目录 [源码解析] 深度学习分布式训练框架 horovod (2) --- 从使用者角度切入 0x00 摘要 0 ...

随机推荐

  1. 【译】如何在 Visual Studio 中调试异步代码

    虽然异步代码可以提高程序的整体吞吐量,但异步代码仍然无法免除错误!当潜在的死锁.模糊的错误消息以及查找导致 Bug 的 Task 时,编写异步代码会使调试更加困难.幸运的是,Visual Studio ...

  2. mysql:EXPLAIN

    推荐阅读原文:EXPLAIN用法和结果分析 语法:EXPLAIN SELECT * FROM t1 使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句 ...

  3. protolator - Protobuf <==> json

    github.com/hyperledger/fabric-config/protolator 是 Hyperledger Fabric 中的一个 Go 包,用于将 Protocol Buffers( ...

  4. ASP.NET WebForm中asp:Repeater和UI:Grid数据为空时如何显示表头?

    一.asp:Repeater Repeater 控件用于显示被绑定在该控件上的项目的重复列表.Repeater 控件可被绑定到数据库表.XML 文件或者其他项目列表. 1.1-前台页面代码 <a ...

  5. 为什么大于 $3$ 的素数可以表示为 $6n\pm1$?

    我们有一个素数 \(p\),都能表示为 \(6n \pm 1\). 为什么呢? 我们设 \(p = 6n \pm k\),\(k\) 可以是 \(0, 1, 2, 3, 4, 5\). 如果 \(k\ ...

  6. 可不要忽视了TypeScript中函数和类的重要性

    上一篇文章总结了 TypeScript的类型注解,这一篇来聊聊同样重要的函数和类 函数 以下声明了一个函数类型,通过type来定义类型别名,void 表示没有返回值 type fnType = () ...

  7. Unity 编辑器资源导入处理函数 OnPreprocessTexture:深入解析与实用案例

    Unity 编辑器资源导入处理函数 OnPreprocessTexture 用法 点击封面跳转下载页面 简介 在Unity中,我们可以使用编辑器资源导入处理函数(OnPreprocessTexture ...

  8. 简单描述下HTTP协议和TCP协议之间的关系以及TCP三次握手, 四次挥手

    TCP 三次握手, 四次挥手 TCP(传输控制协议)是一种用于在计算机网络中建立可靠连接的协议.TCP连接的建立和终止分别使用了"三次握手"和"四次挥手"的过程 ...

  9. 使用pycharm脚本发送钉钉群通知

    使用Pychon脚本发送钉钉群通知 我们可以使用钉钉的机器人助手发送群通知,只需要非常简单的配置就可以实现,而没有任何的成本. 1) 首先我们要在钉钉群里添加一个机器人助手 选择智能群助手,然后选择添 ...

  10. 代码随想录算法训练营第二十五天| 216.组合总和III 17.电话号码的字母组合

      216.组合总和III 卡哥建议:如果把 组合问题理解了,本题就容易一些了. 题目链接/文章讲解:https://programmercarl.com/0216.%E7%BB%84%E5%90%8 ...