0

I have a class that extends the SurfaceView and implements Camera.PreviewCallback. In this class I setup the camera to preview to supplied buffers (setPreviewCallbackWithBuffer) and a couple of buffers (addCallbackBuffer). After I call startPreview the onPreviewFrame callback is successfully called. In onPreviewFrame I hand the work over to a different thread that does some processing and eventually visualizes the data.

However, I noticed that occasionally the onPreviewFrame is not called anymore. During exploration of this issue, I observed that it is most likely to occur when processing 1280x720 frames - which the camera supports) but it also happens on lower resolutions but less frequently. I eventually stripped down the code down to an almost empty onPreviewFrame (it only logs receiving the call and calling addCallbackBuffer again; nothing more). The processing thread is not started. The same behavior can be observed.

In this case, with 3 buffers for the preview at 1280x720 this runs for about 20 minutes and then onPreviewFrame is not being called anymore. Logcat doesn't show any other issues. This 20 minutes varies, sometimes its 5 minutes, sometimes under a minute. Using logging I verified that the buffer sequence is rather clean (buffer1, buffer2, buffer3, buffer1, buffer2, ...) on each onPreviewFrame invocation.

The device I'm working on is a Galaxy Tab 2 (using Android 4.2.2 CyanogenMod); but I've seen this on other devices using stock roms also - so I doubt that it is due to the rom.

So I guess it comes to these questions:

  1. how many buffers do I need to supply (given a certain resolution and a certain processing time)?
  2. Why does the onPreviewFrame not get called anymore (the are free buffer at that time)?

The relevant code boils down to this:

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);
    }
}
BCL
  • 127
  • 2
  • 14
  • I've found some threads (also on SO) discussing that this could be due to having a dummy SurfaceView. Lets see if we can update our code to not use a dummy SurfaceView and verify what happens. – BCL May 07 '13 at 06:03
  • For the SO post, see [here](http://stackoverflow.com/questions/2386025/android-camera-without-preview) – BCL May 07 '13 at 06:19
  • what is the value of imageBufferSize? Are you calling stopPreview() and restarting preview after that anywhere in the code? Try calling setPreviewCallbackwithBuffer() everytime you call startPreview(). – abggcv Aug 16 '17 at 14:44

1 Answers1

0

If the code is updated to use not a dummy SurfaceView and we render our processing results to a second SurfaceView (that lies on top) the code works. We have to be a bit more careful about synchronization I guess, but it works on all devices we tested it on so far.

BCL
  • 127
  • 2
  • 14
  • What do you mean by a "dummy" `SurfaceView`? The problem I'm facing is that `onPreviewFrame()` isn't called for every frame that is displayed on the `SurfaceView`. The number of calls to `onPreviewFrame()` is about 4/sec but the camera preview is very smooth. – timemanx Sep 17 '13 at 19:47