Add support to update image only when there is a new frame
This commit is contained in:
parent
0704fc70a3
commit
ee165b50ff
52
README.md
52
README.md
|
@ -53,30 +53,39 @@ public class TestDriver extends Application {
|
|||
root.getChildren().add(imageView);
|
||||
|
||||
Webcam.getWebcams().stream()
|
||||
.findFirst()
|
||||
.ifPresent((final Webcam camera) -> {
|
||||
final WebcamDevice device = camera.getDevice();
|
||||
LOG.info("Found camera: {}, device = {}", camera, device);
|
||||
.findFirst()
|
||||
.ifPresent((final Webcam camera) -> {
|
||||
final WebcamDevice device = camera.getDevice();
|
||||
LOG.info("Found camera: {}, device = {}", camera, device);
|
||||
|
||||
final int width = device.getResolution().width;
|
||||
final int height = device.getResolution().height;
|
||||
final WritableImage fxImage = new WritableImage(width, height);
|
||||
Platform.runLater(() -> {
|
||||
imageView.setImage(fxImage);
|
||||
stage.setWidth(width);
|
||||
stage.setHeight(height);
|
||||
stage.centerOnScreen();
|
||||
final int width = device.getResolution().width;
|
||||
final int height = device.getResolution().height;
|
||||
final WritableImage fxImage = new WritableImage(width, height);
|
||||
Platform.runLater(() -> {
|
||||
imageView.setImage(fxImage);
|
||||
stage.setWidth(width);
|
||||
stage.setHeight(height);
|
||||
stage.centerOnScreen();
|
||||
});
|
||||
|
||||
camera.getLock().disable();
|
||||
camera.open();
|
||||
if (device instanceof WebcamDeviceWithBufferOperations) {
|
||||
final WebcamDeviceWithBufferOperations dev = ((WebcamDeviceWithBufferOperations) device);
|
||||
EXECUTOR.scheduleAtFixedRate(new Runnable() {
|
||||
private long lastFrameTimestamp = -1;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (dev.updateFXIMage(fxImage, lastFrameTimestamp)) {
|
||||
lastFrameTimestamp = dev.getLastFrameTimestamp();
|
||||
}
|
||||
|
||||
}
|
||||
}, 0, 16, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
});
|
||||
|
||||
camera.getLock().disable();
|
||||
camera.open();
|
||||
if (device instanceof WebcamDeviceWithBufferOperations) {
|
||||
EXECUTOR.scheduleAtFixedRate(() -> {
|
||||
((WebcamDeviceWithBufferOperations) device).updateFXIMage(fxImage);
|
||||
}, 0, 16, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
});
|
||||
|
||||
stage.setOnCloseRequest(t -> {
|
||||
Platform.exit();
|
||||
System.exit(0);
|
||||
|
@ -89,7 +98,6 @@ public class TestDriver extends Application {
|
|||
stage.show();
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
# Future work
|
||||
|
|
|
@ -54,8 +54,17 @@ public class TestDriver extends Application {
|
|||
camera.getLock().disable();
|
||||
camera.open();
|
||||
if (device instanceof WebcamDeviceWithBufferOperations) {
|
||||
EXECUTOR.scheduleAtFixedRate(() -> {
|
||||
((WebcamDeviceWithBufferOperations) device).updateFXIMage(fxImage);
|
||||
final WebcamDeviceWithBufferOperations dev = ((WebcamDeviceWithBufferOperations) device);
|
||||
EXECUTOR.scheduleAtFixedRate(new Runnable() {
|
||||
private long lastFrameTimestamp = -1;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (dev.updateFXIMage(fxImage, lastFrameTimestamp)) {
|
||||
lastFrameTimestamp = dev.getLastFrameTimestamp();
|
||||
}
|
||||
|
||||
}
|
||||
}, 0, 16, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -7,9 +7,11 @@ import javafx.scene.image.WritableImage;
|
|||
|
||||
public interface WebcamDeviceWithBufferOperations extends WebcamDevice {
|
||||
|
||||
BufferedImage getImage(final ByteBuffer byteBuffer);
|
||||
BufferedImage getImage(ByteBuffer byteBuffer);
|
||||
|
||||
boolean updateFXIMage(final WritableImage writableImage, final ByteBuffer byteBuffer);
|
||||
boolean updateFXIMage(WritableImage writableImage);
|
||||
|
||||
boolean updateFXIMage(final WritableImage writableImage);
|
||||
boolean updateFXIMage(WritableImage writableImage, long lastFrameTimestamp);
|
||||
|
||||
long getLastFrameTimestamp();
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ public class AVFVideoDevice implements WebcamDevice, WebcamDevice.FPSSource, Web
|
|||
private ByteBuffer imgBuffer = null;
|
||||
private byte[] arrayByteBuffer = null;
|
||||
private BufferedImage bufferedImage = null;
|
||||
private long lastFrameTimestamp = -1;
|
||||
|
||||
public AVFVideoDevice(final int deviceIndex, final String id, final String name, final Collection<Dimension> resolutions) {
|
||||
this.deviceIndex = deviceIndex;
|
||||
|
@ -159,6 +160,11 @@ public class AVFVideoDevice implements WebcamDevice, WebcamDevice.FPSSource, Web
|
|||
return open;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastFrameTimestamp() {
|
||||
return lastFrameTimestamp;
|
||||
}
|
||||
|
||||
public static final int MAX_FPS = 30;
|
||||
|
||||
@Override
|
||||
|
@ -217,18 +223,23 @@ public class AVFVideoDevice implements WebcamDevice, WebcamDevice.FPSSource, Web
|
|||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean updateFXIMage(WritableImage writableImage) {
|
||||
public boolean updateFXIMage(WritableImage writableImage) {
|
||||
return updateFXIMage(writableImage, -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean updateFXIMage(final WritableImage writableImage, final long lastFrameTimestamp) {
|
||||
return updateFXIMage(writableImage, imgBuffer, lastFrameTimestamp);
|
||||
}
|
||||
|
||||
private boolean updateFXIMage(final WritableImage writableImage, final ByteBuffer byteBuffer, final long lastFrameTimestamp) {
|
||||
if (!isOpen()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
updateBuffer();
|
||||
|
||||
return updateFXIMage(writableImage, imgBuffer);
|
||||
}
|
||||
|
||||
public boolean updateFXIMage(final WritableImage writableImage, final ByteBuffer byteBuffer) {
|
||||
if (!isOpen()) {
|
||||
if (this.lastFrameTimestamp <= lastFrameTimestamp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -249,9 +260,11 @@ public class AVFVideoDevice implements WebcamDevice, WebcamDevice.FPSSource, Web
|
|||
|
||||
private void updateBuffer() {
|
||||
if (LibVideoCapture.INSTANCE.vcavf_has_new_frame(deviceIndex)) {
|
||||
LibVideoCapture.INSTANCE.vcavf_grab_frame(
|
||||
if (LibVideoCapture.INSTANCE.vcavf_grab_frame(
|
||||
deviceIndex,
|
||||
Native.getDirectBufferPointer(imgBuffer), imgBuffer.capacity());
|
||||
Native.getDirectBufferPointer(imgBuffer), imgBuffer.capacity())) {
|
||||
lastFrameTimestamp = System.currentTimeMillis();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ public class CaptureManagerFrameGrabberSession {
|
|||
private int videoWidth = -1;
|
||||
private int videoHeight = -1;
|
||||
private int bufferSizeBytes = -1;
|
||||
private long lastFrameTimestamp = -1;
|
||||
|
||||
public boolean init(
|
||||
final CaptureManagerSource source,
|
||||
|
@ -223,6 +224,10 @@ public class CaptureManagerFrameGrabberSession {
|
|||
session.closeSession();
|
||||
}
|
||||
|
||||
public long getLastFrameTimestamp() {
|
||||
return lastFrameTimestamp;
|
||||
}
|
||||
|
||||
public synchronized BufferedImage toBufferedImage() {
|
||||
if (!isOpen()) {
|
||||
return null;
|
||||
|
@ -249,7 +254,7 @@ public class CaptureManagerFrameGrabberSession {
|
|||
return bufferedImage;
|
||||
}
|
||||
|
||||
public synchronized boolean updateFXIMage(final WritableImage writableImage) {
|
||||
public synchronized boolean updateFXIMage(final WritableImage writableImage, long lastFrameTimestamp) {
|
||||
if (!isOpen()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -260,6 +265,10 @@ public class CaptureManagerFrameGrabberSession {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (this.lastFrameTimestamp <= lastFrameTimestamp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
updateFXIMage(writableImage, directBuffer);
|
||||
|
||||
return true;
|
||||
|
@ -285,7 +294,12 @@ public class CaptureManagerFrameGrabberSession {
|
|||
|
||||
|
||||
public synchronized int updateDirectBuffer() {
|
||||
return sampleGrabberCall.readData(directBuffer);
|
||||
final int readSize = sampleGrabberCall.readData(directBuffer);
|
||||
if (readSize > 0) {
|
||||
lastFrameTimestamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
return readSize;
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
|
|
|
@ -144,6 +144,15 @@ public class CaptureManagerVideoDevice implements WebcamDevice, WebcamDevice.FPS
|
|||
return session != null && session.isOpen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastFrameTimestamp() {
|
||||
if (isOpen()) {
|
||||
return session.getLastFrameTimestamp();
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static Pair<CaptureManagerStreamDescriptor, CaptureManagerMediaType> findBestMediaTypeInStreams(
|
||||
final Collection<CaptureManagerStreamDescriptor> videoStreams,
|
||||
final Dimension resolution
|
||||
|
@ -231,9 +240,9 @@ public class CaptureManagerVideoDevice implements WebcamDevice, WebcamDevice.FPS
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean updateFXIMage(WritableImage writableImage, ByteBuffer byteBuffer) {
|
||||
public boolean updateFXIMage(final WritableImage writableImage, final long lastFrameTimestamp) {
|
||||
if (isOpen()) {
|
||||
session.updateFXIMage(writableImage, byteBuffer);
|
||||
session.updateFXIMage(writableImage, lastFrameTimestamp);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -242,11 +251,7 @@ public class CaptureManagerVideoDevice implements WebcamDevice, WebcamDevice.FPS
|
|||
|
||||
@Override
|
||||
public boolean updateFXIMage(WritableImage writableImage) {
|
||||
if (isOpen()) {
|
||||
return session.updateFXIMage(writableImage);
|
||||
}
|
||||
|
||||
return false;
|
||||
return updateFXIMage(writableImage, -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in New Issue