【Android Camera1】Camera1初始化销毁流程(六) —— Camera1Impl类之startPreview,release伪代码

一、摘要

本篇文章包含如下2个部分:

  • startPreview
  • release

二、伪代码

2.1 Camera1源码

Camera.java源码里startPreview描述如下:


    /**
     * Starts capturing and drawing preview frames to the screen.
     * Preview will not actually start until a surface is supplied
     * with {@link #setPreviewDisplay(SurfaceHolder)} or
     * {@link #setPreviewTexture(SurfaceTexture)}.
     *
     * <p>If {@link #setPreviewCallback(Camera.PreviewCallback)},
     * {@link #setOneShotPreviewCallback(Camera.PreviewCallback)}, or
     * {@link #setPreviewCallbackWithBuffer(Camera.PreviewCallback)} were
     * called, {@link Camera.PreviewCallback#onPreviewFrame(byte[], Camera)}
     * will be called when preview data becomes available.
     *
     * @throws RuntimeException if starting preview fails; usually this would be
     *    because of a hardware or other low-level error, or because release()
     *    has been called on this Camera instance. The QCIF (176x144) exception
     *    mentioned in {@link Parameters#setPreviewSize setPreviewSize} and
     *    {@link Parameters#setPictureSize setPictureSize} can also cause this
     *    exception be thrown.
     */
    public native final void startPreview();

分析

  1. Starts capturing and drawing preview frames to the screen
  2. 需要提供SurfaceTexture或者SurfaceHolder才可preview
  3. setPreviewCallback可监听preview的状态
  4. 会抛异常。

2.2 官方Demo

官方Demo里startPreview的相关逻辑如下:

  Camera1(Callback callback, PreviewImpl preview) {
    
    
      super(callback, preview);
      preview.setCallback(new PreviewImpl.Callback() {
    
    
          @Override
          public void onSurfaceChanged() {
    
    
              if (mCamera != null) {
    
    
                  setUpPreview();
                  adjustCameraParameters();
              }
          }
      });
  }
    
  @Override
  boolean start() {
    
    
      chooseCamera();
      openCamera();
      if (mPreview.isReady()) {
    
    
          setUpPreview();
      }
      mShowingPreview = true;
      mCamera.startPreview();
      return true;
  }
  
  // Suppresses Camera#setPreviewTexture
  @SuppressLint("NewApi")
  void setUpPreview() {
    
    
      try {
    
    
          if (mPreview.getOutputClass() == SurfaceHolder.class) {
    
    
              mCamera.setPreviewDisplay(mPreview.getSurfaceHolder());
          } else {
    
    
              mCamera.setPreviewTexture((SurfaceTexture) mPreview.getSurfaceTexture());
          }
      } catch (IOException e) {
    
    
          throw new RuntimeException(e);
      }
  }

分析

  1. 构造函数里监听surfaceChange来设置SurfaceTexture/SurfaceHolder
  2. start 函数里直接调用mCamera.startPreview();

2.3 更新代码

public void initCamera(int cameraId, float aspectRatio, SurfaceTexture surfaceTexture){
    
    
	this.mSurfaceTexture = surfaceTexture;
	...
}

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(mSurfaceTexture);
		//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();
		}
	}
}

2.4 releaseCamera

源码如下:


    /**
     * Disconnects and releases the Camera object resources.
     *
     * <p>You must call this as soon as you're done with the Camera object.</p>
     */
    public final void release() {
    
    
        native_release();
        mFaceDetectionRunning = false;
        releaseAppOps();
    }

官方Demo代码如下:

    private void releaseCamera() {
    
    
        if (mCamera != null) {
    
    
            mCamera.release();
            mCamera = null;
            mCallback.onCameraClosed();
        }
    }

更新代码如下:

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){
    
    
			...
		}
	}
}

至此Camera1Impl初始化销毁流程阐述完毕。下篇将会对所有伪代码进行汇总总结:
Camera1初始化销毁流程(七) —— 伪代码

猜你喜欢

转载自blog.csdn.net/Scott_S/article/details/122286578
今日推荐