package com.basic.security.opengles; import java.nio.ByteBuffer; import java.util.Arrays; /** * Java version of VideoRendererInterface. In addition to allowing clients to * define their own rendering behavior (by passing in a Callbacks object), this * class also provides a createGui() method for creating a GUI-rendering window * on various platforms. */ public class VideoRenderer { // |this| either wraps a native (GUI) renderer or a client-supplied Callbacks // (Java) implementation; so exactly one of these will be non-0/null. final long nativeVideoRenderer; private final Callbacks callbacks; private VideoRenderer(long nativeVideoRenderer) { this.nativeVideoRenderer = nativeVideoRenderer; callbacks = null; } public void dispose() { // free(nativeVideoRenderer); } // public static VideoRenderer createGui(int x, int y) { // long nativeVideoRenderer = nativeCreateGuiVideoRenderer(x, y); // if (nativeVideoRenderer == 0) { // return null; // } // return new VideoRenderer(nativeVideoRenderer); // } // public VideoRenderer(Callbacks callbacks) { // nativeVideoRenderer = nativeWrapVideoRenderer(callbacks); // this.callbacks = callbacks; // } /** * The real meat of VideoRendererInterface. */ public static interface Callbacks { public void setSize(int width, int height); public void renderFrame(I420Frame frame); } /** * Java version of cricket::VideoFrame. */ public static class I420Frame { public final int width; public final int height; public final int[] yuvStrides; public final ByteBuffer[] yuvPlanes; /** * Construct a frame of the given dimensions with the specified planar * data. If |yuvPlanes| is null, new planes of the appropriate sizes are * allocated. */ public I420Frame( int width, int height, int[] yuvStrides, ByteBuffer[] yuvPlanes) { this.width = width; this.height = height; this.yuvStrides = yuvStrides; if (yuvPlanes == null) { yuvPlanes = new ByteBuffer[3]; yuvPlanes[0] = ByteBuffer.allocateDirect(yuvStrides[0] * height); yuvPlanes[1] = ByteBuffer.allocateDirect(yuvStrides[1] * height); yuvPlanes[2] = ByteBuffer.allocateDirect(yuvStrides[2] * height); } this.yuvPlanes = yuvPlanes; } /** * Copy the planes out of |source| into |this| and return |this|. Calling * this with mismatched frame dimensions is a programming error and will * likely crash. */ public I420Frame copyFrom(I420Frame source) { if (!Arrays.equals(yuvStrides, source.yuvStrides) || width != source.width || height != source.height) { throw new RuntimeException("Mismatched dimensions! Source: " + source.toString() + ", destination: " + toString()); } copyPlane(source.yuvPlanes[0], yuvPlanes[0]); copyPlane(source.yuvPlanes[1], yuvPlanes[1]); copyPlane(source.yuvPlanes[2], yuvPlanes[2]); return this; } @Override public String toString() { return width + "x" + height + ":" + yuvStrides[0] + ":" + yuvStrides[1] + ":" + yuvStrides[2]; } // Copy the bytes out of |src| and into |dst|, ignoring and overwriting // positon & limit in both buffers. private void copyPlane(ByteBuffer src, ByteBuffer dst) { // System1.out.println("aaa src " + src.capacity() + " dst " + dst.capacity()); src.position(0).limit(src.capacity()); dst.put(src); dst.position(0).limit(dst.capacity()); } } // private static native long nativeCreateGuiVideoRenderer(int x, int y); // private static native long nativeWrapVideoRenderer(Callbacks callbacks); // // private static native void free(long nativeVideoRenderer); }