Fix SrtCaller Crash problem (#4171)

1.Fix the crash problem when SrtPlayer reveives an Ack packet 
2.Remove SrtCaller's Check on streamid format to make it compatible with
other SRT streaming service。
3.Modify the coding format: replace tab to space
This commit is contained in:
baigao-X 2025-02-28 12:46:43 +08:00 committed by GitHub
parent 52ca731392
commit c0a93f3c8f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 793 additions and 819 deletions

View File

@ -21,57 +21,38 @@ using namespace SRT;
namespace mediakit { namespace mediakit {
//zlm play format
//srt://127.0.0.1:9000?streamid=#!::r=live/test //srt://127.0.0.1:9000?streamid=#!::r=live/test
//srt://127.0.0.1:9000?streamid=#!::r=live/test,h=__defaultVhost__ //srt://127.0.0.1:9000?streamid=#!::r=live/test,h=__defaultVhost__
//zlm push format
//srt://127.0.0.1:9000?streamid=#!::r=live/test,m=publish
//srt://127.0.0.1:9000?streamid=#!::r=live/test,h=__defaultVhost__,m=publish
void SrtUrl::parse(const string &strUrl) { void SrtUrl::parse(const string &strUrl) {
//DebugL << "url: " << strUrl; //DebugL << "url: " << strUrl;
_full_url = strUrl; _full_url = strUrl;
auto url = strUrl; auto url = strUrl;
auto ip = findSubString(url.data(), "://", "?"); auto ip = findSubString(url.data(), "://", "?");
splitUrl(ip, _host, _port); splitUrl(ip, _host, _port);
auto _params = findSubString(url.data(), "?" , NULL); auto _params = findSubString(url.data(), "?" , NULL);
auto kv = Parser::parseArgs(_params); auto kv = Parser::parseArgs(_params);
auto it = kv.find("streamid"); auto it = kv.find("streamid");
if (it != kv.end()) { if (it != kv.end()) {
auto streamid = it->second; auto streamid = it->second;
if (!toolkit::start_with(streamid, "#!::")) { if (!toolkit::start_with(streamid, "#!::")) {
return; return;
} }
std::string real_streamid = streamid.substr(4); _streamid = streamid;
}
auto params = Parser::parseArgs(real_streamid, ",", "="); //TraceL << "ip: " << ip;
//TraceL << "_host: " << _host;
for (auto iit : params) { //TraceL << "_port: " << _port;
if (iit.first == "h") { //TraceL << "_params: " << _params;
_vhost = iit.second; //TraceL << "_streamid: " << _streamid;
} else if (iit.first == "r") { return;
auto tmps = toolkit::split(iit.second, "/");
if (tmps.size() < 2) {
continue;
}
_app = tmps[0];
_stream = tmps[1];
} else {
//nop
}
}
if (_vhost.empty()) {
_vhost = DEFAULT_VHOST;
}
}
//TraceL << "ip: " << ip;
//TraceL << "_host: " << _host;
//TraceL << "_port: " << _port;
//TraceL << "_params: " << _params;
//TraceL << "_vhost: " << _vhost;
//TraceL << "_app: " << _app;
//TraceL << "_stream: " << _stream;
return;
} }
@ -79,10 +60,10 @@ void SrtUrl::parse(const string &strUrl) {
SrtCaller::SrtCaller(const toolkit::EventPoller::Ptr &poller) { SrtCaller::SrtCaller(const toolkit::EventPoller::Ptr &poller) {
_poller = poller ? std::move(poller) : EventPollerPool::Instance().getPoller(); _poller = poller ? std::move(poller) : EventPollerPool::Instance().getPoller();
_start_timestamp = SteadyClock::now(); _start_timestamp = SteadyClock::now();
_socket_id = generateSocketId(); _socket_id = generateSocketId();
/* _init_seq_number = generateInitSeq(); */ /* _init_seq_number = generateInitSeq(); */
_init_seq_number = 0; _init_seq_number = 0;
_last_pkt_seq = _init_seq_number - 1; _last_pkt_seq = _init_seq_number - 1;
_pkt_recv_rate_context = std::make_shared<SRT::PacketRecvRateContext>(_start_timestamp); _pkt_recv_rate_context = std::make_shared<SRT::PacketRecvRateContext>(_start_timestamp);
@ -93,16 +74,16 @@ SrtCaller::SrtCaller(const toolkit::EventPoller::Ptr &poller) {
} }
SrtCaller::~SrtCaller(void) { SrtCaller::~SrtCaller(void) {
DebugL; DebugL;
} }
void SrtCaller::onConnect() { void SrtCaller::onConnect() {
//DebugL; //DebugL;
auto peer_addr = SockUtil::make_sockaddr(_url._host.c_str(), (_url._port)); auto peer_addr = SockUtil::make_sockaddr(_url._host.c_str(), (_url._port));
_socket = Socket::createSocket(_poller, false); _socket = Socket::createSocket(_poller, false);
_socket->bindUdpSock(0, SockUtil::is_ipv4(_url._host.data()) ? "0.0.0.0" : "::"); _socket->bindUdpSock(0, SockUtil::is_ipv4(_url._host.data()) ? "0.0.0.0" : "::");
_socket->bindPeerAddr((struct sockaddr *)&peer_addr, 0, true); _socket->bindPeerAddr((struct sockaddr *)&peer_addr, 0, true);
weak_ptr<SrtCaller> weak_self = shared_from_this(); weak_ptr<SrtCaller> weak_self = shared_from_this();
_socket->setOnRead([weak_self](const Buffer::Ptr &buf, struct sockaddr *addr, int addr_len) mutable { _socket->setOnRead([weak_self](const Buffer::Ptr &buf, struct sockaddr *addr, int addr_len) mutable {
@ -110,10 +91,10 @@ void SrtCaller::onConnect() {
if (!strong_self) { if (!strong_self) {
return; return;
} }
strong_self->inputSockData((uint8_t*)buf->data(), buf->size(), addr); strong_self->inputSockData((uint8_t*)buf->data(), buf->size(), addr);
}); });
doHandshake(); doHandshake();
} }
void SrtCaller::onResult(const SockException &ex) { void SrtCaller::onResult(const SockException &ex) {
@ -138,7 +119,7 @@ void SrtCaller::onResult(const SockException &ex) {
void SrtCaller::onHandShakeFinished() { void SrtCaller::onHandShakeFinished() {
DebugL; DebugL;
_is_handleshake_finished = true; _is_handleshake_finished = true;
if (_handleshake_timer) { if (_handleshake_timer) {
_handleshake_timer.reset(); _handleshake_timer.reset();
} }
@ -165,7 +146,7 @@ void SrtCaller::onHandShakeFinished() {
void SrtCaller::onSRTData(DataPacket::Ptr pkt) { void SrtCaller::onSRTData(DataPacket::Ptr pkt) {
InfoL; InfoL;
if (!isPlayer()) { if (!isPlayer()) {
WarnL << "this is not a player data ignore"; WarnL << "this is not a player data ignore";
return; return;
} }
} }
@ -215,7 +196,7 @@ void SrtCaller::onSendTSData(const Buffer::Ptr &buffer, bool flush) {
} }
void SrtCaller::inputSockData(uint8_t *buf, int len, struct sockaddr *addr) { void SrtCaller::inputSockData(uint8_t *buf, int len, struct sockaddr *addr) {
//TraceL << hexdump((void*)buf, len); //TraceL << hexdump((void*)buf, len);
using srt_control_handler = void (SrtCaller::*)(uint8_t * buf, int len, struct sockaddr *addr); using srt_control_handler = void (SrtCaller::*)(uint8_t * buf, int len, struct sockaddr *addr);
static std::unordered_map<uint16_t, srt_control_handler> s_control_functions; static std::unordered_map<uint16_t, srt_control_handler> s_control_functions;
@ -277,16 +258,16 @@ void SrtCaller::doHandshake() {
_crypto = std::make_shared<SRT::Crypto>(getPassphrase()); _crypto = std::make_shared<SRT::Crypto>(getPassphrase());
} }
sendHandshakeInduction(); sendHandshakeInduction();
return; return;
} }
void SrtCaller::sendHandshakeInduction() { void SrtCaller::sendHandshakeInduction() {
DebugL; DebugL;
_induction_ts = SteadyClock::now(); _induction_ts = SteadyClock::now();
SRT::HandshakePacket::Ptr req = std::make_shared<SRT::HandshakePacket>(); SRT::HandshakePacket::Ptr req = std::make_shared<SRT::HandshakePacket>();
req->timestamp = DurationCountMicroseconds(_induction_ts - _start_timestamp); req->timestamp = DurationCountMicroseconds(_induction_ts - _start_timestamp);
req->dst_socket_id = 0; req->dst_socket_id = 0;
req->version = 4; req->version = 4;
@ -299,11 +280,11 @@ void SrtCaller::sendHandshakeInduction() {
req->srt_socket_id = _socket_id; req->srt_socket_id = _socket_id;
req->syn_cookie = 0; req->syn_cookie = 0;
auto dataSenderAddr = SockUtil::make_sockaddr(_url._host.c_str(), _url._port); auto dataSenderAddr = SockUtil::make_sockaddr(_url._host.c_str(), _url._port);
req->assignPeerIPBE(&dataSenderAddr); req->assignPeerIPBE(&dataSenderAddr);
req->storeToData(); req->storeToData();
_handleshake_req = req; _handleshake_req = req;
sendControlPacket(req, true); sendControlPacket(req, true);
std::weak_ptr<SrtCaller> weak_self = std::static_pointer_cast<SrtCaller>(shared_from_this()); std::weak_ptr<SrtCaller> weak_self = std::static_pointer_cast<SrtCaller>(shared_from_this());
_handleshake_timer = std::make_shared<Timer>(0.2, [weak_self]()->bool{ _handleshake_timer = std::make_shared<Timer>(0.2, [weak_self]()->bool{
@ -323,10 +304,10 @@ void SrtCaller::sendHandshakeInduction() {
} }
void SrtCaller::sendHandshakeConclusion() { void SrtCaller::sendHandshakeConclusion() {
DebugL; DebugL;
SRT::HandshakePacket::Ptr req = std::make_shared<SRT::HandshakePacket>(); SRT::HandshakePacket::Ptr req = std::make_shared<SRT::HandshakePacket>();
req->timestamp = DurationCountMicroseconds(_now - _start_timestamp); req->timestamp = DurationCountMicroseconds(_now - _start_timestamp);
req->dst_socket_id = 0; req->dst_socket_id = 0;
req->version = 5; req->version = 5;
@ -345,13 +326,13 @@ void SrtCaller::sendHandshakeConclusion() {
req->srt_socket_id = _socket_id; req->srt_socket_id = _socket_id;
req->syn_cookie = _sync_cookie; req->syn_cookie = _sync_cookie;
auto addr = SockUtil::make_sockaddr(_url._host.c_str(), _url._port); auto addr = SockUtil::make_sockaddr(_url._host.c_str(), _url._port);
req->assignPeerIPBE(&addr); req->assignPeerIPBE(&addr);
HSExtMessage::Ptr ext = std::make_shared<HSExtMessage>(); HSExtMessage::Ptr ext = std::make_shared<HSExtMessage>();
ext->extension_type = HSExt::SRT_CMD_HSREQ; ext->extension_type = HSExt::SRT_CMD_HSREQ;
ext->srt_version = srtVersion(1, 5, 0); ext->srt_version = srtVersion(1, 5, 0);
ext->srt_flag = 0xbf; ext->srt_flag = 0xbf;
// if set latency, use set value // if set latency, use set value
_delay = getLatency(); _delay = getLatency();
@ -364,13 +345,13 @@ void SrtCaller::sendHandshakeConclusion() {
} }
} }
ext->recv_tsbpd_delay = _delay; ext->recv_tsbpd_delay = _delay;
ext->send_tsbpd_delay = _delay; ext->send_tsbpd_delay = _delay;
req->ext_list.push_back(std::move(ext)); req->ext_list.push_back(std::move(ext));
HSExtStreamID::Ptr extStreamId = std::make_shared<HSExtStreamID>(); HSExtStreamID::Ptr extStreamId = std::make_shared<HSExtStreamID>();
extStreamId->streamid = generateStreamId(); extStreamId->streamid = generateStreamId();
req->ext_list.push_back(std::move(extStreamId)); req->ext_list.push_back(std::move(extStreamId));
if (_crypto) { if (_crypto) {
HSExtKeyMaterial::Ptr keyMaterial = _crypto->generateKeyMaterialExt(HSExt::SRT_CMD_KMREQ); HSExtKeyMaterial::Ptr keyMaterial = _crypto->generateKeyMaterialExt(HSExt::SRT_CMD_KMREQ);
@ -378,8 +359,8 @@ void SrtCaller::sendHandshakeConclusion() {
} }
req->storeToData(); req->storeToData();
_handleshake_req = req; _handleshake_req = req;
sendControlPacket(req); sendControlPacket(req);
return; return;
} }
@ -491,7 +472,7 @@ void SrtCaller::sendMsgDropReq(uint32_t first, uint32_t last) {
void SrtCaller::sendKeepLivePacket() { void SrtCaller::sendKeepLivePacket() {
auto now = SteadyClock::now(); auto now = SteadyClock::now();
SRT::KeepLivePacket::Ptr req = std::make_shared<SRT::KeepLivePacket>(); SRT::KeepLivePacket::Ptr req = std::make_shared<SRT::KeepLivePacket>();
req->timestamp = SRT::DurationCountMicroseconds(now - _start_timestamp); req->timestamp = SRT::DurationCountMicroseconds(now - _start_timestamp);
req->dst_socket_id = _peer_socket_id; req->dst_socket_id = _peer_socket_id;
req->storeToData(); req->storeToData();
@ -510,7 +491,7 @@ void SrtCaller::sendShutDown() {
} }
void SrtCaller::tryAnnounceKeyMaterial() { void SrtCaller::tryAnnounceKeyMaterial() {
//TraceL; //TraceL;
if (!_crypto) { if (!_crypto) {
return; return;
@ -546,9 +527,9 @@ void SrtCaller::tryAnnounceKeyMaterial() {
} }
void SrtCaller::sendControlPacket(SRT::ControlPacket::Ptr pkt, bool flush) { void SrtCaller::sendControlPacket(SRT::ControlPacket::Ptr pkt, bool flush) {
//TraceL; //TraceL;
sendPacket(pkt, flush); sendPacket(pkt, flush);
return; return;
} }
void SrtCaller::sendDataPacket(SRT::DataPacket::Ptr pkt, char *buf, int len, bool flush) { void SrtCaller::sendDataPacket(SRT::DataPacket::Ptr pkt, char *buf, int len, bool flush) {
@ -571,22 +552,22 @@ void SrtCaller::sendDataPacket(SRT::DataPacket::Ptr pkt, char *buf, int len, boo
pkt->storeToData((uint8_t *)data, size); pkt->storeToData((uint8_t *)data, size);
sendPacket(pkt, flush); sendPacket(pkt, flush);
_send_buf->inputPacket(pkt); _send_buf->inputPacket(pkt);
return; return;
} }
void SrtCaller::sendPacket(Buffer::Ptr pkt, bool flush) { void SrtCaller::sendPacket(Buffer::Ptr pkt, bool flush) {
//TraceL << pkt->size(); //TraceL << pkt->size();
auto tmp = _packet_pool.obtain2(); auto tmp = _packet_pool.obtain2();
tmp->assign(pkt->data(), pkt->size()); tmp->assign(pkt->data(), pkt->size());
_socket->send(std::move(tmp), nullptr, 0, flush); _socket->send(std::move(tmp), nullptr, 0, flush);
_send_ticker.resetTime(); _send_ticker.resetTime();
return; return;
} }
void SrtCaller::handleHandshake(uint8_t *buf, int len, struct sockaddr *addr) { void SrtCaller::handleHandshake(uint8_t *buf, int len, struct sockaddr *addr) {
//DebugL; //DebugL;
SRT::HandshakePacket pkt; SRT::HandshakePacket pkt;
if(!pkt.loadFromData(buf, len)){ if(!pkt.loadFromData(buf, len)){
WarnL<< "is not vaild HandshakePacket"; WarnL<< "is not vaild HandshakePacket";
return; return;
@ -610,96 +591,96 @@ void SrtCaller::handleHandshake(uint8_t *buf, int len, struct sockaddr *addr) {
} }
void SrtCaller::handleHandshakeInduction(SRT::HandshakePacket &pkt, struct sockaddr *addr) { void SrtCaller::handleHandshakeInduction(SRT::HandshakePacket &pkt, struct sockaddr *addr) {
DebugL; DebugL;
if (!_handleshake_req) { if (!_handleshake_req) {
WarnL << "must Induction Phase for handleshake"; WarnL << "must Induction Phase for handleshake";
return; return;
} }
if (_handleshake_req->handshake_type == HandshakePacket::HS_TYPE_CONCLUSION) { if (_handleshake_req->handshake_type == HandshakePacket::HS_TYPE_CONCLUSION) {
WarnL << "should be Conclusion Phase for handleshake "; WarnL << "should be Conclusion Phase for handleshake ";
return; return;
} else if (_handleshake_req->handshake_type != HandshakePacket::HS_TYPE_INDUCTION) { } else if (_handleshake_req->handshake_type != HandshakePacket::HS_TYPE_INDUCTION) {
WarnL <<"not reach this"; WarnL <<"not reach this";
return; return;
} }
// Induction Phase // Induction Phase
if (pkt.version != 5) { if (pkt.version != 5) {
WarnL << "not support handleshake version: " << pkt.version; WarnL << "not support handleshake version: " << pkt.version;
return; return;
} }
if (pkt.extension_field != 0x4A17) { if (pkt.extension_field != 0x4A17) {
WarnL << "not match SRT MAGIC"; WarnL << "not match SRT MAGIC";
return; return;
} }
if (pkt.dst_socket_id != _handleshake_req->srt_socket_id) { if (pkt.dst_socket_id != _handleshake_req->srt_socket_id) {
WarnL << "not match _socket_id"; WarnL << "not match _socket_id";
return; return;
} }
// TODO: encryption_field // TODO: encryption_field
_sync_cookie = pkt.syn_cookie; _sync_cookie = pkt.syn_cookie;
_mtu = std::min<uint32_t>(pkt.mtu, _mtu); _mtu = std::min<uint32_t>(pkt.mtu, _mtu);
_max_flow_window_size = std::min<uint32_t>(pkt.max_flow_window_size, _max_flow_window_size); _max_flow_window_size = std::min<uint32_t>(pkt.max_flow_window_size, _max_flow_window_size);
sendHandshakeConclusion(); sendHandshakeConclusion();
return; return;
} }
void SrtCaller::handleHandshakeConclusion(SRT::HandshakePacket &pkt, struct sockaddr *addr) { void SrtCaller::handleHandshakeConclusion(SRT::HandshakePacket &pkt, struct sockaddr *addr) {
DebugL; DebugL;
if (!_handleshake_req) { if (!_handleshake_req) {
WarnL << "must Conclusion Phase for handleshake "; WarnL << "must Conclusion Phase for handleshake ";
return; return;
} }
if (_handleshake_req->handshake_type == HandshakePacket::HS_TYPE_INDUCTION) { if (_handleshake_req->handshake_type == HandshakePacket::HS_TYPE_INDUCTION) {
WarnL << "should be Conclusion Phase for handleshake "; WarnL << "should be Conclusion Phase for handleshake ";
return; return;
} else if (_handleshake_req->handshake_type != HandshakePacket::HS_TYPE_CONCLUSION) { } else if (_handleshake_req->handshake_type != HandshakePacket::HS_TYPE_CONCLUSION) {
WarnL <<"not reach this"; WarnL <<"not reach this";
return; return;
} }
// Conclusion Phase // Conclusion Phase
if (pkt.version != 5) { if (pkt.version != 5) {
WarnL << "not support handleshake version: " << pkt.version; WarnL << "not support handleshake version: " << pkt.version;
return; return;
} }
if (pkt.dst_socket_id != _handleshake_req->srt_socket_id) { if (pkt.dst_socket_id != _handleshake_req->srt_socket_id) {
WarnL << "not match _socket_id"; WarnL << "not match _socket_id";
return; return;
} }
// TODO: encryption_field // TODO: encryption_field
_peer_socket_id = pkt.srt_socket_id; _peer_socket_id = pkt.srt_socket_id;
HSExtMessage::Ptr resp; HSExtMessage::Ptr resp;
HSExtKeyMaterial::Ptr keyMaterial; HSExtKeyMaterial::Ptr keyMaterial;
for (auto& ext : pkt.ext_list) { for (auto& ext : pkt.ext_list) {
if (!resp) { if (!resp) {
resp = std::dynamic_pointer_cast<HSExtMessage>(ext); resp = std::dynamic_pointer_cast<HSExtMessage>(ext);
} }
if (!keyMaterial) { if (!keyMaterial) {
keyMaterial = std::dynamic_pointer_cast<HSExtKeyMaterial>(ext); keyMaterial = std::dynamic_pointer_cast<HSExtKeyMaterial>(ext);
} }
} }
if (resp) { if (resp) {
_delay = std::max<uint16_t>(_delay, resp->recv_tsbpd_delay); _delay = std::max<uint16_t>(_delay, resp->recv_tsbpd_delay);
//DebugL << "flag " << resp->srt_flag; //DebugL << "flag " << resp->srt_flag;
//DebugL << "recv_tsbpd_delay " << resp->recv_tsbpd_delay; //DebugL << "recv_tsbpd_delay " << resp->recv_tsbpd_delay;
//DebugL << "send_tsbpd_delay " << resp->send_tsbpd_delay; //DebugL << "send_tsbpd_delay " << resp->send_tsbpd_delay;
} }
if (keyMaterial && _crypto) { if (keyMaterial && _crypto) {
_crypto->loadFromKeyMaterial(keyMaterial); _crypto->loadFromKeyMaterial(keyMaterial);
@ -715,7 +696,7 @@ void SrtCaller::handleHandshakeConclusion(SRT::HandshakePacket &pkt, struct sock
} }
onHandShakeFinished(); onHandShakeFinished();
return; return;
} }
void SrtCaller::handleACK(uint8_t *buf, int len, struct sockaddr *addr) { void SrtCaller::handleACK(uint8_t *buf, int len, struct sockaddr *addr) {
@ -730,7 +711,9 @@ void SrtCaller::handleACK(uint8_t *buf, int len, struct sockaddr *addr) {
pkt->timestamp = DurationCountMicroseconds(_now - _start_timestamp); pkt->timestamp = DurationCountMicroseconds(_now - _start_timestamp);
pkt->ack_number = ack.ack_number; pkt->ack_number = ack.ack_number;
pkt->storeToData(); pkt->storeToData();
_send_buf->drop(ack.last_ack_pkt_seq_number); if (_send_buf) {
_send_buf->drop(ack.last_ack_pkt_seq_number);
}
sendControlPacket(pkt, true); sendControlPacket(pkt, true);
// TraceL<<"ack number "<<ack.ack_number; // TraceL<<"ack number "<<ack.ack_number;
return; return;
@ -892,9 +875,9 @@ void SrtCaller::handleKeyMaterialRspPacket(uint8_t *buf, int len, struct sockadd
} }
void SrtCaller::handleDataPacket(uint8_t *buf, int len, struct sockaddr *addr) { void SrtCaller::handleDataPacket(uint8_t *buf, int len, struct sockaddr *addr) {
//TraceL; //TraceL;
DataPacket::Ptr pkt = std::make_shared<DataPacket>(); DataPacket::Ptr pkt = std::make_shared<DataPacket>();
pkt->loadFromData(buf, len); pkt->loadFromData(buf, len);
if (_crypto) { if (_crypto) {
auto payload = _crypto->decrypt(pkt, pkt->payloadData(), pkt->payloadSize()); auto payload = _crypto->decrypt(pkt, pkt->payloadData(), pkt->payloadSize());
@ -906,10 +889,10 @@ void SrtCaller::handleDataPacket(uint8_t *buf, int len, struct sockaddr *addr) {
pkt->reloadPayload((uint8_t*)payload->data(), payload->size()); pkt->reloadPayload((uint8_t*)payload->data(), payload->size());
} }
_estimated_link_capacity_context->inputPacket(_now, pkt); _estimated_link_capacity_context->inputPacket(_now, pkt);
std::list<DataPacket::Ptr> list; std::list<DataPacket::Ptr> list;
_recv_buf->inputPacket(pkt, list); _recv_buf->inputPacket(pkt, list);
for (auto& data : list) { for (auto& data : list) {
if (_last_pkt_seq + 1 != data->packet_seq_number) { if (_last_pkt_seq + 1 != data->packet_seq_number) {
TraceL << "pkt lost " << _last_pkt_seq + 1 << "->" << data->packet_seq_number; TraceL << "pkt lost " << _last_pkt_seq + 1 << "->" << data->packet_seq_number;
@ -1008,14 +991,7 @@ float SrtCaller::getTimeOutSec() {
}; };
std::string SrtCaller::generateStreamId() { std::string SrtCaller::generateStreamId() {
auto streamId = "#!::r=" + _url._app + "/" + _url._stream; return _url._streamid;
if (_url._vhost != DEFAULT_VHOST) {
streamId += ",h=" +_url._vhost;
}
if (!isPlayer()) {
streamId += ",m=publish";
}
return streamId;
}; };
uint32_t SrtCaller::generateSocketId() { uint32_t SrtCaller::generateSocketId() {

View File

@ -1,199 +1,197 @@
/* /*
* Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved.
* *
* This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit).
* *
* Use of this source code is governed by MIT-like license that can be found in the * Use of this source code is governed by MIT-like license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors * LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree. * may be found in the AUTHORS file in the root of the source tree.
*/ */
#ifndef ZLMEDIAKIT_SRTCALLER_H #ifndef ZLMEDIAKIT_SRTCALLER_H
#define ZLMEDIAKIT_SRTCALLER_H #define ZLMEDIAKIT_SRTCALLER_H
//srt //srt
#include "srt/Packet.hpp" #include "srt/Packet.hpp"
#include "srt/Crypto.hpp" #include "srt/Crypto.hpp"
#include "srt/PacketQueue.hpp" #include "srt/PacketQueue.hpp"
#include "srt/PacketSendQueue.hpp" #include "srt/PacketSendQueue.hpp"
#include "srt/Statistic.hpp" #include "srt/Statistic.hpp"
#include "Poller/EventPoller.h" #include "Poller/EventPoller.h"
#include "Network/Socket.h" #include "Network/Socket.h"
#include "Poller/Timer.h" #include "Poller/Timer.h"
#include "Util/TimeTicker.h" #include "Util/TimeTicker.h"
#include "Common/MultiMediaSourceMuxer.h" #include "Common/MultiMediaSourceMuxer.h"
#include "Rtp/Decoder.h" #include "Rtp/Decoder.h"
#include "TS/TSMediaSource.h" #include "TS/TSMediaSource.h"
#include <memory> #include <memory>
#include <string> #include <string>
namespace mediakit { namespace mediakit {
// 解析srt 信令url的工具类 // 解析srt 信令url的工具类
class SrtUrl { class SrtUrl {
public: public:
std::string _full_url; std::string _full_url;
std::string _params; std::string _params;
std::string _host; std::string _host;
uint16_t _port; uint16_t _port;
std::string _vhost; std::string _streamid;
std::string _app;
std::string _stream; public:
void parse(const std::string &url);
public: };
void parse(const std::string &url);
}; // 实现了webrtc代理拉流功能
class SrtCaller : public std::enable_shared_from_this<SrtCaller>{
// 实现了webrtc代理拉流功能 public:
class SrtCaller : public std::enable_shared_from_this<SrtCaller>{ using Ptr = std::shared_ptr<SrtCaller>;
public:
using Ptr = std::shared_ptr<SrtCaller>; using SteadyClock = std::chrono::steady_clock;
using TimePoint = std::chrono::time_point<SteadyClock>;
using SteadyClock = std::chrono::steady_clock;
using TimePoint = std::chrono::time_point<SteadyClock>; SrtCaller(const toolkit::EventPoller::Ptr &poller);
virtual ~SrtCaller();
SrtCaller(const toolkit::EventPoller::Ptr &poller);
virtual ~SrtCaller(); const toolkit::EventPoller::Ptr &getPoller() const {return _poller;}
const toolkit::EventPoller::Ptr &getPoller() const {return _poller;} virtual void inputSockData(uint8_t *buf, int len, struct sockaddr *addr);
virtual void onSendTSData(const SRT::Buffer::Ptr &buffer, bool flush);
virtual void inputSockData(uint8_t *buf, int len, struct sockaddr *addr);
virtual void onSendTSData(const SRT::Buffer::Ptr &buffer, bool flush); protected:
protected: virtual void onConnect();
virtual void onHandShakeFinished();
virtual void onConnect(); virtual void onResult(const toolkit::SockException &ex);
virtual void onHandShakeFinished();
virtual void onResult(const toolkit::SockException &ex); virtual void onSRTData(SRT::DataPacket::Ptr pkt);
virtual void onSRTData(SRT::DataPacket::Ptr pkt); virtual uint16_t getLatency() = 0;
virtual int getLatencyMul();
virtual uint16_t getLatency() = 0; virtual int getPktBufSize();
virtual int getLatencyMul(); virtual float getTimeOutSec();
virtual int getPktBufSize();
virtual float getTimeOutSec(); virtual bool isPlayer() = 0;
virtual bool isPlayer() = 0; private:
void doHandshake();
private:
void doHandshake(); void sendHandshakeInduction();
void sendHandshakeConclusion();
void sendHandshakeInduction(); void sendACKPacket();
void sendHandshakeConclusion(); void sendLightACKPacket();
void sendACKPacket(); void sendNAKPacket(std::list<SRT::PacketQueue::LostPair> &lost_list);
void sendLightACKPacket(); void sendMsgDropReq(uint32_t first, uint32_t last);
void sendNAKPacket(std::list<SRT::PacketQueue::LostPair> &lost_list); void sendKeepLivePacket();
void sendMsgDropReq(uint32_t first, uint32_t last); void sendShutDown();
void sendKeepLivePacket(); void tryAnnounceKeyMaterial();
void sendShutDown(); void sendControlPacket(SRT::ControlPacket::Ptr pkt, bool flush = true);
void tryAnnounceKeyMaterial(); void sendDataPacket(SRT::DataPacket::Ptr pkt, char *buf, int len, bool flush = false);
void sendControlPacket(SRT::ControlPacket::Ptr pkt, bool flush = true); void sendPacket(toolkit::Buffer::Ptr pkt, bool flush);
void sendDataPacket(SRT::DataPacket::Ptr pkt, char *buf, int len, bool flush = false);
void sendPacket(toolkit::Buffer::Ptr pkt, bool flush); void handleHandshake(uint8_t *buf, int len, struct sockaddr *addr);
void handleHandshakeInduction(SRT::HandshakePacket &pkt, struct sockaddr *addr);
void handleHandshake(uint8_t *buf, int len, struct sockaddr *addr); void handleHandshakeConclusion(SRT::HandshakePacket &pkt, struct sockaddr *addr);
void handleHandshakeInduction(SRT::HandshakePacket &pkt, struct sockaddr *addr); void handleACK(uint8_t *buf, int len, struct sockaddr *addr);
void handleHandshakeConclusion(SRT::HandshakePacket &pkt, struct sockaddr *addr); void handleACKACK(uint8_t *buf, int len, struct sockaddr *addr);
void handleACK(uint8_t *buf, int len, struct sockaddr *addr); void handleNAK(uint8_t *buf, int len, struct sockaddr *addr);
void handleACKACK(uint8_t *buf, int len, struct sockaddr *addr); void handleDropReq(uint8_t *buf, int len, struct sockaddr *addr);
void handleNAK(uint8_t *buf, int len, struct sockaddr *addr); void handleKeeplive(uint8_t *buf, int len, struct sockaddr *addr);
void handleDropReq(uint8_t *buf, int len, struct sockaddr *addr); void handleShutDown(uint8_t *buf, int len, struct sockaddr *addr);
void handleKeeplive(uint8_t *buf, int len, struct sockaddr *addr); void handlePeerError(uint8_t *buf, int len, struct sockaddr *addr);
void handleShutDown(uint8_t *buf, int len, struct sockaddr *addr); void handleCongestionWarning(uint8_t *buf, int len, struct sockaddr *addr);
void handlePeerError(uint8_t *buf, int len, struct sockaddr *addr); void handleUserDefinedType(uint8_t *buf, int len, struct sockaddr *addr);
void handleCongestionWarning(uint8_t *buf, int len, struct sockaddr *addr); void handleDataPacket(uint8_t *buf, int len, struct sockaddr *addr);
void handleUserDefinedType(uint8_t *buf, int len, struct sockaddr *addr); void handleKeyMaterialReqPacket(uint8_t *buf, int len, struct sockaddr *addr);
void handleDataPacket(uint8_t *buf, int len, struct sockaddr *addr); void handleKeyMaterialRspPacket(uint8_t *buf, int len, struct sockaddr *addr);
void handleKeyMaterialReqPacket(uint8_t *buf, int len, struct sockaddr *addr);
void handleKeyMaterialRspPacket(uint8_t *buf, int len, struct sockaddr *addr); void checkAndSendAckNak();
void createTimerForCheckAlive();
void checkAndSendAckNak();
void createTimerForCheckAlive(); std::string generateStreamId();
uint32_t generateSocketId();
std::string generateStreamId(); int32_t generateInitSeq();
uint32_t generateSocketId(); size_t getPayloadSize();
int32_t generateInitSeq();
size_t getPayloadSize(); virtual std::string getPassphrase() = 0;
virtual std::string getPassphrase() = 0; protected:
SrtUrl _url;
protected: toolkit::EventPoller::Ptr _poller;
SrtUrl _url;
toolkit::EventPoller::Ptr _poller; bool _is_handleshake_finished = false;
bool _is_handleshake_finished = false; private:
toolkit::Socket::Ptr _socket;
private:
toolkit::Socket::Ptr _socket; TimePoint _now;
TimePoint _start_timestamp;
TimePoint _now; // for calculate rtt for delay
TimePoint _start_timestamp; TimePoint _induction_ts;
// for calculate rtt for delay
TimePoint _induction_ts; //the initial value of RTT is 100 milliseconds
//RTTVar is 50 milliseconds
//the initial value of RTT is 100 milliseconds uint32_t _rtt = 100 * 1000;
//RTTVar is 50 milliseconds uint32_t _rtt_variance = 50 * 1000;
uint32_t _rtt = 100 * 1000;
uint32_t _rtt_variance = 50 * 1000; //local
uint32_t _socket_id = 0;
//local uint32_t _init_seq_number = 0;
uint32_t _socket_id = 0; uint32_t _mtu = 1500;
uint32_t _init_seq_number = 0; uint32_t _max_flow_window_size = 8192;
uint32_t _mtu = 1500; uint16_t _delay = 120;
uint32_t _max_flow_window_size = 8192;
uint16_t _delay = 120; //peer
uint32_t _sync_cookie = 0;
//peer uint32_t _peer_socket_id;
uint32_t _sync_cookie = 0;
uint32_t _peer_socket_id; // for handshake
SRT::Timer::Ptr _handleshake_timer;
// for handshake SRT::HandshakePacket::Ptr _handleshake_req;
SRT::Timer::Ptr _handleshake_timer;
SRT::HandshakePacket::Ptr _handleshake_req; // for keeplive
SRT::Ticker _send_ticker;
// for keeplive SRT::Timer::Ptr _keeplive_timer;
SRT::Ticker _send_ticker;
SRT::Timer::Ptr _keeplive_timer; // for alive
SRT::Ticker _alive_ticker;
// for alive SRT::Timer::Ptr _alive_timer;
SRT::Ticker _alive_ticker;
SRT::Timer::Ptr _alive_timer; // for recv
SRT::PacketQueueInterface::Ptr _recv_buf;
// for recv uint32_t _last_pkt_seq = 0;
SRT::PacketQueueInterface::Ptr _recv_buf;
uint32_t _last_pkt_seq = 0; // Ack
SRT::UTicker _ack_ticker;
// Ack uint32_t _last_ack_pkt_seq = 0;
SRT::UTicker _ack_ticker; uint32_t _light_ack_pkt_count = 0;
uint32_t _last_ack_pkt_seq = 0; uint32_t _ack_number_count = 0;
uint32_t _light_ack_pkt_count = 0; std::map<uint32_t, TimePoint> _ack_send_timestamp;
uint32_t _ack_number_count = 0; // Full Ack
std::map<uint32_t, TimePoint> _ack_send_timestamp; // Link Capacity and Receiving Rate Estimation
// Full Ack std::shared_ptr<SRT::PacketRecvRateContext> _pkt_recv_rate_context;
// Link Capacity and Receiving Rate Estimation std::shared_ptr<SRT::EstimatedLinkCapacityContext> _estimated_link_capacity_context;
std::shared_ptr<SRT::PacketRecvRateContext> _pkt_recv_rate_context;
std::shared_ptr<SRT::EstimatedLinkCapacityContext> _estimated_link_capacity_context; // Nak
SRT::UTicker _nak_ticker;
// Nak
SRT::UTicker _nak_ticker; //for Send
SRT::PacketSendQueue::Ptr _send_buf;
//for Send SRT::ResourcePool<SRT::BufferRaw> _packet_pool;
SRT::PacketSendQueue::Ptr _send_buf; uint32_t _send_packet_seq_number = 0;
SRT::ResourcePool<SRT::BufferRaw> _packet_pool; uint32_t _send_msg_number = 1;
uint32_t _send_packet_seq_number = 0;
uint32_t _send_msg_number = 1; //AckAck
uint32_t _last_recv_ackack_seq_num = 0;
//AckAck
uint32_t _last_recv_ackack_seq_num = 0; // for encryption
SRT::Crypto::Ptr _crypto;
// for encryption SRT::Timer::Ptr _announce_timer;
SRT::Crypto::Ptr _crypto; SRT::KeyMaterialPacket::Ptr _announce_req;
SRT::Timer::Ptr _announce_timer; };
SRT::KeyMaterialPacket::Ptr _announce_req;
}; } /* namespace mediakit */
#endif /* ZLMEDIAKIT_SRTCALLER_H */
} /* namespace mediakit */
#endif /* ZLMEDIAKIT_SRTCALLER_H */

View File

@ -1,169 +1,169 @@
/* /*
* Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved.
* *
* This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit).
* *
* Use of this source code is governed by MIT-like license that can be found in the * Use of this source code is governed by MIT-like license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors * LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree. * may be found in the AUTHORS file in the root of the source tree.
*/ */
#include "SrtPlayer.h" #include "SrtPlayer.h"
#include "SrtPlayerImp.h" #include "SrtPlayerImp.h"
#include "Common/config.h" #include "Common/config.h"
#include "Http/HlsPlayer.h" #include "Http/HlsPlayer.h"
using namespace toolkit; using namespace toolkit;
using namespace std; using namespace std;
namespace mediakit { namespace mediakit {
SrtPlayer::SrtPlayer(const EventPoller::Ptr &poller) SrtPlayer::SrtPlayer(const EventPoller::Ptr &poller)
: SrtCaller(poller) { : SrtCaller(poller) {
DebugL; DebugL;
} }
SrtPlayer::~SrtPlayer(void) { SrtPlayer::~SrtPlayer(void) {
DebugL; DebugL;
} }
void SrtPlayer::play(const string &strUrl) { void SrtPlayer::play(const string &strUrl) {
DebugL; DebugL;
try { try {
_url.parse(strUrl); _url.parse(strUrl);
} catch (std::exception &ex) { } catch (std::exception &ex) {
onResult(SockException(Err_other, StrPrinter << "illegal srt url:" << ex.what())); onResult(SockException(Err_other, StrPrinter << "illegal srt url:" << ex.what()));
return; return;
} }
onConnect(); onConnect();
return; return;
} }
void SrtPlayer::teardown() { void SrtPlayer::teardown() {
SrtCaller::onResult(SockException(Err_other, StrPrinter << "teardown: " << _url._full_url)); SrtCaller::onResult(SockException(Err_other, StrPrinter << "teardown: " << _url._full_url));
} }
void SrtPlayer::pause(bool bPause) { void SrtPlayer::pause(bool bPause) {
DebugL; DebugL;
} }
void SrtPlayer::speed(float speed) { void SrtPlayer::speed(float speed) {
DebugL; DebugL;
} }
void SrtPlayer::onHandShakeFinished() { void SrtPlayer::onHandShakeFinished() {
SrtCaller::onHandShakeFinished(); SrtCaller::onHandShakeFinished();
onResult(SockException(Err_success, "srt play success")); onResult(SockException(Err_success, "srt play success"));
} }
void SrtPlayer::onResult(const SockException &ex) { void SrtPlayer::onResult(const SockException &ex) {
SrtCaller::onResult(ex); SrtCaller::onResult(ex);
if (!ex) { if (!ex) {
// 播放成功 // 播放成功
onPlayResult(ex); onPlayResult(ex);
_benchmark_mode = (*this)[Client::kBenchmarkMode].as<int>(); _benchmark_mode = (*this)[Client::kBenchmarkMode].as<int>();
// 播放成功,恢复数据包接收超时定时器 // 播放成功,恢复数据包接收超时定时器
_recv_ticker.resetTime(); _recv_ticker.resetTime();
auto timeout = getTimeOutSec(); auto timeout = getTimeOutSec();
//读取配置文件 //读取配置文件
weak_ptr<SrtPlayer> weakSelf = static_pointer_cast<SrtPlayer>(shared_from_this()); weak_ptr<SrtPlayer> weakSelf = static_pointer_cast<SrtPlayer>(shared_from_this());
// 创建rtp数据接收超时检测定时器 // 创建rtp数据接收超时检测定时器
_check_timer = std::make_shared<Timer>(timeout /2, _check_timer = std::make_shared<Timer>(timeout /2,
[weakSelf, timeout]() { [weakSelf, timeout]() {
auto strongSelf = weakSelf.lock(); auto strongSelf = weakSelf.lock();
if (!strongSelf) { if (!strongSelf) {
return false; return false;
} }
if (strongSelf->_recv_ticker.elapsedTime() > timeout * 1000) { if (strongSelf->_recv_ticker.elapsedTime() > timeout * 1000) {
// 接收媒体数据包超时 // 接收媒体数据包超时
strongSelf->onResult(SockException(Err_timeout, "receive srt media data timeout:" + strongSelf->_url._full_url)); strongSelf->onResult(SockException(Err_timeout, "receive srt media data timeout:" + strongSelf->_url._full_url));
return false; return false;
} }
return true; return true;
}, getPoller()); }, getPoller());
} else { } else {
WarnL << ex.getErrCode() << " " << ex.what(); WarnL << ex.getErrCode() << " " << ex.what();
if (ex.getErrCode() == Err_shutdown) { if (ex.getErrCode() == Err_shutdown) {
// 主动shutdown的不触发回调 // 主动shutdown的不触发回调
return; return;
} }
if (!_is_handleshake_finished) { if (!_is_handleshake_finished) {
onPlayResult(ex); onPlayResult(ex);
} else { } else {
onShutdown(ex); onShutdown(ex);
} }
} }
return; return;
} }
void SrtPlayer::onSRTData(SRT::DataPacket::Ptr pkt) { void SrtPlayer::onSRTData(SRT::DataPacket::Ptr pkt) {
_recv_ticker.resetTime(); _recv_ticker.resetTime();
} }
uint16_t SrtPlayer::getLatency() { uint16_t SrtPlayer::getLatency() {
auto latency = (*this)[Client::kLatency].as<uint16_t>(); auto latency = (*this)[Client::kLatency].as<uint16_t>();
return (uint16_t)latency ; return (uint16_t)latency ;
} }
float SrtPlayer::getTimeOutSec() { float SrtPlayer::getTimeOutSec() {
auto timeoutMS = (*this)[Client::kTimeoutMS].as<uint64_t>(); auto timeoutMS = (*this)[Client::kTimeoutMS].as<uint64_t>();
return (float)timeoutMS / (float)1000; return (float)timeoutMS / (float)1000;
} }
std::string SrtPlayer::getPassphrase() { std::string SrtPlayer::getPassphrase() {
auto passPhrase = (*this)[Client::kPassPhrase].as<string>(); auto passPhrase = (*this)[Client::kPassPhrase].as<string>();
return passPhrase; return passPhrase;
} }
/////////////////////////////////////////////////// ///////////////////////////////////////////////////
// SrtPlayerImp // SrtPlayerImp
void SrtPlayerImp::onPlayResult(const toolkit::SockException &ex) { void SrtPlayerImp::onPlayResult(const toolkit::SockException &ex) {
if (ex) { if (ex) {
Super::onPlayResult(ex); Super::onPlayResult(ex);
} }
//success result only occur when addTrackCompleted //success result only occur when addTrackCompleted
return; return;
} }
std::vector<Track::Ptr> SrtPlayerImp::getTracks(bool ready /*= true*/) const { std::vector<Track::Ptr> SrtPlayerImp::getTracks(bool ready /*= true*/) const {
return _demuxer ? static_pointer_cast<HlsDemuxer>(_demuxer)->getTracks(ready) : Super::getTracks(ready); return _demuxer ? static_pointer_cast<HlsDemuxer>(_demuxer)->getTracks(ready) : Super::getTracks(ready);
} }
void SrtPlayerImp::addTrackCompleted() { void SrtPlayerImp::addTrackCompleted() {
Super::onPlayResult(toolkit::SockException(toolkit::Err_success, "play success")); Super::onPlayResult(toolkit::SockException(toolkit::Err_success, "play success"));
} }
void SrtPlayerImp::onSRTData(SRT::DataPacket::Ptr pkt) { void SrtPlayerImp::onSRTData(SRT::DataPacket::Ptr pkt) {
SrtPlayer::onSRTData(pkt); SrtPlayer::onSRTData(pkt);
if (_benchmark_mode) { if (_benchmark_mode) {
return; return;
} }
auto strong_self = shared_from_this(); auto strong_self = shared_from_this();
if (!_demuxer) { if (!_demuxer) {
auto demuxer = std::make_shared<HlsDemuxer>(); auto demuxer = std::make_shared<HlsDemuxer>();
demuxer->start(getPoller(), this); demuxer->start(getPoller(), this);
_demuxer = std::move(demuxer); _demuxer = std::move(demuxer);
} }
if (!_decoder && _demuxer) { if (!_decoder && _demuxer) {
_decoder = DecoderImp::createDecoder(DecoderImp::decoder_ts, _demuxer.get()); _decoder = DecoderImp::createDecoder(DecoderImp::decoder_ts, _demuxer.get());
} }
if (_decoder && _demuxer) { if (_decoder && _demuxer) {
_decoder->input(reinterpret_cast<const uint8_t *>(pkt->payloadData()), pkt->payloadSize()); _decoder->input(reinterpret_cast<const uint8_t *>(pkt->payloadData()), pkt->payloadSize());
} }
return; return;
} }
} /* namespace mediakit */ } /* namespace mediakit */

View File

@ -1,65 +1,65 @@
/* /*
* Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved.
* *
* This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit).
* *
* Use of this source code is governed by MIT-like license that can be found in the * Use of this source code is governed by MIT-like license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors * LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree. * may be found in the AUTHORS file in the root of the source tree.
*/ */
#ifndef ZLMEDIAKIT_SRTPLAYER_H #ifndef ZLMEDIAKIT_SRTPLAYER_H
#define ZLMEDIAKIT_SRTPLAYER_H #define ZLMEDIAKIT_SRTPLAYER_H
#include "Network/Socket.h" #include "Network/Socket.h"
#include "Player/PlayerBase.h" #include "Player/PlayerBase.h"
#include "Poller/Timer.h" #include "Poller/Timer.h"
#include "Util/TimeTicker.h" #include "Util/TimeTicker.h"
#include "srt/SrtTransport.hpp" #include "srt/SrtTransport.hpp"
#include "Http/HttpRequester.h" #include "Http/HttpRequester.h"
#include <memory> #include <memory>
#include <string> #include <string>
#include "SrtCaller.h" #include "SrtCaller.h"
namespace mediakit { namespace mediakit {
// 实现了srt代理拉流功能 // 实现了srt代理拉流功能
class SrtPlayer class SrtPlayer
: public PlayerBase , public SrtCaller { : public PlayerBase , public SrtCaller {
public: public:
using Ptr = std::shared_ptr<SrtPlayer>; using Ptr = std::shared_ptr<SrtPlayer>;
SrtPlayer(const toolkit::EventPoller::Ptr &poller); SrtPlayer(const toolkit::EventPoller::Ptr &poller);
~SrtPlayer() override; ~SrtPlayer() override;
//// PlayerBase override//// //// PlayerBase override////
void play(const std::string &strUrl) override; void play(const std::string &strUrl) override;
void teardown() override; void teardown() override;
void pause(bool pause) override; void pause(bool pause) override;
void speed(float speed) override; void speed(float speed) override;
protected: protected:
//// SrtCaller override//// //// SrtCaller override////
void onHandShakeFinished() override; void onHandShakeFinished() override;
void onSRTData(SRT::DataPacket::Ptr pkt) override; void onSRTData(SRT::DataPacket::Ptr pkt) override;
void onResult(const toolkit::SockException &ex) override; void onResult(const toolkit::SockException &ex) override;
bool isPlayer() override {return true;} bool isPlayer() override {return true;}
uint16_t getLatency() override; uint16_t getLatency() override;
float getTimeOutSec() override; float getTimeOutSec() override;
std::string getPassphrase() override; std::string getPassphrase() override;
protected: protected:
//是否为性能测试模式 //是否为性能测试模式
bool _benchmark_mode = false; bool _benchmark_mode = false;
//超时功能实现 //超时功能实现
toolkit::Ticker _recv_ticker; toolkit::Ticker _recv_ticker;
std::shared_ptr<toolkit::Timer> _check_timer; std::shared_ptr<toolkit::Timer> _check_timer;
}; };
} /* namespace mediakit */ } /* namespace mediakit */
#endif /* ZLMEDIAKIT_SRTPLAYER_H */ #endif /* ZLMEDIAKIT_SRTPLAYER_H */

View File

@ -1,51 +1,51 @@
/* /*
* Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved.
* *
* This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit).
* *
* Use of this source code is governed by MIT-like license that can be found in the * Use of this source code is governed by MIT-like license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors * LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree. * may be found in the AUTHORS file in the root of the source tree.
*/ */
#ifndef ZLMEDIAKIT_SRtPLAYERIMP_H #ifndef ZLMEDIAKIT_SRtPLAYERIMP_H
#define ZLMEDIAKIT_SRtPLAYERIMP_H #define ZLMEDIAKIT_SRtPLAYERIMP_H
#include "SrtPlayer.h" #include "SrtPlayer.h"
namespace mediakit { namespace mediakit {
class SrtPlayerImp class SrtPlayerImp
: public PlayerImp<SrtPlayer, PlayerBase> : public PlayerImp<SrtPlayer, PlayerBase>
, private TrackListener { , private TrackListener {
public: public:
using Ptr = std::shared_ptr<SrtPlayerImp>; using Ptr = std::shared_ptr<SrtPlayerImp>;
using Super = PlayerImp<SrtPlayer, PlayerBase>; using Super = PlayerImp<SrtPlayer, PlayerBase>;
SrtPlayerImp(const toolkit::EventPoller::Ptr &poller) : Super(poller) {} SrtPlayerImp(const toolkit::EventPoller::Ptr &poller) : Super(poller) {}
~SrtPlayerImp() override { DebugL; } ~SrtPlayerImp() override { DebugL; }
private: private:
//// SrtPlayer override//// //// SrtPlayer override////
void onSRTData(SRT::DataPacket::Ptr pkt) override; void onSRTData(SRT::DataPacket::Ptr pkt) override;
//// PlayerBase override//// //// PlayerBase override////
void onPlayResult(const toolkit::SockException &ex) override; void onPlayResult(const toolkit::SockException &ex) override;
std::vector<Track::Ptr> getTracks(bool ready = true) const override; std::vector<Track::Ptr> getTracks(bool ready = true) const override;
private: private:
//// TrackListener override//// //// TrackListener override////
bool addTrack(const Track::Ptr &track) override { return true; } bool addTrack(const Track::Ptr &track) override { return true; }
void addTrackCompleted() override; void addTrackCompleted() override;
private: private:
// for player // for player
DecoderImp::Ptr _decoder; DecoderImp::Ptr _decoder;
MediaSinkInterface::Ptr _demuxer; MediaSinkInterface::Ptr _demuxer;
// for pusher // for pusher
TSMediaSource::RingType::RingReader::Ptr _ts_reader; TSMediaSource::RingType::RingReader::Ptr _ts_reader;
}; };
} /* namespace mediakit */ } /* namespace mediakit */
#endif /* ZLMEDIAKIT_SRtPLAYERIMP_H */ #endif /* ZLMEDIAKIT_SRtPLAYERIMP_H */

View File

@ -1,116 +1,116 @@
/* /*
* Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved.
* *
* This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit).
* *
* Use of this source code is governed by MIT-like license that can be found in the * Use of this source code is governed by MIT-like license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors * LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree. * may be found in the AUTHORS file in the root of the source tree.
*/ */
#include "SrtPusher.h" #include "SrtPusher.h"
#include "Common/config.h" #include "Common/config.h"
using namespace toolkit; using namespace toolkit;
using namespace std; using namespace std;
namespace mediakit { namespace mediakit {
SrtPusher::SrtPusher(const EventPoller::Ptr &poller, const TSMediaSource::Ptr &src) : SrtCaller(poller) { SrtPusher::SrtPusher(const EventPoller::Ptr &poller, const TSMediaSource::Ptr &src) : SrtCaller(poller) {
_push_src = src; _push_src = src;
DebugL; DebugL;
} }
SrtPusher::~SrtPusher(void) { SrtPusher::~SrtPusher(void) {
DebugL; DebugL;
} }
void SrtPusher::publish(const string &strUrl) { void SrtPusher::publish(const string &strUrl) {
DebugL; DebugL;
try { try {
_url.parse(strUrl); _url.parse(strUrl);
} catch (std::exception &ex) { } catch (std::exception &ex) {
onResult(SockException(Err_other, StrPrinter << "illegal srt url:" << ex.what())); onResult(SockException(Err_other, StrPrinter << "illegal srt url:" << ex.what()));
return; return;
} }
onConnect(); onConnect();
return; return;
} }
void SrtPusher::teardown() { void SrtPusher::teardown() {
SrtCaller::onResult(SockException(Err_other, StrPrinter << "teardown: " << _url._full_url)); SrtCaller::onResult(SockException(Err_other, StrPrinter << "teardown: " << _url._full_url));
} }
void SrtPusher::onHandShakeFinished() { void SrtPusher::onHandShakeFinished() {
SrtCaller::onHandShakeFinished(); SrtCaller::onHandShakeFinished();
onResult(SockException(Err_success, "srt push success")); onResult(SockException(Err_success, "srt push success"));
doPublish(); doPublish();
} }
void SrtPusher::onResult(const SockException &ex) { void SrtPusher::onResult(const SockException &ex) {
SrtCaller::onResult(ex); SrtCaller::onResult(ex);
if (!ex) { if (!ex) {
onPublishResult(ex); onPublishResult(ex);
} else { } else {
WarnL << ex.getErrCode() << " " << ex.what(); WarnL << ex.getErrCode() << " " << ex.what();
if (ex.getErrCode() == Err_shutdown) { if (ex.getErrCode() == Err_shutdown) {
// 主动shutdown的不触发回调 // 主动shutdown的不触发回调
return; return;
} }
if (!_is_handleshake_finished) { if (!_is_handleshake_finished) {
onPublishResult(ex); onPublishResult(ex);
} else { } else {
onShutdown(ex); onShutdown(ex);
} }
} }
return; return;
} }
uint16_t SrtPusher::getLatency() { uint16_t SrtPusher::getLatency() {
auto latency = (*this)[Client::kLatency].as<uint16_t>(); auto latency = (*this)[Client::kLatency].as<uint16_t>();
return (uint16_t)latency ; return (uint16_t)latency ;
} }
float SrtPusher::getTimeOutSec() { float SrtPusher::getTimeOutSec() {
auto timeoutMS = (*this)[Client::kTimeoutMS].as<uint64_t>(); auto timeoutMS = (*this)[Client::kTimeoutMS].as<uint64_t>();
return (float)timeoutMS / (float)1000; return (float)timeoutMS / (float)1000;
} }
std::string SrtPusher::getPassphrase() { std::string SrtPusher::getPassphrase() {
auto passPhrase = (*this)[Client::kPassPhrase].as<string>(); auto passPhrase = (*this)[Client::kPassPhrase].as<string>();
return passPhrase; return passPhrase;
} }
void SrtPusher::doPublish() { void SrtPusher::doPublish() {
auto src = _push_src.lock(); auto src = _push_src.lock();
if (!src) { if (!src) {
onResult(SockException(Err_eof, "the media source was released")); onResult(SockException(Err_eof, "the media source was released"));
return; return;
} }
// 异步查找直播流 // 异步查找直播流
std::weak_ptr<SrtPusher> weak_self = static_pointer_cast<SrtPusher>(shared_from_this()); std::weak_ptr<SrtPusher> weak_self = static_pointer_cast<SrtPusher>(shared_from_this());
_ts_reader = src->getRing()->attach(getPoller()); _ts_reader = src->getRing()->attach(getPoller());
_ts_reader->setDetachCB([weak_self]() { _ts_reader->setDetachCB([weak_self]() {
auto strong_self = weak_self.lock(); auto strong_self = weak_self.lock();
if (!strong_self) { if (!strong_self) {
// 本对象已经销毁 // 本对象已经销毁
return; return;
} }
strong_self->onShutdown(SockException(Err_shutdown)); strong_self->onShutdown(SockException(Err_shutdown));
}); });
_ts_reader->setReadCB([weak_self](const TSMediaSource::RingDataType &ts_list) { _ts_reader->setReadCB([weak_self](const TSMediaSource::RingDataType &ts_list) {
auto strong_self = weak_self.lock(); auto strong_self = weak_self.lock();
if (!strong_self) { if (!strong_self) {
// 本对象已经销毁 // 本对象已经销毁
return; return;
} }
size_t i = 0; size_t i = 0;
auto size = ts_list->size(); auto size = ts_list->size();
ts_list->for_each([&](const TSPacket::Ptr &ts) { ts_list->for_each([&](const TSPacket::Ptr &ts) {
strong_self->onSendTSData(ts, ++i == size); strong_self->onSendTSData(ts, ++i == size);
}); });
}); });
} }
} /* namespace mediakit */ } /* namespace mediakit */

View File

@ -1,59 +1,59 @@
/* /*
* Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved.
* *
* This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit).
* *
* Use of this source code is governed by MIT-like license that can be found in the * Use of this source code is governed by MIT-like license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors * LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree. * may be found in the AUTHORS file in the root of the source tree.
*/ */
#ifndef ZLMEDIAKIT_SRTPUSHER_H #ifndef ZLMEDIAKIT_SRTPUSHER_H
#define ZLMEDIAKIT_SRTPUSHER_H #define ZLMEDIAKIT_SRTPUSHER_H
#include "Network/Socket.h" #include "Network/Socket.h"
#include "Pusher/PusherBase.h" #include "Pusher/PusherBase.h"
#include "Poller/Timer.h" #include "Poller/Timer.h"
#include "Util/TimeTicker.h" #include "Util/TimeTicker.h"
#include "srt/SrtTransport.hpp" #include "srt/SrtTransport.hpp"
#include "Http/HttpRequester.h" #include "Http/HttpRequester.h"
#include <memory> #include <memory>
#include <string> #include <string>
#include "SrtCaller.h" #include "SrtCaller.h"
namespace mediakit { namespace mediakit {
// 实现了srt代理推流功能 // 实现了srt代理推流功能
class SrtPusher class SrtPusher
: public PusherBase , public SrtCaller { : public PusherBase , public SrtCaller {
public: public:
using Ptr = std::shared_ptr<SrtPusher>; using Ptr = std::shared_ptr<SrtPusher>;
SrtPusher(const toolkit::EventPoller::Ptr &poller,const TSMediaSource::Ptr &src); SrtPusher(const toolkit::EventPoller::Ptr &poller,const TSMediaSource::Ptr &src);
~SrtPusher() override; ~SrtPusher() override;
//// PusherBase override//// //// PusherBase override////
void publish(const std::string &url) override; void publish(const std::string &url) override;
void teardown() override; void teardown() override;
void doPublish(); void doPublish();
protected: protected:
//// SrtCaller override//// //// SrtCaller override////
void onHandShakeFinished() override; void onHandShakeFinished() override;
void onResult(const toolkit::SockException &ex) override; void onResult(const toolkit::SockException &ex) override;
bool isPlayer() override {return false;} bool isPlayer() override {return false;}
uint16_t getLatency() override; uint16_t getLatency() override;
float getTimeOutSec() override; float getTimeOutSec() override;
std::string getPassphrase() override; std::string getPassphrase() override;
protected: protected:
std::weak_ptr<TSMediaSource> _push_src; std::weak_ptr<TSMediaSource> _push_src;
TSMediaSource::RingType::RingReader::Ptr _ts_reader; TSMediaSource::RingType::RingReader::Ptr _ts_reader;
}; };
using SrtPusherImp = PusherImp<SrtPusher, PusherBase>; using SrtPusherImp = PusherImp<SrtPusher, PusherBase>;
} /* namespace mediakit */ } /* namespace mediakit */
#endif /* ZLMEDIAKIT_SRTPUSHER_H */ #endif /* ZLMEDIAKIT_SRTPUSHER_H */