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 源码 轻微微 学习总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 维珍银河宣布裁员 18%,将于明年中期暂
- 下一篇: 微软 Win11 Dev 23585 预