From dce09fe24d55d67f60d7bc691e285897f1d64fc2 Mon Sep 17 00:00:00 2001
From: dknn <yoann.blein@free.fr>
Date: Thu, 16 Aug 2012 23:52:56 +0200
Subject: Add error resilience on decoder side


diff --git a/Swift/Controllers/ScreenSharing/ScreenSharingController.cpp b/Swift/Controllers/ScreenSharing/ScreenSharingController.cpp
index b932765..2e9a75d 100644
--- a/Swift/Controllers/ScreenSharing/ScreenSharingController.cpp
+++ b/Swift/Controllers/ScreenSharing/ScreenSharingController.cpp
@@ -123,7 +123,8 @@ void ScreenSharingController::handleStateChange(ScreenSharing::SCState state)
 void ScreenSharingController::handleWindowStopRequest()
 {
 	remoteScreenWindow->onStopRequest.disconnect(boost::bind(&ScreenSharingController::handleWindowStopRequest, this));
-	screenSharing->stop();
+	if (screenSharing)
+		screenSharing->stop();
 }
 
 }
diff --git a/Swift/QtUI/ScreenSharing/QtDesktopScreenGrabber.cpp b/Swift/QtUI/ScreenSharing/QtDesktopScreenGrabber.cpp
index a5eeafd..aae2ff1 100644
--- a/Swift/QtUI/ScreenSharing/QtDesktopScreenGrabber.cpp
+++ b/Swift/QtUI/ScreenSharing/QtDesktopScreenGrabber.cpp
@@ -11,20 +11,17 @@
 #include <QApplication>
 #include <QDesktopWidget>
 
+#include <QPainter>
+#include <QColor>
+
 #include <Swiften/ScreenSharing/Image.h>
 
-/*#include <QImage>
-#include <QLabel>*/
+#include <Swiften/Base/Log.h>
 
 namespace Swift {
 
 QtDesktopScreenGrabber::QtDesktopScreenGrabber()
 {
-	/*Image img = grab();
-	QImage qImg(img.data.data(), img.width, img.height, QImage::Format_RGB888);
-	QLabel *label = new QLabel;
-	label->setPixmap(QPixmap::fromImage(qImg));
-	label->show();*/
 }
 
 QtDesktopScreenGrabber::~QtDesktopScreenGrabber()
@@ -33,7 +30,35 @@ QtDesktopScreenGrabber::~QtDesktopScreenGrabber()
 
 Image QtDesktopScreenGrabber::grab() const
 {
-	QImage qImg = QPixmap::grabWindow(QApplication::desktop()->winId()).toImage().convertToFormat(QImage::Format_RGB888);
+	QImage qImg = QPixmap::grabWindow(QApplication::desktop()->winId()).toImage();//.convertToFormat(QImage::Format_RGB888);
+//	QImage qImg("/home/yb/Images/wallpaper-1681250.jpg");
+	qImg = qImg.scaled(qImg.width() * 0.7, qImg.height() * 0.7, Qt::KeepAspectRatio, Qt::SmoothTransformation);
+//	SWIFT_LOG(debug) << "Format RGB32: " << (qImg.format() == QImage::Format_RGB32) << std::endl;
+
+//	QImage qImg(1920, 1080, QImage::Format_RGB32);
+//	qImg.fill(QColor(qrand() % 255, qrand()%255, qrand()%255));
+//	QPainter p(&qImg);
+//	p.translate(qImg.width() / 2, qImg.height() / 2);
+//	p.setBrush(Qt::black);
+//	static int x = 0;
+//	static int y = 0;
+//	x = (x+50)%qImg.width();
+//	y = (y+50)%qImg.height();
+//	p.drawEllipse(x, y, 100, 100);
+
+//	for (int i = 0; i < 40; ++i) {
+//		p.setBrush(QColor(qrand() % 255, qrand()%255, qrand()%255));
+//		p.drawEllipse(qrand()%qImg.width(), qrand()%qImg.height(), qrand()%(qImg.width()/4), qrand()%(qImg.height()/4));
+//	}
+//	p.end();
+
+	qImg = qImg.convertToFormat(QImage::Format_RGB888);
+
+//	uchar* bits = qImg.bits();
+//	for (int i = 0; i < qImg.byteCount(); ++i) {
+//		bits[i] = qrand();
+//	}
+
 	return Image(qImg.width(), qImg.height(), qImg.constBits());
 }
 
diff --git a/Swiften/ScreenSharing/ScreenSharing.cpp b/Swiften/ScreenSharing/ScreenSharing.cpp
index 7fb1280..f2977a2 100644
--- a/Swiften/ScreenSharing/ScreenSharing.cpp
+++ b/Swiften/ScreenSharing/ScreenSharing.cpp
@@ -84,8 +84,9 @@ bool ScreenSharing::addBestCandidate(boost::shared_ptr<JingleRawUDPTransportPayl
 				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));
+				int port = serverSocket->bind(HostAddressPort(addr, 29999));
+				if (port != 29999)
+					port = serverSocket->bindOnAvailablePort(addr);
 				if (!port)
 					continue;
 
diff --git a/Swiften/ScreenSharing/VP8Decoder.cpp b/Swiften/ScreenSharing/VP8Decoder.cpp
index 2634cc5..90f5101 100644
--- a/Swiften/ScreenSharing/VP8Decoder.cpp
+++ b/Swiften/ScreenSharing/VP8Decoder.cpp
@@ -19,7 +19,7 @@ inline int clamp8(int v)
 
 VP8Decoder::VP8Decoder()
 	: VideoDecoder(),
-	  codecInterface(vpx_codec_vp8_dx()), codecFlags(0)
+	  codecInterface(vpx_codec_vp8_dx()), codecFlags(0), refFrame(0)
 {
 	SWIFT_LOG(debug) << "VP8 Decoder:" << vpx_codec_iface_name(codecInterface) << std::endl;
 
@@ -28,6 +28,11 @@ VP8Decoder::VP8Decoder()
 
 VP8Decoder::~VP8Decoder()
 {
+	vpx_codec_destroy(&codecContext);
+	if (refFrame) {
+		vpx_img_free(&refFrame->img);
+		delete refFrame;
+	}
 }
 
 void VP8Decoder::updateCodecConfig()
@@ -53,10 +58,34 @@ void VP8Decoder::decodeFrame(const std::vector<uint8_t>& frame, int pictureID)
 	}
 
 	vpx_codec_iter_t iter = NULL;
-	vpx_image_t* img;
-	while ((img = vpx_codec_get_frame(&codecContext, &iter))) {
-		Image rgbImg = convertYV12toRGB(img);
+	vpx_image_t* decodedImg;
+	while ((decodedImg = vpx_codec_get_frame(&codecContext, &iter))) {
+		Image rgbImg = convertYV12toRGB(decodedImg);
 		onNewImageAvailable(rgbImg);
+		// Restore ref from last save if corrupted, else save the ref
+		int corrupted = 0;
+		vpx_codec_control(&codecContext, VP8D_GET_FRAME_CORRUPTED, &corrupted);
+		if (corrupted) {
+			vpx_codec_control(&codecContext, VP8_SET_REFERENCE, refFrame);
+		} else {
+			// Re-alloc the image ref if the format has changed
+			if (refFrame && (decodedImg->d_w != refFrame->img.d_w
+							 || decodedImg->d_h != refFrame->img.d_h
+							 || decodedImg->fmt != refFrame->img.fmt)) {
+				vpx_img_free(&refFrame->img);
+				delete refFrame;
+				refFrame = 0;
+			}
+			if (!refFrame) {
+				refFrame = new vpx_ref_frame_t;
+				refFrame->frame_type = VP8_LAST_FRAME;
+				unsigned int align = 1;
+				if (decodedImg->d_w % 32 == 0)
+					align = 32;
+				vpx_img_alloc(&refFrame->img, decodedImg->fmt, decodedImg->d_w, decodedImg->d_h, align);
+			}
+			vpx_codec_control(&codecContext, VP8_COPY_REFERENCE, refFrame);
+		}
 	}
 }
 
diff --git a/Swiften/ScreenSharing/VP8Decoder.h b/Swiften/ScreenSharing/VP8Decoder.h
index 0bdc664..0ed6334 100644
--- a/Swiften/ScreenSharing/VP8Decoder.h
+++ b/Swiften/ScreenSharing/VP8Decoder.h
@@ -10,6 +10,7 @@
 
 #define VPX_CODEC_DISABLE_COMPAT 1
 #include "vpx/vpx_decoder.h"
+#include "vpx/vp8.h"
 
 namespace Swift {
 	class Image;
@@ -30,5 +31,6 @@ namespace Swift {
 			vpx_codec_iface_t* codecInterface;
 			vpx_codec_ctx_t codecContext;
 			vpx_codec_flags_t codecFlags;
+			vpx_ref_frame_t* refFrame;
 	};
 }
diff --git a/Swiften/ScreenSharing/VP8Encoder.cpp b/Swiften/ScreenSharing/VP8Encoder.cpp
index c25e153..e48d6d9 100644
--- a/Swiften/ScreenSharing/VP8Encoder.cpp
+++ b/Swiften/ScreenSharing/VP8Encoder.cpp
@@ -76,6 +76,7 @@ void VP8Encoder::encodeImage(const Image& frame)
 
 	vpx_enc_frame_flags_t localFrameFlags = frameFlags;
 	if (!rpsiReceived && frameNumber > 1) {
+		SWIFT_LOG(error) << "VP8 Encoder: RPSI not received, do not ref last frame" << std::endl;
 		localFrameFlags |= VP8_EFLAG_NO_REF_LAST; // VP8_EFLAG_FORCE_GF; // TODO: VP8_EFLAG_NO_REF_LAST;
 	}
 
-- 
cgit v0.10.2-6-g49f6