Back to project page AndroidVideoSamples.
The source code is released under:
Apache License
If you think the Android project AndroidVideoSamples listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
/* * Copyright (C) 2013 The Android Open Source Project *//from ww w.ja va2s . co m * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.roryhool.commonvideolibrary; import android.opengl.EGL14; import android.opengl.EGLConfig; import android.opengl.EGLContext; import android.opengl.EGLDisplay; import android.opengl.EGLExt; import android.opengl.EGLSurface; import android.util.Log; import android.view.Surface; /** * Holds state associated with a Surface used for MediaCodec encoder input. * <p> * The constructor takes a Surface obtained from MediaCodec.createInputSurface(), and uses that to create an EGL window surface. Calls to eglSwapBuffers() cause a frame of data to be sent to the video encoder. */ class InputSurface { private static final String TAG = "InputSurface"; private static final boolean VERBOSE = false; private static final int EGL_RECORDABLE_ANDROID = 0x3142; private static final int EGL_OPENGL_ES2_BIT = 4; private EGLDisplay mEGLDisplay; private EGLContext mEGLContext; private EGLSurface mEGLSurface; private Surface mSurface; /** * Creates an InputSurface from a Surface. */ public InputSurface( Surface surface ) { if ( surface == null ) { throw new NullPointerException(); } mSurface = surface; eglSetup(); } /** * Prepares EGL. We want a GLES 2.0 context and a surface that supports recording. */ private void eglSetup() { mEGLDisplay = EGL14.eglGetDisplay( EGL14.EGL_DEFAULT_DISPLAY ); if ( mEGLDisplay == EGL14.EGL_NO_DISPLAY ) { throw new RuntimeException( "unable to get EGL14 display" ); } int[] version = new int[2]; if ( !EGL14.eglInitialize( mEGLDisplay, version, 0, version, 1 ) ) { mEGLDisplay = null; throw new RuntimeException( "unable to initialize EGL14" ); } // Configure EGL for pbuffer and OpenGL ES 2.0. We want enough RGB bits // to be able to tell if the frame is reasonable. int[] attribList = { EGL14.EGL_RED_SIZE, 8, EGL14.EGL_GREEN_SIZE, 8, EGL14.EGL_BLUE_SIZE, 8, EGL14.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_RECORDABLE_ANDROID, 1, EGL14.EGL_NONE }; EGLConfig[] configs = new EGLConfig[1]; int[] numConfigs = new int[1]; if ( !EGL14.eglChooseConfig( mEGLDisplay, attribList, 0, configs, 0, configs.length, numConfigs, 0 ) ) { throw new RuntimeException( "unable to find RGB888+recordable ES2 EGL config" ); } // Configure context for OpenGL ES 2.0. int[] attrib_list = { EGL14.EGL_CONTEXT_CLIENT_VERSION, 2, EGL14.EGL_NONE }; mEGLContext = EGL14.eglCreateContext( mEGLDisplay, configs[0], EGL14.EGL_NO_CONTEXT, attrib_list, 0 ); checkEglError( "eglCreateContext" ); if ( mEGLContext == null ) { throw new RuntimeException( "null context" ); } // Create a window surface, and attach it to the Surface we received. int[] surfaceAttribs = { EGL14.EGL_NONE }; mEGLSurface = EGL14.eglCreateWindowSurface( mEGLDisplay, configs[0], mSurface, surfaceAttribs, 0 ); checkEglError( "eglCreateWindowSurface" ); if ( mEGLSurface == null ) { throw new RuntimeException( "surface was null" ); } } /** * Discard all resources held by this class, notably the EGL context. Also releases the Surface that was passed to our constructor. */ public void release() { if ( EGL14.eglGetCurrentContext().equals( mEGLContext ) ) { // Clear the current context and surface to ensure they are discarded immediately. EGL14.eglMakeCurrent( mEGLDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_CONTEXT ); } EGL14.eglDestroySurface( mEGLDisplay, mEGLSurface ); EGL14.eglDestroyContext( mEGLDisplay, mEGLContext ); // EGL14.eglTerminate(mEGLDisplay); mSurface.release(); // null everything out so future attempts to use this object will cause an NPE mEGLDisplay = null; mEGLContext = null; mEGLSurface = null; mSurface = null; } /** * Makes our EGL context and surface current. */ public void makeCurrent() { if ( !EGL14.eglMakeCurrent( mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext ) ) { throw new RuntimeException( "eglMakeCurrent failed" ); } } /** * Calls eglSwapBuffers. Use this to "publish" the current frame. */ public boolean swapBuffers() { return EGL14.eglSwapBuffers( mEGLDisplay, mEGLSurface ); } /** * Returns the Surface that the MediaCodec receives buffers from. */ public Surface getSurface() { return mSurface; } /** * Sends the presentation time stamp to EGL. Time is expressed in nanoseconds. */ public void setPresentationTime( long nsecs ) { EGLExt.eglPresentationTimeANDROID( mEGLDisplay, mEGLSurface, nsecs ); } /** * Checks for EGL errors. */ private void checkEglError( String msg ) { boolean failed = false; int error; while ( ( error = EGL14.eglGetError() ) != EGL14.EGL_SUCCESS ) { Log.e( TAG, msg + ": EGL error: 0x" + Integer.toHexString( error ) ); failed = true; } if ( failed ) { throw new RuntimeException( "EGL error encountered (see log)" ); } } }