The startPreview function is slow, Any work around

2019-06-17 01:40发布

问题:

Problem:

I'm making an application on android which requires a fast response from the camera while shooting images, I noticed a slow behavior from the application, after measuring the time I noticed that function startPreview() is the responsible of the problem.

Code Preview:

This is the necessary part of the code (related to the problem).

PreviewGoogle Class (the custom preview): On the start of the application the surfaceChanged is called, I've set some camera parameters then called the startPreview

public class PreviewGoogle extends ViewGroup implements SurfaceHolder.Callback {
    private final String TAG = "myapp1";
    Camera mCamera;

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        try
        {
            // Now that the size is known, set up the camera parameters and begin
            // the preview.
            Camera.Parameters parameters = mCamera.getParameters();

            parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY);
            parameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);
            parameters.setSceneMode(Camera.Parameters.SCENE_MODE_AUTO);
            parameters.setJpegQuality(100);
            parameters.setPictureSize(Globals.CAMERA_WIDTH, Globals.CAMERA_HEIGHT);

            requestLayout();
            mCamera.setParameters(parameters);

            long before = System.currentTimeMillis();
            mCamera.startPreview();
            long after = System.currentTimeMillis();

            Log.d(TAG, "PreviewGoogle, surfaceChanged: startPreview took " + (after - before) + " ms");
        }
        catch (Exception e) {
            Log.d(TAG, "PreviewGoogle, surfaceChanged: " + e.getMessage());
        }
    }
}

PhotoShootActivity class: In this class I called the startPreview on the rawImageCallback because I'm using the BitmapFactory in the jpegCallback (not necessary thing)

public class PhotoShootActivity extends Activity
{
    private static final String TAG = "myapp1";
    PreviewGoogle preview;

    // Handles data for raw picture
    PictureCallback rawCallback = new PictureCallback()
    {
        public void onPictureTaken(byte[] data, Camera camera)
        {
            try
            {
                long before = System.currentTimeMillis();
                preview.getCamera().startPreview();
                long after = System.currentTimeMillis();

                Log.d(PhotoShootActivity.TAG, "PhotoShootActivity, rawCallback: preview started in " + (after - before) + " ms");
            }
            catch(Exception e)
            {
                Log.e(TAG, "PhotoShootActivity, rawCallback: " + e.getMessage());
            }
        }
    };
}

The Timer Numbers were like this:

09-09 10:58:42.336: DEBUG/myapp1(21958): PhotoShootActivity, onCreate
**09-09 10:58:44.396: DEBUG/myapp1(21958): PreviewGoogle, surfaceChanged: startPreview took 1457 ms**
09-09 10:58:48.438: DEBUG/myapp1(21958): PhotoShootActivity, buttonCapture: Picture taken in 65ms
09-09 10:58:48.496: DEBUG/myapp1(21958): PhotoShootActivity, shutterCallback: Empty
**09-09 10:58:49.790: DEBUG/myapp1(21958): PhotoShootActivity, rawCallback: preview started in 662 ms**

The first startPreview took ~1500ms and the second took 662 ms!!!

Searched solution:

The question I'm looking for is not a full code (just tip me :)), I've thought that I could missing something in the preview, and I thought about using threads in this case but I'm not familiar with android-sdk yet (I started with android programing 4 days ago)

Regards...

回答1:

From the android docs:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

startPreview()

Starts capturing and drawing preview frames to the screen. Preview will not actually start until a surface is supplied with setPreviewDisplay(SurfaceHolder) or setPreviewTexture(SurfaceTexture).

If setPreviewCallback(Camera.PreviewCallback), setOneShotPreviewCallback(Camera.PreviewCallback), or setPreviewCallbackWithBuffer(Camera.PreviewCallback) were called, onPreviewFrame(byte[], Camera) will be called when preview data becomes available.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

So in your comment you said you decided to use onPreviewFrame(byte[], Camera), as you can see in the docs, it says it is only called when the preview data becomes available, whihc takes some time. Try adding the first option by providing the camera with a texture or a preview display.

Ie, in your surfaceChanged(SurfaceHolder holder, int format, int w, int h) method:

mCamera.setPreviewDisplay(holder);

See if that makes a difference.