package com.example.datalibrary.gl.shape; import android.graphics.Rect; import android.opengl.GLES11Ext; import android.opengl.GLES20; import com.example.datalibrary.gl.utils.ShaderUtils; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; public class GLFrame { private int width; private int height; private int screenWidth; private int screenHeight; public float getWd() { return wd; } public float getHd() { return hd; } private float wd = 1; private float hd = 1; private float[] vertexData = { 1f, -1f, 0f, -1f, -1f, 0f, 1f, 1f, 0f, -1f, 1f, 0f }; private final float[] textureVertexReverseData = { 0f, 0f, 1f, 0f, 0f, 1f, 1f, 1f, }; private final float[] textureVertexData = { 1f, 0f, 0f, 0f, 1f, 1f, 0f, 1f }; private FloatBuffer vertexBuffer; private int mirrorRGB; private FloatBuffer textureVertexBuffer; private int programId = -1; private int aPositionHandle; private int uTextureSamplerHandle; private int iTextureSamplerHandle; private int aTextureCoordHandle; private int uSTMMatrixHandle; private int sHandle; private int hHandle; private int lHandle; private int iHandle; private int[] vertexBuffers; private String fragmentShader = "#extension GL_OES_EGL_image_external : require\n" + "varying highp vec2 vTexCoord;\n" + "uniform samplerExternalOES sTexture;\n" + "uniform sampler2D iTexture;\n" + "uniform highp mat4 usTMatrix;\n" + "uniform highp float S;\n" + "uniform highp float H;\n"+ "uniform highp float L;\n"+ "uniform highp float i;\n"+ "highp vec3 rgb2hsv(highp vec3 c){\n" + " highp vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n" + " highp vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\n" + " highp vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n" + " highp float d = q.x - min(q.w, q.y);\n" + " highp float e = 1.0e-10;\n" + " return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\n" + "}\n" + "highp vec3 hsv2rgb(highp vec3 c){\n" + " highp vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n" + " highp vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n" + " return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n" + "}"+ "void main() {\n" + " highp vec2 tx_transformed = (usTMatrix * vec4(vTexCoord, 0, 1.0)).xy;\n" + " highp vec4 video = texture2D(sTexture , tx_transformed);\n" + " highp vec4 rgba;\n"+ " if(i == 0.0){\n" + " rgba = video;\n" + " }\n"+ " else{\n" + " highp vec4 image = texture2D(iTexture , vTexCoord);\n" + " rgba = mix(video,image , image.a);\n"+ " }\n"+ " highp vec3 hsl = rgb2hsv(rgba.xyz);\n"+ " if(H != 0.0)hsl.x = H;\n" + " if(hsl.x<0.0)hsl.x = hsl.x+1.0;\n" + " else if(hsl.x>1.0)hsl.x = hsl.x-1.0;\n"+ " if(S != 1.0)hsl.y = hsl.y*S;\n"+ " highp vec3 rgb = hsv2rgb(hsl);\n" + " if (L < 0.0) rgb = rgb + rgb * vec3(L);\n"+ " else rgb = rgb + (1.0 - rgb) * vec3(L);\n"+ " gl_FragColor = vec4(rgb,rgba.w);\n" + "}"; private String vertexShader = "attribute vec4 aPosition;\n" + "attribute vec2 aTexCoord;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n" + " vTexCoord = aTexCoord;\n" + " gl_Position = aPosition;\n" + "}"; private void againInit(){ vertexBuffer = ByteBuffer.allocateDirect(vertexData.length * 4) .order(ByteOrder.nativeOrder()) .asFloatBuffer() .put(vertexData); vertexBuffer.position(0); if (mirrorRGB == 0){ textureVertexBuffer = ByteBuffer.allocateDirect(textureVertexData.length * 4) .order(ByteOrder.nativeOrder()) .asFloatBuffer() .put(textureVertexData); }else { textureVertexBuffer = ByteBuffer.allocateDirect(textureVertexReverseData.length * 4) .order(ByteOrder.nativeOrder()) .asFloatBuffer() .put(textureVertexReverseData); } textureVertexBuffer.position(0); initFrame(); } public GLFrame(int mirrorRGB){ vertexBuffer = ByteBuffer.allocateDirect(vertexData.length * 4) .order(ByteOrder.nativeOrder()) .asFloatBuffer() .put(vertexData); vertexBuffer.position(0); this.mirrorRGB = mirrorRGB; if (mirrorRGB == 0){ textureVertexBuffer = ByteBuffer.allocateDirect(textureVertexData.length * 4) .order(ByteOrder.nativeOrder()) .asFloatBuffer() .put(textureVertexData); }else { textureVertexBuffer = ByteBuffer.allocateDirect(textureVertexReverseData.length * 4) .order(ByteOrder.nativeOrder()) .asFloatBuffer() .put(textureVertexReverseData); } textureVertexBuffer.position(0); } public void initFrame(){ programId = ShaderUtils.createProgram(vertexShader, fragmentShader); aPositionHandle = GLES20.glGetAttribLocation(programId, "aPosition"); uSTMMatrixHandle = GLES20.glGetUniformLocation(programId, "usTMatrix"); uTextureSamplerHandle = GLES20.glGetUniformLocation(programId, "sTexture"); iTextureSamplerHandle = GLES20.glGetUniformLocation(programId, "iTexture"); aTextureCoordHandle = GLES20.glGetAttribLocation(programId, "aTexCoord"); sHandle = GLES20.glGetUniformLocation(programId , "S"); hHandle = GLES20.glGetUniformLocation(programId , "H"); lHandle = GLES20.glGetUniformLocation(programId , "L"); iHandle = GLES20.glGetUniformLocation(programId , "i"); vertexBuffers = new int[2]; GLES20.glGenBuffers(2 , vertexBuffers , 0); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBuffers[0]); GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertexData.length * 4, vertexBuffer , GLES20.GL_STATIC_DRAW); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBuffers[1]); GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, textureVertexData.length * 4, textureVertexBuffer , GLES20.GL_STATIC_DRAW); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); } private float s = 1.0f; public void setS(float s){ this.s = s; } private float h = 0.0f; public void setH(float h) { this.h = h; } private float l = 1.0f; public void setL(float l) { this.l = l; } private boolean isInit; private Rect rect = new Rect(); public void setSize(int screenWidth , int screenHeight , int videoWidth , int videoHeight){ if (isInit){ return; } isInit = true; this.screenWidth = screenWidth; this.screenHeight = screenHeight; this.width = videoWidth; this.height = videoHeight; if (screenHeight > screenWidth && videoWidth > videoHeight){ wd = (float) screenHeight / (float) videoHeight; }else if (screenHeight < screenWidth && videoWidth < videoHeight){ hd = (float) screenWidth / (float) videoWidth; }else if (videoWidth < screenWidth && videoHeight < screenHeight){ float ywd = (float) videoWidth / (float) screenWidth; float yhd = (float) videoHeight / (float) screenHeight; float ywd1 = 1 - ywd; float yhd1 = 1 - yhd; if (ywd > yhd){ wd = ywd + yhd1; }else { hd += yhd + ywd1; } } // vertexData = new float[]{ // 1f, -1f, 0f, // -1f, -1f, 0f, // 1f, 1f, 0f, // -1f, 1f, 0f // }; vertexData = new float[]{ wd, -hd, 0f, -wd, -hd, 0f, wd, hd, 0f, -wd, hd, 0f }; againInit(); rect(); } public void correctSize(int videoWidth , int videoHeight){ if (this.width == videoWidth && this.height == videoHeight){ return; } // setSize(screenHeight , screenWidth , videoWidth , videoHeight); } private void rect(){ /*int left,top,viewWidth,viewHeight; float sh = screenWidth*1.0f/screenHeight; float vh = width *1.0f/ height; if(sh < vh){ left = 0; viewWidth = screenWidth; viewHeight = (int)(height *1.0f/ width *viewWidth); top = (screenHeight - viewHeight)/2; }else{ top = 0; viewHeight = screenHeight; viewWidth = (int)(width *1.0f/ height *viewHeight); left = (screenWidth - viewWidth)/2; }*/ // rect.left = 0; // rect.top = 0; // rect.right = screenWidth; // rect.bottom = screenHeight; rect.left = 0; rect.top = 0; rect.right = screenWidth; rect.bottom = screenHeight; } public void drawFrame(int tId , int textureId , float[] sTMatrix){ GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT); GLES20.glViewport(rect.left, rect.top, rect.right, rect.bottom); GLES20.glUseProgram(programId); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBuffers[0]); GLES20.glEnableVertexAttribArray(aPositionHandle); GLES20.glVertexAttribPointer(aPositionHandle , 3, GLES20.GL_FLOAT, false , 0, 0); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBuffers[1]); GLES20.glEnableVertexAttribArray(aTextureCoordHandle); GLES20.glVertexAttribPointer(aTextureCoordHandle , 2, GLES20.GL_FLOAT, false , 0, 0); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); GLES20.glActiveTexture(GLES20.GL_TEXTURE0); GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES , textureId); GLES20.glUniform1i(uTextureSamplerHandle , 0); GLES20.glUniformMatrix4fv(uSTMMatrixHandle , 1, false , sTMatrix, 0); GLES20.glActiveTexture(GLES20.GL_TEXTURE1); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tId); GLES20.glUniform1i(iTextureSamplerHandle , 1); GLES20.glUniform1f(sHandle , s); GLES20.glUniform1f(hHandle , h); GLES20.glUniform1f(lHandle , l); GLES20.glUniform1f(iHandle , tId); GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); } public void release(){ if (vertexBuffers == null){ return; } GLES20.glDeleteProgram(programId); GLES20.glDeleteBuffers(2 , vertexBuffers , 0); } }