package com.example.datalibrary.gatecamera; import android.graphics.SurfaceTexture; import android.hardware.Camera; import android.util.Log; import android.util.SparseIntArray; import android.view.Surface; import android.view.SurfaceHolder; import android.view.TextureView; import android.view.ViewGroup; import android.view.ViewParent; import com.example.datalibrary.callback.CameraDataCallback; import com.example.datalibrary.gl.view.GLFaceSurfaceView; import com.example.datalibrary.gl.view.GlMantleSurfacView; import java.io.IOException; import java.util.List; /** * Time: 2019/1/24 * Author: v_chaixiaogang * Description: */ public class CameraPreviewManager implements SurfaceHolder.Callback , TextureView.SurfaceTextureListener { private static final String TAG = "camera_preview"; GLFaceSurfaceView surfaceView; boolean mPreviewed = false; public static final int CAMERA_FACING_BACK = 0; public static final int CAMERA_FACING_FRONT = 1; public static final int CAMERA_USB = 2; /** * 当前相机的ID。 */ private int cameraFacing = CAMERA_FACING_BACK; private int previewWidth; private int previewHeight; private int videoWidth; private int videoHeight; private int surfaceWidth; private int surfaceHeight; private Camera mCamera; private int displayOrientation = 0; private int videoDirection; private GlMantleSurfacView mTextureView; private SurfaceTexture mSurfaceTexture; private int mirrorVideoRGB; public void setmCameraDataCallback(CameraDataCallback mCameraDataCallback) { this.mCameraDataCallback = mCameraDataCallback; } public void destroy() { } private CameraDataCallback mCameraDataCallback; private static volatile CameraPreviewManager instance = null; private static final SparseIntArray ORIENTATIONS = new SparseIntArray(); static { ORIENTATIONS.append(Surface.ROTATION_0, 0); ORIENTATIONS.append(Surface.ROTATION_90, 90); ORIENTATIONS.append(Surface.ROTATION_180, 180); ORIENTATIONS.append(Surface.ROTATION_270, 270); } public static CameraPreviewManager getInstance() { synchronized (CameraPreviewManager.class) { if (instance == null) { instance = new CameraPreviewManager(); } } return instance; } public int getCameraFacing() { return cameraFacing; } public void setCameraFacing(int cameraFacing) { this.cameraFacing = cameraFacing; } public int getDisplayOrientation() { return displayOrientation; } public void setDisplayOrientation(int displayOrientation) { this.displayOrientation = displayOrientation; } @Override public void surfaceCreated(SurfaceHolder surfaceHolder) { } @Override public void surfaceChanged(SurfaceHolder surfaceHolder, int i, final int width, final int height) { if (surfaceView != null){ surfaceWidth = width; surfaceHeight = height; surfaceView.surfaceChanged(surfaceHolder); openCamera(); } } /** * 开启预览 * @param textureView */ public void startPreview(GlMantleSurfacView textureView, int videoDirection , int width, int height) { Log.e(TAG, "开启预览模式"); mTextureView = textureView; if (textureView.getGlFaceSurfaceView() != null){ surfaceView = textureView.getGlFaceSurfaceView(); this.previewWidth = width; this.previewHeight = height; this.videoDirection = videoDirection; }else { this.previewWidth = width; this.previewHeight = height; this.videoDirection = videoDirection; this.mirrorVideoRGB = textureView.getMirrorRGB(); mSurfaceTexture = mTextureView.getTextureView().getSurfaceTexture(); mTextureView.getTextureView().setSurfaceTextureListener(this); } } @Override public void surfaceDestroyed(SurfaceHolder surfaceHolder) { if (surfaceView != null){ //System.out.println("==内存==>surfaceDestroyed"); surfaceView.surfaceDestroyed(); } } /** * 关闭预览 */ public void stopPreview() { if (mCamera != null) { try { mCamera.setPreviewCallback(null); mCamera.stopPreview(); mPreviewed = false; mCamera.release(); mCamera = null; } catch (Exception e) { Log.e("qing", "camera destory error"); e.printStackTrace(); } } } public static interface ErrInfoCallBack{ void err(String errInfo); } public int[] initCamera(ErrInfoCallBack callBack){ try { if (mCamera == null) { mCamera = Camera.open(cameraFacing); Log.e(TAG, "initCamera---open camera"); } // 摄像头图像预览角度 int cameraRotation = videoDirection; mCamera.setDisplayOrientation(cameraRotation); if (mTextureView != null){ if (cameraRotation == 90 || cameraRotation == 270) { if (mirrorVideoRGB == 1) { mTextureView.setRotationY(180); } else { mTextureView.setRotationY(0); } // 旋转90度或者270,需要调整宽高 mTextureView.setPreviewSize(previewHeight, previewWidth); } else { if (mirrorVideoRGB == 1) { mTextureView.setRotationY(180); } else { mTextureView.setRotationY(0); } mTextureView.setPreviewSize(previewWidth, previewHeight); } } Camera.Parameters params = mCamera.getParameters(); List sizeList = params.getSupportedPreviewSizes(); // 获取所有支持的camera尺寸 final Camera.Size optionSize = getOptimalPreviewSize(sizeList, previewWidth, previewHeight); // 获取一个最为适配的camera.size if (optionSize.width == previewWidth && optionSize.height == previewHeight) { videoWidth = previewWidth; videoHeight = previewHeight; } else { videoWidth = optionSize.width; videoHeight = optionSize.height; } params.setPreviewSize(videoWidth, videoHeight); mCamera.setParameters(params); if (mTextureView != null){ try { mCamera.setPreviewCallback(new Camera.PreviewCallback() { @Override public void onPreviewFrame(byte[] bytes, Camera camera) { if (mCameraDataCallback != null) { mCameraDataCallback.onGetCameraData(bytes, camera, videoWidth, videoHeight); } } }); mCamera.setPreviewTexture(mSurfaceTexture); mCamera.startPreview(); } catch (Exception e) { e.printStackTrace(); if(callBack!=null){ callBack.err("开启相机报错 (2)==>"+e.getMessage()); } Log.e(TAG, e.getMessage()); } } if (surfaceView != null){ surfaceView.getHolder().addCallback(this); surfaceView.setWillNotDraw(false); } }catch (Exception e){ e.printStackTrace(); if(callBack!=null){ callBack.err("开启相机报错 (1)==>"+e.getMessage()); } } return new int[]{videoWidth , videoHeight}; } /** * 开启摄像头 */ public void openCamera() { try { try { mCamera.setPreviewTexture(surfaceView.getFramebuffer()); mCamera.setPreviewCallback(new Camera.PreviewCallback() { @Override public void onPreviewFrame(byte[] bytes, Camera camera) { if (mCameraDataCallback != null) { mCameraDataCallback.onGetCameraData(bytes, camera, videoWidth, videoHeight); } } }); mCamera.startPreview(); surfaceView.initFrame(surfaceWidth , surfaceHeight); if (videoDirection == 90 || videoDirection == 270){ surfaceView.setSize(videoHeight , videoWidth); }else { surfaceView.setSize(videoWidth , videoHeight); } } catch (Exception e) { e.printStackTrace(); Log.e(TAG, e.getMessage()); } } catch (RuntimeException e) { Log.e(TAG, e.getMessage()); } } private int getCameraDisplayOrientation(int degrees, int cameraId) { Camera.CameraInfo info = new Camera.CameraInfo(); Camera.getCameraInfo(cameraId, info); int rotation = 0; if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { rotation = (info.orientation + degrees) % 360; rotation = (360 - rotation) % 360; } else { // back-facing rotation = (info.orientation - degrees + 360) % 360; } return rotation; } /** * 解决预览变形问题 * * @param sizes * @param w * @param h * @return */ private Camera.Size getOptimalPreviewSize(List sizes, int w, int h) { final double aspectTolerance = 0.1; double targetRatio = (double) w / h; if (sizes == null) { return null; } Camera.Size optimalSize = null; double minDiff = Double.MAX_VALUE; int targetHeight = h; // Try to find an size match aspect ratio and size for (Camera.Size size : sizes) { double ratio = (double) size.width / size.height; if (Math.abs(ratio - targetRatio) > aspectTolerance) { continue; } if (Math.abs(size.height - targetHeight) < minDiff) { optimalSize = size; minDiff = Math.abs(size.height - targetHeight); } } // Cannot find the one match the aspect ratio, ignore the requirement if (optimalSize == null) { minDiff = Double.MAX_VALUE; for (Camera.Size size : sizes) { if (Math.abs(size.height - targetHeight) < minDiff) { optimalSize = size; minDiff = Math.abs(size.height - targetHeight); } } } return optimalSize; } @Override public void onSurfaceTextureAvailable(SurfaceTexture texture, int i, int i1) { try { if (mCamera != null && !mPreviewed) { mSurfaceTexture = texture; mCamera.setPreviewTexture(mSurfaceTexture); mCamera.startPreview(); mPreviewed = true; } } catch (Exception exception) { Log.e("chaixiaogang", "IOException caused by setPreviewDisplay()", exception); } } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) { Log.e(TAG, "--surfaceTexture--TextureSizeChanged"); } @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) { if (mCamera != null) { mCamera.stopPreview(); mPreviewed = false; mCamera.setPreviewCallback(null); mCamera.stopPreview(); mCamera.release(); mCamera = null; } mCameraDataCallback = null; //System.out.println("==内存==>onSurfaceTextureDestroyed"); if(mSurfaceTexture!=null) { mSurfaceTexture.release(); mSurfaceTexture = null; } if (surfaceView != null){ surfaceView.surfaceDestroyed(); surfaceView = null; } if(mTextureView!=null) { //System.out.println("==内存==>mTextureView"); mTextureView.getTextureView().setSurfaceTextureListener(null); mTextureView.destroy(); mTextureView = null; } return true; } @Override public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { Log.e(TAG, "--surfaceTexture--Updated"); } }