Add new function to get bytes per row. Necessary to properly decode some resolutions with row bytes padding

This commit is contained in:
Eduardo Ramos 2023-07-05 16:30:17 +02:00
parent 144a8a7463
commit 055cdd61ca
4 changed files with 27 additions and 17 deletions

View File

@ -31,6 +31,7 @@ public class AVFVideoDevice implements WebcamDeviceExtended {
//State:
private boolean open = false;
private int bytesPerRow = -1;
private ByteBuffer imgBuffer = null;
private byte[] arrayByteBuffer = null;
private BufferedImage bufferedImage = null;
@ -128,12 +129,9 @@ public class AVFVideoDevice implements WebcamDeviceExtended {
return;
}
final var bufferSizeBytes = width * height * 3;
this.open = true;
this.imgBuffer = ByteBuffer.allocateDirect(bufferSizeBytes);
this.bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
this.arrayByteBuffer = new byte[imgBuffer.capacity()];
LOG.info("Device {} opened successfully", id);
}
@ -143,6 +141,7 @@ public class AVFVideoDevice implements WebcamDeviceExtended {
if (isOpen()) {
LibVideoCapture.INSTANCE.vcavf_stop_capture(deviceIndex);
open = false;
bytesPerRow = -1;
imgBuffer = null;
arrayByteBuffer = null;
bufferedImage = null;
@ -227,37 +226,46 @@ public class AVFVideoDevice implements WebcamDeviceExtended {
@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();
if (this.lastFrameTimestamp <= lastFrameTimestamp) {
if (imgBuffer == null) {
return false;
}
if (this.lastFrameTimestamp <= lastFrameTimestamp) {
return false;
}
final int videoWidth = resolution.width;
final int videoHeight = resolution.height;
final PixelWriter pw = writableImage.getPixelWriter();
byteBuffer.mark();
byteBuffer.position(0);
imgBuffer.mark();
imgBuffer.position(0);
pw.setPixels(
0, 0, videoWidth, videoHeight,
PixelFormat.getByteRgbInstance(), byteBuffer, 3 * videoWidth
PixelFormat.getByteRgbInstance(), imgBuffer, bytesPerRow
);
return true;
}
private void updateBuffer() {
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(
deviceIndex,
Native.getDirectBufferPointer(imgBuffer), imgBuffer.capacity())) {
@ -267,7 +275,7 @@ public class AVFVideoDevice implements WebcamDeviceExtended {
}
private void updateBufferedImage() {
if (!isOpen()) {
if (!isOpen() || imgBuffer == null) {
return;
}
@ -275,7 +283,7 @@ public class AVFVideoDevice implements WebcamDeviceExtended {
final int videoHeight = resolution.height;
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}
);

View File

@ -45,5 +45,7 @@ public interface LibVideoCapture extends Library {
int vcavf_frame_height(int deviceIndex);
int vcavf_frame_bytes_per_row(int deviceIndex);
boolean vcavf_grab_frame(int deviceIndex, Pointer pointer, int availableBytes);
}