Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2013 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 android.media.cts;
     18 
     19 import android.opengl.EGL14;
     20 import android.opengl.EGLExt;
     21 import android.opengl.EGLConfig;
     22 import android.opengl.EGLContext;
     23 import android.opengl.EGLDisplay;
     24 import android.opengl.EGLSurface;
     25 import android.util.Log;
     26 import android.view.Surface;
     27 
     28 
     29 /**
     30  * Holds state associated with a Surface used for MediaCodec encoder input.
     31  * <p>
     32  * The constructor takes a Surface obtained from MediaCodec.createInputSurface(), and uses that
     33  * to create an EGL window surface.  Calls to eglSwapBuffers() cause a frame of data to be sent
     34  * to the video encoder.
     35  */
     36 class InputSurface {
     37     private static final String TAG = "InputSurface";
     38     private static final boolean VERBOSE = false;
     39 
     40     private static final int EGL_RECORDABLE_ANDROID = 0x3142;
     41 
     42     private EGLDisplay mEGLDisplay = EGL14.EGL_NO_DISPLAY;
     43     private EGLContext mEGLContext = EGL14.EGL_NO_CONTEXT;
     44     private EGLSurface mEGLSurface = EGL14.EGL_NO_SURFACE;
     45 
     46     private Surface mSurface;
     47 
     48     /**
     49      * Creates an InputSurface from a Surface.
     50      */
     51     public InputSurface(Surface surface) {
     52         if (surface == null) {
     53             throw new NullPointerException();
     54         }
     55         mSurface = surface;
     56 
     57         eglSetup();
     58     }
     59 
     60     /**
     61      * Prepares EGL.  We want a GLES 2.0 context and a surface that supports recording.
     62      */
     63     private void eglSetup() {
     64         mEGLDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
     65         if (mEGLDisplay == EGL14.EGL_NO_DISPLAY) {
     66             throw new RuntimeException("unable to get EGL14 display");
     67         }
     68         int[] version = new int[2];
     69         if (!EGL14.eglInitialize(mEGLDisplay, version, 0, version, 1)) {
     70             mEGLDisplay = null;
     71             throw new RuntimeException("unable to initialize EGL14");
     72         }
     73 
     74         // Configure EGL for recordable and OpenGL ES 2.0.  We want enough RGB bits
     75         // to minimize artifacts from possible YUV conversion.
     76         int[] attribList = {
     77                 EGL14.EGL_RED_SIZE, 8,
     78                 EGL14.EGL_GREEN_SIZE, 8,
     79                 EGL14.EGL_BLUE_SIZE, 8,
     80                 EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
     81                 EGL_RECORDABLE_ANDROID, 1,
     82                 EGL14.EGL_NONE
     83         };
     84         EGLConfig[] configs = new EGLConfig[1];
     85         int[] numConfigs = new int[1];
     86         if (!EGL14.eglChooseConfig(mEGLDisplay, attribList, 0, configs, 0, configs.length,
     87                 numConfigs, 0)) {
     88             throw new RuntimeException("unable to find RGB888+recordable ES2 EGL config");
     89         }
     90 
     91         // Configure context for OpenGL ES 2.0.
     92         int[] attrib_list = {
     93                 EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
     94                 EGL14.EGL_NONE
     95         };
     96         mEGLContext = EGL14.eglCreateContext(mEGLDisplay, configs[0], EGL14.EGL_NO_CONTEXT,
     97                 attrib_list, 0);
     98         checkEglError("eglCreateContext");
     99         if (mEGLContext == null) {
    100             throw new RuntimeException("null context");
    101         }
    102 
    103         // Create a window surface, and attach it to the Surface we received.
    104         int[] surfaceAttribs = {
    105                 EGL14.EGL_NONE
    106         };
    107         mEGLSurface = EGL14.eglCreateWindowSurface(mEGLDisplay, configs[0], mSurface,
    108                 surfaceAttribs, 0);
    109         checkEglError("eglCreateWindowSurface");
    110         if (mEGLSurface == null) {
    111             throw new RuntimeException("surface was null");
    112         }
    113     }
    114 
    115     /**
    116      * Discard all resources held by this class, notably the EGL context.  Also releases the
    117      * Surface that was passed to our constructor.
    118      */
    119     public void release() {
    120         if (mEGLDisplay != EGL14.EGL_NO_DISPLAY) {
    121             EGL14.eglDestroySurface(mEGLDisplay, mEGLSurface);
    122             EGL14.eglDestroyContext(mEGLDisplay, mEGLContext);
    123             EGL14.eglReleaseThread();
    124             EGL14.eglTerminate(mEGLDisplay);
    125         }
    126 
    127         mSurface.release();
    128 
    129         mEGLDisplay = EGL14.EGL_NO_DISPLAY;
    130         mEGLContext = EGL14.EGL_NO_CONTEXT;
    131         mEGLSurface = EGL14.EGL_NO_SURFACE;
    132 
    133         mSurface = null;
    134     }
    135 
    136     /**
    137      * Makes our EGL context and surface current.
    138      */
    139     public void makeCurrent() {
    140         if (!EGL14.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext)) {
    141             throw new RuntimeException("eglMakeCurrent failed");
    142         }
    143     }
    144 
    145     public void makeUnCurrent() {
    146         if (!EGL14.eglMakeCurrent(mEGLDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE,
    147                 EGL14.EGL_NO_CONTEXT)) {
    148             throw new RuntimeException("eglMakeCurrent failed");
    149         }
    150     }
    151 
    152     /**
    153      * Calls eglSwapBuffers.  Use this to "publish" the current frame.
    154      */
    155     public boolean swapBuffers() {
    156         return EGL14.eglSwapBuffers(mEGLDisplay, mEGLSurface);
    157     }
    158 
    159     /**
    160      * Returns the Surface that the MediaCodec receives buffers from.
    161      */
    162     public Surface getSurface() {
    163         return mSurface;
    164     }
    165 
    166     /**
    167      * Queries the surface's width.
    168      */
    169     public int getWidth() {
    170         int[] value = new int[1];
    171         EGL14.eglQuerySurface(mEGLDisplay, mEGLSurface, EGL14.EGL_WIDTH, value, 0);
    172         return value[0];
    173     }
    174 
    175     /**
    176      * Queries the surface's height.
    177      */
    178     public int getHeight() {
    179         int[] value = new int[1];
    180         EGL14.eglQuerySurface(mEGLDisplay, mEGLSurface, EGL14.EGL_HEIGHT, value, 0);
    181         return value[0];
    182     }
    183 
    184     /**
    185      * Sends the presentation time stamp to EGL.  Time is expressed in nanoseconds.
    186      */
    187     public void setPresentationTime(long nsecs) {
    188         EGLExt.eglPresentationTimeANDROID(mEGLDisplay, mEGLSurface, nsecs);
    189     }
    190 
    191     /**
    192      * Checks for EGL errors.
    193      */
    194     private void checkEglError(String msg) {
    195         int error;
    196         if ((error = EGL14.eglGetError()) != EGL14.EGL_SUCCESS) {
    197             throw new RuntimeException(msg + ": EGL error: 0x" + Integer.toHexString(error));
    198         }
    199     }
    200 }
    201