/* * * Camera2Model.java * * Created by Wuwang on 2017/3/3 * Copyright © 2016年 深圳哎吖科技. All rights reserved. */ package com.aiyaapp.aiya.mvc; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.annotation.TargetApi; import android.content.Context; import android.graphics.SurfaceTexture; import android.hardware.camera2.CameraAccessException; import android.hardware.camera2.CameraCaptureSession; import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CameraManager; import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.CaptureResult; import android.hardware.camera2.TotalCaptureResult; import android.hardware.camera2.params.StreamConfigurationMap; import android.os.Build; import android.os.Handler; import android.os.HandlerThread; import android.util.Size; import android.view.Surface; import com.aiyaapp.camera.sdk.base.Renderer; import com.aiyaapp.camera.sdk.widget.AiyaController; import com.aiyaapp.camera.sdk.widget.AiyaModel; import com.aiyaapp.camera.sdk.base.Log; /** * Description: 使用{@link android.hardware.camera2}中的API的Model示例 */ @TargetApi(Build.VERSION_CODES.LOLLIPOP) public class Camera2Model implements AiyaModel { private CameraDevice mCameraDevice; private CameraController mCameraController; private static final Object lock=new Object(); private AiyaController mController; private Context mContext; public Camera2Model(Context context){ this.mContext=context; } public void setCameraController(CameraController cameraController){ this.mCameraController=cameraController; } @Override public void attachToController(final AiyaController controller) { if(mCameraController==null){ mCameraController=new CameraController(mContext); } this.mController=controller; controller.setRenderer(new Renderer() { @Override public void onDestroy() { mCameraController.release(); } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { mCameraController.start(); mCameraController.setTarget(controller.getTexture()); mCameraController.openCamera(1); controller.setDataSize(mCameraController.mPreviewSize.getHeight(), mCameraController.mPreviewSize.getWidth()); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { } @Override public void onDrawFrame(GL10 gl) { } }); } public class CameraController{ private CameraManager mCameraManager; private CameraDevice mCameraDevice; private CameraCaptureSession mCaptureSession; private CaptureRequest.Builder mCaptureRequestBuilder; private SurfaceTexture mTexture; private HandlerThread mThread; private Handler mHandler; public Size mPreviewSize=new Size(720,1280); public CameraController(Context context){ mCameraManager= (CameraManager)context.getSystemService(Context.CAMERA_SERVICE); } protected void start(){ mThread=new HandlerThread("camera2 thread"+System.currentTimeMillis()); mThread.start(); mHandler=new Handler(mThread.getLooper()); } protected Size setSize(int cameraId, StreamConfigurationMap map){ List<Size> sizes=Arrays.asList(map.getOutputSizes(SurfaceTexture.class)); Collections.sort(sizes, sizeComparator); return getPropPreviewSize(sizes,1.778f,720); } public CameraDevice openCamera(int cameraId){ try { CameraCharacteristics characteristics= mCameraManager.getCameraCharacteristics(cameraId+""); //支持的STREAM CONFIGURATION StreamConfigurationMap map = characteristics.get(CameraCharacteristics .SCALER_STREAM_CONFIGURATION_MAP); mPreviewSize=setSize(cameraId,map); mCameraDevice=null; while (mCameraDevice==null){ mCameraManager.openCamera(cameraId+"",mDeviceStateCallback,mHandler); synchronized (lock){ try { Log.e("camera2","wait"); lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } catch (CameraAccessException | SecurityException e) { e.printStackTrace(); } Log.e("camera2","reture device"+(mCameraDevice==null)); return mCameraDevice; } public final void setTarget(SurfaceTexture texture){ this.mTexture=texture; } private CameraDevice.StateCallback mDeviceStateCallback=new CameraDevice.StateCallback() { @Override public void onOpened(CameraDevice camera) { mCameraDevice=camera; synchronized (lock){ Log.e("camera2","lock.notifyAll()"); lock.notifyAll(); } try { Surface mSurface=new Surface(mTexture); mTexture.setDefaultBufferSize(mPreviewSize.getWidth(),mPreviewSize.getHeight()); mCaptureRequestBuilder=mCameraDevice.createCaptureRequest(CameraDevice .TEMPLATE_RECORD); mCaptureRequestBuilder.addTarget(mSurface); mCameraDevice.createCaptureSession(Arrays.asList(mSurface), mCaptureSessionStateCallback,mHandler); Log.e("camera2","createCaptureSession"); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onDisconnected(CameraDevice camera) { synchronized (lock){ Log.e("camera2","onDisconnected"); lock.notifyAll(); } } @Override public void onError(CameraDevice camera, int error) { synchronized (lock){ Log.e("camera2","open error"); lock.notifyAll(); } } }; private CameraCaptureSession.StateCallback mCaptureSessionStateCallback= new CameraCaptureSession.StateCallback() { @Override public void onConfigured(CameraCaptureSession session) { mCaptureSession=session; try { session.setRepeatingRequest(mCaptureRequestBuilder.build(), mCaptureSessionCaptureCallback,mHandler); Log.e("camera2","setRepeatingRequest"); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onConfigureFailed(CameraCaptureSession session) { } }; private CameraCaptureSession.CaptureCallback mCaptureSessionCaptureCallback= new CameraCaptureSession.CaptureCallback() { @Override public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) { super.onCaptureCompleted(session, request, result); Log.e("camera2","onCaptureCompleted"); onPreviewCallback(mCameraDevice,session); } @Override public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request, CaptureResult partialResult) { super.onCaptureProgressed(session, request, partialResult); Log.e("camera2","onCaptureProgressed"); } }; protected void onPreviewCallback(CameraDevice device,CameraCaptureSession session){ mController.requestRender(); } protected void release(){ if(mCaptureSession!=null){ mCaptureSession.close(); } if(mCameraDevice!=null){ mCameraDevice.close(); } mHandler.getLooper().quitSafely(); } protected Size getPropPreviewSize(List<Size> list, float th, int minWidth){ Collections.sort(list, sizeComparator); int i = 0; for(Size s:list){ if((s.getHeight() >= minWidth) && equalRate(s, th)){ break; } i++; } if(i == list.size()){ i = 0; } return list.get(i); } private boolean equalRate(Size s, float rate){ float r = (float)(s.getWidth())/(float)(s.getHeight()); return Math.abs(r - rate) <= 0.03; } private Comparator<Size> sizeComparator=new Comparator<Size>(){ public int compare(Size lhs, Size rhs) { // TODO Auto-generated method stub if(lhs.getHeight() == rhs.getHeight()){ return 0; } else if(lhs.getHeight() > rhs.getHeight()){ return 1; } else{ return -1; } } }; } }