diff --git a/bigbluebutton-client/resources/prod/bbb-deskshare-applet-0.64.jar b/bigbluebutton-client/resources/prod/bbb-deskshare-applet-0.64.jar
index fdfa631e5da1df69911160572c9f20bbad08a290..62ecac0ba2d754f5b9c8abfacdeefc7da22930a0 100755
Binary files a/bigbluebutton-client/resources/prod/bbb-deskshare-applet-0.64.jar and b/bigbluebutton-client/resources/prod/bbb-deskshare-applet-0.64.jar differ
diff --git a/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/events/CaptureEndBlockEvent.java b/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/events/CaptureEndBlockEvent.java
index 7e8c425e88f82ae61eedf06dc5e864cf62bda4b3..b30927b7f3fb6e587ad2acea9b1f397782df977d 100755
--- a/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/events/CaptureEndBlockEvent.java
+++ b/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/events/CaptureEndBlockEvent.java
@@ -22,12 +22,18 @@ package org.bigbluebutton.deskshare.server.events;
 public class CaptureEndBlockEvent {
 
 	private final String room;
+	private final int sequenceNum;
 	
-	public CaptureEndBlockEvent(String room) {
+	public CaptureEndBlockEvent(String room, int sequenceNum) {
 		this.room = room;
+		this.sequenceNum = sequenceNum;
 	}
 		
 	public String getRoom() {
 		return room;
 	}
+	
+	public int getSequenceNum() {
+		return sequenceNum;
+	}
 }
diff --git a/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/events/CaptureStartBlockEvent.java b/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/events/CaptureStartBlockEvent.java
index 3cd629dc7d4e8c0efbd4667094d9ac499ff6a543..197ebcab0b426f710ca6b01ba68b42f89bc99a5c 100755
--- a/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/events/CaptureStartBlockEvent.java
+++ b/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/events/CaptureStartBlockEvent.java
@@ -26,11 +26,13 @@ public class CaptureStartBlockEvent {
 	private final String room;
 	private final Dimension screenDim;
 	private final Dimension blockDim;
+	private final int sequenceNum;
 	
-	public CaptureStartBlockEvent(String room, Dimension screen, Dimension block) {
+	public CaptureStartBlockEvent(String room, Dimension screen, Dimension block, int sequenceNum) {
 		this.room = room;
 		screenDim = screen;
 		blockDim = block;
+		this.sequenceNum = sequenceNum;
 	}
 	
 	public Dimension getScreenDimension() {
@@ -44,4 +46,8 @@ public class CaptureStartBlockEvent {
 	public String getRoom() {
 		return room;
 	}
+	
+	public int getSequenceNum() {
+		return sequenceNum;
+	}
 }
diff --git a/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/events/CaptureUpdateBlockEvent.java b/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/events/CaptureUpdateBlockEvent.java
index 9dc15a0122d8383c6dc935f42c312963bc87b35d..afbce9461b256ef6d596ea53d4a199da0eb983b0 100755
--- a/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/events/CaptureUpdateBlockEvent.java
+++ b/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/events/CaptureUpdateBlockEvent.java
@@ -19,19 +19,19 @@
  */
 package org.bigbluebutton.deskshare.server.events;
 
-import java.awt.Point;
-
 public class CaptureUpdateBlockEvent {
 	private final String room;
 	private final int position;
 	private final byte[] videoData;
 	private final boolean isKeyFrame;
-
-	public CaptureUpdateBlockEvent(String room, int position, byte[] videoData, boolean isKeyFrame) {
+	private final int sequenceNum;
+	
+	public CaptureUpdateBlockEvent(String room, int position, byte[] videoData, boolean isKeyFrame, int sequenceNum) {
 		this.room = room;
 		this.position = position;
 		this.videoData = videoData;
 		this.isKeyFrame = isKeyFrame;
+		this.sequenceNum = sequenceNum;
 	}
 		
 	public String getRoom() {
@@ -49,4 +49,8 @@ public class CaptureUpdateBlockEvent {
 	public boolean isKeyFrame() {
 		return isKeyFrame;
 	}
+	
+	public int getSequenceNum() {
+		return sequenceNum;
+	}
 }
diff --git a/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/events/MouseLocationEvent.java b/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/events/MouseLocationEvent.java
index bfa7edd7fe0e7d93212d4b072b16f6c9df819eac..f8ce28c3af7f2e8ecba7fe1539f20a85b848ca4a 100755
--- a/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/events/MouseLocationEvent.java
+++ b/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/events/MouseLocationEvent.java
@@ -25,10 +25,12 @@ public class MouseLocationEvent {
 
 	private String room;
 	private Point loc;
+	private final int sequenceNum;
 	
-	public MouseLocationEvent(String room, Point loc) {
+	public MouseLocationEvent(String room, Point loc, int sequenceNum) {
 		this.room = room;
 		this.loc = loc;
+		this.sequenceNum = sequenceNum;
 	}
 	
 	public String getRoom() {
@@ -38,4 +40,8 @@ public class MouseLocationEvent {
 	public Point getLoc() {
 		return loc;
 	}
+	
+	public int getSequenceNum() {
+		return sequenceNum;
+	}
 }
diff --git a/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/servlet/HttpTunnelStreamController.java b/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/servlet/HttpTunnelStreamController.java
index 50c2205c83c5a927d784efba9362e85cbc281909..83181403d4bbd6419ce394ce60df0ee084fe1509 100755
--- a/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/servlet/HttpTunnelStreamController.java
+++ b/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/servlet/HttpTunnelStreamController.java
@@ -60,19 +60,20 @@ public class HttpTunnelStreamController extends MultiActionController {
 	private void handleUpdateMouseLocationRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {		
 		String room = request.getParameterValues("room")[0];
 		String mouseX = request.getParameterValues("mousex")[0];
-		String mouseY = request.getParameterValues("mousey")[0];
-		
+		String mouseY = request.getParameterValues("mousey")[0];		
+		String seqNum = request.getParameterValues("sequenceNumber")[0];
 		Point loc = new Point(Integer.parseInt(mouseX), Integer.parseInt(mouseY));
 
 		if (! hasSessionManager) {
 			sessionManager = getSessionManager();
 			hasSessionManager = true;
 		}
-		sessionManager.updateMouseLocation(room, loc);		
+		sessionManager.updateMouseLocation(room, loc, Integer.parseInt(seqNum));		
 	}
 	
 	private void handleCaptureStartRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {		
 		String room = request.getParameterValues("room")[0];
+		String seqNum = request.getParameterValues("sequenceNumber")[0];
 		String screenInfo = request.getParameterValues("screenInfo")[0];
 		String blockInfo = request.getParameterValues("blockInfo")[0];
 		
@@ -87,7 +88,7 @@ public class HttpTunnelStreamController extends MultiActionController {
 			sessionManager = getSessionManager();
 			hasSessionManager = true;
 		}
-		sessionManager.createSession(room, screenDim, blockDim);		
+		sessionManager.createSession(room, screenDim, blockDim, Integer.parseInt(seqNum));		
 	}	
 	
 	private void handleCaptureUpdateRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
@@ -99,6 +100,7 @@ public class HttpTunnelStreamController extends MultiActionController {
 		
 		byte[] blockData = multipartFile.getBytes();
 		String room = request.getParameterValues("room")[0];
+		String seqNum = request.getParameterValues("sequenceNumber")[0];
 		String keyframe = request.getParameterValues("keyframe")[0];
 		String position = request.getParameterValues("position")[0];
 				
@@ -107,17 +109,18 @@ public class HttpTunnelStreamController extends MultiActionController {
 			hasSessionManager = true;
 		}
 			
-		sessionManager.updateBlock(room, Integer.valueOf(position), blockData, Boolean.parseBoolean(keyframe));
+		sessionManager.updateBlock(room, Integer.valueOf(position), blockData, Boolean.parseBoolean(keyframe), Integer.parseInt(seqNum));
 	}
 	
 	private void handleCaptureEndRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {	
 		String room = request.getParameterValues("room")[0];
+		String seqNum = request.getParameterValues("sequenceNumber")[0];
 		if (! hasSessionManager) {
 			sessionManager = getSessionManager();
 			hasSessionManager = true;
 		}
 		System.out.println("HttpTunnel: Received Capture Enfd Event.");
-    	sessionManager.removeSession(room);
+    	sessionManager.removeSession(room, Integer.parseInt(seqNum));
 	}
 	    
 	private ISessionManagerGateway getSessionManager() {
diff --git a/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/session/ISessionManagerGateway.java b/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/session/ISessionManagerGateway.java
index 4a95a0d2951a39b525295c8b49438d891a9318ae..7303a4915e00b0b3c35c80d1eecf060505ea8cf9 100755
--- a/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/session/ISessionManagerGateway.java
+++ b/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/session/ISessionManagerGateway.java
@@ -29,11 +29,11 @@ import org.bigbluebutton.deskshare.common.Dimension;
  *
  */
 public interface ISessionManagerGateway {
-	public void createSession(String room, Dimension screenDim, Dimension blockDim);
+	public void createSession(String room, Dimension screenDim, Dimension blockDim, int seqNum);
 
-	public void removeSession(String room);
+	public void removeSession(String room, int seqNum);
 
-	public void updateBlock(String room, int position, byte[] blockData, boolean keyframe);
+	public void updateBlock(String room, int position, byte[] blockData, boolean keyframe, int seqNum);
 	
-	public void updateMouseLocation(String room, Point loc);
+	public void updateMouseLocation(String room, Point loc, int seqNum);
 }
diff --git a/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/socket/BlockStreamEventMessageHandler.java b/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/socket/BlockStreamEventMessageHandler.java
index 0b2901e1d92bd96718d4d7b9167d7e2cee26c163..13dc0026e987f55c2f7013e59868a38de2cf47be 100755
--- a/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/socket/BlockStreamEventMessageHandler.java
+++ b/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/socket/BlockStreamEventMessageHandler.java
@@ -48,17 +48,17 @@ public class BlockStreamEventMessageHandler extends IoHandlerAdapter {
     	if (message instanceof CaptureStartBlockEvent) {
     		System.out.println("Got CaptureStartBlockEvent");
     		CaptureStartBlockEvent event = (CaptureStartBlockEvent) message;
-    		sessionManager.createSession(event.getRoom(), event.getScreenDimension(), event.getBlockDimension());
+    		sessionManager.createSession(event.getRoom(), event.getScreenDimension(), event.getBlockDimension(), event.getSequenceNum());
     	} else if (message instanceof CaptureUpdateBlockEvent) {
 //    		System.out.println("Got CaptureUpdateBlockEvent");
     		CaptureUpdateBlockEvent event = (CaptureUpdateBlockEvent) message;
-    		sessionManager.updateBlock(event.getRoom(), event.getPosition(), event.getVideoData(), event.isKeyFrame());
+    		sessionManager.updateBlock(event.getRoom(), event.getPosition(), event.getVideoData(), event.isKeyFrame(), event.getSequenceNum());
     	} else if (message instanceof CaptureEndBlockEvent) {
     		CaptureEndBlockEvent event = (CaptureEndBlockEvent) message;
-    		sessionManager.removeSession(event.getRoom());
+    		sessionManager.removeSession(event.getRoom(), event.getSequenceNum());
     	} else if (message instanceof MouseLocationEvent) {
     		MouseLocationEvent event = (MouseLocationEvent) message;
-    		sessionManager.updateMouseLocation(event.getRoom(), event.getLoc());
+    		sessionManager.updateMouseLocation(event.getRoom(), event.getLoc(), event.getSequenceNum());
     	}
     }
 
@@ -88,7 +88,7 @@ public class BlockStreamEventMessageHandler extends IoHandlerAdapter {
     	String room = (String) session.getAttribute("ROOM");
     	if (room != null) {
     		log.debug("Session Closed for room " + room);
-    		sessionManager.removeSession(room);
+    		sessionManager.removeSession(room, 0);
     	} else {
     		log.warn("Closing session for a NULL room");
     	}
diff --git a/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/socket/BlockStreamProtocolDecoder.java b/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/socket/BlockStreamProtocolDecoder.java
index affdd1aab3c8e027d3ae1a2bd6e192e0d0d59026..9550692673f1ec981e30763a90dba9b532f6dc6c 100755
--- a/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/socket/BlockStreamProtocolDecoder.java
+++ b/deskshare/app/src/main/java/org/bigbluebutton/deskshare/server/socket/BlockStreamProtocolDecoder.java
@@ -95,9 +95,10 @@ public class BlockStreamProtocolDecoder extends CumulativeProtocolDecoder {
     
     private void decodeMouseLocationEvent(IoSession session, IoBuffer in, ProtocolDecoderOutput out) {
     	String room = decodeRoom(session, in);
+    	int seqNum = in.getInt();
     	int mouseX = in.getInt();
     	int mouseY = in.getInt();
-    	MouseLocationEvent event = new MouseLocationEvent(room, new Point(mouseX, mouseY));
+    	MouseLocationEvent event = new MouseLocationEvent(room, new Point(mouseX, mouseY), seqNum);
     	out.write(event);
     }
     
@@ -106,7 +107,8 @@ public class BlockStreamProtocolDecoder extends CumulativeProtocolDecoder {
     	
     	if (! "".equals(room)) {
     		log.info("CaptureEndEvent for " + room);
-    		CaptureEndBlockEvent event = new CaptureEndBlockEvent(room);
+    		int seqNum = in.getInt();
+    		CaptureEndBlockEvent event = new CaptureEndBlockEvent(room, seqNum);
     		out.write(event);
     	} else {
     		log.warn("Room is empty.");
@@ -116,13 +118,13 @@ public class BlockStreamProtocolDecoder extends CumulativeProtocolDecoder {
     private void decodeCaptureStartEvent(IoSession session, IoBuffer in, ProtocolDecoderOutput out) { 
     	String room = decodeRoom(session, in);
     	session.setAttribute(ROOM, room);
+    	int seqNum = in.getInt();
     	
 		Dimension blockDim = decodeDimension(in);
 		Dimension screenDim = decodeDimension(in);    	
-//	    System.out.println("Block dim [" + blockDim.getWidth() + "," + blockDim.getHeight() + "]");
-//	    System.out.println("Screen dim [" + screenDim.getWidth() + "," + screenDim.getHeight() + "]");
+
 	    log.info("CaptureStartEvent for " + room);
-	    CaptureStartBlockEvent event = new CaptureStartBlockEvent(room, screenDim, blockDim);	
+	    CaptureStartBlockEvent event = new CaptureStartBlockEvent(room, screenDim, blockDim, seqNum);	
 	    out.write(event);
     }
     
@@ -153,15 +155,22 @@ public class BlockStreamProtocolDecoder extends CumulativeProtocolDecoder {
     
     private void decodeCaptureUpdateEvent(IoSession session, IoBuffer in, ProtocolDecoderOutput out) {
     	String room = decodeRoom(session, in);
-    	int position = in.getShort();
-    	boolean isKeyFrame = (in.get() == 1) ? true : false;
-    	int length = in.getInt();
-    	byte[] data = new byte[length];
-    	in.get(data, 0, length);
-    	
-//    	System.out.println("position=[" + position + "] keyframe=" + isKeyFrame + " length= " + length);
+    	int seqNum = in.getInt();
+    	int numBlocks = in.getShort();
+//    	System.out.println("Number of blocks changed " + numBlocks);
+    	String blocksStr = "Blocks changed ";
     	
-    	CaptureUpdateBlockEvent event = new CaptureUpdateBlockEvent(room, position, data, isKeyFrame);
-    	out.write(event);
+    	for (int i = 0; i < numBlocks; i++) {
+        	int position = in.getShort();
+        	blocksStr += " " + position;
+        	
+        	boolean isKeyFrame = (in.get() == 1) ? true : false;
+        	int length = in.getInt();
+        	byte[] data = new byte[length];
+        	in.get(data, 0, length);    	
+        	CaptureUpdateBlockEvent event = new CaptureUpdateBlockEvent(room, position, data, isKeyFrame, seqNum);
+        	out.write(event);    		
+    	}
+//    	System.out.println(blocksStr);
     }
 }
diff --git a/deskshare/app/src/main/scala/org/bigbluebutton/deskshare/server/sessions/SessionManagerGateway.scala b/deskshare/app/src/main/scala/org/bigbluebutton/deskshare/server/sessions/SessionManagerGateway.scala
index 86bdb456a8d2159e91828832734acb44e0f25da7..0433acf05fb87cb53553e1ac7a655b0c465fcac8 100755
--- a/deskshare/app/src/main/scala/org/bigbluebutton/deskshare/server/sessions/SessionManagerGateway.scala
+++ b/deskshare/app/src/main/scala/org/bigbluebutton/deskshare/server/sessions/SessionManagerGateway.scala
@@ -34,24 +34,24 @@ class SessionManagerGateway(streamManager: StreamManager) extends ISessionManage
 	val sessionManager: SessionManagerSVC = new SessionManagerSVC(streamManager)
     sessionManager.start 
   
-	def createSession(room: String, screenDim: common.Dimension, blockDim: common.Dimension): Unit = {
+	def createSession(room: String, screenDim: common.Dimension, blockDim: common.Dimension, seqNum: Int): Unit = {
 		log.info("SessionManagerGateway:createSession for %s", room)
 		sessionManager ! new CreateSession(room, new svc1.Dimension(screenDim.getWidth(), screenDim.getHeight()), 
-	                                       new svc1.Dimension(blockDim.getWidth(), blockDim.getHeight()))
+	                                       new svc1.Dimension(blockDim.getWidth(), blockDim.getHeight()), seqNum)
 		log.info("SessionManagerGateway:Sent create session for %s", room)	    
 	}
 
-	def removeSession(room: String): Unit = {
+	def removeSession(room: String, seqNum: Int): Unit = {
 	  log.info("SessionManagerGateway:removeSession for %s", room)
 	  sessionManager ! new RemoveSession(room)
 	}
 	
-	def updateBlock(room : String, position : Int, blockData : Array[Byte], keyframe : Boolean): Unit = {
-		sessionManager ! new UpdateBlock(room, position, blockData, keyframe)
+	def updateBlock(room : String, position : Int, blockData : Array[Byte], keyframe : Boolean, seqNum: Int): Unit = {
+		sessionManager ! new UpdateBlock(room, position, blockData, keyframe, seqNum)
 	}
  
-	def updateMouseLocation(room: String, mouseLoc: Point): Unit = {
-	    sessionManager ! new UpdateMouseLocation(room, mouseLoc)
+	def updateMouseLocation(room: String, mouseLoc: Point, seqNum: Int): Unit = {
+	    sessionManager ! new UpdateMouseLocation(room, mouseLoc, seqNum)
 	}
  
 	def sendKeyFrame(room: String) {
diff --git a/deskshare/app/src/main/scala/org/bigbluebutton/deskshare/server/sessions/SessionManagerSVC.scala b/deskshare/app/src/main/scala/org/bigbluebutton/deskshare/server/sessions/SessionManagerSVC.scala
index d6dff319134c2212c0445563c39650f87b3c2736..58c62cbae8716169ec4d8bd51557d6b13f55aa7f 100755
--- a/deskshare/app/src/main/scala/org/bigbluebutton/deskshare/server/sessions/SessionManagerSVC.scala
+++ b/deskshare/app/src/main/scala/org/bigbluebutton/deskshare/server/sessions/SessionManagerSVC.scala
@@ -28,11 +28,11 @@ import org.bigbluebutton.deskshare.server.svc1.Dimension
 import org.bigbluebutton.deskshare.server.stream.StreamManager
 import java.awt.Point
 
-case class CreateSession(room: String, screenDim: Dimension, blockDim: Dimension)
+case class CreateSession(room: String, screenDim: Dimension, blockDim: Dimension, seqNum: Int)
 case class RemoveSession(room: String)
 case class SendKeyFrame(room: String)
-case class UpdateBlock(room: String, position: Int, blockData: Array[Byte], keyframe: Boolean)
-case class UpdateMouseLocation(room: String, mouseLoc:Point)
+case class UpdateBlock(room: String, position: Int, blockData: Array[Byte], keyframe: Boolean, seqNum: Int)
+case class UpdateMouseLocation(room: String, mouseLoc:Point, seqNum: Int)
 
 class SessionManagerSVC(streamManager: StreamManager) extends Actor {
 	private val log = Logger.get 
@@ -45,8 +45,8 @@ class SessionManagerSVC(streamManager: StreamManager) extends Actor {
 	      case c: CreateSession => createSession(c); printMailbox("CreateSession") 
 	      case r: RemoveSession => removeSession(r.room); printMailbox("RemoveSession")
 	      case k: SendKeyFrame => sendKeyFrame(k.room); printMailbox("SendKeyFrame")
-	      case ub: UpdateBlock => updateBlock(ub.room, ub.position, ub.blockData, ub.keyframe)
-	      case ml: UpdateMouseLocation => updateMouseLocation(ml.room, ml.mouseLoc)
+	      case ub: UpdateBlock => updateBlock(ub.room, ub.position, ub.blockData, ub.keyframe, ub.seqNum)
+	      case ml: UpdateMouseLocation => updateMouseLocation(ml.room, ml.mouseLoc, ml.seqNum)
 	      case m: Any => log.warning("SessionManager: Unknown message " + m); printMailbox("Any")
 	    }
 	  }
@@ -98,16 +98,16 @@ class SessionManagerSVC(streamManager: StreamManager) extends Actor {
     	}
 	}
 	
-	private def updateMouseLocation(room: String, mouseLoc: Point): Unit = {
+	private def updateMouseLocation(room: String, mouseLoc: Point, seqNum: Int): Unit = {
 		sessions.get(room) match {
-		  case Some(s) => s ! new UpdateSessionMouseLocation(mouseLoc)
+		  case Some(s) => s ! new UpdateSessionMouseLocation(mouseLoc, seqNum)
 		  case None => log.warning("SessionManager: Could not update mouse loc for session %s. Does not exist.", room)
 		}
 	}
 	
-	private def updateBlock(room: String, position: Int, blockData: Array[Byte], keyframe: Boolean): Unit = {
+	private def updateBlock(room: String, position: Int, blockData: Array[Byte], keyframe: Boolean, seqNum: Int): Unit = {
 		sessions.get(room) match {
-		  case Some(s) => s ! new UpdateSessionBlock(position, blockData, keyframe)
+		  case Some(s) => s ! new UpdateSessionBlock(position, blockData, keyframe, seqNum)
 		  case None => log.warning("SessionManager: Could not update session %s. Does not exist.", room)
 		}
 	}
diff --git a/deskshare/app/src/main/scala/org/bigbluebutton/deskshare/server/sessions/SessionSVC.scala b/deskshare/app/src/main/scala/org/bigbluebutton/deskshare/server/sessions/SessionSVC.scala
index 6c0be6be23a84316d1c198fe172f27c7f29bc122..70abd974d098b8f31be3e75418af955ebed407fc 100755
--- a/deskshare/app/src/main/scala/org/bigbluebutton/deskshare/server/sessions/SessionSVC.scala
+++ b/deskshare/app/src/main/scala/org/bigbluebutton/deskshare/server/sessions/SessionSVC.scala
@@ -29,8 +29,8 @@ import net.lag.logging.Logger
 import java.awt.Point
 
 case object StartSession
-case class UpdateSessionBlock(position: Int, blockData: Array[Byte], keyframe: Boolean)
-case class UpdateSessionMouseLocation(loc: Point)
+case class UpdateSessionBlock(position: Int, blockData: Array[Byte], keyframe: Boolean, seqNum: Int)
+case class UpdateSessionMouseLocation(loc: Point, seqNum: Int)
                                       
 case object StopSession
 case object GenerateKeyFrame
@@ -92,7 +92,7 @@ class SessionSVC(sessionManager:SessionManagerSVC, room: String, screenDim: Dime
          	  log.debug("Session: Generating Key Frame for room %s", room)
         	  generateFrame(true)       	  
           }
-          case b: UpdateSessionBlock => updateBlock(b.position, b.blockData, b.keyframe)
+          case b: UpdateSessionBlock => updateBlock(b.position, b.blockData, b.keyframe, b.seqNum)
           case m: Any => log.warning("Session: Unknown message [%s]", m)
         }
       }
@@ -121,9 +121,9 @@ class SessionSVC(sessionManager:SessionManagerSVC, room: String, screenDim: Dime
 		streamManager.destroyStream(room)
 	}
 	
-	private def updateBlock(position: Int, videoData: Array[Byte], keyFrame: Boolean): Unit = {
+	private def updateBlock(position: Int, videoData: Array[Byte], keyFrame: Boolean, seqNum: Int): Unit = {
 		lastUpdate = System.currentTimeMillis()
-		blockManager.updateBlock(position, videoData, keyFrame)	
+		blockManager.updateBlock(position, videoData, keyFrame, seqNum)	
 	}
 	
 	private def generateFrame(keyframe:Boolean) {				  
diff --git a/deskshare/app/src/main/scala/org/bigbluebutton/deskshare/server/svc1/Block.scala b/deskshare/app/src/main/scala/org/bigbluebutton/deskshare/server/svc1/Block.scala
index a943ccc388d337e15703d7763ce246d6159df68b..8e1497e87d791ab56c3ef8caddbb50795f73a530 100755
--- a/deskshare/app/src/main/scala/org/bigbluebutton/deskshare/server/svc1/Block.scala
+++ b/deskshare/app/src/main/scala/org/bigbluebutton/deskshare/server/svc1/Block.scala
@@ -20,8 +20,10 @@
 package org.bigbluebutton.deskshare.server.svc1
 
 import java.util.Random
+import net.lag.logging.Logger
 
 class Block(val dim: Dimension, val position: Int) {
+	private val log = Logger.get
 
     val nextForceUpdate = 10000
     val MIN_DURATION = 5000
@@ -33,11 +35,17 @@ class Block(val dim: Dimension, val position: Int) {
     var encodedBlock: Array[Byte] = null
     
     val random: Random = new Random();
+    private var sequenceNumber = 0;
     
-    def update(videoData: Array[Byte], isKeyFrame: Boolean): Unit =  {	
-    	this.isKeyFrame = isKeyFrame;
-    	encodedBlock = videoData;
-    	hasChanged = true;
+    def update(videoData: Array[Byte], isKeyFrame: Boolean, seqNum: Int): Unit =  {	
+    	if (seqNum >= sequenceNumber) {
+			sequenceNumber = seqNum				
+	    	this.isKeyFrame = isKeyFrame;
+	    	encodedBlock = videoData;
+	    	hasChanged = true;
+    	} else {
+			log.warning("Block[" + position + "[: Delayed sequence number [%s < %s]", seqNum, sequenceNumber)
+		}
     }
  
     def getEncodedBlock(): Array[Byte] = {
diff --git a/deskshare/app/src/main/scala/org/bigbluebutton/deskshare/server/svc1/BlockManager.scala b/deskshare/app/src/main/scala/org/bigbluebutton/deskshare/server/svc1/BlockManager.scala
index 0fe1a90a30871e2a5f6d7408df97fa69cf286065..9aff2e5d0b3468a2164f763b07361cd89e01ad90 100755
--- a/deskshare/app/src/main/scala/org/bigbluebutton/deskshare/server/svc1/BlockManager.scala
+++ b/deskshare/app/src/main/scala/org/bigbluebutton/deskshare/server/svc1/BlockManager.scala
@@ -48,14 +48,14 @@ class BlockManager(room: String, screenDim: Dimension, blockDim: Dimension) exte
 				blankPixels(i) = 0xFFFF;
 			}
 			val encodedPixels = ScreenVideoEncoder.encodePixels(blankPixels, dim.width, dim.height)
-			block.update(encodedPixels, true)
+			block.update(encodedPixels, true, 0)
 			blocksMap.put(position, block)
 		}
 	}
 	
-	def updateBlock(position: Int, videoData: Array[Byte], keyFrame: Boolean): Unit = {
+	def updateBlock(position: Int, videoData: Array[Byte], keyFrame: Boolean, seqNum: Int): Unit = {
 		val block: Block = blocksMap.get(position)
-		block.update(videoData, keyFrame)
+		block.update(videoData, keyFrame, seqNum)
 	}
 	
 	def generateFrame(genKeyFrame: Boolean): Array[Byte] = {
diff --git a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/blocks/Block.java b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/blocks/Block.java
index fed3cf6c5c88dbbe24c516cf2e27caa4e2edbe65..e812a1c67934c0bfe770f15ef77245011c978c22 100755
--- a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/blocks/Block.java
+++ b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/blocks/Block.java
@@ -83,11 +83,14 @@ public final class Block {
     	return false;
     }
     
+    public void sent() {
+    	dirtyBlock.set(false);
+    }
+    
     public EncodedBlockData encode() {   
     	int[] pixelsCopy = new int[capturedPixels.length];
     	
-    	synchronized (pixelsLock) { 
-    		dirtyBlock.set(false);
+    	synchronized (pixelsLock) {     		
             System.arraycopy(capturedPixels, 0, pixelsCopy, 0, capturedPixels.length);
 		}
     	
diff --git a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/blocks/BlockManager.java b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/blocks/BlockManager.java
index 110855874370644ac17e4fb0a42891e45e26ae69..d5ab5b9a0c5aed1c3041fdb88c4aa5404ed3e272 100755
--- a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/blocks/BlockManager.java
+++ b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/blocks/BlockManager.java
@@ -22,6 +22,7 @@ package org.bigbluebutton.deskshare.client.blocks;
 import java.awt.image.BufferedImage;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Vector;
 
 import org.bigbluebutton.deskshare.client.net.BlockMessage;
 import org.bigbluebutton.deskshare.common.Dimension;
@@ -57,18 +58,42 @@ public class BlockManager {
     
     public void processCapturedScreen(BufferedImage capturedScreen) {    	
     	long start = System.currentTimeMillis();
+
+    	Vector<Integer> changedBlocks = new Vector<Integer>();
+/*		
 		int numberOfBlocks = numColumns * numRows;
-        for (int position = 1; position <= numberOfBlocks; position++) {
-        	Block block = blocksMap.get(new Integer(position));
+		for (int position = 1; position <= numberOfBlocks; position++) {
+			Block block = blocksMap.get(new Integer(position));
         	if (block.hasChanged(capturedScreen)) {
-        		notifyChangedBlockListener(new BlockMessage(block.getPosition()));
+        		changedBlocks.add(new Integer(position));        		
         	}
-        }
-        
-		long end = System.currentTimeMillis();
-//		System.out.println("ProcessCapturedScreen took " + (end-start) + " ms.");
+		}  
+    	
+		if (changedBlocks.size() > 0) {
+			Integer[] bc = new Integer[changedBlocks.size()];
+			System.arraycopy(changedBlocks.toArray(), 0, bc, 0, bc.length);
+			changedBlocks.clear();
+			notifyChangedBlockListener(new BlockMessage(bc));
+		}
+*/
+		
+		int numberOfBlocks = numColumns * numRows;
+		for (int position = 1; position <= numberOfBlocks; position++) {
+			Block block = blocksMap.get(new Integer(position));
+        	if (block.hasChanged(capturedScreen)) {
+        		changedBlocks.add(new Integer(position));        		
+        	}
+        	
+    		if ((position % numColumns == 0) && (changedBlocks.size() > 0)) {
+    			Integer[] bc = new Integer[changedBlocks.size()];
+    			System.arraycopy(changedBlocks.toArray(), 0, bc, 0, bc.length);
+    			changedBlocks.clear();
+    			notifyChangedBlockListener(new BlockMessage(bc));
+    		}
+		}
+
     }
-    
+        
     private void notifyChangedBlockListener(BlockMessage position) {
     	listeners.onChangedBlock(position);
     }
@@ -82,6 +107,11 @@ public class BlockManager {
 		listeners = null;
 	}
     
+	public void blockSent(int position) {
+		Block block = (Block) blocksMap.get(new Integer(position));
+		block.sent();
+	}
+	
 	public Block getBlock(int position) {
 		return (Block) blocksMap.get(new Integer(position));
 	}
diff --git a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/BlockMessage.java b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/BlockMessage.java
index 33a073a26f03fe40b8cbbf4b34bdbc1878ff8629..93f8d197c01ff3eec1164fc58bb6ac1531131358 100755
--- a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/BlockMessage.java
+++ b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/BlockMessage.java
@@ -21,10 +21,10 @@ package org.bigbluebutton.deskshare.client.net;
 
 public class BlockMessage implements Message {
 
-	private int position;
+	private Integer[] blocks;
 	
-	public BlockMessage(int position) {
-		this.position = position;
+	public BlockMessage(Integer[] blocks) {
+		this.blocks = blocks;
 	}
 	
 	@Override
@@ -32,7 +32,7 @@ public class BlockMessage implements Message {
 		return MessageType.BLOCK;
 	}
 
-	public int getPosition() {
-		return position;
+	public Integer[] getBlocks() {
+		return blocks;
 	}
 }
diff --git a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/BlockStreamProtocolEncoder.java b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/BlockStreamProtocolEncoder.java
index e9036e39dbdcfa1bcab7931d5da00fa2fecfa92e..a035e3e96e1882f1f0afa2489b68e02e35788cfb 100755
--- a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/BlockStreamProtocolEncoder.java
+++ b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/BlockStreamProtocolEncoder.java
@@ -34,21 +34,24 @@ public class BlockStreamProtocolEncoder {
     private static final byte MOUSE_LOCATION_EVENT = 3;
     
 	public static void encodeStartStreamMessage(String room, Dimension screen, Dimension block,
-						ByteArrayOutputStream data) throws IOException {		
+						ByteArrayOutputStream data, int seqNum) throws IOException {	
+		
 		data.write(CAPTURE_START_EVENT);
-		data.write(room.length());
-		data.write(room.getBytes());		
+		encodeRoom(data, room);
+		encodeSequenceNumber(data, seqNum);
+		
 		data.write(intToBytes(block.getWidth()));
 		data.write(intToBytes(block.getHeight()));
 		data.write(intToBytes(screen.getWidth()));
 		data.write(intToBytes(screen.getHeight()));
 	}
 	
-	public static void encodeBlock(BlockVideoData block, ByteArrayOutputStream data) throws IOException {
+	public static void encodeBlock(BlockVideoData block, ByteArrayOutputStream data, int seqNum) throws IOException {		
 		data.write(CAPTURE_UPDATE_EVENT);
-		data.write(block.getRoom().length());
-		data.write(block.getRoom().getBytes());
-			
+		encodeRoom(data, block.getRoom());
+		
+		encodeSequenceNumber(data, seqNum);
+		
 		byte[] position = new byte[2];
 		int pos = block.getPosition();
 		position[0] = (byte)((pos >> 8) & 0xff);
@@ -58,19 +61,35 @@ public class BlockStreamProtocolEncoder {
 		data.write(block.isKeyFrame() ? 1:0);
 			
 		int length = block.getVideoData().length;			
-//		System.out.println("position=" + pos + " keyframe=" + block.isKeyFrame() + " data length=" + length);
-		data.write(intToBytes(length));
-			
+		data.write(intToBytes(length));			
 		data.write(block.getVideoData());		
 	}
+
+	public static void numBlocksChanged(int numBlocks, ByteArrayOutputStream data) throws IOException{
+		byte[] nb = new byte[2];
+		nb[0] = (byte)((numBlocks >> 8) & 0xff);
+		nb[1] = (byte)(numBlocks & 0xff);
+		data.write(nb);
+	}
 	
-	private static byte[] intToBytes(int i) {
-		byte[] data = new byte[4];
-		data[0] = (byte)((i >> 24) & 0xff);
-		data[1] = (byte)((i >> 16) & 0xff);
-		data[2] = (byte)((i >> 8) & 0xff);
-		data[3] = (byte)(i & 0xff);		
-		return data;
+	public static void encodeRoomAndSequenceNumber(String room, int seqNum, ByteArrayOutputStream data) throws IOException{
+		data.write(CAPTURE_UPDATE_EVENT);
+		encodeRoom(data, room);		
+		encodeSequenceNumber(data, seqNum);		
+	}
+	
+	public static void encodeBlock(BlockVideoData block, ByteArrayOutputStream data) throws IOException {				
+		byte[] position = new byte[2];
+		int pos = block.getPosition();
+		position[0] = (byte)((pos >> 8) & 0xff);
+		position[1] = (byte)(pos & 0xff);
+			
+		data.write(position);
+		data.write(block.isKeyFrame() ? 1:0);
+			
+		int length = block.getVideoData().length;			
+		data.write(intToBytes(length));			
+		data.write(block.getVideoData());		
 	}
 	
 	public static byte[] encodeHeaderAndLength(ByteArrayOutputStream data) throws IOException {
@@ -80,17 +99,35 @@ public class BlockStreamProtocolEncoder {
 		return header.toByteArray();
 	}
 	
-	public static void encodeMouseLocation(Point mouseLoc, String room, ByteArrayOutputStream data) throws IOException {
+	public static void encodeMouseLocation(Point mouseLoc, String room, ByteArrayOutputStream data, int seqNum) throws IOException {		
 		data.write(MOUSE_LOCATION_EVENT);
-		data.write(room.length());
-		data.write(room.getBytes());
+		encodeRoom(data, room);
+		encodeSequenceNumber(data, seqNum);
 		data.write(intToBytes(mouseLoc.x));
 		data.write(intToBytes(mouseLoc.y));
 	}
 	
-	public static void encodeEndStreamMessage(String room, ByteArrayOutputStream data) throws IOException {
+	public static void encodeEndStreamMessage(String room, ByteArrayOutputStream data, int seqNum) throws IOException {		
 		data.write(CAPTURE_END_EVENT);
+		encodeRoom(data, room);
+		encodeSequenceNumber(data, seqNum);
+	}
+	
+	private static byte[] intToBytes(int i) {
+		byte[] data = new byte[4];
+		data[0] = (byte)((i >> 24) & 0xff);
+		data[1] = (byte)((i >> 16) & 0xff);
+		data[2] = (byte)((i >> 8) & 0xff);
+		data[3] = (byte)(i & 0xff);		
+		return data;
+	}
+	
+	private static void encodeRoom(ByteArrayOutputStream data, String room) throws IOException {
 		data.write(room.length());
 		data.write(room.getBytes());
 	}
+	
+	private static void encodeSequenceNumber(ByteArrayOutputStream data, int seqNum) throws IOException {
+		data.write(intToBytes(seqNum));
+	}
 }
diff --git a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/NetworkHttpStreamSender.java b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/NetworkHttpStreamSender.java
index 22e9bafc5f496d262f2ebf5b30e3b6a7150f412f..f43f03b84692de2a961ec408e3a5a5b24e58e18f 100755
--- a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/NetworkHttpStreamSender.java
+++ b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/NetworkHttpStreamSender.java
@@ -33,7 +33,18 @@ import org.bigbluebutton.deskshare.common.Dimension;
 
 import com.myjavatools.web.ClientHttpRequest;
 
-public class NetworkHttpStreamSender implements Runnable {
+public class NetworkHttpStreamSender implements Runnable {	
+	private static final String SEQ_NUM = "sequenceNumber";
+	private static final String ROOM = "room";
+	private static final String BLOCK = "blockInfo";
+	private static final String EVENT = "event";
+	private static final String SCREEN = "screenInfo";
+	private static final String POSITION = "position";
+	private static final String KEYFRAME = "keyframe";
+	private static final String BLOCKDATA = "blockdata";
+	private static final String MOUSEX = "mousex";
+	private static final String MOUSEY = "mousey";
+	
 	private String host = "localhost";
 	private static final String SCREEN_CAPTURE__URL = "/deskshare/tunnel/screenCapture";
 	private URL url;
@@ -45,13 +56,16 @@ public class NetworkHttpStreamSender implements Runnable {
 	private volatile boolean processBlocks = false;
 	private final int id;
 	private NetworkStreamListener listener;
+	private final SequenceNumberGenerator seqNumGenerator;
 	
-	public NetworkHttpStreamSender(int id, NextBlockRetriever retriever, String room, Dimension screenDim, Dimension blockDim) {
+	public NetworkHttpStreamSender(int id, NextBlockRetriever retriever, String room, 
+									Dimension screenDim, Dimension blockDim, SequenceNumberGenerator seqNumGenerator) {
 		this.id = id;
 		this.retriever = retriever;
 		this.room = room;
 		this.screenDim = screenDim;
 		this.blockDim = blockDim;
+		this.seqNumGenerator = seqNumGenerator;
 	}
 	
 	public void addListener(NetworkStreamListener listener) {
@@ -102,19 +116,18 @@ public class NetworkHttpStreamSender implements Runnable {
 		ClientHttpRequest chr;
 		try {
 			chr = new ClientHttpRequest(conn);
-			chr.setParameter("room", room);
+			chr.setParameter(ROOM, room);
 			
+			chr.setParameter(SEQ_NUM, seqNumGenerator.getNext());
 			String screenInfo = Integer.toString(screen.getWidth())
 								+ "x" + Integer.toString(screen.getHeight());
-
-			chr.setParameter("screenInfo", screenInfo);
+			chr.setParameter(SCREEN, screenInfo);
 			
 			String blockInfo = Integer.toString(block.getWidth())
 								+ "x" + Integer.toString(block.getHeight());
+			chr.setParameter(BLOCK, blockInfo);
 
-			chr.setParameter("blockInfo", blockInfo);
-
-			chr.setParameter("event", CaptureEvents.CAPTURE_START.getEvent());
+			chr.setParameter(EVENT, CaptureEvents.CAPTURE_START.getEvent());
 			chr.post();
 		} catch (IOException e) {
 			e.printStackTrace();
@@ -141,9 +154,9 @@ public class NetworkHttpStreamSender implements Runnable {
 		ClientHttpRequest chr;
 		try {
 			chr = new ClientHttpRequest(conn);
-			chr.setParameter("room", room);
-			
-			chr.setParameter("event", CaptureEvents.CAPTURE_END.getEvent());
+			chr.setParameter(ROOM, room);
+			chr.setParameter(SEQ_NUM, seqNumGenerator.getNext());
+			chr.setParameter(EVENT, CaptureEvents.CAPTURE_END.getEvent());
 			chr.post();
 		} catch (IOException e) {
 			e.printStackTrace();
@@ -153,9 +166,10 @@ public class NetworkHttpStreamSender implements Runnable {
 	
 	private void processNextMessageToSend(Message message) {
 		if (message.getMessageType() == Message.MessageType.BLOCK) {
-			EncodedBlockData block = retriever.getBlockToSend(((BlockMessage)message).getPosition());
-			BlockVideoData	bv = new BlockVideoData(room, block.getPosition(), block.getVideoData(), false /* should remove later */);									
-			sendBlockData(bv);
+//			EncodedBlockData block = retriever.getBlockToSend(((BlockMessage)message).getPosition());
+//			BlockVideoData	bv = new BlockVideoData(room, block.getPosition(), block.getVideoData(), false /* should remove later */);									
+//			sendBlockData(bv);
+//			retriever.blockSent(block.getPosition());
 		} else if (message.getMessageType() == Message.MessageType.CURSOR) {
 			CursorMessage msg = (CursorMessage)message;
 			sendCursor(msg.getMouseLocation(), msg.getRoom());
@@ -183,10 +197,11 @@ public class NetworkHttpStreamSender implements Runnable {
 		try {
 			openConnection();
 			chr = new ClientHttpRequest(conn);
-			chr.setParameter("room", room);
-			chr.setParameter("event", CaptureEvents.MOUSE_LOCATION_EVENT.getEvent());
-			chr.setParameter("mousex", mouseLoc.x);
-			chr.setParameter("mousey", mouseLoc.y);
+			chr.setParameter(ROOM, room);
+			chr.setParameter(SEQ_NUM, seqNumGenerator.getNext());
+			chr.setParameter(EVENT, CaptureEvents.MOUSE_LOCATION_EVENT.getEvent());
+			chr.setParameter(MOUSEX, mouseLoc.x);
+			chr.setParameter(MOUSEY, mouseLoc.y);
 			chr.post();		
 			} catch (IOException e) {
 				e.printStackTrace();
@@ -200,12 +215,13 @@ public class NetworkHttpStreamSender implements Runnable {
 		try {
 			openConnection();
 			chr = new ClientHttpRequest(conn);
-		    chr.setParameter("room", blockData.getRoom());
-		    chr.setParameter("position", blockData.getPosition());
-		    chr.setParameter("keyframe", blockData.isKeyFrame());
-		    chr.setParameter("event", CaptureEvents.CAPTURE_UPDATE.getEvent());
+		    chr.setParameter(ROOM, blockData.getRoom());
+		    chr.setParameter(SEQ_NUM, seqNumGenerator.getNext());
+		    chr.setParameter(POSITION, blockData.getPosition());
+		    chr.setParameter(KEYFRAME, blockData.isKeyFrame());
+		    chr.setParameter(EVENT, CaptureEvents.CAPTURE_UPDATE.getEvent());
 			ByteArrayInputStream block = new ByteArrayInputStream(blockData.getVideoData());				
-			chr.setParameter("blockdata", "block", block);
+			chr.setParameter(BLOCKDATA, "block", block);
 			chr.post();		
 		} catch (IOException e) {
 			e.printStackTrace();
diff --git a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/NetworkSocketStreamSender.java b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/NetworkSocketStreamSender.java
index 1cfa6fb614e452f7237efa434612e2ec96f5ff9d..fb36a6da8a13594a4e6a3c7dea2cd90d2c0f926b 100755
--- a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/NetworkSocketStreamSender.java
+++ b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/NetworkSocketStreamSender.java
@@ -25,6 +25,7 @@ import java.io.DataOutputStream;
 import java.io.IOException;
 import java.net.Socket;
 import java.net.UnknownHostException;
+import java.util.Vector;
 
 import org.bigbluebutton.deskshare.client.ExitCode;
 import org.bigbluebutton.deskshare.common.Dimension;
@@ -40,13 +41,16 @@ public class NetworkSocketStreamSender implements Runnable {
 	private volatile boolean processMessages = false;
 	private final int id;
 	private NetworkStreamListener listener;
+	private final SequenceNumberGenerator seqNumGenerator;
 	
-	public NetworkSocketStreamSender(int id, NextBlockRetriever retriever, String room, Dimension screenDim, Dimension blockDim) {
+	public NetworkSocketStreamSender(int id, NextBlockRetriever retriever, String room, 
+			Dimension screenDim, Dimension blockDim, SequenceNumberGenerator seqNumGenerator) {
 		this.id = id;
 		this.retriever = retriever;
 		this.room = room;
 		this.screenDim = screenDim;
 		this.blockDim = blockDim;	
+		this.seqNumGenerator = seqNumGenerator;
 	}
 	
 	public void addListener(NetworkStreamListener listener) {
@@ -58,7 +62,7 @@ public class NetworkSocketStreamSender implements Runnable {
 	}
 	
 	public void connect(String host, int port) throws ConnectionException {
-		System.out.println("Starting NetworkSocketStreamSender ");
+		System.out.println("NetworkSocketStreamSender: connecting to " + host + ":" + port);
 		try {
 			socket = new Socket(host, port);
 			outstream = new DataOutputStream(socket.getOutputStream());
@@ -75,7 +79,7 @@ public class NetworkSocketStreamSender implements Runnable {
 		try {
 			ByteArrayOutputStream dataToSend = new ByteArrayOutputStream();
 			dataToSend.reset();
-			BlockStreamProtocolEncoder.encodeStartStreamMessage(room, screenDim, blockDim, dataToSend);
+			BlockStreamProtocolEncoder.encodeStartStreamMessage(room, screenDim, blockDim, dataToSend, seqNumGenerator.getNext());
 			sendHeader(BlockStreamProtocolEncoder.encodeHeaderAndLength(dataToSend));
 			sendToStream(dataToSend);
 		} catch (IOException e) {
@@ -87,7 +91,7 @@ public class NetworkSocketStreamSender implements Runnable {
 	private void sendCursor(Point mouseLoc, String room) throws IOException {
 		ByteArrayOutputStream dataToSend = new ByteArrayOutputStream();
 		dataToSend.reset();
-		BlockStreamProtocolEncoder.encodeMouseLocation(mouseLoc, room, dataToSend);
+		BlockStreamProtocolEncoder.encodeMouseLocation(mouseLoc, room, dataToSend, seqNumGenerator.getNext());
 		sendHeader(BlockStreamProtocolEncoder.encodeHeaderAndLength(dataToSend));
 		sendToStream(dataToSend);
 	}
@@ -95,7 +99,7 @@ public class NetworkSocketStreamSender implements Runnable {
 	private void sendBlock(BlockVideoData block) throws IOException {
 		ByteArrayOutputStream dataToSend = new ByteArrayOutputStream();
 		dataToSend.reset();
-		BlockStreamProtocolEncoder.encodeBlock(block, dataToSend);
+		BlockStreamProtocolEncoder.encodeBlock(block, dataToSend, seqNumGenerator.getNext());
 		sendHeader(BlockStreamProtocolEncoder.encodeHeaderAndLength(dataToSend));
 		sendToStream(dataToSend);
 	}
@@ -115,7 +119,7 @@ public class NetworkSocketStreamSender implements Runnable {
 		try {
 			ByteArrayOutputStream dataToSend = new ByteArrayOutputStream();
 			dataToSend.reset();
-			BlockStreamProtocolEncoder.encodeEndStreamMessage(room, dataToSend);
+			BlockStreamProtocolEncoder.encodeEndStreamMessage(room, dataToSend, seqNumGenerator.getNext());
 			sendHeader(BlockStreamProtocolEncoder.encodeHeaderAndLength(dataToSend));
 			sendToStream(dataToSend);
 		} catch (IOException e) {
@@ -128,9 +132,29 @@ public class NetworkSocketStreamSender implements Runnable {
 	
 	private void processNextMessageToSend(Message message) throws IOException {
 		if (message.getMessageType() == Message.MessageType.BLOCK) {
-			EncodedBlockData block = retriever.getBlockToSend(((BlockMessage)message).getPosition());
-			BlockVideoData	bv = new BlockVideoData(room, block.getPosition(), block.getVideoData(), false /* should remove later */);									
-			sendBlock(bv);
+			ByteArrayOutputStream dataToSend = new ByteArrayOutputStream();
+			dataToSend.reset();
+			BlockStreamProtocolEncoder.encodeRoomAndSequenceNumber(room, seqNumGenerator.getNext(), dataToSend);
+			
+			Integer[] changedBlocks = ((BlockMessage)message).getBlocks();
+
+			BlockStreamProtocolEncoder.numBlocksChanged(changedBlocks.length, dataToSend);
+//			System.out.println("Number of blocks changed: " + changedBlocks.length);
+			String blocksStr = "Encoding ";
+			for (int i = 0; i < changedBlocks.length; i++) {
+				blocksStr += " " + (Integer)changedBlocks[i];
+				EncodedBlockData block = retriever.getBlockToSend((Integer)changedBlocks[i]);
+				BlockVideoData	bv = new BlockVideoData(room, block.getPosition(), block.getVideoData(), false /* should remove later */);	
+				BlockStreamProtocolEncoder.encodeBlock(bv, dataToSend);
+			}
+			
+//			System.out.println(blocksStr);
+			
+			sendHeader(BlockStreamProtocolEncoder.encodeHeaderAndLength(dataToSend));
+			sendToStream(dataToSend);
+			for (int i = 0; i< changedBlocks.length; i++) {
+				retriever.blockSent((Integer)changedBlocks[i]);
+			}
 		} else if (message.getMessageType() == Message.MessageType.CURSOR) {
 			CursorMessage msg = (CursorMessage)message;
 			sendCursor(msg.getMouseLocation(), msg.getRoom());
diff --git a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/NetworkStreamSender.java b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/NetworkStreamSender.java
index 0c39ec80bfe686a3522946d37622e39ae71c5721..70a7fc1061f6df0e69beeb1d7a5081bee263f5a4 100755
--- a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/NetworkStreamSender.java
+++ b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/NetworkStreamSender.java
@@ -50,6 +50,7 @@ public class NetworkStreamSender implements NextBlockRetriever, NetworkStreamLis
 	private Dimension blockDim;
 	private BlockManager blockManager;
 	private NetworkConnectionListener listener;
+	private final SequenceNumberGenerator seqNumGenerator = new SequenceNumberGenerator();
 	
 	public NetworkStreamSender(BlockManager blockManager, String host, int port,
 			String room, Dimension screenDim, Dimension blockDim, boolean httpTunnel) {
@@ -126,13 +127,13 @@ public class NetworkStreamSender implements NextBlockRetriever, NetworkStreamLis
 	}
 	
 	private void createSender(int i) throws ConnectionException {
-		socketSenders[i] = new NetworkSocketStreamSender(i, this, room, screenDim, blockDim);
+		socketSenders[i] = new NetworkSocketStreamSender(i, this, room, screenDim, blockDim, seqNumGenerator);
 		socketSenders[i].addListener(this);
 		socketSenders[i].connect(host, port);		
 	}
 	
 	private void createHttpSender(int i) throws ConnectionException {
-		httpSenders[i] = new NetworkHttpStreamSender(i, this, room, screenDim, blockDim);
+		httpSenders[i] = new NetworkHttpStreamSender(i, this, room, screenDim, blockDim, seqNumGenerator);
 		httpSenders[i].addListener(this);
 		httpSenders[i].connect(host);
 	}
@@ -181,7 +182,7 @@ public class NetworkStreamSender implements NextBlockRetriever, NetworkStreamLis
 	}
 
 	private boolean tryHttpTunneling() {
-		NetworkHttpStreamSender httpSender = new NetworkHttpStreamSender(0, this, room, screenDim, blockDim);
+		NetworkHttpStreamSender httpSender = new NetworkHttpStreamSender(0, this, room, screenDim, blockDim, seqNumGenerator);
 		try {
 			httpSender.connect(host);
 			return true;
@@ -191,6 +192,10 @@ public class NetworkStreamSender implements NextBlockRetriever, NetworkStreamLis
 		return false;
 	}
 	
+	public void blockSent(int position) {
+		blockManager.blockSent(position);
+	}
+	
 	public EncodedBlockData getBlockToSend(int position) {		
 		return blockManager.getBlock(position).encode();
 	}	
@@ -211,7 +216,10 @@ public class NetworkStreamSender implements NextBlockRetriever, NetworkStreamLis
 			numRunningThreads--;
 		
 			if (tunneling) {								
-				httpSenders[id].disconnect();				
+//				httpSenders[id].disconnect();
+				System.out.println(NAME + "Failed to use http tunneling. Stopping.");
+				stop();
+				notifyNetworkConnectionListener(reason);
 			} else {
 				socketSenders[id].disconnect();
 			}
@@ -225,6 +233,12 @@ public class NetworkStreamSender implements NextBlockRetriever, NetworkStreamLis
 		} catch (ConnectionException e) {
 			// TODO Auto-generated catch block
 			e.printStackTrace();
+			if (numRunningThreads < 1) {
+				System.out.println(NAME + "No more sender threads. Stopping.");
+				notifyNetworkConnectionListener(reason);
+			} else {
+				System.out.println(NAME + "Sender thread stopped. " + numRunningThreads + " sender threads remaining.");
+			}
 		}		
 	}
 	
diff --git a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/NextBlockRetriever.java b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/NextBlockRetriever.java
index 6fad08b9d80a30886b0da392e8be384023031d76..88adaf5febe200d7a7d065d1428b0660cc7943b7 100755
--- a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/NextBlockRetriever.java
+++ b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/NextBlockRetriever.java
@@ -20,6 +20,7 @@
 package org.bigbluebutton.deskshare.client.net;
 
 public interface NextBlockRetriever {
+	public void blockSent(int position);
 	public EncodedBlockData getBlockToSend(int position);
 	public Message getNextMessageToSend() throws InterruptedException;
 }
diff --git a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/SequenceNumberGenerator.java b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/SequenceNumberGenerator.java
new file mode 100755
index 0000000000000000000000000000000000000000..de55e815f72590b6567a6007c954d7bcc5a27752
--- /dev/null
+++ b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/SequenceNumberGenerator.java
@@ -0,0 +1,17 @@
+package org.bigbluebutton.deskshare.client.net;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+
+public class SequenceNumberGenerator {
+
+	private final AtomicInteger sequenceNum;
+	
+	public SequenceNumberGenerator() {
+		sequenceNum = new AtomicInteger(0);
+	}
+	
+	public int getNext() {
+		return sequenceNum.incrementAndGet();
+	}
+}