Add new function to get bytes per row. Necessary to properly decode some resolutions with row bytes padding
This commit is contained in:
parent
144a8a7463
commit
055cdd61ca
|
@ -31,6 +31,7 @@ public class AVFVideoDevice implements WebcamDeviceExtended {
|
||||||
|
|
||||||
//State:
|
//State:
|
||||||
private boolean open = false;
|
private boolean open = false;
|
||||||
|
private int bytesPerRow = -1;
|
||||||
private ByteBuffer imgBuffer = null;
|
private ByteBuffer imgBuffer = null;
|
||||||
private byte[] arrayByteBuffer = null;
|
private byte[] arrayByteBuffer = null;
|
||||||
private BufferedImage bufferedImage = null;
|
private BufferedImage bufferedImage = null;
|
||||||
|
@ -128,12 +129,9 @@ public class AVFVideoDevice implements WebcamDeviceExtended {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final var bufferSizeBytes = width * height * 3;
|
|
||||||
|
|
||||||
this.open = true;
|
this.open = true;
|
||||||
this.imgBuffer = ByteBuffer.allocateDirect(bufferSizeBytes);
|
|
||||||
this.bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
|
this.bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
|
||||||
this.arrayByteBuffer = new byte[imgBuffer.capacity()];
|
|
||||||
|
|
||||||
LOG.info("Device {} opened successfully", id);
|
LOG.info("Device {} opened successfully", id);
|
||||||
}
|
}
|
||||||
|
@ -143,6 +141,7 @@ public class AVFVideoDevice implements WebcamDeviceExtended {
|
||||||
if (isOpen()) {
|
if (isOpen()) {
|
||||||
LibVideoCapture.INSTANCE.vcavf_stop_capture(deviceIndex);
|
LibVideoCapture.INSTANCE.vcavf_stop_capture(deviceIndex);
|
||||||
open = false;
|
open = false;
|
||||||
|
bytesPerRow = -1;
|
||||||
imgBuffer = null;
|
imgBuffer = null;
|
||||||
arrayByteBuffer = null;
|
arrayByteBuffer = null;
|
||||||
bufferedImage = null;
|
bufferedImage = null;
|
||||||
|
@ -227,37 +226,46 @@ public class AVFVideoDevice implements WebcamDeviceExtended {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean updateFXIMage(final WritableImage writableImage, final long lastFrameTimestamp) {
|
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()) {
|
if (!isOpen()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateBuffer();
|
updateBuffer();
|
||||||
|
|
||||||
if (this.lastFrameTimestamp <= lastFrameTimestamp) {
|
if (imgBuffer == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.lastFrameTimestamp <= lastFrameTimestamp) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
final int videoWidth = resolution.width;
|
final int videoWidth = resolution.width;
|
||||||
final int videoHeight = resolution.height;
|
final int videoHeight = resolution.height;
|
||||||
|
|
||||||
final PixelWriter pw = writableImage.getPixelWriter();
|
final PixelWriter pw = writableImage.getPixelWriter();
|
||||||
|
|
||||||
byteBuffer.mark();
|
imgBuffer.mark();
|
||||||
byteBuffer.position(0);
|
imgBuffer.position(0);
|
||||||
pw.setPixels(
|
pw.setPixels(
|
||||||
0, 0, videoWidth, videoHeight,
|
0, 0, videoWidth, videoHeight,
|
||||||
PixelFormat.getByteRgbInstance(), byteBuffer, 3 * videoWidth
|
PixelFormat.getByteRgbInstance(), imgBuffer, bytesPerRow
|
||||||
);
|
);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateBuffer() {
|
private void updateBuffer() {
|
||||||
if (LibVideoCapture.INSTANCE.vcavf_has_new_frame(deviceIndex)) {
|
if (LibVideoCapture.INSTANCE.vcavf_has_new_frame(deviceIndex)) {
|
||||||
|
if (imgBuffer == null) {
|
||||||
|
// Init buffer if still not initialized:
|
||||||
|
this.bytesPerRow = LibVideoCapture.INSTANCE.vcavf_frame_bytes_per_row(deviceIndex);
|
||||||
|
|
||||||
|
final var bufferSizeBytes = bytesPerRow * resolution.height;
|
||||||
|
this.imgBuffer = ByteBuffer.allocateDirect(bufferSizeBytes);
|
||||||
|
this.arrayByteBuffer = new byte[imgBuffer.capacity()];
|
||||||
|
}
|
||||||
|
|
||||||
if (LibVideoCapture.INSTANCE.vcavf_grab_frame(
|
if (LibVideoCapture.INSTANCE.vcavf_grab_frame(
|
||||||
deviceIndex,
|
deviceIndex,
|
||||||
Native.getDirectBufferPointer(imgBuffer), imgBuffer.capacity())) {
|
Native.getDirectBufferPointer(imgBuffer), imgBuffer.capacity())) {
|
||||||
|
@ -267,7 +275,7 @@ public class AVFVideoDevice implements WebcamDeviceExtended {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateBufferedImage() {
|
private void updateBufferedImage() {
|
||||||
if (!isOpen()) {
|
if (!isOpen() || imgBuffer == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,7 +283,7 @@ public class AVFVideoDevice implements WebcamDeviceExtended {
|
||||||
final int videoHeight = resolution.height;
|
final int videoHeight = resolution.height;
|
||||||
|
|
||||||
final ComponentSampleModel sampleModel = new ComponentSampleModel(
|
final ComponentSampleModel sampleModel = new ComponentSampleModel(
|
||||||
DataBuffer.TYPE_BYTE, videoWidth, videoHeight, 3, videoWidth * 3,
|
DataBuffer.TYPE_BYTE, videoWidth, videoHeight, 3, bytesPerRow,
|
||||||
new int[]{0, 1, 2}
|
new int[]{0, 1, 2}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -45,5 +45,7 @@ public interface LibVideoCapture extends Library {
|
||||||
|
|
||||||
int vcavf_frame_height(int deviceIndex);
|
int vcavf_frame_height(int deviceIndex);
|
||||||
|
|
||||||
|
int vcavf_frame_bytes_per_row(int deviceIndex);
|
||||||
|
|
||||||
boolean vcavf_grab_frame(int deviceIndex, Pointer pointer, int availableBytes);
|
boolean vcavf_grab_frame(int deviceIndex, Pointer pointer, int availableBytes);
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue