diff options
| author | dknn <yoann.blein@free.fr> | 2012-08-16 16:05:33 (GMT) | 
|---|---|---|
| committer | dknn <yoann.blein@free.fr> | 2012-09-22 09:32:38 (GMT) | 
| commit | 867a950d5b3eb1422051a57c2533509188014b1a (patch) | |
| tree | 01c9d7372c7e780aaa90456df2bac55082632dae | |
| parent | 054bf7baf02cf088930c340fead40b464c1ed015 (diff) | |
| download | swift-contrib-867a950d5b3eb1422051a57c2533509188014b1a.zip swift-contrib-867a950d5b3eb1422051a57c2533509188014b1a.tar.bz2 | |
Add error resilence (buggy)
| -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;  	};  } | 
 Swift
 Swift