ZLMediaKit/src/Rtsp/RtpBroadCaster.cpp

192 lines
6.5 KiB
C++
Raw Normal View History

2017-10-09 22:11:01 +08:00
/*
2017-09-27 16:20:30 +08:00
* MIT License
2017-04-01 16:35:56 +08:00
*
2019-05-08 15:40:07 +08:00
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
2017-09-27 16:20:30 +08:00
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
2017-04-01 16:35:56 +08:00
*/
#include <list>
2017-10-09 11:24:00 +08:00
#include <type_traits>
2017-04-25 11:35:41 +08:00
#include "RtpBroadCaster.h"
#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() {
static MultiCastAddressMaker instance;
return instance;
}
2018-02-07 13:43:44 +08:00
static uint32_t addressToInt(const string &ip){
struct in_addr addr;
bzero(&addr,sizeof(addr));
2018-03-05 10:41:15 +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) {
2018-10-24 15:43:52 +08:00
lock_guard<recursive_mutex> lck(_mtx);
2018-10-24 17:17:55 +08:00
GET_CONFIG_AND_REGISTER(string,addrMinStr,MultiCast::kAddrMin);
GET_CONFIG_AND_REGISTER(string,addrMaxStr,MultiCast::kAddrMax);
2018-02-09 11:42:55 +08:00
uint32_t addrMin = addressToInt(addrMinStr);
uint32_t addrMax = addressToInt(addrMaxStr);
2018-02-07 13:43:44 +08:00
2018-10-24 15:43:52 +08:00
if(_iAddr > addrMax || _iAddr == 0){
_iAddr = addrMin;
2017-04-01 16:35:56 +08:00
}
2018-10-24 15:43:52 +08:00
auto iGotAddr = _iAddr++;
if(_setBadAddr.find(iGotAddr) != _setBadAddr.end()){
2017-04-01 16:35:56 +08:00
//已经分配过了
if(iTry){
return obtain(--iTry);
}
//分配完了,应该不可能到这里
2018-04-09 11:26:39 +08:00
ErrorL;
2017-04-01 16:35:56 +08:00
return nullptr;
}
2018-10-24 15:43:52 +08:00
_setBadAddr.emplace(iGotAddr);
2017-04-01 16:35:56 +08:00
std::shared_ptr<uint32_t> ret(new uint32_t(iGotAddr),[](uint32_t *ptr){
2018-02-07 13:43:44 +08:00
MultiCastAddressMaker::Instance().release(*ptr);
2017-04-01 16:35:56 +08:00
delete ptr;
});
return ret;
}
void MultiCastAddressMaker::release(uint32_t iAddr){
2018-10-24 15:43:52 +08:00
lock_guard<recursive_mutex> lck(_mtx);
_setBadAddr.erase(iAddr);
2017-04-01 16:35:56 +08:00
}
recursive_mutex RtpBroadCaster::g_mtx;
unordered_map<string, weak_ptr<RtpBroadCaster> > RtpBroadCaster::g_mapBroadCaster;
void RtpBroadCaster::setDetachCB(void* listener, const onDetach& cb) {
2018-10-24 15:43:52 +08:00
lock_guard<recursive_mutex> lck(_mtx);
2017-04-01 16:35:56 +08:00
if(cb){
2018-10-24 15:43:52 +08:00
_mapDetach.emplace(listener,cb);
2017-04-01 16:35:56 +08:00
}else{
2018-10-24 15:43:52 +08:00
_mapDetach.erase(listener);
2017-04-01 16:35:56 +08:00
}
}
RtpBroadCaster::~RtpBroadCaster() {
2018-10-24 15:43:52 +08:00
_pReader->setReadCB(nullptr);
_pReader->setDetachCB(nullptr);
2017-04-01 16:35:56 +08:00
DebugL;
}
2019-05-10 18:33:23 +08:00
RtpBroadCaster::RtpBroadCaster(const EventPoller::Ptr &poller,const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream) {
auto src = dynamic_pointer_cast<RtspMediaSource>(MediaSource::find(RTSP_SCHEMA,strVhost,strApp, strStream));
2017-04-01 16:35:56 +08:00
if(!src){
auto strErr = StrPrinter << "未找到媒体源:" << strVhost << " " << strApp << " " << strStream << endl;
2017-04-01 16:35:56 +08:00
throw std::runtime_error(strErr);
}
2018-10-24 15:43:52 +08:00
_multiAddr = MultiCastAddressMaker::Instance().obtain();
2017-04-01 16:35:56 +08:00
for(auto i = 0; i < 2; i++){
2018-10-24 15:43:52 +08:00
_apUdpSock[i].reset(new Socket());
if(!_apUdpSock[i]->bindUdpSock(0, strLocalIp.data())){
2017-04-01 16:35:56 +08:00
auto strErr = StrPrinter << "绑定UDP端口失败:" << strLocalIp << endl;
throw std::runtime_error(strErr);
}
2018-10-24 15:43:52 +08:00
auto fd = _apUdpSock[i]->rawFD();
2018-10-24 17:17:55 +08:00
GET_CONFIG_AND_REGISTER(uint32_t,udpTTL,MultiCast::kUdpTTL);
2018-02-09 11:42:55 +08:00
SockUtil::setMultiTTL(fd, udpTTL);
2017-04-01 16:35:56 +08:00
SockUtil::setMultiLOOP(fd, false);
SockUtil::setMultiIF(fd, strLocalIp.data());
2018-10-24 15:43:52 +08:00
struct sockaddr_in &peerAddr = _aPeerUdpAddr[i];
2017-04-01 16:35:56 +08:00
peerAddr.sin_family = AF_INET;
2018-10-24 15:43:52 +08:00
peerAddr.sin_port = htons(_apUdpSock[i]->get_local_port());
peerAddr.sin_addr.s_addr = htonl(*_multiAddr);
2017-04-01 16:35:56 +08:00
bzero(&(peerAddr.sin_zero), sizeof peerAddr.sin_zero);
_apUdpSock[i]->setSendPeerAddr((struct sockaddr *)&peerAddr);
2017-04-01 16:35:56 +08:00
}
2019-05-10 18:33:23 +08:00
_pReader = src->getRing()->attach(poller);
2018-10-24 15:43:52 +08:00
_pReader->setReadCB([this](const RtpPacket::Ptr &pkt){
2018-07-05 18:56:11 +08:00
int i = (int)(pkt->type);
2018-10-24 15:43:52 +08:00
auto &pSock = _apUdpSock[i];
auto &peerAddr = _aPeerUdpAddr[i];
2018-01-30 09:35:54 +08:00
BufferRtp::Ptr buffer(new BufferRtp(pkt,4));
pSock->send(buffer);
2017-04-01 16:35:56 +08:00
});
2018-10-24 15:43:52 +08:00
_pReader->setDetachCB([this](){
unordered_map<void * , onDetach > _mapDetach_copy;
2017-05-04 09:47:02 +08:00
{
2018-10-24 15:43:52 +08:00
lock_guard<recursive_mutex> lck(_mtx);
_mapDetach_copy = std::move(_mapDetach);
2017-04-01 16:35:56 +08:00
}
2018-10-24 15:43:52 +08:00
for(auto &pr : _mapDetach_copy){
2017-05-04 09:47:02 +08:00
pr.second();
2017-04-01 16:35:56 +08:00
}
});
2018-10-24 15:43:52 +08:00
DebugL << MultiCastAddressMaker::toString(*_multiAddr) << " "
<< _apUdpSock[0]->get_local_port() << " "
<< _apUdpSock[1]->get_local_port() << " "
<< strVhost << " "
2017-04-01 16:35:56 +08:00
<< strApp << " " << strStream;
}
2018-07-06 23:04:43 +08:00
uint16_t RtpBroadCaster::getPort(TrackType trackType){
2018-10-24 15:43:52 +08:00
return _apUdpSock[trackType]->get_local_port();
2017-04-01 16:35:56 +08:00
}
string RtpBroadCaster::getIP(){
2018-10-24 15:43:52 +08:00
return inet_ntoa(_aPeerUdpAddr[0].sin_addr);
2017-04-01 16:35:56 +08:00
}
2019-05-10 18:33:23 +08:00
RtpBroadCaster::Ptr RtpBroadCaster::make(const EventPoller::Ptr &poller,const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream){
2017-04-01 16:35:56 +08:00
try{
2019-05-13 09:36:23 +08:00
auto ret = Ptr(new RtpBroadCaster(poller,strLocalIp,strVhost,strApp,strStream),[poller](RtpBroadCaster *ptr){
poller->async([ptr]() {
delete ptr;
});
});
2017-04-01 16:35:56 +08:00
lock_guard<recursive_mutex> lck(g_mtx);
string strKey = StrPrinter << strLocalIp << " " << strVhost << " " << strApp << " " << strStream << endl;
2017-04-01 16:35:56 +08:00
weak_ptr<RtpBroadCaster> weakPtr = ret;
g_mapBroadCaster.emplace(strKey,weakPtr);
return ret;
}catch (std::exception &ex) {
WarnL << ex.what();
return nullptr;
}
}
2019-05-10 18:33:23 +08:00
RtpBroadCaster::Ptr RtpBroadCaster::get(const EventPoller::Ptr &poller,const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream) {
string strKey = StrPrinter << strLocalIp << " " << strVhost << " " << strApp << " " << strStream << endl;
2017-04-01 16:35:56 +08:00
lock_guard<recursive_mutex> lck(g_mtx);
auto it = g_mapBroadCaster.find(strKey);
if (it == g_mapBroadCaster.end()) {
2019-05-10 18:33:23 +08:00
return make(poller,strLocalIp,strVhost,strApp, strStream);
2017-04-01 16:35:56 +08:00
}
auto ret = it->second.lock();
if (!ret) {
g_mapBroadCaster.erase(it);
2019-05-10 18:33:23 +08:00
return make(poller,strLocalIp,strVhost,strApp, strStream);
2017-04-01 16:35:56 +08:00
}
return ret;
}
2018-10-24 17:17:55 +08:00
}//namespace mediakit