2017-10-09 22:11:01 +08:00
|
|
|
|
/*
|
2020-04-04 20:30:09 +08:00
|
|
|
|
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
2017-09-27 16:20:30 +08:00
|
|
|
|
*
|
|
|
|
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
|
|
|
|
*
|
2020-04-04 20:30:09 +08:00
|
|
|
|
* Use of this source code is governed by MIT license that can be found in the
|
|
|
|
|
* 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.
|
2017-04-01 16:35:56 +08:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <list>
|
2017-10-09 11:24:00 +08:00
|
|
|
|
#include <type_traits>
|
2019-08-22 16:25:19 +08:00
|
|
|
|
#include "RtpMultiCaster.h"
|
2017-04-25 11:35:41 +08:00
|
|
|
|
#include "Util/util.h"
|
|
|
|
|
#include "Network/sockutil.h"
|
2018-01-30 09:35:54 +08:00
|
|
|
|
#include "RtspSession.h"
|
|
|
|
|
|
2017-10-09 11:24:00 +08:00
|
|
|
|
using namespace std;
|
2018-10-24 17:17:55 +08:00
|
|
|
|
using namespace toolkit;
|
2017-04-01 16:35:56 +08:00
|
|
|
|
|
2018-10-24 17:17:55 +08:00
|
|
|
|
namespace mediakit{
|
2017-04-01 16:35:56 +08:00
|
|
|
|
|
2018-07-03 17:10:11 +08:00
|
|
|
|
MultiCastAddressMaker &MultiCastAddressMaker::Instance() {
|
2020-03-20 11:51:24 +08:00
|
|
|
|
static MultiCastAddressMaker instance;
|
|
|
|
|
return instance;
|
2018-07-03 17:10:11 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-02-07 13:43:44 +08:00
|
|
|
|
static uint32_t addressToInt(const string &ip){
|
|
|
|
|
struct in_addr addr;
|
|
|
|
|
bzero(&addr,sizeof(addr));
|
2020-03-20 11:51:24 +08:00
|
|
|
|
addr.s_addr = inet_addr(ip.data());
|
2018-02-07 13:43:44 +08:00
|
|
|
|
return (uint32_t)ntohl((uint32_t &)addr.s_addr);
|
|
|
|
|
}
|
2017-04-01 16:35:56 +08:00
|
|
|
|
|
|
|
|
|
std::shared_ptr<uint32_t> MultiCastAddressMaker::obtain(uint32_t iTry) {
|
2020-03-20 11:51:24 +08:00
|
|
|
|
lock_guard<recursive_mutex> lck(_mtx);
|
2019-05-28 17:14:36 +08:00
|
|
|
|
GET_CONFIG(string,addrMinStr,MultiCast::kAddrMin);
|
|
|
|
|
GET_CONFIG(string,addrMaxStr,MultiCast::kAddrMax);
|
2018-02-09 11:42:55 +08:00
|
|
|
|
uint32_t addrMin = addressToInt(addrMinStr);
|
2020-03-20 11:51:24 +08:00
|
|
|
|
uint32_t addrMax = addressToInt(addrMaxStr);
|
2018-02-07 13:43:44 +08:00
|
|
|
|
|
2020-03-20 11:51:24 +08:00
|
|
|
|
if(_iAddr > addrMax || _iAddr == 0){
|
|
|
|
|
_iAddr = addrMin;
|
|
|
|
|
}
|
|
|
|
|
auto iGotAddr = _iAddr++;
|
|
|
|
|
if(_setBadAddr.find(iGotAddr) != _setBadAddr.end()){
|
|
|
|
|
//已经分配过了
|
|
|
|
|
if(iTry){
|
|
|
|
|
return obtain(--iTry);
|
|
|
|
|
}
|
|
|
|
|
//分配完了,应该不可能到这里
|
|
|
|
|
ErrorL;
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
_setBadAddr.emplace(iGotAddr);
|
|
|
|
|
std::shared_ptr<uint32_t> ret(new uint32_t(iGotAddr),[](uint32_t *ptr){
|
|
|
|
|
MultiCastAddressMaker::Instance().release(*ptr);
|
|
|
|
|
delete ptr;
|
|
|
|
|
});
|
|
|
|
|
return ret;
|
2017-04-01 16:35:56 +08:00
|
|
|
|
}
|
|
|
|
|
void MultiCastAddressMaker::release(uint32_t iAddr){
|
2020-03-20 11:51:24 +08:00
|
|
|
|
lock_guard<recursive_mutex> lck(_mtx);
|
|
|
|
|
_setBadAddr.erase(iAddr);
|
2017-04-01 16:35:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2019-08-22 16:25:19 +08:00
|
|
|
|
recursive_mutex RtpMultiCaster::g_mtx;
|
|
|
|
|
unordered_map<string, weak_ptr<RtpMultiCaster> > RtpMultiCaster::g_mapBroadCaster;
|
2017-04-01 16:35:56 +08:00
|
|
|
|
|
2019-08-22 16:25:19 +08:00
|
|
|
|
void RtpMultiCaster::setDetachCB(void* listener, const onDetach& cb) {
|
2020-03-20 11:51:24 +08:00
|
|
|
|
lock_guard<recursive_mutex> lck(_mtx);
|
|
|
|
|
if(cb){
|
|
|
|
|
_mapDetach.emplace(listener,cb);
|
|
|
|
|
}else{
|
|
|
|
|
_mapDetach.erase(listener);
|
|
|
|
|
}
|
2017-04-01 16:35:56 +08:00
|
|
|
|
}
|
2019-08-22 16:25:19 +08:00
|
|
|
|
RtpMultiCaster::~RtpMultiCaster() {
|
2020-03-20 11:51:24 +08:00
|
|
|
|
_pReader->setReadCB(nullptr);
|
|
|
|
|
_pReader->setDetachCB(nullptr);
|
|
|
|
|
DebugL;
|
2017-04-01 16:35:56 +08:00
|
|
|
|
}
|
2019-08-22 16:25:19 +08:00
|
|
|
|
RtpMultiCaster::RtpMultiCaster(const EventPoller::Ptr &poller,const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream) {
|
2020-03-20 11:51:24 +08:00
|
|
|
|
auto src = dynamic_pointer_cast<RtspMediaSource>(MediaSource::find(RTSP_SCHEMA,strVhost,strApp, strStream));
|
|
|
|
|
if(!src){
|
|
|
|
|
auto strErr = StrPrinter << "未找到媒体源:" << strVhost << " " << strApp << " " << strStream << endl;
|
|
|
|
|
throw std::runtime_error(strErr);
|
|
|
|
|
}
|
|
|
|
|
_multiAddr = MultiCastAddressMaker::Instance().obtain();
|
|
|
|
|
for(auto i = 0; i < 2; i++){
|
|
|
|
|
_apUdpSock[i].reset(new Socket(poller));
|
|
|
|
|
if(!_apUdpSock[i]->bindUdpSock(0, strLocalIp.data())){
|
|
|
|
|
auto strErr = StrPrinter << "绑定UDP端口失败:" << strLocalIp << endl;
|
|
|
|
|
throw std::runtime_error(strErr);
|
|
|
|
|
}
|
|
|
|
|
auto fd = _apUdpSock[i]->rawFD();
|
2019-05-28 17:14:36 +08:00
|
|
|
|
GET_CONFIG(uint32_t,udpTTL,MultiCast::kUdpTTL);
|
2018-02-09 11:42:55 +08:00
|
|
|
|
|
|
|
|
|
SockUtil::setMultiTTL(fd, udpTTL);
|
2020-03-20 11:51:24 +08:00
|
|
|
|
SockUtil::setMultiLOOP(fd, false);
|
|
|
|
|
SockUtil::setMultiIF(fd, strLocalIp.data());
|
2017-04-01 16:35:56 +08:00
|
|
|
|
|
2020-03-20 11:51:24 +08:00
|
|
|
|
struct sockaddr_in &peerAddr = _aPeerUdpAddr[i];
|
|
|
|
|
peerAddr.sin_family = AF_INET;
|
|
|
|
|
peerAddr.sin_port = htons(_apUdpSock[i]->get_local_port());
|
|
|
|
|
peerAddr.sin_addr.s_addr = htonl(*_multiAddr);
|
|
|
|
|
bzero(&(peerAddr.sin_zero), sizeof peerAddr.sin_zero);
|
|
|
|
|
_apUdpSock[i]->setSendPeerAddr((struct sockaddr *)&peerAddr);
|
|
|
|
|
}
|
|
|
|
|
_pReader = src->getRing()->attach(poller);
|
|
|
|
|
_pReader->setReadCB([this](const RtpPacket::Ptr &pkt){
|
|
|
|
|
int i = (int)(pkt->type);
|
|
|
|
|
auto &pSock = _apUdpSock[i];
|
|
|
|
|
auto &peerAddr = _aPeerUdpAddr[i];
|
2018-01-30 09:35:54 +08:00
|
|
|
|
BufferRtp::Ptr buffer(new BufferRtp(pkt,4));
|
2020-03-20 11:51:24 +08:00
|
|
|
|
pSock->send(buffer);
|
|
|
|
|
});
|
|
|
|
|
_pReader->setDetachCB([this](){
|
|
|
|
|
unordered_map<void * , onDetach > _mapDetach_copy;
|
|
|
|
|
{
|
|
|
|
|
lock_guard<recursive_mutex> lck(_mtx);
|
|
|
|
|
_mapDetach_copy = std::move(_mapDetach);
|
|
|
|
|
}
|
|
|
|
|
for(auto &pr : _mapDetach_copy){
|
|
|
|
|
pr.second();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
DebugL << MultiCastAddressMaker::toString(*_multiAddr) << " "
|
|
|
|
|
<< _apUdpSock[0]->get_local_port() << " "
|
|
|
|
|
<< _apUdpSock[1]->get_local_port() << " "
|
2018-02-02 18:06:08 +08:00
|
|
|
|
<< strVhost << " "
|
2020-03-20 11:51:24 +08:00
|
|
|
|
<< strApp << " " << strStream;
|
2017-04-01 16:35:56 +08:00
|
|
|
|
}
|
2019-08-22 16:25:19 +08:00
|
|
|
|
uint16_t RtpMultiCaster::getPort(TrackType trackType){
|
2020-03-20 11:51:24 +08:00
|
|
|
|
return _apUdpSock[trackType]->get_local_port();
|
2017-04-01 16:35:56 +08:00
|
|
|
|
}
|
2019-08-22 16:25:19 +08:00
|
|
|
|
string RtpMultiCaster::getIP(){
|
2020-03-20 11:51:24 +08:00
|
|
|
|
return inet_ntoa(_aPeerUdpAddr[0].sin_addr);
|
2017-04-01 16:35:56 +08:00
|
|
|
|
}
|
2019-08-22 16:25:19 +08:00
|
|
|
|
RtpMultiCaster::Ptr RtpMultiCaster::make(const EventPoller::Ptr &poller,const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream){
|
2020-03-20 11:51:24 +08:00
|
|
|
|
try{
|
|
|
|
|
auto ret = Ptr(new RtpMultiCaster(poller,strLocalIp,strVhost,strApp,strStream),[poller](RtpMultiCaster *ptr){
|
2019-05-13 09:36:23 +08:00
|
|
|
|
poller->async([ptr]() {
|
|
|
|
|
delete ptr;
|
|
|
|
|
});
|
2020-03-20 11:51:24 +08:00
|
|
|
|
});
|
|
|
|
|
lock_guard<recursive_mutex> lck(g_mtx);
|
|
|
|
|
string strKey = StrPrinter << strLocalIp << " " << strVhost << " " << strApp << " " << strStream << endl;
|
|
|
|
|
weak_ptr<RtpMultiCaster> weakPtr = ret;
|
|
|
|
|
g_mapBroadCaster.emplace(strKey,weakPtr);
|
|
|
|
|
return ret;
|
|
|
|
|
}catch (std::exception &ex) {
|
|
|
|
|
WarnL << ex.what();
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
2017-04-01 16:35:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
2019-08-22 16:25:19 +08:00
|
|
|
|
RtpMultiCaster::Ptr RtpMultiCaster::get(const EventPoller::Ptr &poller,const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream) {
|
2020-03-20 11:51:24 +08:00
|
|
|
|
string strKey = StrPrinter << strLocalIp << " " << strVhost << " " << strApp << " " << strStream << endl;
|
|
|
|
|
lock_guard<recursive_mutex> lck(g_mtx);
|
|
|
|
|
auto it = g_mapBroadCaster.find(strKey);
|
|
|
|
|
if (it == g_mapBroadCaster.end()) {
|
|
|
|
|
return make(poller,strLocalIp,strVhost,strApp, strStream);
|
|
|
|
|
}
|
|
|
|
|
auto ret = it->second.lock();
|
|
|
|
|
if (!ret) {
|
|
|
|
|
g_mapBroadCaster.erase(it);
|
|
|
|
|
return make(poller,strLocalIp,strVhost,strApp, strStream);
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
2017-04-01 16:35:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2018-10-24 17:17:55 +08:00
|
|
|
|
}//namespace mediakit
|