summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften')
-rw-r--r--Swiften/Network/BoostUDPSocket.cpp4
-rw-r--r--Swiften/ScreenSharing/IncomingScreenSharing.cpp14
-rw-r--r--Swiften/ScreenSharing/IncomingScreenSharing.h3
-rw-r--r--Swiften/ScreenSharing/OutgoingScreenSharing.cpp1
-rw-r--r--Swiften/ScreenSharing/RTPSession.h5
-rw-r--r--Swiften/ScreenSharing/RTPSessionImpl.cpp96
-rw-r--r--Swiften/ScreenSharing/RTPSessionImpl.h24
-rw-r--r--Swiften/ScreenSharing/ScreenSharing.cpp32
-rw-r--r--Swiften/ScreenSharing/VP8Decoder.cpp8
-rw-r--r--Swiften/ScreenSharing/VP8Decoder.h2
-rw-r--r--Swiften/ScreenSharing/VP8Encoder.cpp22
-rw-r--r--Swiften/ScreenSharing/VP8Encoder.h4
-rw-r--r--Swiften/ScreenSharing/VP8RTPPacketizer.cpp8
-rw-r--r--Swiften/ScreenSharing/VP8RTPPacketizer.h4
-rw-r--r--Swiften/ScreenSharing/VP8RTPParser.cpp24
-rw-r--r--Swiften/ScreenSharing/VP8RTPParser.h3
-rw-r--r--Swiften/ScreenSharing/VideoDecoder.h5
-rw-r--r--Swiften/ScreenSharing/VideoEncoder.h2
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;
};
}