Android Camera2 API preview sometimes distorted

2019-05-30 04:12发布

问题:

I am building a custom camera with the Camera2 API. So far the camera works very well except for the preview which is distorted sometimes. Let's say I open the camera 7 times in a row. All of the attempts are succesful and the 8th time the camera preview is distorted. It looks like it uses the width as the height and vice versa.

I have based my code on the Google sample implementation of the camera2 which can be found here. the interesting thing is that even the Google sample implementation has this distorted preview sometimes. I have tried to modify the AutoFitTextureView but nothing was successful. I am currently using the AutoFitTextureView.java Google provides again.

A similar post to this one can be found here. However the proposed fixes didn't solve the problem.

I can reproduce the problem by changing the following in the setUpCameraOutputs method:

mTextureView.setAspectRatio(mPreviewSize.getHeight(), mPreviewSize.getWidth());

to:

mTextureView.setAspectRatio(mPreviewSize.getWidth(), mPreviewSize.getHeight());

Another weird thing is that whenever the distorted preview occurs and you just press the home button so the app goes in onPause() and open up the app again so onResume() gets called, the preview is perfect every time.

Has anyone here experienced this problem and found a fix for it?

Thanks in advance

回答1:

I am facing the same issue on Sony Xperia Z3 Tablet Compact.

The pull request that Alex pointed out doesn't seem to work for me. It results in camera preview larger than the view's area (preview is cropped).

While I was not able to track the issue specifically, I was able to find a workaround. It seems the distortion happens while there are changes of mTextureView's size while in process of opening camera. Delaying the camera opening procedure fixes the issue.

Modified openCamera method:

/**
 * Opens the camera specified by {@link StepFragmentCamera#mCameraId}.
 */
private void openCamera(int width, int height) {
    startBackgroundThread();

    if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA)
            != PackageManager.PERMISSION_GRANTED) {
        requestCameraPermission();
        return;
    }
    setUpCameraOutputs(width, height);
    configureTransform(width, height);

    /*
     * Delay the opening of the camera until (hopefully) layout has been fully settled.
     * Otherwise there is a chance the preview will be distorted (tested on Sony Xperia Z3 Tablet Compact).
     */
    mTextureView.post(new Runnable() {
        @Override
        public void run() {
            /*
             * Carry out the camera opening in a background thread so it does not cause lag
             * to any potential running animation.
             */
            mBackgroundHandler.post(new Runnable() {
                @Override
                public void run() {
                    Activity activity = getActivity();
                    CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
                    try {
                        if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
                            throw new RuntimeException("Time out waiting to lock camera opening.");
                        }
                        manager.openCamera(mCameraId, mStateCallback, mBackgroundHandler);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    } catch (InterruptedException e) {
                        throw new RuntimeException("Interrupted while trying to lock camera opening.", e);
                    }
                }
            });
        }
    });
}


回答2:

The Google Camera2Basic sample was finally fixed. The original code had a tiny < vs > mistake. It had been wrong for 2 years.