From d735aa179780053af1756e3efd84ca3e4d2dfb2f Mon Sep 17 00:00:00 2001 From: mtdxc Date: Sun, 14 Jul 2024 09:32:41 +0800 Subject: [PATCH] Media tuple refactor (#3715) Co-authored-by: cqm --- api/source/mk_proxyplayer.cpp | 6 ++++-- server/WebApi.cpp | 23 ++++++++++++----------- server/WebApi.h | 2 +- server/WebHook.cpp | 2 +- src/Common/MediaSource.cpp | 3 ++- src/Player/PlayerProxy.cpp | 8 ++------ src/Player/PlayerProxy.h | 6 +++--- src/Record/MP4Reader.cpp | 11 +++++------ src/Record/MP4Reader.h | 8 +++----- src/Rtsp/RtpMultiCaster.cpp | 24 ++++++++++++------------ src/Rtsp/RtpMultiCaster.h | 4 ++-- src/Rtsp/RtspSession.cpp | 2 +- tests/test_bench_forward.cpp | 3 ++- tests/test_bench_proxy.cpp | 3 ++- tests/test_bench_push.cpp | 5 +++-- tests/test_pusher.cpp | 3 ++- tests/test_pusherMp4.cpp | 3 ++- tests/test_server.cpp | 4 ++-- 18 files changed, 61 insertions(+), 59 deletions(-) diff --git a/api/source/mk_proxyplayer.cpp b/api/source/mk_proxyplayer.cpp index 90849304..218a3a5e 100644 --- a/api/source/mk_proxyplayer.cpp +++ b/api/source/mk_proxyplayer.cpp @@ -28,7 +28,8 @@ API_EXPORT mk_proxy_player API_CALL mk_proxy_player_create3(const char *vhost, c ProtocolOption option; option.enable_hls = hls_enabled; option.enable_mp4 = mp4_enabled; - PlayerProxy::Ptr *obj(new PlayerProxy::Ptr(new PlayerProxy(vhost, app, stream, option, retry_count))); + MediaTuple tuple = {vhost, app, stream, ""}; + PlayerProxy::Ptr *obj(new PlayerProxy::Ptr(new PlayerProxy(tuple, option, retry_count))); return (mk_proxy_player)obj; } @@ -36,7 +37,8 @@ API_EXPORT mk_proxy_player API_CALL mk_proxy_player_create3(const char *vhost, c API_EXPORT mk_proxy_player API_CALL mk_proxy_player_create4(const char *vhost, const char *app, const char *stream, mk_ini ini, int retry_count) { assert(vhost && app && stream); ProtocolOption option(*((mINI *)ini)); - PlayerProxy::Ptr *obj(new PlayerProxy::Ptr(new PlayerProxy(vhost, app, stream, option, retry_count))); + MediaTuple tuple = {vhost, app, stream, ""}; + PlayerProxy::Ptr *obj(new PlayerProxy::Ptr(new PlayerProxy(tuple, option, retry_count))); return (mk_proxy_player)obj; } diff --git a/server/WebApi.cpp b/server/WebApi.cpp index 90d63197..2b08817a 100755 --- a/server/WebApi.cpp +++ b/server/WebApi.cpp @@ -376,9 +376,6 @@ static ServiceController s_ffmpeg_src; static ServiceController s_rtp_server; #endif -static inline string getProxyKey(const string &vhost, const string &app, const string &stream) { - return vhost + "/" + app + "/" + stream; -} static inline string getPusherKey(const string &schema, const string &vhost, const string &app, const string &stream, const string &dst_url) { @@ -582,17 +579,17 @@ void getStatisticJson(const function &cb) { #endif } -void addStreamProxy(const string &vhost, const string &app, const string &stream, const string &url, int retry_count, +void addStreamProxy(const MediaTuple &tuple, const string &url, int retry_count, const ProtocolOption &option, int rtp_type, float timeout_sec, const mINI &args, const function &cb) { - auto key = getProxyKey(vhost, app, stream); + auto key = tuple.shortUrl(); if (s_player_proxy.find(key)) { //已经在拉流了 cb(SockException(Err_other, "This stream already exists"), key); return; } //添加拉流代理 - auto player = s_player_proxy.make(key, vhost, app, stream, option, retry_count); + auto player = s_player_proxy.make(key, tuple, option, retry_count); // 先透传拷贝参数 for (auto &pr : args) { @@ -1102,9 +1099,13 @@ void installWebApi() { ProtocolOption option(allArgs); auto retry_count = allArgs["retry_count"].empty()? -1: allArgs["retry_count"].as(); - addStreamProxy(allArgs["vhost"], - allArgs["app"], - allArgs["stream"], + + std::string vhost = DEFAULT_VHOST; + if (!allArgs["vhost"].empty()) { + vhost = allArgs["vhost"]; + } + auto tuple = MediaTuple { vhost, allArgs["app"], allArgs["stream"], "" }; + addStreamProxy(tuple, allArgs["url"], retry_count, option, @@ -1963,8 +1964,8 @@ void installWebApi() { option.load(allArgs); // 强制无人观看时自动关闭 option.auto_close = true; - - auto reader = std::make_shared(allArgs["vhost"], allArgs["app"], allArgs["stream"], allArgs["file_path"], option); + auto tuple = MediaTuple{allArgs["vhost"], allArgs["app"], allArgs["stream"], ""}; + auto reader = std::make_shared(tuple, allArgs["file_path"], option); // sample_ms设置为0,从配置文件加载;file_repeat可以指定,如果配置文件也指定循环解复用,那么强制开启 reader->startReadMP4(0, true, allArgs["file_repeat"]); }); diff --git a/server/WebApi.h b/server/WebApi.h index 7ec1887e..536c799e 100755 --- a/server/WebApi.h +++ b/server/WebApi.h @@ -207,7 +207,7 @@ uint16_t openRtpServer(uint16_t local_port, const mediakit::MediaTuple &tuple, i Json::Value makeMediaSourceJson(mediakit::MediaSource &media); void getStatisticJson(const std::function &cb); -void addStreamProxy(const std::string &vhost, const std::string &app, const std::string &stream, const std::string &url, int retry_count, +void addStreamProxy(const mediakit::MediaTuple &tuple, const std::string &url, int retry_count, const mediakit::ProtocolOption &option, int rtp_type, float timeout_sec, const toolkit::mINI &args, const std::function &cb); #endif //ZLMEDIAKIT_WEBAPI_H diff --git a/server/WebHook.cpp b/server/WebHook.cpp index 9e93cc9d..787b72b2 100755 --- a/server/WebHook.cpp +++ b/server/WebHook.cpp @@ -301,7 +301,7 @@ static void pullStreamFromOrigin(const vector &urls, size_t index, size_ option.enable_hls = option.enable_hls || (args.schema == HLS_SCHEMA); option.enable_mp4 = false; - addStreamProxy(args.vhost, args.app, args.stream, url, retry_count, option, Rtsp::RTP_TCP, timeout_sec, mINI{}, [=](const SockException &ex, const string &key) mutable { + addStreamProxy(args, url, retry_count, option, Rtsp::RTP_TCP, timeout_sec, mINI{}, [=](const SockException &ex, const string &key) mutable { if (!ex) { return; } diff --git a/src/Common/MediaSource.cpp b/src/Common/MediaSource.cpp index 1f2d6cd3..8406f680 100644 --- a/src/Common/MediaSource.cpp +++ b/src/Common/MediaSource.cpp @@ -595,7 +595,8 @@ MediaSource::Ptr MediaSource::createFromMP4(const string &schema, const string & } #ifdef ENABLE_MP4 try { - auto reader = std::make_shared(vhost, app, stream, file_path); + MediaTuple tuple = {vhost, app, stream, ""}; + auto reader = std::make_shared(tuple, file_path); reader->startReadMP4(); return MediaSource::find(schema, vhost, app, stream); } catch (std::exception &ex) { diff --git a/src/Player/PlayerProxy.cpp b/src/Player/PlayerProxy.cpp index 0f31e33b..b601e16e 100644 --- a/src/Player/PlayerProxy.cpp +++ b/src/Player/PlayerProxy.cpp @@ -24,13 +24,9 @@ using namespace std; namespace mediakit { PlayerProxy::PlayerProxy( - const string &vhost, const string &app, const string &stream_id, const ProtocolOption &option, int retry_count, + const MediaTuple &tuple, const ProtocolOption &option, int retry_count, const EventPoller::Ptr &poller, int reconnect_delay_min, int reconnect_delay_max, int reconnect_delay_step) - : MediaPlayer(poller) - , _option(option) { - _tuple.vhost = vhost; - _tuple.app = app; - _tuple.stream = stream_id; + : MediaPlayer(poller), _tuple(tuple), _option(option) { _retry_count = retry_count; setOnClose(nullptr); diff --git a/src/Player/PlayerProxy.h b/src/Player/PlayerProxy.h index c3c5b5bc..cc10a4e6 100644 --- a/src/Player/PlayerProxy.h +++ b/src/Player/PlayerProxy.h @@ -66,9 +66,9 @@ public: // 如果retry_count<0,则一直重试播放;否则重试retry_count次数 // 默认一直重试 - PlayerProxy( - const std::string &vhost, const std::string &app, const std::string &stream_id, const ProtocolOption &option, int retry_count = -1, - const toolkit::EventPoller::Ptr &poller = nullptr, int reconnect_delay_min = 2, int reconnect_delay_max = 60, int reconnect_delay_step = 3); + PlayerProxy(const MediaTuple &tuple, const ProtocolOption &option, int retry_count = -1, + const toolkit::EventPoller::Ptr &poller = nullptr, + int reconnect_delay_min = 2, int reconnect_delay_max = 60, int reconnect_delay_step = 3); ~PlayerProxy() override; diff --git a/src/Record/MP4Reader.cpp b/src/Record/MP4Reader.cpp index 6437fcff..146b70b1 100644 --- a/src/Record/MP4Reader.cpp +++ b/src/Record/MP4Reader.cpp @@ -20,7 +20,7 @@ using namespace toolkit; namespace mediakit { -MP4Reader::MP4Reader(const std::string &vhost, const std::string &app, const std::string &stream_id, const string &file_path, +MP4Reader::MP4Reader(const MediaTuple &tuple, const string &file_path, toolkit::EventPoller::Ptr poller) { ProtocolOption option; // 读取mp4文件并流化时,不重复生成mp4/hls文件 @@ -29,16 +29,15 @@ MP4Reader::MP4Reader(const std::string &vhost, const std::string &app, const std option.enable_hls_fmp4 = false; // mp4支持多track option.max_track = 16; - setup(vhost, app, stream_id, file_path, option, std::move(poller)); + setup(tuple, file_path, option, std::move(poller)); } -MP4Reader::MP4Reader(const std::string &vhost, const std::string &app, const std::string &stream_id, const string &file_path, const ProtocolOption &option, toolkit::EventPoller::Ptr poller) { - setup(vhost, app, stream_id, file_path, option, std::move(poller)); +MP4Reader::MP4Reader(const MediaTuple &tuple, const string &file_path, const ProtocolOption &option, toolkit::EventPoller::Ptr poller) { + setup(tuple, file_path, option, std::move(poller)); } -void MP4Reader::setup(const std::string &vhost, const std::string &app, const std::string &stream_id, const std::string &file_path, const ProtocolOption &option, toolkit::EventPoller::Ptr poller) { +void MP4Reader::setup(const MediaTuple &tuple, const std::string &file_path, const ProtocolOption &option, toolkit::EventPoller::Ptr poller) { //读写文件建议放在后台线程 - auto tuple = MediaTuple{vhost, app, stream_id, ""}; _poller = poller ? std::move(poller) : WorkThreadPool::Instance().getPoller(); _file_path = file_path; if (_file_path.empty()) { diff --git a/src/Record/MP4Reader.h b/src/Record/MP4Reader.h index c97c4862..f6607d85 100644 --- a/src/Record/MP4Reader.h +++ b/src/Record/MP4Reader.h @@ -28,11 +28,9 @@ public: * @param stream_id 流id,置空时,只解复用mp4,但是不生成MediaSource * @param file_path 文件路径,如果为空则根据配置文件和上面参数自动生成,否则使用指定的文件 */ - MP4Reader(const std::string &vhost, const std::string &app, const std::string &stream_id, - const std::string &file_path = "", toolkit::EventPoller::Ptr poller = nullptr); + MP4Reader(const MediaTuple &tuple, const std::string &file_path = "", toolkit::EventPoller::Ptr poller = nullptr); - MP4Reader(const std::string &vhost, const std::string &app, const std::string &stream_id, - const std::string &file_path, const ProtocolOption &option, toolkit::EventPoller::Ptr poller = nullptr); + MP4Reader(const MediaTuple &tuple, const std::string &file_path, const ProtocolOption &option, toolkit::EventPoller::Ptr poller = nullptr); /** * 开始解复用MP4文件 @@ -69,7 +67,7 @@ private: void setCurrentStamp(uint32_t stamp); bool seekTo(uint32_t stamp_seek); - void setup(const std::string &vhost, const std::string &app, const std::string &stream_id, const std::string &file_path, const ProtocolOption &option, toolkit::EventPoller::Ptr poller); + void setup(const MediaTuple &tuple, const std::string &file_path, const ProtocolOption &option, toolkit::EventPoller::Ptr poller); private: bool _file_repeat = false; diff --git a/src/Rtsp/RtpMultiCaster.cpp b/src/Rtsp/RtpMultiCaster.cpp index c358e68e..37ada760 100644 --- a/src/Rtsp/RtpMultiCaster.cpp +++ b/src/Rtsp/RtpMultiCaster.cpp @@ -99,10 +99,10 @@ RtpMultiCaster::~RtpMultiCaster() { DebugL; } -RtpMultiCaster::RtpMultiCaster(SocketHelper &helper, const string &local_ip, const string &vhost, const string &app, const string &stream, uint32_t multicast_ip, uint16_t video_port, uint16_t audio_port) { - auto src = dynamic_pointer_cast(MediaSource::find(RTSP_SCHEMA, vhost, app, stream)); +RtpMultiCaster::RtpMultiCaster(SocketHelper &helper, const string &local_ip, const MediaTuple &tuple, uint32_t multicast_ip, uint16_t video_port, uint16_t audio_port) { + auto src = dynamic_pointer_cast(MediaSource::find(RTSP_SCHEMA, tuple.vhost, tuple.app, tuple.stream)); if (!src) { - auto err = StrPrinter << "未找到媒体源:" << vhost << " " << app << " " << stream << endl; + auto err = StrPrinter << "未找到媒体源:" << tuple.shortUrl() << endl; throw std::runtime_error(err); } _multicast_ip = (multicast_ip) ? make_shared(multicast_ip) : MultiCastAddressMaker::Instance().obtain(); @@ -144,7 +144,7 @@ RtpMultiCaster::RtpMultiCaster(SocketHelper &helper, const string &local_ip, con }); }); - string strKey = StrPrinter << local_ip << " " << vhost << " " << app << " " << stream << endl; + string strKey = StrPrinter << local_ip << " " << tuple.vhost << " " << tuple.app << " " << tuple.stream << endl; _rtp_reader->setDetachCB([this, strKey]() { { lock_guard lck(g_mtx); @@ -167,7 +167,7 @@ RtpMultiCaster::RtpMultiCaster(SocketHelper &helper, const string &local_ip, con DebugL << MultiCastAddressMaker::toString(*_multicast_ip) << " " << _udp_sock[0]->get_local_port() << " " << _udp_sock[1]->get_local_port() << " " - << vhost << " " << app << " " << stream; + << tuple.shortUrl(); } uint16_t RtpMultiCaster::getMultiCasterPort(TrackType trackType) { @@ -180,17 +180,17 @@ string RtpMultiCaster::getMultiCasterIP() { return SockUtil::inet_ntoa(addr); } -RtpMultiCaster::Ptr RtpMultiCaster::get(SocketHelper &helper, const string &local_ip, const string &vhost, const string &app, const string &stream, uint32_t multicast_ip, uint16_t video_port, uint16_t audio_port) { - static auto on_create = [](SocketHelper &helper, const string &local_ip, const string &vhost, const string &app, const string &stream, uint32_t multicast_ip, uint16_t video_port, uint16_t audio_port){ +RtpMultiCaster::Ptr RtpMultiCaster::get(SocketHelper &helper, const string &local_ip, const MediaTuple &tuple, uint32_t multicast_ip, uint16_t video_port, uint16_t audio_port) { + static auto on_create = [](SocketHelper &helper, const string &local_ip, const MediaTuple &tuple, uint32_t multicast_ip, uint16_t video_port, uint16_t audio_port){ try { auto poller = helper.getPoller(); - auto ret = RtpMultiCaster::Ptr(new RtpMultiCaster(helper, local_ip, vhost, app, stream, multicast_ip, video_port, audio_port), [poller](RtpMultiCaster *ptr) { + auto ret = RtpMultiCaster::Ptr(new RtpMultiCaster(helper, local_ip, tuple, multicast_ip, video_port, audio_port), [poller](RtpMultiCaster *ptr) { poller->async([ptr]() { delete ptr; }); }); lock_guard lck(g_mtx); - string strKey = StrPrinter << local_ip << " " << vhost << " " << app << " " << stream << endl; + string strKey = StrPrinter << local_ip << " " << tuple.vhost << " " << tuple.app << " " << tuple.stream << endl; g_multi_caster_map.emplace(strKey, ret); return ret; } catch (std::exception &ex) { @@ -199,16 +199,16 @@ RtpMultiCaster::Ptr RtpMultiCaster::get(SocketHelper &helper, const string &loca } }; - string strKey = StrPrinter << local_ip << " " << vhost << " " << app << " " << stream << endl; + string strKey = StrPrinter << local_ip << " " << tuple.vhost << " " << tuple.app << " " << tuple.stream << endl; lock_guard lck(g_mtx); auto it = g_multi_caster_map.find(strKey); if (it == g_multi_caster_map.end()) { - return on_create(helper, local_ip, vhost, app, stream, multicast_ip, video_port, audio_port); + return on_create(helper, local_ip, tuple, multicast_ip, video_port, audio_port); } auto ret = it->second.lock(); if (!ret) { g_multi_caster_map.erase(it); - return on_create(helper, local_ip, vhost, app, stream, multicast_ip, video_port, audio_port); + return on_create(helper, local_ip, tuple, multicast_ip, video_port, audio_port); } return ret; } diff --git a/src/Rtsp/RtpMultiCaster.h b/src/Rtsp/RtpMultiCaster.h index 1b9aa1bf..fae48f7e 100644 --- a/src/Rtsp/RtpMultiCaster.h +++ b/src/Rtsp/RtpMultiCaster.h @@ -45,14 +45,14 @@ public: ~RtpMultiCaster(); - static Ptr get(toolkit::SocketHelper &helper, const std::string &local_ip, const std::string &vhost, const std::string &app, const std::string &stream, uint32_t multicast_ip = 0, uint16_t video_port = 0, uint16_t audio_port = 0); + static Ptr get(toolkit::SocketHelper &helper, const std::string &local_ip, const MediaTuple &tuple, uint32_t multicast_ip = 0, uint16_t video_port = 0, uint16_t audio_port = 0); void setDetachCB(void *listener,const onDetach &cb); std::string getMultiCasterIP(); uint16_t getMultiCasterPort(TrackType trackType); private: - RtpMultiCaster(toolkit::SocketHelper &helper, const std::string &local_ip, const std::string &vhost, const std::string &app, const std::string &stream, uint32_t multicast_ip, uint16_t video_port, uint16_t audio_port); + RtpMultiCaster(toolkit::SocketHelper &helper, const std::string &local_ip, const MediaTuple &tuple, uint32_t multicast_ip, uint16_t video_port, uint16_t audio_port); private: std::recursive_mutex _mtx; diff --git a/src/Rtsp/RtspSession.cpp b/src/Rtsp/RtspSession.cpp index 2020846c..46e62fe2 100644 --- a/src/Rtsp/RtspSession.cpp +++ b/src/Rtsp/RtspSession.cpp @@ -742,7 +742,7 @@ void RtspSession::handleReq_Setup(const Parser &parser) { break; case Rtsp::RTP_MULTICAST: { if(!_multicaster){ - _multicaster = RtpMultiCaster::get(*this, get_local_ip(), _media_info.vhost, _media_info.app, _media_info.stream, _multicast_ip, _multicast_video_port, _multicast_audio_port); + _multicaster = RtpMultiCaster::get(*this, get_local_ip(), _media_info, _multicast_ip, _multicast_video_port, _multicast_audio_port); if (!_multicaster) { send_NotAcceptable(); throw SockException(Err_shutdown, "can not get a available udp multicast socket"); diff --git a/tests/test_bench_forward.cpp b/tests/test_bench_forward.cpp index a71994d1..c75b45ed 100644 --- a/tests/test_bench_forward.cpp +++ b/tests/test_bench_forward.cpp @@ -224,7 +224,8 @@ int main(int argc, char *argv[]) { option.enable_mp4 = false; option.modify_stamp = (int)ProtocolOption::kModifyStampRelative; //添加拉流代理 - auto proxy = std::make_shared(DEFAULT_VHOST, "app", std::to_string(i), option, -1, nullptr, 1); + auto tuple = MediaTuple{DEFAULT_VHOST, "app", std::to_string(i)}; + auto proxy = std::make_shared(tuple, option, -1, nullptr, 1); //开始拉流代理 proxy->play(input_urls[i]); proxy_map.emplace(i, std::move(proxy)); diff --git a/tests/test_bench_proxy.cpp b/tests/test_bench_proxy.cpp index c0f1fceb..cea0c4be 100644 --- a/tests/test_bench_proxy.cpp +++ b/tests/test_bench_proxy.cpp @@ -137,7 +137,8 @@ int main(int argc, char *argv[]) { option.enable_mp4 = false; for (auto i = 0; i < proxy_count; ++i) { auto stream = to_string(i); - PlayerProxy::Ptr player(new PlayerProxy(DEFAULT_VHOST, "live", stream, option)); + auto tuple = MediaTuple{DEFAULT_VHOST, "live", stream, ""}; + PlayerProxy::Ptr player(new PlayerProxy(tuple, option)); (*player)[Client::kRtpType] = rtp_type; player->play(in_url); proxyMap.emplace(stream, player); diff --git a/tests/test_bench_push.cpp b/tests/test_bench_push.cpp index a22d8879..8ae0d41c 100644 --- a/tests/test_bench_push.cpp +++ b/tests/test_bench_push.cpp @@ -148,9 +148,10 @@ int main(int argc, char *argv[]) { MediaSource::Ptr src = nullptr; PlayerProxy::Ptr proxy = nullptr;; + auto tuple = MediaTuple{DEFAULT_VHOST, app, stream}; if (end_with(in_url, ".mp4")) { // create MediaSource from mp4file - auto reader = std::make_shared(DEFAULT_VHOST, app, stream, in_url); + auto reader = std::make_shared(tuple, in_url); //mp4 repeat reader->startReadMP4(0, true, true); src = MediaSource::find(schema, DEFAULT_VHOST, app, stream, false); @@ -161,7 +162,7 @@ int main(int argc, char *argv[]) { } } else { //添加拉流代理 - proxy = std::make_shared(DEFAULT_VHOST, app, stream, option); + proxy = std::make_shared(tuple, option); //rtsp拉流代理方式 (*proxy)[Client::kRtpType] = rtp_type; //开始拉流代理 diff --git a/tests/test_pusher.cpp b/tests/test_pusher.cpp index 025cdd0f..fd368950 100644 --- a/tests/test_pusher.cpp +++ b/tests/test_pusher.cpp @@ -79,7 +79,8 @@ int domain(const string &playUrl, const string &pushUrl) { ProtocolOption option; option.enable_hls = false; option.enable_mp4 = false; - PlayerProxy::Ptr player(new PlayerProxy(DEFAULT_VHOST, "app", "stream", option, -1, poller)); + auto tuple = MediaTuple{DEFAULT_VHOST, "app", "stream", ""}; + PlayerProxy::Ptr player(new PlayerProxy(tuple, option, -1, poller)); //可以指定rtsp拉流方式,支持tcp和udp方式,默认tcp // (*player)[Client::kRtpType] = Rtsp::RTP_UDP; player->play(playUrl.data()); diff --git a/tests/test_pusherMp4.cpp b/tests/test_pusherMp4.cpp index 41e91dea..28ee2f99 100644 --- a/tests/test_pusherMp4.cpp +++ b/tests/test_pusherMp4.cpp @@ -43,7 +43,8 @@ int domain(const string &file, const string &url) { mINI::Instance()["protocol.enable_" + schema] = 1; // 从mp4文件加载生成MediaSource对象 - auto reader = std::make_shared(DEFAULT_VHOST, "live", "stream", file); + auto tuple = MediaTuple {DEFAULT_VHOST, "live", "stream", ""}; + auto reader = std::make_shared(tuple, file); // 开始加载mp4,ref_self设置为false,这样reader对象设置为nullptr就能注销了,file_repeat可以设置为空,这样文件读完了就停止推流了 reader->startReadMP4(100, false, true); auto src = MediaSource::find(schema, DEFAULT_VHOST, "live", "stream", false); diff --git a/tests/test_server.cpp b/tests/test_server.cpp index 0b3c93ef..0389d9ab 100644 --- a/tests/test_server.cpp +++ b/tests/test_server.cpp @@ -230,8 +230,8 @@ int main(int argc,char *argv[]) { //http://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4 //rtsp://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4 //rtmp://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4 - - PlayerProxy::Ptr player(new PlayerProxy(DEFAULT_VHOST, "live", std::string("chn") + to_string(i).data(), ProtocolOption())); + auto tuple = MediaTuple{DEFAULT_VHOST, "live", std::string("chn") + to_string(i).data(), ""}; + PlayerProxy::Ptr player(new PlayerProxy(tuple, ProtocolOption())); //指定RTP over TCP(播放rtsp时有效) (*player)[Client::kRtpType] = Rtsp::RTP_TCP; //开始播放,如果播放失败或者播放中止,将会自动重试若干次,重试次数在配置文件中配置,默认一直重试