Merge branch 'master' into dev
This commit is contained in:
commit
b8729dc2a5
|
|
@ -50,8 +50,8 @@ BraceWrapping:
|
||||||
BreakConstructorInitializers: BeforeComma
|
BreakConstructorInitializers: BeforeComma
|
||||||
# 继承过长需要换行时也在 `,` 前
|
# 继承过长需要换行时也在 `,` 前
|
||||||
BreakInheritanceList: BeforeComma
|
BreakInheritanceList: BeforeComma
|
||||||
# 列宽 120
|
# 列宽 160
|
||||||
ColumnLimit: 120
|
ColumnLimit: 160
|
||||||
# c++11 括号内起始/结束无空格, false 会加上
|
# c++11 括号内起始/结束无空格, false 会加上
|
||||||
Cpp11BracedListStyle: false
|
Cpp11BracedListStyle: false
|
||||||
# 命名空间后的注释会修正为: // namespace_name
|
# 命名空间后的注释会修正为: // namespace_name
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,7 @@ file(GLOB ToolKit_SRC_LIST
|
||||||
${ToolKit_ROOT}/src/*/*.c)
|
${ToolKit_ROOT}/src/*/*.c)
|
||||||
if(IOS)
|
if(IOS)
|
||||||
list(APPEND ToolKit_SRC_LIST
|
list(APPEND ToolKit_SRC_LIST
|
||||||
${ToolKit_ROOT}/Network/Socket_ios.mm)
|
${ToolKit_ROOT}/src/Network/Socket_ios.mm)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
###################################################################
|
###################################################################
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit ca26e43a5f62986bb8a007226e0bad148d154abc
|
Subproject commit 7e40c751659d5c1ec623699732284c12e0a4feb8
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 5aa9884660df1c193d730a90835af36ee411668c
|
Subproject commit cdbb3d6b9ea254f454c6e466c5962af5ace01199
|
||||||
|
|
@ -308,7 +308,7 @@ API_EXPORT void API_CALL mk_webrtc_get_answer_sdp2(void *user_data, on_user_data
|
||||||
WebRtcPluginManager::Instance().getAnswerSdp(*session, type, WebRtcArgsUrl(url),
|
WebRtcPluginManager::Instance().getAnswerSdp(*session, type, WebRtcArgsUrl(url),
|
||||||
[offer_str, session, ptr, cb](const WebRtcInterface &exchanger) mutable {
|
[offer_str, session, ptr, cb](const WebRtcInterface &exchanger) mutable {
|
||||||
try {
|
try {
|
||||||
auto sdp_answer = const_cast<WebRtcInterface &>(exchanger).getAnswerSdp(offer_str);
|
auto sdp_answer = exchangeSdp(exchanger, offer_str);
|
||||||
cb(ptr.get(), sdp_answer.data(), nullptr);
|
cb(ptr.get(), sdp_answer.data(), nullptr);
|
||||||
} catch (std::exception &ex) {
|
} catch (std::exception &ex) {
|
||||||
cb(ptr.get(), nullptr, ex.what());
|
cb(ptr.get(), nullptr, ex.what());
|
||||||
|
|
|
||||||
|
|
@ -27,13 +27,9 @@ public:
|
||||||
|
|
||||||
~MediaHelper() = default;
|
~MediaHelper() = default;
|
||||||
|
|
||||||
void attachEvent(){
|
void attachEvent() { _channel->setMediaListener(shared_from_this()); }
|
||||||
_channel->setMediaListener(shared_from_this());
|
|
||||||
}
|
|
||||||
|
|
||||||
DevChannel::Ptr &getChannel(){
|
DevChannel::Ptr &getChannel() { return _channel; }
|
||||||
return _channel;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setOnClose(on_mk_media_close cb, std::shared_ptr<void> user_data) {
|
void setOnClose(on_mk_media_close cb, std::shared_ptr<void> user_data) {
|
||||||
_on_close = cb;
|
_on_close = cb;
|
||||||
|
|
@ -103,9 +99,7 @@ protected:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toolkit::EventPoller::Ptr getOwnerPoller(MediaSource &sender) {
|
toolkit::EventPoller::Ptr getOwnerPoller(MediaSource &sender) override { return _poller; }
|
||||||
return _poller;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EventPoller::Ptr _poller;
|
EventPoller::Ptr _poller;
|
||||||
|
|
@ -290,7 +284,8 @@ API_EXPORT void API_CALL mk_media_start_send_rtp(mk_media ctx, const char *dst_u
|
||||||
mk_media_start_send_rtp2(ctx, dst_url, dst_port, ssrc, is_udp, cb, user_data, nullptr);
|
mk_media_start_send_rtp2(ctx, dst_url, dst_port, ssrc, is_udp, cb, user_data, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORT void API_CALL mk_media_start_send_rtp2(mk_media ctx, const char *dst_url, uint16_t dst_port, const char *ssrc, int is_udp, on_mk_media_send_rtp_result cb, void *user_data, on_user_data_free user_data_free){
|
API_EXPORT void API_CALL mk_media_start_send_rtp2(mk_media ctx, const char *dst_url, uint16_t dst_port, const char *ssrc, int is_udp, on_mk_media_send_rtp_result cb, void *user_data,
|
||||||
|
on_user_data_free user_data_free) {
|
||||||
assert(ctx && dst_url && ssrc);
|
assert(ctx && dst_url && ssrc);
|
||||||
MediaHelper::Ptr* obj = (MediaHelper::Ptr*) ctx;
|
MediaHelper::Ptr* obj = (MediaHelper::Ptr*) ctx;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ public:
|
||||||
MediaPlayerForC(){
|
MediaPlayerForC(){
|
||||||
_player = std::make_shared<MediaPlayer>();
|
_player = std::make_shared<MediaPlayer>();
|
||||||
}
|
}
|
||||||
~MediaPlayerForC(){}
|
~MediaPlayerForC() = default;
|
||||||
|
|
||||||
MediaPlayer *operator->(){
|
MediaPlayer *operator->(){
|
||||||
return _player.get();
|
return _player.get();
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ API_EXPORT uint16_t API_CALL mk_sock_info_local_port(const mk_sock_info ctx){
|
||||||
API_EXPORT mk_sock_info API_CALL mk_tcp_session_get_sock_info(const mk_tcp_session ctx) {
|
API_EXPORT mk_sock_info API_CALL mk_tcp_session_get_sock_info(const mk_tcp_session ctx) {
|
||||||
assert(ctx);
|
assert(ctx);
|
||||||
SessionForC *session = (SessionForC *)ctx;
|
SessionForC *session = (SessionForC *)ctx;
|
||||||
return (mk_sock_info)session;
|
return reinterpret_cast<mk_sock_info>(static_cast<SockInfo *>(session));
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORT void API_CALL mk_tcp_session_shutdown(const mk_tcp_session ctx,int err,const char *err_msg){
|
API_EXPORT void API_CALL mk_tcp_session_shutdown(const mk_tcp_session ctx,int err,const char *err_msg){
|
||||||
|
|
@ -320,7 +320,7 @@ TcpClientForC::Ptr *mk_tcp_client_create_l(mk_tcp_client_events *events, mk_tcp_
|
||||||
API_EXPORT mk_sock_info API_CALL mk_tcp_client_get_sock_info(const mk_tcp_client ctx){
|
API_EXPORT mk_sock_info API_CALL mk_tcp_client_get_sock_info(const mk_tcp_client ctx){
|
||||||
assert(ctx);
|
assert(ctx);
|
||||||
TcpClientForC::Ptr *client = (TcpClientForC::Ptr *)ctx;
|
TcpClientForC::Ptr *client = (TcpClientForC::Ptr *)ctx;
|
||||||
return (mk_sock_info)(SockInfo *)client->get();
|
return reinterpret_cast<mk_sock_info>(static_cast<SockInfo *>(client->get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORT mk_tcp_client API_CALL mk_tcp_client_create(mk_tcp_client_events *events, mk_tcp_type type){
|
API_EXPORT mk_tcp_client API_CALL mk_tcp_client_create(mk_tcp_client_events *events, mk_tcp_type type){
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ EXPOSE 443/tcp
|
||||||
EXPOSE 10000/udp
|
EXPOSE 10000/udp
|
||||||
EXPOSE 10000/tcp
|
EXPOSE 10000/tcp
|
||||||
EXPOSE 8000/udp
|
EXPOSE 8000/udp
|
||||||
|
EXPOSE 8000/tcp
|
||||||
EXPOSE 9000/udp
|
EXPOSE 9000/udp
|
||||||
|
|
||||||
# ADD sources.list /etc/apt/sources.list
|
# ADD sources.list /etc/apt/sources.list
|
||||||
|
|
@ -82,4 +83,4 @@ COPY --from=build /opt/media/ZLMediaKit/release/linux/${MODEL}/MediaServer /opt/
|
||||||
COPY --from=build /opt/media/ZLMediaKit/release/linux/${MODEL}/config.ini /opt/media/conf/
|
COPY --from=build /opt/media/ZLMediaKit/release/linux/${MODEL}/config.ini /opt/media/conf/
|
||||||
COPY --from=build /opt/media/ZLMediaKit/www/ /opt/media/bin/www/
|
COPY --from=build /opt/media/ZLMediaKit/www/ /opt/media/bin/www/
|
||||||
ENV PATH /opt/media/bin:$PATH
|
ENV PATH /opt/media/bin:$PATH
|
||||||
CMD ["sh","-c","./MediaServer -s default.pem -c ../conf/config.ini"]
|
CMD ["sh","-c","./MediaServer -s default.pem -c ../conf/config.ini -l 0"]
|
||||||
|
|
|
||||||
|
|
@ -1488,6 +1488,42 @@
|
||||||
},
|
},
|
||||||
"response": []
|
"response": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "更新RTP服务器过滤SSRC(updateRtpServerSSRC)",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{ZLMediaKit_URL}}/index/api/updateRtpServerSSRC?secret={{ZLMediaKit_secret}}&stream_id=test&ssrc=123456",
|
||||||
|
"host": [
|
||||||
|
"{{ZLMediaKit_URL}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"index",
|
||||||
|
"api",
|
||||||
|
"updateRtpServerSSRC"
|
||||||
|
],
|
||||||
|
"query": [
|
||||||
|
{
|
||||||
|
"key": "secret",
|
||||||
|
"value": "{{ZLMediaKit_secret}}",
|
||||||
|
"description": "api操作密钥(配置文件配置),如果操作ip是127.0.0.1,则不需要此参数"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "stream_id",
|
||||||
|
"value": "test",
|
||||||
|
"description": "该端口绑定的流id"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "ssrc",
|
||||||
|
"value": "123456",
|
||||||
|
"description": "十进制ssrc"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "暂停RTP超时检查(pauseRtpCheck)",
|
"name": "暂停RTP超时检查(pauseRtpCheck)",
|
||||||
"request": {
|
"request": {
|
||||||
|
|
|
||||||
|
|
@ -247,7 +247,7 @@ static inline void addHttpListener(){
|
||||||
size = body->remainSize();
|
size = body->remainSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
LogContextCapture log(getLogger(), LDebug, __FILE__, "http api debug", __LINE__);
|
LogContextCapture log(getLogger(), toolkit::LTrace, __FILE__, "http api debug", __LINE__);
|
||||||
log << "\r\n# request:\r\n" << parser.Method() << " " << parser.FullUrl() << "\r\n";
|
log << "\r\n# request:\r\n" << parser.Method() << " " << parser.FullUrl() << "\r\n";
|
||||||
log << "# header:\r\n";
|
log << "# header:\r\n";
|
||||||
|
|
||||||
|
|
@ -966,7 +966,7 @@ void installWebApi() {
|
||||||
//开始推流,如果推流失败或者推流中止,将会自动重试若干次,默认一直重试
|
//开始推流,如果推流失败或者推流中止,将会自动重试若干次,默认一直重试
|
||||||
pusher->setPushCallbackOnce([cb, key, url](const SockException &ex) {
|
pusher->setPushCallbackOnce([cb, key, url](const SockException &ex) {
|
||||||
if (ex) {
|
if (ex) {
|
||||||
WarnL << "Push " << url << " failed, key: " << key << ", err: " << ex.what();
|
WarnL << "Push " << url << " failed, key: " << key << ", err: " << ex;
|
||||||
lock_guard<recursive_mutex> lck(s_proxyPusherMapMtx);
|
lock_guard<recursive_mutex> lck(s_proxyPusherMapMtx);
|
||||||
s_proxyPusherMap.erase(key);
|
s_proxyPusherMap.erase(key);
|
||||||
}
|
}
|
||||||
|
|
@ -975,7 +975,7 @@ void installWebApi() {
|
||||||
|
|
||||||
//被主动关闭推流
|
//被主动关闭推流
|
||||||
pusher->setOnClose([key, url](const SockException &ex) {
|
pusher->setOnClose([key, url](const SockException &ex) {
|
||||||
WarnL << "Push " << url << " failed, key: " << key << ", err: " << ex.what();
|
WarnL << "Push " << url << " failed, key: " << key << ", err: " << ex;
|
||||||
lock_guard<recursive_mutex> lck(s_proxyPusherMapMtx);
|
lock_guard<recursive_mutex> lck(s_proxyPusherMapMtx);
|
||||||
s_proxyPusherMap.erase(key);
|
s_proxyPusherMap.erase(key);
|
||||||
});
|
});
|
||||||
|
|
@ -1182,6 +1182,18 @@ void installWebApi() {
|
||||||
val["hit"] = 1;
|
val["hit"] = 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
api_regist("/index/api/updateRtpServerSSRC",[](API_ARGS_MAP){
|
||||||
|
CHECK_SECRET();
|
||||||
|
CHECK_ARGS("stream_id", "ssrc");
|
||||||
|
|
||||||
|
lock_guard<recursive_mutex> lck(s_rtpServerMapMtx);
|
||||||
|
auto it = s_rtpServerMap.find(allArgs["stream_id"]);
|
||||||
|
if (it == s_rtpServerMap.end()) {
|
||||||
|
throw ApiRetException("RtpServer not found by stream_id", API::NotFound);
|
||||||
|
}
|
||||||
|
it->second->updateSSRC(allArgs["ssrc"]);
|
||||||
|
});
|
||||||
|
|
||||||
api_regist("/index/api/listRtpServer",[](API_ARGS_MAP){
|
api_regist("/index/api/listRtpServer",[](API_ARGS_MAP){
|
||||||
CHECK_SECRET();
|
CHECK_SECRET();
|
||||||
|
|
||||||
|
|
@ -1595,7 +1607,7 @@ void installWebApi() {
|
||||||
auto offer = allArgs.getArgs();
|
auto offer = allArgs.getArgs();
|
||||||
CHECK(!offer.empty(), "http body(webrtc offer sdp) is empty");
|
CHECK(!offer.empty(), "http body(webrtc offer sdp) is empty");
|
||||||
|
|
||||||
WebRtcPluginManager::Instance().getAnswerSdp(*(static_cast<Session *>(&sender)), type,
|
WebRtcPluginManager::Instance().getAnswerSdp(static_cast<Session&>(sender), type,
|
||||||
WebRtcArgsImp(allArgs, sender.getIdentifier()),
|
WebRtcArgsImp(allArgs, sender.getIdentifier()),
|
||||||
[invoker, val, offer, headerOut](const WebRtcInterface &exchanger) mutable {
|
[invoker, val, offer, headerOut](const WebRtcInterface &exchanger) mutable {
|
||||||
//设置返回类型
|
//设置返回类型
|
||||||
|
|
@ -1604,7 +1616,7 @@ void installWebApi() {
|
||||||
headerOut["Access-Control-Allow-Origin"] = "*";
|
headerOut["Access-Control-Allow-Origin"] = "*";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val["sdp"] = const_cast<WebRtcInterface &>(exchanger).getAnswerSdp(offer);
|
val["sdp"] = exchangeSdp(exchanger, offer);
|
||||||
val["id"] = exchanger.getIdentifier();
|
val["id"] = exchanger.getIdentifier();
|
||||||
val["type"] = "answer";
|
val["type"] = "answer";
|
||||||
invoker(200, headerOut, val.toStyledString());
|
invoker(200, headerOut, val.toStyledString());
|
||||||
|
|
@ -1620,7 +1632,7 @@ void installWebApi() {
|
||||||
auto offer = allArgs.getArgs();
|
auto offer = allArgs.getArgs();
|
||||||
CHECK(!offer.empty(), "http body(webrtc offer sdp) is empty");
|
CHECK(!offer.empty(), "http body(webrtc offer sdp) is empty");
|
||||||
|
|
||||||
WebRtcPluginManager::Instance().getAnswerSdp(*(static_cast<Session *>(&sender)), type,
|
WebRtcPluginManager::Instance().getAnswerSdp(static_cast<Session&>(sender), type,
|
||||||
WebRtcArgsImp(allArgs, sender.getIdentifier()),
|
WebRtcArgsImp(allArgs, sender.getIdentifier()),
|
||||||
[invoker, offer, headerOut](const WebRtcInterface &exchanger) mutable {
|
[invoker, offer, headerOut](const WebRtcInterface &exchanger) mutable {
|
||||||
// 设置跨域
|
// 设置跨域
|
||||||
|
|
@ -1628,7 +1640,7 @@ void installWebApi() {
|
||||||
try {
|
try {
|
||||||
// 设置返回类型
|
// 设置返回类型
|
||||||
headerOut["Content-Type"] = "application/sdp";
|
headerOut["Content-Type"] = "application/sdp";
|
||||||
invoker(201, headerOut, const_cast<WebRtcInterface &>(exchanger).getAnswerSdp(offer));
|
invoker(201, headerOut, exchangeSdp(exchanger, offer));
|
||||||
} catch (std::exception &ex) {
|
} catch (std::exception &ex) {
|
||||||
headerOut["Content-Type"] = "text/plain";
|
headerOut["Content-Type"] = "text/plain";
|
||||||
invoker(406, headerOut, ex.what());
|
invoker(406, headerOut, ex.what());
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,10 @@
|
||||||
#include "Util/NoticeCenter.h"
|
#include "Util/NoticeCenter.h"
|
||||||
#include "Common/config.h"
|
#include "Common/config.h"
|
||||||
#include "Common/MediaSource.h"
|
#include "Common/MediaSource.h"
|
||||||
|
#include "Http/HttpSession.h"
|
||||||
#include "Http/HttpRequester.h"
|
#include "Http/HttpRequester.h"
|
||||||
#include "Network/Session.h"
|
#include "Network/Session.h"
|
||||||
#include "Rtsp/RtspSession.h"
|
#include "Rtsp/RtspSession.h"
|
||||||
#include "Http/HttpSession.h"
|
|
||||||
#include "WebHook.h"
|
#include "WebHook.h"
|
||||||
#include "WebApi.h"
|
#include "WebApi.h"
|
||||||
|
|
||||||
|
|
@ -52,7 +52,7 @@ const string kAliveInterval = HOOK_FIELD"alive_interval";
|
||||||
const string kRetry = HOOK_FIELD "retry";
|
const string kRetry = HOOK_FIELD "retry";
|
||||||
const string kRetryDelay = HOOK_FIELD "retry_delay";
|
const string kRetryDelay = HOOK_FIELD "retry_delay";
|
||||||
|
|
||||||
onceToken token([](){
|
static onceToken token([]() {
|
||||||
mINI::Instance()[kEnable] = false;
|
mINI::Instance()[kEnable] = false;
|
||||||
mINI::Instance()[kTimeoutSec] = 10;
|
mINI::Instance()[kTimeoutSec] = 10;
|
||||||
// 默认hook地址设置为空,采用默认行为(例如不鉴权)
|
// 默认hook地址设置为空,采用默认行为(例如不鉴权)
|
||||||
|
|
@ -76,7 +76,7 @@ onceToken token([](){
|
||||||
mINI::Instance()[kAliveInterval] = 30.0;
|
mINI::Instance()[kAliveInterval] = 30.0;
|
||||||
mINI::Instance()[kRetry] = 1;
|
mINI::Instance()[kRetry] = 1;
|
||||||
mINI::Instance()[kRetryDelay] = 3.0;
|
mINI::Instance()[kRetryDelay] = 3.0;
|
||||||
},nullptr);
|
});
|
||||||
} // namespace Hook
|
} // namespace Hook
|
||||||
|
|
||||||
namespace Cluster {
|
namespace Cluster {
|
||||||
|
|
@ -93,11 +93,10 @@ static onceToken token([]() {
|
||||||
|
|
||||||
} // namespace Cluster
|
} // namespace Cluster
|
||||||
|
|
||||||
static void parse_http_response(const SockException &ex, const Parser &res,
|
static void parse_http_response(const SockException &ex, const Parser &res, const function<void(const Value &, const string &, bool)> &fun) {
|
||||||
const function<void(const Value &,const string &,const bool &)> &fun){
|
|
||||||
bool should_retry = true;
|
bool should_retry = true;
|
||||||
if (ex) {
|
if (ex) {
|
||||||
auto errStr = StrPrinter << "[network err]:" << ex.what() << endl;
|
auto errStr = StrPrinter << "[network err]:" << ex << endl;
|
||||||
fun(Json::nullValue, errStr, should_retry);
|
fun(Json::nullValue, errStr, should_retry);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -183,7 +182,7 @@ void do_http_hook(const string &url, const ArgsType &body, const function<void(c
|
||||||
Ticker ticker;
|
Ticker ticker;
|
||||||
requester->startRequester(url, [url, func, bodyStr, body, requester, ticker, retry](const SockException &ex, const Parser &res) mutable {
|
requester->startRequester(url, [url, func, bodyStr, body, requester, ticker, retry](const SockException &ex, const Parser &res) mutable {
|
||||||
onceToken token(nullptr, [&]() mutable { requester.reset(); });
|
onceToken token(nullptr, [&]() mutable { requester.reset(); });
|
||||||
parse_http_response(ex, res, [&](const Value &obj, const string &err,const bool &should_retry) {
|
parse_http_response(ex, res, [&](const Value &obj, const string &err, bool should_retry) {
|
||||||
if (!err.empty()) {
|
if (!err.empty()) {
|
||||||
// hook失败
|
// hook失败
|
||||||
WarnL << "hook " << url << " " << ticker.elapsedTime() << "ms,failed" << err << ":" << bodyStr;
|
WarnL << "hook " << url << " " << ticker.elapsedTime() << "ms,failed" << err << ":" << bodyStr;
|
||||||
|
|
@ -272,9 +271,7 @@ static string getPullUrl(const string &origin_fmt, const MediaInfo &info) {
|
||||||
return string(url) + '?' + kEdgeServerParam + '&' + VHOST_KEY + '=' + info._vhost + '&' + info._param_strs;
|
return string(url) + '?' + kEdgeServerParam + '&' + VHOST_KEY + '=' + info._vhost + '&' + info._param_strs;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pullStreamFromOrigin(const vector<string>& urls, size_t index, size_t failed_cnt, const MediaInfo &args,
|
static void pullStreamFromOrigin(const vector<string> &urls, size_t index, size_t failed_cnt, const MediaInfo &args, const function<void()> &closePlayer) {
|
||||||
const function<void()> &closePlayer) {
|
|
||||||
|
|
||||||
GET_CONFIG(float, cluster_timeout_sec, Cluster::kTimeoutSec);
|
GET_CONFIG(float, cluster_timeout_sec, Cluster::kTimeoutSec);
|
||||||
GET_CONFIG(int, retry_count, Cluster::kRetryCount);
|
GET_CONFIG(int, retry_count, Cluster::kRetryCount);
|
||||||
|
|
||||||
|
|
@ -286,8 +283,7 @@ static void pullStreamFromOrigin(const vector<string>& urls, size_t index, size_
|
||||||
option.enable_hls = option.enable_hls || (args._schema == HLS_SCHEMA);
|
option.enable_hls = option.enable_hls || (args._schema == HLS_SCHEMA);
|
||||||
option.enable_mp4 = false;
|
option.enable_mp4 = false;
|
||||||
|
|
||||||
addStreamProxy(args._vhost, args._app, args._streamid, url, retry_count, option, Rtsp::RTP_TCP, timeout_sec,
|
addStreamProxy(args._vhost, args._app, args._streamid, url, retry_count, option, Rtsp::RTP_TCP, timeout_sec, [=](const SockException &ex, const string &key) mutable {
|
||||||
[=](const SockException &ex, const string &key) mutable {
|
|
||||||
if (!ex) {
|
if (!ex) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -359,9 +355,7 @@ void installWebHook(){
|
||||||
body["port"] = sender.get_peer_port();
|
body["port"] = sender.get_peer_port();
|
||||||
body["id"] = sender.getIdentifier();
|
body["id"] = sender.getIdentifier();
|
||||||
// 执行hook
|
// 执行hook
|
||||||
do_http_hook(hook_play,body,[invoker](const Value &obj,const string &err){
|
do_http_hook(hook_play, body, [invoker](const Value &obj, const string &err) { invoker(err); });
|
||||||
invoker(err);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
NoticeCenter::Instance().addListener(&web_hook_tag, Broadcast::kBroadcastFlowReport, [](BroadcastFlowReportArgs) {
|
NoticeCenter::Instance().addListener(&web_hook_tag, Broadcast::kBroadcastFlowReport, [](BroadcastFlowReportArgs) {
|
||||||
|
|
@ -380,7 +374,6 @@ void installWebHook(){
|
||||||
do_http_hook(hook_flowreport, body, nullptr);
|
do_http_hook(hook_flowreport, body, nullptr);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
static const string unAuthedRealm = "unAuthedRealm";
|
static const string unAuthedRealm = "unAuthedRealm";
|
||||||
|
|
||||||
// 监听kBroadcastOnGetRtspRealm事件决定rtsp链接是否需要鉴权(传统的rtsp鉴权方案)才能访问
|
// 监听kBroadcastOnGetRtspRealm事件决定rtsp链接是否需要鉴权(传统的rtsp鉴权方案)才能访问
|
||||||
|
|
@ -432,7 +425,6 @@ void installWebHook(){
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// 监听rtsp、rtmp源注册或注销事件
|
// 监听rtsp、rtmp源注册或注销事件
|
||||||
NoticeCenter::Instance().addListener(&web_hook_tag, Broadcast::kBroadcastMediaChanged, [](BroadcastMediaChangedArgs) {
|
NoticeCenter::Instance().addListener(&web_hook_tag, Broadcast::kBroadcastMediaChanged, [](BroadcastMediaChangedArgs) {
|
||||||
GET_CONFIG(string, hook_stream_chaned, Hook::kOnStreamChanged);
|
GET_CONFIG(string, hook_stream_chaned, Hook::kOnStreamChanged);
|
||||||
|
|
@ -552,9 +544,7 @@ void installWebHook(){
|
||||||
body["passwd"] = passwd;
|
body["passwd"] = passwd;
|
||||||
|
|
||||||
// 执行hook
|
// 执行hook
|
||||||
do_http_hook(hook_shell_login,body, [invoker](const Value &,const string &err){
|
do_http_hook(hook_shell_login, body, [invoker](const Value &, const string &err) { invoker(err); });
|
||||||
invoker(err);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
NoticeCenter::Instance().addListener(&web_hook_tag, Broadcast::kBroadcastStreamNoneReader, [](BroadcastStreamNoneReaderArgs) {
|
NoticeCenter::Instance().addListener(&web_hook_tag, Broadcast::kBroadcastStreamNoneReader, [](BroadcastStreamNoneReaderArgs) {
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ public:
|
||||||
(*_parser) << Option('l',/*该选项简称,如果是\x00则说明无简称*/
|
(*_parser) << Option('l',/*该选项简称,如果是\x00则说明无简称*/
|
||||||
"level",/*该选项全称,每个选项必须有全称;不得为null或空字符串*/
|
"level",/*该选项全称,每个选项必须有全称;不得为null或空字符串*/
|
||||||
Option::ArgRequired,/*该选项后面必须跟值*/
|
Option::ArgRequired,/*该选项后面必须跟值*/
|
||||||
to_string(LTrace).data(),/*该选项默认值*/
|
to_string(LDebug).data(),/*该选项默认值*/
|
||||||
false,/*该选项是否必须赋值,如果没有默认值且为ArgRequired时用户必须提供该参数否则将抛异常*/
|
false,/*该选项是否必须赋值,如果没有默认值且为ArgRequired时用户必须提供该参数否则将抛异常*/
|
||||||
"日志等级,LTrace~LError(0~4)",/*该选项说明文字*/
|
"日志等级,LTrace~LError(0~4)",/*该选项说明文字*/
|
||||||
nullptr);
|
nullptr);
|
||||||
|
|
@ -160,6 +160,14 @@ public:
|
||||||
"启动事件触发线程数",/*该选项说明文字*/
|
"启动事件触发线程数",/*该选项说明文字*/
|
||||||
nullptr);
|
nullptr);
|
||||||
|
|
||||||
|
(*_parser) << Option(0,/*该选项简称,如果是\x00则说明无简称*/
|
||||||
|
"affinity",/*该选项全称,每个选项必须有全称;不得为null或空字符串*/
|
||||||
|
Option::ArgRequired,/*该选项后面必须跟值*/
|
||||||
|
to_string(1).data(),/*该选项默认值*/
|
||||||
|
false,/*该选项是否必须赋值,如果没有默认值且为ArgRequired时用户必须提供该参数否则将抛异常*/
|
||||||
|
"是否启动cpu亲和性设置",/*该选项说明文字*/
|
||||||
|
nullptr);
|
||||||
|
|
||||||
#if defined(ENABLE_VERSION)
|
#if defined(ENABLE_VERSION)
|
||||||
(*_parser) << Option('v', "version", Option::ArgNone, nullptr, false, "显示版本号",
|
(*_parser) << Option('v', "version", Option::ArgNone, nullptr, false, "显示版本号",
|
||||||
[](const std::shared_ptr<ostream> &stream, const string &arg) -> bool {
|
[](const std::shared_ptr<ostream> &stream, const string &arg) -> bool {
|
||||||
|
|
@ -200,15 +208,16 @@ int start_main(int argc,char *argv[]) {
|
||||||
g_ini_file = cmd_main["config"];
|
g_ini_file = cmd_main["config"];
|
||||||
string ssl_file = cmd_main["ssl"];
|
string ssl_file = cmd_main["ssl"];
|
||||||
int threads = cmd_main["threads"];
|
int threads = cmd_main["threads"];
|
||||||
|
bool affinity = cmd_main["affinity"];
|
||||||
|
|
||||||
//设置日志
|
//设置日志
|
||||||
Logger::Instance().add(std::make_shared<ConsoleChannel>("ConsoleChannel", logLevel));
|
Logger::Instance().add(std::make_shared<ConsoleChannel>("ConsoleChannel", logLevel));
|
||||||
#ifndef ANDROID
|
#if !defined(ANDROID)
|
||||||
auto fileChannel = std::make_shared<FileChannel>("FileChannel", exeDir() + "log/", logLevel);
|
auto fileChannel = std::make_shared<FileChannel>("FileChannel", exeDir() + "log/", logLevel);
|
||||||
// 日志最多保存天数
|
// 日志最多保存天数
|
||||||
fileChannel->setMaxDay(cmd_main["max_day"]);
|
fileChannel->setMaxDay(cmd_main["max_day"]);
|
||||||
Logger::Instance().add(fileChannel);
|
Logger::Instance().add(fileChannel);
|
||||||
#endif//
|
#endif // !defined(ANDROID)
|
||||||
|
|
||||||
#if !defined(_WIN32)
|
#if !defined(_WIN32)
|
||||||
pid_t pid = getpid();
|
pid_t pid = getpid();
|
||||||
|
|
@ -252,24 +261,27 @@ int start_main(int argc,char *argv[]) {
|
||||||
uint16_t httpsPort = mINI::Instance()[Http::kSSLPort];
|
uint16_t httpsPort = mINI::Instance()[Http::kSSLPort];
|
||||||
uint16_t rtpPort = mINI::Instance()[RtpProxy::kPort];
|
uint16_t rtpPort = mINI::Instance()[RtpProxy::kPort];
|
||||||
|
|
||||||
//设置poller线程数,该函数必须在使用ZLToolKit网络相关对象之前调用才能生效
|
//设置poller线程数和cpu亲和性,该函数必须在使用ZLToolKit网络相关对象之前调用才能生效
|
||||||
|
//如果需要调用getSnap和addFFmpegSource接口,可以关闭cpu亲和性
|
||||||
|
|
||||||
EventPollerPool::setPoolSize(threads);
|
EventPollerPool::setPoolSize(threads);
|
||||||
|
EventPollerPool::enableCpuAffinity(affinity);
|
||||||
|
|
||||||
//简单的telnet服务器,可用于服务器调试,但是不能使用23端口,否则telnet上了莫名其妙的现象
|
//简单的telnet服务器,可用于服务器调试,但是不能使用23端口,否则telnet上了莫名其妙的现象
|
||||||
//测试方法:telnet 127.0.0.1 9000
|
//测试方法:telnet 127.0.0.1 9000
|
||||||
auto shellSrv = std::make_shared<TcpServer>();
|
auto shellSrv = std::make_shared<TcpServer>();
|
||||||
|
|
||||||
//rtsp[s]服务器, 可用于诸如亚马逊echo show这样的设备访问
|
//rtsp[s]服务器, 可用于诸如亚马逊echo show这样的设备访问
|
||||||
auto rtspSrv = std::make_shared<TcpServer>();;
|
auto rtspSrv = std::make_shared<TcpServer>();
|
||||||
auto rtspSSLSrv = std::make_shared<TcpServer>();;
|
auto rtspSSLSrv = std::make_shared<TcpServer>();
|
||||||
|
|
||||||
//rtmp[s]服务器
|
//rtmp[s]服务器
|
||||||
auto rtmpSrv = std::make_shared<TcpServer>();;
|
auto rtmpSrv = std::make_shared<TcpServer>();
|
||||||
auto rtmpsSrv = std::make_shared<TcpServer>();;
|
auto rtmpsSrv = std::make_shared<TcpServer>();
|
||||||
|
|
||||||
//http[s]服务器
|
//http[s]服务器
|
||||||
auto httpSrv = std::make_shared<TcpServer>();;
|
auto httpSrv = std::make_shared<TcpServer>();
|
||||||
auto httpsSrv = std::make_shared<TcpServer>();;
|
auto httpsSrv = std::make_shared<TcpServer>();
|
||||||
|
|
||||||
#if defined(ENABLE_RTPPROXY)
|
#if defined(ENABLE_RTPPROXY)
|
||||||
//GB28181 rtp推流端口,支持UDP/TCP
|
//GB28181 rtp推流端口,支持UDP/TCP
|
||||||
|
|
|
||||||
|
|
@ -270,7 +270,7 @@ void MultiMediaSourceMuxer::startSendRtp(MediaSource &sender, const MediaSourceE
|
||||||
if (auto strong_self = weak_self.lock()) {
|
if (auto strong_self = weak_self.lock()) {
|
||||||
// 可能归属线程发生变更
|
// 可能归属线程发生变更
|
||||||
strong_self->getOwnerPoller(MediaSource::NullMediaSource())->async([=]() {
|
strong_self->getOwnerPoller(MediaSource::NullMediaSource())->async([=]() {
|
||||||
WarnL << "stream:" << strong_self->shortUrl() << " stop send rtp:" << ssrc << ", reason:" << ex.what();
|
WarnL << "stream:" << strong_self->shortUrl() << " stop send rtp:" << ssrc << ", reason:" << ex;
|
||||||
strong_self->_rtp_sender.erase(ssrc);
|
strong_self->_rtp_sender.erase(ssrc);
|
||||||
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastSendRtpStopped, *strong_self, ssrc, ex);
|
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastSendRtpStopped, *strong_self, ssrc, ex);
|
||||||
});
|
});
|
||||||
|
|
@ -393,12 +393,11 @@ void MultiMediaSourceMuxer::createGopCacheIfNeed() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
weak_ptr<MultiMediaSourceMuxer> weak_self = shared_from_this();
|
weak_ptr<MultiMediaSourceMuxer> weak_self = shared_from_this();
|
||||||
_ring = std::make_shared<RingType>(1024, [weak_self](int size) {
|
auto src = std::make_shared<MediaSourceForMuxer>(weak_self.lock());
|
||||||
auto strong_self = weak_self.lock();
|
_ring = std::make_shared<RingType>(1024, [weak_self, src](int size) {
|
||||||
if (strong_self) {
|
if (auto strong_self = weak_self.lock()) {
|
||||||
// 切换到归属线程
|
// 切换到归属线程
|
||||||
strong_self->getOwnerPoller(MediaSource::NullMediaSource())->async([=]() {
|
strong_self->getOwnerPoller(MediaSource::NullMediaSource())->async([=]() {
|
||||||
auto src = std::make_shared<MediaSourceForMuxer>(strong_self);
|
|
||||||
strong_self->onReaderChanged(*src, strong_self->totalReaderCount());
|
strong_self->onReaderChanged(*src, strong_self->totalReaderCount());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,8 @@ namespace mediakit{
|
||||||
class Track : public FrameDispatcher , public CodecInfo{
|
class Track : public FrameDispatcher , public CodecInfo{
|
||||||
public:
|
public:
|
||||||
using Ptr = std::shared_ptr<Track>;
|
using Ptr = std::shared_ptr<Track>;
|
||||||
Track(){}
|
Track() = default;
|
||||||
|
virtual ~Track() = default;
|
||||||
virtual ~Track(){}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否准备好,准备好才能获取譬如sps pps等信息
|
* 是否准备好,准备好才能获取譬如sps pps等信息
|
||||||
|
|
@ -177,8 +176,8 @@ private:
|
||||||
|
|
||||||
class TrackSource{
|
class TrackSource{
|
||||||
public:
|
public:
|
||||||
TrackSource(){}
|
TrackSource() = default;
|
||||||
virtual ~TrackSource(){}
|
virtual ~TrackSource() = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取全部的Track
|
* 获取全部的Track
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,7 @@ void HlsPlayer::fetchSegment() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (err) {
|
if (err) {
|
||||||
WarnL << "Download ts segment " << url << " failed:" << err.what();
|
WarnL << "Download ts segment " << url << " failed:" << err;
|
||||||
if (err.getErrCode() == Err_timeout) {
|
if (err.getErrCode() == Err_timeout) {
|
||||||
strong_self->_timeout_multiple = MAX(strong_self->_timeout_multiple + 1, MAX_TIMEOUT_MULTIPLE);
|
strong_self->_timeout_multiple = MAX(strong_self->_timeout_multiple + 1, MAX_TIMEOUT_MULTIPLE);
|
||||||
}else{
|
}else{
|
||||||
|
|
|
||||||
|
|
@ -189,7 +189,7 @@ public:
|
||||||
_data = map_addr.get() + offset;
|
_data = map_addr.get() + offset;
|
||||||
_size = size;
|
_size = size;
|
||||||
}
|
}
|
||||||
~BufferMmap() override {};
|
~BufferMmap() override = default;
|
||||||
//返回数据长度
|
//返回数据长度
|
||||||
char *data() const override { return _data; }
|
char *data() const override { return _data; }
|
||||||
size_t size() const override { return _size; }
|
size_t size() const override { return _size; }
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,9 @@ namespace mediakit {
|
||||||
class HttpBody : public std::enable_shared_from_this<HttpBody>{
|
class HttpBody : public std::enable_shared_from_this<HttpBody>{
|
||||||
public:
|
public:
|
||||||
using Ptr = std::shared_ptr<HttpBody>;
|
using Ptr = std::shared_ptr<HttpBody>;
|
||||||
HttpBody(){}
|
HttpBody() = default;
|
||||||
|
|
||||||
virtual ~HttpBody(){}
|
virtual ~HttpBody() = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 剩余数据大小,如果返回-1, 那么就不设置content-length
|
* 剩余数据大小,如果返回-1, 那么就不设置content-length
|
||||||
|
|
@ -151,7 +151,7 @@ public:
|
||||||
* @param boundary boundary字符串
|
* @param boundary boundary字符串
|
||||||
*/
|
*/
|
||||||
HttpMultiFormBody(const HttpArgs &args,const std::string &filePath,const std::string &boundary = "0xKhTmLbOuNdArY");
|
HttpMultiFormBody(const HttpArgs &args,const std::string &filePath,const std::string &boundary = "0xKhTmLbOuNdArY");
|
||||||
virtual ~HttpMultiFormBody(){}
|
virtual ~HttpMultiFormBody() = default;
|
||||||
int64_t remainSize() override ;
|
int64_t remainSize() override ;
|
||||||
toolkit::Buffer::Ptr readData(size_t size) override;
|
toolkit::Buffer::Ptr readData(size_t size) override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,8 @@ class HttpCookie {
|
||||||
public:
|
public:
|
||||||
using Ptr = std::shared_ptr<HttpCookie>;
|
using Ptr = std::shared_ptr<HttpCookie>;
|
||||||
friend class HttpCookieStorage;
|
friend class HttpCookieStorage;
|
||||||
HttpCookie(){}
|
HttpCookie() = default;
|
||||||
~HttpCookie(){}
|
~HttpCookie() = default;
|
||||||
|
|
||||||
void setPath(const std::string &path);
|
void setPath(const std::string &path);
|
||||||
void setHost(const std::string &host);
|
void setHost(const std::string &host);
|
||||||
|
|
@ -52,12 +52,14 @@ private:
|
||||||
*/
|
*/
|
||||||
class HttpCookieStorage{
|
class HttpCookieStorage{
|
||||||
public:
|
public:
|
||||||
~HttpCookieStorage(){}
|
~HttpCookieStorage() = default;
|
||||||
static HttpCookieStorage &Instance();
|
static HttpCookieStorage &Instance();
|
||||||
void set(const HttpCookie::Ptr &cookie);
|
void set(const HttpCookie::Ptr &cookie);
|
||||||
std::vector<HttpCookie::Ptr> get(const std::string &host,const std::string &path);
|
std::vector<HttpCookie::Ptr> get(const std::string &host,const std::string &path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HttpCookieStorage(){};
|
HttpCookieStorage() = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<std::string/*host*/, std::map<std::string/*cookie path*/,std::map<std::string/*cookie_key*/, HttpCookie::Ptr> > > _all_cookie;
|
std::unordered_map<std::string/*host*/, std::map<std::string/*cookie path*/,std::map<std::string/*cookie_key*/, HttpCookie::Ptr> > > _all_cookie;
|
||||||
std::mutex _mtx_cookie;
|
std::mutex _mtx_cookie;
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,8 @@ public:
|
||||||
typedef std::function<void(int code, const StrCaseMap &headerOut, const HttpBody::Ptr &body)> HttpResponseInvokerLambda0;
|
typedef std::function<void(int code, const StrCaseMap &headerOut, const HttpBody::Ptr &body)> HttpResponseInvokerLambda0;
|
||||||
typedef std::function<void(int code, const StrCaseMap &headerOut, const std::string &body)> HttpResponseInvokerLambda1;
|
typedef std::function<void(int code, const StrCaseMap &headerOut, const std::string &body)> HttpResponseInvokerLambda1;
|
||||||
|
|
||||||
HttpResponseInvokerImp(){}
|
HttpResponseInvokerImp() = default;
|
||||||
~HttpResponseInvokerImp(){}
|
~HttpResponseInvokerImp() = default;
|
||||||
template<typename C>
|
template<typename C>
|
||||||
HttpResponseInvokerImp(const C &c):HttpResponseInvokerImp(typename toolkit::function_traits<C>::stl_function_type(c)) {}
|
HttpResponseInvokerImp(const C &c):HttpResponseInvokerImp(typename toolkit::function_traits<C>::stl_function_type(c)) {}
|
||||||
HttpResponseInvokerImp(const HttpResponseInvokerLambda0 &lambda);
|
HttpResponseInvokerImp(const HttpResponseInvokerLambda0 &lambda);
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@ namespace mediakit {
|
||||||
|
|
||||||
class HttpRequestSplitter {
|
class HttpRequestSplitter {
|
||||||
public:
|
public:
|
||||||
HttpRequestSplitter(){};
|
HttpRequestSplitter() = default;
|
||||||
virtual ~HttpRequestSplitter(){};
|
virtual ~HttpRequestSplitter() = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加数据
|
* 添加数据
|
||||||
|
|
|
||||||
|
|
@ -24,14 +24,11 @@ using namespace toolkit;
|
||||||
namespace mediakit {
|
namespace mediakit {
|
||||||
|
|
||||||
HttpSession::HttpSession(const Socket::Ptr &pSock) : Session(pSock) {
|
HttpSession::HttpSession(const Socket::Ptr &pSock) : Session(pSock) {
|
||||||
TraceP(this);
|
|
||||||
GET_CONFIG(uint32_t,keep_alive_sec,Http::kKeepAliveSecond);
|
GET_CONFIG(uint32_t,keep_alive_sec,Http::kKeepAliveSecond);
|
||||||
pSock->setSendTimeOutSecond(keep_alive_sec);
|
pSock->setSendTimeOutSecond(keep_alive_sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpSession::~HttpSession() {
|
HttpSession::~HttpSession() = default;
|
||||||
TraceP(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HttpSession::Handle_Req_HEAD(ssize_t &content_len){
|
void HttpSession::Handle_Req_HEAD(ssize_t &content_len){
|
||||||
//暂时全部返回200 OK,因为HTTP GET存在按需生成流的操作,所以不能按照HTTP GET的流程返回
|
//暂时全部返回200 OK,因为HTTP GET存在按需生成流的操作,所以不能按照HTTP GET的流程返回
|
||||||
|
|
@ -104,7 +101,7 @@ void HttpSession::onError(const SockException& err) {
|
||||||
uint64_t duration = _ticker.createdTime() / 1000;
|
uint64_t duration = _ticker.createdTime() / 1000;
|
||||||
WarnP(this) << "FLV/TS/FMP4播放器("
|
WarnP(this) << "FLV/TS/FMP4播放器("
|
||||||
<< _mediaInfo.shortUrl()
|
<< _mediaInfo.shortUrl()
|
||||||
<< ")断开:" << err.what()
|
<< ")断开:" << err
|
||||||
<< ",耗时(s):" << duration;
|
<< ",耗时(s):" << duration;
|
||||||
|
|
||||||
GET_CONFIG(uint32_t, iFlowThreshold, General::kFlowThreshold);
|
GET_CONFIG(uint32_t, iFlowThreshold, General::kFlowThreshold);
|
||||||
|
|
@ -114,9 +111,6 @@ void HttpSession::onError(const SockException& err) {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//http客户端
|
|
||||||
TraceP(this) << err.what();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpSession::onManager() {
|
void HttpSession::onManager() {
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ public:
|
||||||
|
|
||||||
template <typename... ArgsType>
|
template <typename... ArgsType>
|
||||||
ClientTypeImp(ArgsType &&...args) : ClientType(std::forward<ArgsType>(args)...) {}
|
ClientTypeImp(ArgsType &&...args) : ClientType(std::forward<ArgsType>(args)...) {}
|
||||||
~ClientTypeImp() override {};
|
~ClientTypeImp() override = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ template<typename Creator, typename HttpSessionType = mediakit::HttpSession, med
|
||||||
class WebSocketSessionBase : public HttpSessionType {
|
class WebSocketSessionBase : public HttpSessionType {
|
||||||
public:
|
public:
|
||||||
WebSocketSessionBase(const toolkit::Socket::Ptr &pSock) : HttpSessionType(pSock){}
|
WebSocketSessionBase(const toolkit::Socket::Ptr &pSock) : HttpSessionType(pSock){}
|
||||||
virtual ~WebSocketSessionBase(){}
|
virtual ~WebSocketSessionBase() = default;
|
||||||
|
|
||||||
//收到eof或其他导致脱离TcpServer事件的回调
|
//收到eof或其他导致脱离TcpServer事件的回调
|
||||||
void onError(const toolkit::SockException &err) override{
|
void onError(const toolkit::SockException &err) override{
|
||||||
|
|
@ -248,7 +248,7 @@ template<typename SessionType,typename HttpSessionType = mediakit::HttpSession,
|
||||||
class WebSocketSession : public WebSocketSessionBase<SessionCreator<SessionType>,HttpSessionType,DataType>{
|
class WebSocketSession : public WebSocketSessionBase<SessionCreator<SessionType>,HttpSessionType,DataType>{
|
||||||
public:
|
public:
|
||||||
WebSocketSession(const toolkit::Socket::Ptr &pSock) : WebSocketSessionBase<SessionCreator<SessionType>,HttpSessionType,DataType>(pSock){}
|
WebSocketSession(const toolkit::Socket::Ptr &pSock) : WebSocketSessionBase<SessionCreator<SessionType>,HttpSessionType,DataType>(pSock){}
|
||||||
virtual ~WebSocketSession(){}
|
virtual ~WebSocketSession() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //ZLMEDIAKIT_WEBSOCKETSESSION_H
|
#endif //ZLMEDIAKIT_WEBSOCKETSESSION_H
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ public:
|
||||||
//根据内存地址设置掩码随机数
|
//根据内存地址设置掩码随机数
|
||||||
_mask.assign((uint8_t*)(&ptr), (uint8_t*)(&ptr) + 4);
|
_mask.assign((uint8_t*)(&ptr), (uint8_t*)(&ptr) + 4);
|
||||||
}
|
}
|
||||||
virtual ~WebSocketHeader(){}
|
virtual ~WebSocketHeader() = default;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool _fin;
|
bool _fin;
|
||||||
|
|
@ -71,7 +71,7 @@ public:
|
||||||
WebSocketBuffer(WebSocketHeader::Type headType, bool fin, ARGS &&...args)
|
WebSocketBuffer(WebSocketHeader::Type headType, bool fin, ARGS &&...args)
|
||||||
: toolkit::BufferString(std::forward<ARGS>(args)...), _fin(fin), _head_type(headType){}
|
: toolkit::BufferString(std::forward<ARGS>(args)...), _fin(fin), _head_type(headType){}
|
||||||
|
|
||||||
~WebSocketBuffer() override {}
|
~WebSocketBuffer() override = default;
|
||||||
|
|
||||||
WebSocketHeader::Type headType() const { return _head_type; }
|
WebSocketHeader::Type headType() const { return _head_type; }
|
||||||
|
|
||||||
|
|
@ -84,8 +84,8 @@ private:
|
||||||
|
|
||||||
class WebSocketSplitter : public WebSocketHeader{
|
class WebSocketSplitter : public WebSocketHeader{
|
||||||
public:
|
public:
|
||||||
WebSocketSplitter(){}
|
WebSocketSplitter() = default;
|
||||||
virtual ~WebSocketSplitter(){}
|
virtual ~WebSocketSplitter() = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 输入数据以便解包webSocket数据以及处理粘包问题
|
* 输入数据以便解包webSocket数据以及处理粘包问题
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,13 @@ void PlayerProxy::play(const string &strUrlTmp) {
|
||||||
strongSelf->_on_close(err);
|
strongSelf->_on_close(err);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
try {
|
||||||
MediaPlayer::play(strUrlTmp);
|
MediaPlayer::play(strUrlTmp);
|
||||||
|
} catch (std::exception &ex) {
|
||||||
|
ErrorL << ex.what();
|
||||||
|
_on_play_result(SockException(Err_other, ex.what()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
_pull_url = strUrlTmp;
|
_pull_url = strUrlTmp;
|
||||||
setDirectProxy();
|
setDirectProxy();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,18 @@ bool MP4MuxerInterface::inputFrame(const Frame::Ptr &frame) {
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case CodecJPEG:{
|
||||||
|
int64_t dts_out, pts_out;
|
||||||
|
track_info.stamp.revise(frame->dts(), frame->pts(), dts_out, pts_out);
|
||||||
|
mp4_writer_write(_mov_writter.get(),
|
||||||
|
track_info.track_id,
|
||||||
|
frame->data(),
|
||||||
|
frame->size(),
|
||||||
|
pts_out,
|
||||||
|
dts_out,
|
||||||
|
frame->keyFrame() ? MOV_AV_FLAG_KEYFREAME : 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
int64_t dts_out, pts_out;
|
int64_t dts_out, pts_out;
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ namespace mediakit {
|
||||||
|
|
||||||
class MpegMuxer : public MediaSinkInterface {
|
class MpegMuxer : public MediaSinkInterface {
|
||||||
public:
|
public:
|
||||||
MpegMuxer(bool is_ps) {};
|
MpegMuxer(bool is_ps) = default;
|
||||||
~MpegMuxer() override = default;
|
~MpegMuxer() override = default;
|
||||||
bool addTrack(const Track::Ptr &track) override { return false; }
|
bool addTrack(const Track::Ptr &track) override { return false; }
|
||||||
void resetTracks() override {}
|
void resetTracks() override {}
|
||||||
|
|
|
||||||
|
|
@ -242,11 +242,9 @@ vector<RtcpHeader *> RtcpHeader::loadFromBytes(char *data, size_t len) {
|
||||||
class BufferRtcp : public Buffer {
|
class BufferRtcp : public Buffer {
|
||||||
public:
|
public:
|
||||||
BufferRtcp(std::shared_ptr<RtcpHeader> rtcp) { _rtcp = std::move(rtcp); }
|
BufferRtcp(std::shared_ptr<RtcpHeader> rtcp) { _rtcp = std::move(rtcp); }
|
||||||
|
~BufferRtcp() override = default;
|
||||||
~BufferRtcp() override {}
|
|
||||||
|
|
||||||
char *data() const override { return (char *)_rtcp.get(); }
|
char *data() const override { return (char *)_rtcp.get(); }
|
||||||
|
|
||||||
size_t size() const override { return _rtcp->getSize(); }
|
size_t size() const override { return _rtcp->getSize(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -551,7 +549,7 @@ const void *RtcpFB::getFciPtr() const {
|
||||||
|
|
||||||
size_t RtcpFB::getFciSize() const {
|
size_t RtcpFB::getFciSize() const {
|
||||||
auto fci_len = (ssize_t)getSize() - getPaddingSize() - sizeof(RtcpFB);
|
auto fci_len = (ssize_t)getSize() - getPaddingSize() - sizeof(RtcpFB);
|
||||||
CHECK(fci_len >= 0);
|
CHECK(getSize() >= getPaddingSize() + sizeof(RtcpFB));
|
||||||
return fci_len;
|
return fci_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ TitleMeta::TitleMeta(float dur_sec, size_t fileSize, const std::map<std::string,
|
||||||
{
|
{
|
||||||
_metadata.set("duration", dur_sec);
|
_metadata.set("duration", dur_sec);
|
||||||
_metadata.set("fileSize", (int)fileSize);
|
_metadata.set("fileSize", (int)fileSize);
|
||||||
_metadata.set("server", kServerName);
|
_metadata.set("title", std::string("Streamed by ") + kServerName);
|
||||||
for (auto &pr : header) {
|
for (auto &pr : header) {
|
||||||
_metadata.set(pr.first, pr.second);
|
_metadata.set(pr.first, pr.second);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -208,7 +208,7 @@ public:
|
||||||
using Ptr = std::shared_ptr<Metadata>;
|
using Ptr = std::shared_ptr<Metadata>;
|
||||||
|
|
||||||
Metadata(): _metadata(AMF_OBJECT) {}
|
Metadata(): _metadata(AMF_OBJECT) {}
|
||||||
virtual ~Metadata(){}
|
virtual ~Metadata() = default;
|
||||||
const AMFValue &getMetadata() const{
|
const AMFValue &getMetadata() const{
|
||||||
return _metadata;
|
return _metadata;
|
||||||
}
|
}
|
||||||
|
|
@ -239,7 +239,7 @@ public:
|
||||||
using Ptr = std::shared_ptr<VideoMeta>;
|
using Ptr = std::shared_ptr<VideoMeta>;
|
||||||
|
|
||||||
VideoMeta(const VideoTrack::Ptr &video);
|
VideoMeta(const VideoTrack::Ptr &video);
|
||||||
virtual ~VideoMeta(){}
|
virtual ~VideoMeta() = default;
|
||||||
|
|
||||||
CodecId getCodecId() const override{
|
CodecId getCodecId() const override{
|
||||||
return _codecId;
|
return _codecId;
|
||||||
|
|
@ -253,8 +253,7 @@ public:
|
||||||
using Ptr = std::shared_ptr<AudioMeta>;
|
using Ptr = std::shared_ptr<AudioMeta>;
|
||||||
|
|
||||||
AudioMeta(const AudioTrack::Ptr &audio);
|
AudioMeta(const AudioTrack::Ptr &audio);
|
||||||
|
virtual ~AudioMeta() = default;
|
||||||
virtual ~AudioMeta(){}
|
|
||||||
|
|
||||||
CodecId getCodecId() const override{
|
CodecId getCodecId() const override{
|
||||||
return _codecId;
|
return _codecId;
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void setMetaData(const AMFValue &metadata) {
|
virtual void setMetaData(const AMFValue &metadata) {
|
||||||
_metadata = metadata;
|
_metadata = metadata;
|
||||||
_metadata.set("server", kServerName);
|
_metadata.set("title", std::string("Streamed by ") + kServerName);
|
||||||
_have_video = _metadata["videocodecid"];
|
_have_video = _metadata["videocodecid"];
|
||||||
_have_audio = _metadata["audiocodecid"];
|
_have_audio = _metadata["audiocodecid"];
|
||||||
if (_ring) {
|
if (_ring) {
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ void RtmpPlayer::onPlayResult_l(const SockException &ex, bool handshake_done) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
WarnL << ex.getErrCode() << " " << ex.what();
|
WarnL << ex.getErrCode() << " " << ex;
|
||||||
if (!handshake_done) {
|
if (!handshake_done) {
|
||||||
//开始播放阶段
|
//开始播放阶段
|
||||||
_play_timer.reset();
|
_play_timer.reset();
|
||||||
|
|
|
||||||
|
|
@ -187,7 +187,7 @@ public:
|
||||||
_size = size;
|
_size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
~BufferPartial() override{}
|
~BufferPartial() override = default;
|
||||||
|
|
||||||
char *data() const override {
|
char *data() const override {
|
||||||
return _data;
|
return _data;
|
||||||
|
|
|
||||||
|
|
@ -19,14 +19,11 @@ using namespace toolkit;
|
||||||
namespace mediakit {
|
namespace mediakit {
|
||||||
|
|
||||||
RtmpSession::RtmpSession(const Socket::Ptr &sock) : Session(sock) {
|
RtmpSession::RtmpSession(const Socket::Ptr &sock) : Session(sock) {
|
||||||
DebugP(this);
|
|
||||||
GET_CONFIG(uint32_t,keep_alive_sec,Rtmp::kKeepAliveSecond);
|
GET_CONFIG(uint32_t,keep_alive_sec,Rtmp::kKeepAliveSecond);
|
||||||
sock->setSendTimeOutSecond(keep_alive_sec);
|
sock->setSendTimeOutSecond(keep_alive_sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
RtmpSession::~RtmpSession() {
|
RtmpSession::~RtmpSession() = default;
|
||||||
DebugP(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RtmpSession::onError(const SockException& err) {
|
void RtmpSession::onError(const SockException& err) {
|
||||||
bool is_player = !_push_src_ownership;
|
bool is_player = !_push_src_ownership;
|
||||||
|
|
|
||||||
|
|
@ -336,7 +336,7 @@ void RtpSender::onFlushRtpList(shared_ptr<List<Buffer::Ptr> > rtp_list) {
|
||||||
|
|
||||||
void RtpSender::onErr(const SockException &ex) {
|
void RtpSender::onErr(const SockException &ex) {
|
||||||
_is_connect = false;
|
_is_connect = false;
|
||||||
WarnL << "send rtp connection lost: " << ex.what();
|
WarnL << "send rtp connection lost: " << ex;
|
||||||
onClose(ex);
|
onClose(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,8 @@ public:
|
||||||
process->setOnDetach(std::move(strong_self->_on_detach));
|
process->setOnDetach(std::move(strong_self->_on_detach));
|
||||||
}
|
}
|
||||||
if (!process) { // process 未创建,触发rtp server 超时事件
|
if (!process) { // process 未创建,触发rtp server 超时事件
|
||||||
NoticeCenter::Instance().emitEvent(Broadcast::KBroadcastRtpServerTimeout,strong_self->_local_port,strong_self->_stream_id,(int)strong_self->_tcp_mode,strong_self->_re_use_port,strong_self->_ssrc);
|
NoticeCenter::Instance().emitEvent(Broadcast::KBroadcastRtpServerTimeout, strong_self->_local_port, strong_self->_stream_id,
|
||||||
|
(int)strong_self->_tcp_mode, strong_self->_re_use_port, strong_self->_ssrc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -198,11 +199,14 @@ void RtpServer::start(uint16_t local_port, const string &stream_id, TcpMode tcp_
|
||||||
helper->startRtcp();
|
helper->startRtcp();
|
||||||
helper->setRtpServerInfo(local_port, tcp_mode, re_use_port, ssrc, only_audio);
|
helper->setRtpServerInfo(local_port, tcp_mode, re_use_port, ssrc, only_audio);
|
||||||
bool bind_peer_addr = false;
|
bool bind_peer_addr = false;
|
||||||
rtp_socket->setOnRead([rtp_socket, helper, ssrc, bind_peer_addr](const Buffer::Ptr &buf, struct sockaddr *addr, int addr_len) mutable {
|
auto ssrc_ptr = std::make_shared<uint32_t>(ssrc);
|
||||||
|
_ssrc = ssrc_ptr;
|
||||||
|
rtp_socket->setOnRead([rtp_socket, helper, ssrc_ptr, bind_peer_addr](const Buffer::Ptr &buf, struct sockaddr *addr, int addr_len) mutable {
|
||||||
RtpHeader *header = (RtpHeader *)buf->data();
|
RtpHeader *header = (RtpHeader *)buf->data();
|
||||||
auto rtp_ssrc = ntohl(header->ssrc);
|
auto rtp_ssrc = ntohl(header->ssrc);
|
||||||
|
auto ssrc = *ssrc_ptr;
|
||||||
if (ssrc && rtp_ssrc != ssrc) {
|
if (ssrc && rtp_ssrc != ssrc) {
|
||||||
WarnL << "ssrc不匹配,rtp已丢弃:" << rtp_ssrc << " != " << ssrc;
|
WarnL << "ssrc mismatched, rtp dropped: " << rtp_ssrc << " != " << ssrc;
|
||||||
} else {
|
} else {
|
||||||
if (!bind_peer_addr) {
|
if (!bind_peer_addr) {
|
||||||
//绑定对方ip+端口,防止多个设备或一个设备多次推流从而日志报ssrc不匹配问题
|
//绑定对方ip+端口,防止多个设备或一个设备多次推流从而日志报ssrc不匹配问题
|
||||||
|
|
@ -213,19 +217,11 @@ void RtpServer::start(uint16_t local_port, const string &stream_id, TcpMode tcp_
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
#if 1
|
|
||||||
//单端口多线程接收多个流,根据ssrc区分流
|
//单端口多线程接收多个流,根据ssrc区分流
|
||||||
udp_server = std::make_shared<UdpServer>(rtp_socket->getPoller());
|
udp_server = std::make_shared<UdpServer>(rtp_socket->getPoller());
|
||||||
(*udp_server)[RtpSession::kOnlyAudio] = only_audio;
|
(*udp_server)[RtpSession::kOnlyAudio] = only_audio;
|
||||||
udp_server->start<RtpSession>(local_port, local_ip);
|
udp_server->start<RtpSession>(local_port, local_ip);
|
||||||
rtp_socket = nullptr;
|
rtp_socket = nullptr;
|
||||||
#else
|
|
||||||
//单端口单线程接收多个流
|
|
||||||
auto &ref = RtpSelector::Instance();
|
|
||||||
rtp_socket->setOnRead([&ref, rtp_socket](const Buffer::Ptr &buf, struct sockaddr *addr, int) {
|
|
||||||
ref.inputRtp(rtp_socket, buf->data(), buf->size(), addr);
|
|
||||||
});
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_on_cleanup = [rtp_socket, stream_id]() {
|
_on_cleanup = [rtp_socket, stream_id]() {
|
||||||
|
|
@ -264,7 +260,7 @@ void RtpServer::connectToServer(const std::string &url, uint16_t port, const fun
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (err) {
|
if (err) {
|
||||||
WarnL << "连接到服务器 " << url << ":" << port << " 失败 " << err.what();
|
WarnL << "连接到服务器 " << url << ":" << port << " 失败 " << err;
|
||||||
} else {
|
} else {
|
||||||
InfoL << "连接到服务器 " << url << ":" << port << " 成功";
|
InfoL << "连接到服务器 " << url << ":" << port << " 成功";
|
||||||
strong_self->onConnect();
|
strong_self->onConnect();
|
||||||
|
|
@ -288,5 +284,15 @@ void RtpServer::onConnect() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RtpServer::updateSSRC(uint32_t ssrc) {
|
||||||
|
if (_ssrc) {
|
||||||
|
*_ssrc = ssrc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_tcp_server) {
|
||||||
|
(*_tcp_server)[RtpSession::kSSRC] = ssrc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}//namespace mediakit
|
}//namespace mediakit
|
||||||
#endif//defined(ENABLE_RTPPROXY)
|
#endif//defined(ENABLE_RTPPROXY)
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,11 @@ public:
|
||||||
*/
|
*/
|
||||||
void setOnDetach(std::function<void()> cb);
|
void setOnDetach(std::function<void()> cb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新ssrc
|
||||||
|
*/
|
||||||
|
void updateSSRC(uint32_t ssrc);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// tcp主动模式连接服务器成功回调
|
// tcp主动模式连接服务器成功回调
|
||||||
void onConnect();
|
void onConnect();
|
||||||
|
|
@ -72,6 +77,7 @@ protected:
|
||||||
toolkit::Socket::Ptr _rtp_socket;
|
toolkit::Socket::Ptr _rtp_socket;
|
||||||
toolkit::UdpServer::Ptr _udp_server;
|
toolkit::UdpServer::Ptr _udp_server;
|
||||||
toolkit::TcpServer::Ptr _tcp_server;
|
toolkit::TcpServer::Ptr _tcp_server;
|
||||||
|
std::shared_ptr<uint32_t> _ssrc;
|
||||||
std::shared_ptr<RtcpHelper> _rtcp_helper;
|
std::shared_ptr<RtcpHelper> _rtcp_helper;
|
||||||
std::function<void()> _on_cleanup;
|
std::function<void()> _on_cleanup;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,6 @@ void RtpSession::setParams(mINI &ini) {
|
||||||
}
|
}
|
||||||
|
|
||||||
RtpSession::RtpSession(const Socket::Ptr &sock) : Session(sock) {
|
RtpSession::RtpSession(const Socket::Ptr &sock) : Session(sock) {
|
||||||
DebugP(this);
|
|
||||||
socklen_t addr_len = sizeof(_addr);
|
socklen_t addr_len = sizeof(_addr);
|
||||||
getpeername(sock->rawFD(), (struct sockaddr *)&_addr, &addr_len);
|
getpeername(sock->rawFD(), (struct sockaddr *)&_addr, &addr_len);
|
||||||
_is_udp = sock->sockType() == SockNum::Sock_UDP;
|
_is_udp = sock->sockType() == SockNum::Sock_UDP;
|
||||||
|
|
@ -47,7 +46,6 @@ RtpSession::RtpSession(const Socket::Ptr &sock) : Session(sock) {
|
||||||
}
|
}
|
||||||
|
|
||||||
RtpSession::~RtpSession() {
|
RtpSession::~RtpSession() {
|
||||||
DebugP(this);
|
|
||||||
if(_process){
|
if(_process){
|
||||||
RtpSelector::Instance().delProcess(_stream_id,_process.get());
|
RtpSelector::Instance().delProcess(_stream_id,_process.get());
|
||||||
}
|
}
|
||||||
|
|
@ -62,7 +60,7 @@ void RtpSession::onRecv(const Buffer::Ptr &data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtpSession::onError(const SockException &err) {
|
void RtpSession::onError(const SockException &err) {
|
||||||
WarnP(this) << _stream_id << " " << err.what();
|
WarnP(this) << _stream_id << " " << err;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtpSession::onManager() {
|
void RtpSession::onManager() {
|
||||||
|
|
@ -130,7 +128,7 @@ void RtpSession::onRtpPacket(const char *data, size_t len) {
|
||||||
uint32_t rtp_ssrc = 0;
|
uint32_t rtp_ssrc = 0;
|
||||||
RtpSelector::getSSRC(data, len, rtp_ssrc);
|
RtpSelector::getSSRC(data, len, rtp_ssrc);
|
||||||
if (rtp_ssrc != _ssrc) {
|
if (rtp_ssrc != _ssrc) {
|
||||||
WarnP(this) << "ssrc不匹配,rtp已丢弃:" << rtp_ssrc << " != " << _ssrc;
|
WarnP(this) << "ssrc mismatched, rtp dropped: " << rtp_ssrc << " != " << _ssrc;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_process->inputRtp(false, getSock(), data, len, (struct sockaddr *)&_addr);
|
_process->inputRtp(false, getSock(), data, len, (struct sockaddr *)&_addr);
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,8 @@
|
||||||
#include "RtpSplitter.h"
|
#include "RtpSplitter.h"
|
||||||
namespace mediakit{
|
namespace mediakit{
|
||||||
|
|
||||||
static const char kEHOME_MAGIC[] = "\x01\x00\x01\x00";
|
|
||||||
static const int kEHOME_OFFSET = 256;
|
static const int kEHOME_OFFSET = 256;
|
||||||
|
|
||||||
RtpSplitter::RtpSplitter() {}
|
|
||||||
RtpSplitter::~RtpSplitter() {}
|
|
||||||
|
|
||||||
ssize_t RtpSplitter::onRecvHeader(const char *data,size_t len){
|
ssize_t RtpSplitter::onRecvHeader(const char *data,size_t len){
|
||||||
//忽略偏移量
|
//忽略偏移量
|
||||||
data += _offset;
|
data += _offset;
|
||||||
|
|
@ -42,7 +38,6 @@ static bool isEhome(const char *data, size_t len){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
//return memcmp(data, kEHOME_MAGIC, sizeof(kEHOME_MAGIC) - 1) == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *RtpSplitter::onSearchPacketTail(const char *data, size_t len) {
|
const char *RtpSplitter::onSearchPacketTail(const char *data, size_t len) {
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@ namespace mediakit{
|
||||||
|
|
||||||
class RtpSplitter : public HttpRequestSplitter{
|
class RtpSplitter : public HttpRequestSplitter{
|
||||||
public:
|
public:
|
||||||
RtpSplitter();
|
RtpSplitter() = default;
|
||||||
~RtpSplitter() override;
|
~RtpSplitter() override = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ class TSSegment : public HttpRequestSplitter {
|
||||||
public:
|
public:
|
||||||
typedef std::function<void(const char *data,size_t len)> onSegment;
|
typedef std::function<void(const char *data,size_t len)> onSegment;
|
||||||
TSSegment(size_t size = TS_PACKET_SIZE) : _size(size){}
|
TSSegment(size_t size = TS_PACKET_SIZE) : _size(size){}
|
||||||
~TSSegment(){}
|
~TSSegment() = default;
|
||||||
void setOnSegment(onSegment cb);
|
void setOnSegment(onSegment cb);
|
||||||
static bool isTSPacket(const char *data, size_t len);
|
static bool isTSPacket(const char *data, size_t len);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ public:
|
||||||
_interleaved = interleaved;
|
_interleaved = interleaved;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~RtpInfo() {}
|
virtual ~RtpInfo() = default;
|
||||||
|
|
||||||
//返回rtp负载最大长度
|
//返回rtp负载最大长度
|
||||||
size_t getMaxSize() const {
|
size_t getMaxSize() const {
|
||||||
|
|
|
||||||
|
|
@ -237,9 +237,9 @@ class SdpParser {
|
||||||
public:
|
public:
|
||||||
using Ptr = std::shared_ptr<SdpParser>;
|
using Ptr = std::shared_ptr<SdpParser>;
|
||||||
|
|
||||||
SdpParser() {}
|
SdpParser() = default;
|
||||||
SdpParser(const std::string &sdp) { load(sdp); }
|
SdpParser(const std::string &sdp) { load(sdp); }
|
||||||
~SdpParser() {}
|
~SdpParser() = default;
|
||||||
|
|
||||||
void load(const std::string &sdp);
|
void load(const std::string &sdp);
|
||||||
bool available() const;
|
bool available() const;
|
||||||
|
|
@ -268,7 +268,7 @@ public:
|
||||||
_payload_type = payload_type;
|
_payload_type = payload_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Sdp(){}
|
virtual ~Sdp() = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取sdp字符串
|
* 获取sdp字符串
|
||||||
|
|
|
||||||
|
|
@ -53,14 +53,11 @@ static unordered_map<string, weak_ptr<RtspSession> > g_mapGetter;
|
||||||
static recursive_mutex g_mtxGetter;
|
static recursive_mutex g_mtxGetter;
|
||||||
|
|
||||||
RtspSession::RtspSession(const Socket::Ptr &sock) : Session(sock) {
|
RtspSession::RtspSession(const Socket::Ptr &sock) : Session(sock) {
|
||||||
DebugP(this);
|
|
||||||
GET_CONFIG(uint32_t,keep_alive_sec,Rtsp::kKeepAliveSecond);
|
GET_CONFIG(uint32_t,keep_alive_sec,Rtsp::kKeepAliveSecond);
|
||||||
sock->setSendTimeOutSecond(keep_alive_sec);
|
sock->setSendTimeOutSecond(keep_alive_sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
RtspSession::~RtspSession() {
|
RtspSession::~RtspSession() = default;
|
||||||
DebugP(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RtspSession::onError(const SockException &err) {
|
void RtspSession::onError(const SockException &err) {
|
||||||
bool is_player = !_push_src_ownership;
|
bool is_player = !_push_src_ownership;
|
||||||
|
|
@ -454,7 +451,6 @@ void RtspSession::handleReq_Describe(const Parser &parser) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtspSession::onAuthSuccess() {
|
void RtspSession::onAuthSuccess() {
|
||||||
TraceP(this);
|
|
||||||
weak_ptr<RtspSession> weak_self = dynamic_pointer_cast<RtspSession>(shared_from_this());
|
weak_ptr<RtspSession> weak_self = dynamic_pointer_cast<RtspSession>(shared_from_this());
|
||||||
MediaSource::findAsync(_media_info, weak_self.lock(), [weak_self](const MediaSource::Ptr &src){
|
MediaSource::findAsync(_media_info, weak_self.lock(), [weak_self](const MediaSource::Ptr &src){
|
||||||
auto strong_self = weak_self.lock();
|
auto strong_self = weak_self.lock();
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@ namespace mediakit{
|
||||||
|
|
||||||
class RtspSplitter : public HttpRequestSplitter{
|
class RtspSplitter : public HttpRequestSplitter{
|
||||||
public:
|
public:
|
||||||
RtspSplitter(){}
|
RtspSplitter() = default;
|
||||||
virtual ~RtspSplitter(){}
|
virtual ~RtspSplitter() = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否允许接收rtp包
|
* 是否允许接收rtp包
|
||||||
|
|
|
||||||
|
|
@ -25,13 +25,10 @@ static onceToken s_token([]() {
|
||||||
}, nullptr);
|
}, nullptr);
|
||||||
|
|
||||||
ShellSession::ShellSession(const Socket::Ptr &_sock) : Session(_sock) {
|
ShellSession::ShellSession(const Socket::Ptr &_sock) : Session(_sock) {
|
||||||
DebugP(this);
|
|
||||||
pleaseInputUser();
|
pleaseInputUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
ShellSession::~ShellSession() {
|
ShellSession::~ShellSession() = default;
|
||||||
DebugP(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShellSession::onRecv(const Buffer::Ptr&buf) {
|
void ShellSession::onRecv(const Buffer::Ptr&buf) {
|
||||||
//DebugL << hexdump(buf->data(), buf->size());
|
//DebugL << hexdump(buf->data(), buf->size());
|
||||||
|
|
@ -60,7 +57,7 @@ void ShellSession::onRecv(const Buffer::Ptr&buf) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShellSession::onError(const SockException &err){
|
void ShellSession::onError(const SockException &err){
|
||||||
WarnP(this) << err.what();
|
WarnP(this) << err;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShellSession::onManager() {
|
void ShellSession::onManager() {
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,7 @@ SrtSession::SrtSession(const Socket::Ptr &sock)
|
||||||
// TraceL<<"after addr len "<<addr_len<<" family "<<_peer_addr.ss_family;
|
// TraceL<<"after addr len "<<addr_len<<" family "<<_peer_addr.ss_family;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrtSession::~SrtSession() {
|
SrtSession::~SrtSession() = default;
|
||||||
InfoP(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
EventPoller::Ptr SrtSession::queryPoller(const Buffer::Ptr &buffer) {
|
EventPoller::Ptr SrtSession::queryPoller(const Buffer::Ptr &buffer) {
|
||||||
uint8_t *data = (uint8_t *)buffer->data();
|
uint8_t *data = (uint8_t *)buffer->data();
|
||||||
|
|
@ -119,7 +117,7 @@ void SrtSession::onError(const SockException &err) {
|
||||||
// udp链接超时,但是srt链接不一定超时,因为可能存在udp链接迁移的情况
|
// udp链接超时,但是srt链接不一定超时,因为可能存在udp链接迁移的情况
|
||||||
//在udp链接迁移时,新的SrtSession对象将接管SrtSession对象的生命周期
|
//在udp链接迁移时,新的SrtSession对象将接管SrtSession对象的生命周期
|
||||||
//本SrtSession对象将在超时后自动销毁
|
//本SrtSession对象将在超时后自动销毁
|
||||||
WarnP(this) << err.what();
|
WarnP(this) << err;
|
||||||
|
|
||||||
if (!_transport) {
|
if (!_transport) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,10 @@
|
||||||
|
|
||||||
namespace SRT {
|
namespace SRT {
|
||||||
SrtTransportImp::SrtTransportImp(const EventPoller::Ptr &poller)
|
SrtTransportImp::SrtTransportImp(const EventPoller::Ptr &poller)
|
||||||
: SrtTransport(poller) {}
|
: SrtTransport(poller) {
|
||||||
|
}
|
||||||
|
|
||||||
SrtTransportImp::~SrtTransportImp() {
|
SrtTransportImp::~SrtTransportImp() {
|
||||||
InfoP(this);
|
|
||||||
uint64_t duration = _alive_ticker.createdTime() / 1000;
|
uint64_t duration = _alive_ticker.createdTime() / 1000;
|
||||||
WarnP(this) << (_is_pusher ? "srt 推流器(" : "srt 播放器(") << _media_info.shortUrl() << ")断开,耗时(s):" << duration;
|
WarnP(this) << (_is_pusher ? "srt 推流器(" : "srt 播放器(") << _media_info.shortUrl() << ")断开,耗时(s):" << duration;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ protected:
|
||||||
}
|
}
|
||||||
//被动断开连接回调
|
//被动断开连接回调
|
||||||
void onErr(const SockException &ex) override {
|
void onErr(const SockException &ex) override {
|
||||||
WarnL << ex.what();
|
WarnL << ex;
|
||||||
}
|
}
|
||||||
//tcp连接成功后每2秒触发一次该事件
|
//tcp连接成功后每2秒触发一次该事件
|
||||||
void onManager() override {
|
void onManager() override {
|
||||||
|
|
@ -42,7 +42,7 @@ protected:
|
||||||
}
|
}
|
||||||
//连接服务器结果回调
|
//连接服务器结果回调
|
||||||
void onConnect(const SockException &ex) override{
|
void onConnect(const SockException &ex) override{
|
||||||
DebugL << ex.what();
|
DebugL << ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
//数据全部发送完毕后回调
|
//数据全部发送完毕后回调
|
||||||
|
|
|
||||||
|
|
@ -51,9 +51,7 @@ WebRtcSession::WebRtcSession(const Socket::Ptr &sock) : Session(sock) {
|
||||||
_over_tcp = sock->sockType() == SockNum::Sock_TCP;
|
_over_tcp = sock->sockType() == SockNum::Sock_TCP;
|
||||||
}
|
}
|
||||||
|
|
||||||
WebRtcSession::~WebRtcSession() {
|
WebRtcSession::~WebRtcSession() = default;
|
||||||
InfoP(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebRtcSession::attachServer(const Server &server) {
|
void WebRtcSession::attachServer(const Server &server) {
|
||||||
_server = std::dynamic_pointer_cast<toolkit::TcpServer>(const_cast<Server &>(server).shared_from_this());
|
_server = std::dynamic_pointer_cast<toolkit::TcpServer>(const_cast<Server &>(server).shared_from_this());
|
||||||
|
|
@ -71,7 +69,7 @@ void WebRtcSession::onRecv_l(const char *data, size_t len) {
|
||||||
if (!transport->getPoller()->isCurrentThread()) {
|
if (!transport->getPoller()->isCurrentThread()) {
|
||||||
auto sock = Socket::createSocket(transport->getPoller(), false);
|
auto sock = Socket::createSocket(transport->getPoller(), false);
|
||||||
//1、克隆socket(fd不变),切换poller线程到WebRtcTransport所在线程
|
//1、克隆socket(fd不变),切换poller线程到WebRtcTransport所在线程
|
||||||
sock->cloneFromPeerSocket(*(getSock()));
|
sock->cloneSocket(*(getSock()));
|
||||||
auto server = _server;
|
auto server = _server;
|
||||||
std::string str(data, len);
|
std::string str(data, len);
|
||||||
sock->getPoller()->async([sock, server, str](){
|
sock->getPoller()->async([sock, server, str](){
|
||||||
|
|
@ -105,7 +103,7 @@ void WebRtcSession::onError(const SockException &err) {
|
||||||
//udp链接超时,但是rtc链接不一定超时,因为可能存在链接迁移的情况
|
//udp链接超时,但是rtc链接不一定超时,因为可能存在链接迁移的情况
|
||||||
//在udp链接迁移时,新的WebRtcSession对象将接管WebRtcTransport对象的生命周期
|
//在udp链接迁移时,新的WebRtcSession对象将接管WebRtcTransport对象的生命周期
|
||||||
//本WebRtcSession对象将在超时后自动销毁
|
//本WebRtcSession对象将在超时后自动销毁
|
||||||
WarnP(this) << err.what();
|
WarnP(this) << err;
|
||||||
|
|
||||||
if (!_transport) {
|
if (!_transport) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -1054,7 +1054,7 @@ void WebRtcTransportImp::onBeforeEncryptRtp(const char *buf, int &len, void *ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebRtcTransportImp::onShutdown(const SockException &ex) {
|
void WebRtcTransportImp::onShutdown(const SockException &ex) {
|
||||||
WarnL << ex.what();
|
WarnL << ex;
|
||||||
unrefSelf();
|
unrefSelf();
|
||||||
for (auto &tuple : _ice_server->GetTuples()) {
|
for (auto &tuple : _ice_server->GetTuples()) {
|
||||||
tuple->shutdown(ex);
|
tuple->shutdown(ex);
|
||||||
|
|
@ -1131,6 +1131,10 @@ void WebRtcPluginManager::registerPlugin(const string &type, Plugin cb) {
|
||||||
_map_creator[type] = std::move(cb);
|
_map_creator[type] = std::move(cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string exchangeSdp(const WebRtcInterface &exchanger, const std::string& offer) {
|
||||||
|
return const_cast<WebRtcInterface &>(exchanger).getAnswerSdp(offer);
|
||||||
|
}
|
||||||
|
|
||||||
void WebRtcPluginManager::getAnswerSdp(Session &sender, const string &type, const WebRtcArgs &args, const onCreateRtc &cb) {
|
void WebRtcPluginManager::getAnswerSdp(Session &sender, const string &type, const WebRtcArgs &args, const onCreateRtc &cb) {
|
||||||
lock_guard<mutex> lck(_mtx_creator);
|
lock_guard<mutex> lck(_mtx_creator);
|
||||||
auto it = _map_creator.find(type);
|
auto it = _map_creator.find(type);
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,8 @@ public:
|
||||||
virtual const std::string &getIdentifier() const = 0;
|
virtual const std::string &getIdentifier() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::string exchangeSdp(const WebRtcInterface &exchanger, const std::string& offer);
|
||||||
|
|
||||||
class WebRtcException : public WebRtcInterface {
|
class WebRtcException : public WebRtcInterface {
|
||||||
public:
|
public:
|
||||||
WebRtcException(const SockException &ex) : _ex(ex) {};
|
WebRtcException(const SockException &ex) : _ex(ex) {};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue