• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.example.nativecodec;
18 
19 import android.graphics.SurfaceTexture;
20 import android.util.Log;
21 
22 import java.nio.ByteBuffer;
23 import java.nio.ByteOrder;
24 import java.nio.FloatBuffer;
25 
26 import javax.microedition.khronos.egl.EGLConfig;
27 import javax.microedition.khronos.opengles.GL10;
28 
29 import android.content.Context;
30 import android.opengl.GLES20;
31 import android.opengl.GLSurfaceView;
32 import android.opengl.Matrix;
33 import android.os.SystemClock;
34 import android.util.AttributeSet;
35 
36 public class MyGLSurfaceView extends GLSurfaceView {
37 
38     MyRenderer mRenderer;
39 
MyGLSurfaceView(Context context)40     public MyGLSurfaceView(Context context) {
41         this(context, null);
42     }
43 
MyGLSurfaceView(Context context, AttributeSet attributeSet)44     public MyGLSurfaceView(Context context, AttributeSet attributeSet) {
45         super(context, attributeSet);
46         init();
47     }
48 
init()49     private void init() {
50         setEGLContextClientVersion(2);
51         mRenderer = new MyRenderer();
52         setRenderer(mRenderer);
53         Log.i("@@@", "setrenderer");
54     }
55 
56     @Override
onPause()57     public void onPause() {
58         mRenderer.onPause();
59         super.onPause();
60     }
61 
62     @Override
onResume()63     public void onResume() {
64         super.onResume();
65         mRenderer.onResume();
66     }
67 
getSurfaceTexture()68     public SurfaceTexture getSurfaceTexture() {
69         return mRenderer.getSurfaceTexture();
70     }
71 }
72 
73 class MyRenderer implements GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener {
74 
MyRenderer()75     public MyRenderer() {
76         mVertices = ByteBuffer.allocateDirect(mVerticesData.length
77                 * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
78         mVertices.put(mVerticesData).position(0);
79 
80         Matrix.setIdentityM(mSTMatrix, 0);
81     }
onPause()82     public void onPause() {
83     }
84 
onResume()85     public void onResume() {
86         mLastTime = SystemClock.elapsedRealtimeNanos();
87     }
88 
89     @Override
onDrawFrame(GL10 glUnused)90     public void onDrawFrame(GL10 glUnused) {
91         synchronized(this) {
92             if (updateSurface) {
93                 mSurface.updateTexImage();
94 
95                 mSurface.getTransformMatrix(mSTMatrix);
96                 updateSurface = false;
97             }
98         }
99 
100         // Ignore the passed-in GL10 interface, and use the GLES20
101         // class's static methods instead.
102         GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
103         GLES20.glUseProgram(mProgram);
104         checkGlError("glUseProgram");
105 
106         GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
107         GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureID);
108 
109         mVertices.position(VERTICES_DATA_POS_OFFSET);
110         GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false,
111                 VERTICES_DATA_STRIDE_BYTES, mVertices);
112         checkGlError("glVertexAttribPointer maPosition");
113         GLES20.glEnableVertexAttribArray(maPositionHandle);
114         checkGlError("glEnableVertexAttribArray maPositionHandle");
115 
116         mVertices.position(VERTICES_DATA_UV_OFFSET);
117         GLES20.glVertexAttribPointer(maTextureHandle, 3, GLES20.GL_FLOAT, false,
118                 VERTICES_DATA_STRIDE_BYTES, mVertices);
119         checkGlError("glVertexAttribPointer maTextureHandle");
120         GLES20.glEnableVertexAttribArray(maTextureHandle);
121         checkGlError("glEnableVertexAttribArray maTextureHandle");
122 
123         long now = SystemClock.elapsedRealtimeNanos();
124         mRunTime += (now - mLastTime);
125         mLastTime = now;
126         double d = ((double)mRunTime) / 1000000000;
127         Matrix.setIdentityM(mMMatrix, 0);
128         Matrix.rotateM(mMMatrix, 0, 30, (float)Math.sin(d), (float)Math.cos(d), 0);
129         Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0);
130         Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
131 
132         GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
133         GLES20.glUniformMatrix4fv(muSTMatrixHandle, 1, false, mSTMatrix, 0);
134 
135         GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
136         checkGlError("glDrawArrays");
137     }
138 
139     @Override
onSurfaceChanged(GL10 glUnused, int width, int height)140     public void onSurfaceChanged(GL10 glUnused, int width, int height) {
141         // Ignore the passed-in GL10 interface, and use the GLES20
142         // class's static methods instead.
143         GLES20.glViewport(0, 0, width, height);
144         mRatio = (float) width / height;
145         Matrix.frustumM(mProjMatrix, 0, -mRatio, mRatio, -1, 1, 3, 7);
146     }
147 
148     @Override
onSurfaceCreated(GL10 glUnused, EGLConfig config)149     public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
150         // Ignore the passed-in GL10 interface, and use the GLES20
151         // class's static methods instead.
152 
153         /* Set up alpha blending and an Android background color */
154         GLES20.glEnable(GLES20.GL_BLEND);
155         GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
156         GLES20.glClearColor(0.643f, 0.776f, 0.223f, 1.0f);
157 
158         /* Set up shaders and handles to their variables */
159         mProgram = createProgram(mVertexShader, mFragmentShader);
160         if (mProgram == 0) {
161             return;
162         }
163         maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
164         checkGlError("glGetAttribLocation aPosition");
165         if (maPositionHandle == -1) {
166             throw new RuntimeException("Could not get attrib location for aPosition");
167         }
168         maTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord");
169         checkGlError("glGetAttribLocation aTextureCoord");
170         if (maTextureHandle == -1) {
171             throw new RuntimeException("Could not get attrib location for aTextureCoord");
172         }
173 
174         muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
175         checkGlError("glGetUniformLocation uMVPMatrix");
176         if (muMVPMatrixHandle == -1) {
177             throw new RuntimeException("Could not get attrib location for uMVPMatrix");
178         }
179 
180         muSTMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uSTMatrix");
181         checkGlError("glGetUniformLocation uSTMatrix");
182         if (muMVPMatrixHandle == -1) {
183             throw new RuntimeException("Could not get attrib location for uSTMatrix");
184         }
185 
186         checkGlError("glGetUniformLocation uCRatio");
187         if (muMVPMatrixHandle == -1) {
188             throw new RuntimeException("Could not get attrib location for uCRatio");
189         }
190 
191         /*
192          * Create our texture. This has to be done each time the
193          * surface is created.
194          */
195 
196         int[] textures = new int[1];
197         GLES20.glGenTextures(1, textures, 0);
198 
199         mTextureID = textures[0];
200         GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureID);
201         checkGlError("glBindTexture mTextureID");
202 
203         // Can't do mipmapping with camera source
204         GLES20.glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER,
205                 GLES20.GL_NEAREST);
206         GLES20.glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER,
207                 GLES20.GL_LINEAR);
208         // Clamp to edge is the only option
209         GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S,
210                 GLES20.GL_CLAMP_TO_EDGE);
211         GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T,
212                 GLES20.GL_CLAMP_TO_EDGE);
213         checkGlError("glTexParameteri mTextureID");
214 
215         /*
216          * Create the SurfaceTexture that will feed this textureID, and pass it to the camera
217          */
218 
219         mSurface = new SurfaceTexture(mTextureID);
220         mSurface.setOnFrameAvailableListener(this);
221 
222         Matrix.setLookAtM(mVMatrix, 0, 0, 0, 4f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
223 
224         synchronized(this) {
225             updateSurface = false;
226         }
227     }
228 
229     @Override
onFrameAvailable(SurfaceTexture surface)230     synchronized public void onFrameAvailable(SurfaceTexture surface) {
231         /* For simplicity, SurfaceTexture calls here when it has new
232          * data available.  Call may come in from some random thread,
233          * so let's be safe and use synchronize. No OpenGL calls can be done here.
234          */
235         updateSurface = true;
236         //Log.v(TAG, "onFrameAvailable " + surface.getTimestamp());
237     }
238 
loadShader(int shaderType, String source)239     private int loadShader(int shaderType, String source) {
240         int shader = GLES20.glCreateShader(shaderType);
241         if (shader != 0) {
242             GLES20.glShaderSource(shader, source);
243             GLES20.glCompileShader(shader);
244             int[] compiled = new int[1];
245             GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
246             if (compiled[0] == 0) {
247                 Log.e(TAG, "Could not compile shader " + shaderType + ":");
248                 Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
249                 GLES20.glDeleteShader(shader);
250                 shader = 0;
251             }
252         }
253         return shader;
254     }
255 
createProgram(String vertexSource, String fragmentSource)256     private int createProgram(String vertexSource, String fragmentSource) {
257         int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
258         if (vertexShader == 0) {
259             return 0;
260         }
261         int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
262         if (pixelShader == 0) {
263             return 0;
264         }
265 
266         int program = GLES20.glCreateProgram();
267         if (program != 0) {
268             GLES20.glAttachShader(program, vertexShader);
269             checkGlError("glAttachShader");
270             GLES20.glAttachShader(program, pixelShader);
271             checkGlError("glAttachShader");
272             GLES20.glLinkProgram(program);
273             int[] linkStatus = new int[1];
274             GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
275             if (linkStatus[0] != GLES20.GL_TRUE) {
276                 Log.e(TAG, "Could not link program: ");
277                 Log.e(TAG, GLES20.glGetProgramInfoLog(program));
278                 GLES20.glDeleteProgram(program);
279                 program = 0;
280             }
281         }
282         return program;
283     }
284 
checkGlError(String op)285     private void checkGlError(String op) {
286         int error;
287         while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
288             Log.e(TAG, op + ": glError " + error);
289             throw new RuntimeException(op + ": glError " + error);
290         }
291     }
292 
293     private static final int FLOAT_SIZE_BYTES = 4;
294     private static final int VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
295     private static final int VERTICES_DATA_POS_OFFSET = 0;
296     private static final int VERTICES_DATA_UV_OFFSET = 3;
297     private final float[] mVerticesData = {
298         // X, Y, Z, U, V
299         -1.25f, -1.0f, 0, 0.f, 0.f,
300          1.25f, -1.0f, 0, 1.f, 0.f,
301         -1.25f,  1.0f, 0, 0.f, 1.f,
302          1.25f,  1.0f, 0, 1.f, 1.f,
303     };
304 
305     private FloatBuffer mVertices;
306 
307     private final String mVertexShader =
308         "uniform mat4 uMVPMatrix;\n" +
309         "uniform mat4 uSTMatrix;\n" +
310         "attribute vec4 aPosition;\n" +
311         "attribute vec4 aTextureCoord;\n" +
312         "varying vec2 vTextureCoord;\n" +
313         "void main() {\n" +
314         "  gl_Position = uMVPMatrix * aPosition;\n" +
315         "  vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" +
316         "}\n";
317 
318     private final String mFragmentShader =
319         "#extension GL_OES_EGL_image_external : require\n" +
320         "precision mediump float;\n" +
321         "varying vec2 vTextureCoord;\n" +
322         "uniform samplerExternalOES sTexture;\n" +
323         "void main() {\n" +
324         "  gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +
325         "}\n";
326 
327     private float[] mMVPMatrix = new float[16];
328     private float[] mProjMatrix = new float[16];
329     private float[] mMMatrix = new float[16];
330     private float[] mVMatrix = new float[16];
331     private float[] mSTMatrix = new float[16];
332 
333     private int mProgram;
334     private int mTextureID;
335     private int muMVPMatrixHandle;
336     private int muSTMatrixHandle;
337     private int maPositionHandle;
338     private int maTextureHandle;
339 
340     private float mRatio = 1.0f;
341     private SurfaceTexture mSurface;
342     private boolean updateSurface = false;
343     private long mLastTime = -1;
344     private long mRunTime = 0;
345 
346     private static final String TAG = "MyRenderer";
347 
348     // Magic key
349     private static final int GL_TEXTURE_EXTERNAL_OES = 0x8D65;
350 
getSurfaceTexture()351     public SurfaceTexture getSurfaceTexture() {
352         return mSurface;
353     }
354 }
355