1. 程式人生 > >android下camera資料流的分析

android下camera資料流的分析

  1. 首先從上層講解下來
  2. Packages/apps/camera/src/com/android/camera/camera.java
  3. private void capture() {
  4.             mCaptureOnlyData = null;
  5.             // See android.hardware.Camera.Parameters.setRotation for
  6.             mParameters.setRotation(rotation);
  7.           …….
  8.            mCameraDevice.setParameters(mParameters);
  9.                 //app 應用註冊takepicture回撥函式
  10.             mCameraDevice.takePicture(mShutterCallback, mRawPictureCallback,
  11.                     mPostViewPictureCallback, new JpegPictureCallback(loc));
  12.             mPreviewing = false;
  13.         }
  14. 下面是關於四個回撥函式的實現
  15. private final class ShutterCallback
  16.             implements android.hardware.Camera.ShutterCallback {
  17.         public void onShutter() {
  18.             mShutterCallbackTime = System.currentTimeMillis();
  19.             mShutterLag = mShutterCallbackTime - mCaptureStartTime;
  20.             Log.v(TAG, "mShutterLag = " + mShutterLag + "ms");
  21.             clearFocusState();
  22.         }
  23. }
  24.   private final class RawPictureCallback implements PictureCallback {
  25.         public void onPictureTaken(
  26.                 byte [] rawData, android.hardware.Camera camera) {
  27.             mRawPictureCallbackTime = System.currentTimeMillis();
  28.             Log.v(TAG, "mShutterToRawCallbackTime = "
  29.                     + (mRawPictureCallbackTime - mShutterCallbackTime) + "ms");
  30.         }
  31.     }
  32.     private final class PostViewPictureCallback implements PictureCallback {
  33.         public void onPictureTaken(
  34.                 byte [] data, android.hardware.Camera camera) {
  35.             mPostViewPictureCallbackTime = System.currentTimeMillis();
  36.             Log.v(TAG, "mShutterToPostViewCallbackTime = "
  37.                     + (mPostViewPictureCallbackTime - mShutterCallbackTime)
  38.                     + "ms");
  39.         }
  40.     }
  41.     private final class JpegPictureCallback implements PictureCallback {
  42.         Location mLocation;
  43.         public void onPictureTaken(
  44.                 final byte [] jpegData, final android.hardware.Camera camera) {
  45.             if (mPausing) {
  46.                 return;
  47.             }
  48.             mJpegPictureCallbackTime = System.currentTimeMillis();
  49.            …………………..
  50.                 //這個函式等下做詳解
  51.             mImageCapture.storeImage(jpegData, camera, mLocation);
  52.         }
  53.     }
  54. 2、上層註冊好回撥函式之後frameworks/base/core/java/android/hardware/camera.java註冊回撥函式
  55.   public final void takePicture(ShutterCallback shutter, PictureCallback raw,
  56.             PictureCallback postview, PictureCallback jpeg) {
  57.         mShutterCallback = shutter;
  58.         mRawImageCallback = raw;
  59.         mPostviewCallback = postview;
  60.         mJpegCallback = jpeg;
  61.      native_takePicture();
  62.     }
  63. frameworks/base/services/camera/libcameraservice
  64. // take a picture - image is returned in callback
  65. status_t CameraService::Client::takePicture() {
  66.     LOG1("takePicture (pid %d)", getCallingPid());
  67.     Mutex::Autolock lock(mLock);
  68.     status_t result = checkPidAndHardware();
  69.     if (result != NO_ERROR) return result;
  70.         //用於判斷指定的msg所對應的callback是否可以回撥
  71.     enableMsgType(CAMERA_MSG_SHUTTER |
  72.                   CAMERA_MSG_POSTVIEW_FRAME |
  73.                   CAMERA_MSG_RAW_IMAGE |
  74.                   CAMERA_MSG_COMPRESSED_IMAGE);
  75.     return mHardware->takePicture();//從這裡就進入hal實現了,即上層提供操作裝置驅動的介面
  76. }
  77. 3、HAL層的實現,介面被定義在cameraHardwareInterface.h檔案中,所以hal層要做的就是實現其介面
  78. 其實寫到這裡,還是有很多不瞭解,如service中stub的概念,IPC的機制如何實現,功底還是太淺了,有空專門研究下這塊
  79. 下面就仔細看下hal如何實現takepicture操作,同時向上層傳遞data
  80. status_t CameraHardwareSec::takePicture()
  81. {
  82.       stopPreview();
  83.     Mutex::Autolock lock(mStateLock);
  84.     if (mCaptureInProgress) {
  85.         LOGE("%s : capture already in progress", __func__);
  86.         return INVALID_OPERATION;
  87.     }
  88.     //啟動PictureThread執行緒
  89.     if (mPictureThread->run("CameraPictureThread", PRIORITY_DEFAULT) != NO_ERROR) {
  90.         LOGE("%s : couldn't run picture thread", __func__);
  91.         return INVALID_OPERATION;
  92.     }
  93.     mCaptureInProgress = true;
  94.     return NO_ERROR;
  95. }
  96. int CameraHardwareSec::pictureThread()
  97. {
  98.     mRawHeap = new MemoryHeapBase(picture_size);
  99.     if (mRawHeap->getHeapID() < 0) {
  100.         LOGE("ERR(%s): Raw heap creation fail", __func__);
  101.         mRawHeap.clear();
  102.         return UNKNOWN_ERROR;
  103.     }
  104.     sp<MemoryHeapBase> JpegHeap;
  105.     sp<MemoryHeapBase> PostviewHeap;
  106.     sp<MemoryHeapBase> ThumbnailHeap;
  107.     sp<MemoryBase> buffer = new MemoryBase(mRawHeap, 0, picture_size + 8);
  108. //主要是將raw data照片原始資料通過encode成jpeg的格式
  109.     if ((mMsgEnabled & CAMERA_MSG_RAW_IMAGE)&&(mSecCamera->getJpegStreamPossible() != true)) {
  110.         LOG_TIME_DEFINE(1)
  111.         LOG_TIME_START(1)
  112.      JpegHeap = new MemoryHeapBase(jpeg_heap_size);
  113.          PostviewHeap = new MemoryHeapBase(picture_size);
  114.         ThumbnailHeap = new MemoryHeapBase(thumb_size);    
  115.         // Modified the shutter sound timing for Jpeg capture
  116.         mSecCamera->startSnapshot();
  117.         if (mMsgEnabled & CAMERA_MSG_SHUTTER) {
  118.             //回撥shuttcallback的介面
  119.             mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);
  120.         }
  121.         if(mSecCamera->getJpegStreamPossible() != true){
  122.             if (mSecCamera->getSnapshotAndJpeg((unsigned char*)PostviewHeap->base(),
  123.                     (unsigned char*)JpegHeap->base(), &jpeg_size) < 0) {
  124.                 LOGE("ERR(%s):Fail on SecCamera->getSnapshotAndJpeg()", __func__);
  125.                 mStateLock.lock();
  126.                 mCaptureInProgress = false;
  127.                 mStateLock.unlock();
  128.                 return UNKNOWN_ERROR;
  129.             }
  130.         }
  131.     }
  132.     int JpegImageSize = 10000, JpegExifSize;
  133.     bool isLSISensor = false;
  134.      JpegImageSize = static_cast<int>(jpeg_size);
  135.     CropScaleYUY2((char *)PostviewHeap->base(), picture_width, picture_height, 0, 0,
  136.                   (char *)ThumbnailHeap->base(), thumb_width, thumb_height);
  137.     memcpy(mRawHeap->base(),PostviewHeap->base(), picture_size);
  138. }
  139.     memcpy(static_cast<unsigned char*>(mPreviewHeap->base()) + offset + (previewWidth*previewHeight * 3 / 2),
  140.             overlay_header, mSizeOfADDRS);
  141.     ret = mOverlay->queueBuffer((void*)(static_cast<unsigned char *>(mPreviewHeap->base()) + offset +
  142.                                 (previewWidth * previewHeight * 3 / 2)));
  143.     if ((mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) &&(mSecCamera->getJpegStreamPossible() != true)) {
  144.         sp<MemoryHeapBase> ExifHeap = new MemoryHeapBase(EXIF_FILE_SIZE + picture_size);
  145.      if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE)    
  146.          mDataCb(CAMERA_MSG_RAW_IMAGE, buffer, mCallbackCookie);
  147.             JpegExifSize = mSecCamera->getExif((unsigned char *)ExifHeap->base(),
  148.                     (unsigned char *)ThumbnailHeap->base());
  149.         LOGW("JpegExifSize=%d", JpegExifSize);
  150.             unsigned char *ExifStart = (unsigned char *)JpegHeap->base() + 2;
  151.             unsigned char *ImageStart = ExifStart + JpegExifSize;
  152.             memmove(ImageStart, ExifStart, JpegImageSize - 2);
  153.             memcpy(ExifStart, ExifHeap->base(), JpegExifSize);
  154.         sp<MemoryBase> mem = new MemoryBase(JpegHeap, 0, JpegImageSize + JpegExifSize);
  155.         //壓縮格式照片訊息
  156.         mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mem, mCallbackCookie);
  157.     }
  158. }
  159. 現在我們來看下在hal定義的三個回撥函式
  160. typedef void (*notify_callback)(int32_t msgType, //用於處理一些通知的訊息,如快門
  161.                                 int32_t ext1,
  162.                                 int32_t ext2,
  163.                                 void* user);
  164. typedef void (*data_callback)(int32_t msgType, // 返回通過camera得到的raw data
  165.                               const sp<IMemory>& dataPtr,
  166.                               void* user);
  167. // 返回通過camera得到的raw data並且攜帶時間戳
  168. typedef void (*data_callback_timestamp)(nsecs_t timestamp,
  169.                                         int32_t msgType,
  170.                                         const sp<IMemory>& dataPtr,
  171.                                         void* user);
  172. 介面如下:
  173. /** Set the notification and data callbacks */
  174. virtual void setCallbacks(notify_callback notify_cb,
  175.                           data_callback data_cb,
  176.                           data_callback_timestamp data_cb_timestamp,
  177.                           void* user) = 0;
  178. 現在又返回到cameraService是如何處理hal發過來的訊息
  179. void CameraService::Client::notifyCallback(int32_t msgType, int32_t ext1,
  180.         int32_t ext2, void* user) {
  181.     LOG2("notifyCallback(%d)", msgType);
  182.     sp<Client> client = getClientFromCookie(user);
  183.     if (client == 0) return;
  184.     if (!client->lockIfMessageWanted(msgType)) return;
  185.     switch (msgType) {//接收到的Hal層訊息
  186.         case CAMERA_MSG_SHUTTER:
  187.             // ext1 is the dimension of the yuv picture.
  188.             client->handleShutter((image_rect_type *)ext1);
  189.             break;
  190.         default:
  191.             client->handleGenericNotify(msgType, ext1, ext2);
  192.             break;
  193.     }
  194. }
  195. void CameraService::Client::dataCallback(int32_t msgType,
  196.         const sp<IMemory>& dataPtr, void* user) {
  197.     LOG2("dataCallback(%d)", msgType);
  198.     sp<Client> client = getClientFromCookie(user);
  199.     if (client == 0) return;
  200.     if (!client->lockIfMessageWanted(msgType)) return;
  201.     if (dataPtr == 0) {
  202.         LOGE("Null data returned in data callback");
  203.         client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
  204.         return;
  205.     }
  206.     switch (msgType) {
  207.         case CAMERA_MSG_PREVIEW_FRAME:
  208.             client->handlePreviewData(dataPtr);
  209.             break;
  210.         case CAMERA_MSG_POSTVIEW_FRAME:
  211.             client->handlePostview(dataPtr);
  212.             break;
  213.         case CAMERA_MSG_RAW_IMAGE:
  214.             client->handleRawPicture(dataPtr);
  215.             break;
  216.         case CAMERA_MSG_COMPRESSED_IMAGE:
  217.             client->handleCompressedPicture(dataPtr);
  218.             break;
  219.         default:
  220.             client->handleGenericData(msgType, dataPtr);
  221.             break;
  222.     }
  223. }
  224. // picture callback - compressed picture ready
  225. void CameraService::Client::handleCompressedPicture(const sp<IMemory>& mem) {
  226.     disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
  227.     sp<ICameraClient> c = mCameraClient;
  228.     mLock.unlock();
  229. if (c != 0) {
  230. //回撥函式
  231.         c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem);
  232.     }
  233. }
  234. 回到frameworks/base/core/java/android/hardware/camera.java 處理訊息
  235. @Override
  236.         public void handleMessage(Message msg) {
  237.             switch(msg.what) {
  238.             case CAMERA_MSG_SHUTTER:
  239.                 if (mShutterCallback != null) {
  240.                     mShutterCallback.onShutter();
  241.                 }
  242.                 return;
  243.             ………………
  244.             case CAMERA_MSG_COMPRESSED_IMAGE:
  245.                 if (mJpegCallback != null) {
  246.                     //現在總算回到app時候註冊的幾個回撥函數了
  247.                     mJpegCallback.onPictureTaken((byte[])msg.obj, mCamera);
  248.                 }
  249.                 return;
  250.             default:
  251.                 Log.e(TAG, "Unknown message type " + msg.what);
  252.                 return;
  253.             }
  254.         }
  255. //這裡就是儲存資料的地方了,這裡採用file的形式
  256. private int storeImage(byte[] data, Location loc) {
  257.             try {
  258.                 long dateTaken = System.currentTimeMillis();
  259.                 String title = createName(dateTaken);
  260.                 String filename = title + ".jpg";
  261.                 int[] degree = new int[1];
  262.                 mLastContentUri = ImageManager.addImage(
  263.                         mContentResolver,
  264.                         title,
  265.                         dateTaken,
  266.                         loc, // location from gps/network
  267.                         ImageManager.CAMERA_IMAGE_BUCKET_NAME, filename,
  268.                         null, data,
  269.                         degree);
  270.                 return degree[0];
  271.             } catch (Exception ex) {
  272.                 Log.e(TAG, "Exception while compressing image.", ex);
  273.                 return 0;
  274.             }
  275.         }