<var id="fnfpo"><source id="fnfpo"></source></var>
<rp id="fnfpo"></rp>

<em id="fnfpo"><object id="fnfpo"><input id="fnfpo"></input></object></em>
<em id="fnfpo"><acronym id="fnfpo"></acronym></em>
  • <th id="fnfpo"><track id="fnfpo"></track></th>
  • <progress id="fnfpo"><track id="fnfpo"></track></progress>
  • <tbody id="fnfpo"><pre id="fnfpo"></pre></tbody>

  • x
    x

    Android Camera 系統框架分析

    發布時間:2013-9-16 16:28    發布者:reggae
    關鍵詞: android
    一、在android中開發人員可以做那些工作?
    應用程序開發:利用android提供的強大的sdk,開發出各種各樣新穎的應用。
    系統開發:在android中Google實現了與硬件無關的所有代碼,但是與硬件密切相關的硬件抽象層卻沒有也無法提供,對于移動設備不同的設備提供商 底層硬件是千變萬化的,不可能提供統一的硬件驅動以及接口實現,只能提供標準的接口,因此硬件提供商需要自個兒開發設備驅動,并去實現android框架提供的接口。
    二、android框架中Camera系統源碼分析
    在每個android手機中都有一個Camera應用程序用來實現拍照功能,不同硬件提供商可能會對這個應用程序進行改變來適合自己的UI風格,
    這里僅僅分析android原生Camera應用以及框架(Android 4.0)
    原生Camera應用代碼在Camera.java(android4.0\packages\apps\camera\src\com\android\camera),這個應該算是Camera系統最上層,應用層的實現。
    (PS:^_^不錯的Android學習交流群314230976,驗證:eec,有興趣的話可以加入進來一起討論)
    下面是Camera類部分代碼
    1. public class Camera extends ActivityBase implements FocusManager.Listener,
    2. View.OnTouchListener, ShutterButton.OnShutterButtonListener,
    3. SurfaceHolder.Callback, ModePicker.OnModeChangeListener,
    4. FaceDetectionListener, CameraPreference.OnPreferenceChangedListener,
    5. LocationManager.Listener, ShutterButton.OnShutterButtonLongPressListener
    復制代碼
    從上面可以看出,Camera在繼承了很多監聽接口,用來監聽各種事件(對焦事件、用戶觸摸事件等)。這個應用時繼承ActivityBase,
    可以重載OnCreate、OnResume等接口,在這些接口中完成相關初始化的工作,基本就是初始化各種監聽對象,以及獲取相機參數等相關。
    比較關鍵的在 doOnResume這個函數中:

    1. @Override
    2. protected void doOnResume() {
    3. if (mOpenCameraFail || mCameraDisabled) return;

    4. mPausing = false;

    5. mJpegPictureCallbackTime = 0;
    6. mZoomValue = 0;

    7. // Start the preview if it is not started.
    8. if (mCameraState == PREVIEW_STOPPED) {
    9. try {
    10. mCameraDevice = Util.openCamera(this, mCameraId);
    11. initializeCapabilities();
    12. resetExposureCompensation();
    13. startPreview();
    14. if (mFirstTimeInitialized) startFaceDetection();
    15. } catch (CameraHardwareException e) {
    16. Util.showErrorAndFinish(this, R.string.cannot_connect_camera);
    17. return;
    18. } catch (CameraDisabledException e) {
    19. Util.showErrorAndFinish(this, R.string.camera_disabled);
    20. return;
    21. }
    22. }

    23. if (mSurfaceHolder != null) {
    24. // If first time initialization is not finished, put it in the
    25. // message queue.
    26. if (!mFirstTimeInitialized) {
    27. mHandler.sendEmptyMessage(FIRST_TIME_INIT);
    28. } else {
    29. initializeSecondTime();
    30. }
    31. }
    32. keepScreenOnAwhile();

    33. if (mCameraState == IDLE) {
    34. mOnResumeTime = SystemClock.uptimeMillis();
    35. mHandler.sendEmptyMessageDelayed(CHECK_DISPLAY_ROTATION, 100);
    36. }
    37. }
    復制代碼
    在這個函數中看到通過這個函數獲得Camera底層對象
    mCameraDevice = Util.openCamera(this, mCameraId),這里使用Util這個類,這個類的實現在
    Util.java (android4.0\packages\apps\camera\src\com\android\camera)中,找到OpenCamera這個函數實現:

    1. public static android.hardware.Camera openCamera(Activity activity, int cameraId)
    2. throws CameraHardwareException, CameraDisabledException {
    3. // Check if device policy has disabled the camera.
    4. DevicePolicyManager dpm = (DevicePolicyManager) activity.getSystemService(
    5. Context.DEVICE_POLICY_SERVICE);
    6. if (dpm.getCameraDisabled(null)) {
    7. throw new CameraDisabledException();
    8. }

    9. try {
    10. return CameraHolder.instance().open(cameraId);
    11. } catch (CameraHardwareException e) {
    12. // In eng build, we throw the exception so that test tool
    13. // can detect it and report it
    14. if ("eng".equals(Build.TYPE)) {
    15. throw new RuntimeException("openCamera failed", e);
    16. } else {
    17. throw e;
    18. }
    19. }
    20. }
    復制代碼
    從這個函數可以看出,android系統中對下層Camera管理,是通過一個單例模式CameraHolder來管理的,
    定位到這個類的實現CameraHolder.java (android4.0\packages\apps\camera\src\com\android\camera)通過調用open函數獲取一個Camera硬件設備對象,
    因為Camera設備是獨享設備,不能同時被兩個進程占用,而整個android系統是一個多進程環境,因此需要加入一些進程間互斥同步的方法。
    定位到這個類的open函數:

    1. public synchronized android.hardware.Camera open(int cameraId)
    2. throws CameraHardwareException {
    3. Assert(mUsers == 0);
    4. if (mCameraDevice != null && mCameraId != cameraId) {
    5. mCameraDevice.release();
    6. mCameraDevice = null;
    7. mCameraId = -1;
    8. }
    9. if (mCameraDevice == null) {
    10. try {
    11. Log.v(TAG, "open camera " + cameraId);
    12. mCameraDevice = android.hardware.Camera.open(cameraId);
    13. mCameraId = cameraId;
    14. } catch (RuntimeException e) {
    15. Log.e(TAG, "fail to connect Camera", e);
    16. throw new CameraHardwareException(e);
    17. }
    18. mParameters = mCameraDevice.getParameters();
    19. } else {
    20. try {
    21. mCameraDevice.reconnect();
    22. } catch (IOException e) {
    23. Log.e(TAG, "reconnect failed.");
    24. throw new CameraHardwareException(e);
    25. }
    26. mCameraDevice.setParameters(mParameters);
    27. }
    28. ++mUsers;
    29. mHandler.removeMessages(RELEASE_CAMERA);
    30. mKeepBeforeTime = 0;
    31. return mCameraDevice;
    32. }
    復制代碼
    通 過android.hardware.Camera.open(cameraId)調用進入下一層封裝,JNI層,這一層是java代碼的最下層,對下層 CameraC++代碼進行JNI封裝,封裝實現類在Camera.java (android4.0\frameworks\base\core\java\android\hardware) 下面是這個類的部分實現,里面定義了不少回調函數:

    1. public class Camera {
    2. private static final String TAG = "Camera";

    3. // These match the enums in frameworks/base/include/camera/Camera.h
    4. private static final int CAMERA_MSG_ERROR            = 0x001;
    5. private static final int CAMERA_MSG_SHUTTER          = 0x002;
    6. private static final int CAMERA_MSG_FOCUS            = 0x004;
    7. private static final int CAMERA_MSG_ZOOM             = 0x008;
    8. private static final int CAMERA_MSG_PREVIEW_FRAME    = 0x010;
    9. private static final int CAMERA_MSG_VIDEO_FRAME      = 0x020;
    10. private static final int CAMERA_MSG_POSTVIEW_FRAME   = 0x040;
    11. private static final int CAMERA_MSG_RAW_IMAGE        = 0x080;
    12. private static final int CAMERA_MSG_COMPRESSED_IMAGE = 0x100;
    13. private static final int CAMERA_MSG_RAW_IMAGE_NOTIFY = 0x200;
    14. private static final int CAMERA_MSG_PREVIEW_METADATA = 0x400;
    15. private static final int CAMERA_MSG_ALL_MSGS         = 0x4FF;

    16. private int mNativeContext; // accessed by native methods
    17. private EventHandler mEventHandler;
    18. private ShutterCallback mShutterCallback;
    19. private PictureCallback mRawImageCallback;
    20. private PictureCallback mJpegCallback;
    21. private PreviewCallback mPreviewCallback;
    22. private PictureCallback mPostviewCallback;
    23. private AutoFocusCallback mAutoFocusCallback;
    24. private OnZoomChangeListener mZoomListener;
    25. private FaceDetectionListener mFaceListener;
    26. private ErrorCallback mErrorCallback;
    復制代碼
    定位到Open函數:

    1. public static Camera open(int cameraId) {
    2. return new Camera(cameraId);
    3. }
    復制代碼


    Open函數是一個靜態方法,構造一個Camera對象:

    1. Camera(int cameraId) {
    2. mShutterCallback = null;
    3. mRawImageCallback = null;
    4. mJpegCallback = null;
    5. mPreviewCallback = null;
    6. mPostviewCallback = null;
    7. mZoomListener = null;

    8. Looper looper;
    9. if ((looper = Looper.myLooper()) != null) {
    10. mEventHandler = new EventHandler(this, looper);
    11. } else if ((looper = Looper.getMainLooper()) != null) {
    12. mEventHandler = new EventHandler(this, looper);
    13. } else {
    14. mEventHandler = null;
    15. }

    16. native_setup(new WeakReference(this), cameraId);
    17. }
    復制代碼
    在構造函數中調用native_setup方法,此方法對應于C++代碼的android_hardware_Camera_native_setup方法,
    實現在android_hardware_Camera.cpp (android4.0\frameworks\base\core\jni),具體代碼如下:

    1. static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
    2. jobject weak_this, jint cameraId)
    3. {
    4. sp camera = Camera::connect(cameraId);

    5. if (camera == NULL) {
    6. jniThrowRuntimeException(env, "Fail to connect to camera service");
    7. return;
    8. }

    9. // make sure camera hardware is alive
    10. if (camera->getStatus() != NO_ERROR) {
    11. jniThrowRuntimeException(env, "Camera initialization failed");
    12. return;
    13. }

    14. jclass clazz = env->GetObjectClass(thiz);
    15. if (clazz == NULL) {
    16. jniThrowRuntimeException(env, "Can't find android/hardware/Camera");
    17. return;
    18. }

    19. // We use a weak reference so the Camera object can be garbage collected.
    20. // The reference is only used as a proxy for callbacks.
    21. sp context = new JNICameraContext(env, weak_this, clazz, camera);
    22. context->incStrong(thiz);
    23. camera->setListener(context);

    24. // save context in opaque field
    25. env->SetIntField(thiz, fields.context, (int)context.get());
    26. }
    復制代碼

    在android_hardware_Camera_native_setup方法中調用了Camera對象的connect方法,這個Camera類的 聲明在Camera.h (android4.0\frameworks\base\include\camera)
    定位到connect方法:

    1. sp Camera::connect(int cameraId)
    2. {
    3. LOGV("connect");
    4. sp c = new Camera();
    5. const sp& cs = getCameraService();
    6. if (cs != 0) {
    7. c->mCamera = cs->connect(c, cameraId);
    8. }
    9. if (c->mCamera != 0) {
    10. c->mCamera->asBinder()->linkToDeath(c);
    11. c->mStatus = NO_ERROR;
    12. } else {
    13. c.clear();
    14. }
    15. return c;
    16. }
    復制代碼

    這里以下的代碼就比較關鍵了,涉及到Camera框架的實現機制,Camera系統使用的是Server-Client機制,Service和Client位于不同的進程中,進程間使用Binder機制進行通信,
    Service端實際實現相機相關的操作,Client端通過Binder接口調用Service對應的操作。
    繼續分析代碼,上面函數調用getCameraService方法,獲得CameraService的引用,ICameraService有兩個子類,BnCameraService和BpCameraService,這兩個子類同時也
    繼承了IBinder接口,這兩個子類分別實現了Binder通信的兩端,Bnxxx實現ICameraService的具體功能,Bpxxx利用Binder的通信功能封裝ICameraService方法,具體如下:

    1. class ICameraService : public IInterface
    2. {
    3. public:
    4. enum {
    5. GET_NUMBER_OF_CAMERAS = IBinder::FIRST_CALL_TRANSACTION,
    6. GET_CAMERA_INFO,
    7. CONNECT
    8. };
    復制代碼

    1. public:
    2. DECLARE_META_INTERFACE(CameraService);

    3. virtual int32_t         getNumberOfCameras() = 0;
    4. virtual status_t        getCameraInfo(int cameraId,
    5. struct CameraInfo* cameraInfo) = 0;
    6. virtual sp     connect(const sp& cameraClient,
    7. int cameraId) = 0;
    8. };

    9. // ----------------------------------------------------------------------------

    10. class BnCameraService: public BnInterface
    11. {
    12. public:
    13. virtual status_t    onTransact( uint32_t code,
    14. const Parcel& data,
    15. Parcel* reply,
    16. uint32_t flags = 0);
    17. };

    18. }; // na
    19. class BpCameraService: public BpInterface
    20. {
    21. public:
    22. BpCameraService(const sp& impl)
    23. : BpInterface(impl)
    24. {
    25. }

    26. // get number of cameras available
    27. virtual int32_t getNumberOfCameras()
    28. {
    29. Parcel data, reply;
    30. data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
    31. remote()->transact(BnCameraService::GET_NUMBER_OF_CAMERAS, data, &reply);
    32. return reply.readInt32();
    33. }

    34. // get information about a camera
    35. virtual status_t getCameraInfo(int cameraId,
    36. struct CameraInfo* cameraInfo) {
    37. Parcel data, reply;
    38. data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
    39. data.writeInt32(cameraId);
    40. remote()->transact(BnCameraService::GET_CAMERA_INFO, data, &reply);
    41. cameraInfo->facing = reply.readInt32();
    42. cameraInfo->orientation = reply.readInt32();
    43. return reply.readInt32();
    44. }

    45. // connect to camera service
    46. virtual sp connect(const sp& cameraClient, int cameraId)
    47. {
    48. Parcel data, reply;
    49. data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
    50. data.writeStrongBinder(cameraClient->asBinder());
    51. data.writeInt32(cameraId);
    52. remote()->transact(BnCameraService::CONNECT, data, &reply);
    53. return interface_cast(reply.readStrongBinder());
    54. }
    55. };

    56. IMPLEMENT_META_INTERFACE(CameraService, "android.hardware.ICameraService");

    57. // ----------------------------------------------------------------------

    58. status_t BnCameraService::onTransact(
    59. uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    60. {
    61. switch(code) {
    62. case GET_NUMBER_OF_CAMERAS: {
    63. CHECK_INTERFACE(ICameraService, data, reply);
    64. reply->writeInt32(getNumberOfCameras());
    65. return NO_ERROR;
    66. } break;
    67. case GET_CAMERA_INFO: {
    68. CHECK_INTERFACE(ICameraService, data, reply);
    69. CameraInfo cameraInfo;
    70. memset(&cameraInfo, 0, sizeof(cameraInfo));
    71. status_t result = getCameraInfo(data.readInt32(), &cameraInfo);
    72. reply->writeInt32(cameraInfo.facing);
    73. reply->writeInt32(cameraInfo.orientation);
    74. reply->writeInt32(result);
    75. return NO_ERROR;
    76. } break;
    77. case CONNECT: {
    78. CHECK_INTERFACE(ICameraService, data, reply);
    79. sp cameraClient = interface_cast(data.readStrongBinder());
    80. sp camera = connect(cameraClient, data.readInt32());
    81. reply->writeStrongBinder(camera->asBinder());
    82. return NO_ERROR;
    83. } break;
    84. default:
    85. return BBinder::onTransact(code, data, reply, flags);
    86. }
    87. }

    88. // ----------------------------------------------------------------------------

    89. }; // namespace android
    復制代碼
    下面繼續分析sp Camera::connect(int cameraId)這個方法,,定位到getCameraService這個方法

    1. const sp& Camera::getCameraService()
    2. {
    3. Mutex::Autolock _l(mLock);
    4. if (mCameraService.get() == 0) {
    5. sp sm = defaultServiceManager();
    6. sp binder;
    7. do {
    8. binder = sm->getService(String16("media.camera"));
    9. if (binder != 0)
    10. break;
    11. LOGW("CameraService not published, waiting...");
    12. usleep(500000); // 0.5 s
    13. } while(true);
    14. if (mDeathNotifier == NULL) {
    15. mDeathNotifier = new DeathNotifier();
    16. }
    17. binder->linkToDeath(mDeathNotifier);
    18. mCameraService = interface_cast(binder);
    19. }
    20. LOGE_IF(mCameraService==0, "no CameraService!?");
    21. return mCameraService;
    22. }
    復制代碼

    定位到mCameraService = interface_cast(binder); mCameraService是一個ICamerService類型,更加具體具體一點來講應該是BpCameraService,
    因為在這個類中實現了ICameraService的方法。
    總結上面Binder機制,僅僅考慮分析Binder用法,對底層實現不進行深究,基本步驟如下:
    1.定義進程間通信的接口比如這里的ICameraService;
    2.在BnCameraService和BpCamaraService實現這個接口,這兩個接口也分別繼承于BnInterface和BpInterface;
    3.服務端向ServiceManager注冊Binder,客戶端向ServiceManager獲得Binder;
    4.然后就可以實現雙向進程間通信了;




    通過getCameraService得到ICameraService引用后,調用ICameraService的connect方法獲得ICamera引用,


    c->mCamera = cs->connect(c, cameraId);


    進一步跟進connect方法,這里就是BpCameraService類中connect方法的具體實現。

    1. virtual sp connect(const sp& cameraClient, int cameraId)
    2. {
    3. Parcel data, reply;
    4. data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
    5. data.writeStrongBinder(cameraClient->asBinder());
    6. data.writeInt32(cameraId);
    7. remote()->transact(BnCameraService::CONNECT, data, &reply);
    8. return interface_cast(reply.readStrongBinder());
    9. }
    復制代碼
    在這里返回的ICamera對象,實際上應該是BpCamera對象,這里使用的是匿名Binder,前面獲取CameraService的 使用的有名Binder,有名Binder需要借助于ServiceManager獲取Binder,而匿名Binder可以通過已經建立后的通信通道 (有名Binder)獲得。以上是實現Camera框架部分,具體的實現Camera相關的方法是在ICamera相關的接口,下面是給接口的定義:

    1. class ICamera: public IInterface
    2. {
    3. public:
    4. DECLARE_META_INTERFACE(Camera);
    5. virtual void            disconnect() = 0;
    6. // connect new client with existing camera remote
    7. virtual status_t        connect(const sp& client) = 0;
    8. // prevent other processes from using this ICamera interface
    9. virtual status_t        lock() = 0;
    10. // allow other processes to use this ICamera interface
    11. virtual status_t        unlock() = 0;
    12. // pass the buffered Surface to the camera service
    13. virtual status_t        setPreviewDisplay(const sp& surface) = 0;
    14. // pass the buffered ISurfaceTexture to the camera service
    15. virtual status_t        setPreviewTexture(
    16. const sp& surfaceTexture) = 0;
    17. // set the preview callback flag to affect how the received frames from
    18. // preview are handled.
    19. virtual void            setPreviewCallbackFlag(int flag) = 0;
    20. // start preview mode, must call setPreviewDisplay first
    21. virtual status_t        startPreview() = 0;
    22. // stop preview mode
    23. virtual void            stopPreview() = 0;
    24. // get preview state
    25. virtual bool            previewEnabled() = 0;
    26. // start recording mode
    27. virtual status_t        startRecording() = 0;
    28. // stop recording mode
    29. virtual void            stopRecording() = 0;
    30. // get recording state
    31. virtual bool            recordingEnabled() = 0;
    32. // release a recording frame
    33. virtual void            releaseRecordingFrame(const sp& mem) = 0;
    34. // auto focus
    35. virtual status_t        autoFocus() = 0;
    36. // cancel auto focus
    37. virtual status_t        cancelAutoFocus() = 0;
    38. virtual status_t        takePicture(int msgType) = 0;
    39. // set preview/capture parameters - key/value pairs
    40. virtual status_t        setParameters(const String8& params) = 0;
    41. // get preview/capture parameters - key/value pairs
    42. virtual String8         getParameters() const = 0;
    43. // send command to camera driver
    44. virtual status_t        sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) = 0;
    45. // tell the camera hal to store meta data or real YUV data in video buffers.
    46. virtual status_t        storeMetaDataInBuffers(bool enabled) = 0;
    47. };
    復制代碼
    ICamera接口有兩個子類BnCamera和BpCamera,是Binder通信的兩端,BpCamera提供客戶端調用 接口,BnCamera封裝具體的實現,BnCamera也并沒有真正實現ICamera相關接口而是在BnCamera子類 CameraService::Client中進行實現。而在CameraService::Client類中會繼續調用硬件抽象層中相關方法來具體實現Camera功能。


    本文地址:http://www.portaltwn.com/thread-121041-1-1.html     【打印本頁】

    本站部分文章為轉載或網友發布,目的在于傳遞和分享信息,并不代表本網贊同其觀點和對其真實性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問題,我們將根據著作權人的要求,第一時間更正或刪除。
    您需要登錄后才可以發表評論 登錄 | 立即注冊

    廠商推薦

    • Microchip視頻專區
    • EtherCAT®和Microchip LAN925x從站控制器介紹培訓教程
    • MPLAB®模擬設計器——在線電源解決方案,加速設計
    • 讓您的模擬設計靈感,化為觸手可及的現實
    • 深度體驗Microchip自動輔助駕駛應用方案——2025巡展開啟報名!
    • 貿澤電子(Mouser)專區

    相關視頻

    關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯系我們
    電子工程網 © 版權所有   京ICP備16069177號 | 京公網安備11010502021702
    快速回復 返回頂部 返回列表
    精品一区二区三区自拍图片区_国产成人亚洲精品_亚洲Va欧美va国产综合888_久久亚洲国产精品五月天婷