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方法

我们就还是看看在这里都做了些什么事情


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,下面看看他的具体是实现


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



这个显示的过程相对来说还是比较复杂的,之后还需要花点时间研究一下

转载于:https://my.oschina.net/jerikc/blog/219353

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值