RtpBroadCaster.cpp 6.5 KB
Newer Older
xiongziliang committed
1
/*
xiongziliang committed
2
 * MIT License
xzl committed
3
 *
xiongziliang committed
4
 * Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
xiongziliang committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * 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.
xzl committed
25 26 27
 */

#include <list>
28
#include <type_traits>
xiongzilaing committed
29 30 31
#include "RtpBroadCaster.h"
#include "Util/util.h"
#include "Network/sockutil.h"
32 33
#include "RtspSession.h"

34
using namespace std;
xiongziliang committed
35
using namespace toolkit;
xzl committed
36

xiongziliang committed
37
namespace mediakit{
xzl committed
38

39 40 41 42 43
MultiCastAddressMaker &MultiCastAddressMaker::Instance() {
	static MultiCastAddressMaker instance;
	return instance;
}

44 45 46
static uint32_t addressToInt(const string &ip){
    struct in_addr addr;
    bzero(&addr,sizeof(addr));
47
	addr.s_addr =  inet_addr(ip.data());
48 49
    return (uint32_t)ntohl((uint32_t &)addr.s_addr);
}
xzl committed
50 51

std::shared_ptr<uint32_t> MultiCastAddressMaker::obtain(uint32_t iTry) {
52
	lock_guard<recursive_mutex> lck(_mtx);
53 54
    GET_CONFIG(string,addrMinStr,MultiCast::kAddrMin);
    GET_CONFIG(string,addrMaxStr,MultiCast::kAddrMax);
55 56
    uint32_t addrMin = addressToInt(addrMinStr);
	uint32_t addrMax = addressToInt(addrMaxStr);
57

58 59
	if(_iAddr > addrMax || _iAddr == 0){
		_iAddr = addrMin;
xzl committed
60
	}
61 62
	auto iGotAddr =  _iAddr++;
	if(_setBadAddr.find(iGotAddr) != _setBadAddr.end()){
xzl committed
63 64 65 66 67
		//已经分配过了
		if(iTry){
			return obtain(--iTry);
		}
		//分配完了,应该不可能到这里
xiongziliang committed
68
		ErrorL;
xzl committed
69 70
		return nullptr;
	}
71
	_setBadAddr.emplace(iGotAddr);
xzl committed
72
	std::shared_ptr<uint32_t> ret(new uint32_t(iGotAddr),[](uint32_t *ptr){
73
		MultiCastAddressMaker::Instance().release(*ptr);
xzl committed
74 75 76 77 78
		delete ptr;
	});
	return ret;
}
void MultiCastAddressMaker::release(uint32_t iAddr){
79 80
	lock_guard<recursive_mutex> lck(_mtx);
	_setBadAddr.erase(iAddr);
xzl committed
81 82 83 84 85 86 87
}


recursive_mutex RtpBroadCaster::g_mtx;
unordered_map<string, weak_ptr<RtpBroadCaster> > RtpBroadCaster::g_mapBroadCaster;

void RtpBroadCaster::setDetachCB(void* listener, const onDetach& cb) {
88
	lock_guard<recursive_mutex> lck(_mtx);
xzl committed
89
	if(cb){
90
		_mapDetach.emplace(listener,cb);
xzl committed
91
	}else{
92
		_mapDetach.erase(listener);
xzl committed
93 94 95
	}
}
RtpBroadCaster::~RtpBroadCaster() {
96 97
	_pReader->setReadCB(nullptr);
	_pReader->setDetachCB(nullptr);
xzl committed
98 99
	DebugL;
}
100
RtpBroadCaster::RtpBroadCaster(const EventPoller::Ptr &poller,const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream) {
101
	auto src = dynamic_pointer_cast<RtspMediaSource>(MediaSource::find(RTSP_SCHEMA,strVhost,strApp, strStream));
xzl committed
102
	if(!src){
103
		auto strErr = StrPrinter << "未找到媒体源:" << strVhost << " " << strApp << " " << strStream << endl;
xzl committed
104 105
		throw std::runtime_error(strErr);
	}
106
	_multiAddr = MultiCastAddressMaker::Instance().obtain();
xzl committed
107
	for(auto i = 0; i < 2; i++){
108
		_apUdpSock[i].reset(new Socket(poller));
109
		if(!_apUdpSock[i]->bindUdpSock(0, strLocalIp.data())){
xzl committed
110 111 112
			auto strErr = StrPrinter << "绑定UDP端口失败:" << strLocalIp << endl;
			throw std::runtime_error(strErr);
		}
113
		auto fd = _apUdpSock[i]->rawFD();
114
        GET_CONFIG(uint32_t,udpTTL,MultiCast::kUdpTTL);
115 116

        SockUtil::setMultiTTL(fd, udpTTL);
xzl committed
117 118 119
		SockUtil::setMultiLOOP(fd, false);
		SockUtil::setMultiIF(fd, strLocalIp.data());

120
		struct sockaddr_in &peerAddr = _aPeerUdpAddr[i];
xzl committed
121
		peerAddr.sin_family = AF_INET;
122 123
		peerAddr.sin_port = htons(_apUdpSock[i]->get_local_port());
		peerAddr.sin_addr.s_addr = htonl(*_multiAddr);
xzl committed
124
		bzero(&(peerAddr.sin_zero), sizeof peerAddr.sin_zero);
125
		_apUdpSock[i]->setSendPeerAddr((struct sockaddr *)&peerAddr);
xzl committed
126
	}
127
	_pReader = src->getRing()->attach(poller);
128
	_pReader->setReadCB([this](const RtpPacket::Ptr &pkt){
xiongziliang committed
129
		int i = (int)(pkt->type);
130 131
		auto &pSock = _apUdpSock[i];
		auto &peerAddr = _aPeerUdpAddr[i];
132
        BufferRtp::Ptr buffer(new BufferRtp(pkt,4));
133
		pSock->send(buffer);
xzl committed
134
	});
135 136
	_pReader->setDetachCB([this](){
		unordered_map<void * , onDetach > _mapDetach_copy;
xiongziliang committed
137
		{
138 139
			lock_guard<recursive_mutex> lck(_mtx);
			_mapDetach_copy = std::move(_mapDetach);
xzl committed
140
		}
141
		for(auto &pr : _mapDetach_copy){
xiongziliang committed
142
			pr.second();
xzl committed
143 144
		}
	});
145 146 147
	DebugL << MultiCastAddressMaker::toString(*_multiAddr) << " "
			<< _apUdpSock[0]->get_local_port() << " "
			<< _apUdpSock[1]->get_local_port() << " "
148
            << strVhost << " "
xzl committed
149 150
			<< strApp << " " << strStream;
}
151
uint16_t RtpBroadCaster::getPort(TrackType trackType){
152
	return _apUdpSock[trackType]->get_local_port();
xzl committed
153 154
}
string RtpBroadCaster::getIP(){
155
	return inet_ntoa(_aPeerUdpAddr[0].sin_addr);
xzl committed
156
}
157
RtpBroadCaster::Ptr RtpBroadCaster::make(const EventPoller::Ptr &poller,const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream){
xzl committed
158
	try{
159 160 161 162 163
		auto ret = Ptr(new RtpBroadCaster(poller,strLocalIp,strVhost,strApp,strStream),[poller](RtpBroadCaster *ptr){
            poller->async([ptr]() {
                delete ptr;
            });
		});
xzl committed
164
		lock_guard<recursive_mutex> lck(g_mtx);
165
		string strKey = StrPrinter << strLocalIp << " "  << strVhost << " " << strApp << " " << strStream << endl;
xzl committed
166 167 168 169 170 171 172 173 174
		weak_ptr<RtpBroadCaster> weakPtr = ret;
		g_mapBroadCaster.emplace(strKey,weakPtr);
		return ret;
	}catch (std::exception &ex) {
		WarnL << ex.what();
		return nullptr;
	}
}

175
RtpBroadCaster::Ptr RtpBroadCaster::get(const EventPoller::Ptr &poller,const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream) {
176
	string strKey = StrPrinter << strLocalIp << " " << strVhost << " " << strApp << " " << strStream << endl;
xzl committed
177 178 179
	lock_guard<recursive_mutex> lck(g_mtx);
	auto it = g_mapBroadCaster.find(strKey);
	if (it == g_mapBroadCaster.end()) {
180
		return make(poller,strLocalIp,strVhost,strApp, strStream);
xzl committed
181 182 183 184
	}
	auto ret = it->second.lock();
	if (!ret) {
		g_mapBroadCaster.erase(it);
185
		return make(poller,strLocalIp,strVhost,strApp, strStream);
xzl committed
186 187 188 189 190
	}
	return ret;
}


xiongziliang committed
191
}//namespace mediakit