diff --git a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/DeskShareApplet.java b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/DeskShareApplet.java
index f1118b2381..4e87b59dc0 100644
--- a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/DeskShareApplet.java
+++ b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/DeskShareApplet.java
@@ -29,12 +29,11 @@ import java.io.ByteArrayOutputStream;
import org.bigbluebutton.deskshare.client.blocks.BlockManager;
import org.bigbluebutton.deskshare.client.blocks.ChangedBlocksListener;
import org.bigbluebutton.deskshare.client.net.ConnectionException;
+import org.bigbluebutton.deskshare.client.net.EncodedBlockData;
import org.bigbluebutton.deskshare.client.net.NetworkStreamSender;
import org.bigbluebutton.deskshare.common.Dimension;
-import netscape.javascript.*;
public class DeskShareApplet extends Applet implements IScreenCaptureListener, ChangedBlocksListener {
-
private static final long serialVersionUID = 1L;
private ScreenCaptureTaker captureTaker;
private ScreenCapture capture;
@@ -63,9 +62,6 @@ public class DeskShareApplet extends Applet implements IScreenCaptureListener, C
y = Integer.parseInt(getParameter("Y"));
room = getParameter("ROOM");
host = getParameter("IP");
-
- String t = getParameter("TUNNEL");
- System.out.println("Tunnel param " + t);
}
public void stop() {
@@ -76,15 +72,13 @@ public class DeskShareApplet extends Applet implements IScreenCaptureListener, C
if (senderStarted)
sender.stop();
} catch (ConnectionException e) {
- // TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void start() {
- System.out.println("RunnerApplet start()");
-
+ System.out.println("Deskshare Applet start");
startCapture();
}
@@ -98,7 +92,7 @@ public class DeskShareApplet extends Applet implements IScreenCaptureListener, C
blockManager.addListener(this);
blockManager.initialize(screenDim, tileDim);
- sender = new NetworkStreamSender(blockManager, host, room);
+ sender = new NetworkStreamSender(host, room, screenDim, tileDim);
connected = sender.connect();
if (connected) {
captureTaker.addListener(this);
@@ -107,52 +101,31 @@ public class DeskShareApplet extends Applet implements IScreenCaptureListener, C
captureTakerThread = new Thread(captureTaker, "ScreenCaptureTaker");
captureTakerThread.start();
}
+ sender.start();
}
-
- private void testFunctionCall() {
- try {
- System.out.println("testFunctionCall: test started");
- JSObject window = JSObject.getWindow(this);
- System.out.println("Calling JavaScript getString();");
- if (window == null) System.out.println("WINDOW IS NULL");
- else System.out.println("WINDOW IS NOT NULL");
-
- String res = (String) window.eval("getString();");
- System.out.println("Got string from JavaScript: \"" + res + "\"");
- if (!res.equals("Hello, world!")) {
- throw new RuntimeException("string value did not match expected value");
- }
- Number num = (Number) window.eval("getNumber()");
- System.out.println("Got number from JavaScript: " + num);
- if (num.intValue() != 5) {
- throw new RuntimeException("number value did not match expected value");
- }
- System.out.println("testFunctionCall: test passed.");
- } catch (JSException e) {
- e.printStackTrace();
- System.out.println("TEST FAILED");
- } catch (Exception e2) {
- e2.printStackTrace();
- System.out.println("TEST FAILED");
- }
- }
-
+
/**
* This method is called when the user closes the browser window containing the applet
* It is very important that the connection to the server is closed at this point. That way the server knows to
* close the stream.
*/
- public void destroy(){
+ public void destroy() {
+ try {
+ sender.stop();
+ } catch (ConnectionException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
stop();
}
- public void setScreenCoordinates(int x, int y){
+ public void setScreenCoordinates(int x, int y) {
capture.setX(x);
capture.setY(y);
}
- public void onScreenCaptured(BufferedImage screen, boolean isKeyFrame) {
- blockManager.processCapturedScreen(screen, isKeyFrame);
+ public void onScreenCaptured(BufferedImage screen) {
+ blockManager.processCapturedScreen(screen);
}
@@ -161,11 +134,8 @@ public class DeskShareApplet extends Applet implements IScreenCaptureListener, C
destroy();
}
- public void onChangedTiles(ByteArrayOutputStream pixelData, boolean isKeyFrame) {
- if (! senderStarted) {
- sender.start();
- senderStarted = true;
- }
+ public void onChangedBlock(EncodedBlockData encodedData) {
+ sender.send(encodedData);
}
static public void main (String argv[]) {
diff --git a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/IScreenCaptureListener.java b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/IScreenCaptureListener.java
index 4875d98d06..eb73e26f06 100644
--- a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/IScreenCaptureListener.java
+++ b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/IScreenCaptureListener.java
@@ -25,5 +25,5 @@ import java.awt.image.BufferedImage;
public interface IScreenCaptureListener {
public void screenCaptureStopped();
- public void onScreenCaptured(BufferedImage screen, boolean isKeyFrame);
+ public void onScreenCaptured(BufferedImage screen);
}
diff --git a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/ScreenCapture.java b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/ScreenCapture.java
index 60d7a9d485..1eb8349a5a 100644
--- a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/ScreenCapture.java
+++ b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/ScreenCapture.java
@@ -42,7 +42,7 @@ public class ScreenCapture {
private Rectangle screenBounds;
private int width, height, x,y, videoWidth, videoHeight;
- public ScreenCapture(int x, int y, int screenWidth, int screenHeight){
+ public ScreenCapture(int x, int y, int screenWidth, int screenHeight) {
this.width = screenWidth;
this.height = screenHeight;
try{
@@ -54,26 +54,26 @@ public class ScreenCapture {
this.screenBounds = new Rectangle(x, y, this.width, this.height);
}
- public BufferedImage takeSingleSnapshot(){
+ public BufferedImage takeSingleSnapshot() {
return robot.createScreenCapture(this.screenBounds);
}
- public int getScreenshotWidth(){
+ public int getScreenshotWidth() {
return toolkit.getScreenSize().width;
}
- public int getScreenshotHeight(){
+ public int getScreenshotHeight() {
return toolkit.getScreenSize().height;
}
- public void setWidth(int width){
+ public void setWidth(int width) {
int screenWidth = toolkit.getScreenSize().width;
if (width > screenWidth) this.width = screenWidth;
else this.width = width;
updateBounds();
}
- public void setHeight(int height){
+ public void setHeight(int height) {
int screenHeight = toolkit.getScreenSize().height;
if (height > screenHeight) {
this.height = screenHeight;
@@ -84,29 +84,29 @@ public class ScreenCapture {
updateBounds();
}
- public void setX(int x){
+ public void setX(int x) {
this.x = x;
updateBounds();
}
- public void setY(int y){
+ public void setY(int y) {
this.y = y;
updateBounds();
}
- public void updateBounds(){
+ public void updateBounds() {
this.screenBounds = new Rectangle(x,y,width,height);
}
- public int getWidth(){
+ public int getWidth() {
return this.width;
}
- public int getHeight(){
+ public int getHeight() {
return this.height;
}
- public int getProperFrameRate(){
+ public int getProperFrameRate() {
long area = width*height;
if (area > 1000000) return 1;
else if (area > 600000) return 2;
@@ -115,11 +115,11 @@ public class ScreenCapture {
else return 10;
}
- public int getVideoWidth(){
+ public int getVideoWidth() {
return videoWidth;
}
- public int getVideoHeight(){
+ public int getVideoHeight() {
return videoHeight;
}
diff --git a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/ScreenCaptureTaker.java b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/ScreenCaptureTaker.java
index ea564cc8a3..416a79fa60 100644
--- a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/ScreenCaptureTaker.java
+++ b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/ScreenCaptureTaker.java
@@ -23,11 +23,8 @@ package org.bigbluebutton.deskshare.client;
import java.awt.image.BufferedImage;
-public class ScreenCaptureTaker implements Runnable {
-
+public class ScreenCaptureTaker implements Runnable {
private ScreenCapture capture;
- private int timeBase;
- private int frameCount = 0;
private IScreenCaptureListener listeners;
private volatile boolean startCapture = false;
@@ -35,64 +32,34 @@ public class ScreenCaptureTaker implements Runnable {
public ScreenCaptureTaker(ScreenCapture capture){
System.out.println("Capture thread constructor.");
this.capture = capture;
- this.timeBase = 1000 / capture.getProperFrameRate();
}
public void run(){
while (startCapture){
System.out.println("----- Taking screen capture -----");
- long snapshotTime = System.currentTimeMillis();
BufferedImage image = capture.takeSingleSnapshot();
- long snapshotEnd = System.currentTimeMillis();
-// System.out.println("Snapshot time = " + (snapshotEnd - snapshotTime) + "ms.");
notifyListeners(image);
- long completeTime = System.currentTimeMillis();
-// System.out.println("Processing time = " + (completeTime - snapshotTime) + "ms.");
try{
- //Thread.sleep(timeBase);
- Thread.sleep(500);
+ System.out.println("Going to sleeeeeep.");
+ Thread.sleep(1000);
+ System.out.println("Just woke up.");
} catch (Exception e){
System.out.println("Exception sleeping.");
System.exit(0);
}
}
- System.out.println("Stopping screen capture.");
-
+ System.out.println("Stopping screen capture.");
listeners.screenCaptureStopped();
}
private void notifyListeners(BufferedImage image) {
- listeners.onScreenCaptured(image, isKeyFrame());
+ listeners.onScreenCaptured(image);
}
-
- private boolean isKeyFrame() {
- if (frameCount == 0) {
-// System.out.println("Is Key Frame " + frameCount);
- frameCount++;
-
- return true;
- } else {
-// System.out.println("Is Not Key Frame " + frameCount);
- if (frameCount < 20) {
- frameCount++;
- } else {
- frameCount = 0;
- }
-
- return false;
- }
- }
-
public void addListener(IScreenCaptureListener listener) {
-// listeners.add(listener);
listeners = listener;
}
-
- public void removeListener(IScreenCaptureListener listener) {
-// listeners.remove(listener);
- }
public void setCapture(boolean capture) {
startCapture = capture;
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 a17bb899c8..15be0baa1d 100644
--- 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
@@ -36,16 +36,9 @@ public final class Block {
private final Adler32 checksum;
private final Dimension dim;
private final int position;
- private final Point location;
-
- private boolean isKeyFrame = false;
+ private final Point location;
private int[] pixels;
- private EncodedBlockData encodedBlockData;
-
- private int nextForceUpdate = 10000;
- private final static int MIN_DURATION = 5000;
- private final static int MAX_DURATION = 10000;
- private long lastChanged;
+ private boolean firstTime = true;
Block(Dimension dim, int position, Point location) {
checksum = new Adler32();
@@ -54,10 +47,8 @@ public final class Block {
this.location = location;
}
- public void updateBlock(BufferedImage capturedScreen, boolean isKeyFrame)
- {
- synchronized(this) {
- this.isKeyFrame = isKeyFrame;
+ public void updateBlock(BufferedImage capturedScreen) {
+ synchronized(this) {
try {
pixels = ScreenVideoEncoder.getPixels(capturedScreen, getX(), getY(), getWidth(), getHeight());
} catch (PixelExtractException e) {
@@ -66,82 +57,44 @@ public final class Block {
}
}
- public EncodedBlockData encode() {
- int[] pixelsCopy = new int[pixels.length];
- synchronized (this) {
- System.arraycopy(pixels, 0, pixelsCopy, 0, pixels.length);
- }
-
- byte[] encodedBlock;
- boolean hasChanged = false;
-
- /** Seems that this thing isn't working properly.
- * The blocks only gets sent after forceUpdate. (ralam Oct 29, 2009)
- */
- if (!checksumSame(pixelsCopy)) {
- //if (!checksumSame(pixelsCopy) || isKeyFrame) {
- encodedBlock = ScreenVideoEncoder.encodePixels(pixelsCopy, getWidth(), getHeight(), false, isKeyFrame);
- hasChanged = true;
- } else {
- encodedBlock = ScreenVideoEncoder.encodeBlockUnchanged();
- hasChanged = false;
- }
-
- EncodedBlockData data = new EncodedBlockData(position, hasChanged, encodedBlock, isKeyFrame);
- return data;
+ public boolean hasChanged() {
+ if (firstTime) {
+ firstTime = false;
+ return true;
+ }
+ return ! checksumSame();
}
- private boolean checksumSame(int[] pixelsCopy) {
+ public EncodedBlockData encode() {
+ byte[] encodedBlock = ScreenVideoEncoder.encodePixels(pixels, getWidth(), getHeight());
+ return new EncodedBlockData(position, encodedBlock);
+ }
+
+ private boolean checksumSame() {
long oldsum;
oldsum = checksum.getValue();
- calcChecksum(pixelsCopy);
+ calcChecksum();
return (oldsum == checksum.getValue());
}
-
- private boolean forceUpdate() {
- long now = System.currentTimeMillis();
- boolean update = ((now - lastChanged) > nextForceUpdate);
- if (update) {
- synchronized(this) {
- nextUpdate();
- lastChanged = now;
- }
- }
- return update;
- }
-
- private void nextUpdate() {
- //get the range, casting to long to avoid overflow problems
- long range = (long)MAX_DURATION - (long)MIN_DURATION + 1;
- // compute a fraction of the range, 0 <= frac < range
- long fraction = (long)(range * random.nextDouble());
- nextForceUpdate = (int)(fraction + 5000);
- }
-
- public synchronized EncodedBlockData getEncodedBlockData() {
- return encodedBlockData;
- }
-
- private synchronized void calcChecksum(int pixelsCopy[])
- {
+
+ private void calcChecksum() {
checksum.reset();
int height = getHeight();
int width = getWidth();
+
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
- if ((i * width + i) % 13 == 0)
- checksum.update(pixelsCopy[i * width + j]);
+ if ((i * width + j) % 5 == 0)
+ checksum.update(pixels[i * width + j]);
}
}
}
- public int getWidth()
- {
+ public int getWidth() {
return new Integer(dim.getWidth()).intValue();
}
- public int getHeight()
- {
+ public int getHeight() {
return new Integer(dim.getHeight()).intValue();
}
diff --git a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/blocks/BlockImp.java b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/blocks/BlockImp.java
deleted file mode 100644
index f30bc2757f..0000000000
--- a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/blocks/BlockImp.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * BigBlueButton - http://www.bigbluebutton.org
- *
- * Copyright (c) 2008-2009 by respective authors (see below). All rights reserved.
- *
- * BigBlueButton is free software; you can redistribute it and/or modify it under the
- * terms of the GNU Affero General Public License as published by the Free Software
- * Foundation; either version 3 of the License, or (at your option) any later
- * version.
- *
- * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- * PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License along
- * with BigBlueButton; if not, If not, see .
- *
- * Author: Richard Alam
- *
- * $Id: $x
- */
-package org.bigbluebutton.deskshare.client.blocks;
-
-import java.awt.Point;
-import java.awt.image.BufferedImage;
-import java.util.zip.Adler32;
-
-import org.bigbluebutton.deskshare.common.PixelExtractException;
-import org.bigbluebutton.deskshare.common.ScreenVideoEncoder;
-import org.bigbluebutton.deskshare.common.Dimension;
-
-public final class BlockImp implements IBlock {
- private final Adler32 checksum;
- private final Dimension dim;
- private final int position;
- private final Point location;
-
- private boolean isKeyFrame = false;
- private byte[] encodedBlock;
- private int[] pixels;
-
- private boolean encoded = false;
-
- BlockImp(Dimension dim, int position, Point location) {
- checksum = new Adler32();
- this.dim = dim;
- this.position = position;
- this.location = location;
- }
-
- public synchronized void updateBlock(BufferedImage capturedScreen, boolean isKeyFrame)
- {
- this.isKeyFrame = isKeyFrame;
-
- try {
- pixels = ScreenVideoEncoder.getPixels(capturedScreen, getX(), getY(), getWidth(), getHeight());
- } catch (PixelExtractException e) {
- System.out.println(e.toString());
- encodedBlock = ScreenVideoEncoder.encodeBlockUnchanged();
- }
- }
-
- public synchronized byte[] encode() {
- long oldsum;
- oldsum = checksum.getValue();
- calcChecksum(pixels);
-
- if ((oldsum == checksum.getValue()) && !isKeyFrame) {
- encodedBlock = ScreenVideoEncoder.encodeBlockUnchanged();
- }
- else {
- encodedBlock = ScreenVideoEncoder.encodePixels(pixels, getWidth(), getHeight(), false, isKeyFrame);
- }
- return encodedBlock;
- }
-
- public byte[] getEncodedBlock() {
- return encodedBlock;
- }
-
- private synchronized void calcChecksum(int pixels[])
- {
- checksum.reset();
- int height = getHeight();
- int width = getWidth();
- for (int i = 0; i < height; i++) {
- for (int j = 0; j < width; j++) {
- if ((i * width + i) % 13 == 0)
- checksum.update(pixels[i * width + j]);
- }
- }
- }
-
- public synchronized boolean isKeyFrame() {
- return isKeyFrame;
- }
-
- public synchronized boolean hasChanged() {
- long oldsum;
- oldsum = checksum.getValue();
- calcChecksum(pixels);
-
- return ((oldsum == checksum.getValue()) && !isKeyFrame);
- }
-
- public int getWidth()
- {
- return new Integer(dim.getWidth()).intValue();
- }
-
- public int getHeight()
- {
- return new Integer(dim.getHeight()).intValue();
- }
-
- public int getPosition() {
- return new Integer(position).intValue();
- }
-
- public int getX() {
- return new Integer(location.x).intValue();
- }
-
- public int getY() {
- return new Integer(location.y).intValue();
- }
-
- Dimension getDimension() {
- return new Dimension(dim.getWidth(), dim.getHeight());
- }
-
- Point getLocation() {
- return new Point(location.x, location.y);
- }
-}
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 4866034b53..1c1a20bd68 100644
--- 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
@@ -23,18 +23,11 @@ package org.bigbluebutton.deskshare.client.blocks;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-import org.bigbluebutton.deskshare.client.encoder.BlockEncodeException;
-import org.bigbluebutton.deskshare.client.encoder.ScreenVideoBlockEncoder;
-import org.bigbluebutton.deskshare.common.ScreenVideoEncoder;
import org.bigbluebutton.deskshare.common.Dimension;
+import org.bigbluebutton.deskshare.client.net.EncodedBlockData;
public class BlockManager {
private final Map blocksMap;
@@ -48,12 +41,9 @@ public class BlockManager {
private ByteArrayOutputStream encodedPixelStream = new ByteArrayOutputStream();
private Dimension screenDim, blockDim;
-// private ScreenVideoBlockEncoder encoder;
-
public BlockManager() {
blocksMap = new HashMap();
unmodifiableBlocksMap = Collections.unmodifiableMap(blocksMap);
- // encoder = new ScreenVideoBlockEncoder();
}
public void initialize(Dimension screen, Dimension tile) {
@@ -72,62 +62,24 @@ public class BlockManager {
}
}
- public void processCapturedScreen(BufferedImage capturedScreen, boolean isKeyFrame)
- {
+ public void processCapturedScreen(BufferedImage capturedScreen) {
long start = System.currentTimeMillis();
-// Block[] blocks = new Block[numRows * numColumns];
- int index = 0;
int numberOfBlocks = numColumns * numRows;
for (int position = 1; position <= numberOfBlocks; position++) {
Block block = blocksMap.get(new Integer(position));
- block.updateBlock(capturedScreen, isKeyFrame);
-
-
-// blocks[index++] = block;
+ block.updateBlock(capturedScreen);
+ if (block.hasChanged()) {
+ System.out.println("Block " + block.getPosition() + " has changed.");
+ notifyChangedBlockListener(block.encode());
+ }
}
- long qEncode = System.currentTimeMillis();
-// System.out.println("Grabbing pixels for blocks[" + numberOfBlocks + "] took " + (qEncode-start) + " ms.");
-
-// try {
-// encoder.encode(blocks);
-// sendEncodedData(isKeyFrame);
-// } catch (BlockEncodeException e) {
-// e.printStackTrace();
-// }
- notifyChangedTilesListener(null, isKeyFrame);
long end = System.currentTimeMillis();
System.out.println("ProcessCapturedScreen took " + (end-start) + " ms.");
}
-/*
- private void sendEncodedData(boolean isKeyFrame) {
- long start = System.currentTimeMillis();
- encodedPixelStream.reset();
- byte[] encodedDim = ScreenVideoEncoder.encodeBlockDimensionsAndGridSize(blockDim.getWidth(), screenDim.getWidth(), blockDim.getHeight(), screenDim.getHeight());
- byte videoDataHeader = ScreenVideoEncoder.encodeFlvVideoDataHeader(isKeyFrame);
- try {
- encodedPixelStream.write(videoDataHeader);
- encodedPixelStream.write(encodedDim);
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- int numberOfBlocks = numColumns * numRows;
- for (int position = 1; position <= numberOfBlocks; position++) {
- Block block = blocksMap.get(new Integer(position));
- byte[] data = block.getEncodedBlock();
- encodedPixelStream.write(data, 0, data.length);
- }
-
-// System.out.println("Encoded data length = " + encodedPixelStream.size());
- notifyChangedTilesListener(encodedPixelStream, isKeyFrame);
- long end = System.currentTimeMillis();
- System.out.println("Sending encoded data took " + (end-start) + " ms.");
- }
-*/
- private void notifyChangedTilesListener(ByteArrayOutputStream encodedPixelStream, boolean isKeyFrame) {
- listeners.onChangedTiles(encodedPixelStream, isKeyFrame);
+
+ private void notifyChangedBlockListener(EncodedBlockData encodedData) {
+ listeners.onChangedBlock(encodedData);
}
@@ -135,9 +87,7 @@ public class BlockManager {
listeners = listener;
}
-
public void removeListener(ChangedBlocksListener listener) {
- //listeners.remove(listener);
listeners = null;
}
@@ -145,13 +95,11 @@ public class BlockManager {
return (Block) blocksMap.get(Integer.valueOf(position));
}
- public int getRowCount()
- {
+ public int getRowCount() {
return numRows;
}
- public int getColumnCount()
- {
+ public int getColumnCount() {
return numColumns;
}
@@ -162,11 +110,4 @@ public class BlockManager {
public Dimension getBlockDim() {
return blockDim;
}
-
- /*
- * Returns a read-only "live" view of the blocks;
- */
- public Map getBlocks() {
- return unmodifiableBlocksMap;
- }
}
diff --git a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/blocks/ChangedBlocksListener.java b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/blocks/ChangedBlocksListener.java
index c2d130e69b..1157ea231d 100644
--- a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/blocks/ChangedBlocksListener.java
+++ b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/blocks/ChangedBlocksListener.java
@@ -21,9 +21,8 @@
*/
package org.bigbluebutton.deskshare.client.blocks;
-import java.io.ByteArrayOutputStream;
+import org.bigbluebutton.deskshare.client.net.EncodedBlockData;
public interface ChangedBlocksListener {
-
- public void onChangedTiles(ByteArrayOutputStream pixelData, boolean isKeyFrame);
+ public void onChangedBlock(EncodedBlockData encodedData);
}
diff --git a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/EncodedBlockData.java b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/EncodedBlockData.java
index b30a9cffb0..69871c2fd4 100644
--- a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/EncodedBlockData.java
+++ b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/net/EncodedBlockData.java
@@ -22,18 +22,13 @@
package org.bigbluebutton.deskshare.client.net;
public class EncodedBlockData {
-
private final byte[] videoData;
- private final boolean keyFrame;
private final int position;
private final long timestamp;
- private final boolean hasChanged;
- public EncodedBlockData(int position, boolean hasChanged, byte[] videoData, boolean keyFrame) {
+ public EncodedBlockData(int position, byte[] videoData) {
this.position = position;
this.videoData = videoData;
- this.keyFrame = keyFrame;
- this.hasChanged = hasChanged;
timestamp = System.currentTimeMillis();
}
@@ -44,16 +39,8 @@ public class EncodedBlockData {
public byte[] getVideoData() {
return videoData;
}
-
- public boolean isKeyFrame() {
- return keyFrame;
- }
public long getTimestamp() {
return timestamp;
}
-
- public boolean hasChanged() {
- return hasChanged;
- }
}
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 07ccfac63a..889ecdb9ea 100644
--- 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
@@ -40,12 +40,17 @@ public class NetworkHttpStreamSender implements Runnable {
private URL url;
URLConnection conn;
private String room;
+ private Dimension screenDim;
+ private Dimension blockDim;
private final NextBlockRetriever retriever;
private volatile boolean processBlocks = false;
- public NetworkHttpStreamSender(NextBlockRetriever retriever) {
+ public NetworkHttpStreamSender(NextBlockRetriever retriever, String room, Dimension screenDim, Dimension blockDim) {
this.retriever = retriever;
+ this.room = room;
+ this.screenDim = screenDim;
+ this.blockDim = blockDim;
}
public void connect(String host) throws ConnectionException {
@@ -74,11 +79,10 @@ public class NetworkHttpStreamSender implements Runnable {
}
}
- public void sendStartStreamMessage(String room, Dimension screen, Dimension block) {
- this.room = room;
+ public void sendStartStreamMessage() {
try {
openConnection();
- sendCaptureStartEvent(screen, block);
+ sendCaptureStartEvent(screenDim, blockDim);
} catch (ConnectionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
@@ -142,13 +146,15 @@ public class NetworkHttpStreamSender implements Runnable {
processBlocks = true;
while (processBlocks) {
- Block block = retriever.fetchNextBlockToSend();
- EncodedBlockData ebd = block.encode();
- if (ebd.hasChanged()) {
- BlockVideoData bv = new BlockVideoData(room, ebd.getPosition(), ebd.getVideoData(), ebd.isKeyFrame());
-
- sendBlockData(bv);
- }
+ EncodedBlockData block;
+ try {
+ block = retriever.fetchNextBlockToSend();
+ BlockVideoData bv = new BlockVideoData(room, block.getPosition(), block.getVideoData(), false);
+ sendBlockData(bv);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ 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 fcb863eb34..4cf55b9044 100644
--- 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
@@ -26,8 +26,6 @@ import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
-
-import org.bigbluebutton.deskshare.client.blocks.Block;
import org.bigbluebutton.deskshare.common.Dimension;
public class NetworkSocketStreamSender implements Runnable {
@@ -42,8 +40,11 @@ public class NetworkSocketStreamSender implements Runnable {
private final NextBlockRetriever retriever;
private volatile boolean processBlocks = false;
- public NetworkSocketStreamSender(NextBlockRetriever retriever) {
+ public NetworkSocketStreamSender(NextBlockRetriever retriever, String room, Dimension screenDim, Dimension blockDim) {
this.retriever = retriever;
+ this.room = room;
+ this.screenDim = screenDim;
+ this.blockDim = blockDim;
}
public void connect(String host) throws ConnectionException {
@@ -60,10 +61,7 @@ public class NetworkSocketStreamSender implements Runnable {
}
}
- public void sendStartStreamMessage(String room, Dimension screen, Dimension block) {
- this.room = room;
- screenDim = screen;
- blockDim = block;
+ public void sendStartStreamMessage() {
try {
ByteArrayOutputStream dataToSend = new ByteArrayOutputStream();
dataToSend.reset();
@@ -121,12 +119,16 @@ public class NetworkSocketStreamSender implements Runnable {
public void run() {
processBlocks = true;
while (processBlocks) {
- Block block = retriever.fetchNextBlockToSend();
- EncodedBlockData ebd = block.encode();
- if (ebd.hasChanged()) {
- BlockVideoData bv = new BlockVideoData(room, ebd.getPosition(), ebd.getVideoData(), ebd.isKeyFrame());
+ EncodedBlockData block;
+ try {
+ block = retriever.fetchNextBlockToSend();
+ BlockVideoData bv = new BlockVideoData(room, block.getPosition(), block.getVideoData(), false /* should remove later */);
+ System.out.println("Sending block " + block.getPosition());
sendBlock(bv);
- }
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
}
}
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 9b09b838d7..1d26bef8d2 100644
--- 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
@@ -21,36 +21,33 @@
*/
package org.bigbluebutton.deskshare.client.net;
-import java.util.Map;
-
+import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-import net.jcip.annotations.GuardedBy;
+import java.util.concurrent.LinkedBlockingQueue;
import net.jcip.annotations.ThreadSafe;
-
-import org.bigbluebutton.deskshare.client.blocks.Block;
-import org.bigbluebutton.deskshare.client.blocks.BlockManager;
+import org.bigbluebutton.deskshare.common.Dimension;
@ThreadSafe
public class NetworkStreamSender implements NextBlockRetriever {
- private BlockManager blockManager;
- private ExecutorService executor;
-
- @GuardedBy("this") private int nextBlockToSend = 1;
- private final Map blocksMap;
+ private ExecutorService executor;
+ private final BlockingQueue blockDataQ = new LinkedBlockingQueue();
+
private final int numThreads;
private final String host;
private final String room;
private NetworkSocketStreamSender[] senders;
- private NetworkHttpStreamSender httpSender;
+ private NetworkHttpStreamSender[] httpSenders;
private boolean tunneling = false;
private int numRunningThreads = 0;
-
- public NetworkStreamSender(BlockManager blockManager, String host, String room) {
- this.blockManager = blockManager;
- blocksMap = blockManager.getBlocks();
+ private Dimension screenDim;
+ private Dimension blockDim;
+
+ public NetworkStreamSender(String host, String room, Dimension screenDim, Dimension blockDim) {
this.host = host;
this.room = room;
+ this.screenDim = screenDim;
+ this.blockDim = blockDim;
numThreads = Runtime.getRuntime().availableProcessors();
System.out.println("Starting up " + numThreads + " sender threads.");
@@ -73,6 +70,7 @@ public class NetworkStreamSender implements NextBlockRetriever {
System.out.println("Trying http tunneling");
if (tryHttpTunneling()) {
tunneling = true;
+ httpSenders = new NetworkHttpStreamSender[numThreads];
return true;
}
} else {
@@ -83,28 +81,32 @@ public class NetworkStreamSender implements NextBlockRetriever {
}
private void createSender(int i) throws ConnectionException {
- senders[i] = new NetworkSocketStreamSender(this);
+ senders[i] = new NetworkSocketStreamSender(this, room, screenDim, blockDim);
senders[i].connect(host);
}
+ public void send(EncodedBlockData data) {
+ blockDataQ.offer(data);
+ }
+
public void start() {
- if (tunneling) {
- httpSender.sendStartStreamMessage(room, blockManager.getScreenDim(), blockManager.getBlockDim());
- executor.execute(httpSender);
- } else {
- for (int i = 0; i < numRunningThreads; i++) {
- senders[i].sendStartStreamMessage(room, blockManager.getScreenDim(), blockManager.getBlockDim());
- executor.execute(senders[i]);
- }
+ for (int i = 0; i < numRunningThreads; i++) {
+ if (tunneling) {
+ httpSenders[i].sendStartStreamMessage();
+ executor.execute(httpSenders[i]);
+ } else {
+ senders[i].sendStartStreamMessage();
+ executor.execute(senders[i]);
+ }
}
}
public void stop() throws ConnectionException {
System.out.println("Stopping network sender");
- if (tunneling) {
- httpSender.disconnect();
- } else {
- for (int i = 0; i < numRunningThreads; i++) {
+ for (int i = 0; i < numRunningThreads; i++) {
+ if (tunneling) {
+ httpSenders[i].disconnect();
+ } else {
senders[i].disconnect();
}
}
@@ -113,7 +115,7 @@ public class NetworkStreamSender implements NextBlockRetriever {
}
private boolean tryHttpTunneling() {
- httpSender = new NetworkHttpStreamSender(this);
+ NetworkHttpStreamSender httpSender = new NetworkHttpStreamSender(this, room, screenDim, blockDim);
try {
httpSender.connect(host);
return true;
@@ -123,14 +125,7 @@ public class NetworkStreamSender implements NextBlockRetriever {
return false;
}
- public Block fetchNextBlockToSend() {
- synchronized(this) {
- //Block block = blocksMap.get(new Integer(nextBlockToSend));
- Block block = blockManager.getBlock(nextBlockToSend);
-// System.out.println("Fetched block " + nextBlockToSend);
- nextBlockToSend++;
- if (nextBlockToSend > blocksMap.size()) nextBlockToSend = 1;
- return block;
- }
+ public EncodedBlockData fetchNextBlockToSend() throws InterruptedException {
+ return (EncodedBlockData) blockDataQ.take();
}
}
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 3894e2b141..35eca6686d 100644
--- 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
@@ -21,9 +21,6 @@
*/
package org.bigbluebutton.deskshare.client.net;
-import org.bigbluebutton.deskshare.client.blocks.Block;
-
public interface NextBlockRetriever {
-
- public Block fetchNextBlockToSend();
+ public EncodedBlockData fetchNextBlockToSend() throws InterruptedException;
}
diff --git a/deskshare/common/src/main/java/org/bigbluebutton/deskshare/common/ScreenVideoEncoder.java b/deskshare/common/src/main/java/org/bigbluebutton/deskshare/common/ScreenVideoEncoder.java
index 5956ccccf8..4ae439636d 100644
--- a/deskshare/common/src/main/java/org/bigbluebutton/deskshare/common/ScreenVideoEncoder.java
+++ b/deskshare/common/src/main/java/org/bigbluebutton/deskshare/common/ScreenVideoEncoder.java
@@ -84,11 +84,11 @@ public final class ScreenVideoEncoder {
return pixels;
}
- public static byte[] encodePixels(int pixels[], int width, int height, boolean isRedTile, boolean isKeyFrame) {
+ public static byte[] encodePixels(int pixels[], int width, int height) {
changePixelScanFromBottomLeftToTopRight(pixels, width, height);
- byte[] bgrPixels = convertFromRGBtoBGR(pixels, isRedTile, isKeyFrame);
+ byte[] bgrPixels = convertFromRGBtoBGR(pixels);
byte[] compressedPixels = compressUsingZlib(bgrPixels);
@@ -165,7 +165,7 @@ public final class ScreenVideoEncoder {
* @param pixels
* @return pixels in BGR order
*/
- private static byte[] convertFromRGBtoBGR(int[] pixels, boolean isRedTile, boolean isKeyFrame) {
+ private static byte[] convertFromRGBtoBGR(int[] pixels) {
long start = System.currentTimeMillis();
byte[] rgbPixels = new byte[pixels.length * 3];
int position = 0;
@@ -175,21 +175,10 @@ public final class ScreenVideoEncoder {
byte green = (byte) ((pixels[i] >> 8) & 0xff);
byte blue = (byte) (pixels[i] & 0xff);
- if (isRedTile && !isKeyFrame) {
- // Sequence should be BGR
- rgbPixels[position++] = 0;
- rgbPixels[position++] = 0;
- rgbPixels[position++] = (byte) 0xff;
- } else if (isRedTile && isKeyFrame) {
- rgbPixels[position++] = (byte) 0xff;
- rgbPixels[position++] = 0;
- rgbPixels[position++] = 0;
- } else {
- // Sequence should be BGR
- rgbPixels[position++] = blue;
- rgbPixels[position++] = green;
- rgbPixels[position++] = red;
- }
+ // Sequence should be BGR
+ rgbPixels[position++] = blue;
+ rgbPixels[position++] = green;
+ rgbPixels[position++] = red;
}
long end = System.currentTimeMillis();