Android Camera数据流分析全程记录(overlay方式)

 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方法
我们就还是看看在这里都做了些什么事情
  1. public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
  2.         // Make sure we have a surface in the holder before proceeding.
  3.         if (holder.getSurface() == null) {
  4.             Log.d(TAG, "holder.getSurface() == null");
  5.             return;
  6.         }

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

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

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

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

  19.         setSurfaceLayout();

  20.         // Set preview display if the surface is being created. Preview was
  21.         // already started. Also restart the preview if display rotation has
  22.         // changed. Sometimes this happens when the device is held in portrait
  23.         // and camera app is opened. Rotation animation takes some time and
  24.         // display rotation in onCreate may not be what we want.
  25.         if (mCameraState == PREVIEW_STOPPED) {//这里表示第一次打开camera时,那么调用startpreview
  26.             startPreview(true);
  27.             startFaceDetection();
  28.         } else {//这里则表示camera已经打开过程中发生的显示变化,比如横屏竖频转换,所以zheli只需要重新设置previewdisplay
  29.             if (Util.getDisplayRotation(this) != mDisplayRotation) {
  30.                 setDisplayOrientation();
  31.             }
  32.             if (holder.isCreating()) {
  33.                 // Set preview display if the surface is being created and preview
  34.                 // was already started. That means preview display was set to null
  35.                 // and we need to set it now.
  36.                 setPreviewDisplay(holder);
  37.             }
  38.         }

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

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

  52.         mTouchManager.initialize(preview.getHeight() / 3, preview.getHeight() / 3,
  53.                preview, this, mirror, displayOrientation);

  54.     }
从上面代码我们必须知道,在surface发生变化时必须调用 setPreviewDisplay,根据之后的学习,在startpreview方式中真正startpreview之前同样要调用 setPreviewDisplay,在 setPreviewDisplay的方法中完成了很多初始化,也是在这里决定是否使用overlay方式的,我们就先看看startpreview这个方法吧
  1. private void startPreview(boolean updateAll) {
  2.         if (mPausing || isFinishing()) return;

  3.         mFocusManager.resetTouchFocus();

  4.         mCameraDevice.setErrorCallback(mErrorCallback);

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

  8.         setPreviewDisplay(mSurfaceHolder);
  9.         setDisplayOrientation();

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

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

  24.         //setCameraParameters(UPDATE_PARAM_ALL);

  25.         // Inform the mainthread to go on the UI initialization.
  26.         if (mCameraPreviewThread != null) {
  27.             synchronized (mCameraPreviewThread) {
  28.                 mCameraPreviewThread.notify();
  29.             }
  30.         }

  31.         try {
  32.             Log.v(TAG, "startPreview");
  33.             mCameraDevice.startPreview();
  34.         } catch (Throwable ex) {
  35.             closeCamera();
  36.             throw new RuntimeException("startPreview failed", ex);
  37.         }

  38.         mZoomState = ZOOM_STOPPED;
  39.         setCameraState(IDLE);
  40.         mFocusManager.onPreviewStarted();
  41.         if ( mTempBracketingEnabled ) {
  42.             mFocusManager.setTempBracketingState(FocusManager.TempBracketingStates.ACTIVE);
  43.         }

  44.         if (mSnapshotOnIdle) {
  45.             mHandler.post(mDoSnapRunnable);
  46.         }
  47.     }
上面大家看到了,先调用了 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层的实现
  1. /**
  2.    @brief Sets ANativeWindow object.

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

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

  8.  */
  9. status_t CameraHal::setPreviewWindow(struct preview_stream_ops *window)
  10. {
  11.     status_t ret = NO_ERROR;
  12.     CameraAdapter::BuffersDescriptor desc;

  13.     LOG_FUNCTION_NAME;
  14.     mSetPreviewWindowCalled = true;

  15.    ///If the Camera service passes a null window, we destroy existing window and free the DisplayAdapter
  16.     if(!window)//这种情况下,window是null,表示不采用overlay方式,则不需要新建displayadapter
  17.     {
  18.         if(mDisplayAdapter.get() != NULL)
  19.         {
  20.             ///NULL window passed, destroy the display adapter if present
  21.             CAMHAL_LOGD("NULL window passed, destroying display adapter");
  22.             mDisplayAdapter.clear();
  23.             ///@remarks If there was a window previously existing, we usually expect another valid window to be passed by the client
  24.             ///@remarks so, we will wait until it passes a valid window to begin the preview again
  25.             mSetPreviewWindowCalled = false;
  26.         }
  27.         CAMHAL_LOGD("NULL ANativeWindow passed to setPreviewWindow");
  28.         return NO_ERROR;
  29.     }else if(mDisplayAdapter.get() == NULL)//传入的window不是null,但是还没有未使用overlay方式创建displayadapter,创建displayadapter
  30.     {
  31.         // Need to create the display adapter since it has not been created
  32.         // Create display adapter
  33.         mDisplayAdapter = new ANativeWindowDisplayAdapter();
  34.         ret = NO_ERROR;
  35.         if(!mDisplayAdapter.get() || ((ret=mDisplayAdapter->initialize())!=NO_ERROR))
  36.         {
  37.             if(ret!=NO_ERROR)
  38.             {
  39.                 mDisplayAdapter.clear();
  40.                 CAMHAL_LOGEA("DisplayAdapter initialize failed");
  41.                 LOG_FUNCTION_NAME_EXIT;
  42.                 return ret;
  43.             }
  44.             else
  45.             {
  46.                 CAMHAL_LOGEA("Couldn't create DisplayAdapter");
  47.                 LOG_FUNCTION_NAME_EXIT;
  48.                 return NO_MEMORY;
  49.             }
  50.         }

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

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

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

  64.         if(mPreviewStartInProgress)
  65.         {
  66.             CAMHAL_LOGDA("setPreviewWindow called when preview running");
  67.             // Start the preview since the window is now available
  68.             ret = startPreview();
  69.         }
  70.     } else {//传入的window不是null,并且displaadaper已经创建好,那么这里只需要将新的window与已经创建好的displayadapter关联即可
  71.         // Update the display adapter with the new window that is passed from CameraService
  72.         ret = mDisplayAdapter->setPreviewWindow(window);
  73.         if ( (NO_ERROR == ret) && previewEnabled() ) {
  74.             restartPreview();
  75.         } else if (ret == ALREADY_EXISTS) {
  76.             // ALREADY_EXISTS should be treated as a noop in this case
  77.             ret = NO_ERROR;
  78.         }
  79.     }
  80.     LOG_FUNCTION_NAME_EXIT;

  81.     return ret;

  82. }
这里我们重点看看新建displayadapter的过程:
1.实例化一个 ANativeWindowDisplayAdapter 对象
2. mDisplayAdapter - > initialize ( )
3. mDisplayAdapter - > setFrameProvider ( mCameraAdapter )//这一步是关键,之后会遇到的
4.
mDisplayAdapter - > setErrorHandler ( mAppCallbackNotifier . get ( ) )
5. mDisplayAdapter - > setPreviewWindow ( window ) ;
做完了上面这些步骤之后,就是startpreview了
  1. /**
  2.    @brief Start preview mode.

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

  6.  */
  7. status_t CameraHal::startPreview() {
  8.     LOG_FUNCTION_NAME;

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

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

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

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

  40. #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
  41.         ret = mDisplayAdapter->enableDisplay(width, height, &mStartPreview);
  42. #else
  43.         ret = mDisplayAdapter->enableDisplay(width, height, NULL);
  44. #endif

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

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

  55.             goto error;
  56.         }

  57.     }

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

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

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

  66.     mPreviewEnabled = true;
  67.     mPreviewStartInProgress = false;
  68.     return ret;

  69.     error:

  70.         CAMHAL_LOGEA("Performing cleanup after error");

  71.         //Do all the cleanup
  72.         freePreviewBufs();
  73.         mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_PREVIEW);
  74.         if(mDisplayAdapter.get() != NULL) {
  75.             mDisplayAdapter->disableDisplay(false);
  76.         }
  77.         mAppCallbackNotifier->stop();
  78.         mPreviewStartInProgress = false;
  79.         mPreviewEnabled = false;
  80.         LOG_FUNCTION_NAME_EXIT;

  81.         return ret;
  82. }
上面标出的 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,下面看看他的具体是实现
  1. status_t V4LCameraAdapter::startPreview()
  2. {
  3.     status_t ret = NO_ERROR;

  4.     LOG_FUNCTION_NAME;
  5.     Mutex::Autolock lock(mPreviewBufsLock);

  6.     if(mPreviewing) {
  7.         ret = BAD_VALUE;
  8.         goto EXIT;
  9.     }

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

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

  14.         ret = v4lIoctl(mCameraHandle, VIDIOC_QBUF, &mVideoInfo->buf);//请求分配内存
  15.         if (ret < 0) {
  16.             CAMHAL_LOGEA("VIDIOC_QBUF Failed");
  17.             goto EXIT;
  18.         }
  19.         nQueued++;
  20.     }

  21.     ret = v4lStartStreaming();

  22.     // Create and start preview thread for receiving buffers from V4L Camera
  23.     if(!mCapturing) {
  24.         mPreviewThread = new PreviewThread(this);//开启PreviewThread
  25.         CAMHAL_LOGDA("Created preview thread");
  26.     }

  27.     //Update the flag to indicate we are previewing
  28.     mPreviewing = true;
  29.     mCapturing = false;

  30. EXIT:
  31.     LOG_FUNCTION_NAME_EXIT;
  32.     return ret;
  33. }
  1. int V4LCameraAdapter::previewThread()
  2. {
  3.     status_t ret = NO_ERROR;
  4.     int width, height;
  5.     CameraFrame frame;
  6.     void *y_uv[2];
  7.     int index = 0;
  8.     int stride = 4096;
  9.     char *fp = NULL;

  10.     mParams.getPreviewSize(&width, &height);

  11.     if (mPreviewing) {

  12.         fp = this->GetFrame(index);
  13.         if(!fp) {
  14.             ret = BAD_VALUE;
  15.             goto EXIT;
  16.         }
  17.         CameraBuffer *buffer = mPreviewBufs.keyAt(index);//获取camerabuffer
  18.         CameraFrame *lframe = (CameraFrame *)mFrameQueue.valueFor(buffer);//获取cameraframe
  19.         if (!lframe) {
  20.             ret = BAD_VALUE;
  21.             goto EXIT;
  22.         }

  23.         debugShowFPS();

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

  33. #ifdef SAVE_RAW_FRAMES
  34.         unsigned char* nv12_buff = (unsigned char*) malloc(width*height*3/2);
  35.         //Convert yuv422i to yuv420sp(NV12) & dump the frame to a file
  36.         convertYUV422ToNV12 ( (unsigned char*)fp, nv12_buff, width, height);
  37.         saveFile( nv12_buff, ((width*height)*3/2) );//if you want to save the data,save it
  38.         free (nv12_buff);
  39. #endif
  40.         //填充frame结构,用于数据处理
  41.         frame.mFrameType = CameraFrame::PREVIEW_FRAME_SYNC;
  42.         frame.mBuffer = buffer;
  43.         frame.mLength = width*height*3/2;
  44.         frame.mAlignment = stride;
  45.         frame.mOffset = 0;
  46.         frame.mTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
  47.         frame.mFrameMask = (unsigned int)CameraFrame::PREVIEW_FRAME_SYNC;

  48.         if (mRecording)
  49.         {
  50.             frame.mFrameMask |= (unsigned int)CameraFrame::VIDEO_FRAME_SYNC;
  51.             mFramesWithEncoder++;
  52.         }
  53.     
  54.         //这里是重点,数据回调,或者使用overlay方式显示这里是决定性调用
  55.         ret = setInitFrameRefCount(frame.mBuffer, frame.mFrameMask);
  56.         if (ret != NO_ERROR) {
  57.             CAMHAL_LOGDB("Error in setInitFrameRefCount %d", ret);
  58.         } else {
  59.             ret = sendFrameToSubscribers(&frame);
  60.         }
  61.     }
  62. EXIT:

  63.     return ret;
  64. }
现在就开始看看setInitFrameCount方法都做了些什么
  1. int BaseCameraAdapter::setInitFrameRefCount(CameraBuffer * buf, unsigned int mask)
  2. {
  3.   int ret = NO_ERROR;
  4.   unsigned int lmask;

  5.   LOG_FUNCTION_NAME;

  6.   if (buf == NULL)
  7.     {
  8.       return -EINVAL;
  9.     }

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

  13.       case CameraFrame::IMAGE_FRAME:
  14.         {
  15.           setFrameRefCount(buf, CameraFrame::IMAGE_FRAME, (int) mImageSubscribers.size());
  16.         }
  17.         break;
  18.       case CameraFrame::RAW_FRAME:
  19.         {
  20.           setFrameRefCount(buf, CameraFrame::RAW_FRAME, mRawSubscribers.size());
  21.         }
  22.         break;
  23.       case CameraFrame::PREVIEW_FRAME_SYNC:
  24.         {
  25.           setFrameRefCount(buf, CameraFrame::PREVIEW_FRAME_SYNC, mFrameSubscribers.size());//这里这个mFrameSubscribers对应的key上保存着响应的callback方法
  26.         }
  27.         break;
  28.       case CameraFrame::SNAPSHOT_FRAME:
  29.         {
  30.           setFrameRefCount(buf, CameraFrame::SNAPSHOT_FRAME, mSnapshotSubscribers.size());
  31.         }
  32.         break;
  33.       case CameraFrame::VIDEO_FRAME_SYNC:
  34.         {
  35.           setFrameRefCount(buf,CameraFrame::VIDEO_FRAME_SYNC, mVideoSubscribers.size());
  36.         }
  37.         break;
  38.       case CameraFrame::FRAME_DATA_SYNC:
  39.         {
  40.           setFrameRefCount(buf, CameraFrame::FRAME_DATA_SYNC, mFrameDataSubscribers.size());
  41.         }
  42.         break;
  43.       case CameraFrame::REPROCESS_INPUT_FRAME:
  44.         {
  45.           setFrameRefCount(buf,CameraFrame::REPROCESS_INPUT_FRAME, mVideoInSubscribers.size());
  46.         }
  47.         break;
  48.       default:
  49.         CAMHAL_LOGEB("FRAMETYPE NOT SUPPORTED 0x%x", lmask);
  50.         break;
  51.       }//SWITCH
  52.       mask &= ~lmask;
  53.     }//IF
  54.   }//FOR
  55.   LOG_FUNCTION_NAME_EXIT;
  56.   return ret;
  57. }
上面我标注的部分通过enableMsgType方法实现mFrameSubscribers.add的,经callback添加到对应的key处,算是实现关联,
同样的通过disableMsgType方法实现mFrameSubscribers.removeItem的,具体在哪里调用 enableMsgType和disableMsgType之后再给予说明
  1. void BaseCameraAdapter::setFrameRefCount(CameraBuffer * frameBuf, CameraFrame::FrameType frameType, int refCount)
  2. {

  3.     LOG_FUNCTION_NAME;

  4.     switch ( frameType )
  5.         {
  6.         case CameraFrame::IMAGE_FRAME:
  7.         case CameraFrame::RAW_FRAME:
  8.                 {
  9.                 Mutex::Autolock lock(mCaptureBufferLock);
  10.                 mCaptureBuffersAvailable.replaceValueFor(frameBuf, refCount);
  11.                 }
  12.             break;
  13.         case CameraFrame::SNAPSHOT_FRAME:
  14.                 {
  15.                 Mutex::Autolock lock(mSnapshotBufferLock);
  16.                 mSnapshotBuffersAvailable.replaceValueFor( ( unsigned int ) frameBuf, refCount);
  17.                 }
  18.             break;
  19.         case CameraFrame::PREVIEW_FRAME_SYNC:
  20.                 {
  21.                 Mutex::Autolock lock(mPreviewBufferLock)
  22.                 mPreviewBuffersAvailable.replaceValueFor(frameBuf, refCount);//这里我的理解是refCount和frameBuf实现了绑定,即camerabuf保存在mPreviewBuffersAvailable对应的key处
  23.                 }
  24.             break;
  25.         case CameraFrame::FRAME_DATA_SYNC:
  26.                 {
  27.                 Mutex::Autolock lock(mPreviewDataBufferLock);
  28.                 mPreviewDataBuffersAvailable.replaceValueFor(frameBuf, refCount);
  29.                 }
  30.             break;
  31.         case CameraFrame::VIDEO_FRAME_SYNC:
  32.                 {
  33.                 Mutex::Autolock lock(mVideoBufferLock);
  34.                 mVideoBuffersAvailable.replaceValueFor(frameBuf, refCount);
  35.                 }
  36.             break;
  37.         case CameraFrame::REPROCESS_INPUT_FRAME: {
  38.             Mutex::Autolock lock(mVideoInBufferLock);
  39.             mVideoInBuffersAvailable.replaceValueFor(frameBuf, refCount);
  40.         }
  41.             break;
  42.         default:
  43.             break;
  44.         };

  45.     LOG_FUNCTION_NAME_EXIT;

  46. }
接下我们看看 sendFrameToSubscribers方法的具体实现过程
  1. status_t BaseCameraAdapter::sendFrameToSubscribers(CameraFrame *frame)
  2. {
  3.     status_t ret = NO_ERROR;
  4.     unsigned int mask;

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

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

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

  56.         if (ret != NO_ERROR) {
  57.             goto EXIT;
  58.         }
  59.       }//IF
  60.     }//FOR

  61.  EXIT:
  62.     return ret;
  63. }
  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.     frame->mFrameType = frameType;

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

  22.     if (NULL != subscribers) {
  23.         refCount = getFrameRefCount(frame->mBuffer, frameType);//通过这个refCount可以找到对应的callback方法

  24.         if (refCount == 0) {
  25.             CAMHAL_LOGDA("Invalid ref count of 0");
  26.             return -EINVAL;
  27.         }

  28.         if (refCount > subscribers->size()) {
  29.             CAMHAL_LOGEB("Invalid ref count for frame type: 0x%x", frameType);
  30.             return -EINVAL;
  31.         }

  32.         CAMHAL_LOGVB("Type of Frame: 0x%x address: 0x%x refCount start %d",
  33.                      frame->mFrameType,
  34.                      ( uint32_t ) frame->mBuffer,
  35.                      refCount);

  36.         for ( unsigned int i = 0 ; i < refCount; i++ ) {
  37.             frame->mCookie = ( void * ) subscribers->keyAt(i);
  38.             callback = (frame_callback) subscribers->valueAt(i);

  39.             if (!callback) {
  40.                 CAMHAL_LOGEB("callback not set for frame type: 0x%x", frameType);
  41.                 return -EINVAL;
  42.             }

  43.             callback(frame);
  44.         }
  45.     } else {
  46.         CAMHAL_LOGEA("Subscribers is null??");
  47.         return -EINVAL;
  48.     }

  49.     return ret;
  50. }
这里别的我们先暂且不分析,但是callback到底是从哪里来的,这个我们必须说清楚
上面在实例化displayadapter时有这样一步: 3. mDisplayAdapter - > setFrameProvider ( mCameraAdapter )//这一步是关键,之后会遇到的
我们看看setFrameProvider这个方法的实现:
  1. int ANativeWindowDisplayAdapter::setFrameProvider(FrameNotifier *frameProvider)
  2. {
  3.     LOG_FUNCTION_NAME;

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

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

  14.     /** Dont do anything here, Just save the pointer for use when display is
  15.          actually enabled or disabled
  16.     */
  17.     mFrameProvider = new FrameProvider(frameProvider, this, frameCallbackRelay);//实例化一个FrameProvider,这其中有一个参数非常重要:frameCallbackRelay,他的定义在下面给出

  18.     LOG_FUNCTION_NAME_EXIT;

  19.     return NO_ERROR;
  20. }
  1. void ANativeWindowDisplayAdapter::frameCallbackRelay(CameraFrame* caFrame)
  2. {

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

  19. }
  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. status_t CameraHal::cameraPreviewInitialization()
  12. {

  13.     status_t ret = NO_ERROR;
  14.     CameraAdapter::BuffersDescriptor desc;
  15.     CameraFrame frame;
  16.     unsigned int required_buffer_count;
  17.     unsigned int max_queueble_buffers;

  18. #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
  19.         gettimeofday(&mStartPreview, NULL);
  20. #endif

  21.     LOG_FUNCTION_NAME;

  22.     if (mPreviewInitializationDone) {
  23.         return NO_ERROR;
  24.     }

  25.     if ( mPreviewEnabled ){
  26.       CAMHAL_LOGDA("Preview already running");
  27.       LOG_FUNCTION_NAME_EXIT;
  28.       return ALREADY_EXISTS;
  29.     }

  30.     if ( NULL != mCameraAdapter ) {
  31.       ret = mCameraAdapter->setParameters(mParameters);
  32.     }

  33.     if ((mPreviewStartInProgress == false) && (mDisplayPaused == false)){
  34.       ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_QUERY_RESOLUTION_PREVIEW,( int ) &frame);
  35.       if ( NO_ERROR != ret ){
  36.         CAMHAL_LOGEB("Error: CAMERA_QUERY_RESOLUTION_PREVIEW %d", ret);
  37.         return ret;
  38.       }

  39.       ///Update the current preview width and height
  40.       mPreviewWidth = frame.mWidth;
  41.       mPreviewHeight = frame.mHeight;
  42.     }

  43.     ///If we don't have the preview callback enabled and display adapter,
  44.     if(!mSetPreviewWindowCalled || (mDisplayAdapter.get() == NULL)){
  45.       CAMHAL_LOGD("Preview not started. Preview in progress flag set");
  46.       mPreviewStartInProgress = true;
  47.       ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_SWITCH_TO_EXECUTING);
  48.       if ( NO_ERROR != ret ){
  49.         CAMHAL_LOGEB("Error: CAMERA_SWITCH_TO_EXECUTING %d", ret);
  50.         return ret;
  51.       }
  52.       return NO_ERROR;
  53.     }

  54.     if( (mDisplayAdapter.get() != NULL) && ( !mPreviewEnabled ) && ( mDisplayPaused ) )
  55.         {
  56.         CAMHAL_LOGDA("Preview is in paused state");

  57.         mDisplayPaused = false;
  58.         mPreviewEnabled = true;
  59.         if ( NO_ERROR == ret )
  60.             {
  61.             ret = mDisplayAdapter->pauseDisplay(mDisplayPaused);

  62.             if ( NO_ERROR != ret )
  63.                 {
  64.                 CAMHAL_LOGEB("Display adapter resume failed %x", ret);
  65.                 }
  66.             }
  67.         //restart preview callbacks
  68.         if(mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)
  69.         {
  70.             mAppCallbackNotifier->enableMsgType (CAMERA_MSG_PREVIEW_FRAME);
  71.         }

  72.         signalEndImageCapture();
  73.         return ret;
  74.         }

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

  76.     ///Allocate the preview buffers
  77.     ret = allocPreviewBufs(mPreviewWidth, mPreviewHeight, mParameters.getPreviewFormat(), required_buffer_count, max_queueble_buffers);

  78.     if ( NO_ERROR != ret )
  79.         {
  80.         CAMHAL_LOGEA("Couldn't allocate buffers for Preview");
  81.         goto error;
  82.         }

  83.     if ( mMeasurementEnabled )
  84.         {

  85.         ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_QUERY_BUFFER_SIZE_PREVIEW_DATA,
  86.                                           ( int ) &frame,
  87.                                           required_buffer_count);
  88.         if ( NO_ERROR != ret )
  89.             {
  90.             return ret;
  91.             }

  92.          ///Allocate the preview data buffers
  93.         ret = allocPreviewDataBufs(frame.mLength, required_buffer_count);
  94.         if ( NO_ERROR != ret ) {
  95.             CAMHAL_LOGEA("Couldn't allocate preview data buffers");
  96.             goto error;
  97.            }

  98.         if ( NO_ERROR == ret )
  99.             {
  100.             desc.mBuffers = mPreviewDataBuffers;
  101.             desc.mOffsets = mPreviewDataOffsets;
  102.             desc.mFd = mPreviewDataFd;
  103.             desc.mLength = mPreviewDataLength;
  104.             desc.mCount = ( size_t ) required_buffer_count;
  105.             desc.mMaxQueueable = (size_t) required_buffer_count;

  106.             mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_PREVIEW_DATA,
  107.                                         ( int ) &desc);
  108.             }

  109.         }

  110.     ///Pass the buffers to Camera Adapter
  111.     desc.mBuffers = mPreviewBuffers;
  112.     desc.mOffsets = mPreviewOffsets;
  113.     desc.mFd = mPreviewFd;
  114.     desc.mLength = mPreviewLength;
  115.     desc.mCount = ( size_t ) required_buffer_count;
  116.     desc.mMaxQueueable = (size_t) max_queueble_buffers;

  117.     ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_PREVIEW,
  118.                                       ( int ) &desc);

  119.     if ( NO_ERROR != ret )
  120.         {
  121.         CAMHAL_LOGEB("Failed to register preview buffers: 0x%x", ret);
  122.         freePreviewBufs();
  123.         return ret;
  124.         }

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

  126.     ///Start the callback notifier
  127.     ret = mAppCallbackNotifier->start();

  128.     if( ALREADY_EXISTS == ret )
  129.         {
  130.         //Already running, do nothing
  131.         CAMHAL_LOGDA("AppCallbackNotifier already running");
  132.         ret = NO_ERROR;
  133.         }
  134.     else if ( NO_ERROR == ret ) {
  135.         CAMHAL_LOGDA("Started AppCallbackNotifier..");
  136.         mAppCallbackNotifier->setMeasurements(mMeasurementEnabled);
  137.         }
  138.     else
  139.         {
  140.         CAMHAL_LOGDA("Couldn't start AppCallbackNotifier");
  141.         goto error;
  142.         }

  143.     if (ret == NO_ERROR) mPreviewInitializationDone = true;
  144.     return ret;

  145.     error:

  146.         CAMHAL_LOGEA("Performing cleanup after error");

  147.         //Do all the cleanup
  148.         freePreviewBufs();
  149.         mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_PREVIEW);
  150.         if(mDisplayAdapter.get() != NULL)
  151.             {
  152.             mDisplayAdapter->disableDisplay(false);
  153.             }
  154.         mAppCallbackNotifier->stop();
  155.         mPreviewStartInProgress = false;
  156.         mPreviewEnabled = false;
  157.         LOG_FUNCTION_NAME_EXIT;

  158.         return ret;
  159. }
我们就看看这个方法的是实现吧: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.     if( msgType & CAMERA_MSG_POSTVIEW_FRAME ) {
  7.         mFrameProvider->enableFrameNotification(CameraFrame::SNAPSHOT_FRAME);
  8.     }

  9.     if(msgType & CAMERA_MSG_RAW_IMAGE) {
  10.         mFrameProvider->enableFrameNotification(CameraFrame::RAW_FRAME);
  11.     }

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

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

  7.     LOG_FUNCTION_NAME_EXIT;
  8.     return ret;
  9. }
这里这个 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.     LOG_FUNCTION_NAME;

  5.     int32_t frameMsg = ((msgs >> MessageNotifier::FRAME_BIT_FIELD_POSITION) & EVENT_MASK);
  6.     int32_t eventMsg = ((msgs >> MessageNotifier::EVENT_BIT_FIELD_POSITION) & EVENT_MASK);

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

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

  53.     LOG_FUNCTION_NAME_EXIT;
  54. }
这里通过 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.     ///@todo Do cropping based on the stabilized frame coordinates
  9.     ///@todo Insert logic to drop frames here based on refresh rate of
  10.     ///display or rendering rate whichever is lower
  11.     ///Queue the buffer to overlay

  12.     if ( NULL == mANativeWindow ) {
  13.         return NO_INIT;
  14.     }

  15.     if (!mBuffers || !dispFrame.mBuffer) {
  16.         CAMHAL_LOGEA("NULL sent to PostFrame");
  17.         return BAD_VALUE;
  18.     }

  19.     for ( i = 0; i < mBufferCount; i++ )
  20.         {
  21.         if ( dispFrame.mBuffer == &mBuffers[i] )
  22.             {
  23.             break;
  24.         }
  25.     }


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

  27.     if ( mDisplayState == ANativeWindowDisplayAdapter::DISPLAY_STARTED &&
  28.                 (!mPaused || CameraFrame::CameraFrame::SNAPSHOT_FRAME == dispFrame.mType) &&
  29.                 !mSuspend)
  30.     {
  31.         Mutex::Autolock lock(mLock);
  32.         uint32_t xOff = (dispFrame.mOffset% PAGE_SIZE);
  33.         uint32_t yOff = (dispFrame.mOffset / PAGE_SIZE);

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

  56.             CAMHAL_LOGVB(" crop.left = %d crop.top = %d crop.right = %d crop.bottom = %d",
  57.                           xOff/bytesPerPixel, yOff , (xOff/bytesPerPixel)+mPreviewWidth, yOff+mPreviewHeight);
  58.             // We'll ignore any errors here, if the surface is
  59.             // already invalid, we'll know soon enough.
  60.             mANativeWindow->set_crop(mANativeWindow, xOff/bytesPerPixel, yOff,
  61.                                      (xOff/bytesPerPixel)+mPreviewWidth, yOff+mPreviewHeight);

  62.             ///Update the current x and y offsets
  63.             mXOff = xOff;
  64.             mYOff = yOff;
  65.         }

  66.         {
  67.             buffer_handle_t *handle = (buffer_handle_t *) mBuffers[i].opaque;
  68.             // unlock buffer before sending to display
  69.             mapper.unlock(*handle);
  70.             ret = mANativeWindow->enqueue_buffer(mANativeWindow, handle);
  71.         }
  72.         if ( NO_ERROR != ret ) {
  73.             CAMHAL_LOGE("Surface::queueBuffer returned error %d", ret);
  74.         }

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


  76.         // HWComposer has not minimum buffer requirement. We should be able to dequeue
  77.         // the buffer immediately
  78.         TIUTILS::Message msg;
  79.         mDisplayQ.put(&msg);


  80. #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS

  81.         if ( mMeasureStandby )
  82.             {
  83.             CameraHal::PPM("Standby to first shot: Sensor Change completed - ", &mStandbyToShot);
  84.             mMeasureStandby = false;
  85.             }
  86.         else if (CameraFrame::CameraFrame::SNAPSHOT_FRAME == dispFrame.mType)
  87.             {
  88.             CameraHal::PPM("Shot to snapshot: ", &mStartCapture);
  89.             mShotToShot = true;
  90.             }
  91.         else if ( mShotToShot )
  92.             {
  93.             CameraHal::PPM("Shot to shot: ", &mStartCapture);
  94.             mShotToShot = false;
  95.         }
  96. #endif

  97.     }
  98.     else
  99.     {
  100.         Mutex::Autolock lock(mLock);
  101.         buffer_handle_t *handle = (buffer_handle_t *) mBuffers[i].opaque;

  102.         // unlock buffer before giving it up
  103.         mapper.unlock(*handle);

  104.         // cancel buffer and dequeue another one
  105.         ret = mANativeWindow->cancel_buffer(mANativeWindow, handle);
  106.         if ( NO_ERROR != ret ) {
  107.             CAMHAL_LOGE("Surface::cancelBuffer returned error %d", ret);
  108.         }

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

  110.         TIUTILS::Message msg;
  111.         mDisplayQ.put(&msg);
  112.         ret = NO_ERROR;
  113.     }

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

待续。。。。。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值