androidandroid-cameraglsurfaceviewgrafika

setPreviewTexture failed in MTK device


Recently I am learning android Camera and OpenglES by grafika (Thanks fadden).It's good on most device, but I encounter bugs in some device, espacially MTK device(such as MT6580,MT8163...).

For example, when "CameraCaptureActivity" run in MTK. I am getting this error:

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.hardware.Camera.setPreviewTexture(android.graphics.SurfaceTexture)' on a null object reference

so I changed "handleSetSurfaceTexture" function to this:

 private void handleSetSurfaceTexture(SurfaceTexture st) {
    if(mCamera == null)
    {
        Log.e(TAG, "mCamera return null");
        return;
    }
    st.setOnFrameAvailableListener(this);
    try {
        mCamera.setPreviewTexture(st);

    } catch (Exception ioe) {
        Log.e(TAG, "camera failed handleSetSurfaceTexture");
        throw new RuntimeException(ioe);
    }
    mCamera.startPreview();
}

Then error change to this:

java.lang.RuntimeException: java.io.IOException: setPreviewTexture failed at jp.co.cyberagent.android.gpuimage.grafika.CameraCaptureActivity.handleSetSurfaceTexture(CameraCaptureActivity.java:1150)

I read many other camera app source code, I guess maybe there are Synchronous problem with Camera and SurfaceRender in MTK device. So I change the code like this:

private void waitUntilSetup()
{
    long l = System.currentTimeMillis();
    while ((getMaxTextureSize() == 0) && (System.currentTimeMillis() - l < 3000L))
    {
        SystemClock.sleep(100L);
    }

    Log.e(TAG,"getMaxTextureSize() = " + getMaxTextureSize());
}

private int getMaxTextureSize() {
    int[] maxTextureSize = new int[1];
    GLES20.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, maxTextureSize, 0);
    Log.e(TAG, "Max texture size = " + maxTextureSize[0]);
    return maxTextureSize[0];
}

private void handleSetSurfaceTexture(SurfaceTexture st) {
    //wait for gl
    waitUntilSetup();
    if(mCamera == null)
    {
        Log.e(TAG, "mCamera return null");
        return;
    }
    st.setOnFrameAvailableListener(this);
    try {
        mCamera.setPreviewTexture(st);
    } catch (Exception ioe) {
        Log.e(TAG, "camera failed handleSetSurfaceTexture");
        throw new RuntimeException(ioe);
    }
    mCamera.startPreview();
}

Unfortunately, "getMaxTextureSize()" return a useful number in other device, but I just get getMaxTextureSize()=0 in MTK device.

So I have these questions:

1) How to use surfaceRender/Camera/SurfaceTexture safely?

2) Why does this problem just happen in MTK?

any answer will be appreciate.

I add this and test again

    //get glVersion
    final ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
    int nGLVersion = configurationInfo.reqGlEsVersion;
    final boolean supportsEs2 = (nGLVersion >= 0x20000);
    Log.e(TAG, "nGLVersion = " + nGLVersion + ", supportsEs2 = " + supportsEs2);

in two of the device result is:

nGLVersion = 131072, supportsEs2 = true

nGLVersion = 196608, supportsEs2 = true

I also get device info:

     String strDevice = Devices.getDeviceName();    //https://gist.github.com/jaredrummler/16ed4f1c14189375131d
     String strModel =  Build.MODEL;
     int nVersion = Build.VERSION.SDK_INT;
     Log.e(TAG, "strDeviceName = " + strDevice + ", strModel =" + strModel + ", nVersion =" + nVersion);

results:

strDevice = Alps k80_gmo, strModel =k80_gmo, nVersion =22

strDevice = Alps tb8163p3_64_sph, strModel =tb8163p3_64_sph, nVersion =22

By the way, It's ok at the first time open Camera and startpreview. But encounter "setPreviewTexture failed" when activity pause or reopen the Camera. I get some logs, when release camera:

CameraClient native_window_api_disconnect failed: Broken pipe (-32)

when reopen camera:

CameraClient native_window_api_connect failed: No such device (-19)

Probably there are problem with these device, but I also test some other Camera app in these device, and some of them performs well. So it must have a better way to use Camera and glsurfaceview.


Solution

  • As fadden said, Maybe there is a race condition that causes "setPreviewTexture failed". Finnaly I find a solution from google camera2 sample code here : https://github.com/googlesamples/android-Camera2Basic/blob/master/Application/src/main/java/com/example/android/camera2basic/Camera2BasicFragment.java. It uses "Semaphore" to solve the problem.