package com.laifeng.sopcastsdk.camera; import android.annotation.TargetApi; import android.graphics.Rect; import android.graphics.SurfaceTexture; import android.hardware.Camera; import com.laifeng.sopcastsdk.camera.exception.CameraHardwareException; import com.laifeng.sopcastsdk.camera.exception.CameraNotSupportException; import com.laifeng.sopcastsdk.configuration.CameraConfiguration; import com.laifeng.sopcastsdk.utils.SopCastLog; import java.io.IOException; import java.util.ArrayList; import java.util.List; /** * @Title: CameraHolder * @Package com.youku.crazytogether.app.modules.sopCastV2 * @Description: * @Author Jim * @Date 16/3/23 * @Time 上午11:57 * @Version */ @TargetApi(14) public class CameraHolder { private static final String TAG = "CameraHolder"; private final static int FOCUS_WIDTH = 80; private final static int FOCUS_HEIGHT = 80; private List<CameraData> mCameraDatas; private Camera mCameraDevice; private CameraData mCameraData; private State mState; private SurfaceTexture mTexture; private boolean isTouchMode = false; private boolean isOpenBackFirst = false; private CameraConfiguration mConfiguration = CameraConfiguration.createDefault(); public enum State { INIT, OPENED, PREVIEW } private static CameraHolder sHolder; public static synchronized CameraHolder instance() { if (sHolder == null) { sHolder = new CameraHolder(); } return sHolder; } private CameraHolder() { mState = State.INIT; } public int getNumberOfCameras() { return Camera.getNumberOfCameras(); } public CameraData getCameraData() { return mCameraData; } public boolean isLandscape() { return (mConfiguration.orientation != CameraConfiguration.Orientation.PORTRAIT); } public synchronized Camera openCamera() throws CameraHardwareException, CameraNotSupportException { if(mCameraDatas == null || mCameraDatas.size() == 0) { mCameraDatas = CameraUtils.getAllCamerasData(isOpenBackFirst); } CameraData cameraData = mCameraDatas.get(0); if(mCameraDevice != null && mCameraData == cameraData) { return mCameraDevice; } if (mCameraDevice != null) { releaseCamera(); } try { SopCastLog.d(TAG, "open camera " + cameraData.cameraID); mCameraDevice = Camera.open(cameraData.cameraID); } catch (RuntimeException e) { SopCastLog.e(TAG, "fail to connect Camera"); throw new CameraHardwareException(e); } if(mCameraDevice == null) { throw new CameraNotSupportException(); } try { CameraUtils.initCameraParams(mCameraDevice, cameraData, isTouchMode, mConfiguration); } catch (Exception e) { e.printStackTrace(); mCameraDevice.release(); mCameraDevice = null; throw new CameraNotSupportException(); } mCameraData = cameraData; mState = State.OPENED; return mCameraDevice; } public void setSurfaceTexture(SurfaceTexture texture) { mTexture = texture; if(mState == State.PREVIEW && mCameraDevice != null && mTexture != null) { try { mCameraDevice.setPreviewTexture(mTexture); } catch (IOException e) { releaseCamera(); } } } public State getState() { return mState; } public void setConfiguration(CameraConfiguration configuration) { isTouchMode = (configuration.focusMode != CameraConfiguration.FocusMode.AUTO); isOpenBackFirst = (configuration.facing != CameraConfiguration.Facing.FRONT); mConfiguration = configuration; } public synchronized void startPreview() { if(mState != State.OPENED) { return; } if(mCameraDevice == null) { return; } if(mTexture == null) { return; } try { mCameraDevice.setPreviewTexture(mTexture); mCameraDevice.startPreview(); mState = State.PREVIEW; } catch (Exception e) { releaseCamera(); e.printStackTrace(); } } public synchronized void stopPreview() { if(mState != State.PREVIEW) { return; } if(mCameraDevice == null) { return; } mCameraDevice.setPreviewCallback(null); Camera.Parameters cameraParameters = mCameraDevice.getParameters(); if (cameraParameters != null && cameraParameters.getFlashMode() != null && !cameraParameters.getFlashMode().equals(Camera.Parameters.FLASH_MODE_OFF)) { cameraParameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); } mCameraDevice.setParameters(cameraParameters); mCameraDevice.stopPreview(); mState = State.OPENED; } public synchronized void releaseCamera() { if(mState == State.PREVIEW) { stopPreview(); } if(mState != State.OPENED) { return; } if(mCameraDevice == null) { return; } mCameraDevice.release(); mCameraDevice = null; mCameraData = null; mState = State.INIT; } public void release() { mCameraDatas = null; mTexture = null; isTouchMode = false; isOpenBackFirst = false; mConfiguration = CameraConfiguration.createDefault(); } public void setFocusPoint(int x, int y) { if(mState != State.PREVIEW || mCameraDevice == null) { return; } if (x < -1000 || x > 1000 || y < -1000 || y > 1000) { SopCastLog.w(TAG, "setFocusPoint: values are not ideal " + "x= " + x + " y= " + y); return; } Camera.Parameters params = mCameraDevice.getParameters(); if (params != null && params.getMaxNumFocusAreas() > 0) { List<Camera.Area> focusArea = new ArrayList<Camera.Area>(); focusArea.add(new Camera.Area(new Rect(x, y, x + FOCUS_WIDTH, y + FOCUS_HEIGHT), 1000)); params.setFocusAreas(focusArea); try { mCameraDevice.setParameters(params); } catch (Exception e) { // Ignore, we might be setting it too // fast since previous attempt } } else { SopCastLog.w(TAG, "Not support Touch focus mode"); } } public boolean doAutofocus(Camera.AutoFocusCallback focusCallback) { if(mState != State.PREVIEW || mCameraDevice == null) { return false; } // Make sure our auto settings aren't locked Camera.Parameters params = mCameraDevice.getParameters(); if (params.isAutoExposureLockSupported()) { params.setAutoExposureLock(false); } if (params.isAutoWhiteBalanceLockSupported()) { params.setAutoWhiteBalanceLock(false); } mCameraDevice.setParameters(params); mCameraDevice.cancelAutoFocus(); mCameraDevice.autoFocus(focusCallback); return true; } public void changeFocusMode(boolean touchMode) { if(mState != State.PREVIEW || mCameraDevice == null || mCameraData == null) { return; } isTouchMode = touchMode; mCameraData.touchFocusMode = touchMode; if(touchMode) { CameraUtils.setTouchFocusMode(mCameraDevice); } else { CameraUtils.setAutoFocusMode(mCameraDevice); } } public void switchFocusMode() { changeFocusMode(!isTouchMode); } public float cameraZoom(boolean isBig) { if(mState != State.PREVIEW || mCameraDevice == null || mCameraData == null) { return -1; } Camera.Parameters params = mCameraDevice.getParameters(); if(isBig) { params.setZoom(Math.min(params.getZoom() + 1, params.getMaxZoom())); } else { params.setZoom(Math.max(params.getZoom() - 1, 0)); } mCameraDevice.setParameters(params); return (float) params.getZoom()/params.getMaxZoom(); } public boolean switchCamera() { if(mState != State.PREVIEW) { return false; } try { CameraData camera = mCameraDatas.remove(1); mCameraDatas.add(0, camera); openCamera(); startPreview(); return true; } catch (Exception e) { CameraData camera = mCameraDatas.remove(1); mCameraDatas.add(0, camera); try { openCamera(); startPreview(); } catch (Exception e1) { e1.printStackTrace(); } e.printStackTrace(); return false; } } public boolean switchLight() { if(mState != State.PREVIEW || mCameraDevice == null || mCameraData == null) { return false; } if(!mCameraData.hasLight) { return false; } Camera.Parameters cameraParameters = mCameraDevice.getParameters(); if (cameraParameters.getFlashMode().equals(Camera.Parameters.FLASH_MODE_OFF)) { cameraParameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); } else { cameraParameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); } try { mCameraDevice.setParameters(cameraParameters); return true; }catch (Exception e) { e.printStackTrace(); return false; } } }