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

来源:互联网 发布:淘宝网 网银支付 编辑:程序博客网 时间:2024/05/29 08:28
 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 surfacein 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 needto save the holderfor later use, even when the mCameraDevice
  9.         //isnull. This could happenif onResume()is invoked after this
  10.         //function.
  11.         mSurfaceHolder = holder;

  12.         // The mCameraDevice will benullif it failsto connectto the camera
  13.         // hardware.In thiscase we will show a dialogandthen finish the
  14.         // activity, so it's OKto ignore it.
  15.         if (mCameraDevice==null) return;

  16.         // Sometimes surfaceChangedis called after onPauseor before onResume.
  17.         // Ignore it.
  18.         if (mPausing|| isFinishing()) return;

  19.         setSurfaceLayout();

  20.         //Set preview displayif the surface is being created. Preview was
  21.         // already started. Also restart the previewif display rotation has
  22.         // changed. Sometimes this happens when the deviceis heldin portrait
  23.         //and camera appis opened. Rotation animation takes sometimeand
  24.         // display rotationin onCreate maynot 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 displayif the surface is being createdand preview
  34.                 // was already started. That means preview display wassetto null
  35.                 //and we needtoset it now.
  36.                 setPreviewDisplay(holder);
  37.             }
  38.         }

  39.         //If firsttime initializationisnot finished, send a messagetodo
  40.         // it later. We wantto finish surfaceChanged as soon as possibleto 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 modeis continuous autofocus,call cancelAutoFocus to
  12.             //resume it because it may have been paused by autoFocuscall.
  13.             if (Parameters.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mFocusManager.getFocusMode())){
  14.                 mCameraDevice.cancelAutoFocus();
  15.             }
  16.             mFocusManager.setAeAwbLock(false);// Unlock AEand 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 mainthreadto goon 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. Defineerror codesfor 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 anullwindow, we destroy existingwindowand free the DisplayAdapter
  16.     if(!window)//这种情况下,window是null,表示不采用overlay方式,则不需要新建displayadapter
  17.     {
  18.         if(mDisplayAdapter.get()!=NULL)
  19.         {
  20.             ///NULLwindow passed, destroy the display adapterif present
  21.             CAMHAL_LOGD("NULL window passed, destroying display adapter");
  22.             mDisplayAdapter.clear();
  23.             ///@remarksIf there was awindow previously existing, we usually expect another validwindowto be passed by the client
  24.             ///@remarks so, we will waituntil 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.     }elseif(mDisplayAdapter.get()==NULL)//传入的window不是null,但是还没有未使用overlay方式创建displayadapter,创建displayadapter
  30.     {
  31.         // Needto create the display adapter since it hasnot 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 needsto know wheretoget the CameraFrames from inorderto display
  52.         // Since CameraAdapteris 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 usecase hasto be propagated backto the application
  55.         // via CAMERA_MSG_ERROR. AppCallbackNotifieris theclass that notifies such errorsto the application
  56.         //Set it as theerror handlerfor the DisplayAdapter
  57.         mDisplayAdapter->setErrorHandler(mAppCallbackNotifier.get());

  58.         // Update the display adapter with the newwindow thatis 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 thewindowis now available
  68.             ret = startPreview();
  69.         }
  70.     } else {//传入的window不是null,并且displaadaper已经创建好,那么这里只需要将新的window与已经创建好的displayadapter关联即可
  71.         // Update the display adapter with the newwindow thatis passed from CameraService
  72.         ret = mDisplayAdapter->setPreviewWindow(window);
  73.         if ((NO_ERROR== ret)&& previewEnabled()){
  74.             restartPreview();
  75.         } elseif(ret == ALREADY_EXISTS){
  76.             // ALREADY_EXISTS should be treated as a noopin thiscase
  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 tunnelingis enabled during VTC, startPreview happensin 2 steps:
  10.     // When the application sends the command CAMERA_CMD_PREVIEW_INITIALIZATION,
  11.     // cameraPreviewInitialization()is called, whichin turn causes the CameraAdapter
  12.     // to move from loaded to idle state.And when the application calls startPreview,
  13.     // the CameraAdapter moves from idleto executing state.
  14.     //
  15.     // If the application calls startPreview() without sending the command
  16.     // CAMERA_CMD_PREVIEW_INITIALIZATION,then thefunction 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 idleto executing statein one shot.
  20.     status_t ret = cameraPreviewInitialization();

  21.     // The flag mPreviewInitializationDoneisset to true at the end of the function
  22.     // cameraPreviewInitialization(). Therefore,if everything goes alright,then the
  23.     // flag will beset. Sometimes, thefunction cameraPreviewInitialization() may
  24.     // return prematurelyif all the resources arenot 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 welland should
  27.     // not continue execution. That is why, we check the flag and not the return value.
  28.     if (!mPreviewInitializationDone) return ret;

  29.     // Once startPreviewis called, thereis no needto continueto remember whether
  30.     // thefunction cameraPreviewInitialization() was called earlierornot.And so
  31.     // the flag mPreviewInitializationDoneis reset here. Plus, this preserves the
  32.     // current behavior of startPreview under the circumstances where the application
  33.     // calls startPreview twiceor more.
  34.     mPreviewInitializationDone = false;

  35.     ///Enable the display adapterif 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 mStateSwitchLockis lockedand unlockis supposedto be called
  48.             // only from mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_PREVIEW)
  49.             // below. But this will never happen because of gotoerror. Thus atnext
  50.             // startPreview()call CameraHAL will be deadlocked.
  51.             // Needto revisit mStateSwitch lock,fornow 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 commandto 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.     // Createand start preview threadfor receiving buffers from V4L Camera
  23.     if(!mCapturing){
  24.         mPreviewThread = new PreviewThread(this);//开启PreviewThread
  25.         CAMHAL_LOGDA("Created preview thread");
  26.     }

  27.     //Update the flagto 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 yuv422ito 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 |= (unsignedint)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, unsignedint 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(( unsignedint) 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 ( unsignedint 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.     // CheckforNULL 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.     /** Dontdo anything here, Just save the pointerfor 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 overlayin 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 Adapterset params
  5.           -> Allocate buffers
  6.           ->Set use buffersfor 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 widthand height
  40.       mPreviewWidth = frame.mWidth;
  41.       mPreviewHeight = frame.mHeight;
  42.     }

  43.     ///If we don't have the preview callback enabledand 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 buffersto 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,donothing
  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 notificationto 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.     ///@todoDo cropping basedon the stabilized frame coordinates
  9.     ///@todo Insert logicto drop frames here basedon refresh rate of
  10.     ///displayor rendering rate whicheveris lower
  11.     ///Queue the bufferto 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 onlyif current xand y offsetsdonot 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 basedon 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 surfaceis
  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 xand 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 sendingto 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 hasnot minimum buffer requirement. We should be ableto 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 bufferand 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. }
这个显示的过程相对来说还是比较复杂的,之后还需要花点时间研究一下

待续。。。。。