0

A week ago I've started researching the Android camera API. I have successfully inited the camera and started preview, and it worked fine. Then I've found out I wasn't initializing and releasing the camera properly, so I overhauled the code somewhat, and now I have a problem that didn't occur initially: extremely low FPS. About 0.5, that's 2 seconds per frame. Interestingly enough, I get 1 frame with a delay, and then a second frame immediately after (1-15 ms), followed again by 2 seconds delay before the next frame.

This is my camera initialization code:

    m_openedCamera = Camera.open(id);
    m_surfaceHolder = new SurfaceView(MyApplication.instance().getApplicationContext()).getHolder();
    Assert.assertNotNull(m_openedCamera);

    // This is required on A500 for some reason
    Camera.Parameters params = m_openedCamera.getParameters();
    params.setPreviewFormat(ImageFormat.NV21);
    params.setPreviewSize(320, 240);
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    {
        params.setRecordingHint(true);
        params.setAutoExposureLock(true);
        params.setAutoWhiteBalanceLock(true);
    }

    m_openedCamera.setParameters(params);

    int bitsPerPx  = ImageFormat.getBitsPerPixel(ImageFormat.NV21);
    int width       = params.getPreviewSize().width;
    int height      = params.getPreviewSize().height;
    int size        = (int)(width * height * bitsPerPx / 8.0);
    m_openedCamera.addCallbackBuffer( new byte[size] );
    m_openedCamera.addCallbackBuffer( new byte[size] );
    m_openedCamera.addCallbackBuffer( new byte[size] );
    m_openedCamera.addCallbackBuffer( new byte[size] );

    m_openedCamera.setErrorCallback(this);
    m_openedCamera.setPreviewDisplay(m_surfaceHolder);
    m_openedCameraFacing = facing;
    m_openedCamera.setPreviewCallback(this);
    m_openedCamera.startPreview();

I have just added callback buffers - hasn't changed anything. In my initial code from a week ago I had no surface view, but removing it now has no effect either. This occurs on my second, much newer tablet as well, even though FPS is higher there (8-10), and there's no double frame there, the frames are spaced evenly. The FPS used to be at least 20. Light conditions haven't changed between now and then, btw.

Update: tried opening the camera in a separate thread as described here - no change.

Community
  • 1
  • 1
Violet Giraffe
  • 32,368
  • 48
  • 194
  • 335
  • So the performance improves if you eliminate the callback buffers? Similar to http://stackoverflow.com/questions/7790566/how-to-get-raw-preview-data-from-camera-object-at-least-15-frames-per-second-in ? – fadden Oct 14 '14 at 15:19
  • @fadden: No. Performance is exactly the same with or without buffers. – Violet Giraffe Oct 15 '14 at 06:17
  • One call that is lacking here is [`Camera.Parameters.setPreviewFrameRate()`](http://developer.android.com/reference/android/hardware/Camera.Parameters.html#setPreviewFrameRate(int)) or [`setPreviewFpsRange()`](http://developer.android.com/reference/android/hardware/Camera.Parameters.html#setPreviewFpsRange(int,%20int)). Be careful only to choose supported FPS. – Alex Cohn Oct 15 '14 at 10:26
  • 1
    Please note that `addCallbackBuffer()` without `setPreviewCallbackWithBuffer()` is irrelevant. The preallocated callback buffers may prove very useful if your processing involves worker threads, etc. It doesn't help if garbage collection is immediate (e.g. all processing done inside the callback). – Alex Cohn Oct 15 '14 at 11:07
  • @AlexCohn: Missed that one. As for FPS range - this device's camera only has one supported range, I've tried explicitly setting it and it didn't make a difference. – Violet Giraffe Oct 15 '14 at 13:33
  • Do you have heavy processing in your `onPreviewFrame()` callback? Please measure the time between the callback starts and completes. – Alex Cohn Oct 15 '14 at 14:08
  • @AlexCohn: no processing whatsoever, the callback is empty. – Violet Giraffe Oct 15 '14 at 17:00
  • I am kindof at loss: by adding the irrelevant four calls to `addCallbackBuffer()` you reduced the frame rate dramatically. Is this your question? – Alex Cohn Oct 15 '14 at 18:23
  • @AlexCohn: no. As I already mentioned in the comments, `addCallbackBuffer` had no effect on framerate (as it should be, according to your explanation). – Violet Giraffe Oct 15 '14 at 19:06
  • So, what was the change that had the significant effect? Because at the second glance, there is nothing ion your published code that could reduce the frame rate below reasonable. – Alex Cohn Oct 15 '14 at 19:19
  • @AlexCohn: I wonder myself. Couldn't find it so far. Unfortunately, while I was researching the camera and actively editing the code I did not commit often enough, so I can't roll back and have a look. I wouldn't probably had to ask this on SO if I knew what change caused the slowdown. – Violet Giraffe Oct 15 '14 at 19:22
  • This is a frustrating situation, indeed. Start a new project, write a minimum code to launch the camera preview, and it delivers acceptable frame rate, start adding the other pieces of your app one by one. – Alex Cohn Oct 16 '14 at 04:21
  • Did you call addCallbackBuffer() again in onPreviewFrame()? If not, you can't improve FPS rate.Please post the code in onPreviewFrame(). – yushulx Oct 16 '14 at 06:31
  • @yushulx: `onPreviewFrame` is empty, I commented it out to make sure my code wasn't slowing the FPS down. – Violet Giraffe Oct 16 '14 at 07:01

3 Answers3

1

params.setRecordingHint(true); is used to start video record starts.

Please check it again with "params.setRecordingHint(false)"

1

From your comment below "I have successfully inited the camera and started preview, and it worked fine. Then I've found out I wasn't initializing and releasing the camera properly"

I guess you was using the default camera parameters defined in camera HAL at first. Although it is not clear what "initializing" means, I think they is likely camera parameters setting.

So, I'd like to suggest you remove the code for params and then test it again. Or, you can test it one by one

  1. Remove only "params.setPreviewSize(320, 240);"
  2. Remove only "params.setPreviewFormat(ImageFormat.NV21);"
  3. Remove both 1 and 2.
0

Please make your own previewcallbak function and then

private PreviewCallback mPreviewCallback = new PreviewCallback();

.... setPreviewCallback(mPreviewCallback);

Regarding PreviewCallback(), you can refer to CameraTest.Java in cts directory : cts/tests/tests/hawdware/src/android/hardware/cts

  • How is this an answer? I do have a callback, obviously. With an empty body (more specifically, the callback only measures and logs elapsed FPS, nothing else). – Violet Giraffe Oct 16 '14 at 11:48