diff options
Diffstat (limited to 'Swiften/ScreenSharing/RTPSessionImpl.cpp')
-rw-r--r-- | Swiften/ScreenSharing/RTPSessionImpl.cpp | 96 |
1 files changed, 87 insertions, 9 deletions
diff --git a/Swiften/ScreenSharing/RTPSessionImpl.cpp b/Swiften/ScreenSharing/RTPSessionImpl.cpp index 922ffa2..33b9c2e 100644 --- a/Swiften/ScreenSharing/RTPSessionImpl.cpp +++ b/Swiften/ScreenSharing/RTPSessionImpl.cpp @@ -10,6 +10,7 @@ #include <Swiften/Network/BoostUDPSocket.h> #include <Swiften/Base/boost_bsignals.h> #include <Swiften/Network/UDPSocket.h> +#include <Swiften/Base/Log.h> #include <boost/algorithm/string/split.hpp> #include <boost/algorithm/string/classification.hpp> @@ -63,9 +64,9 @@ RTPSessionImpl::RTPSessionImpl(boost::shared_ptr<UDPSocket> udpSocket, const RTP // 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)); + checkError(Create(sessparams, &transparams, jrtplib::RTPTransmitter::ExternalProto)); - packetInjecter = static_cast<jrtplib::RTPExternalTransmissionInfo*>(session.GetTransmissionInfo())->GetPacketInjector(); + packetInjecter = static_cast<jrtplib::RTPExternalTransmissionInfo*>(GetTransmissionInfo())->GetPacketInjector(); udpSocket->onDataRead.connect(boost::bind(&RTPSessionImpl::handleDataRead, this, _1)); udpSocket->listen(); @@ -78,27 +79,27 @@ RTPSessionImpl::~RTPSessionImpl() void RTPSessionImpl::poll() { - checkError(session.Poll()); // Required if threading disabled + checkError(Poll()); // Required if threading disabled } void RTPSessionImpl::checkIncomingPackets() { // session.BeginDataAccess(); // useless without threading - if (session.GotoFirstSourceWithData() && session.GetCurrentSourceInfo()->GetRTPDataAddress()->IsSameAddress(jRTPRemotePeer)) { + if (GotoFirstSourceWithData() && GetCurrentSourceInfo()->GetRTPDataAddress()->IsSameAddress(jRTPRemotePeer)) { do { jrtplib::RTPPacket *pack; - while ((pack = session.GetNextPacket()) != NULL) { + while ((pack = GetNextPacket()) != NULL) { onIncomingPacket(pack->GetPayloadData(), pack->GetPayloadLength(), pack->HasMarker()); - session.DeletePacket(pack); + DeletePacket(pack); } - } while (session.GotoNextSourceWithData()); + } while (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)); + checkError(SendPacket((void*)(data.data()), data.size(), payloadType.getID(), marker, timestampinc)); poll(); } @@ -111,16 +112,69 @@ void RTPSessionImpl::injectData(const SafeByteArray& data) void RTPSessionImpl::stop(int maxWaitMs) { - session.BYEDestroy(jrtplib::RTPTime(0, maxWaitMs * 1000), "", 0); + BYEDestroy(jrtplib::RTPTime(0, maxWaitMs * 1000), "", 0); udpSocket->close(); } +void RTPSessionImpl::sendSLIFeedback(int pictureID) +{ + // Send an SLI as negative feedback. VP8: 0, total number of macroblocks, pictureID (6 bits) + int first = 0; // 13 bits + int number = 0; // 13 bits // TODO : Find the total number of macroblocks per frame + + uint32_t data = 0; + data |= first << 19; + data |= (number & 2047) << 6; + data |= (pictureID & 63); + + SendUnknownPacket(false, PSFB, PSFB_SLI, (void*)&data, sizeof(uint32_t)); +} + +void RTPSessionImpl::sendRPSIFeedback(int pictureID) +{ + // Send an RPSI as positive feedback. With VP8, it only contains the picture ID (7 bits) + int pb = 9; // trailing padding bits + int pt = payloadType.getID(); // payload type (7 bits) + + uint32_t data = 0; + data |= pb << 24; + data |= (pt & 127) << 16; + data |= (pictureID & 127) << 9; + + SendUnknownPacket(false, PSFB, PSFB_RPSI, (void*)&data, sizeof(uint32_t)); +} + size_t RTPSessionImpl::getMaxRTPPayloadSize() const { jrtplib::RTPSessionParams sessparams; return sessparams.GetMaximumPacketSize(); } +void RTPSessionImpl::OnUnknownPacketType(jrtplib::RTCPPacket* rtcpPack, const jrtplib::RTPTime& /*receivetime*/, const jrtplib::RTPAddress* senderAddress) +{ + if (!senderAddress->IsSameAddress(jRTPRemotePeer)) + return; + + uint8_t* data = rtcpPack->GetPacketData(); + size_t len = rtcpPack->GetPacketLength(); + jrtplib::RTCPCommonHeader* rtcpHdr = (jrtplib::RTCPCommonHeader*)data; + int type = rtcpHdr->packettype; + if (type != PSFB) + return; + + int subtype = rtcpHdr->count; + switch (subtype) { + case PSFB_SLI: + parseSLIFeedBack(data + 8, len - 8); + break; + case PSFB_RPSI: + parseRPSIFeedBack(data + 8, len - 8); + break; + default: + break; + } +} + void RTPSessionImpl::checkError(int rtperr) const { if (rtperr < 0) @@ -132,6 +186,30 @@ void RTPSessionImpl::handleDataRead(boost::shared_ptr<SafeByteArray> data) injectData(*data); } +void RTPSessionImpl::parseSLIFeedBack(uint8_t* data, size_t len) +{ + SWIFT_LOG(debug) << "Got SLI feedback (negative)" << std::endl; + + if (len < 4) + return; + int pictureID = data[len - 1] & 63; // pictureID correspond to the 6 last bits + onSLIFeedback(pictureID); +} + +void RTPSessionImpl::parseRPSIFeedBack(uint8_t* data, size_t len) +{ + SWIFT_LOG(debug) << "Got RPSI feedback (postive)" << std::endl; + + if (len < 4) + return; + int pb = data[0]; // First byte : trailing padding bits + uint32_t intData = *((uint32_t*)(data)); + intData >>= pb; // remove padding bits + int pictureID = (intData & 127); // pictureID correspond to the 7 last bits + onRPSIFeedback(pictureID); + +} + jrtplib::RTPAddress* RTPSessionImpl::nativeAddressToJRTPAddress(const HostAddressPort& hostAddressPort) { jrtplib::RTPAddress* jrtpAddress = 0; |