IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> 【Android Camera1】Camera1初始化销毁流程(七) ——初始化伪代码 -> 正文阅读

[游戏开发]【Android Camera1】Camera1初始化销毁流程(七) ——初始化伪代码

//CameraView.java
public int mCameraId = DEFAULT_CAMERA_ID;
 @Override
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
   super.surfaceChanged(holder, format, w, h);
   tryInit(holder, w, h);
}
public void tryInit(SurfaceHolder holder ,int w, int h){
   if(!checkHasPermission(CAMERA)) {
       uiObserver.onPermissionDeny();
       return false;
   }
   uiObserver.onPermissionGranted();
   mAspectRatio = w / h;
   CameraManager.of().initCamera(holder, mAspectRatio, mCameraId)
}

//CameraManager.java
public static final int MSG_INIT_CAMERA = 0;
public void initCamera(SurfaceHolder holder, float aspectRatio, int cameraId,){
	getCameraHandler()
	.sendMessage(handler.obtainMessage(MSG_INIT_CAMERA, cameraId, aspectRatio));
}

...

public void handleMessage(Message msg){
	switch (msg.what) {
		case MSG_INIT_CAMERA:
			camera.initCamera((SurfaceHolder)msg.obj[0], (float)msg.obj[1],(int)msg.obj[2]);
            break;
        ...
	}
}

//Camera1Impl.java
public void initCamera(SurfaceHolder holder, int cameraId, float aspectRatio){
	this.mHolder = holder;
	this.mCameraId = cameraId;
	this.mAspectRatio = aspectRatio;
	synchronized(lock){
		try{
			if(acquireLock(timeout = 2000)){
				Log.i(TAG, "initCamera超时")
			}
			openCamera(cameraId);
			applyDefaultParameters();
			startPreview();
			releaseLock();
			Log.i(TAG, "initCamera succ")
			retryCount = 0;
		}catch(Exception e){
			releaseLock();
			Log.e(TAG, "initCamera exception info = "+e.getInfo();
			if(retryCount > DEFAULT_RETRY_COUNT){
				getCameraHandler().postDelay(()->{
					retryCount++;
					initCamera(holder, cameraId, aspectRatio);
				},20);
			}
		}
	}
}

public void openCamera(int cameraId){
	int count = 0;
		// @return total number of accessible camera devices, 
		//or 0 if there are no cameras or an error was encountered enumerating them.
	try{
		count = Camera.getNumberOfCameras();
	}catch(Exception e){
		count = -1;
	}
	if(count == 0){
		Toast("清检查设备前后置摄像头")
		//释放锁
		releaseLock();
		return;
	}
	if(count == -1){
		releaseLock();
		if(retryCount> DEFAULT_RETRY_COUNT){
			getCameraHandle().postDelay(()->{
				openCamera(cameraId);
				retryCount++;
			},20);
		}
		return;
	}
	retryCount= 0;
	if(mCamera!=null){
		//releaseCamera释放camera,并set null to mCamera。
		releaseCamera();
	}
	mCamera = Camera.open(cameraId);
	if(mCamera == null){
		Toast("打开摄像头失败");
		releaseLock();
		return;
	}
	mCameraId = cameraId;
	Camera.CameraInfo info = new Camera.CameraInfo();
	try{
		Camera.getCameraInfo(mCameraId,info)
	}catch(Exception e){
		Log.e(TAG,"exception info = "+ e.getInfo());
	}
	
	mCanDisableSound = info.canDisableShutterSound;
	if(mCanDisableSound){
		try {
			// 关闭快门声
	       mCamera.enableShutterSound(false);  
	   	}catch (Exception e){
	    }
	}else{
		//TODO 需要做额外的关闭声音容错处理
	}
}

private void applyDefaultParameters(){
	//1.apply方向
	applyDefaultOrientation();
	//2.apply previewSize
	applyDefaultPreviewSize();
	//3.apply pictureSize
	applyDefaultPictureSize();
	//4.apply focus mode
	applyDefaultFocusMode();
	//5.apply flash mode
	applyDefaultFlashMode();
}
private int applyDefaultOrientation() {
 	int displayOrientation;
 	 //1.问题机型兼容逻辑处理
 	if(CameraCompat.Camera1.isOrientationExcepDevice(Build.Model)){
 	 	displayOrientation = CameraCompat.Camera1.getOrientationForExcepDevices();
 	}else{	
 	//2.逻辑计算
	    int rotation = activity.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;
	    }

//mOrientation为 CameraInfo里 orientation字段,在openCamera阶段保存为变量即可
	    if (mFacing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
	        displayOrientation = (mOrientation + degrees) % 360;
	        displayOrientation = (360 - displayOrientation) % 360;  
	        // compensate the mirror
	    } else {  // back-facing
	        displayOrientation = (mOrientation - degrees + 360) % 360;
	    }
	}
    try{
    //3.非致命异常 try-catch
   		camera.setDisplayOrientation(displayOrientation);
    }catch(Exception e){
   		Log.e(TAG, "setDisplayOrientation exception info = "+e.getInfo());
    }
}

public void applyDefaultPreviewSize(){
    if (mShowingPreview) {
        mCamera.stopPreview();
    }
	Camera.Parameters params = null;
	try{
		//mCamera.getParameters();需要try-catch住,不是致命bug
		params = mCamera.getParameters();
	}catch(Exception e){
		...
	}
	if(params == null){
		//不设置 return
		return;
	}
	List<Size> previewSize = null;
	try{
		//可参看源码,内部没有异常try-catch。可能会抛异常,也可能返回为null;
		previewSize = params.getSupportedPreviewSizes();
	}catch(Exception e){
		...
	}
	if(previewSize == null || previewSize.size() == 0){
		return;
	}
	float min = Integer.MAX_VALUE;
	Size selectSize = null;
	for(Size s : previewSize){
		float ar = AspectRatio.cal(s);
		if(ar - mAspectRatio < min){
			selectPreviewSize = s;
			min = Math.min(min,Math.abs(mAspectRatio - ar));
		}
	}
	if(selectPreviewSize == null){
		return;
	}
	try{
		params.setPreviewSize(selectSize.getWidth(),selectSize.getHeight());
	}catch(Exception e){
		...
	}
}

public void applyDefaultPictureSize(){
    if (mShowingPreview) {
        mCamera.stopPreview();
    }
	Camera.Parameters params = null;
	try{
		//mCamera.getParameters();需要try-catch住,不是致命bug
		params = mCamera.getParameters();
	}catch(Exception e){
		...
	}
	if(params == null){
		//不设置 return
		return;
	}
	List<Size> pictureSize = null;
	try{
		//可参看源码,内部没有异常try-catch。可能会抛异常,也可能返回为null;
		pictureSize = params.getSupportedPictureSizes();
	}catch(Exception e){
		...
	}
	if(pictureSize == null || pictureSize.size() == 0){
		return;
	}
	float min = Integer.MAX_VALUE;
	Size selectSize = null;
	for(Size s : pictureSize){
		float ar = AspectRatio.cal(s);
		if(ar - mAspectRatio < min){
			selectPictureSize = s;
			min = Math.min(min,Math.abs(mAspectRatio - ar));
		}
	}
	if(selectPictureSize == null){
		return;
	}
	try{
		params.setPictureSize(selectSize.getWidth(),selectSize.getHeight());
	}catch(Exception e){
		...
	}
}

public boolean applyDefaultFocusMode(){
	if(!isCameraOpened()){
		return false;
	}
	try{
	    final List<String> modes = mCameraParameters.getSupportedFocusModes();
	    if(modes == null || modes.size() == 0){
	    	return false;
	    }
	    if (isCurVideoTab()
	    && modes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
	        mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
	    } else if (modes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
	        mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
	    }else if (modes.contains(Camera.Parameters.FOCUS_MODE_FIXED)) {
	        mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_FIXED);
	    } else if (modes.contains(Camera.Parameters.FOCUS_MODE_INFINITY)) {
	        mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY);
	    } else {
	        mCameraParameters.setFocusMode(modes.get(0));
	    }
	}catch(Exception e){
		...
	}
}

private static final SparseArrayCompat<String> FLASH_MODES = new SparseArrayCompat<>();

static {
    FLASH_MODES.put(Constants.FLASH_OFF, Camera.Parameters.FLASH_MODE_OFF);
    FLASH_MODES.put(Constants.FLASH_ON, Camera.Parameters.FLASH_MODE_ON);
    FLASH_MODES.put(Constants.FLASH_TORCH, Camera.Parameters.FLASH_MODE_TORCH);
    FLASH_MODES.put(Constants.FLASH_AUTO, Camera.Parameters.FLASH_MODE_AUTO);
    FLASH_MODES.put(Constants.FLASH_RED_EYE, Camera.Parameters.FLASH_MODE_RED_EYE);
}

private boolean applyDefaultFlashMode(int flash) {
    if (isCameraOpened()) {
        List<String> modes = mCameraParameters.getSupportedFlashModes();
        String mode = FLASH_MODES.get(flash);
        if (modes != null && modes.contains(mode)) {
            mCameraParameters.setFlashMode(mode);
            mFlash = flash;
            return true;
        }
        String currentMode = FLASH_MODES.get(mFlash);
        if (modes == null || !modes.contains(currentMode)) {
            mCameraParameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
            mFlash = Constants.FLASH_OFF;
            return true;
        }
        return false;
    } else {
        mFlash = flash;
        return false;
    }
}

public void startPreview(){
	//这里兜底再做一次权限检查防止无权限出错
	if(CheckHasPermission(CAMERA_PERMISSION)){
		Toast("无相机权限")
		return;
	}
	if(isPreviewing){
		Toast("重复初始化")
		return;
	}
	if(mCamera == null){
		//这里因为openCamera底层是异步的在极端情况下,mCamera会由于时许问题在此位null
		return;
	}
	try{
		//mCamera.startPreview() 经常会抛异常错误信息位startPreview fail. 该异常一部分通常与自动对焦有关系,所以这里try-catch cancelAutoFocus.
		//cancelAutoFocus
		mCamera.cancelAutoFocus();
	}catch(Exception e){
		
	}
	synchronize(Lock){
		if(acquireLock(timeot = 2000)){
			Log.w("timeout");
		}
		mCamera.setPreviewDisplay(mSurfaceHolder);
		//previewCallBack监听回调,通知UI层。
		mCamera.setPreviewCallBack(new PreviewCallback(){
			void onPreviewFrame(byte[] data, Camera camera){
				releaseLock();
				if(isPreviewing) return;
				isPreviewing = true;
				CameraManager.of().onCameraPreviewed();=
			}
		})
		try{
			mCamera.startPreview();
		}catch(Exception e){
			Log.e(TAG, "exp info = "+e.getInfos());
			//重试逻辑
			retryStartPreview();
		}
	}
}

public void releaseCamera(){
	if(mCamera == null) return;
	synchronized(Lock){
		try{
			if(acquireLock(timeout = 2000)){
				Log.e(TAG, "timeout")
			}
			mCamera.stopPreview();
			mCamera.release();
			mCamera = null;
			releaseLock();
		}catch(Exception e){
			...
		}
	}
}
  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-01-04 13:45:22  更:2022-01-04 13:45:24 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 18:41:53-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码