onPreviewFrame在一段时间之后没有被调用,之前它工作得很好

时间:2013-05-02 09:45:13

标签: android camera

我有一个扩展SurfaceView并实现Camera.PreviewCallback的类。在这个类中,我设置相机预览提供的缓冲区(setPreviewCallbackWithBuffer)和几个缓冲区(addCallbackBuffer)。调用startPreview后,成功调用onPreviewFrame回调。 在onPreviewFrame中,我将工作交给另一个执行某些处理并最终可视化数据的线程。

然而,我注意到偶尔不再调用onPreviewFrame。在探讨这个问题的过程中,我观察到它最有可能在处理1280x720帧时发生 - 相机支持这种帧,但它也会在较低分辨率下发生,但频率较低。 我最终将代码分解为几乎空的onPreviewFrame(它只记录接收调用并再次调用addCallbackBuffer;仅此而已)。处理线程未启动。可以观察到相同的行为。

在这种情况下,使用3个缓冲区进行1280x720的预览,这将运行大约20分钟,然后再不再调用onPreviewFrame。 Logcat不会显示任何其他问题。 这20分钟不一,有时是5分钟,有时是一分钟。 使用日志记录我在每个onPreviewFrame调用上验证了缓冲区序列相当干净(buffer1,buffer2,buffer3,buffer1,buffer2,...)。

我正在使用的设备是Galaxy Tab 2(使用Android 4.2.2 CyanogenMod);但是我在其他设备上也看到过这种情况,所以我怀疑它是由rom引起的。

所以我想这就是这些问题:

  1. 我需要提供多少缓冲区(给定一定的分辨率和一定的处理时间)?
  2. 为什么不再调用onPreviewFrame(当时是空闲缓冲区)?
  3. 相关代码归结为:

    private void startPreview()
    {
        Camera.Parameters parameters = mCamera.getParameters();
        int width  = 1280;
        int height = 720;
        Resolution bestCameraResolution = getBestCameraResolutionMatch(width, height);
        width  = bestCameraResolution.width();
        height = bestCameraResolution.height();
        parameters.setPreviewSize(width, height);
        mCamera.setParameters(parameters);
    
        try {
            mCamera.setPreviewDisplay(mSurfaceHolder);
        } catch (IOException e) {
            Log.d(TAG, "Error setting camera preview: " + e.getMessage());
        }
    
        // calculate imageBufferSize here...
    
        mCamera.addCallbackBuffer(new byte[imageBufferSize]);
        mCamera.addCallbackBuffer(new byte[imageBufferSize]);
        mCamera.addCallbackBuffer(new byte[imageBufferSize]);
        mCamera.setPreviewCallbackWithBuffer(this);
        mCamera.startPreview();
        Log.d(TAG, "Start preview with " + width + "x" + height);
    }
    
    @Override
    public void onPreviewFrame(byte[] frameData, Camera camera)
    {
        // Log to a separate tag to allow better filtering
        Log.d(TAG + "Frame", "preview frame on buffer " + frameData.toString());
    
        // Give used buffer back for future grabbing
        if (mCamera != null) {
            mCamera.addCallbackBuffer(frameData);
        }
    }
    

1 个答案:

答案 0 :(得分:0)

如果代码更新为不使用虚拟SurfaceView,并且我们将处理结果渲染到第二个SurfaceView(位于顶部),则代码可以正常工作。 我想我们必须对同步更加小心,但它适用于我们迄今为止测试它的所有设备。