Android Camera數據流分析全程記錄(overlay方式一)

這裏爲何要研究overlay方式呢?android camera須要driver和app層須要有大量數據須要傳輸,若是使用非overlay方式進行數據從driver到app層的傳輸,使系統性能受到 很到影響,使系統速度變慢,同時會影響功耗等,而在camera preview module時,一般咱們是沒必要要將採集的數據保存下來的,而不像錄像module下,須要將數據保存下來,因此overlay方式就是不通過數據回傳, 直接顯示從driver的數據方式,採用這種方式app從沒法獲取到數據,因此這種方式應用在preview方式下

這裏我是針對android4.0版本的,相對android2.x版本的overlay已經發生了很大的變化,想要研究這方面的能夠本身去了解一下,這裏再也不多說了

開始部分我就直接在這裏帶過了,系統初始打開camera時,調用到app的onCreate方法,這裏主要作了一下工做:
1.開始一個openCamera線程打開camera
2.實例化不少的對象,用於camera工做使用
3.實例化surfaceview和surfaceholder,而且填充了其中的surfacechanged,surfacedestoryed和surfacecreated這三個方式
4.開始一個preview線程用於preview過程
這其中3.4是咱們這裏要關注的重點,上面實例化了這個surfaceview將決定了咱們究竟是否使用overlay方式
在這裏第三遍完成以後,系統會自動執行surfacechanged這個方式,每次顯示區域發生改變都會自動調用這個方法,剛開始打開camera時,顯示區域從無到有,所以必要這裏會想調用到surfacechanged方法

咱們就仍是看看在這裏都作了些什麼事情 java


public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
         // Make sure we have a surface in the holder before proceeding.
         if (holder.getSurface() == null) {
             Log.d(TAG, "holder.getSurface() == null");
             return;
         }

         Log.v(TAG, "surfaceChanged. w=" + w + ". h=" + h);

         // We need to save the holder for later use, even when the mCameraDevice
         // is null. This could happen if onResume() is invoked after this
         // function.
         mSurfaceHolder = holder;

         // The mCameraDevice will be null if it fails to connect to the camera
         // hardware. In this case we will show a dialog and then finish the
         // activity, so it's OK to ignore it.
         if (mCameraDevice == null) return;

         // Sometimes surfaceChanged is called after onPause or before onResume.
         // Ignore it.
         if (mPausing || isFinishing()) return;

         setSurfaceLayout();

         // Set preview display if the surface is being created. Preview was
         // already started. Also restart the preview if display rotation has
         // changed. Sometimes this happens when the device is held in portrait
         // and camera app is opened. Rotation animation takes some time and
         // display rotation in onCreate may not be what we want.
         if (mCameraState == PREVIEW_STOPPED) {//這裏表示第一次打開camera時,那麼調用startpreview
             startPreview(true);
             startFaceDetection();
         } else {//這裏則表示camera已經打開過程當中發生的顯示變化,好比橫屏豎頻轉換,因此zheli只須要從新設置previewdisplay
             if (Util.getDisplayRotation(this) != mDisplayRotation) {
                 setDisplayOrientation();
             }
             if (holder.isCreating()) {
                 // Set preview display if the surface is being created and preview
                 // was already started. That means preview display was set to null
                 // and we need to set it now.
                 setPreviewDisplay(holder);
             }
         }

         // If first time initialization is not finished, send a message to do
         // it later. We want to finish surfaceChanged as soon as possible to let
         // user see preview first.
         if (!mFirstTimeInitialized) {
             mHandler.sendEmptyMessage(FIRST_TIME_INIT);
         } else {
             initializeSecondTime();
         }

         SurfaceView preview = (SurfaceView) findViewById(R.id.camera_preview);
         CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
         boolean mirror = (info.facing == CameraInfo.CAMERA_FACING_FRONT);
         int displayRotation = Util.getDisplayRotation(this);
         int displayOrientation = Util.getDisplayOrientation(displayRotation, mCameraId);

         mTouchManager.initialize(preview.getHeight() / 3, preview.getHeight() / 3,
                preview, this, mirror, displayOrientation);
}
從上面代碼咱們必須知道,在surface發生變化時必須調用setPreviewDisplay,根據以後的學習,在startpreview方式中真正startpreview以前一樣要調用setPreviewDisplay,在setPreviewDisplay的方法中完成了不少初始化,也是在這裏決定是否使用overlay方式的,咱們就先看看startpreview這個方法吧



private void startPreview(boolean updateAll) {
         if (mPausing || isFinishing()) return;
         mFocusManager.resetTouchFocus();

         mCameraDevice.setErrorCallback(mErrorCallback);

         // If we're previewing already, stop the preview first (this will blank
         // the screen).
         if (mCameraState != PREVIEW_STOPPED) stopPreview();

         setPreviewDisplay(mSurfaceHolder);
         setDisplayOrientation();

         if (!mSnapshotOnIdle) {
             // If the focus mode is continuous autofocus, call cancelAutoFocus to
             // resume it because it may have been paused by autoFocus call.
             if (Parameters.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mFocusManager.getFocusMode())) {
                 mCameraDevice.cancelAutoFocus();
             }
             mFocusManager.setAeAwbLock(false); // Unlock AE and AWB.
         }

         if ( updateAll ) {
             Log.v(TAG, "Updating all parameters!");
             setCameraParameters(UPDATE_PARAM_INITIALIZE | UPDATE_PARAM_ZOOM | UPDATE_PARAM_PREFERENCE);
         } else {
             setCameraParameters(UPDATE_PARAM_MODE);
         }

         //setCameraParameters(UPDATE_PARAM_ALL);

         // Inform the mainthread to go on the UI initialization.
         if (mCameraPreviewThread != null) {
             synchronized (mCameraPreviewThread) {
                 mCameraPreviewThread.notify();
             }
         }

         try {
             Log.v(TAG, "startPreview");
             mCameraDevice.startPreview();
         } catch (Throwable ex) {
             closeCamera();
             throw new RuntimeException("startPreview failed", ex);
         }

         mZoomState = ZOOM_STOPPED;
         setCameraState(IDLE);
         mFocusManager.onPreviewStarted();
         if ( mTempBracketingEnabled ) {
             mFocusManager.setTempBracketingState(FocusManager.TempBracketingStates.ACTIVE);
         }

         if (mSnapshotOnIdle) {
             mHandler.post(mDoSnapRunnable);
         }
}
上面你們看到了,先調用了setPreviewDisplay,最後調用mCameraDevice.startPreview()開始preview
這裏過程以下:app-->frameworks-->JNI-->camera client-->camera service-->hardware interface-->HAL
1.setPreviewDisplay方法調用時在app層最初的傳入的參數是surfaceholder結構
2.到了JNI層setPreviewDisplay方法傳入的參數已是surface結構了
3.到了camera service層
    sp<IBinder> binder(surface != 0 ? surface->asBinder() : 0);
    sp<ANativeWindow> window(surface);
    return setPreviewWindow(binder, window);
    經過上面的轉換調用同名不一樣參數的另一個方法,到這裏調用的參數已經轉變爲IBinder和ANativeWindow
4.調用hardware interface的setPreviewWindow(window),這裏只有一個ANativeWindow類型的參數
5.到了camerahal_module中轉站時又發生了變化
,看看下面的定義,參數變爲preview_stream_ops 這個類型的結構
    int camera_set_preview_window(struct camera_device * device, struct preview_stream_ops *window)
上面過程參數類型一直在變化,不過從app層一直傳到這裏,實際上是對同一個內存地址的傳輸,就像張三換了身衣服,可是他仍是張三同樣
如今咱們就直接看看HAL層的實現



/**
    @brief Sets ANativeWindow object.


    Preview buffers provided to CameraHal via this object. DisplayAdapter will be interfacing with it
    to render buffers to display.


    @param[in] window The ANativeWindow object created by Surface flinger
    @return NO_ERROR If the ANativeWindow object passes validation criteria
    @todo Define validation criteria for ANativeWindow object. Define error codes for scenarios


  */
 status_t CameraHal::setPreviewWindow(struct preview_stream_ops *window)
 {
     status_t ret = NO_ERROR;
     CameraAdapter::BuffersDescriptor desc;

     LOG_FUNCTION_NAME;
     mSetPreviewWindowCalled = true;


    ///If the Camera service passes a null window, we destroy existing window and free the DisplayAdapter
     if(!window)//這種狀況下,window是null,表示不採用overlay方式,則不須要新建displayadapter
     {
         if(mDisplayAdapter.get() != NULL)
         {
             ///NULL window passed, destroy the display adapter if present
             CAMHAL_LOGD("NULL window passed, destroying display adapter");
             mDisplayAdapter.clear();
             ///@remarks If there was a window previously existing, we usually expect another valid window to be passed by the client
             ///@remarks so, we will wait until it passes a valid window to begin the preview again
             mSetPreviewWindowCalled = false;
         }
         CAMHAL_LOGD("NULL ANativeWindow passed to setPreviewWindow");
         return NO_ERROR;
     } else if(mDisplayAdapter.get() == NULL)//傳入的window不是null,可是尚未未使用overlay方式建立displayadapter,建立displayadapter
     {
         // Need to create the display adapter since it has not been created
         // Create display adapter
         mDisplayAdapter = new ANativeWindowDisplayAdapter();
         ret = NO_ERROR;
         if(!mDisplayAdapter.get() || ((ret=mDisplayAdapter->initialize())!=NO_ERROR))
         {
             if(ret!=NO_ERROR)
             {
                 mDisplayAdapter.clear();
                 CAMHAL_LOGEA("DisplayAdapter initialize failed");
                 LOG_FUNCTION_NAME_EXIT;
                 return ret;
             } else {
                 CAMHAL_LOGEA("Couldn't create DisplayAdapter");
                 LOG_FUNCTION_NAME_EXIT;
                 return NO_MEMORY;
             }
         }

         // DisplayAdapter needs to know where to get the CameraFrames from inorder to display
         // Since CameraAdapter is the one that provides the frames, set it as the frame provider for DisplayAdapter
         mDisplayAdapter->setFrameProvider(mCameraAdapter);

         // Any dynamic errors that happen during the camera use case has to be propagated back to the application
         // via CAMERA_MSG_ERROR. AppCallbackNotifier is the class that notifies such errors to the application
         // Set it as the error handler for the DisplayAdapter
mDisplayAdapter->setErrorHandler(mAppCallbackNotifier.get());

         // Update the display adapter with the new window that is passed from CameraService
         ret = mDisplayAdapter->setPreviewWindow(window);
         if(ret!=NO_ERROR)
             {
             CAMHAL_LOGEB("DisplayAdapter setPreviewWindow returned error %d", ret);
             }


         if(mPreviewStartInProgress)
         {
             CAMHAL_LOGDA("setPreviewWindow called when preview running");
             // Start the preview since the window is now available
             ret = startPreview();
         }
     } else {//傳入的window不是null,而且displaadaper已經建立好,那麼這裏只須要將新的window與已經建立好的displayadapter關聯便可
         // Update the display adapter with the new window that is passed from CameraService
         ret = mDisplayAdapter->setPreviewWindow(window);
         if ( (NO_ERROR == ret) && previewEnabled() ) {
             restartPreview();
         } else if (ret == ALREADY_EXISTS) {
             // ALREADY_EXISTS should be treated as a noop in this case
             ret = NO_ERROR;
         }
     }
     LOG_FUNCTION_NAME_EXIT;

     return ret;

}



這裏咱們重點看看新建displayadapter的過程:
1.實例化一個ANativeWindowDisplayAdapter對象
2.mDisplayAdapter->initialize()
3.mDisplayAdapter->setFrameProvider(mCameraAdapter)//這一步是關鍵,以後會遇到的
4.
mDisplayAdapter->setErrorHandler(mAppCallbackNotifier.get())
5.mDisplayAdapter->setPreviewWindow(window);
作完了上面這些步驟以後,就是startpreview了


/**
    @brief Start preview mode.

    @param none
    @return NO_ERROR Camera switched to VF mode
    @todo Update function header with the different errors that are possible

  */
 status_t CameraHal::startPreview() {
     LOG_FUNCTION_NAME;

     // When tunneling is enabled during VTC, startPreview happens in 2 steps:
     // When the application sends the command CAMERA_CMD_PREVIEW_INITIALIZATION,
     // cameraPreviewInitialization() is called, which in turn causes the CameraAdapter
     // to move from loaded to idle state. And when the application calls startPreview,
     // the CameraAdapter moves from idle to executing state.
     //
     // If the application calls startPreview() without sending the command
     // CAMERA_CMD_PREVIEW_INITIALIZATION, then the function cameraPreviewInitialization()
     // AND startPreview() are executed. In other words, if the application calls
     // startPreview() without sending the command CAMERA_CMD_PREVIEW_INITIALIZATION,
     // then the CameraAdapter moves from loaded to idle to executing state in one shot.
     status_t ret = cameraPreviewInitialization();

     // The flag mPreviewInitializationDone is set to true at the end of the function
     // cameraPreviewInitialization(). Therefore, if everything goes alright, then the
     // flag will be set. Sometimes, the function cameraPreviewInitialization() may
     // return prematurely if all the resources are not available for starting preview.
     // For example, if the preview window is not set, then it would return NO_ERROR.
     // Under such circumstances, one should return from startPreview as well and should
     // not continue execution. That is why, we check the flag and not the return value.
     if (!mPreviewInitializationDone) return ret;

     // Once startPreview is called, there is no need to continue to remember whether
     // the function cameraPreviewInitialization() was called earlier or not. And so
     // the flag mPreviewInitializationDone is reset here. Plus, this preserves the
     // current behavior of startPreview under the circumstances where the application
     // calls startPreview twice or more.
     mPreviewInitializationDone = false;

     ///Enable the display adapter if present, actual overlay enable happens when we post the buffer
     if(mDisplayAdapter.get() != NULL) {
         CAMHAL_LOGDA("Enabling display");
         int width, height;
         mParameters.getPreviewSize(&width, &height);

 #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
         ret = mDisplayAdapter->enableDisplay(width, height, &mStartPreview);
 #else
         ret = mDisplayAdapter->enableDisplay(width, height, NULL);
 #endif

         if ( ret != NO_ERROR ) {
             CAMHAL_LOGEA("Couldn't enable display");

             // FIXME: At this stage mStateSwitchLock is locked and unlock is supposed to be called
             // only from mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_PREVIEW)
             // below. But this will never happen because of goto error. Thus at next
             // startPreview() call CameraHAL will be deadlocked.
             // Need to revisit mStateSwitch lock, for now just abort the process.
             CAMHAL_ASSERT_X(false,
                 "At this stage mCameraAdapter->mStateSwitchLock is still locked, "
                 "deadlock is guaranteed");

             goto error;
         }


     }


     ///Send START_PREVIEW command to adapter
     CAMHAL_LOGDA("Starting CameraAdapter preview mode");


     ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_PREVIEW);


     if(ret!=NO_ERROR) {
         CAMHAL_LOGEA("Couldn't start preview w/ CameraAdapter");
         goto error;
     }
     CAMHAL_LOGDA("Started preview");


     mPreviewEnabled = true;
     mPreviewStartInProgress = false;
     return ret;

     error:
         CAMHAL_LOGEA("Performing cleanup after error");

         //Do all the cleanup
         freePreviewBufs();
          mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_PREVIEW);
         if(mDisplayAdapter.get() != NULL) {
             mDisplayAdapter->disableDisplay(false);
         }
         mAppCallbackNotifier->stop();
         mPreviewStartInProgress = false;
         mPreviewEnabled = false;
         LOG_FUNCTION_NAME_EXIT;

         return ret;
}



上面標出的cameraPreviewInitialization()方法也十分關鍵,以前已經說過,以後若是須要會再作說明
Enable the display adapter if present, actual overlay enable happens when we post the buffer
說明若是display adapter不是null,這裏會enable,overlay方式就啓動了
咱們接着往下看,看看driver獲取的數據究竟是怎樣處理的,startpreview會經過camerahal-->cameraapapter-->V4Lcameradapter

調用到v4l2層的startpreview,下面看看他的具體是實現 android


status_t V4LCameraAdapter::startPreview()
{
    status_t ret = NO_ERROR;

    LOG_FUNCTION_NAME;
    Mutex::Autolock lock(mPreviewBufsLock);


    if(mPreviewing) {
        ret = BAD_VALUE;
        goto EXIT;
    }


    for (int i = 0; i < mPreviewBufferCountQueueable; i++) {

        mVideoInfo->buf.index = i;
        mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;

        ret = v4lIoctl(mCameraHandle, VIDIOC_QBUF, &mVideoInfo->buf);//請求分配內存
        if (ret < 0) {
            CAMHAL_LOGEA("VIDIOC_QBUF Failed");
            goto EXIT;
        }
        nQueued++;
    }


    ret = v4lStartStreaming();


    // Create and start preview thread for receiving buffers from V4L Camera
    if(!mCapturing) {
        mPreviewThread = new PreviewThread(this);//開啓PreviewThread
        CAMHAL_LOGDA("Created preview thread");
    }


    //Update the flag to indicate we are previewing
    mPreviewing = true;
    mCapturing = false;


EXIT:
    LOG_FUNCTION_NAME_EXIT;
    return ret;
}


int V4LCameraAdapter::previewThread()
{
    status_t ret = NO_ERROR;
    int width, height;
    CameraFrame frame;
    void *y_uv[2];
    int index = 0;
    int stride = 4096;
    char *fp = NULL;

    mParams.getPreviewSize(&width, &height);

    if (mPreviewing) {

        fp = this->GetFrame(index);
        if(!fp) {
            ret = BAD_VALUE;
            goto EXIT;
        }
        CameraBuffer *buffer = mPreviewBufs.keyAt(index);//獲取camerabuffer
        CameraFrame *lframe = (CameraFrame *)mFrameQueue.valueFor(buffer);//獲取cameraframe
        if (!lframe) {
            ret = BAD_VALUE;
            goto EXIT;
        }
        debugShowFPS();

        if ( mFrameSubscribers.size() == 0 ) {
            ret = BAD_VALUE;
            goto EXIT;
        }
        y_uv[0] = (void*) lframe->mYuv[0];
        //y_uv[1] = (void*) lframe->mYuv[1];
        //y_uv[1] = (void*) (lframe->mYuv[0] + height*stride);
        convertYUV422ToNV12Tiler ( (unsigned char*)fp, (unsigned char*)y_uv[0], width, height);//convert the data
        CAMHAL_LOGVB("##...index= %d.;camera buffer= 0x%x; y= 0x%x; UV= 0x%x.",index, buffer, y_uv[0], y_uv[1] );

#ifdef SAVE_RAW_FRAMES
        unsigned char* nv12_buff = (unsigned char*) malloc(width*height*3/2);
        //Convert yuv422i to yuv420sp(NV12) & dump the frame to a file
        convertYUV422ToNV12 ( (unsigned char*)fp, nv12_buff, width, height);
        saveFile( nv12_buff, ((width*height)*3/2) );//if you want to save the data,save it
        free (nv12_buff);
#endif
        //填充frame結構,用於數據處理
        frame.mFrameType = CameraFrame::PREVIEW_FRAME_SYNC;
        frame.mBuffer = buffer;
        frame.mLength = width*height*3/2;
        frame.mAlignment = stride;
        frame.mOffset = 0;
        frame.mTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
        frame.mFrameMask = (unsigned int)CameraFrame::PREVIEW_FRAME_SYNC;

        if (mRecording)
        {
            frame.mFrameMask |= (unsigned int)CameraFrame::VIDEO_FRAME_SYNC;
            mFramesWithEncoder++;
        }

        //這裏是重點,數據回調,或者使用overlay方式顯示這裏是決定性調用
        ret = setInitFrameRefCount(frame.mBuffer, frame.mFrameMask);
        if (ret != NO_ERROR) {
            CAMHAL_LOGDB("Error in setInitFrameRefCount %d", ret);
        } else {
            ret = sendFrameToSubscribers(&frame);
        }
    }
EXIT:

    return ret;
}
如今就開始看看setInitFrameCount方法都作了些什麼



int BaseCameraAdapter::setInitFrameRefCount(CameraBuffer * buf, unsigned int mask)
{
   int ret = NO_ERROR;
   unsigned int lmask;

   LOG_FUNCTION_NAME;

   if (buf == NULL)
   {
       return -EINVAL;
   }

  for( lmask = 1; lmask < CameraFrame::ALL_FRAMES; lmask <<= 1){
    if( lmask & mask ){
      switch( lmask ){


      case CameraFrame::IMAGE_FRAME:
      {
          setFrameRefCount(buf, CameraFrame::IMAGE_FRAME, (int) mImageSubscribers.size());
        }
        break;
      case CameraFrame::RAW_FRAME:
        {
          setFrameRefCount(buf, CameraFrame::RAW_FRAME, mRawSubscribers.size());
        }
        break;
      case CameraFrame::PREVIEW_FRAME_SYNC:
        {
         setFrameRefCount(buf, CameraFrame::PREVIEW_FRAME_SYNC, mFrameSubscribers.size());//這裏這個mFrameSubscribers對應的key上保存着響應的callback方法
        }
        break;
      case CameraFrame::SNAPSHOT_FRAME:
        {
          setFrameRefCount(buf, CameraFrame::SNAPSHOT_FRAME, mSnapshotSubscribers.size());
        }
        break;
      case CameraFrame::VIDEO_FRAME_SYNC:
        {
          setFrameRefCount(buf,CameraFrame::VIDEO_FRAME_SYNC, mVideoSubscribers.size());
        }
        break;
      case CameraFrame::FRAME_DATA_SYNC:
        {
          setFrameRefCount(buf, CameraFrame::FRAME_DATA_SYNC, mFrameDataSubscribers.size());
        }
        break;
      case CameraFrame::REPROCESS_INPUT_FRAME:
        {
          setFrameRefCount(buf,CameraFrame::REPROCESS_INPUT_FRAME, mVideoInSubscribers.size());
        }
        break;
      default:
        CAMHAL_LOGEB("FRAMETYPE NOT SUPPORTED 0x%x", lmask);
        break;
      }//SWITCH
      mask &= ~lmask;
    }//IF
  }//FOR
  LOG_FUNCTION_NAME_EXIT;
  return ret;
}
上面我標註的部分經過enableMsgType方法實現mFrameSubscribers.add的,經callback添加到對應的key處,算是實現關聯,
一樣的經過disableMsgType方法實現mFrameSubscribers.removeItem的,具體在哪裏調用enableMsgType和disableMsgType以後再給予說明



1. void BaseCameraAdapter::setFrameRefCount(CameraBuffer * frameBuf, CameraFrame::FrameType frameType, int refCount)
   2. {
   3.

   4.     LOG_FUNCTION_NAME;
   5.

   6.     switch ( frameType )
   7.         {
   8.         case CameraFrame::IMAGE_FRAME:
   9.         case CameraFrame::RAW_FRAME:
  10.                 {
  11.                 Mutex::Autolock lock(mCaptureBufferLock);
  12.                 mCaptureBuffersAvailable.replaceValueFor(frameBuf, refCount);
  13.                 }
  14.             break;
  15.         case CameraFrame::SNAPSHOT_FRAME:
  16.                 {
  17.                 Mutex::Autolock lock(mSnapshotBufferLock);
  18.                 mSnapshotBuffersAvailable.replaceValueFor( ( unsigned int ) frameBuf, refCount);
  19.                 }
  20.             break;
  21.         case CameraFrame::PREVIEW_FRAME_SYNC:
  22.                 {
  23.                 Mutex::Autolock lock(mPreviewBufferLock)
  24.                 mPreviewBuffersAvailable.replaceValueFor(frameBuf, refCount);//這裏個人理解是refCount和frameBuf實現了綁定,即camerabuf保存在mPreviewBuffersAvailable對應的key處
  25.                 }
  26.             break;
  27.         case CameraFrame::FRAME_DATA_SYNC:
  28.                 {
  29.                 Mutex::Autolock lock(mPreviewDataBufferLock);
  30.                 mPreviewDataBuffersAvailable.replaceValueFor(frameBuf, refCount);
  31.                 }
  32.             break;
  33.         case CameraFrame::VIDEO_FRAME_SYNC:
  34.                 {
  35.                 Mutex::Autolock lock(mVideoBufferLock);
  36.                 mVideoBuffersAvailable.replaceValueFor(frameBuf, refCount);
  37.                 }
  38.             break;
  39.         case CameraFrame::REPROCESS_INPUT_FRAME: {
  40.             Mutex::Autolock lock(mVideoInBufferLock);
  41.             mVideoInBuffersAvailable.replaceValueFor(frameBuf, refCount);
  42.         }
  43.             break;
  44.         default:
  45.             break;
  46.         };
  47.

  48.     LOG_FUNCTION_NAME_EXIT;
  49.

  50. }
接下咱們看看sendFrameToSubscribers方法的具體實現過程



1. status_t BaseCameraAdapter::sendFrameToSubscribers(CameraFrame *frame)
   2. {
   3.     status_t ret = NO_ERROR;
   4.     unsigned int mask;
   5.

   6.     if ( NULL == frame )
   7.         {
   8.         CAMHAL_LOGEA("Invalid CameraFrame");
   9.         return -EINVAL;
  10.         }
  11.

  12.     for( mask = 1; mask < CameraFrame::ALL_FRAMES; mask <<= 1){
  13.       if( mask & frame->mFrameMask ){
  14.         switch( mask ){
  15.

  16.         case CameraFrame::IMAGE_FRAME:
  17.           {
  18. #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
  19.             CameraHal::PPM("Shot to Jpeg: ", &mStartCapture);
  20. #endif
  21.             ret = __sendFrameToSubscribers(frame, &mImageSubscribers, CameraFrame::IMAGE_FRAME);
  22.           }
  23.           break;
  24.         case CameraFrame::RAW_FRAME:
  25.           {
  26.             ret = __sendFrameToSubscribers(frame, &mRawSubscribers, CameraFrame::RAW_FRAME);
  27.           }
  28.           break;
  29.         case CameraFrame::PREVIEW_FRAME_SYNC:
  30.           {
  31.             ret = __sendFrameToSubscribers(frame, &mFrameSubscribers, CameraFrame::PREVIEW_FRAME_SYNC);
  32.           }
  33.           break;
  34.         case CameraFrame::SNAPSHOT_FRAME:
  35.           {
  36.             ret = __sendFrameToSubscribers(frame, &mSnapshotSubscribers, CameraFrame::SNAPSHOT_FRAME);
  37.           }
  38.           break;
  39.         case CameraFrame::VIDEO_FRAME_SYNC:
  40.           {
  41.             ret = __sendFrameToSubscribers(frame, &mVideoSubscribers, CameraFrame::VIDEO_FRAME_SYNC);
  42.           }
  43.           break;
  44.         case CameraFrame::FRAME_DATA_SYNC:
  45.           {
  46.             ret = __sendFrameToSubscribers(frame, &mFrameDataSubscribers, CameraFrame::FRAME_DATA_SYNC);
  47.           }
  48.           break;
  49.         case CameraFrame::REPROCESS_INPUT_FRAME:
  50.           {
  51.             ret = __sendFrameToSubscribers(frame, &mVideoInSubscribers, CameraFrame::REPROCESS_INPUT_FRAME);
  52.           }
  53.           break;
  54.         default:
  55.           CAMHAL_LOGEB("FRAMETYPE NOT SUPPORTED 0x%x", mask);
  56.         break;
  57.         }//SWITCH
  58.         frame->mFrameMask &= ~mask;
  59.

  60.         if (ret != NO_ERROR) {
  61.             goto EXIT;
  62.         }
  63.       }//IF
  64.     }//FOR
  65.

  66.  EXIT:
  67.     return ret;
  68. }



1. status_t BaseCameraAdapter::__sendFrameToSubscribers(CameraFrame* frame,
   2.                                                      KeyedVector<int, frame_callback> *subscribers,
   3.                                                      CameraFrame::FrameType frameType)
   4. {
   5.     size_t refCount = 0;
   6.     status_t ret = NO_ERROR;
   7.     frame_callback callback = NULL;
   8.

   9.     frame->mFrameType = frameType;
  10.

  11.     if ( (frameType == CameraFrame::PREVIEW_FRAME_SYNC) ||
  12.          (frameType == CameraFrame::VIDEO_FRAME_SYNC) ||
  13.          (frameType == CameraFrame::SNAPSHOT_FRAME) ){
  14.         if (mFrameQueue.size() > 0){
  15.           CameraFrame *lframe = (CameraFrame *)mFrameQueue.valueFor(frame->mBuffer);
  16.           frame->mYuv[0] = lframe->mYuv[0];
  17.           frame->mYuv[1] = frame->mYuv[0] + (frame->mLength + frame->mOffset)*2/3;
  18.         }
  19.         else{
  20.           CAMHAL_LOGDA("Empty Frame Queue");
  21.           return -EINVAL;
  22.         }
  23.       }
  24.

  25.     if (NULL != subscribers) {
  26.         refCount = getFrameRefCount(frame->mBuffer, frameType);//經過這個refCount能夠找到對應的callback方法
  27.

  28.         if (refCount == 0) {
  29.             CAMHAL_LOGDA("Invalid ref count of 0");
  30.             return -EINVAL;
  31.         }
  32.

  33.         if (refCount > subscribers->size()) {
  34.             CAMHAL_LOGEB("Invalid ref count for frame type: 0x%x", frameType);
  35.             return -EINVAL;
  36.         }
  37.

  38.         CAMHAL_LOGVB("Type of Frame: 0x%x address: 0x%x refCount start %d",
  39.                      frame->mFrameType,
  40.                      ( uint32_t ) frame->mBuffer,
  41.                      refCount);
  42.

  43.         for ( unsigned int i = 0 ; i < refCount; i++ ) {
  44.             frame->mCookie = ( void * ) subscribers->keyAt(i);
  45.             callback = (frame_callback) subscribers->valueAt(i);
  46.

  47.             if (!callback) {
  48.                 CAMHAL_LOGEB("callback not set for frame type: 0x%x", frameType);
  49.                 return -EINVAL;
  50.             }
  51.

  52.             callback(frame);
  53.         }
  54.     } else {
  55.         CAMHAL_LOGEA("Subscribers is null??");
  56.         return -EINVAL;
  57.     }
  58.

  59.     return ret;
  60. }
這裏別的咱們先暫且不分析,可是callback究竟是從哪裏來的,這個咱們必須說清楚
上面在實例化displayadapter時有這樣一步:3.mDisplayAdapter->setFrameProvider(mCameraAdapter)//這一步是關鍵,以後會遇到的
咱們看看setFrameProvider這個方法的實現:

1. int ANativeWindowDisplayAdapter::setFrameProvider(FrameNotifier *frameProvider)
   2. {
   3.     LOG_FUNCTION_NAME;
   4.

   5.     // Check for NULL pointer
   6.     if ( !frameProvider ) {
   7.         CAMHAL_LOGEA("NULL passed for frame provider");
   8.         LOG_FUNCTION_NAME_EXIT;
   9.         return BAD_VALUE;
  10.     }
  11.

  12.     //Release any previous frame providers
  13.     if ( NULL != mFrameProvider ) {
  14.         delete mFrameProvider;
  15.     }
  16.

  17.     /** Dont do anything here, Just save the pointer for use when display is
  18.          actually enabled or disabled
  19.     */
  20.     mFrameProvider = new FrameProvider(frameProvider, this, frameCallbackRelay);//實例化一個FrameProvider,這其中有一個參數很是重要:frameCallbackRelay,他的定義在下面給出
  21.

  22.     LOG_FUNCTION_NAME_EXIT;
  23.

  24.     return NO_ERROR;
  25. }


   1. void ANativeWindowDisplayAdapter::frameCallbackRelay(CameraFrame* caFrame)
   2. {
   3.

   4.     if ( NULL != caFrame )
   5.         {
   6.         if ( NULL != caFrame->mCookie )
   7.             {
   8.             ANativeWindowDisplayAdapter *da = (ANativeWindowDisplayAdapter*) caFrame->mCookie;
   9.             da->frameCallback(caFrame);
  10.         }
  11.         else
  12.             {
  13.             CAMHAL_LOGEB("Invalid Cookie in Camera Frame = %p, Cookie = %p", caFrame, caFrame->mCookie);
  14.             }
  15.         }
  16.     else
  17.         {
  18.         CAMHAL_LOGEB("Invalid Camera Frame = %p", caFrame);
  19.     }
  20.

  21. }


   1. void ANativeWindowDisplayAdapter::frameCallback(CameraFrame* caFrame)
   2. {
   3.     ///Call queueBuffer of overlay in the context of the callback thread
   4.     DisplayFrame df;
   5.     df.mBuffer = caFrame->mBuffer;
   6.     df.mType = (CameraFrame::FrameType) caFrame->mFrameType;
   7.     df.mOffset = caFrame->mOffset;
   8.     df.mWidthStride = caFrame->mAlignment;
   9.     df.mLength = caFrame->mLength;
  10.     df.mWidth = caFrame->mWidth;
  11.     df.mHeight = caFrame->mHeight;
  12.     PostFrame(df);
  13. }
這個回調函數在這裏設置,等待數據回調,咱們頗有必要去看看FrameProvider這個類的構造函數,他是怎樣讓其餘方法調用到這個回調函數的呢

1. FrameProvider(FrameNotifier *fn, void* cookie, frame_callback frameCallback)
   2.         :mFrameNotifier(fn), mCookie(cookie),mFrameCallback(frameCallback) { }
這個構造函數仍是頗有意思,沒有任何實現,只是經過傳入的三個參數實例化了三個對象而已
1.mFrameNotifier(fn), //這裏mFrameNotifier就是camerasdapter
2.mCookie
(cookie),
3.
mFrameCallback(frameCallback)//mFrameCallback指向咱們定義好的callback方法
咱們接着就須要到以前已經提到過的startPreview方法中cameraPreviewInitialization的方法中去看了

1. ////////////
   2. /**
   3.    @brief Set preview mode related initialization
   4.           -> Camera Adapter set params
   5.           -> Allocate buffers
   6.           -> Set use buffers for preview
   7.    @param none
   8.    @return NO_ERROR
   9.    @todo Update function header with the different errors that are possible
  10.

  11.  */
  12. status_t CameraHal::cameraPreviewInitialization()
  13. {
  14.

  15.     status_t ret = NO_ERROR;
  16.     CameraAdapter::BuffersDescriptor desc;
  17.     CameraFrame frame;
  18.     unsigned int required_buffer_count;
  19.     unsigned int max_queueble_buffers;
  20.

  21. #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
  22.         gettimeofday(&mStartPreview, NULL);
  23. #endif
  24.

  25.     LOG_FUNCTION_NAME;
  26.

  27.     if (mPreviewInitializationDone) {
  28.         return NO_ERROR;
  29.     }
  30.

  31.     if ( mPreviewEnabled ){
  32.       CAMHAL_LOGDA("Preview already running");
  33.       LOG_FUNCTION_NAME_EXIT;
  34.       return ALREADY_EXISTS;
  35.     }
  36.

  37.     if ( NULL != mCameraAdapter ) {
  38.       ret = mCameraAdapter->setParameters(mParameters);
  39.     }
  40.

  41.     if ((mPreviewStartInProgress == false) && (mDisplayPaused == false)){
  42.       ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_QUERY_RESOLUTION_PREVIEW,( int ) &frame);
  43.       if ( NO_ERROR != ret ){
  44.         CAMHAL_LOGEB("Error: CAMERA_QUERY_RESOLUTION_PREVIEW %d", ret);
  45.         return ret;
  46.       }
  47.

  48.       ///Update the current preview width and height
  49.       mPreviewWidth = frame.mWidth;
  50.       mPreviewHeight = frame.mHeight;
  51.     }
  52.

  53.     ///If we don't have the preview callback enabled and display adapter,
  54.     if(!mSetPreviewWindowCalled || (mDisplayAdapter.get() == NULL)){
  55.       CAMHAL_LOGD("Preview not started. Preview in progress flag set");
  56.       mPreviewStartInProgress = true;
  57.       ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_SWITCH_TO_EXECUTING);
  58.       if ( NO_ERROR != ret ){
  59.         CAMHAL_LOGEB("Error: CAMERA_SWITCH_TO_EXECUTING %d", ret);
  60.         return ret;
  61.       }
  62.       return NO_ERROR;
  63.     }
  64.

  65.     if( (mDisplayAdapter.get() != NULL) && ( !mPreviewEnabled ) && ( mDisplayPaused ) )
  66.         {
  67.         CAMHAL_LOGDA("Preview is in paused state");
  68.

  69.         mDisplayPaused = false;
  70.         mPreviewEnabled = true;
  71.         if ( NO_ERROR == ret )
  72.             {
  73.             ret = mDisplayAdapter->pauseDisplay(mDisplayPaused);
  74.

  75.             if ( NO_ERROR != ret )
  76.                 {
  77.                 CAMHAL_LOGEB("Display adapter resume failed %x", ret);
  78.                 }
  79.             }
  80.         //restart preview callbacks
  81.         if(mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)
  82.         {
  83.             mAppCallbackNotifier->enableMsgType (CAMERA_MSG_PREVIEW_FRAME);
  84.         }
  85.

  86.         signalEndImageCapture();
  87.         return ret;
  88.         }
  89.

  90.     required_buffer_count = atoi(mCameraProperties->get(CameraProperties::REQUIRED_PREVIEW_BUFS));
  91.

  92.     ///Allocate the preview buffers
  93.     ret = allocPreviewBufs(mPreviewWidth, mPreviewHeight, mParameters.getPreviewFormat(), required_buffer_count, max_queueble_buffers);
  94.

  95.     if ( NO_ERROR != ret )
  96.         {
  97.         CAMHAL_LOGEA("Couldn't allocate buffers for Preview");
  98.         goto error;
  99.         }
 100.

 101.     if ( mMeasurementEnabled )
 102.         {
 103.

 104.         ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_QUERY_BUFFER_SIZE_PREVIEW_DATA,
 105.                                           ( int ) &frame,
 106.                                           required_buffer_count);
 107.         if ( NO_ERROR != ret )
 108.             {
 109.             return ret;
 110.             }
 111.

 112.          ///Allocate the preview data buffers
 113.         ret = allocPreviewDataBufs(frame.mLength, required_buffer_count);
 114.         if ( NO_ERROR != ret ) {
 115.             CAMHAL_LOGEA("Couldn't allocate preview data buffers");
 116.             goto error;
 117.            }
 118.

 119.         if ( NO_ERROR == ret )
 120.             {
 121.             desc.mBuffers = mPreviewDataBuffers;
 122.             desc.mOffsets = mPreviewDataOffsets;
 123.             desc.mFd = mPreviewDataFd;
 124.             desc.mLength = mPreviewDataLength;
 125.             desc.mCount = ( size_t ) required_buffer_count;
 126.             desc.mMaxQueueable = (size_t) required_buffer_count;
 127.

 128.             mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_PREVIEW_DATA,
 129.                                         ( int ) &desc);
 130.             }
 131.

 132.         }
 133.

 134.     ///Pass the buffers to Camera Adapter
 135.     desc.mBuffers = mPreviewBuffers;
 136.     desc.mOffsets = mPreviewOffsets;
 137.     desc.mFd = mPreviewFd;
 138.     desc.mLength = mPreviewLength;
 139.     desc.mCount = ( size_t ) required_buffer_count;
 140.     desc.mMaxQueueable = (size_t) max_queueble_buffers;
 141.

 142.     ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_PREVIEW,
 143.                                       ( int ) &desc);
 144.

 145.     if ( NO_ERROR != ret )
 146.         {
 147.         CAMHAL_LOGEB("Failed to register preview buffers: 0x%x", ret);
 148.         freePreviewBufs();
 149.         return ret;
 150.         }
 151.

 152.     mAppCallbackNotifier->startPreviewCallbacks(mParameters, mPreviewBuffers, mPreviewOffsets, mPreviewFd, mPreviewLength, required_buffer_count);
 153.

 154.     ///Start the callback notifier
 155.     ret = mAppCallbackNotifier->start();
 156.

 157.     if( ALREADY_EXISTS == ret )
 158.         {
 159.         //Already running, do nothing
 160.         CAMHAL_LOGDA("AppCallbackNotifier already running");
 161.         ret = NO_ERROR;
 162.         }
 163.     else if ( NO_ERROR == ret ) {
 164.         CAMHAL_LOGDA("Started AppCallbackNotifier..");
 165.         mAppCallbackNotifier->setMeasurements(mMeasurementEnabled);
 166.         }
 167.     else
 168.         {
 169.         CAMHAL_LOGDA("Couldn't start AppCallbackNotifier");
 170.         goto error;
 171.         }
 172.

 173.     if (ret == NO_ERROR) mPreviewInitializationDone = true;
 174.     return ret;
 175.

 176.     error:
 177.

 178.         CAMHAL_LOGEA("Performing cleanup after error");
 179.

 180.         //Do all the cleanup
 181.         freePreviewBufs();
 182.         mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_PREVIEW);
 183.         if(mDisplayAdapter.get() != NULL)
 184.             {
 185.             mDisplayAdapter->disableDisplay(false);
 186.             }
 187.         mAppCallbackNotifier->stop();
 188.         mPreviewStartInProgress = false;
 189.         mPreviewEnabled = false;
 190.         LOG_FUNCTION_NAME_EXIT;
 191.

 192.         return ret;
 193. }
咱們就看看這個方法的是實現吧:mAppCallbackNotifier->enableMsgType (CAMERA_MSG_PREVIEW_FRAME);

1. status_t AppCallbackNotifier::enableMsgType(int32_t msgType)
   2. {
   3.     if( msgType & CAMERA_MSG_PREVIEW_FRAME ) {
   4.         mFrameProvider->enableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC);
   5.     }
   6.

   7.     if( msgType & CAMERA_MSG_POSTVIEW_FRAME ) {
   8.         mFrameProvider->enableFrameNotification(CameraFrame::SNAPSHOT_FRAME);
   9.     }
  10.

  11.     if(msgType & CAMERA_MSG_RAW_IMAGE) {
  12.         mFrameProvider->enableFrameNotification(CameraFrame::RAW_FRAME);
  13.     }
  14.

  15.     return NO_ERROR;
  16. }



   1. int FrameProvider::enableFrameNotification(int32_t frameTypes)
   2. {
   3.     LOG_FUNCTION_NAME;
   4.     status_t ret = NO_ERROR;
   5.

   6.     ///Enable the frame notification to CameraAdapter (which implements FrameNotifier interface)
   7.     mFrameNotifier->enableMsgType(frameTypes<<MessageNotifier::FRAME_BIT_FIELD_POSITION, mFrameCallback, NULL, mCookie);
   8.

   9.     LOG_FUNCTION_NAME_EXIT;
  10.     return ret;
  11. }
這裏這個enableMsgType其實就是前面已經提到過的那個enableMsgType方法,實現callback方法add到響應的key上
這裏這個mFrameNotifier是FrameNotifier的對象,FrameNotifier這個類繼承於MessageNotifier
而BaseCameraAdapter繼承於CameraAdapter,CameraAdapter又繼承於FrameNotifier,因此mFrameNotifier對象調用的enableMsgType方法實際上是一個虛函數,
最終調用的是BaseCameraAdapter這個類中定義的enableMsgType方法,咱們來看一看他的實現:

1. void BaseCameraAdapter::enableMsgType(int32_t msgs, frame_callback callback, event_callback eventCb, void* cookie)
   2. {
   3.     Mutex::Autolock lock(mSubscriberLock);
   4.

   5.     LOG_FUNCTION_NAME;
   6.

   7.     int32_t frameMsg = ((msgs >> MessageNotifier::FRAME_BIT_FIELD_POSITION) & EVENT_MASK);
   8.     int32_t eventMsg = ((msgs >> MessageNotifier::EVENT_BIT_FIELD_POSITION) & EVENT_MASK);
   9.

  10.     if ( frameMsg != 0 )
  11.         {
  12.         CAMHAL_LOGVB("Frame message type id=0x%x subscription request", frameMsg);
  13.         switch ( frameMsg )
  14.             {
  15.             case CameraFrame::PREVIEW_FRAME_SYNC:
  16.                 mFrameSubscribers.add((int) cookie, callback);
  17.                 break;
  18.             case CameraFrame::FRAME_DATA_SYNC:
  19.                 mFrameDataSubscribers.add((int) cookie, callback);
  20.                 break;
  21.             case CameraFrame::SNAPSHOT_FRAME:
  22.                 mSnapshotSubscribers.add((int) cookie, callback);
  23.                 break;
  24.             case CameraFrame::IMAGE_FRAME:
  25.                 mImageSubscribers.add((int) cookie, callback);
  26.                 break;
  27.             case CameraFrame::RAW_FRAME:
  28.                 mRawSubscribers.add((int) cookie, callback);
  29.                 break;
  30.             case CameraFrame::VIDEO_FRAME_SYNC:
  31.                 mVideoSubscribers.add((int) cookie, callback);
  32.                 break;
  33.             case CameraFrame::REPROCESS_INPUT_FRAME:
  34.                 mVideoInSubscribers.add((int) cookie, callback);
  35.                 break;
  36.             default:
  37.                 CAMHAL_LOGEA("Frame message type id=0x%x subscription no supported yet!", frameMsg);
  38.                 break;
  39.             }
  40.         }
  41.

  42.     if ( eventMsg != 0)
  43.         {
  44.         CAMHAL_LOGVB("Event message type id=0x%x subscription request", eventMsg);
  45.         if ( CameraHalEvent::ALL_EVENTS == eventMsg )
  46.             {
  47.             mFocusSubscribers.add((int) cookie, eventCb);
  48.             mShutterSubscribers.add((int) cookie, eventCb);
  49.             mZoomSubscribers.add((int) cookie, eventCb);
  50.             mMetadataSubscribers.add((int) cookie, eventCb);
  51.             }
  52.         else
  53.             {
  54.             CAMHAL_LOGEA("Event message type id=0x%x subscription no supported yet!", eventMsg);
  55.             }
  56.         }
  57.

  58.     LOG_FUNCTION_NAME_EXIT;
  59. }
這裏經過mFrameSubscribers.add((int) cookie, callback)這個方法將mFrameCallback回調函數與key相關聯
因此上面能夠經過callback = (frame_callback) subscribers->valueAt(i);
這個方法獲取callback的實現,由於上面已經實現了關聯,因此數據最終是經過上面分析道的方法繼續進行數據流顯示

1. void ANativeWindowDisplayAdapter::frameCallback(CameraFrame* caFrame)
   2. {
   3.     ///Call queueBuffer of overlay in the context of the callback thread
   4.     DisplayFrame df;
   5.     df.mBuffer = caFrame->mBuffer;
   6.     df.mType = (CameraFrame::FrameType) caFrame->mFrameType;
   7.     df.mOffset = caFrame->mOffset;
   8.     df.mWidthStride = caFrame->mAlignment;
   9.     df.mLength = caFrame->mLength;
  10.     df.mWidth = caFrame->mWidth;
  11.     df.mHeight = caFrame->mHeight;
  12.     PostFrame(df);//這裏填充了DisplayFrame這個結構,並調用PostFrome實現顯示
  13. }
這裏PostFrame成了我要研究的主要內容,將數據以DisplayFrame結構的方式打包以後究竟是怎麼實現顯示的呢??

1. status_t ANativeWindowDisplayAdapter::PostFrame(ANativeWindowDisplayAdapter::DisplayFrame &dispFrame)
   2. {
   3.     status_t ret = NO_ERROR;
   4.     uint32_t actualFramesWithDisplay = 0;
   5.     android_native_buffer_t *buffer = NULL;
   6.     GraphicBufferMapper &mapper = GraphicBufferMapper::get();
   7.     int i;
   8.

   9.     ///@todo Do cropping based on the stabilized frame coordinates
  10.     ///@todo Insert logic to drop frames here based on refresh rate of
  11.     ///display or rendering rate whichever is lower
  12.     ///Queue the buffer to overlay
  13.

  14.     if ( NULL == mANativeWindow ) {
  15.         return NO_INIT;
  16.     }
  17.

  18.     if (!mBuffers || !dispFrame.mBuffer) {
  19.         CAMHAL_LOGEA("NULL sent to PostFrame");
  20.         return BAD_VALUE;
  21.     }
  22.

  23.     for ( i = 0; i < mBufferCount; i++ )
  24.         {
  25.         if ( dispFrame.mBuffer == &mBuffers[i] )
  26.             {
  27.             break;
  28.         }
  29.     }
  30.

  31.


  32.     mFramesType.add( (int)mBuffers[i].opaque ,dispFrame.mType );
  33.

  34.     if ( mDisplayState == ANativeWindowDisplayAdapter::DISPLAY_STARTED &&
  35.                 (!mPaused || CameraFrame::CameraFrame::SNAPSHOT_FRAME == dispFrame.mType) &&
  36.                 !mSuspend)
  37.     {
  38.         Mutex::Autolock lock(mLock);
  39.         uint32_t xOff = (dispFrame.mOffset% PAGE_SIZE);
  40.         uint32_t yOff = (dispFrame.mOffset / PAGE_SIZE);
  41.

  42.         // Set crop only if current x and y offsets do not match with frame offsets
  43.         if((mXOff!=xOff) || (mYOff!=yOff))
  44.         {
  45.             CAMHAL_LOGDB("Offset %d xOff = %d, yOff = %d", dispFrame.mOffset, xOff, yOff);
  46.             uint8_t bytesPerPixel;
  47.             ///Calculate bytes per pixel based on the pixel format
  48.             if(strcmp(mPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV422I) == 0)
  49.                 {
  50.                 bytesPerPixel = 2;
  51.                 }
  52.             else if(strcmp(mPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_RGB565) == 0)
  53.                 {
  54.                 bytesPerPixel = 2;
  55.                 }
  56.             else if(strcmp(mPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV420SP) == 0)
  57.                 {
  58.                 bytesPerPixel = 1;
  59.                 }
  60.             else
  61.                 {
  62.                 bytesPerPixel = 1;
  63.             }
  64.

  65.             CAMHAL_LOGVB(" crop.left = %d crop.top = %d crop.right = %d crop.bottom = %d",
  66.                           xOff/bytesPerPixel, yOff , (xOff/bytesPerPixel)+mPreviewWidth, yOff+mPreviewHeight);
  67.             // We'll ignore any errors here, if the surface is
  68.             // already invalid, we'll know soon enough.
  69.             mANativeWindow->set_crop(mANativeWindow, xOff/bytesPerPixel, yOff,
  70.                                      (xOff/bytesPerPixel)+mPreviewWidth, yOff+mPreviewHeight);
  71.

  72.             ///Update the current x and y offsets
  73.             mXOff = xOff;
  74.             mYOff = yOff;
  75.         }
  76.

  77.         {
  78.             buffer_handle_t *handle = (buffer_handle_t *) mBuffers[i].opaque;
  79.             // unlock buffer before sending to display
  80.             mapper.unlock(*handle);
  81.             ret = mANativeWindow->enqueue_buffer(mANativeWindow, handle);
  82.         }
  83.         if ( NO_ERROR != ret ) {
  84.             CAMHAL_LOGE("Surface::queueBuffer returned error %d", ret);
  85.         }
  86.

  87.         mFramesWithCameraAdapterMap.removeItem((buffer_handle_t *) dispFrame.mBuffer->opaque);
  88.

  89.


  90.         // HWComposer has not minimum buffer requirement. We should be able to dequeue
  91.         // the buffer immediately
  92.         TIUTILS::Message msg;
  93.         mDisplayQ.put(&msg);
  94.

  95.


  96. #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
  97.

  98.         if ( mMeasureStandby )
  99.             {
 100.             CameraHal::PPM("Standby to first shot: Sensor Change completed - ", &mStandbyToShot);
 101.             mMeasureStandby = false;
 102.             }
 103.         else if (CameraFrame::CameraFrame::SNAPSHOT_FRAME == dispFrame.mType)
 104.             {
 105.             CameraHal::PPM("Shot to snapshot: ", &mStartCapture);
 106.             mShotToShot = true;
 107.             }
 108.         else if ( mShotToShot )
 109.             {
 110.             CameraHal::PPM("Shot to shot: ", &mStartCapture);
 111.             mShotToShot = false;
 112.         }
 113. #endif
 114.

 115.     }
 116.     else
 117.     {
 118.         Mutex::Autolock lock(mLock);
 119.         buffer_handle_t *handle = (buffer_handle_t *) mBuffers[i].opaque;
 120.

 121.         // unlock buffer before giving it up
 122.         mapper.unlock(*handle);
 123.

 124.         // cancel buffer and dequeue another one
 125.         ret = mANativeWindow->cancel_buffer(mANativeWindow, handle);
 126.         if ( NO_ERROR != ret ) {
 127.             CAMHAL_LOGE("Surface::cancelBuffer returned error %d", ret);
 128.         }
 129.

 130.         mFramesWithCameraAdapterMap.removeItem((buffer_handle_t *) dispFrame.mBuffer->opaque);
 131.

 132.         TIUTILS::Message msg;
 133.         mDisplayQ.put(&msg);
 134.         ret = NO_ERROR;
 135.     }
 136.

 137.     return ret;
 138. }



這個顯示的過程相對來講仍是比較複雜的,以後還須要花點時間研究一下
相關文章
相關標籤/搜索