diff --git a/Quelea/launch.sh b/Quelea/launch.sh index 29d300265..e1f54fbcc 100644 --- a/Quelea/launch.sh +++ b/Quelea/launch.sh @@ -3,4 +3,4 @@ cd $SNAP/jar export GST_PLUGIN_PATH=$SNAP/usr/lib/x86_64-linux-gnu/gstreamer-1.0 export GST_PLUGIN_SCANNER=$SNAP/usr/lib/x86_64-linux-gnu/gstreamer-1.0/gst-plugin-scanner export G_FILENAME_ENCODING=UTF-8 -jvm/bin/java --add-exports=javafx.graphics/com.sun.javafx.scene.traversal=ALL-UNNAMED --add-exports=javafx.graphics/com.sun.javafx.scene=ALL-UNNAMED --add-exports=javafx.graphics/com.sun.javafx.css=ALL-UNNAMED --add-exports=javafx.base/com.sun.javafx.runtime=ALL-UNNAMED --add-exports=javafx.base/com.sun.javafx.event=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens javafx.controls/javafx.scene.control=ALL-UNNAMED -Djdk.gtk.verbose=true -DVLCJ_INITX=no -Duser.dir=$SNAP/jar -Dfile.encoding=UTF-8 -Dprism.dirtyopts=false -Djavafx.cachedir=$SNAP_USER_COMMON -jar $SNAP/jar/Quelea.jar --userhome=$SNAP_USER_COMMON +jvm/bin/java --add-opens java.base/java.nio=ALL-UNNAMED --add-exports=javafx.graphics/com.sun.javafx.scene.traversal=ALL-UNNAMED --add-exports=javafx.graphics/com.sun.javafx.scene=ALL-UNNAMED --add-exports=javafx.graphics/com.sun.javafx.css=ALL-UNNAMED --add-exports=javafx.base/com.sun.javafx.runtime=ALL-UNNAMED --add-exports=javafx.base/com.sun.javafx.event=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens javafx.controls/javafx.scene.control=ALL-UNNAMED -Djdk.gtk.verbose=true -DVLCJ_INITX=no -Duser.dir=$SNAP/jar -Dfile.encoding=UTF-8 -Dprism.dirtyopts=false -Djavafx.cachedir=$SNAP_USER_COMMON -jar $SNAP/jar/Quelea.jar --userhome=$SNAP_USER_COMMON diff --git a/Quelea/packr.json b/Quelea/packr.json index afd37883f..4d13027cf 100644 --- a/Quelea/packr.json +++ b/Quelea/packr.json @@ -15,7 +15,8 @@ "add-exports","javafx.base/com.sun.javafx.runtime=ALL-UNNAMED", "add-exports","javafx.base/com.sun.javafx.event=ALL-UNNAMED", "add-opens","java.base/java.lang=ALL-UNNAMED", - "add-opens","javafx.controls/javafx.scene.control=ALL-UNNAMED" + "add-opens","javafx.controls/javafx.scene.control=ALL-UNNAMED", + "add-opens","java.base/java.nio=ALL-UNNAMED" ], "resources": [ "dist/bibles", @@ -35,5 +36,6 @@ "dist/songformat.xsl" ], "icon": "dist/icons/mac-logo.icns", - "output": "out-mac/Quelea.app" + "output": "out-mac/Quelea.app", + "verbose": true } \ No newline at end of file diff --git a/Quelea/src/main/java/org/quelea/windows/video/FXImageSink.java b/Quelea/src/main/java/org/quelea/windows/video/FXImageSink.java index fe9535c1d..5b9d725fd 100644 --- a/Quelea/src/main/java/org/quelea/windows/video/FXImageSink.java +++ b/Quelea/src/main/java/org/quelea/windows/video/FXImageSink.java @@ -18,6 +18,7 @@ */ package org.quelea.windows.video; +import com.sun.jna.Pointer; import javafx.application.Platform; import javafx.beans.property.ReadOnlyObjectProperty; import javafx.beans.property.ReadOnlyObjectWrapper; @@ -32,7 +33,11 @@ import org.freedesktop.gstreamer.Structure; import org.freedesktop.gstreamer.elements.AppSink; +import java.lang.module.ModuleFinder; +import java.lang.reflect.Field; +import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.nio.IntBuffer; import java.util.Queue; import java.util.concurrent.ArrayBlockingQueue; @@ -50,16 +55,36 @@ public class FXImageSink { private final static String DEFAULT_CAPS; private final static int OLD_SAMPLE_BUFFER_SIZE = 2; + private static final Field mapInfoBufferField; + private static final Field pointerPeerField; + private static final Field bufferAddress; + private static final Field bufferCapacity; + static { if (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) { DEFAULT_CAPS = "video/x-raw, format=BGRx"; } else { DEFAULT_CAPS = "video/x-raw, format=xRGB"; } + + try { + mapInfoBufferField = Buffer.class.getDeclaredField("mapInfo"); + mapInfoBufferField.setAccessible(true); + pointerPeerField = Pointer.class.getDeclaredField("peer"); + pointerPeerField.setAccessible(true); + bufferAddress = java.nio.Buffer.class.getDeclaredField("address"); + bufferAddress.setAccessible(true); + bufferCapacity = java.nio.Buffer.class.getDeclaredField("capacity"); + bufferCapacity.setAccessible(true); + } catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } } private final AppSink sink; private final ReadOnlyObjectWrapper image; + private IntBuffer imageBuffer; + private PixelBuffer pixelBuffer; private Sample activeSample; private Buffer activeBuffer; private final Queue oldSamples; @@ -94,7 +119,10 @@ public FXImageSink(AppSink sink) { return FlowReturn.OK; }); sink.setCaps(Caps.fromString(DEFAULT_CAPS)); - image = new ReadOnlyObjectWrapper<>(new WritableImage(1, 1)); + + imageBuffer = ByteBuffer.allocateDirect(4).asIntBuffer(); + pixelBuffer = new PixelBuffer<>(1, 1, imageBuffer, PixelFormat.getIntArgbPreInstance()); + image = new ReadOnlyObjectWrapper<>(new WritableImage(pixelBuffer)); } /** @@ -118,7 +146,19 @@ public AppSink getSinkElement() { return sink; } + long lastTs = 0; + int frames = 0; + private void updateImage(Sample newSample) { + long ts = System.currentTimeMillis(); + if(ts-lastTs>1000) { + System.out.println(frames); + frames = 1; + lastTs= ts; + } + else { + frames++; + } if (!Platform.isFxApplicationThread()) { throw new IllegalStateException("Not on FX application thread"); } @@ -135,10 +175,45 @@ private void updateImage(Sample newSample) { activeBuffer = newSample.getBuffer(); if (image.get().getWidth() != width || image.get().getHeight() != height) { - image.set(new WritableImage(width, height)); + imageBuffer = ByteBuffer.allocateDirect(width*height*4).asIntBuffer(); + pixelBuffer = new PixelBuffer<>(width, height, imageBuffer, PixelFormat.getIntArgbPreInstance()); + image.set(new WritableImage(pixelBuffer)); } - image.get().getPixelWriter().setPixels(0, 0, width, height, PixelFormat.getByteBgraPreInstance(), activeBuffer.map(false), width * 4); + IntBuffer gBuffer = activeBuffer.map(false).asIntBuffer(); + + try { +// GstBufferAPI.MapInfoStruct mapInfo = (GstBufferAPI.MapInfoStruct) mapInfoBufferField.get(activeBuffer); +// long baseAddress = (long)pointerPeerField.get(mapInfo.data); +// long size = mapInfo.size.longValue(); + + long baseAddress = bufferAddress.getLong(gBuffer); + long size = bufferCapacity.getInt(gBuffer); + +// System.out.println(baseAddress + " "+ size); + +// imageBuffer.rewind(); + + bufferAddress.setLong(imageBuffer, baseAddress); + bufferCapacity.setInt(imageBuffer, (int)size); + imageBuffer.position(0); + imageBuffer.limit((int)size); +// System.out.println(imageBuffer.get(4140000)); +// System.out.println(gBuffer.get(4140000)); +// System.out.println(gBuffer.getClass()); +// System.out.println(imageBuffer.getClass()); +// imageBuffer.put(gBuffer); + +// imageBuffer.flip(); + + pixelBuffer.updateBuffer(b -> null); + + + } catch (IllegalAccessException ex) { + ex.printStackTrace(); + } + +// image.get().getPixelWriter().setPixels(0, 0, width, height, PixelFormat.getByteBgraPreInstance(), activeBuffer.map(false), width * 4); if (oldSample != null) oldSamples.add(oldSample); if (oldBuffer != null) { @@ -148,6 +223,9 @@ private void updateImage(Sample newSample) { oldSamples.remove().dispose(); } +// long dur = System.nanoTime() - val; +// System.out.println("REFRESH TIME: " + dur / 1000); + } /**