RtpServer.cpp 3.19 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
 * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
 *
 * This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
 *
 * 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.
 */

#if defined(ENABLE_RTPPROXY)
#include "RtpServer.h"
#include "RtpSelector.h"
namespace mediakit{

RtpServer::RtpServer() {
}

RtpServer::~RtpServer() {
xiongziliang committed
20 21
    if(_on_clearup){
        _on_clearup();
22 23 24
    }
}

25
void RtpServer::start(uint16_t local_port, const string &stream_id,  bool enable_tcp, const char *local_ip) {
26
    //创建udp服务器
27
    Socket::Ptr udp_server = Socket::createSocket(nullptr, false);
xiongziliang committed
28 29 30 31 32 33 34 35 36
    if (local_port == 0) {
        //随机端口,rtp端口采用偶数
        Socket::Ptr rtcp_server = Socket::createSocket(nullptr, false);
        auto pair = std::make_pair(udp_server, rtcp_server);
        makeSockPair(pair, local_ip);
        //取偶数端口
        udp_server = pair.first;
    } else if (!udp_server->bindUdpSock(local_port, local_ip)) {
        //用户指定端口
xiongziliang committed
37
        throw std::runtime_error(StrPrinter << "bindUdpSock on " << local_ip << ":" << local_port << " failed:" << get_uv_errmsg(true));
38 39
    }
    //设置udp socket读缓存
xiongziliang committed
40
    SockUtil::setRecvBuf(udp_server->rawFD(), 4 * 1024 * 1024);
41

xiongziliang committed
42
    TcpServer::Ptr tcp_server;
43
    if (enable_tcp) {
44 45 46 47
        //创建tcp服务器
        tcp_server = std::make_shared<TcpServer>(udp_server->getPoller());
        (*tcp_server)[RtpSession::kStreamID] = stream_id;
        tcp_server->start<RtpSession>(udp_server->get_local_port(), local_ip);
48
    }
xiongziliang committed
49 50 51 52 53

    RtpProcess::Ptr process;
    if (!stream_id.empty()) {
        //指定了流id,那么一个端口一个流(不管是否包含多个ssrc的多个流,绑定rtp源后,会筛选掉ip端口不匹配的流)
        process = RtpSelector::Instance().getProcess(stream_id, true);
xiongziliang committed
54
        udp_server->setOnRead([udp_server, process](const Buffer::Ptr &buf, struct sockaddr *addr, int) {
xiongziliang committed
55
            process->inputRtp(true, udp_server, buf->data(), buf->size(), addr);
xiongziliang committed
56 57 58 59
        });
    } else {
        //未指定流id,一个端口多个流,通过ssrc来分流
        auto &ref = RtpSelector::Instance();
xiongziliang committed
60 61
        udp_server->setOnRead([&ref, udp_server](const Buffer::Ptr &buf, struct sockaddr *addr, int) {
            ref.inputRtp(udp_server, buf->data(), buf->size(), addr);
xiongziliang committed
62 63 64
        });
    }

xiongziliang committed
65
    _on_clearup = [udp_server, process, stream_id]() {
xiongziliang committed
66
        //去除循环引用
xiongziliang committed
67
        udp_server->setOnRead(nullptr);
xiongziliang committed
68 69 70 71 72
        if (process) {
            //删除rtp处理器
            RtpSelector::Instance().delProcess(stream_id, process.get());
        }
    };
xiongziliang committed
73 74 75

    _tcp_server = tcp_server;
    _udp_server = udp_server;
76 77 78 79 80 81 82
    _rtp_process = process;
}

void RtpServer::setOnDetach(const function<void()> &cb){
    if(_rtp_process){
        _rtp_process->setOnDetach(cb);
    }
83 84 85 86 87 88 89 90 91 92 93 94
}

EventPoller::Ptr RtpServer::getPoller() {
    return _udp_server->getPoller();
}

uint16_t RtpServer::getPort() {
    return _udp_server ? _udp_server->get_local_port() : 0;
}

}//namespace mediakit
#endif//defined(ENABLE_RTPPROXY)