You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openmeetings.apache.org by so...@apache.org on 2015/10/15 21:01:51 UTC
svn commit: r1708868 - in /openmeetings:
branches/3.0.x/src/screenshare/java/org/apache/openmeetings/screen/webstart/CaptureScreen.java
trunk/singlewebapp/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screen/webstart/CaptureScreen.java
Author: solomax
Date: Thu Oct 15 19:01:50 2015
New Revision: 1708868
URL: http://svn.apache.org/viewvc?rev=1708868&view=rev
Log:
[OPENMEETINGS-926] screensharing applet performance is slightly increased
Modified:
openmeetings/branches/3.0.x/src/screenshare/java/org/apache/openmeetings/screen/webstart/CaptureScreen.java
openmeetings/trunk/singlewebapp/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screen/webstart/CaptureScreen.java
Modified: openmeetings/branches/3.0.x/src/screenshare/java/org/apache/openmeetings/screen/webstart/CaptureScreen.java
URL: http://svn.apache.org/viewvc/openmeetings/branches/3.0.x/src/screenshare/java/org/apache/openmeetings/screen/webstart/CaptureScreen.java?rev=1708868&r1=1708867&r2=1708868&view=diff
==============================================================================
--- openmeetings/branches/3.0.x/src/screenshare/java/org/apache/openmeetings/screen/webstart/CaptureScreen.java (original)
+++ openmeetings/branches/3.0.x/src/screenshare/java/org/apache/openmeetings/screen/webstart/CaptureScreen.java Thu Oct 15 19:01:50 2015
@@ -23,13 +23,18 @@ import static org.apache.openmeetings.sc
import static org.apache.openmeetings.screen.webstart.gui.ScreenDimensions.spinnerWidth;
import static org.apache.openmeetings.screen.webstart.gui.ScreenDimensions.spinnerX;
import static org.apache.openmeetings.screen.webstart.gui.ScreenDimensions.spinnerY;
+import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
+import static org.quartz.impl.StdSchedulerFactory.PROP_SCHED_SKIP_UPDATE_CHECK;
import static org.slf4j.LoggerFactory.getLogger;
import java.awt.AWTException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.io.IOException;
+import java.util.Properties;
import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
@@ -42,7 +47,6 @@ import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
-import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
@@ -58,7 +62,8 @@ class CaptureScreen extends Thread {
private final static String QUARTZ_CURSOR_JOB_NAME = "CursorJob";
private CoreScreenShare core;
private int timeBetweenFrames;
- private volatile int timestamp = 0;
+ private volatile AtomicInteger timestamp = new AtomicInteger(0);
+ private volatile AtomicBoolean sendFrameGuard = new AtomicBoolean(false);
private long timeCaptureStarted = 0;
private volatile boolean active = true;
private IScreenEncoder se;
@@ -77,8 +82,11 @@ class CaptureScreen extends Thread {
this.host = host;
this.app = app;
this.port = port;
- SchedulerFactory sf = new StdSchedulerFactory();
+ final Properties p = new Properties();
+ p.put(PROP_SCHED_SKIP_UPDATE_CHECK, "true");
+ p.put("org.quartz.threadPool.threadCount", "10");
try {
+ SchedulerFactory sf = new StdSchedulerFactory(p);
scheduler = sf.getScheduler();
} catch (SchedulerException e) {
log.error("Unexpected error while creating scheduler", e);
@@ -95,7 +103,7 @@ class CaptureScreen extends Thread {
log.error("Unexpected error while shutting down scheduler", e);
}
active = false;
- timestamp = 0;
+ timestamp = new AtomicInteger(0);
timeCaptureStarted = 0;
}
@@ -113,12 +121,12 @@ class CaptureScreen extends Thread {
encodeJob.getJobDataMap().put(EncodeJob.CAPTURE_KEY, this);
Trigger encodeTrigger = TriggerBuilder.newTrigger()
.withIdentity("EncodeTrigger", QUARTZ_GROUP_NAME)
- .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInMilliseconds(timeBetweenFrames).repeatForever())
+ .withSchedule(simpleSchedule().withIntervalInMilliseconds(timeBetweenFrames).repeatForever())
.build();
JobDetail sendJob = JobBuilder.newJob(SendJob.class).withIdentity("SendJob", QUARTZ_GROUP_NAME).build();
Trigger sendTrigger = TriggerBuilder.newTrigger()
.withIdentity("SendTrigger", QUARTZ_GROUP_NAME)
- .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInMilliseconds(timeBetweenFrames).repeatForever())
+ .withSchedule(simpleSchedule().withIntervalInMilliseconds(timeBetweenFrames).repeatForever())
.build();
sendJob.getJobDataMap().put(SendJob.CAPTURE_KEY, this);
@@ -158,7 +166,7 @@ class CaptureScreen extends Thread {
try {
robot = new Robot();
} catch (AWTException e) {
- log.error("Unexpected Error while creating robot", e);
+ log.error("encode: Unexpected Error while creating robot", e);
}
}
@@ -167,17 +175,20 @@ class CaptureScreen extends Thread {
JobDataMap data = context.getJobDetail().getJobDataMap();
CaptureScreen capture = (CaptureScreen)data.get(CAPTURE_KEY);
- long start = System.currentTimeMillis();
+ long start = 0;
+ if (log.isTraceEnabled()) {
+ start = System.currentTimeMillis();
+ }
image = ScreenV1Encoder.getImage(screen, robot);
if (log.isTraceEnabled()) {
- log.trace(String.format("Image was captured in %s ms", System.currentTimeMillis() - start));
+ log.trace(String.format("encode: Image was captured in %s ms, size %sk", System.currentTimeMillis() - start, 4 * image.length * image[0].length / 1024));
+ start = System.currentTimeMillis();
}
- start = System.currentTimeMillis();
try {
VideoData vData = capture.se.encode(image);
if (log.isTraceEnabled()) {
long now = System.currentTimeMillis();
- log.trace(String.format("Image was encoded in %s ms, timestamp is %s", now - start, now - capture.timeCaptureStarted));
+ log.trace(String.format("encode: Image was encoded in %s ms, timestamp is %s", now - start, now - capture.timeCaptureStarted));
}
capture.frames.offer(vData);
capture.se.createUnalteredFrame();
@@ -195,27 +206,34 @@ class CaptureScreen extends Thread {
public void execute(JobExecutionContext context) throws JobExecutionException {
JobDataMap data = context.getJobDetail().getJobDataMap();
CaptureScreen capture = (CaptureScreen)data.get(CAPTURE_KEY);
+ capture.sendFrameGuard.set(true);
if (log.isTraceEnabled()) {
long real = System.currentTimeMillis() - capture.timeCaptureStarted;
- log.trace(String.format("Enter method, timestamp: %s, real: %s, diff: %s", capture.timestamp, real, real - capture.timestamp));
+ log.trace(String.format("send: Enter method, timestamp: %s, real: %s, diff: %s", capture.timestamp, real, real - capture.timestamp.get()));
}
VideoData f = capture.frames.poll();
if (log.isTraceEnabled()) {
- log.trace(String.format("Getting %s image", f == null ? "DUMMY" : "CAPTURED"));
+ log.trace(String.format("send: Getting %s image", f == null ? "DUMMY" : "CAPTURED"));
}
f = f == null ? capture.se.getUnalteredFrame() : f;
if (f != null) {
try {
- capture.pushVideo(f, capture.timestamp);
+ capture.pushVideo(f, capture.timestamp.get());
if (log.isTraceEnabled()) {
long real = System.currentTimeMillis() - capture.timeCaptureStarted;
- log.trace(String.format("Sending video, timestamp: %s, real: %s, diff: %s", capture.timestamp, real, real - capture.timestamp));
+ log.trace(String.format("send: Sending video %sk, timestamp: %s, real: %s, diff: %s", f.getData().capacity() / 1024, capture.timestamp, real, real - capture.timestamp.get()));
+ }
+ capture.timestamp.addAndGet(capture.timeBetweenFrames);
+ if (log.isTraceEnabled()) {
+ log.trace(String.format("send: new timestamp: %s", capture.timestamp));
}
- capture.timestamp += capture.timeBetweenFrames;
} catch (IOException e) {
log.error("Error while sending: ", e);
}
+ } else if (log.isTraceEnabled()) {
+ log.trace(String.format("send: nothing to send"));
}
+ capture.sendFrameGuard.set(false);
}
}
@@ -229,7 +247,9 @@ class CaptureScreen extends Thread {
public void execute(JobExecutionContext context) throws JobExecutionException {
JobDataMap data = context.getJobDetail().getJobDataMap();
CaptureScreen capture = (CaptureScreen)data.get(CAPTURE_KEY);
- capture.core.sendCursorStatus();
+ if (!capture.sendFrameGuard.get()) {
+ capture.core.sendCursorStatus();
+ }
}
}
@@ -273,7 +293,7 @@ class CaptureScreen extends Thread {
JobDetail cursorJob = JobBuilder.newJob(CursorJob.class).withIdentity(QUARTZ_CURSOR_JOB_NAME, QUARTZ_GROUP_NAME).build();
Trigger cursorTrigger = TriggerBuilder.newTrigger()
.withIdentity(QUARTZ_CURSOR_TRIGGER_NAME, QUARTZ_GROUP_NAME)
- .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInMilliseconds(1000 / Math.min(2, FPS)).repeatForever())
+ .withSchedule(simpleSchedule().withIntervalInMilliseconds(1000 / Math.min(5, FPS)).repeatForever())
.build();
cursorJob.getJobDataMap().put(CursorJob.CAPTURE_KEY, this);
scheduler.scheduleJob(cursorJob, cursorTrigger);
Modified: openmeetings/trunk/singlewebapp/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screen/webstart/CaptureScreen.java
URL: http://svn.apache.org/viewvc/openmeetings/trunk/singlewebapp/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screen/webstart/CaptureScreen.java?rev=1708868&r1=1708867&r2=1708868&view=diff
==============================================================================
--- openmeetings/trunk/singlewebapp/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screen/webstart/CaptureScreen.java (original)
+++ openmeetings/trunk/singlewebapp/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screen/webstart/CaptureScreen.java Thu Oct 15 19:01:50 2015
@@ -23,13 +23,18 @@ import static org.apache.openmeetings.sc
import static org.apache.openmeetings.screen.webstart.gui.ScreenDimensions.spinnerWidth;
import static org.apache.openmeetings.screen.webstart.gui.ScreenDimensions.spinnerX;
import static org.apache.openmeetings.screen.webstart.gui.ScreenDimensions.spinnerY;
+import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
+import static org.quartz.impl.StdSchedulerFactory.PROP_SCHED_SKIP_UPDATE_CHECK;
import static org.slf4j.LoggerFactory.getLogger;
import java.awt.AWTException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.io.IOException;
+import java.util.Properties;
import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
@@ -42,7 +47,6 @@ import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
-import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
@@ -58,7 +62,8 @@ class CaptureScreen extends Thread {
private final static String QUARTZ_CURSOR_JOB_NAME = "CursorJob";
private CoreScreenShare core;
private int timeBetweenFrames;
- private volatile int timestamp = 0;
+ private volatile AtomicInteger timestamp = new AtomicInteger(0);
+ private volatile AtomicBoolean sendFrameGuard = new AtomicBoolean(false);
private long timeCaptureStarted = 0;
private volatile boolean active = true;
private IScreenEncoder se;
@@ -77,8 +82,11 @@ class CaptureScreen extends Thread {
this.host = host;
this.app = app;
this.port = port;
- SchedulerFactory sf = new StdSchedulerFactory();
+ final Properties p = new Properties();
+ p.put(PROP_SCHED_SKIP_UPDATE_CHECK, "true");
+ p.put("org.quartz.threadPool.threadCount", "10");
try {
+ SchedulerFactory sf = new StdSchedulerFactory(p);
scheduler = sf.getScheduler();
} catch (SchedulerException e) {
log.error("Unexpected error while creating scheduler", e);
@@ -95,7 +103,7 @@ class CaptureScreen extends Thread {
log.error("Unexpected error while shutting down scheduler", e);
}
active = false;
- timestamp = 0;
+ timestamp = new AtomicInteger(0);
timeCaptureStarted = 0;
}
@@ -113,12 +121,12 @@ class CaptureScreen extends Thread {
encodeJob.getJobDataMap().put(EncodeJob.CAPTURE_KEY, this);
Trigger encodeTrigger = TriggerBuilder.newTrigger()
.withIdentity("EncodeTrigger", QUARTZ_GROUP_NAME)
- .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInMilliseconds(timeBetweenFrames).repeatForever())
+ .withSchedule(simpleSchedule().withIntervalInMilliseconds(timeBetweenFrames).repeatForever())
.build();
JobDetail sendJob = JobBuilder.newJob(SendJob.class).withIdentity("SendJob", QUARTZ_GROUP_NAME).build();
Trigger sendTrigger = TriggerBuilder.newTrigger()
.withIdentity("SendTrigger", QUARTZ_GROUP_NAME)
- .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInMilliseconds(timeBetweenFrames).repeatForever())
+ .withSchedule(simpleSchedule().withIntervalInMilliseconds(timeBetweenFrames).repeatForever())
.build();
sendJob.getJobDataMap().put(SendJob.CAPTURE_KEY, this);
@@ -158,7 +166,7 @@ class CaptureScreen extends Thread {
try {
robot = new Robot();
} catch (AWTException e) {
- log.error("Unexpected Error while creating robot", e);
+ log.error("encode: Unexpected Error while creating robot", e);
}
}
@@ -167,17 +175,20 @@ class CaptureScreen extends Thread {
JobDataMap data = context.getJobDetail().getJobDataMap();
CaptureScreen capture = (CaptureScreen)data.get(CAPTURE_KEY);
- long start = System.currentTimeMillis();
+ long start = 0;
+ if (log.isTraceEnabled()) {
+ start = System.currentTimeMillis();
+ }
image = ScreenV1Encoder.getImage(screen, robot);
if (log.isTraceEnabled()) {
- log.trace(String.format("Image was captured in %s ms", System.currentTimeMillis() - start));
+ log.trace(String.format("encode: Image was captured in %s ms, size %sk", System.currentTimeMillis() - start, 4 * image.length * image[0].length / 1024));
+ start = System.currentTimeMillis();
}
- start = System.currentTimeMillis();
try {
VideoData vData = capture.se.encode(image);
if (log.isTraceEnabled()) {
long now = System.currentTimeMillis();
- log.trace(String.format("Image was encoded in %s ms, timestamp is %s", now - start, now - capture.timeCaptureStarted));
+ log.trace(String.format("encode: Image was encoded in %s ms, timestamp is %s", now - start, now - capture.timeCaptureStarted));
}
capture.frames.offer(vData);
capture.se.createUnalteredFrame();
@@ -195,27 +206,34 @@ class CaptureScreen extends Thread {
public void execute(JobExecutionContext context) throws JobExecutionException {
JobDataMap data = context.getJobDetail().getJobDataMap();
CaptureScreen capture = (CaptureScreen)data.get(CAPTURE_KEY);
+ capture.sendFrameGuard.set(true);
if (log.isTraceEnabled()) {
long real = System.currentTimeMillis() - capture.timeCaptureStarted;
- log.trace(String.format("Enter method, timestamp: %s, real: %s, diff: %s", capture.timestamp, real, real - capture.timestamp));
+ log.trace(String.format("send: Enter method, timestamp: %s, real: %s, diff: %s", capture.timestamp, real, real - capture.timestamp.get()));
}
VideoData f = capture.frames.poll();
if (log.isTraceEnabled()) {
- log.trace(String.format("Getting %s image", f == null ? "DUMMY" : "CAPTURED"));
+ log.trace(String.format("send: Getting %s image", f == null ? "DUMMY" : "CAPTURED"));
}
f = f == null ? capture.se.getUnalteredFrame() : f;
if (f != null) {
try {
- capture.pushVideo(f, capture.timestamp);
+ capture.pushVideo(f, capture.timestamp.get());
if (log.isTraceEnabled()) {
long real = System.currentTimeMillis() - capture.timeCaptureStarted;
- log.trace(String.format("Sending video, timestamp: %s, real: %s, diff: %s", capture.timestamp, real, real - capture.timestamp));
+ log.trace(String.format("send: Sending video %sk, timestamp: %s, real: %s, diff: %s", f.getData().capacity() / 1024, capture.timestamp, real, real - capture.timestamp.get()));
+ }
+ capture.timestamp.addAndGet(capture.timeBetweenFrames);
+ if (log.isTraceEnabled()) {
+ log.trace(String.format("send: new timestamp: %s", capture.timestamp));
}
- capture.timestamp += capture.timeBetweenFrames;
} catch (IOException e) {
log.error("Error while sending: ", e);
}
+ } else if (log.isTraceEnabled()) {
+ log.trace(String.format("send: nothing to send"));
}
+ capture.sendFrameGuard.set(false);
}
}
@@ -229,7 +247,9 @@ class CaptureScreen extends Thread {
public void execute(JobExecutionContext context) throws JobExecutionException {
JobDataMap data = context.getJobDetail().getJobDataMap();
CaptureScreen capture = (CaptureScreen)data.get(CAPTURE_KEY);
- capture.core.sendCursorStatus();
+ if (!capture.sendFrameGuard.get()) {
+ capture.core.sendCursorStatus();
+ }
}
}
@@ -273,7 +293,7 @@ class CaptureScreen extends Thread {
JobDetail cursorJob = JobBuilder.newJob(CursorJob.class).withIdentity(QUARTZ_CURSOR_JOB_NAME, QUARTZ_GROUP_NAME).build();
Trigger cursorTrigger = TriggerBuilder.newTrigger()
.withIdentity(QUARTZ_CURSOR_TRIGGER_NAME, QUARTZ_GROUP_NAME)
- .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInMilliseconds(1000 / Math.min(2, FPS)).repeatForever())
+ .withSchedule(simpleSchedule().withIntervalInMilliseconds(1000 / Math.min(5, FPS)).repeatForever())
.build();
cursorJob.getJobDataMap().put(CursorJob.CAPTURE_KEY, this);
scheduler.scheduleJob(cursorJob, cursorTrigger);