From 6888f20d74b35558c0c3efd7cf26cb20014c6668 Mon Sep 17 00:00:00 2001 From: waken <33921191+mc373906408@users.noreply.github.com> Date: Thu, 9 Nov 2023 11:26:13 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9EopenRtpServerMultiplex?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=EF=BC=8C=E6=94=AF=E6=8C=81=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E5=A4=9A=E8=B7=AF=E5=A4=8D=E7=94=A8RTP=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E5=99=A8=E7=AB=AF=E5=8F=A3=20(#2954)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #2953 --- postman/ZLMediaKit.postman_collection.json | 56 ++++++++++++++++++++-- server/WebApi.cpp | 22 ++++++++- server/WebApi.h | 2 +- src/Rtp/RtpServer.cpp | 5 +- src/Rtp/RtpServer.h | 3 +- 5 files changed, 78 insertions(+), 10 deletions(-) diff --git a/postman/ZLMediaKit.postman_collection.json b/postman/ZLMediaKit.postman_collection.json index d8a49900..784bb60c 100644 --- a/postman/ZLMediaKit.postman_collection.json +++ b/postman/ZLMediaKit.postman_collection.json @@ -1,9 +1,10 @@ { "info": { - "_postman_id": "39e8a1df-cc8e-4e3f-bf5e-197c86e7bf0f", + "_postman_id": "509e5f6b-728c-4d5f-b3e8-521d76b2cc7a", "name": "ZLMediaKit", "description": "媒体服务器", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "29185956" }, "item": [ { @@ -918,7 +919,7 @@ "method": "GET", "header": [], "url": { - "raw": "{{ZLMediaKit_URL}}/index/api/broadcastMessage?secret={{ZLMediaKit_secret}}&schema=rtsp&vhost={{defaultVhost}}&app=live&stream=test&msg=Hello zlmediakit123", + "raw": "{{ZLMediaKit_URL}}/index/api/broadcastMessage?secret={{ZLMediaKit_secret}}&schema=rtsp&vhost={{defaultVhost}}&app=live&stream=test&msg=Hello ZLMediakit", "host": [ "{{ZLMediaKit_URL}}" ], @@ -1247,7 +1248,7 @@ }, { "key": "stamp", - "value": 1000, + "value": "1000", "description": "要设置的录像播放位置" } ] @@ -1478,6 +1479,53 @@ }, "response": [] }, + { + "name": "创建多路复用RTP服务器(openRtpServerMultiplex)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{ZLMediaKit_URL}}/index/api/openRtpServer?secret={{ZLMediaKit_secret}}&port=0&tcp_mode=1&stream_id=test", + "host": [ + "{{ZLMediaKit_URL}}" + ], + "path": [ + "index", + "api", + "openRtpServer" + ], + "query": [ + { + "key": "secret", + "value": "{{ZLMediaKit_secret}}", + "description": "api操作密钥(配置文件配置)" + }, + { + "key": "port", + "value": "0", + "description": "绑定的端口,0时为随机端口" + }, + { + "key": "tcp_mode", + "value": "1", + "description": "tcp模式,0时为不启用tcp监听,1时为启用tcp监听" + }, + { + "key": "stream_id", + "value": "test", + "description": "该端口绑定的流id\n" + }, + { + "key": "only_audio", + "value": "0", + "description": "是否为单音频track,用于语音对讲", + "disabled": true + } + ] + } + }, + "response": [] + }, { "name": "连接RTP服务器(connectRtpServer)", "request": { diff --git a/server/WebApi.cpp b/server/WebApi.cpp index 1ddc0c0f..7833b933 100755 --- a/server/WebApi.cpp +++ b/server/WebApi.cpp @@ -404,7 +404,7 @@ Value makeMediaSourceJson(MediaSource &media){ } #if defined(ENABLE_RTPPROXY) -uint16_t openRtpServer(uint16_t local_port, const string &stream_id, int tcp_mode, const string &local_ip, bool re_use_port, uint32_t ssrc, bool only_audio) { +uint16_t openRtpServer(uint16_t local_port, const string &stream_id, int tcp_mode, const string &local_ip, bool re_use_port, uint32_t ssrc, bool only_audio, bool multiplex) { lock_guard lck(s_rtpServerMapMtx); if (s_rtpServerMap.find(stream_id) != s_rtpServerMap.end()) { //为了防止RtpProcess所有权限混乱的问题,不允许重复添加相同的stream_id @@ -412,7 +412,7 @@ uint16_t openRtpServer(uint16_t local_port, const string &stream_id, int tcp_mod } RtpServer::Ptr server = std::make_shared(); - server->start(local_port, stream_id, (RtpServer::TcpMode)tcp_mode, local_ip.c_str(), re_use_port, ssrc, only_audio); + server->start(local_port, stream_id, (RtpServer::TcpMode)tcp_mode, local_ip.c_str(), re_use_port, ssrc, only_audio, multiplex); server->setOnDetach([stream_id]() { //设置rtp超时移除事件 lock_guard lck(s_rtpServerMapMtx); @@ -1182,6 +1182,24 @@ void installWebApi() { //回复json val["port"] = port; }); + api_regist("/media/api/openRtpServerMultiplex", [](API_ARGS_MAP) { + CHECK_SECRET(); + CHECK_ARGS("port", "stream_id"); + auto stream_id = allArgs["stream_id"]; + auto tcp_mode = allArgs["tcp_mode"].as(); + if (allArgs["enable_tcp"].as() && !tcp_mode) { + // 兼容老版本请求,新版本去除enable_tcp参数并新增tcp_mode参数 + tcp_mode = 1; + } + + auto port = openRtpServer( + allArgs["port"], stream_id, tcp_mode, "::", true, 0, allArgs["only_audio"].as(),true); + if (port == 0) { + throw InvalidArgsException("该stream_id已存在"); + } + // 回复json + val["port"] = port; + }); api_regist("/index/api/connectRtpServer", [](API_ARGS_MAP_ASYNC) { CHECK_SECRET(); diff --git a/server/WebApi.h b/server/WebApi.h index 460d0132..f7ec0cb3 100755 --- a/server/WebApi.h +++ b/server/WebApi.h @@ -239,7 +239,7 @@ void installWebApi(); void unInstallWebApi(); #if defined(ENABLE_RTPPROXY) -uint16_t openRtpServer(uint16_t local_port, const std::string &stream_id, int tcp_mode, const std::string &local_ip, bool re_use_port, uint32_t ssrc, bool only_audio); +uint16_t openRtpServer(uint16_t local_port, const std::string &stream_id, int tcp_mode, const std::string &local_ip, bool re_use_port, uint32_t ssrc, bool only_audio, bool multiplex=false); void connectRtpServer(const std::string &stream_id, const std::string &dst_url, uint16_t dst_port, const std::function &cb); bool closeRtpServer(const std::string &stream_id); #endif diff --git a/src/Rtp/RtpServer.cpp b/src/Rtp/RtpServer.cpp index 34871562..1f71a4a8 100644 --- a/src/Rtp/RtpServer.cpp +++ b/src/Rtp/RtpServer.cpp @@ -156,7 +156,7 @@ private: EventPoller::DelayTask::Ptr _delay_task; }; -void RtpServer::start(uint16_t local_port, const string &stream_id, TcpMode tcp_mode, const char *local_ip, bool re_use_port, uint32_t ssrc, bool only_audio) { +void RtpServer::start(uint16_t local_port, const string &stream_id, TcpMode tcp_mode, const char *local_ip, bool re_use_port, uint32_t ssrc, bool only_audio, bool multiplex) { //创建udp服务器 Socket::Ptr rtp_socket = Socket::createSocket(nullptr, true); Socket::Ptr rtcp_socket = Socket::createSocket(nullptr, true); @@ -195,7 +195,8 @@ void RtpServer::start(uint16_t local_port, const string &stream_id, TcpMode tcp_ //创建udp服务器 UdpServer::Ptr udp_server; RtcpHelper::Ptr helper; - if (!stream_id.empty()) { + //增加了多路复用判断,如果多路复用为true,就走else逻辑,同时保留了原来stream_id为空走else逻辑 + if (!stream_id.empty() && !multiplex) { //指定了流id,那么一个端口一个流(不管是否包含多个ssrc的多个流,绑定rtp源后,会筛选掉ip端口不匹配的流) helper = std::make_shared(std::move(rtcp_socket), stream_id); helper->startRtcp(); diff --git a/src/Rtp/RtpServer.h b/src/Rtp/RtpServer.h index 4efce859..71aa88e7 100644 --- a/src/Rtp/RtpServer.h +++ b/src/Rtp/RtpServer.h @@ -42,9 +42,10 @@ public: * @param local_ip 绑定的本地网卡ip * @param re_use_port 是否设置socket为re_use属性 * @param ssrc 指定的ssrc + * @param multiplex 多路复用 */ void start(uint16_t local_port, const std::string &stream_id = "", TcpMode tcp_mode = PASSIVE, - const char *local_ip = "::", bool re_use_port = true, uint32_t ssrc = 0, bool only_audio = false); + const char *local_ip = "::", bool re_use_port = true, uint32_t ssrc = 0, bool only_audio = false, bool multiplex = false); /** * 连接到tcp服务(tcp主动模式)