/* * 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 namespace Swift { 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 RTPSessionImpl::nativeAddressToJRTPAddress(udpSocket->getLocalAddress()).IsSameAddress(address); } void Sender::send(const void* data, size_t len) { unsigned char *uint8Data = (unsigned char*)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)); } RTPSessionImpl::~RTPSessionImpl() { } 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[0]), data.size(), payloadType.getID(), marker, timestampinc)); poll(); } void RTPSessionImpl::injectData(const SafeByteArray& data) { packetInjecter->InjectRTPorRTCP((void*)(&data[0]), data.size(), jRTPRemotePeer); checkIncomingPackets(); poll(); } void RTPSessionImpl::stop(int maxWaitMs) { session.BYEDestroy(jrtplib::RTPTime(0, maxWaitMs * 1000), "", 0); // TODO: shutdown socket } void RTPSessionImpl::checkError(int rtperr) const { if (rtperr < 0) throw RTPException(jrtplib::RTPGetErrorString(rtperr)); } void RTPSessionImpl::handleDataRead(boost::shared_ptr data) { injectData(*data); } jrtplib::RTPIPv4Address RTPSessionImpl::nativeAddressToJRTPAddress(const HostAddressPort& hostAddressPort) { // Split address std::vector subStrings; std::string ipAddress = hostAddressPort.getAddress().toString(); 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])); return jrtplib::RTPIPv4Address(ipNumbers, boost::numeric_cast(hostAddressPort.getPort())); } }