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. 如何在 Windows Server 2022 阿里云服务器上搭建自己的 MQTT 服务器之二Mosquitto服务器

    一.介绍 最近几天都在搭建MQTT服务器,几天前搭建好了一个 Apache-Apollo的 MQTT 服务器,当我们在管理我们的主题的时候,发现主题的名称的斜杠(/)变成了点号(.),正好我在调试程序 ...

  2. 面试题 01.03. URL化

    面试题 01.03. URL化 简单 URL化.编写一种方法,将字符串中的空格全部替换为%20.假定该字符串尾部有足够的空间存放新增字符,并且知道字符串的"真实"长度.(注:用Ja ...

  3. 王道oj/problem21

    网址:oj.lgwenda.problem/21 思路:先序遍历,中序遍历,后序遍历用递归实现:层序遍历用一个链队实现,出队一个元素,顺序入队他的左孩子和右孩子 代码: #define _CRT_SE ...

  4. SpringBoot3集成Quartz

    目录 一.简介 二.工程搭建 1.工程结构 2.依赖管理 3.数据库 4.配置文件 三.Quartz用法 1.初始化加载 2.新增任务 3.更新任务 4.暂停任务 5.恢复任务 6.执行一次 7.删除 ...

  5. Nginx反向代理服务流式输出设置

    Nginx反向代理服务流式输出设置 1.问题场景 提问:为什么我部署的服务没有流式响应 最近在重构原有的GPT项目时,遇到gpt回答速度很慢的现象.在使用流式输出的接口时,接口响应速度居然还是达到了3 ...

  6. What is TLS ?

    TLS intrduction TLS是一种保障数据传输安全的一种技术(方案),它在传输层工作. 想知道TLS和SSL的关系,先看看他们的历史: 人们遇到数据传输安全问题 1994 SSL 1.0 1 ...

  7. 如何通过拼多多订单API接口获取订单详情

    要获取拼多多订单详情,可以使用以下接口: 1. API名称:pdd.order.detail.get 接口说明:此接口用于查询某个订单的详情信息. API文档地址:前往注册 调用该接口需要提供以下参数 ...

  8. nodejs实现的一个简单粗暴的洗牌算法

    据说名字长别人不一定看得到 之前用python,自带shuffle用的还是超爽的: 去年6月份自己动手用nodejs写一个21点扑克游戏的后台时,就需要一个洗牌算法,于是简单粗暴的实现了一个. 贴出来 ...

  9. Centos7安装yarn

    Centos7安装yarn 设置Yarn仓库 curl --silent --location https://dl.yarnpkg.com/rpm/yarn.repo | sudo tee /etc ...

  10. C++20起支持的一个小特性

    注释掉的为传统的写法,从C++20起支持default关键字修饰的写法,即使是成员变量有多个的时候也支持,减轻了程序员的心智负担.