package com.laifeng.sopcastsdk.camera; import android.annotation.TargetApi; import android.app.admin.DevicePolicyManager; import android.content.Context; import android.graphics.ImageFormat; import android.hardware.Camera; import com.laifeng.sopcastsdk.configuration.CameraConfiguration; import com.laifeng.sopcastsdk.constant.SopCastConstant; import com.laifeng.sopcastsdk.blacklist.BlackListHelper; import com.laifeng.sopcastsdk.camera.exception.CameraDisabledException; import com.laifeng.sopcastsdk.camera.exception.CameraNotSupportException; import com.laifeng.sopcastsdk.camera.exception.NoCameraException; import com.laifeng.sopcastsdk.utils.SopCastLog; import java.util.ArrayList; import java.util.List; /** * @Title: CameraUtils * @Package com.youku.crazytogether.app.modules.sopCastV2 * @Description: * @Author Jim * @Date 16/3/23 * @Time 下午12:01 * @Version */ @TargetApi(14) public class CameraUtils { public static List<CameraData> getAllCamerasData(boolean isBackFirst) { ArrayList<CameraData> cameraDatas = new ArrayList<>(); Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); int numberOfCameras = Camera.getNumberOfCameras(); for (int i = 0; i < numberOfCameras; i++) { Camera.getCameraInfo(i, cameraInfo); if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { CameraData cameraData = new CameraData(i, CameraData.FACING_FRONT); if(isBackFirst) { cameraDatas.add(cameraData); } else { cameraDatas.add(0, cameraData); } } else if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) { CameraData cameraData = new CameraData(i, CameraData.FACING_BACK); if(isBackFirst) { cameraDatas.add(0, cameraData); } else { cameraDatas.add(cameraData); } } } return cameraDatas; } public static void initCameraParams(Camera camera, CameraData cameraData, boolean isTouchMode, CameraConfiguration configuration) throws CameraNotSupportException { boolean isLandscape = (configuration.orientation != CameraConfiguration.Orientation.PORTRAIT); int cameraWidth = Math.max(configuration.height, configuration.width); int cameraHeight = Math.min(configuration.height, configuration.width); Camera.Parameters parameters = camera.getParameters(); setPreviewFormat(camera, parameters); setPreviewFps(camera, configuration.fps, parameters); setPreviewSize(camera, cameraData, cameraWidth, cameraHeight, parameters); cameraData.hasLight = supportFlash(camera); setOrientation(cameraData, isLandscape, camera); setFocusMode(camera, cameraData, isTouchMode); } public static void setPreviewFormat(Camera camera, Camera.Parameters parameters) throws CameraNotSupportException{ //设置预览回调的图片格式 try { parameters.setPreviewFormat(ImageFormat.NV21); camera.setParameters(parameters); } catch (Exception e) { throw new CameraNotSupportException(); } } public static void setPreviewFps(Camera camera, int fps, Camera.Parameters parameters) { //设置摄像头预览帧率 if(BlackListHelper.deviceInFpsBlacklisted()) { SopCastLog.d(SopCastConstant.TAG, "Device in fps setting black list, so set the camera fps 15"); fps = 15; } try { parameters.setPreviewFrameRate(fps); camera.setParameters(parameters); } catch (Exception e) { e.printStackTrace(); } int[] range = adaptPreviewFps(fps, parameters.getSupportedPreviewFpsRange()); try { parameters.setPreviewFpsRange(range[0], range[1]); camera.setParameters(parameters); } catch (Exception e) { e.printStackTrace(); } } private static int[] adaptPreviewFps(int expectedFps, List<int[]> fpsRanges) { expectedFps *= 1000; int[] closestRange = fpsRanges.get(0); int measure = Math.abs(closestRange[0] - expectedFps) + Math.abs(closestRange[1] - expectedFps); for (int[] range : fpsRanges) { if (range[0] <= expectedFps && range[1] >= expectedFps) { int curMeasure = Math.abs(range[0] - expectedFps) + Math.abs(range[1] - expectedFps); if (curMeasure < measure) { closestRange = range; measure = curMeasure; } } } return closestRange; } public static void setPreviewSize(Camera camera, CameraData cameraData, int width, int height, Camera.Parameters parameters) throws CameraNotSupportException { Camera.Size size = getOptimalPreviewSize(camera, width, height); if(size == null) { throw new CameraNotSupportException(); }else { cameraData.cameraWidth = size.width; cameraData.cameraHeight = size.height; } //设置预览大小 SopCastLog.d(SopCastConstant.TAG, "Camera Width: " + size.width + " Height: " + size.height); try { parameters.setPreviewSize(cameraData.cameraWidth, cameraData.cameraHeight); camera.setParameters(parameters); } catch (Exception e) { e.printStackTrace(); } } private static void setOrientation(CameraData cameraData, boolean isLandscape, Camera camera) { int orientation = getDisplayOrientation(cameraData.cameraID); if(isLandscape) { orientation = orientation - 90; } camera.setDisplayOrientation(orientation); } private static void setFocusMode(Camera camera, CameraData cameraData, boolean isTouchMode) { cameraData.supportTouchFocus = supportTouchFocus(camera); if(!cameraData.supportTouchFocus) { setAutoFocusMode(camera); } else { if(!isTouchMode) { cameraData.touchFocusMode = false; setAutoFocusMode(camera); }else { cameraData.touchFocusMode = true; } } } public static boolean supportTouchFocus(Camera camera) { if(camera != null) { return (camera.getParameters().getMaxNumFocusAreas() != 0); } return false; } public static void setAutoFocusMode(Camera camera) { try { Camera.Parameters parameters = camera.getParameters(); List<String> focusModes = parameters.getSupportedFocusModes(); if (focusModes.size() > 0 && focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); camera.setParameters(parameters); } else if (focusModes.size() > 0) { parameters.setFocusMode(focusModes.get(0)); camera.setParameters(parameters); } } catch (Exception e) { e.printStackTrace(); } } public static void setTouchFocusMode(Camera camera) { try { Camera.Parameters parameters = camera.getParameters(); List<String> focusModes = parameters.getSupportedFocusModes(); if (focusModes.size() > 0 && focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) { parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); camera.setParameters(parameters); } else if (focusModes.size() > 0) { parameters.setFocusMode(focusModes.get(0)); camera.setParameters(parameters); } } catch (Exception e) { e.printStackTrace(); } } public static Camera.Size getOptimalPreviewSize(Camera camera, int width, int height) { Camera.Size optimalSize = null; double minHeightDiff = Double.MAX_VALUE; double minWidthDiff = Double.MAX_VALUE; List<Camera.Size> sizes = camera.getParameters().getSupportedPreviewSizes(); if (sizes == null) return null; //找到宽度差距最小的 for(Camera.Size size:sizes){ if (Math.abs(size.width - width) < minWidthDiff) { minWidthDiff = Math.abs(size.width - width); } } //在宽度差距最小的里面,找到高度差距最小的 for(Camera.Size size:sizes){ if(Math.abs(size.width - width) == minWidthDiff) { if(Math.abs(size.height - height) < minHeightDiff) { optimalSize = size; minHeightDiff = Math.abs(size.height - height); } } } return optimalSize; } public static int getDisplayOrientation(int cameraId) { Camera.CameraInfo info = new Camera.CameraInfo(); Camera.getCameraInfo(cameraId, info); int result; if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { result = (info.orientation) % 360; result = (360 - result) % 360; // compensate the mirror } else { // back-facing result = (info.orientation + 360) % 360; } return result; } public static void checkCameraService(Context context) throws CameraDisabledException, NoCameraException { // Check if device policy has disabled the camera. DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService( Context.DEVICE_POLICY_SERVICE); if (dpm.getCameraDisabled(null)) { throw new CameraDisabledException(); } List<CameraData> cameraDatas = getAllCamerasData(false); if(cameraDatas.size() == 0) { throw new NoCameraException(); } } public static boolean supportFlash(Camera camera){ Camera.Parameters params = camera.getParameters(); List<String> flashModes = params.getSupportedFlashModes(); if(flashModes == null) { return false; } for(String flashMode : flashModes) { if(Camera.Parameters.FLASH_MODE_TORCH.equals(flashMode)) { return true; } } return false; } }