| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent f1502ef commit fc0a8fd
4 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -102,6 +102,7 @@ public class Texture implements PConstants { | |||
| 102 | 102 | ||
| 103 | 103 | protected Object bufferSource; | |
| 104 | 104 | protected LinkedList<BufferData> bufferCache = null; | |
| 105 | + protected LinkedList<BufferData> usedBuffers = null; | ||
| 105 | 106 | protected Method disposeBufferMethod; | |
| 106 | 107 | public static final int MAX_BUFFER_CACHE_SIZE = 3; | |
| 107 | 108 | ||
@@ -153,7 +154,6 @@ public Texture(int width, int height, Object params) { | |||
| 153 | 154 | @Override | |
| 154 | 155 | protected void finalize() throws Throwable { | |
| 155 | 156 | try { | |
| 156 | - // PApplet.println("finalize texture"); | ||
| 157 | 157 | if (glName != 0) { | |
| 158 | 158 | PGraphicsOpenGL.finalizeTextureObject(glName, context); | |
| 159 | 159 | } | |
@@ -520,27 +520,6 @@ public void get(int[] pixels) { | |||
| 520 | 520 | } | |
| 521 | 521 | ||
| 522 | 522 | ||
| 523 | - /** | ||
| 524 | - * Copies the contents of the texture to the pixels array. | ||
| 525 | - * @param pixels | ||
| 526 | - */ | ||
| 527 | - // public void loadPixels(int[] pixels) { | ||
| 528 | - // if (hasBuffers()) { | ||
| 529 | - // // Updates the texture AND the pixels array of the image at the same time, | ||
| 530 | - // // getting the pixels directly from the buffer data (and thus avoiding | ||
| 531 | - // // expensive transfer between video and main memory). | ||
| 532 | - // bufferUpdate(pixels); | ||
| 533 | - // } | ||
| 534 | - // | ||
| 535 | - // if (isModified()) { | ||
| 536 | - // // Regular pixel copy from texture. | ||
| 537 | - // get(pixels); | ||
| 538 | - // } | ||
| 539 | - // | ||
| 540 | - // setModified(false); | ||
| 541 | - // } | ||
| 542 | - | ||
| 543 | - | ||
| 544 | 523 | //////////////////////////////////////////////////////////// | |
| 545 | 524 | ||
| 546 | 525 | // Put methods (the source texture is not resized to cover the entire | |
@@ -861,16 +840,53 @@ public void copyBufferFromSource(Object natRef, ByteBuffer byteBuf, | |||
| 861 | 840 | bufferCache.add(new BufferData(natRef, byteBuf.asIntBuffer(), w, h)); | |
| 862 | 841 | } else { | |
| 863 | 842 | // The buffer cache reached the maximum size, so we just dispose | |
| 864 | - // the new buffer. | ||
| 843 | + // the new buffer by adding it to the list of used buffers. | ||
| 865 | 844 | try { | |
| 866 | - disposeBufferMethod.invoke(bufferSource, new Object[] { natRef }); | ||
| 845 | + usedBuffers.add(new BufferData(natRef, byteBuf.asIntBuffer(), w, h)); | ||
| 867 | 846 | } catch (Exception e) { | |
| 868 | 847 | e.printStackTrace(); | |
| 869 | 848 | } | |
| 870 | 849 | } | |
| 871 | 850 | } | |
| 872 | 851 | ||
| 873 | 852 | ||
| 853 | + public void disposeSourceBuffer() { | ||
| 854 | + System.out.println(" in disposeSourceBuffer"); | ||
| 855 | + if (usedBuffers == null) return; | ||
| 856 | + | ||
| 857 | + while (0 < usedBuffers.size()) { | ||
| 858 | + BufferData data = null; | ||
| 859 | + try { | ||
| 860 | + data = usedBuffers.remove(0); | ||
| 861 | + System.out.println("Disposing " + data + " in disposeSourceBuffer"); | ||
| 862 | + } catch (NoSuchElementException ex) { | ||
| 863 | + PGraphics.showWarning("Cannot remove used buffer"); | ||
| 864 | + } | ||
| 865 | + if (data != null) { | ||
| 866 | + data.dispose(); | ||
| 867 | + } | ||
| 868 | + } | ||
| 869 | + } | ||
| 870 | + | ||
| 871 | + public void getBufferPixels(int[] pixels) { | ||
| 872 | + BufferData data = null; | ||
| 873 | + if (usedBuffers != null && 0 < usedBuffers.size()) { | ||
| 874 | + // the last used buffer is the one currently stored in the opengl the | ||
| 875 | + // texture | ||
| 876 | + data = usedBuffers.getLast(); | ||
| 877 | + } else if (bufferCache != null && 0 < bufferCache.size()) { | ||
| 878 | + // The first buffer in the cache will be uploaded to the opengl texture | ||
| 879 | + // the next time it is rendered | ||
| 880 | + data = bufferCache.getFirst(); | ||
| 881 | + } | ||
| 882 | + if (data != null) { | ||
| 883 | + data.rgbBuf.rewind(); | ||
| 884 | + data.rgbBuf.get(pixels); | ||
| 885 | + convertToARGB(pixels); | ||
| 886 | + } | ||
| 887 | + } | ||
| 888 | + | ||
| 889 | + | ||
| 874 | 890 | public boolean hasBufferSource() { | |
| 875 | 891 | return bufferSource != null; | |
| 876 | 892 | } | |
@@ -894,35 +910,15 @@ protected boolean bufferUpdate() { | |||
| 894 | 910 | if ((data.w != width) || (data.h != height)) { | |
| 895 | 911 | init(data.w, data.h); | |
| 896 | 912 | } | |
| 913 | + data.rgbBuf.rewind(); | ||
| 897 | 914 | setNative(data.rgbBuf, 0, 0, width, height); | |
| 898 | 915 | ||
| 899 | - data.dispose(); | ||
| 900 | - | ||
| 901 | - return true; | ||
| 902 | - } else { | ||
| 903 | - return false; | ||
| 904 | - } | ||
| 905 | - } | ||
| 906 | - | ||
| 907 | - | ||
| 908 | - protected boolean bufferUpdate(int[] pixels) { | ||
| 909 | - BufferData data = null; | ||
| 910 | - try { | ||
| 911 | - data = bufferCache.remove(0); | ||
| 912 | - } catch (NoSuchElementException ex) { | ||
| 913 | - PGraphics.showWarning("Don't have pixel data to copy to texture"); | ||
| 914 | - } | ||
| 915 | - | ||
| 916 | - if (data != null) { | ||
| 917 | - if ((data.w != width) || (data.h != height)) { | ||
| 918 | - init(data.w, data.h); | ||
| 916 | + // Putting the buffer in the used buffers list to dispose at the end of | ||
| 917 | + // draw. | ||
| 918 | + if (usedBuffers == null) { | ||
| 919 | + usedBuffers = new LinkedList<BufferData>(); | ||
| 919 | 920 | } | |
| 920 | - setNative(data.rgbBuf, 0, 0, width, height); | ||
| 921 | - | ||
| 922 | - data.rgbBuf.get(pixels); | ||
| 923 | - convertToARGB(pixels); | ||
| 924 | - | ||
| 925 | - data.dispose(); | ||
| 921 | + usedBuffers.add(data); | ||
| 926 | 922 | ||
| 927 | 923 | return true; | |
| 928 | 924 | } else { | |
@@ -1115,8 +1111,8 @@ protected void convertToARGB(int[] intArray) { | |||
| 1115 | 1111 | for (int x = 0; x < width; x++) { | |
| 1116 | 1112 | int pixel = intArray[p++]; | |
| 1117 | 1113 | intArray[t++] = ((pixel & 0xFF) << 16) | | |
| 1118 | - ((pixel & 0xFF0000) >> 16) | | ||
| 1119 | - (pixel & 0xFF00FF00); | ||
| 1114 | + ((pixel & 0xFF0000) >> 16) | | ||
| 1115 | + (pixel & 0xFF00FF00); | ||
| 1120 | 1116 | ||
| 1121 | 1117 | } | |
| 1122 | 1118 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -110,6 +110,8 @@ public class Capture extends PImage implements PConstants { | |||
| 110 | 110 | protected Object bufferSink; | |
| 111 | 111 | protected Method sinkCopyMethod; | |
| 112 | 112 | protected Method sinkSetMethod; | |
| 113 | + protected Method sinkDisposeMethod; | ||
| 114 | + protected Method sinkGetMethod; | ||
| 113 | 115 | protected String copyMask; | |
| 114 | 116 | protected Buffer natBuffer = null; | |
| 115 | 117 | protected BufferDataAppSink natSink = null; | |
@@ -417,7 +419,29 @@ public synchronized void read() { | |||
| 417 | 419 | newFrame = true; | |
| 418 | 420 | } | |
| 419 | 421 | ||
| 420 | - | ||
| 422 | + | ||
| 423 | + public synchronized void loadPixels() { | ||
| 424 | + super.loadPixels(); | ||
| 425 | + if (useBufferSink) { | ||
| 426 | + if (natBuffer != null) { | ||
| 427 | + // This means that the OpenGL texture hasn't been created so far (the | ||
| 428 | + // video frame not drawn using image()), but the user wants to use the | ||
| 429 | + // pixel array, which we can just get from natBuffer. | ||
| 430 | + IntBuffer buf = natBuffer.getByteBuffer().asIntBuffer(); | ||
| 431 | + buf.rewind(); | ||
| 432 | + buf.get(pixels); | ||
| 433 | + Video.convertToARGB(pixels, width, height); | ||
| 434 | + } else if (sinkGetMethod != null) { | ||
| 435 | + try { | ||
| 436 | + sinkGetMethod.invoke(bufferSink, new Object[] { pixels }); | ||
| 437 | + } catch (Exception e) { | ||
| 438 | + e.printStackTrace(); | ||
| 439 | + } | ||
| 440 | + } | ||
| 441 | + } | ||
| 442 | + } | ||
| 443 | + | ||
| 444 | + | ||
| 421 | 445 | //////////////////////////////////////////////////////////// | |
| 422 | 446 | ||
| 423 | 447 | // List methods. | |
@@ -800,6 +824,7 @@ protected void initGStreamer(PApplet parent, int rw, int rh, String src, | |||
| 800 | 824 | ||
| 801 | 825 | // register methods | |
| 802 | 826 | parent.registerMethod("dispose", this); | |
| 827 | + parent.registerMethod("post", this); | ||
| 803 | 828 | ||
| 804 | 829 | setEventHandlerObject(parent); | |
| 805 | 830 | ||
@@ -976,6 +1001,13 @@ protected synchronized void invokeEvent(int w, int h, Buffer buffer) { | |||
| 976 | 1001 | available = true; | |
| 977 | 1002 | bufWidth = w; | |
| 978 | 1003 | bufHeight = h; | |
| 1004 | + if (natBuffer != null) { | ||
| 1005 | + // To handle the situation where read() is not called in the sketch, so | ||
| 1006 | + // that the native buffers are not being sent to the sinke, and therefore, not disposed | ||
| 1007 | + // by it. | ||
| 1008 | + System.out.println(" disposing nat buffer before reading new one"); | ||
| 1009 | + natBuffer.dispose(); | ||
| 1010 | + } | ||
| 979 | 1011 | natBuffer = buffer; | |
| 980 | 1012 | ||
| 981 | 1013 | // Creates a movieEvent. | |
@@ -1129,6 +1161,22 @@ protected void getSinkMethods() { | |||
| 1129 | 1161 | throw new RuntimeException("Capture: provided sink object doesn't have "+ | |
| 1130 | 1162 | "a setBufferSource method."); | |
| 1131 | 1163 | } | |
| 1164 | + | ||
| 1165 | + try { | ||
| 1166 | + sinkDisposeMethod = bufferSink.getClass().getMethod("disposeSourceBuffer", | ||
| 1167 | + new Class[] { }); | ||
| 1168 | + } catch (Exception e) { | ||
| 1169 | + throw new RuntimeException("Capture: provided sink object doesn't have " + | ||
| 1170 | + "a disposeSourceBuffer method."); | ||
| 1171 | + } | ||
| 1172 | + | ||
| 1173 | + try { | ||
| 1174 | + sinkGetMethod = bufferSink.getClass().getMethod("getBufferPixels", | ||
| 1175 | + new Class[] { int[].class }); | ||
| 1176 | + } catch (Exception e) { | ||
| 1177 | + throw new RuntimeException("Capture: provided sink object doesn't have " + | ||
| 1178 | + "a getBufferPixels method."); | ||
| 1179 | + } | ||
| 1132 | 1180 | } | |
| 1133 | 1181 | ||
| 1134 | 1182 | ||
@@ -1139,4 +1187,15 @@ protected void initCopyMask() { | |||
| 1139 | 1187 | copyMask = "red_mask=(int)0xFF, green_mask=(int)0xFF00, blue_mask=(int)0xFF0000"; | |
| 1140 | 1188 | } | |
| 1141 | 1189 | } | |
| 1190 | + | ||
| 1191 | + | ||
| 1192 | + public synchronized void post() { | ||
| 1193 | + if (useBufferSink && sinkDisposeMethod != null) { | ||
| 1194 | + try { | ||
| 1195 | + sinkDisposeMethod.invoke(bufferSink, new Object[] {}); | ||
| 1196 | + } catch (Exception e) { | ||
| 1197 | + e.printStackTrace(); | ||
| 1198 | + } | ||
| 1199 | + } | ||
| 1200 | + } | ||
| 1142 | 1201 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -82,6 +82,8 @@ public class Movie extends PImage implements PConstants { | |||
| 82 | 82 | protected Object bufferSink; | |
| 83 | 83 | protected Method sinkCopyMethod; | |
| 84 | 84 | protected Method sinkSetMethod; | |
| 85 | + protected Method sinkDisposeMethod; | ||
| 86 | + protected Method sinkGetMethod; | ||
| 85 | 87 | protected String copyMask; | |
| 86 | 88 | protected Buffer natBuffer = null; | |
| 87 | 89 | protected BufferDataAppSink natSink = null; | |
@@ -542,6 +544,28 @@ public void volume(float v) { | |||
| 542 | 544 | } | |
| 543 | 545 | ||
| 544 | 546 | ||
| 547 | + public synchronized void loadPixels() { | ||
| 548 | + super.loadPixels(); | ||
| 549 | + if (useBufferSink) { | ||
| 550 | + if (natBuffer != null) { | ||
| 551 | + // This means that the OpenGL texture hasn't been created so far (the | ||
| 552 | + // video frame not drawn using image()), but the user wants to use the | ||
| 553 | + // pixel array, which we can just get from natBuffer. | ||
| 554 | + IntBuffer buf = natBuffer.getByteBuffer().asIntBuffer(); | ||
| 555 | + buf.rewind(); | ||
| 556 | + buf.get(pixels); | ||
| 557 | + Video.convertToARGB(pixels, width, height); | ||
| 558 | + } else if (sinkGetMethod != null) { | ||
| 559 | + try { | ||
| 560 | + sinkGetMethod.invoke(bufferSink, new Object[] { pixels }); | ||
| 561 | + } catch (Exception e) { | ||
| 562 | + e.printStackTrace(); | ||
| 563 | + } | ||
| 564 | + } | ||
| 565 | + } | ||
| 566 | + } | ||
| 567 | + | ||
| 568 | + | ||
| 545 | 569 | //////////////////////////////////////////////////////////// | |
| 546 | 570 | ||
| 547 | 571 | // Initialization methods. | |
@@ -609,11 +633,11 @@ protected void initGStreamer(PApplet parent, String filename) { | |||
| 609 | 633 | ||
| 610 | 634 | // we've got a valid movie! let's rock. | |
| 611 | 635 | try { | |
| 612 | - // PApplet.println("we've got a valid movie! let's rock."); | ||
| 613 | 636 | this.filename = filename; // for error messages | |
| 614 | 637 | ||
| 615 | 638 | // register methods | |
| 616 | 639 | parent.registerMethod("dispose", this); | |
| 640 | + parent.registerMethod("post", this); | ||
| 617 | 641 | ||
| 618 | 642 | setEventHandlerObject(parent); | |
| 619 | 643 | ||
@@ -742,6 +766,13 @@ protected synchronized void invokeEvent(int w, int h, Buffer buffer) { | |||
| 742 | 766 | available = true; | |
| 743 | 767 | bufWidth = w; | |
| 744 | 768 | bufHeight = h; | |
| 769 | + if (natBuffer != null) { | ||
| 770 | + // To handle the situation where read() is not called in the sketch, so | ||
| 771 | + // that the native buffers are not being sent to the sinke, and therefore, not disposed | ||
| 772 | + // by it. | ||
| 773 | + System.out.println(" disposing nat buffer before reading new one"); | ||
| 774 | + natBuffer.dispose(); | ||
| 775 | + } | ||
| 745 | 776 | natBuffer = buffer; | |
| 746 | 777 | ||
| 747 | 778 | if (playing) { | |
@@ -894,6 +925,22 @@ protected void getSinkMethods() { | |||
| 894 | 925 | throw new RuntimeException("Movie: provided sink object doesn't have a " + | |
| 895 | 926 | "setBufferSource method."); | |
| 896 | 927 | } | |
| 928 | + | ||
| 929 | + try { | ||
| 930 | + sinkDisposeMethod = bufferSink.getClass().getMethod("disposeSourceBuffer", | ||
| 931 | + new Class[] { }); | ||
| 932 | + } catch (Exception e) { | ||
| 933 | + throw new RuntimeException("Movie: provided sink object doesn't have " + | ||
| 934 | + "a disposeSourceBuffer method."); | ||
| 935 | + } | ||
| 936 | + | ||
| 937 | + try { | ||
| 938 | + sinkGetMethod = bufferSink.getClass().getMethod("getBufferPixels", | ||
| 939 | + new Class[] { int[].class }); | ||
| 940 | + } catch (Exception e) { | ||
| 941 | + throw new RuntimeException("Movie: provided sink object doesn't have " + | ||
| 942 | + "a getBufferPixels method."); | ||
| 943 | + } | ||
| 897 | 944 | } | |
| 898 | 945 | ||
| 899 | 946 | ||
@@ -902,6 +949,17 @@ protected void initCopyMask() { | |||
| 902 | 949 | copyMask = "red_mask=(int)0xFF000000, green_mask=(int)0xFF0000, blue_mask=(int)0xFF00"; | |
| 903 | 950 | } else { | |
| 904 | 951 | copyMask = "red_mask=(int)0xFF, green_mask=(int)0xFF00, blue_mask=(int)0xFF0000"; | |
| 952 | + } | ||
| 953 | + } | ||
| 954 | + | ||
| 955 | + | ||
| 956 | + public synchronized void post() { | ||
| 957 | + if (useBufferSink && sinkDisposeMethod != null) { | ||
| 958 | + try { | ||
| 959 | + sinkDisposeMethod.invoke(bufferSink, new Object[] {}); | ||
| 960 | + } catch (Exception e) { | ||
| 961 | + e.printStackTrace(); | ||
| 962 | + } | ||
| 905 | 963 | } | |
| 906 | 964 | } | |
| 907 | 965 | } | |
| Back | FazBrowse Home | New Git URL |
0 commit comments