关闭

Camera2(api2) 打开过程(一)

标签: api2camera2
252人阅读 评论(2) 收藏 举报
分类:

C++层log的输出,如果不全,可以调整log的级别:

adb shell dumpsys media.camera -v 1 ,至少改成>=1。

 

Camera2 打开过程 

public void onCreateTasks(Bundle state)@ CameraActivity.java{

       mFirstRunDialog = new FirstRunDialog(this,

              getAndroidContext(),

              mResolutionSetting,

              mSettingsManager,

              mOneCameraManager,

              newFirstRunDialog.FirstRunDialogListener() {

           @Override

           public void onFirstRunStateReady() {

                // Run normal resume tasks.

                resume();

           }

}

à

private void resume()@CameraActivity.java{

         mCurrentModule.resume();

}

à

public void resume()@CaptureModule.java{

       if (texture != null) {

           initSurfaceTextureConsumer();

           guard.mark("initSurfaceTextureConsumer");

       }       

}

à

private void initSurfaceTextureConsumer()@CaptureModule.java{

         reopenCamera();

}

à

private void reopenCamera() @CaptureModule.java{

         openCameraAndStartPreview();

}

à

在打开Camera设备,预览,拍照的过程中有几个比较重要的回调:

1、  OneCamera.OpenCallback @OneCamera.java

2、  CameraDevice. StateCallback@ CameraDevice.java

3、  CameraCaptureSession. StateCallback@ CameraCaptureSession.java

4、  CameraCaptureSession.CaptureCallback @ CameraCaptureSession.java

5、  OneCamera.CaptureReadyCallback@ OneCamera.java

这些回调的执行过程:

Step1CameraManager调用openCamera后,会执行CameraDevice.StateCallback这个回调,重写其中的onOpened方法:

Camera2OneCameraOpenerImpl.java

mCameraManager.openCamera(cameraKey.getValue(),new CameraDevice.StateCallback() {

         publicvoid onOpened(CameraDevice device) {

                   openCallback.onCameraOpened(oneCamera);

         }

}

Step2,在Step1onOpened方法中,又会回调OpenCallback,执行其中重写的onCameraOpened方法。

CaptureModule.java

mOneCameraOpener.open(cameraId,captureSetting, mCameraHandler, mainThread,

         imageRotationCalculator,mBurstController, mSoundPlayer,

         newOpenCallback() {

                   publicvoid onCameraOpened(@Nonnull final OneCamera camera) {

                            camera.startPreview(newSurface(getPreviewSurfaceTexture()),

                                     newCaptureReadyCallback() {

         public voidonReadyForCapture() {……}

}

                  }

}

Step3,在Step2onCameraOpened中,会调用oneCameraImplstartPreview方法,然后createCaptureSession又回调了CameraCaptureSession.StateCallback中的onConfigured方法。

OneCameraImpl.java

public void startPreview(SurfacepreviewSurface, CaptureReadyCallback listener) {

mDevice.createCaptureSession(outputSurfaces,new CameraCaptureSession.StateCallback() {

         public voidonConfigured(CameraCaptureSession session) {

                   boolean success =repeatingPreview(null);

                   listener.onReadyForCapture();

         }

}

Step4,在上一步的onConfigured中,通过repeatingPreview调用setRepeatingRequest开启预览,又会回调CameraCaptureSession.CaptureCallback,如果开启预览成功,会调用其中的方法:onCaptureCompleted

OneCameraImpl.java

private boolean repeatingPreview(Objecttag) {

//向相机设备发起获取图像的请求。

         mCaptureSession.setRepeatingRequest(builder.build(),mCaptureCallback,

                   mCameraHandler);

}

值得注意的这里回调了mCaptureCallback中的onCaptureCompleted,接着看这个函数的处理:

private finalCameraCaptureSession.CaptureCallback mCaptureCallback =

         newCameraCaptureSession.CaptureCallback() {

         publicvoid onCaptureCompleted(CameraCaptureSession session,

                   CaptureRequestrequest, TotalCaptureResult result) {

         if(mCaptureQueue.getFirst().setCaptureResult(result)

                   .isCaptureComplete()){

                   capture= mCaptureQueue.removeFirst();

         }

         OneCameraImpl.this.onCaptureCompleted(capture);

         }

};

根据sCaptureImageFormat,这里会获取到RAW数据,或者jpeg数据,原数据以dng文件的形式保存。

private voidonCaptureCompleted(InFlightCapture capture) {

         if(sCaptureImageFormat == ImageFormat.RAW_SENSOR) {

                   FiledngFile = new File(RAW_DIRECTORY, capture.session.getTitle() +".dng");

                   writeDngBytesAndClose(capture.image,capture.totalCaptureResult,

                            mCharacteristics,dngFile);

         }else {

                   saveJpegPicture(imageBytes,capture.parameters, capture.session,

                            capture.totalCaptureResult);

         }

----------------------------------------------------------------------------------------------------------------

private void openCameraAndStartPreview() @CaptureModule.java{

         mOneCameraOpener.open(…);

}

à

public void open(

           final CameraId cameraKey,

           final OneCameraCaptureSetting captureSetting,

           final Handler handler,

           final MainThread mainThread,

           final ImageRotationCalculator imageRotationCalculator,

           final BurstFacade burstController,

           final SoundPlayer soundPlayer,

           final OpenCallback openCallback,

           final FatalErrorHandler fatalErrorHandler)@Camera2OneCameraOpenerImpl.java{

 

         mCameraManager.openCamera(cameraKey.getValue(),new CameraDevice.StateCallback() {

                @Override

                public voidonDisconnected(CameraDevice device) {

                    if (isFirstCallback) {

                        isFirstCallback =false;

                        // If the camera isdisconnected before it is opened

                        // then we must callclose.

                        device.close();

                       openCallback.onCameraClosed();

                    }

                }

 

                @Override

                public void onClosed(CameraDevicedevice) {

                    if (isFirstCallback) {

                        isFirstCallback =false;

                       openCallback.onCameraClosed();

                    }

                }

 

                @Override

                public voidonOpened(CameraDevice device) {

                    if (isFirstCallback) {

                        isFirstCallback =false;

                        try {

                           CameraCharacteristics characteristics = mCameraManager

                                   .getCameraCharacteristics(device.getId());

                            // TODO: Setboolean based on whether HDR+ is

                            // enabled.

                            OneCamera oneCamera= OneCameraCreator.create(

                                    device,

                                   characteristics,

                                   mFeatureConfig,

                                   captureSetting,

                                    mDisplayMetrics,

                                    mContext,

                                    mainThread,

                                   imageRotationCalculator,

                                   burstController,

                                    soundPlayer, fatalErrorHandler);

 

                            if (oneCamera !=null) {

                               openCallback.onCameraOpened(oneCamera);

                            } else {

                                Log.d(TAG,"Could not construct a OneCamera object!");

                               openCallback.onFailure();

                            }

                        } catch(CameraAccessException e) {

                        } catch(OneCameraAccessException e) {

                        }

                    }

                }                

}

}

总结下几个回调接口的函数:

先说应用层的OneCamera.java中的:

OpenCallback,当一个Camera被打开或者打开失败时会调用其中的方法。具体实例是在CaptureModule中,通过mOneCameraOpener(Camera2OneCameraOpenerImpl)open方法,传入了这个OpenCallback的回调。

public static interface OpenCallback {

//camera成功打开时调用

         publicvoid onCameraOpened(@Nonnull OneCamera camera);

//打开camera失败时调用。

         publicvoid onFailure();

//在尝试打开camera时,如果camera被关闭或者断开连接了,会调用。

         publicvoid onCameraClosed();

}

这个回调是在Camera成功打开的前提下,才会回调,具体实例在CaptureModule中,onCameraOpened回调被执行时,通过mCamera(OneCameraImpl.java)调用startPreview设置了CaptureReadyCallback,然后在CameraCaptureSession.StateCallback()onConfigured回调被执行时,并且启动预览成功时,回调了其中的onReadyForCapture方法。

public static interfaceCaptureReadyCallback {

//系统准备发出拍照请求时调用。

         publicvoid onReadyForCapture();

//系统还没准备好发出拍照请求就出错了,比如camera配置失败等,这时会调用。

         publicvoid onSetupFailed();

}

然后看下Framework层的两个回调接口,

CameraDevice.java

一个Camera实例必须提供CameraManager#openCamera这个方法来打开camera设备,比如在Camera2OneCameraOpenerImpl.javaopen方法中就调用了mCameraManager.openCamera方法。

这个回调中状态更新,包括设备完成启动相关的通知(这里说的完成启动是指允许调用createCaptureSession方法),包括设备断开或者关闭,或者意想不到的设备错误。

public static abstract class StateCallback{

//这个方法是必须要实现的,在设备完成打开时调用。

         publicabstract void onOpened(@NonNull CameraDevice camera);
//
camera设备被关闭时调用,后面如果再尝试调用cameradevice的任何方法都会抛出异常,IllegalStateException

         publicvoid onClosed(@NonNull CameraDevice camera)

//这个方法必须要实现,当camera设备不再可用时调用。如果打开camera失败,调用onDisconnected,就不在调用onOpened了。在disconnected之后,再调用camera设备的其他方法都会抛出CameraAccessException,断开连接的原因有:安全策略或权限的改变,物理层的断开或移除了cameradevice,被更高优先级的cameraclient所需要。

         publicabstract void onDisconnected(@NonNull CameraDevice camera);

//这个方法必须实现,当cameradevice遇到严重错误时会调用。

         publicabstract void onError(@NonNull CameraDevice camera, @ErrorCode int error);

}

CameraCaptureSession.java

通过提供一组目标output Surfaces作为CameraDevice#createCaptureSession的参数,可以创建一个createCaptureSession;或者提供一个(android.hardware.camera2.params.InputConfiguration)和一组目标outputsurfaces作为CameraDevice#createReprocessableCaptureSession的参数,可以创建一个可重复处理的capture session,一旦创建,这个session就是active的,直到有一个新的session被这个camera device创建,或者camera device被关闭了。

所有的capture sessions都可以用来capturing images,但是只有reprocessable capture sessions可以在同一个session上重复的处理imagescaptured

创建一个session是一个很昂贵的操作,可能需要几百毫秒,因为需要配置camera deviceinternal pipelines,还要分配内存缓冲区以便发送images到指定的目标。所以这个创建的完成是异步的,createCaptureSessioncreateReprocessableCaptureSession会发送一个ready-to-use CaptureSessionde回调给它的监听者,这个调用是在CameraCaptureSession.StateCallbackonConfigured回调中处理的,它的监听者就是CaptureReadyCallback,如果配置失败,就会回调CameraCaptureSession.StateCallback#onConfigureFailed。这个过程的实例:CaptureModule中,通过mCamera(OneCameraImpl)调用startview,同时设置了CaptureReadyCallback回调,并重写了其onReadyForCapture方法,在startview的过程中会通过调用CameraDevicecreateCaptureSession创建一个capturesession,同时设置了CameraCaptureSession.StateCallback的回调,并重写其onConfigured,这样在session配置成功后,就会回调onConfigured,进而在onConfigured中回调CaptureReadyCallbackonReadyForCapture方法。

任何在session ready之前提交的capture requests都会入队,一旦session变为ready就开始capture,万一session没有配置成功,onConfigureFailed会被调用,同时所有入队的capture requests会被丢弃。

如果camera device创建了一个新的session,那么前一个session会关闭,相关的回调onClosed被调用,如果session被关闭了,再去调用它的方法就会抛出IllegalStateException

 

StateCallback 接收cameracapture session的状态更新。

public static abstract class StateCallback{

//camera device完成了自身的配置,session可以开始处理capturerequests时,这个方法会被调用。

如果已经有capture requests已经在这个session上排队,一旦这个回调被调用就开始处理,在这个调用callback后,会去调用onActive

如果还没有capture requests提交,在这个调用后,这个session会去调用onReady

         publicabstract void onConfigured(@NonNull CameraCaptureSession session);

//如果session不能做为requested被配置,回调这个方法,可能的情况有:一组请求的outputs包含了不支持的大小,或者一次请求有太多的outputs

         publicabstract void onConfigureFailed(@NonNull CameraCaptureSession session);

}

 

CaptureCallback 跟踪CaptureRequest提交到到cameraDevice的进度。

public static abstract classCaptureCallback {

//cameradevice已经开始为请求捕获输出图像,在图像曝光的起点,或者当camerdevice已经开始为请求处理输入图像时,这个方法被调用。

对于一个正常的拍照请求,这个方法恰好是在开始捕获第一帧时被调用,所以最接近的时间是播放快门音,或者触发拍照UI的标识。

         publicvoid onCaptureStarted(@NonNull CameraCaptureSession session,

                   @NonNullCaptureRequest request, long timestamp, long frameNumber)

//当图像拍摄执行了部分进度,来自图像拍摄的一些结果数据(不是全部)是可用的,这时调用onCaptureProgressed

其中的参数partialResult包含了完整结果字段的一些子集,在每次拍摄时,这个方法可能调用多次,给出的结果字段最多只会出现在一次的部分捕获中。最后,onCaptureCompleted调用时,result会包含所有字段(特别指出的是,所有字段的联合体是由所有的部分结果组合成的总的结果)

         publicvoid onCaptureProgressed(@NonNull CameraCaptureSession session,

                   @NonNullCaptureRequest request, @NonNull CaptureResult partialResult)

//当图片capture全部完成,并且所有的结果metadata数据可用时,调用这个方法

         publicvoid onCaptureCompleted(@NonNull CameraCaptureSession session,

                   @NonNullCaptureRequest request, @NonNull TotalCaptureResult result)

}

 

下面进入到Camera Framework层,CameraManager.java

通常情况下,如果一个前端的Activity运行在你的应用进程,你的进程机会得到一个较高的优先级,当调用openCamera方法访问camera时是会成功的,即使这个camera设备正被另外的一个camera Client使用。任何低优先级的应用是可能失去对camera的控制的,然后收到回调:android.hardware.camera2.CameraDevice.StateCallback#onDisconnected

一旦camera成功打开,CameraDevice.StateCallback#onOpened这个回调随着新打开的设备会被调用,camera设备通过调用CameraDevice#createCaptureSessionCameraDevice#createCaptureRequest准备操作。

因为Camera设备的打开是异步的,任何异步的操作完成返回后,Camera实例会对他们排队,直到camera启动完成,启动完成会有回调:CameraDevice.StateCallback#onOpened onOpened,然后,那些pending的操作就会被顺序的执行。

如果camera在初始化时断开了,CameraDevice.StateCallback#onDisconnected会被调用,CameraDevice.StateCallback#onOpened会被跳过。

如果打开camera失败,会有CameraDevice.StateCallback#onError这个回调,后面再对这个camera设备的调用都会抛出异常:CameraAccessException

 

Framework/base/core/java/android/hardware/camera2/CameraManager.java

   public void openCamera(@NonNull String cameraId,

           @NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler)

           throws CameraAccessException@ CameraManager.java {

         openCameraForUid(cameraId,callback, handler, USE_CALLING_UID);

}

public void openCameraForUid(@NonNullString cameraId,

           @NonNull final CameraDevice.StateCallback callback, @Nullable Handlerhandler,

           int clientUid)

           throws CameraAccessException@ CameraManager.java {

         openCameraDeviceUserAsync(cameraId,callback, handler, clientUid);

}

下面的代码进入到CameraService中,所以我们先看CameraService的启动:

CameraServer有自己的.rc文件:framework/av/camera/cameraserver/cameraserver.rc

service cameraserver/system/bin/cameraserver

   class main

   user cameraserver

   group audio camera input drmrpc

   ioprio rt 4

writepid/dev/cpuset/camera-daemon/tasks /dev/stune/top-app/tasks

所以CameraService是通过cameraserver.rc启动的,它自己是一个单独的进程,这是android7.0的版本,在之前的版本可能是在mediaServer中启动的。

main_cameraserver.cpp{

   sp<ProcessState> proc(ProcessState::self());

   sp<IServiceManager> sm = defaultServiceManager();

ALOGI("ServiceManager:%p", sm.get());

//这句调用会启动cameraService

CameraService::instantiate();

//2句调用,使进程进入到类似Binder_loop的循环。

   ProcessState::self()->startThreadPool();

   IPCThreadState::self()->joinThreadPool();

}

instantiate()调用是CameraService的父类BinderService中的方法。从CameraService.h可以看到这个继承关系。

CameraService.h{

         classCameraService :

                   publicBinderService<CameraService>,

}

BinderService是一个模板类,这里的SERVICE就是CameraService,接下来完成CameraService的注册,具体是在publish方法中,调用了sm->addService(),其中的参数SERVICE::getServiceName()调用的CameraService.h中的:

// Implementation of BinderService<T>

static char const* getServiceName() {return "media.camera"; }

CameraService对应的服务名是media.camera

 

template<typename SERVICE>

BinderService.h{

         staticvoid instantiate() { publish(); }

static status_tpublish(bool allowIsolated = false) {

       sp<IServiceManager> sm(defaultServiceManager());

       return sm->addService(

               String16(SERVICE::getServiceName()),

                new SERVICE(), allowIsolated);

    }       

}

下面就开始获取CameraService的句柄,调用CameraService中的connectDevice函数。

private CameraDeviceopenCameraDeviceUserAsync(String cameraId,

           CameraDevice.StateCallback callback, Handler handler, final int uid)

           throws CameraAccessException@ CameraManager.java {

 

}

0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

使用Camera2 替代过时的Camera API

转自: http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0428/2811.html 概要   从5.0开始(API Le...
  • lyglostangel
  • lyglostangel
  • 2016-06-06 14:44
  • 2989

超实用!Android Camera2.0新API与Camera旧API使用对比总结

Android Camera2.0新API与旧Camera使用对比总结 前言: Camera2.0新API是Android5.0(L)API Level 21 推出来并用以取代之前的CameraAPI...
  • qq_21898059
  • qq_21898059
  • 2016-07-27 17:29
  • 3428

Android Camera2教程之打开相机、开启预览、实现PreviewCallback、拍照

Android API21新增了camera2,这与之前的camera架构完全不同,使用起来也比较复杂,但是功能变得很强大。
  • lb377463323
  • lb377463323
  • 2016-10-05 20:32
  • 11366

camera2 (api2)打开预览过程(二)

下面就开始获取CameraService的句柄,调用CameraService中的connectDevice函数。 private CameraDeviceopenCameraDeviceUserAs...
  • lin20044140410
  • lin20044140410
  • 2017-08-21 09:03
  • 598

Android camera api2 demo

  • 2016-12-22 14:17
  • 18.97MB
  • 下载

PhoneGap,API帮助文档翻译整理2-Camera(相机)

  • 2012-04-28 11:04
  • 92KB
  • 下载

Camera API2录像Demo

  • 2016-09-30 16:34
  • 10.58MB
  • 下载

Camera API2拍照Demo

  • 2016-09-30 16:29
  • 10.96MB
  • 下载

Android Camera2 API

  • 2016-12-11 16:26
  • 44.72MB
  • 下载

android camera2 api点击图片实现聚焦

public class FirstICActivity extends AppCompatActivity { private static final String TAG = "...
  • csharp25
  • csharp25
  • 2018-01-06 21:44
  • 38
    个人资料
    • 访问:35407次
    • 积分:1672
    • 等级:
    • 排名:千里之外
    • 原创:129篇
    • 转载:38篇
    • 译文:0篇
    • 评论:9条
    最新评论