Author: solomax
Date: Thu Mar 29 08:14:45 2012
New Revision: 1306748
URL: http://svn.apache.org/viewvc?rev=1306748&view=rev
Log:
Screen sharing client cleaned up from 'borrowed' code; code cleanup
Added:
incubator/openmeetings/trunk/singlewebapp/WebContent/red5-screenshare/logback.xml
incubator/openmeetings/trunk/singlewebapp/src/org/red5/screen/webstart/IScreenEncoder.java
incubator/openmeetings/trunk/singlewebapp/src/org/red5/screen/webstart/ScreenV1Encoder.java
Modified:
incubator/openmeetings/trunk/singlewebapp/build.xml
incubator/openmeetings/trunk/singlewebapp/src/org/openmeetings/app/installation/ImportInitvalues.java
incubator/openmeetings/trunk/singlewebapp/src/org/red5/screen/webstart/CommonScreenShare.java
incubator/openmeetings/trunk/singlewebapp/src/org/red5/screen/webstart/gui/VirtualScreen.java
incubator/openmeetings/trunk/singlewebapp/src/org/red5/screen/webstart/gui/VirtualScreenBean.java
Added:
incubator/openmeetings/trunk/singlewebapp/WebContent/red5-screenshare/logback.xml
URL:
http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/WebContent/red5-screenshare/logback.xml?rev=1306748&view=auto
==============================================================================
---
incubator/openmeetings/trunk/singlewebapp/WebContent/red5-screenshare/logback.xml
(added)
+++
incubator/openmeetings/trunk/singlewebapp/WebContent/red5-screenshare/logback.xml
Thu Mar 29 08:14:45 2012
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+ <!-- Uncomment if you are using the logback plugin for eclipse
+ <consolePlugin/>
+ -->
+ <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <pattern>[%p] [%thread] %logger - %msg%n</pattern>
+ </encoder>
+ </appender>
+ <root>
+ <level value="WARN" />
+ <appender-ref ref="CONSOLE" />
+ </root>
+ <!-- Red5 -->
+ <logger name="org.red5.server.Launcher">
+ <level value="INFO" />
+ </logger>
+ <logger name="org.red5.io">
+ <level value="INFO" />
+ </logger>
+ <logger name="org.red5.logging.DerbyLogInterceptor">
+ <level value="WARN" />
+ </logger>
+ <logger name="org.red5.server">
+ <level value="WARN" />
+ </logger>
+ <logger name="org.red5.server.Client">
+ <level value="INFO" />
+ </logger>
+ <logger name="org.red5.server.api.stream.support">
+ <level value="INFO" />
+ </logger>
+ <logger name="org.red5.server.cache">
+ <level value="WARN" />
+ </logger>
+ <logger name="org.red5.server.jmx">
+ <level value="WARN" />
+ </logger>
+ <logger name="org.red5.server.messaging.InMemoryPushPushPipe">
+ <level value="INFO" />
+ </logger>
+ <logger name="org.red5.server.net">
+ <level value="INFO" />
+ </logger>
+ <logger name="org.red5.server.net.rtmpt.RTMPTServlet">
+ <level value="WARN" />
+ </logger>
+ <logger name="org.red5.server.net.servlet">
+ <level value="WARN" />
+ </logger>
+ <logger name="org.red5.server.net.proxy">
+ <level value="INFO" />
+ </logger>
+ <logger name="org.red5.server.net.remoting">
+ <level value="WARN" />
+ </logger>
+ <logger name="org.red5.server.net.rtmp">
+ <level value="WARN" />
+ </logger>
+ <logger name="org.red5.server.net.rtmp.BaseRTMPHandler">
+ <level value="WARN" />
+ </logger>
+ <logger name="org.red5.server.net.rtmp.RTMPMinaIoHandler">
+ <level value="WARN" />
+ </logger>
+ <logger name="org.red5.server.net.rtmp.status">
+ <level value="INFO" />
+ </logger>
+ <logger name="org.red5.server.net.rtmpt">
+ <level value="WARN" />
+ </logger>
+ <logger name="org.red5.server.persistence">
+ <level value="WARN" />
+ </logger>
+ <logger name="org.red5.server.script">
+ <level value="WARN" />
+ </logger>
+ <logger name="org.red5.server.service">
+ <level value="INFO" />
+ </logger>
+ <logger name="org.red5.server.so">
+ <level value="WARN" />
+ </logger>
+ <logger name="org.red5.server.stream">
+ <level value="INFO" />
+ </logger>
+ <logger name="org.red5.server.stream.consumer">
+ <level value="WARN" />
+ </logger>
+ <logger name="org.red5.server.net.mrtmp">
+ <level value="WARN" />
+ </logger>
+ <!-- Mina -->
+ <logger name="org.apache.mina">
+ <level value="WARN" />
+ </logger>
+ <logger name="org.apache.mina.filter">
+ <level value="WARN" />
+ </logger>
+ <logger name="org.red5.server.adapter.MultiThreadedApplicationAdapter" >
+ <level value="INFO"/>
+ </logger>
+ <!-- Apache commons -->
+ <logger name="org.apache.commons">
+ <level value="WARN" />
+ </logger>
+ <logger name="httpclient">
+ <level value="WARN" />
+ </logger>
+ <!-- Apache catalina / tomcat -->
+ <logger name="org.red5.server.tomcat">
+ <level value="INFO" />
+ </logger>
+ <logger name="org.apache.catalina">
+ <level value="WARN" />
+ </logger>
+ <logger name="org.apache.jasper">
+ <level value="INFO" />
+ </logger>
+ <logger name="org.apache.tomcat">
+ <level value="INFO" />
+ </logger>
+ <logger name="org.apache.tomcat.util.net">
+ <level value="WARN" />
+ </logger>
+ <logger name="org.apache.coyote.http11">
+ <level value="INFO" />
+ </logger>
+ <!-- Spring -->
+ <logger name="org.springframework">
+ <level value="INFO" />
+ </logger>
+ <logger name="org.springframework.beans.factory">
+ <level value="INFO" />
+ </logger>
+ <logger name="org.springframework.beans.factory.xml">
+ <level value="WARN" />
+ </logger>
+ <logger name="org.springframework.ui.context.support">
+ <level value="WARN" />
+ </logger>
+ <logger name="org.springframework.web.context">
+ <level value="INFO" />
+ </logger>
+ <logger name="org.springframework.web.context.support">
+ <level value="WARN" />
+ </logger>
+ <logger name="org.quartz">
+ <level value="WARN" />
+ </logger>
+ <!-- Caching -->
+ <logger name="net.sf.ehcache">
+ <level value="INFO" />
+ </logger>
+ <logger name="ch.qos">
+ <level value="WARN" />
+ </logger>
+</configuration>
Modified: incubator/openmeetings/trunk/singlewebapp/build.xml
URL:
http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/build.xml?rev=1306748&r1=1306747&r2=1306748&view=diff
==============================================================================
--- incubator/openmeetings/trunk/singlewebapp/build.xml (original)
+++ incubator/openmeetings/trunk/singlewebapp/build.xml Thu Mar 29 08:14:45 2012
@@ -35,7 +35,7 @@
<property name="mainlibs.lib.dir" value="${project.lib.dir}/mainlibs" />
<property name="om.lib.dir" value="${project.lib.dir}/om" />
<property name="anakia.lib.dir" value="${project.lib.dir}/anakia" />
- <property name="red5-screenshare.images"
value="${basedir}/WebContent/red5-screenshare" />
+ <property name="red5-screenshare.resources"
value="${basedir}/WebContent/red5-screenshare" />
<property name="junit.lib.dir" value="${project.lib.dir}/junit" />
<property name="rat.lib.dir" value="${project.lib.dir}/rat" />
<property name="dtd-generator.lib.dir"
value="${project.lib.dir}/dtd-generator" />
@@ -294,7 +294,7 @@
<fileset dir="${main.out.dir}">
<include name="org/red5/screen/**" />
</fileset>
- <fileset file="${red5.lib}/conf/logback.xml"/>
+ <fileset
file="${red5-screenshare.resources}/logback.xml"/>
<manifest>
<attribute name="Built-By" value="OpenMeetings
- http://openmeetings.googlecode.com" />
<attribute name="Built-On"
value="${build.TODAY}" />
@@ -321,7 +321,7 @@
</dname>
</genkey>
<copy todir="${screenshare.out.dir}" filtering="true">
- <fileset dir="${red5-screenshare.images}" />
+ <fileset dir="${red5-screenshare.resources}"
includes="*.jpg"/>
<fileset dir="${red5.server.lib}"
includes="commons-codec*.jar" />
<fileset dir="${red5.server.lib}"
includes="httpclient*.jar" />
<fileset dir="${red5.server.lib}"
includes="httpcore*.jar" />
Modified:
incubator/openmeetings/trunk/singlewebapp/src/org/openmeetings/app/installation/ImportInitvalues.java
URL:
http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/openmeetings/app/installation/ImportInitvalues.java?rev=1306748&r1=1306747&r2=1306748&view=diff
==============================================================================
---
incubator/openmeetings/trunk/singlewebapp/src/org/openmeetings/app/installation/ImportInitvalues.java
(original)
+++
incubator/openmeetings/trunk/singlewebapp/src/org/openmeetings/app/installation/ImportInitvalues.java
Thu Mar 29 08:14:45 2012
@@ -479,8 +479,9 @@ public class ImportInitvalues {
cfgManagement.addConfByKey(3, "show.facebook.login", "" + 0,
null,
"Show Facebook Login");
- cfgManagement.addConfByKey(3, "default.quality.screensharing",
"0",
- null, "Default selection in ScreenSharing
Quality");
+ cfgManagement.addConfByKey(3, "default.quality.screensharing",
"1",
+ null,
+ "Default selection in
ScreenSharing Quality:\n 0 - bigger frame rate, no resize\n 1 - no resize\n 2 -
size == 1/2 of selected area\n 3 - size == 3/8 of selected area");
cfgManagement.addConfByKey(3, "default.dashboard.tab", "0",
null,
"Default selection in Dashboard tabs as
tab-index-id");
Modified:
incubator/openmeetings/trunk/singlewebapp/src/org/red5/screen/webstart/CommonScreenShare.java
URL:
http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/red5/screen/webstart/CommonScreenShare.java?rev=1306748&r1=1306747&r2=1306748&view=diff
==============================================================================
---
incubator/openmeetings/trunk/singlewebapp/src/org/red5/screen/webstart/CommonScreenShare.java
(original)
+++
incubator/openmeetings/trunk/singlewebapp/src/org/red5/screen/webstart/CommonScreenShare.java
Thu Mar 29 08:14:45 2012
@@ -1,13 +1,11 @@
package org.red5.screen.webstart;
import java.awt.Color;
-import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.PointerInfo;
import java.awt.Rectangle;
-import java.awt.RenderingHints;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
@@ -22,14 +20,10 @@ import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
-import java.awt.image.DataBuffer;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.io.OutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
-import java.util.zip.DeflaterOutputStream;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
@@ -45,6 +39,7 @@ import org.red5.io.ITagWriter;
import org.red5.io.utils.ObjectMap;
import org.red5.screen.webstart.gui.VirtualScreen;
import org.red5.screen.webstart.gui.VirtualScreenBean;
+import org.red5.screen.webstart.gui.VirtualScreenBean.ScreenQuality;
import org.red5.server.api.event.IEvent;
import org.red5.server.api.service.IPendingServiceCall;
import org.red5.server.net.rtmp.Channel;
@@ -117,7 +112,7 @@ public class CommonScreenShare {
public String host = "btg199251";
public String app = "oflaDemo";
public int port = 1935;
- public int defaultQualityScreensharing = 0;
+ public int defaultQualityScreensharing = 1;
public Long organization_id = 0L;
public Long user_id = null;
@@ -157,11 +152,7 @@ public class CommonScreenShare {
public String label1092 = "Medium Quality -";
public String label1093 = "Low Quality -";
- public Float imgQuality = new Float(0.40);
-
- // public Float scaleFactor = 1F;
- public float Ampl_factor = 1.3f;
-
+ public float Ampl_factor = 1f;
public boolean isConnected = false;
public Map<Integer, Boolean> currentPressedKeys = new HashMap<Integer,
Boolean>();
@@ -179,6 +170,9 @@ public class CommonScreenShare {
public void main(String[] args) {
try {
if (args.length == 9) {
+ for (String arg : args) {
+ logger.debug("arg: " + arg);
+ }
host = args[0];
app = args[1];
@@ -308,13 +302,6 @@ public class CommonScreenShare {
// *****
// Text Recording
textAreaHeaderRecording = new JLabel();
-
- // FIXME: Set Font to bold
- // textAreaHeaderRecording.setB
- // Font f = textAreaHeaderRecording.getFont();
- //
textAreaHeaderRecording.setFont(f.deriveFont(f.getStyle() ^
- // Font.BOLD));
-
textAreaHeaderRecording.setText(this.label869);
contentPane.add(textAreaHeaderRecording);
textAreaHeaderRecording.setBounds(10, 340, 480, 24);
@@ -421,9 +408,6 @@ public class CommonScreenShare {
PointerInfo a = MouseInfo.getPointerInfo();
Point mouseP = a.getLocation();
- // Integer x =
Long.valueOf(Math.round(mouseP.getX())).intValue();
- // Integer y =
Long.valueOf(Math.round(mouseP.getY())).intValue();
-
Float scaleFactor =
Float.valueOf(VirtualScreenBean.vScreenResizeX)
/
Float.valueOf(VirtualScreenBean.vScreenSpinnerWidth);
@@ -643,18 +627,6 @@ public class CommonScreenShare {
// VirtualScreenBean
- // Integer x = Math.round ( ( (
- //
Float.valueOf(returnMap.get("x").toString()).floatValue()
- // *VirtualScreenBean.vScreenResizeX
- // )/VirtualScreenBean.vScreenSpinnerWidth) /
Ampl_factor) ;
- // Integer y = Math.round ( ( (
- //
Float.valueOf(returnMap.get("y").toString()).floatValue()
- // *VirtualScreenBean.vScreenResizeY
- // )/VirtualScreenBean.vScreenSpinnerHeight)/
Ampl_factor) ;
- //
-
- // logger.debug("x 1 "+returnMap.get("x"));
-
Float scaleFactor = Float
.valueOf(VirtualScreenBean.vScreenSpinnerWidth)
/
Float.valueOf(VirtualScreenBean.vScreenResizeX);
@@ -951,13 +923,10 @@ public class CommonScreenShare {
ex.printStackTrace();
}
return "";
- // clippy.setContents( clippysContent ,null); //zur�cksetzen
vom alten
- // Kontext
}
private void pressSpecialSign(String charValue, Robot instance) {
Clipboard clippy =
Toolkit.getDefaultToolkit().getSystemClipboard();
- // Transferable clippysContent = clippy.getContents( null );
try {
Transferable transferableText = new
StringSelection(charValue);
@@ -1042,7 +1011,7 @@ public class CommonScreenShare {
logger.debug("The Stream was already
started ");
}
- if (returnMap.get("modus") != null) {
+ if (returnMap != null && returnMap.get("modus")
!= null) {
if (returnMap.get("modus").toString()
.equals("startStreaming")) {
this.startButton.setEnabled(false);
@@ -1076,12 +1045,7 @@ public class CommonScreenShare {
logger.debug("setup capture thread
vScreenSpinnerHeight "
+
VirtualScreenBean.vScreenSpinnerHeight);
- capture = new
CaptureScreen(VirtualScreenBean.vScreenSpinnerX,
-
VirtualScreenBean.vScreenSpinnerY,
-
VirtualScreenBean.vScreenSpinnerWidth,
-
VirtualScreenBean.vScreenSpinnerHeight,
-
VirtualScreenBean.vScreenResizeX,
-
VirtualScreenBean.vScreenResizeY);
+ capture = new CaptureScreen();
if (thread == null) {
thread = new Thread(capture);
@@ -1154,11 +1118,6 @@ public class CommonScreenShare {
kt++;
- // if ( kt < 10 ) {
- // logger.debug( "+++ " + videoData );
- // System.out.println( "+++ " + videoData);
- // }
-
RTMPMessage rtmpMsg = RTMPMessage.build(videoData);
instance.publishStreamData(publishStreamId, rtmpMsg);
}
@@ -1170,14 +1129,6 @@ public class CommonScreenShare {
//
------------------------------------------------------------------------
private final class CaptureScreen extends Object implements Runnable {
- private volatile int x = 0;
- private volatile int y = 0;
- private volatile int resizeX;
- private volatile int resizeY;
-
- private volatile int width = resizeX; // 320
- private volatile int height = resizeY; // 240
-
private int timeBetweenFrames = 1000; // frameRate
private volatile long timestamp = 0;
@@ -1185,7 +1136,7 @@ public class CommonScreenShare {
private volatile boolean active = true;
@SuppressWarnings("unused")
private volatile boolean stopped = false;
- private byte[] previousItems = null;
+ private IScreenEncoder se;
//
------------------------------------------------------------------------
//
@@ -1193,27 +1144,9 @@ public class CommonScreenShare {
//
//
------------------------------------------------------------------------
- public CaptureScreen(final int x, final int y, final int width,
- final int height, int resizeX, int resizeY) {
-
- this.x = x;
- this.y = y;
- this.width = width;
- this.height = height;
- this.resizeX = resizeX;
- this.resizeY = resizeY;
-
- if (VirtualScreenBean.vScreenScaleFactor
- .equals(label1090)) {
- timeBetweenFrames = 100;
- } else {
- timeBetweenFrames = 1000;
- }
-
- logger.debug("CaptureScreen: x=" + x + ", y=" + y + ",
w=" + width
- + ", h=" + height + ",resizeX=" +
resizeX + " resizeY= "
- + resizeY);
-
+ public CaptureScreen() {
+ timeBetweenFrames = (VirtualScreenBean.screenQuality ==
ScreenQuality.VeryHigh) ? 100 : 1000;
+ se = new ScreenV1Encoder();
}
//
------------------------------------------------------------------------
@@ -1234,7 +1167,7 @@ public class CommonScreenShare {
}
public void resetBuffer() {
- this.previousItems = null;
+ se.reset();
}
//
------------------------------------------------------------------------
@@ -1242,89 +1175,27 @@ public class CommonScreenShare {
// Thread loop
//
//
------------------------------------------------------------------------
-
public void run() {
- final int blockWidth = 32;
- final int blockHeight = 32;
-
- int frameCounter = 0;
-
- int orig_width = width;
- int orig_height = height;
-
try {
Robot robot = new Robot();
- this.previousItems = null;
-
while (active) {
final long ctime =
System.currentTimeMillis();
- width = orig_width;
- height = orig_height;
-
- BufferedImage image = robot
-
.createScreenCapture(new Rectangle(x, y, width,
-
height));
-
- int width_new = resizeX;
- int height_new = resizeY;
- width = resizeX;
- height = resizeY;
- // Resize to 640*480
- // Create new (blank) image of required
(scaled) size
- BufferedImage image_raw = new
BufferedImage(width_new,
- height_new,
BufferedImage.TYPE_INT_RGB);
-
- Graphics2D graphics2D =
image_raw.createGraphics();
- graphics2D.setRenderingHint(
-
RenderingHints.KEY_INTERPOLATION,
-
RenderingHints.VALUE_INTERPOLATION_BICUBIC);
- graphics2D.drawImage(image, 0, 0,
width_new, height_new,
- null);
- graphics2D.dispose();
-
- // End resize
-
- int scaledWidth = width;
- int scaledHeight = height;
-
- byte[] current = toBGR(image_raw);
- // if (scaleFactor != 1F) {
- //
- // logger.debug("Calc new Scaled
Instance ",scaleFactor);
- //
- // scaledWidth =
- //
Float.valueOf(Math.round(width*scaleFactor)).intValue();
- // scaledHeight =
- //
Float.valueOf(Math.round(height*scaleFactor)).intValue();
- //
- // Image img =
image_raw.getScaledInstance(scaledWidth,
- // scaledHeight,Image.SCALE_SMOOTH);
- //
- // BufferedImage image_scaled = new
- // BufferedImage(scaledWidth,
- //
scaledHeight,BufferedImage.TYPE_3BYTE_BGR);
- //
- // Graphics2D biContext =
image_scaled.createGraphics();
- // biContext.drawImage(img, 0, 0, null);
- // current = toBGR(image_scaled);
- // } else {
- // current = toBGR(image_raw);
- // }
+ Rectangle screen = new
Rectangle(VirtualScreenBean.vScreenSpinnerX,
+
VirtualScreenBean.vScreenSpinnerY,
+
VirtualScreenBean.vScreenSpinnerWidth,
+
VirtualScreenBean.vScreenSpinnerHeight);
+
+ BufferedImage image =
robot.createScreenCapture(screen);
try {
- // timestamp += (1000000 /
timeBetweenFrames);
timestamp += timeBetweenFrames;
- final byte[] screenBytes =
encode(current,
-
this.previousItems, blockWidth, blockHeight,
- scaledWidth,
scaledHeight);
- pushVideo(screenBytes.length,
screenBytes, timestamp);
- this.previousItems = current;
+ byte[] data = se.encode(screen,
image, new Rectangle(VirtualScreenBean.vScreenResizeX,
+
VirtualScreenBean.vScreenResizeY));
- if (++frameCounter % 100 == 0)
- this.previousItems =
null;
+ pushVideo(data.length, data,
timestamp);
} catch (Exception e) {
e.printStackTrace();
}
@@ -1339,132 +1210,5 @@ public class CommonScreenShare {
e.printStackTrace();
}
}
-
- //
------------------------------------------------------------------------
- //
- // Private
- //
- //
------------------------------------------------------------------------
-
- private byte[] toBGR(BufferedImage image) {
- final int width = image.getWidth();
- final int height = image.getHeight();
-
- byte[] buf = new byte[3 * width * height];
-
- final DataBuffer buffer =
image.getData().getDataBuffer();
-
- for (int y = 0; y < height; y++) {
- for (int x = 0; x < width; x++) {
- final int rgb = buffer.getElem(y *
width + x);
- final int offset = 3 * (y * width + x);
-
- buf[offset + 0] = (byte) (rgb & 0xFF);
- buf[offset + 1] = (byte) ((rgb >> 8) &
0xFF);
- buf[offset + 2] = (byte) ((rgb >> 16) &
0xFF);
- }
- }
-
- return buf;
- }
-
- private byte[] encode(final byte[] current, final byte[]
previous,
- final int blockWidth, final int blockHeight,
final int width,
- final int height) throws Exception {
- ByteArrayOutputStream baos = new
ByteArrayOutputStream(16 * 1024);
-
- if (previous == null) {
- baos.write(getTag(0x01, 0x03)); // keyframe
(all cells)
- } else {
- baos.write(getTag(0x02, 0x03)); // frame
(changed cells)
- }
-
- // write header
- final int wh = width + ((blockWidth / 16 - 1) << 12);
- final int hh = height + ((blockHeight / 16 - 1) << 12);
-
- writeShort(baos, wh);
- writeShort(baos, hh);
-
- // write content
- int y0 = height;
- int x0 = 0;
- int bwidth = blockWidth;
- int bheight = blockHeight;
-
- while (y0 > 0) {
- bheight = Math.min(y0, blockHeight);
- y0 -= bheight;
-
- bwidth = blockWidth;
- x0 = 0;
-
- while (x0 < width) {
- bwidth = (x0 + blockWidth > width) ?
width - x0
- : blockWidth;
-
- final boolean changed =
isChanged(current, previous, x0,
- y0, bwidth, bheight,
width, height);
-
- if (changed) {
- ByteArrayOutputStream blaos =
new ByteArrayOutputStream(
- 4 * 1024);
-
- DeflaterOutputStream dos = new
DeflaterOutputStream(
- blaos);
-
- for (int y = 0; y < bheight;
y++) {
- dos.write(current, 3 *
((y0 + bheight - y - 1)
- * width
+ x0), 3 * bwidth);
- }
-
- dos.finish();
-
- final byte[] bbuf =
blaos.toByteArray();
- final int written = bbuf.length;
-
- // write DataSize
- writeShort(baos, written);
- // write Data
- baos.write(bbuf, 0, written);
- } else {
- // write DataSize
- writeShort(baos, 0);
- }
-
- x0 += bwidth;
- }
- }
-
- return baos.toByteArray();
- }
-
- private void writeShort(OutputStream os, final int n) throws
Exception {
- os.write((n >> 8) & 0xFF);
- os.write((n >> 0) & 0xFF);
- }
-
- public boolean isChanged(final byte[] current, final byte[]
previous,
- final int x0, final int y0, final int
blockWidth,
- final int blockHeight, final int width, final
int height) {
- if (previous == null)
- return true;
-
- for (int y = y0, ny = y0 + blockHeight; y < ny; y++) {
- final int foff = 3 * (x0 + width * y);
- final int poff = 3 * (x0 + width * y);
-
- for (int i = 0, ni = 3 * blockWidth; i < ni;
i++) {
- if (current[foff + i] != previous[poff
+ i])
- return true;
- }
- }
-
- return false;
- }
-
- public int getTag(final int frame, final int codec) {
- return ((frame & 0x0F) << 4) + ((codec & 0x0F) << 0);
- }
}
}
Added:
incubator/openmeetings/trunk/singlewebapp/src/org/red5/screen/webstart/IScreenEncoder.java
URL:
http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/red5/screen/webstart/IScreenEncoder.java?rev=1306748&view=auto
==============================================================================
---
incubator/openmeetings/trunk/singlewebapp/src/org/red5/screen/webstart/IScreenEncoder.java
(added)
+++
incubator/openmeetings/trunk/singlewebapp/src/org/red5/screen/webstart/IScreenEncoder.java
Thu Mar 29 08:14:45 2012
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License") + you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.red5.screen.webstart;
+
+import java.awt.Rectangle;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+
+public interface IScreenEncoder {
+
+ byte[] encode(Rectangle screen, BufferedImage img, Rectangle size)
throws IOException;
+
+ void reset();
+}
Added:
incubator/openmeetings/trunk/singlewebapp/src/org/red5/screen/webstart/ScreenV1Encoder.java
URL:
http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/red5/screen/webstart/ScreenV1Encoder.java?rev=1306748&view=auto
==============================================================================
---
incubator/openmeetings/trunk/singlewebapp/src/org/red5/screen/webstart/ScreenV1Encoder.java
(added)
+++
incubator/openmeetings/trunk/singlewebapp/src/org/red5/screen/webstart/ScreenV1Encoder.java
Thu Mar 29 08:14:45 2012
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License") + you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.red5.screen.webstart;
+
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.zip.DeflaterOutputStream;
+
+public class ScreenV1Encoder implements IScreenEncoder {
+ private BufferedImage last = null;
+ private static int KEY_FRAME_INDEX = 100;
+ private static int DEFAULT_BLOCK_SIZE = 32;
+ private int keyFrameIndex;
+ private int frameCount = 0;
+ private int blockSize;
+ private Rectangle screen;
+
+ public ScreenV1Encoder() {
+ this(KEY_FRAME_INDEX, DEFAULT_BLOCK_SIZE);
+ }
+
+ //will create square blocks
+ public ScreenV1Encoder(int keyFrameIndex, int blockSize) {
+ this.keyFrameIndex = keyFrameIndex;
+ if (blockSize < 16 || blockSize > 256 || blockSize % 16 != 0) {
+ throw new RuntimeException("Invalid block size passed:
" + blockSize + " should be: 'from 16 to 256 in multiples of 16'");
+ }
+ this.blockSize = blockSize;
+ }
+
+ public BufferedImage resize(BufferedImage _img, Rectangle size) {
+ BufferedImage img = _img;
+ if (_img.getWidth() != size.width || _img.getHeight() !=
size.height) {
+ img = new BufferedImage(size.width, size.height,
+ BufferedImage.TYPE_INT_RGB);
+
+ Graphics2D graphics2D = img.createGraphics();
+
graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
+
RenderingHints.VALUE_INTERPOLATION_BICUBIC);
+ graphics2D.drawImage(_img, 0, 0, size.width,
size.height, null);
+ graphics2D.dispose();
+ }
+ return img;
+ }
+
+ public byte[] encode(Rectangle screen, BufferedImage _img, Rectangle
size) throws IOException {
+ BufferedImage img = resize(_img, size);
+ Rectangle imgArea = new Rectangle(img.getWidth(),
img.getHeight());
+ Rectangle area = getNextBlock(imgArea, null);
+ boolean isKeyFrame = (frameCount++ % keyFrameIndex) == 0 ||
last == null || (screen.equals(this.screen));
+
+ ByteArrayOutputStream ba = new ByteArrayOutputStream(50 + 3 *
imgArea.width * imgArea.height);
+ //header
+ ba.write(getTag(isKeyFrame ? 0x01 : 0x02, 0x03));
+ writeShort(ba, imgArea.width + ((blockSize / 16 - 1) << 12));
+ writeShort(ba, imgArea.height + ((blockSize / 16 - 1) << 12));
+
+ while (area.width > 0 && area.height > 0) {
+ writeBytesIfChanged(ba, isKeyFrame, img, area);
+ area = getNextBlock(imgArea, area);
+ }
+ this.screen = screen;
+ last = img;
+ return ba.toByteArray();
+ }
+
+ public void reset() {
+ last = null;
+ }
+
+ private Rectangle getNextBlock(Rectangle img, Rectangle _prev) {
+ Rectangle prev;
+ if (_prev == null) {
+ prev = new Rectangle(0, Math.max(0, img.height -
blockSize), blockSize, blockSize);
+ } else {
+ prev = new Rectangle(_prev);
+ if (prev.x + prev.width == img.getWidth()) {
+ if (prev.y == 0) return new Rectangle(); //the
end of the image
+ //next row
+ prev.x = 0; //reset position
+ prev.width = blockSize; //reset width
+ prev.y -= (prev.y > blockSize ? blockSize :
prev.y);
+ } else {
+ prev.x += blockSize;
+ }
+ }
+ return img.intersection(prev);
+ }
+
+ private void writeBytesIfChanged(ByteArrayOutputStream ba, boolean
isKeyFrame, BufferedImage img, Rectangle area) throws IOException {
+ boolean changed = isKeyFrame;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(3 *
area.width * area.height);
+ DeflaterOutputStream dos = new DeflaterOutputStream(baos);
+ for (int y = area.y + area.height - 1; y >= area.y; --y) {
+ for (int x = area.x; x < area.x + area.width; ++x) {
+ int pixel = img.getRGB(x, y);
+ if (!changed && pixel != last.getRGB(x, y)) {
+ changed = true;
+ }
+ dos.write(new byte[]{
+ (byte)(pixel & 0xFF)
// Blue component
+ , (byte)((pixel >> 8) & 0xFF)
// Green component
+ , (byte)((pixel >> 16) & 0xFF)
// Red component
+ });
+ }
+ }
+ dos.finish();
+ if (changed) {
+ final int written = baos.size();
+ writeShort(ba, written);
+ ba.write(baos.toByteArray(), 0, written);
+ } else {
+ writeShort(ba, 0);
+ }
+ }
+
+ public int getTag(final int frame, final int codec) {
+ return ((frame & 0x0F) << 4) + ((codec & 0x0F) << 0);
+ }
+
+ private void writeShort(OutputStream os, final int n) throws
IOException {
+ os.write((n >> 8) & 0xFF);
+ os.write((n >> 0) & 0xFF);
+ }
+}
Modified:
incubator/openmeetings/trunk/singlewebapp/src/org/red5/screen/webstart/gui/VirtualScreen.java
URL:
http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/red5/screen/webstart/gui/VirtualScreen.java?rev=1306748&r1=1306747&r2=1306748&view=diff
==============================================================================
---
incubator/openmeetings/trunk/singlewebapp/src/org/red5/screen/webstart/gui/VirtualScreen.java
(original)
+++
incubator/openmeetings/trunk/singlewebapp/src/org/red5/screen/webstart/gui/VirtualScreen.java
Thu Mar 29 08:14:45 2012
@@ -18,27 +18,29 @@
*/
package org.red5.screen.webstart.gui;
-import javax.imageio.ImageIO;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Robot;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
-import javax.swing.SwingConstants;
+import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
-import javax.swing.JLabel;
import javax.swing.JComboBox;
+import javax.swing.JLabel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
+import javax.swing.SwingConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
-import java.awt.event.*;
import org.red5.screen.webstart.BlankArea;
import org.red5.screen.webstart.CommonScreenShare;
import org.red5.screen.webstart.ScreenShare;
+import org.red5.screen.webstart.gui.VirtualScreenBean.ScreenQuality;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -50,6 +52,40 @@ public class VirtualScreen {
public boolean doUpdateBounds = true;
+ private class KeyValue<T> {
+ private String key;
+ private T value;
+
+ public KeyValue(String key, T value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ @SuppressWarnings("unused")
+ public String getKey() { return key; }
+ public T getValue() { return value; }
+
+ @Override
+ public String toString() { return key; }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof KeyValue) {
+ @SuppressWarnings("unchecked")
+ KeyValue<T> kv = (KeyValue<T>) obj;
+ return (kv.value.equals(this.value));
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 97 * hash + (this.value != null ?
this.value.hashCode() : 0);
+ return hash;
+ }
+ }
+
public VirtualScreen(CommonScreenShare css) throws Exception {
this.css = css;
@@ -175,7 +211,6 @@ public class VirtualScreen {
css.jVScreenXSpin.setBounds(400, 170, 60, 24);
css.jVScreenXSpin.addChangeListener( new ChangeListener(){
public void stateChanged(ChangeEvent arg0) {
- // TODO Auto-generated method stub
calcNewValueXSpin();
}
});
@@ -194,7 +229,6 @@ public class VirtualScreen {
css.jVScreenYSpin.setBounds(400, 200, 60, 24);
css.jVScreenYSpin.addChangeListener( new ChangeListener(){
public void stateChanged(ChangeEvent arg0) {
- // TODO Auto-generated method stub
calcNewValueYSpin();
}
});
@@ -213,7 +247,6 @@ public class VirtualScreen {
css.jVScreenWidthSpin.setBounds(400, 240, 60, 24);
css.jVScreenWidthSpin.addChangeListener( new ChangeListener(){
public void stateChanged(ChangeEvent arg0) {
- // TODO Auto-generated method stub
calcNewValueWidthSpin();
}
});
@@ -232,15 +265,12 @@ public class VirtualScreen {
css.jVScreenHeightSpin.setBounds(400, 270, 60, 24);
css.jVScreenHeightSpin.addChangeListener( new ChangeListener(){
public void stateChanged(ChangeEvent arg0) {
- // TODO Auto-generated method stub
calcNewValueHeightSpin();
}
});
css.t.add(css.jVScreenHeightSpin);
- //String[] selectResize = { css.label1090, css.label1091,
css.label1092, css.label1093 };
- String[] selectResize = { css.label1091, css.label1092,
css.label1093 };
VirtualScreenBean.vScreenResizeX = 640;
VirtualScreenBean.vScreenResizeY = 400;
@@ -249,84 +279,55 @@ public class VirtualScreen {
css.vscreenResizeLabel.setBounds(250, 300, 200,24 );
css.t.add(css.vscreenResizeLabel);
- JComboBox comboResize = new JComboBox(selectResize);
+ JComboBox comboResize = new JComboBox();
+ comboResize.addItem(new KeyValue<ScreenQuality>(css.label1090,
ScreenQuality.VeryHigh));
+ comboResize.addItem(new KeyValue<ScreenQuality>(css.label1091,
ScreenQuality.High));
+ comboResize.addItem(new KeyValue<ScreenQuality>(css.label1092,
ScreenQuality.Medium));
+ comboResize.addItem(new KeyValue<ScreenQuality>(css.label1093,
ScreenQuality.Low));
comboResize.setBounds(250, 330, 200, 24);
- comboResize.addActionListener(new GetResizeChoice());
+ comboResize.addActionListener(new ActionListener(){
+ @SuppressWarnings("unchecked")
+ public void actionPerformed(ActionEvent e) {
+ JComboBox cb = (JComboBox)e.getSource();
+ VirtualScreenBean.screenQuality =
((KeyValue<ScreenQuality>)cb.getSelectedItem()).getValue();
+ calcRescaleFactors();
+ }
+ });
comboResize.setSelectedIndex(css.defaultQualityScreensharing);
css.jVScreenResizeMode = comboResize;
css.t.add(css.jVScreenResizeMode);
}
- class GetResizeChoice implements ActionListener
- {
- public void actionPerformed (ActionEvent e)
- {
-
- JComboBox cb = (JComboBox)e.getSource();
- String petName = (String)cb.getSelectedItem();
-
- VirtualScreenBean.vScreenScaleFactor = petName;
-
- calcRescaleFactors();
-
- }
- }
/**
* Needs to be always invoked after every re-scaling
*/
void calcRescaleFactors() {
-
logger.debug("calcRescaleFactors -- ");
- if(VirtualScreenBean.vScreenScaleFactor.equals(css.label1090))
- {
- logger.debug("resize:
X:"+Integer.valueOf(css.jVScreenWidthSpin.getValue().toString()).intValue()+
- "
Y:"+Integer.valueOf(css.jVScreenHeightSpin.getValue().toString()).intValue());
-
- VirtualScreenBean.vScreenResizeX =
Integer.valueOf(css.jVScreenWidthSpin.getValue().toString()).intValue();
- VirtualScreenBean.vScreenResizeY =
Integer.valueOf(css.jVScreenHeightSpin.getValue().toString()).intValue();
- updateVScreenBounds();
- }
- else
if(VirtualScreenBean.vScreenScaleFactor.equals(css.label1091))
- {
- logger.debug("resize:
X:"+Integer.valueOf(css.jVScreenWidthSpin.getValue().toString()).intValue()+
- "
Y:"+Integer.valueOf(css.jVScreenHeightSpin.getValue().toString()).intValue());
-
- VirtualScreenBean.vScreenResizeX =
Integer.valueOf(css.jVScreenWidthSpin.getValue().toString()).intValue();
- VirtualScreenBean.vScreenResizeY =
Integer.valueOf(css.jVScreenHeightSpin.getValue().toString()).intValue();
- updateVScreenBounds();
- }
- else if(VirtualScreenBean.vScreenScaleFactor.equals(css.label1092))
- {
- logger.debug("resize:
X:"+Integer.valueOf(css.jVScreenWidthSpin.getValue().toString()).intValue()/2+
- "
Y:"+Integer.valueOf(css.jVScreenHeightSpin.getValue().toString()).intValue()/2);
-
- VirtualScreenBean.vScreenResizeX =
(Integer.valueOf(css.jVScreenWidthSpin.getValue().toString()).intValue())/2;
- VirtualScreenBean.vScreenResizeY =
(Integer.valueOf(css.jVScreenHeightSpin.getValue().toString()).intValue())/2;
- updateVScreenBounds();
- }
- else if(VirtualScreenBean.vScreenScaleFactor.equals(css.label1093))
- {
- logger.debug("resize:
X:"+(Integer.valueOf(css.jVScreenWidthSpin.getValue().toString()).intValue()/8)*3+
- "
Y:"+(Integer.valueOf(css.jVScreenHeightSpin.getValue().toString()).intValue()/8)*3);
-
- VirtualScreenBean.vScreenResizeX =
(Integer.valueOf(css.jVScreenWidthSpin.getValue().toString()).intValue()/8)*3;
- VirtualScreenBean.vScreenResizeY =
(Integer.valueOf(css.jVScreenHeightSpin.getValue().toString()).intValue()/8)*3;
- updateVScreenBounds();
- }
-
- logger.debug("########## calcRescaleFactors vScreenResizeX " +
VirtualScreenBean.vScreenResizeX);
- logger.debug("########## calcRescaleFactors vScreenResizeY " +
VirtualScreenBean.vScreenResizeY);
- logger.debug("########## calcRescaleFactors vScreenScaleFactor " +
VirtualScreenBean.vScreenScaleFactor);
-
+ VirtualScreenBean.vScreenResizeX =
Integer.valueOf(css.jVScreenWidthSpin.getValue().toString()).intValue();
+ VirtualScreenBean.vScreenResizeY =
Integer.valueOf(css.jVScreenHeightSpin.getValue().toString()).intValue();
+ switch (VirtualScreenBean.screenQuality) {
+ case VeryHigh:
+ case High:
+ break;
+ case Medium:
+ VirtualScreenBean.vScreenResizeX *= 1/2;
+ VirtualScreenBean.vScreenResizeY *= 2;
+ break;
+ case Low:
+ VirtualScreenBean.vScreenResizeX *= 3/8;
+ VirtualScreenBean.vScreenResizeY *= 3/8;
+ break;
+ }
+ logger.debug("resize: X:" + VirtualScreenBean.vScreenResizeX +
" Y: " + VirtualScreenBean.vScreenResizeY);
+ updateVScreenBounds();
}
void calcNewValueXSpin(){
if (this.doUpdateBounds){
int newX =
Integer.valueOf(css.jVScreenXSpin.getValue().toString()).intValue();
if(VirtualScreenBean.vScreenSpinnerWidth+newX >
VirtualScreenBean.screenWidthMax){
-// System.out.println("WARNING X
"+VirtualScreenBean.vScreenSpinnerWidth+" "+newX);
newX=VirtualScreenBean.screenWidthMax-VirtualScreenBean.vScreenSpinnerWidth;
css.jVScreenXSpin.setValue(newX);
if (this.showWarning)
css.showBandwidthWarning("Reduce the width of the SharingScreen before you try
to move it left");
@@ -363,7 +364,6 @@ public class VirtualScreen {
if (this.doUpdateBounds){
int newWidth =
Integer.valueOf(css.jVScreenWidthSpin.getValue().toString()).intValue();
if(VirtualScreenBean.vScreenSpinnerX+newWidth >
VirtualScreenBean.screenWidthMax){
-// System.out.println("WARNING WIDTH");
newWidth=VirtualScreenBean.screenWidthMax-VirtualScreenBean.vScreenSpinnerX;
css.jVScreenWidthSpin.setValue(newWidth);
if
(this.showWarning)css.showBandwidthWarning("Reduce the x of the SharingScreen
before you try to make it wider");
Modified:
incubator/openmeetings/trunk/singlewebapp/src/org/red5/screen/webstart/gui/VirtualScreenBean.java
URL:
http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/red5/screen/webstart/gui/VirtualScreenBean.java?rev=1306748&r1=1306747&r2=1306748&view=diff
==============================================================================
---
incubator/openmeetings/trunk/singlewebapp/src/org/red5/screen/webstart/gui/VirtualScreenBean.java
(original)
+++
incubator/openmeetings/trunk/singlewebapp/src/org/red5/screen/webstart/gui/VirtualScreenBean.java
Thu Mar 29 08:14:45 2012
@@ -18,11 +18,8 @@
*/
package org.red5.screen.webstart.gui;
-import java.awt.Robot;
public class VirtualScreenBean {
-
-
/**
* image recalcing value's from the virtual Screen drawer
*/
@@ -47,13 +44,15 @@ public class VirtualScreenBean {
public static int vScreenSpinnerX = 0;
public static int vScreenSpinnerY = 0;
- public static String vScreenScaleFactor = "Medium Quality";
+ public static ScreenQuality screenQuality = ScreenQuality.Medium;
public static int vScreenResizeX = 480;
public static int vScreenResizeY = 360;
-
- public static Robot robot = null;
-
- public static Float imgQuality = new Float(0.40);
+ public enum ScreenQuality {
+ VeryHigh
+ , High
+ , Medium
+ , Low
+ }
}