/* * Copyright (c) 2012 Yoann Blein * Licensed under the simplified BSD license. * See Documentation/Licenses/BSD-simplified.txt for more information. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Swift { Sender::Sender(boost::shared_ptr udpSocket) : udpSocket(udpSocket), jRTPLocalAddress(RTPSessionImpl::nativeAddressToJRTPAddress(udpSocket->getLocalAddress())) { } Sender::~Sender() { delete jRTPLocalAddress; } bool Sender::SendRTP(const void *data, size_t len) { send(data, len); return true; } bool Sender::SendRTCP(const void* data, size_t len) { send(data, len); return true; } bool Sender::ComesFromThisSender (const jrtplib::RTPAddress* address) { return jRTPLocalAddress->IsSameAddress(address); } void Sender::send(const void* data, size_t len) { uint8_t* uint8Data = (uint8_t*)data; udpSocket->send(SafeByteArray(uint8Data, uint8Data + len)); } RTPSessionImpl::RTPSessionImpl(boost::shared_ptr udpSocket, const RTPPayloadType& payloadType) : udpSocket(udpSocket), payloadType(payloadType), jRTPRemotePeer(nativeAddressToJRTPAddress(udpSocket->getRemoteAddress())), sender(udpSocket) { jrtplib::RTPExternalTransmissionParams transparams(&sender, 0); jrtplib::RTPSessionParams sessparams; // IMPORTANT: The local timestamp unit MUST be set, otherwise RTCP Sender Report info will be calculated wrong sessparams.SetOwnTimestampUnit(1.0 / payloadType.getClockrate()); checkError(session.Create(sessparams, &transparams, jrtplib::RTPTransmitter::ExternalProto)); packetInjecter = static_cast(session.GetTransmissionInfo())->GetPacketInjector(); udpSocket->onDataRead.connect(boost::bind(&RTPSessionImpl::handleDataRead, this, _1)); udpSocket->listen(); } RTPSessionImpl::~RTPSessionImpl() { delete jRTPRemotePeer; } void RTPSessionImpl::poll() { checkError(session.Poll()); // Required if threading disabled } void RTPSessionImpl::checkIncomingPackets() { // session.BeginDataAccess(); // useless without threading if (session.GotoFirstSourceWithData() && session.GetCurrentSourceInfo()->GetRTPDataAddress()->IsSameAddress(jRTPRemotePeer)) { do { jrtplib::RTPPacket *pack; while ((pack = session.GetNextPacket()) != NULL) { onIncomingPacket(pack->GetPayloadData(), pack->GetPayloadLength(), pack->HasMarker()); session.DeletePacket(pack); } } while (session.GotoNextSourceWithData()); } // session.EndDataAccess(); // useless without threading } void RTPSessionImpl::sendPacket(const SafeByteArray& data, int timestampinc, bool marker) { checkError(session.SendPacket((void*)(data.data()), data.size(), payloadType.getID(), marker, timestampinc)); poll(); } void RTPSessionImpl::injectData(const SafeByteArray& data) { packetInjecter->InjectRTPorRTCP((void*)(data.data()), data.size(), *jRTPRemotePeer); checkIncomingPackets(); poll(); } void RTPSessionImpl::stop(int maxWaitMs) { session.BYEDestroy(jrtplib::RTPTime(0, maxWaitMs * 1000), "", 0); udpSocket->close(); } size_t RTPSessionImpl::getMaxRTPPayloadSize() const { jrtplib::RTPSessionParams sessparams; return sessparams.GetMaximumPacketSize(); } void RTPSessionImpl::checkError(int rtperr) const { if (rtperr < 0) throw RTPException(jrtplib::RTPGetErrorString(rtperr)); } void RTPSessionImpl::handleDataRead(boost::shared_ptr data) { injectData(*data); } jrtplib::RTPAddress* RTPSessionImpl::nativeAddressToJRTPAddress(const HostAddressPort& hostAddressPort) { jrtplib::RTPAddress* jrtpAddress = 0; std::string ipAddress = hostAddressPort.getAddress().toString(); uint16_t port = boost::numeric_cast(hostAddressPort.getPort()); if (hostAddressPort.getAddress().getRawAddress().is_v4()) { // Split address std::vector subStrings; boost::algorithm::split(subStrings, ipAddress, boost::is_any_of(".")); // Cast sub strings array to array of byte uint8_t ipNumbers[4]; for (int i = 0; i < std::min(4, (int)subStrings.size()); ++i) ipNumbers[i] = boost::numeric_cast(boost::lexical_cast(subStrings[i])); jrtpAddress = new jrtplib::RTPIPv4Address(ipNumbers, port); } else if (hostAddressPort.getAddress().getRawAddress().is_v6()) { in6_addr addr; inet_pton(AF_INET6, ipAddress.c_str(), &addr); jrtpAddress = new jrtplib::RTPIPv6Address(addr, port); } return jrtpAddress; } }