ZLMediaKit/src/Rtsp/RtpMultiCaster.cpp

205 lines
7.0 KiB
C++
Raw Normal View History

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/xia-chu/ZLMediaKit).
2017-09-27 16:20:30 +08:00
*
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
}
bool MultiCastAddressMaker::isMultiCastAddress(uint32_t addr) {
static uint32_t addrMin = mINI::Instance()[MultiCast::kAddrMin].as<uint32_t>();
static uint32_t addrMax = mINI::Instance()[MultiCast::kAddrMax].as<uint32_t>();
return addr >= addrMin && addr <= addrMax;
}
string MultiCastAddressMaker::toString(uint32_t addr) {
addr = htonl(addr);
return SockUtil::inet_ntoa((struct in_addr &) (addr));
}
2018-02-07 13:43:44 +08:00
static uint32_t addressToInt(const string &ip){
struct in_addr addr;
bzero(&addr, sizeof(addr));
addr.s_addr = inet_addr(ip.data());
return (uint32_t) ntohl((uint32_t &) addr.s_addr);
2018-02-07 13:43:44 +08:00
}
2017-04-01 16:35:56 +08:00
std::shared_ptr<uint32_t> MultiCastAddressMaker::obtain(uint32_t max_try) {
2020-03-20 11:51:24 +08:00
lock_guard<recursive_mutex> lck(_mtx);
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
if (_addr > addrMax || _addr == 0) {
_addr = addrMin;
2020-03-20 11:51:24 +08:00
}
auto iGotAddr = _addr++;
if (_used_addr.find(iGotAddr) != _used_addr.end()) {
2020-03-20 11:51:24 +08:00
//已经分配过了
if (max_try) {
return obtain(--max_try);
2020-03-20 11:51:24 +08:00
}
//分配完了,应该不可能到这里
ErrorL;
return nullptr;
}
_used_addr.emplace(iGotAddr);
std::shared_ptr<uint32_t> ret(new uint32_t(iGotAddr), [](uint32_t *ptr) {
2020-03-20 11:51:24 +08:00
MultiCastAddressMaker::Instance().release(*ptr);
delete ptr;
});
return ret;
2017-04-01 16:35:56 +08:00
}
void MultiCastAddressMaker::release(uint32_t addr){
2020-03-20 11:51:24 +08:00
lock_guard<recursive_mutex> lck(_mtx);
_used_addr.erase(addr);
2017-04-01 16:35:56 +08:00
}
////////////////////////////////////////////////////////////////////////////////////
2017-04-01 16:35:56 +08:00
recursive_mutex g_mtx;
unordered_map<string, weak_ptr<RtpMultiCaster> > g_multi_caster_map;
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) {
_detach_map.emplace(listener, cb);
} else {
_detach_map.erase(listener);
2020-03-20 11:51:24 +08:00
}
2017-04-01 16:35:56 +08:00
}
2019-08-22 16:25:19 +08:00
RtpMultiCaster::~RtpMultiCaster() {
_rtp_reader->setReadCB(nullptr);
_rtp_reader->setDetachCB(nullptr);
2020-03-20 11:51:24 +08:00
DebugL;
2017-04-01 16:35:56 +08:00
}
2020-05-26 10:11:58 +08:00
RtpMultiCaster::RtpMultiCaster(SocketHelper &helper, const string &local_ip, const string &vhost, const string &app, const string &stream) {
auto src = dynamic_pointer_cast<RtspMediaSource>(MediaSource::find(RTSP_SCHEMA, vhost, app, stream));
if (!src) {
auto err = StrPrinter << "未找到媒体源:" << vhost << " " << app << " " << stream << endl;
throw std::runtime_error(err);
}
_multicast_ip = MultiCastAddressMaker::Instance().obtain();
if (!_multicast_ip) {
throw std::runtime_error("获取组播地址失败");
2020-03-20 11:51:24 +08:00
}
2018-02-09 11:42:55 +08:00
for (auto i = 0; i < 2; ++i) {
//创建udp socket, 数组下标为TrackType
_udp_sock[i] = helper.createSocket();
if (!_udp_sock[i]->bindUdpSock(0, local_ip.data())) {
auto err = StrPrinter << "绑定UDP端口失败:" << local_ip << endl;
throw std::runtime_error(err);
}
auto fd = _udp_sock[i]->rawFD();
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, local_ip.data());
struct sockaddr_in peer;
peer.sin_family = AF_INET;
//组播目标端口为本地发送端口
peer.sin_port = htons(_udp_sock[i]->get_local_port());
//组播目标地址
peer.sin_addr.s_addr = htonl(*_multicast_ip);
bzero(&(peer.sin_zero), sizeof peer.sin_zero);
_udp_sock[i]->setSendPeerAddr((struct sockaddr *) &peer);
2020-03-20 11:51:24 +08:00
}
_rtp_reader = src->getRing()->attach(helper.getPoller());
_rtp_reader->setReadCB([this](const RtspMediaSource::RingDataType &pkt) {
size_t i = 0;
auto size = pkt->size();
2020-04-07 13:03:53 +08:00
pkt->for_each([&](const RtpPacket::Ptr &rtp) {
auto &sock = _udp_sock[rtp->type];
sock->send(std::make_shared<BufferRtp>(rtp, 4), nullptr, 0, ++i == size);
2020-04-07 13:03:53 +08:00
});
2020-03-20 11:51:24 +08:00
});
2020-04-07 13:03:53 +08:00
_rtp_reader->setDetachCB([this]() {
unordered_map<void *, onDetach> _detach_map_copy;
2020-03-20 11:51:24 +08:00
{
lock_guard<recursive_mutex> lck(_mtx);
_detach_map_copy = std::move(_detach_map);
2020-03-20 11:51:24 +08:00
}
for (auto &pr : _detach_map_copy) {
2020-03-20 11:51:24 +08:00
pr.second();
}
});
DebugL << MultiCastAddressMaker::toString(*_multicast_ip) << " "
<< _udp_sock[0]->get_local_port() << " "
<< _udp_sock[1]->get_local_port() << " "
<< vhost << " " << app << " " << stream;
2017-04-01 16:35:56 +08:00
}
uint16_t RtpMultiCaster::getMultiCasterPort(TrackType trackType) {
return _udp_sock[trackType]->get_local_port();
2017-04-01 16:35:56 +08:00
}
string RtpMultiCaster::getMultiCasterIP() {
struct in_addr addr;
addr.s_addr = htonl(*_multicast_ip);
return SockUtil::inet_ntoa(addr);
2017-04-01 16:35:56 +08:00
}
RtpMultiCaster::Ptr RtpMultiCaster::get(SocketHelper &helper, const string &local_ip, const string &vhost, const string &app, const string &stream) {
static auto on_create = [](SocketHelper &helper, const string &local_ip, const string &vhost, const string &app, const string &stream){
try {
auto poller = helper.getPoller();
auto ret = RtpMultiCaster::Ptr(new RtpMultiCaster(helper, local_ip, vhost, app, stream), [poller](RtpMultiCaster *ptr) {
poller->async([ptr]() {
delete ptr;
});
2019-05-13 09:36:23 +08:00
});
lock_guard<recursive_mutex> lck(g_mtx);
string strKey = StrPrinter << local_ip << " " << vhost << " " << app << " " << stream << endl;
g_multi_caster_map.emplace(strKey, ret);
return ret;
} catch (std::exception &ex) {
WarnL << ex.what();
return RtpMultiCaster::Ptr();
}
};
2017-04-01 16:35:56 +08:00
string strKey = StrPrinter << local_ip << " " << vhost << " " << app << " " << stream << endl;
2020-03-20 11:51:24 +08:00
lock_guard<recursive_mutex> 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);
2020-03-20 11:51:24 +08:00
}
auto ret = it->second.lock();
if (!ret) {
g_multi_caster_map.erase(it);
return on_create(helper, local_ip, vhost, app, stream);
2020-03-20 11:51:24 +08:00
}
return ret;
2017-04-01 16:35:56 +08:00
}
2018-10-24 17:17:55 +08:00
}//namespace mediakit