diff --git a/server/FFmpegSource.cpp b/server/FFmpegSource.cpp index 1392d9dc..48fb2cd5 100644 --- a/server/FFmpegSource.cpp +++ b/server/FFmpegSource.cpp @@ -78,7 +78,13 @@ void FFmpegSource::play(const string &ffmpeg_cmd_key, const string &src_url,cons _src_url = src_url; _dst_url = dst_url; _ffmpeg_cmd_key = ffmpeg_cmd_key; - _media_info.parse(dst_url); + + try { + _media_info.parse(dst_url); + } catch (std::exception &ex) { + cb(SockException(Err_other, ex.what())); + return; + } auto ffmpeg_cmd = ffmpeg_cmd_default; if (!ffmpeg_cmd_key.empty()) { diff --git a/server/WebApi.cpp b/server/WebApi.cpp index 887b1736..113df96f 100755 --- a/server/WebApi.cpp +++ b/server/WebApi.cpp @@ -537,7 +537,7 @@ void addStreamProxy(const string &vhost, const string &app, const string &stream return; } //添加拉流代理 - auto player = std::make_shared(vhost, app, stream, option, retry_count ? retry_count : -1); + auto player = std::make_shared(vhost, app, stream, option, retry_count >=0 ? retry_count : -1); s_proxyMap[key] = player; //指定RTP over TCP(播放rtsp时有效) @@ -952,7 +952,7 @@ void installWebApi() { } //添加推流代理 - PusherProxy::Ptr pusher(new PusherProxy(src, retry_count ? retry_count : -1)); + PusherProxy::Ptr pusher(new PusherProxy(src, retry_count>=0 ? retry_count : -1)); s_proxyPusherMap[key] = pusher; //指定RTP over TCP(播放rtsp时有效) @@ -988,12 +988,13 @@ void installWebApi() { CHECK_SECRET(); CHECK_ARGS("schema", "vhost", "app", "stream", "dst_url"); auto dst_url = allArgs["dst_url"]; + auto retry_count = allArgs["retry_count"].empty()? -1: allArgs["retry_count"].as(); addStreamPusherProxy(allArgs["schema"], allArgs["vhost"], allArgs["app"], allArgs["stream"], allArgs["dst_url"], - allArgs["retry_count"], + retry_count, allArgs["rtp_type"], allArgs["timeout_sec"], [invoker, val, headerOut, dst_url](const SockException &ex, const string &key) mutable { @@ -1024,12 +1025,12 @@ void installWebApi() { CHECK_ARGS("vhost","app","stream","url"); ProtocolOption option(allArgs); - + auto retry_count = allArgs["retry_count"].empty()? -1: allArgs["retry_count"].as(); addStreamProxy(allArgs["vhost"], allArgs["app"], allArgs["stream"], allArgs["url"], - allArgs["retry_count"], + retry_count, option, allArgs["rtp_type"], allArgs["timeout_sec"], diff --git a/src/Common/Stamp.cpp b/src/Common/Stamp.cpp index 75f818be..df7f7368 100644 --- a/src/Common/Stamp.cpp +++ b/src/Common/Stamp.cpp @@ -20,6 +20,15 @@ using namespace toolkit; namespace mediakit { +int64_t DeltaStamp::relativeStamp(int64_t stamp) { + _relative_stamp += deltaStamp(stamp); + return _relative_stamp; +} + +int64_t DeltaStamp::relativeStamp(){ + return _relative_stamp; +} + int64_t DeltaStamp::deltaStamp(int64_t stamp) { if(!_last_stamp){ //第一次计算时间戳增量,时间戳增量为0 diff --git a/src/Common/Stamp.h b/src/Common/Stamp.h index f943fc40..cc2dcae0 100644 --- a/src/Common/Stamp.h +++ b/src/Common/Stamp.h @@ -28,9 +28,12 @@ public: * @return 时间戳增量 */ int64_t deltaStamp(int64_t stamp); + int64_t relativeStamp(int64_t stamp); + int64_t relativeStamp(); private: int64_t _last_stamp = 0; + int64_t _relative_stamp = 0; }; //该类解决时间戳回环、回退问题 diff --git a/src/Http/HttpRequester.cpp b/src/Http/HttpRequester.cpp index a7885919..669d17fe 100644 --- a/src/Http/HttpRequester.cpp +++ b/src/Http/HttpRequester.cpp @@ -11,7 +11,7 @@ #include "HttpRequester.h" #include "Util/onceToken.h" #include "Util/NoticeCenter.h" - +#include using namespace std; using namespace toolkit; @@ -26,6 +26,17 @@ void HttpRequester::onResponseBody(const char *buf, size_t size) { } void HttpRequester::onResponseCompleted(const SockException &ex) { + if (ex && _retry++ < _max_retry) { + std::weak_ptr weak_self = std::dynamic_pointer_cast(shared_from_this()); + getPoller()->doDelayTask(_retry_delay, [weak_self](){ + if (auto self = weak_self.lock()) { + InfoL << "resend request " << self->getUrl() << " with retry " << self->getRetry(); + self->sendRequest(self->getUrl()); + } + return 0; + }); + return ; + } const_cast(response()).setContent(std::move(_res_body)); if (_on_result) { _on_result(ex, response()); @@ -33,8 +44,15 @@ void HttpRequester::onResponseCompleted(const SockException &ex) { } } +void HttpRequester::setRetry(size_t count, size_t delay) { + InfoL << "setRetry max=" << count << ", delay=" << delay; + _max_retry = count; + _retry_delay = delay; +} + void HttpRequester::startRequester(const string &url, const HttpRequesterResult &on_result, float timeout_sec) { _on_result = on_result; + _retry = 0; setCompleteTimeout(timeout_sec * 1000); sendRequest(url); } @@ -52,7 +70,6 @@ void HttpRequester::setOnResult(const HttpRequesterResult &onResult) { //////////////////////////////////////////////////////////////////////// #if !defined(DISABLE_REPORT) -static constexpr auto s_interval_second = 60 * 5; static constexpr auto s_report_url = "http://report.zlmediakit.com:8888/index/api/report"; extern const char kServerName[]; @@ -73,6 +90,70 @@ static std::string httpBody() { os = "unknow"; #endif +#if (defined(_WIN32) && !defined(WIN32)) +#define WIN32 _WIN32 +#elif (defined(WIN32) && !defined(_WIN32)) +#define _WIN32 WIN32 +#endif + +#if (defined(_WIN32) && !defined(_MSC_VER) && !defined(_WIN64)) +#ifndef __i386__ +#define __i386__ +#endif +#elif defined(_MSC_VER) +#if (defined(_M_IX86) && !defined(__i386__)) +#define __i386__ +#endif +#endif + +#ifndef __i386__ +#if (defined(__386__) || defined(__I386__) || _M_IX86) +#define __i386__ +#endif +#endif + +#if (defined(__i386__) && !defined(__I386__)) +#define __I386__ +#endif + +#if (defined(__x86_64__) && !defined(__x86_64)) +#define __x86_64 +#endif + +#if (defined(__x86_64) && !defined(__x86_64__)) +#define __x86_64__ +#endif + +#if (defined(_M_AMD64)) && (!defined(__amd64__)) +#define __amd64__ +#endif + +#if (defined(__amd64) && !defined(__amd64__)) +#define __amd64__ +#endif + +#if (defined(__amd64__) && !defined(__amd64)) +#define __amd64 +#endif + +#if (defined(_M_ARM64) && !defined(__arm64__)) +#define __arm64__ +#endif + +#if (defined(_M_X64) && !defined(__x86_64__)) +#define __x86_64__ +#endif + +#if (defined(_M_ARM) && !defined(__arm__)) +#define __arm__ +#endif + +#if (defined(__i386__) || defined(__amd64__)) && (!defined(__x86__)) +#if !(defined(_MSC_VER) && defined(__amd64__)) +#define __x86__ // MSVC doesn't support inline assembly in x64 +#endif +#endif + auto &arch = args["arch"]; #if defined(__x86_64__) || defined(__amd64__) arch = "x86_64"; @@ -112,6 +193,7 @@ static std::string httpBody() { args["build_date"] = __DATE__; args["version"] = kServerName; args["exe_name"] = exeName(); + args["start_time"] = getTimeStr("%Y-%m-%d %H:%M:%S"); #if NDEBUG args["release"] = 1; @@ -161,6 +243,12 @@ static std::string httpBody() { args["openssl"] = 0; #endif +#if ENABLE_FFMPEG + args["ffmpeg"] = 1; +#else + args["ffmpeg"] = 0; +#endif + args["rand_str"] = makeRandStr(32); for (auto &pr : mINI::Instance()) { // 只获取转协议相关配置 @@ -178,14 +266,17 @@ static void sendReport() { requester->setMethod("POST"); requester->setBody(body); - requester->startRequester(s_report_url, nullptr, s_interval_second); + // http超时时间设置为30秒 + requester->startRequester(s_report_url, nullptr, 30); } static toolkit::onceToken s_token([]() { NoticeCenter::Instance().addListener(nullptr, EventPollerPool::kOnStarted, [](EventPollerPool &pool, size_t &size) { - pool.getPoller()->doDelayTask(s_interval_second * 1000, []() { + // 第一次汇报在程序启动后5分钟 + pool.getPoller()->doDelayTask(5 * 60 * 1000, []() { sendReport(); - return s_interval_second * 1000; + // 后续每一个小时汇报一次 + return 60 * 60 * 1000; }); }); }); diff --git a/src/Http/HttpRequester.h b/src/Http/HttpRequester.h index 69dd05a6..067bb0e8 100644 --- a/src/Http/HttpRequester.h +++ b/src/Http/HttpRequester.h @@ -25,6 +25,10 @@ public: void setOnResult(const HttpRequesterResult &onResult); void startRequester(const std::string &url, const HttpRequesterResult &on_result, float timeout_sec = 10); + void setRetry(size_t count, size_t delay); + size_t getRetry() const { return _retry; } + size_t getRetryDelay() const { return _retry_delay; } + size_t getMaxRetry() const { return _max_retry; } void clear() override; private: @@ -33,6 +37,9 @@ private: void onResponseCompleted(const toolkit::SockException &ex) override; private: + size_t _retry = 0; + size_t _max_retry = 0; + size_t _retry_delay = 2000; // ms std::string _res_body; HttpRequesterResult _on_result; }; diff --git a/src/Rtmp/RtmpSession.cpp b/src/Rtmp/RtmpSession.cpp index 9d8acf51..c387ac91 100644 --- a/src/Rtmp/RtmpSession.cpp +++ b/src/Rtmp/RtmpSession.cpp @@ -95,6 +95,15 @@ void RtmpSession::onCmd_connect(AMFDecoder &dec) { //tc_url 中可能包含?以及参数,参见issue: #692 _tc_url = _tc_url.substr(0, pos); } + auto stream_start = _tc_url.rfind('/'); + if (stream_start != string::npos && stream_start > 1) { + auto protocol_end = _tc_url.find("://") + 2; + auto app_start = _tc_url.rfind('/', stream_start - 1); + if (app_start != protocol_end) { + // contain stream name part + _tc_url = _tc_url.substr(0, stream_start); + } + } } bool ok = true; //(app == APP_NAME); AMFValue version(AMF_OBJECT); diff --git a/webrtc/Sdp.cpp b/webrtc/Sdp.cpp index a796ca99..1b08ca8d 100644 --- a/webrtc/Sdp.cpp +++ b/webrtc/Sdp.cpp @@ -680,11 +680,11 @@ string SdpAttrSctpMap::toString() const { void SdpAttrCandidate::parse(const string &str) { char foundation_buf[40] = {0}; char transport_buf[16] = {0}; - char address_buf[8*4+7+1] = {0}; + char address_buf[64] = {0}; char type_buf[16] = {0}; // https://datatracker.ietf.org/doc/html/rfc5245#section-15.1 - CHECK_SDP(sscanf(str.data(), "%32[^ ] %" SCNu32 " %15[^ ] %" SCNu32 " %39[^ ] %" SCNu16 " typ %15[^ ]", + CHECK_SDP(sscanf(str.data(), "%32[^ ] %" SCNu32 " %15[^ ] %" SCNu32 " %63[^ ] %" SCNu16 " typ %15[^ ]", foundation_buf, &component, transport_buf, &priority, address_buf, &port, type_buf) == 7); foundation = foundation_buf; transport = transport_buf; diff --git a/webrtc/WebRtcTransport.cpp b/webrtc/WebRtcTransport.cpp index 3551f00a..347f870c 100644 --- a/webrtc/WebRtcTransport.cpp +++ b/webrtc/WebRtcTransport.cpp @@ -52,8 +52,8 @@ static onceToken token([]() { mINI::Instance()[kTimeOutSec] = 15; mINI::Instance()[kExternIP] = ""; mINI::Instance()[kRembBitRate] = 0; - mINI::Instance()[kPort] = 8000; - mINI::Instance()[kTcpPort] = 8000; + mINI::Instance()[kPort] = 0; + mINI::Instance()[kTcpPort] = 0; }); } // namespace RTC