如何摆脱相机冻结(SurfaceView)?

时间:2017-08-08 20:00:08

标签: android multithreading android-fragments camera

我尝试使用Camera API创建自定义相机。我已经查看了很多类似的问题,但无论如何都不能在我的相机预览中摆脱冻结。有时候预览会在活动开始时冻结,尽管使用了其他线程。但是当我尝试切换到面部相机时,预览图像每次冻结。在日志中我只有这样的东西:

I/Choreographer: Skipped 41 frames!  The application may be doing too much work on its main thread.

如果重要的话,我的SurfaceView将被置于ViewPager活动的Fragment中。

我的自定义相机类方法:

设置显示方向:

void setCameraDisplayOrientation(int cameraId) {
        int rotation = getActivity().getWindowManager().getDefaultDisplay().getRotation();
        int degrees = 0;
        switch (rotation) {
            case Surface.ROTATION_0:
                degrees = 0;
                break;
            case Surface.ROTATION_90:
                degrees = 90;
                break;
            case Surface.ROTATION_180:
                degrees = 180;
                break;
            case Surface.ROTATION_270:
                degrees = 270;
                break;
        }

        int result = 0;

        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(cameraId, info);

        if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
            result = ((360 - degrees) + info.orientation);
        } else

            if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                result = ((360 - degrees) - info.orientation);
                result += 360;
            }
        result = result % 360;
        camera.setDisplayOrientation(result);
    }

Holder Callback类:

class HolderCallback implements SurfaceHolder.Callback {

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            try {
                camera.setPreviewDisplay(holder);
                camera.startPreview();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width,
                                   int height) {
            // TODO Auto-generated method stub
            if (mIsPreviewing) {
                camera.stopPreview();
                mIsPreviewing = false;
            }

            if (camera != null) {
                Camera.Parameters parameters = camera.getParameters();
                Camera.Size bestSize = getBestPreviewSize(width, height, parameters);

                if (bestSize != null) {
                    parameters.setPreviewSize(bestSize.width, bestSize.height);
                    camera.setParameters(parameters);

                    Toast.makeText(
                            getActivity().getApplicationContext(),
                            "Оптимальный размер: " + String.valueOf(bestSize.width)
                                    + " : " + String.valueOf(bestSize.height),
                            Toast.LENGTH_LONG).show();
                }
                try {
                    camera.setPreviewDisplay(holder);
                    camera.startPreview();
                    mIsPreviewing = true;

//                    camera.autoFocus(autoFocusCallback);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }

        private Camera.Size getBestPreviewSize(int width, int height,
                                               Camera.Parameters parameters) {
            Camera.Size bestSize = null;
            List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes();

            bestSize = sizeList.get(0);

            for (int i = 1; i < sizeList.size(); i++) {
                if ((sizeList.get(i).width * sizeList.get(i).height) > (bestSize.width * bestSize.height)) {
                    bestSize = sizeList.get(i);
                }
            }
            return bestSize;
        }


        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {

        }

    }

相机处理程序线程:

private CameraHandlerThread mThread = null;
    private static class CameraHandlerThread extends HandlerThread {
        Handler mHandler = null;

        CameraHandlerThread() {
            super("CameraHandlerThread");
            start();
            mHandler = new Handler(getLooper());
        }

        synchronized void notifyCameraOpened() {
            notify();
        }

        void openCamera() {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    camera = Camera.open(CAMERA_ID);
                    //set camera to continually auto-focus
                    Camera.Parameters params = camera.getParameters();
//*EDIT*//params.setFocusMode("continuous-picture");
//It is better to use defined constraints as opposed to String, thanks to AbdelHady
//                    params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
//                    camera.setParameters(params);
                    //STEP #1: Get rotation degrees
                    Camera.CameraInfo info = new Camera.CameraInfo();
                    Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, info);

                    int degrees = 0;
                    switch (rotation) {
                        case Surface.ROTATION_0: degrees = 0; break; //Natural orientation
                        case Surface.ROTATION_90: degrees = 90; break; //Landscape left
                        case Surface.ROTATION_180: degrees = 180; break;//Upside down
                        case Surface.ROTATION_270: degrees = 270; break;//Landscape right
                    }
                    int rotate = (info.orientation - degrees + 360) % 360;

//STEP #2: Set the 'rotation' parameter
                    params.setRotation(rotate);
                    camera.setParameters(params);
                    notifyCameraOpened();
                    camera.startPreview();

                }
            });
            try {
                wait();
            }
            catch (InterruptedException e) {
                Log.d(TAG, "openCamera: Cannot open Camera");
            }
        }
    }

打开相机:

private void newOpenCamera() {
    mThread = new CameraHandlerThread();
    synchronized (mThread) {
        mThread.openCamera();
    }
}

片段方法:

 @Override
    public void onResume() {
        super.onResume();
        newOpenCamera();
        setCameraDisplayOrientation(CAMERA_ID);
    }

    @Override
    public void onPause() {
        super.onPause();
        if (camera != null)
            camera.release();
        camera = null;
    }

@Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        sv = (SurfaceView) getActivity().findViewById(R.id.surfaceView);

        makePhotoBtn = (ImageView) getActivity().findViewById(R.id.makephotoBtn);
        switchCameraBtn = (ImageView) getActivity().findViewById(R.id.switchCameraBtn);
        holder = sv.getHolder();
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        holderCallback = new HolderCallback();
        holder.addCallback(holderCallback);
        rotation = getActivity().getWindowManager().getDefaultDisplay().getRotation();


        makePhotoBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                camera.takePicture(null, null, new Camera.PictureCallback() {
                    @Override
                    public void onPictureTaken(byte[] data, Camera camera) {
                        try {
                            new SaveBitmap().execute(toObjects(data));
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
        });


        switchCameraBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                swapCamera();
            }
        });
    }

交换相机方法:

 private void swapCamera() {

        if (camera != null) {
            camera.stopPreview();
            camera.setPreviewCallback(null);
            camera.release();
            camera = null;
            holder.removeCallback(holderCallback);
            holder = null;
            sv = null;
            sv = (SurfaceView) getActivity().findViewById(R.id.surfaceView);
        }

        //swap the id of the camera to be used
        if (CAMERA_ID == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            CAMERA_ID = 0;
        } else  {
            CAMERA_ID = 1;
        }

        newOpenCamera();


    }

在这种情况下,我该怎样做才能摆脱冻结?感谢任何帮助!

0 个答案:

没有答案