MTK 设备中的 setPreviewTexture 失败
setPreviewTexture failed in MTK device
最近我在学习android grafika的相机和OpenglES(感谢fadden)。它在大多数设备上都很好,但我在某些设备上遇到了错误,特别是MTK设备(例如MT6580,MT8163 ... ).
例如MTK中"CameraCaptureActivity"运行时。我收到此错误:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.hardware.Camera.setPreviewTexture(android.graphics.SurfaceTexture)' on a null object reference
所以我将 "handleSetSurfaceTexture" 函数更改为:
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();
}
然后报错改成这样:
java.lang.RuntimeException: java.io.IOException: setPreviewTexture failed
at jp.co.cyberagent.android.gpuimage.grafika.CameraCaptureActivity.handleSetSurfaceTexture(CameraCaptureActivity.java:1150)
我看了很多其他相机应用程序的源代码,我想可能在 MTK 设备中 Camera 和 SurfaceRender 存在同步问题。所以我像这样更改代码:
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();
}
不幸的是,"getMaxTextureSize()" return 在其他设备中是一个有用的数字,但我在 MTK 设备中只得到 getMaxTextureSize()=0。
所以我有这些问题:
1) 如何安全使用surfaceRender/Camera/SurfaceTexture?
2)为什么这个问题只出现在MTK中?
任何答案将不胜感激。
我加上这个再测试
//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);
其中两个设备的结果是:
nGLVersion = 131072, supportsEs2 = true
nGLVersion = 196608, supportsEs2 = true
我也得到设备信息:
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);
结果:
strDevice = Alps k80_gmo, strModel =k80_gmo, nVersion =22
strDevice = Alps tb8163p3_64_sph, strModel =tb8163p3_64_sph, nVersion =22
顺便说一句,第一次打开相机并开始预览就可以了。但是在 activity 暂停或重新打开相机时遇到 "setPreviewTexture failed"。
我得到一些日志,当释放相机时:
CameraClient native_window_api_disconnect failed: Broken pipe (-32)
重新打开相机时:
CameraClient native_window_api_connect failed: No such device (-19)
可能这些设备有问题,但我也在这些设备上测试了一些其他相机应用程序,其中一些表现良好。所以它必须有更好的方式来使用Camera和glsurfaceview。
正如 fadden 所说,可能存在导致 "setPreviewTexture failed" 的竞争条件。最后,我从 google camera2 示例代码中找到了解决方案:https://github.com/googlesamples/android-Camera2Basic/blob/master/Application/src/main/java/com/example/android/camera2basic/Camera2BasicFragment.java。它使用 "Semaphore" 来解决问题。
我在语句 mCamera.setPreviewDisplay(holder) 上遇到了同样的问题,通过放置语句
解决了
camera.stopPreview();
之前
mCamera.setPreviewDisplay(holder)
最近我在学习android grafika的相机和OpenglES(感谢fadden)。它在大多数设备上都很好,但我在某些设备上遇到了错误,特别是MTK设备(例如MT6580,MT8163 ... ).
例如MTK中"CameraCaptureActivity"运行时。我收到此错误:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.hardware.Camera.setPreviewTexture(android.graphics.SurfaceTexture)' on a null object reference
所以我将 "handleSetSurfaceTexture" 函数更改为:
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();
}
然后报错改成这样:
java.lang.RuntimeException: java.io.IOException: setPreviewTexture failed at jp.co.cyberagent.android.gpuimage.grafika.CameraCaptureActivity.handleSetSurfaceTexture(CameraCaptureActivity.java:1150)
我看了很多其他相机应用程序的源代码,我想可能在 MTK 设备中 Camera 和 SurfaceRender 存在同步问题。所以我像这样更改代码:
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();
}
不幸的是,"getMaxTextureSize()" return 在其他设备中是一个有用的数字,但我在 MTK 设备中只得到 getMaxTextureSize()=0。
所以我有这些问题:
1) 如何安全使用surfaceRender/Camera/SurfaceTexture?
2)为什么这个问题只出现在MTK中?
任何答案将不胜感激。
我加上这个再测试
//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);
其中两个设备的结果是:
nGLVersion = 131072, supportsEs2 = true
nGLVersion = 196608, supportsEs2 = true
我也得到设备信息:
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);
结果:
strDevice = Alps k80_gmo, strModel =k80_gmo, nVersion =22
strDevice = Alps tb8163p3_64_sph, strModel =tb8163p3_64_sph, nVersion =22
顺便说一句,第一次打开相机并开始预览就可以了。但是在 activity 暂停或重新打开相机时遇到 "setPreviewTexture failed"。 我得到一些日志,当释放相机时:
CameraClient native_window_api_disconnect failed: Broken pipe (-32)
重新打开相机时:
CameraClient native_window_api_connect failed: No such device (-19)
可能这些设备有问题,但我也在这些设备上测试了一些其他相机应用程序,其中一些表现良好。所以它必须有更好的方式来使用Camera和glsurfaceview。
正如 fadden 所说,可能存在导致 "setPreviewTexture failed" 的竞争条件。最后,我从 google camera2 示例代码中找到了解决方案:https://github.com/googlesamples/android-Camera2Basic/blob/master/Application/src/main/java/com/example/android/camera2basic/Camera2BasicFragment.java。它使用 "Semaphore" 来解决问题。
我在语句 mCamera.setPreviewDisplay(holder) 上遇到了同样的问题,通过放置语句
解决了camera.stopPreview();
之前
mCamera.setPreviewDisplay(holder)