diff options
-rw-r--r-- | Swiften/Network/BoostUDPSocket.cpp | 4 | ||||
-rw-r--r-- | Swiften/ScreenSharing/IncomingScreenSharing.cpp | 14 | ||||
-rw-r--r-- | Swiften/ScreenSharing/IncomingScreenSharing.h | 3 | ||||
-rw-r--r-- | Swiften/ScreenSharing/OutgoingScreenSharing.cpp | 1 | ||||
-rw-r--r-- | Swiften/ScreenSharing/RTPSession.h | 5 | ||||
-rw-r--r-- | Swiften/ScreenSharing/RTPSessionImpl.cpp | 96 | ||||
-rw-r--r-- | Swiften/ScreenSharing/RTPSessionImpl.h | 24 | ||||
-rw-r--r-- | Swiften/ScreenSharing/ScreenSharing.cpp | 32 | ||||
-rw-r--r-- | Swiften/ScreenSharing/VP8Decoder.cpp | 8 | ||||
-rw-r--r-- | Swiften/ScreenSharing/VP8Decoder.h | 2 | ||||
-rw-r--r-- | Swiften/ScreenSharing/VP8Encoder.cpp | 22 | ||||
-rw-r--r-- | Swiften/ScreenSharing/VP8Encoder.h | 4 | ||||
-rw-r--r-- | Swiften/ScreenSharing/VP8RTPPacketizer.cpp | 8 | ||||
-rw-r--r-- | Swiften/ScreenSharing/VP8RTPPacketizer.h | 4 | ||||
-rw-r--r-- | Swiften/ScreenSharing/VP8RTPParser.cpp | 24 | ||||
-rw-r--r-- | Swiften/ScreenSharing/VP8RTPParser.h | 3 | ||||
-rw-r--r-- | Swiften/ScreenSharing/VideoDecoder.h | 5 | ||||
-rw-r--r-- | Swiften/ScreenSharing/VideoEncoder.h | 2 |
18 files changed, 219 insertions, 42 deletions
diff --git a/Swiften/Network/BoostUDPSocket.cpp b/Swiften/Network/BoostUDPSocket.cpp index 0f66b92..cd86990 100644 --- a/Swiften/Network/BoostUDPSocket.cpp +++ b/Swiften/Network/BoostUDPSocket.cpp @@ -137,7 +137,7 @@ void BoostUDPSocket::doRead() void BoostUDPSocket::handleSocketRead(const boost::system::error_code& error, size_t bytesTransferred) { - SWIFT_LOG(debug) << "Socket read " << error << std::endl; +// SWIFT_LOG(debug) << "Socket read " << error << std::endl; if (!error) { readBuffer_->resize(bytesTransferred); eventLoop->postEvent(boost::bind(boost::ref(onDataRead), readBuffer_), shared_from_this()); @@ -161,7 +161,7 @@ void BoostUDPSocket::handleFirstRead(const boost::system::error_code &error, std void BoostUDPSocket::handleDataWritten(const boost::system::error_code& error) { - SWIFT_LOG(debug) << "Data written " << error << std::endl; +// SWIFT_LOG(debug) << "Data written " << error << std::endl; // if (!error) { // eventLoop->postEvent(boost::ref(onDataWritten), shared_from_this()); diff --git a/Swiften/ScreenSharing/IncomingScreenSharing.cpp b/Swiften/ScreenSharing/IncomingScreenSharing.cpp index fbd4b16..43e3fbc 100644 --- a/Swiften/ScreenSharing/IncomingScreenSharing.cpp +++ b/Swiften/ScreenSharing/IncomingScreenSharing.cpp @@ -82,7 +82,8 @@ void IncomingScreenSharing::accept() decoder = new VP8Decoder; parser = new VP8RTPParser(decoder); rtpSession->onIncomingPacket.connect(boost::bind(&VP8RTPParser::newPayloadReceived, parser, _1, _2, _3)); - decoder->onNewImageDecoded.connect(boost::bind(&IncomingScreenSharing::handleNewImageDecoded, this, _1)); + decoder->onNewFrameDecoded.connect(boost::bind(&IncomingScreenSharing::handleNewFrameDecoded, this, _1, _2)); + decoder->onNewImageAvailable.connect(boost::bind(&IncomingScreenSharing::handleNewImageAvailable, this, _1)); } onStateChange(ScreenSharing::Connecting); @@ -115,7 +116,16 @@ JingleContentID IncomingScreenSharing::getContentID() const return JingleContentID(initialContent->getName(), initialContent->getCreator()); } -void IncomingScreenSharing::handleNewImageDecoded(const Image& image) +void IncomingScreenSharing::handleNewFrameDecoded(int pictureID, bool success) +{ + if (success) { + rtpSession->sendRPSIFeedback(pictureID); + } else { + rtpSession->sendSLIFeedback(pictureID); + } +} + +void IncomingScreenSharing::handleNewImageAvailable(const Image& image) { onStateChange(ScreenSharing::Receiving); onNewImageReceived(image); diff --git a/Swiften/ScreenSharing/IncomingScreenSharing.h b/Swiften/ScreenSharing/IncomingScreenSharing.h index c46a6f8..d5dd817 100644 --- a/Swiften/ScreenSharing/IncomingScreenSharing.h +++ b/Swiften/ScreenSharing/IncomingScreenSharing.h @@ -44,7 +44,8 @@ namespace Swift { private: JingleContentID getContentID() const; - void handleNewImageDecoded(const Image& image); + void handleNewFrameDecoded(int pictureID, bool success); + void handleNewImageAvailable(const Image& image); void handleEventSendingTimerTick(); void addLastMouseMoveIfDifferent(); diff --git a/Swiften/ScreenSharing/OutgoingScreenSharing.cpp b/Swiften/ScreenSharing/OutgoingScreenSharing.cpp index 363b23c..6700a32 100644 --- a/Swiften/ScreenSharing/OutgoingScreenSharing.cpp +++ b/Swiften/ScreenSharing/OutgoingScreenSharing.cpp @@ -136,6 +136,7 @@ void OutgoingScreenSharing::startRTPSession() packetizer = new VP8RTPPacketizer; encoder = new VP8Encoder(packetizer, width, height); packetizer->onNewPayloadReady.connect(boost::bind(&OutgoingScreenSharing::handleNewPayloadReady, this, _1, _2)); + rtpSession->onRPSIFeedback.connect(boost::bind(&VP8Encoder::handleRPSIFeedback, static_cast<VP8Encoder*>(encoder), _1)); onReady(); onStateChange(ScreenSharing::BroadCasting); } diff --git a/Swiften/ScreenSharing/RTPSession.h b/Swiften/ScreenSharing/RTPSession.h index e4aa9c1..c9c6ae8 100644 --- a/Swiften/ScreenSharing/RTPSession.h +++ b/Swiften/ScreenSharing/RTPSession.h @@ -29,9 +29,14 @@ namespace Swift { virtual void injectData(const SafeByteArray& data) = 0; virtual void stop(int maxWaitMs = 100) = 0; + virtual void sendSLIFeedback(int pictureID) = 0; + virtual void sendRPSIFeedback(int pictureID) = 0; + virtual size_t getMaxRTPPayloadSize() const = 0; public: boost::signal<void (uint8_t* data, size_t len, bool marker)> onIncomingPacket; + boost::signal<void (int sixLeastBitsPictureID)> onSLIFeedback; + boost::signal<void (int pictureID)> onRPSIFeedback; }; } 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; diff --git a/Swiften/ScreenSharing/RTPSessionImpl.h b/Swiften/ScreenSharing/RTPSessionImpl.h index 47af60b..2736605 100644 --- a/Swiften/ScreenSharing/RTPSessionImpl.h +++ b/Swiften/ScreenSharing/RTPSessionImpl.h @@ -34,10 +34,7 @@ namespace Swift { jrtplib::RTPAddress* jRTPLocalAddress; }; - class RTPSessionImpl : public RTPSession { - public: - typedef boost::shared_ptr<RTPSession> ref; - + class RTPSessionImpl : public RTPSession, jrtplib::RTPSession { public: RTPSessionImpl(boost::shared_ptr<UDPSocket> udpSocket, const RTPPayloadType& payloadType); virtual ~RTPSessionImpl(); @@ -48,21 +45,38 @@ namespace Swift { virtual void injectData(const SafeByteArray &data); virtual void stop(int maxWaitMs = 100); + virtual void sendSLIFeedback(int pictureID); + virtual void sendRPSIFeedback(int pictureID); + virtual size_t getMaxRTPPayloadSize() const; public: static jrtplib::RTPAddress* nativeAddressToJRTPAddress(const HostAddressPort& hostAddressPort); + protected: + void OnUnknownPacketType(jrtplib::RTCPPacket* rtcpPack, const jrtplib::RTPTime& /*receivetime*/, const jrtplib::RTPAddress* senderAddress); + + private: + enum PacketType { + PSFB = 206, + }; + + enum SubPacketType { + PSFB_SLI = 2, + PSFB_RPSI = 3, + }; + private: void checkError(int rtperr) const; void handleDataRead(boost::shared_ptr<SafeByteArray> data); + void parseSLIFeedBack(uint8_t* data, size_t len); + void parseRPSIFeedBack(uint8_t* data, size_t len); private: boost::shared_ptr<UDPSocket> udpSocket; RTPPayloadType payloadType; jrtplib::RTPAddress* jRTPRemotePeer; Sender sender; - jrtplib::RTPSession session; jrtplib::RTPExternalPacketInjecter *packetInjecter; }; } diff --git a/Swiften/ScreenSharing/ScreenSharing.cpp b/Swiften/ScreenSharing/ScreenSharing.cpp index f1b7ebf..7fb1280 100644 --- a/Swiften/ScreenSharing/ScreenSharing.cpp +++ b/Swiften/ScreenSharing/ScreenSharing.cpp @@ -65,11 +65,27 @@ bool ScreenSharing::addBestCandidate(boost::shared_ptr<JingleRawUDPTransportPayl } }*/ + SWIFT_LOG(debug) << "Screen sharing: Addresses available: " << std::endl; + foreach (const NetworkInterface& interface, interfaces) { + SWIFT_LOG(debug) << "\tInterface: " << interface.getName() << std::endl; + foreach (const HostAddress& addr, interface.getAddresses()) { + SWIFT_LOG(debug) << "\t\t" << addr.getRawAddress().to_string() << std::endl; + } + } + + std::string scopeLinkBeginning("fe80"); foreach (const NetworkInterface& interface, interfaces) { if (!interface.isLoopback()) { // exclude loopback foreach (const HostAddress& addr, interface.getAddresses()) { -// int port = serverSocket->bindOnAvailablePort(addr); - int port = serverSocket->bind(HostAddressPort(addr, 29999)); + // Disable ipv6 for now + if (addr.getRawAddress().is_v6()) + continue; + // Ignore link scope ipv6 addr + if (addr.getRawAddress().is_v6() && addr.toString().compare(2, scopeLinkBeginning.length(), scopeLinkBeginning) == 0) + continue; + + int port = serverSocket->bindOnAvailablePort(addr); +// int port = serverSocket->bind(HostAddressPort(addr, 29999)); if (!port) continue; @@ -82,6 +98,18 @@ bool ScreenSharing::addBestCandidate(boost::shared_ptr<JingleRawUDPTransportPayl } } + /* + int port = serverSocket->bind(HostAddressPort(HostAddress("0.0.0.0"), 29999)); + if (!port) + return false; + + candidate.hostAddressPort = HostAddressPort(HostAddress("82.225.14.174"), 29999); + candidate.type = JingleRawUDPTransportPayload::Candidate::Host; + transport->addCandidate(candidate); + + return true; +*/ + // else loopback for self sharing /*if (!interfaces.empty() && !interfaces.front().getAddresses().empty()) { int port = serverSocket->bindOnAvailablePort(interfaces.front().getAddresses().front()); diff --git a/Swiften/ScreenSharing/VP8Decoder.cpp b/Swiften/ScreenSharing/VP8Decoder.cpp index 40f631f..2634cc5 100644 --- a/Swiften/ScreenSharing/VP8Decoder.cpp +++ b/Swiften/ScreenSharing/VP8Decoder.cpp @@ -40,21 +40,23 @@ void VP8Decoder::updateCodecConfig() } } -void VP8Decoder::decodeFrame(const std::vector<uint8_t>& frame) +void VP8Decoder::decodeFrame(const std::vector<uint8_t>& frame, int pictureID) { // Decode the frame vpx_codec_err_t err = vpx_codec_decode(&codecContext, &frame[0], frame.size(), NULL, 0); if (err) { SWIFT_LOG(debug) << "VP8 Decoder: Failed to decode frame, " << vpx_codec_err_to_string(err) << std::endl; - // TODO: exception ? + onNewFrameDecoded(pictureID, false); return; + } else { + onNewFrameDecoded(pictureID, true); } vpx_codec_iter_t iter = NULL; vpx_image_t* img; while ((img = vpx_codec_get_frame(&codecContext, &iter))) { Image rgbImg = convertYV12toRGB(img); - onNewImageDecoded(rgbImg); + onNewImageAvailable(rgbImg); } } diff --git a/Swiften/ScreenSharing/VP8Decoder.h b/Swiften/ScreenSharing/VP8Decoder.h index 8b2575a..0bdc664 100644 --- a/Swiften/ScreenSharing/VP8Decoder.h +++ b/Swiften/ScreenSharing/VP8Decoder.h @@ -21,7 +21,7 @@ namespace Swift { void updateCodecConfig(); - virtual void decodeFrame(const std::vector<uint8_t>& frame); + virtual void decodeFrame(const std::vector<uint8_t> &frame, int pictureID); private: Image convertYV12toRGB(const vpx_image_t* img); diff --git a/Swiften/ScreenSharing/VP8Encoder.cpp b/Swiften/ScreenSharing/VP8Encoder.cpp index 7a88418..c25e153 100644 --- a/Swiften/ScreenSharing/VP8Encoder.cpp +++ b/Swiften/ScreenSharing/VP8Encoder.cpp @@ -14,7 +14,7 @@ namespace Swift { VP8Encoder::VP8Encoder(VP8RTPPacketizer* packetizer, unsigned int width, unsigned int height) : VideoEncoder(), - packetizer(packetizer), codecInterface(vpx_codec_vp8_cx()), imageBuffer(0), codecFlags(0), frameFlags(0), frameNumber(0) + packetizer(packetizer), codecInterface(vpx_codec_vp8_cx()), imageBuffer(0), codecFlags(0), frameFlags(0), frameNumber(0), pictureID(0), rpsiReceived(true) { SWIFT_LOG(debug) << "VP8 Encoder:" << vpx_codec_iface_name(codecInterface) << std::endl; @@ -60,6 +60,10 @@ void VP8Encoder::updateCodecConfig() SWIFT_LOG(error) << "VP8 Encoder: Failed to allocate image" << std::endl; // TODO: exception } + + frameNumber = 0; + pictureID = rand() % 128; + rpsiReceived = true; } void VP8Encoder::encodeImage(const Image& frame) @@ -70,7 +74,12 @@ void VP8Encoder::encodeImage(const Image& frame) return; } - vpx_codec_err_t err = vpx_codec_encode(&codecContext, imageBuffer, frameNumber, 1, frameFlags, VPX_DL_REALTIME); + vpx_enc_frame_flags_t localFrameFlags = frameFlags; + if (!rpsiReceived && frameNumber > 1) { + localFrameFlags |= VP8_EFLAG_NO_REF_LAST; // VP8_EFLAG_FORCE_GF; // TODO: VP8_EFLAG_NO_REF_LAST; + } + + vpx_codec_err_t err = vpx_codec_encode(&codecContext, imageBuffer, frameNumber, 1, localFrameFlags, VPX_DL_REALTIME); if (err) { SWIFT_LOG(error) << "VP8 Encoder: Failed to encode frame, " << vpx_codec_err_to_string(err) << std::endl; // TODO: exception ? @@ -82,7 +91,7 @@ void VP8Encoder::encodeImage(const Image& frame) while ((pkt = vpx_codec_get_cx_data(&codecContext, &iter))) { switch (pkt->kind) { case VPX_CODEC_CX_FRAME_PKT: - packetizer->packetizeFrame(pkt); + packetizer->packetizeFrame(pkt, pictureID); break; default: break; @@ -90,6 +99,13 @@ void VP8Encoder::encodeImage(const Image& frame) } ++frameNumber; + pictureID = (pictureID + 1) % 128; + rpsiReceived = false; +} + +void VP8Encoder::handleRPSIFeedback(int /*pictureID*/) +{ + rpsiReceived = true; } bool VP8Encoder::convertRGB24toYV12inBuffer(const Image& frame) diff --git a/Swiften/ScreenSharing/VP8Encoder.h b/Swiften/ScreenSharing/VP8Encoder.h index 0a343bb..62a6ea8 100644 --- a/Swiften/ScreenSharing/VP8Encoder.h +++ b/Swiften/ScreenSharing/VP8Encoder.h @@ -25,6 +25,8 @@ namespace Swift { virtual void encodeImage(const Image& frame); + virtual void handleRPSIFeedback(int /*pictureID*/); + private: bool convertRGB24toYV12inBuffer(const Image& frame); @@ -37,6 +39,8 @@ namespace Swift { vpx_codec_flags_t codecFlags; vpx_enc_frame_flags_t frameFlags; int frameNumber; + int pictureID; + bool rpsiReceived; }; } diff --git a/Swiften/ScreenSharing/VP8RTPPacketizer.cpp b/Swiften/ScreenSharing/VP8RTPPacketizer.cpp index b88e2171..454f35f 100644 --- a/Swiften/ScreenSharing/VP8RTPPacketizer.cpp +++ b/Swiften/ScreenSharing/VP8RTPPacketizer.cpp @@ -12,7 +12,7 @@ VP8RTPPacketizer::VP8RTPPacketizer() { } -void VP8RTPPacketizer::packetizeFrame(const vpx_codec_cx_pkt_t* pkt) +void VP8RTPPacketizer::packetizeFrame(const vpx_codec_cx_pkt_t* pkt, int pictureID) { if (pkt->kind != VPX_CODEC_CX_FRAME_PKT) return; @@ -30,10 +30,14 @@ void VP8RTPPacketizer::packetizeFrame(const vpx_codec_cx_pkt_t* pkt) payloadBuffer.clear(); // Payload descriptor - uint8_t req = 0; + uint8_t req = XBit; if (firstPacket) req |= SBit; + uint8_t optX = IBit; + uint8_t optI = (pictureID & 127); // pictureID payloadBuffer.push_back(req); + payloadBuffer.push_back(optX); + payloadBuffer.push_back(optI); // Payload header if (firstPacket) { diff --git a/Swiften/ScreenSharing/VP8RTPPacketizer.h b/Swiften/ScreenSharing/VP8RTPPacketizer.h index c56e754..f7858da 100644 --- a/Swiften/ScreenSharing/VP8RTPPacketizer.h +++ b/Swiften/ScreenSharing/VP8RTPPacketizer.h @@ -20,12 +20,14 @@ namespace Swift { public: VP8RTPPacketizer(); - void packetizeFrame(const vpx_codec_cx_pkt_t* pkt); + void packetizeFrame(const vpx_codec_cx_pkt_t* pkt, int pictureID); boost::signal<void (const std::vector<uint8_t>&, bool marker)> onNewPayloadReady; private: static const uint8_t SBit = 1 << 4; + static const uint8_t XBit = 1 << 7; + static const uint8_t IBit = 1 << 7; static const uint8_t HBit = 1 << 4; static const uint8_t Size0BitMask = 7; static const uint8_t Size0BitShift = 5; diff --git a/Swiften/ScreenSharing/VP8RTPParser.cpp b/Swiften/ScreenSharing/VP8RTPParser.cpp index 053a50a..d44140b 100644 --- a/Swiften/ScreenSharing/VP8RTPParser.cpp +++ b/Swiften/ScreenSharing/VP8RTPParser.cpp @@ -11,37 +11,43 @@ namespace Swift { VP8RTPParser::VP8RTPParser(VideoDecoder* decoder) - : decoder(decoder), firstPacket(true) + : decoder(decoder), firstPacket(true), pictureID(0) { } void VP8RTPParser::newPayloadReceived(const uint8_t* data, size_t len, bool hasMarker) { + size_t headerSize = 1; + // Payload descriptor uint8_t req = data[0]; if (firstPacket && !(req & SBit)) { /* Error */ } - size_t headerSize; + if (req & XBit) { // Extension byte is present + uint8_t optX = data[headerSize++]; + if (optX & IBit) { // PictureID byte is present + uint8_t optI = data[headerSize++]; + pictureID = optI >> 1; + } + } + // Payload header if (firstPacket) { firstPacket = false; - - uint8_t o1 = data[1]; + uint8_t o1 = data[headerSize]; showFrame = (o1 & 1); isKeyFrame = (o1 & HBit); o1 >>= Size0BitShift; - frameSize = o1 + 8 * data[2] + 2048 * data[3]; + frameSize = o1 + 8 * data[headerSize + 1] + 2048 * data[headerSize + 2]; - headerSize = 4; - } else { - headerSize = 1; + headerSize += 3; } buffer.insert(buffer.end(), data + headerSize, data + len); if (hasMarker || buffer.size() >= frameSize) { // Frame received - decoder->decodeFrame(buffer); + decoder->decodeFrame(buffer, pictureID); buffer.clear(); firstPacket = true; } diff --git a/Swiften/ScreenSharing/VP8RTPParser.h b/Swiften/ScreenSharing/VP8RTPParser.h index 1594c66..7f6a393 100644 --- a/Swiften/ScreenSharing/VP8RTPParser.h +++ b/Swiften/ScreenSharing/VP8RTPParser.h @@ -21,6 +21,8 @@ namespace Swift { private: static const uint8_t SBit = 1 << 4; + static const uint8_t XBit = 1 << 7; + static const uint8_t IBit = 1 << 7; static const uint8_t HBit = 1 << 4; static const uint8_t Size0BitShift = 5; @@ -31,5 +33,6 @@ namespace Swift { size_t frameSize; bool isKeyFrame; bool showFrame; + int pictureID; }; } diff --git a/Swiften/ScreenSharing/VideoDecoder.h b/Swiften/ScreenSharing/VideoDecoder.h index 810d5ae..fdec6b3 100644 --- a/Swiften/ScreenSharing/VideoDecoder.h +++ b/Swiften/ScreenSharing/VideoDecoder.h @@ -18,9 +18,10 @@ namespace Swift { VideoDecoder() {} virtual ~VideoDecoder() {} - virtual void decodeFrame(const std::vector<uint8_t>& frame) = 0; + virtual void decodeFrame(const std::vector<uint8_t>& frame, int pictureID) = 0; public: - boost::signal<void (const Image&)> onNewImageDecoded; + boost::signal<void (int pictureID, bool success)> onNewFrameDecoded; + boost::signal<void (const Image&)> onNewImageAvailable; }; } diff --git a/Swiften/ScreenSharing/VideoEncoder.h b/Swiften/ScreenSharing/VideoEncoder.h index 718b59f..c28b6d1 100644 --- a/Swiften/ScreenSharing/VideoEncoder.h +++ b/Swiften/ScreenSharing/VideoEncoder.h @@ -19,5 +19,7 @@ namespace Swift { virtual ~VideoEncoder() {} virtual void encodeImage(const Image& frame) = 0; + + virtual void handleRPSIFeedback(int /*pictureID*/) = 0; }; } |