如果SurfaceView尺寸不是受支持的尺寸

时间:2016-05-11 00:14:10

标签: android android-camera surfaceview android-camera2

当使用SurfaceHolder / SurfaceView配置CaptureSession时,我预计SurfaceView可以有任何布局大小,而我通过surfaceView.getHolder()设置一个具有相同宽高比的好预览尺寸.setFixedSize(preview_width, preview_height)。结果应该是传入的预览缓冲区可以缩小到布局大小。

但是在camera2 - 硬件级别LEGACY - 中,只有使用与StreamConfigurationMap.getOutputSizes(SurfaceHolder.class)返回的List中具有完全相同布局大小的SurfaceView时,才能配置CaptureSession。如果没有,图像将不会按比例缩小,但配置会引发错误。

/**
 * Prerequisites:
 * - The device must be opened.
 * - The surface view must be ready.
 */
protected void init() {

    // ...

    try {

        CameraCaptureSession.StateCallback cb = new CameraCaptureSession.StateCallback() {

            // ...
        };

        // The following line will result in an error*, if the viewfinder has not the right size:
        cameraDevice.createCaptureSession(Arrays.asList(viewfinder.getHolder().getSurface(), imageReaderSmall.getSurface()), cb, null);
    }
    catch (CameraAccessException e) {

        // ...
    }
}

从日志(Samsung Galaxy A3 '14,SDV v21):

05-12 ...: Output sizes for SurfaceHolder.class: [1440x1080, 1280x720, 960x720, 880x720, 960x540, 720x540, 800x480, 720x480, 640x480, 528x432, 352x288, 320x240, 176x144]
...
05-12 ... I/CameraManager: Using legacy camera HAL.
...
05-12 ... I/OpenGLRenderer: Initialized EGL, version 1.4
05-12 ... D/OpenGLRenderer: Get maximum texture size. GL_MAX_TEXTURE_SIZE is 4096
05-12 ... D/OpenGLRenderer: Enabling debug mode 0
05-12 ....CameraActivity: Surface created
05-12 ....CameraActivity: Surface changed 4 540x405
*) 05-12 ... E/CameraDevice-0-LE: Surface with size (w=540, h=405) and format 0x4 is not valid, size not in valid set: [1440x1080, 1280x720, 960x720, 880x720, 960x540, 720x540, 800x480, 720x480, 640x480, 528x432, 352x288, 320x240, 176x144]
05-12 ... W/CameraDevice-JV-0: Stream configuration failed
05-12 ... E/CameraCaptureSession: Session 0: Failed to create capture session; configuration failed
...
05-12 ....CameraActivity: Configure failed!

使用Nexus 5X,SDK v23,并在surfaceChanged()之后等待surfaceHolder.setFixedSize()调用,预览大小不在支持的输出大小列表中,但是预览没有错误不开始。从日志中:

05-12 08:47:10.052 ....CameraActivity: Surface created
05-12 08:47:10.053 ....CameraActivity: Surface changed 4 1455x1080
05-12 08:47:10.054 ....CameraActivity: Find preview size for 1455x1080 (1.347424:1) px
05-12 08:47:10.054 ....CameraActivity: Preview size 1600x1200 px
05-12 08:47:10.070 ....CameraActivity: Surface changed 4 1600x1200
05-12 08:47:10.110 ....CameraActivity: Session started
05-12 08:47:10.163 ....CameraActivity: Surface: Surface(name=null)/@0xec338e5

结果:预览没有开始,我可以给表面视图一个背景颜色来演示它。

如何解决这个问题,仍然使用SurfaceView,它比使用SurfaceTexture更具性能和向后兼容性。

1 个答案:

答案 0 :(得分:3)

调用setFixedSize后,在创建摄像头捕获会话之前,需要等待surfaceChanged()回调再次触发。

setFixedSize将必要的SurfaceView更改排队,但它们不会立即生效。