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

简介:

http://blog.chinaunix.net/uid-26215986-id-3573400.html


这里为什么要研究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. }
这个显示的过程相对来说还是比较复杂的,之后还需要花点时间研究一下

相关文章
|
22天前
|
Java 开发工具 Android开发
安卓与iOS开发环境对比分析
【7月更文挑战第4天】在移动应用开发的广阔天地中,安卓和iOS两大平台各据一方,引领着技术潮流。本文将深入探讨这两个平台的开发环境,从编程语言、工具链到市场分布等多个维度进行比较。我们将揭示各自的优势与局限,并分析开发者如何在这两个不同的生态系统中做出选择。通过本文,读者将获得一个全面的视角,理解两大平台在开发实践中的差异性及其对项目成功的影响。
|
3天前
|
IDE 开发工具 Android开发
安卓与iOS开发环境对比分析
在移动应用开发的广阔舞台上,安卓与iOS这两大操作系统各占半壁江山。它们在开发环境上的差异,不仅影响了开发者的编码体验,也在一定程度上塑造了应用生态的多样性。本文将深入探讨两者在开发工具、编程语言、用户界面设计以及市场分布等方面的不同特点,为即将踏入这一领域的开发者提供一盏明灯。
|
4天前
|
IDE 开发工具 Android开发
安卓与iOS开发环境的差异性分析
在移动应用开发的广阔舞台上,安卓和iOS两大操作系统各据一方,引领着市场潮流。它们各自拥有独特的开发环境和工具集,为开发者提供了不同的挑战与机遇。本文旨在深入剖析这两个平台的开发环境,通过比较它们的编程语言、集成开发环境(IDE)、用户界面设计、以及系统架构等方面,揭示各自的优势与局限。我们将探讨如何基于这些差异来优化开发策略,并预测未来可能的发展趋势,以期为开发者在选择平台时提供有价值的参考。
|
4天前
|
API 开发工具 Android开发
安卓与iOS开发环境对比分析
移动操作系统的两大巨头,安卓和iOS,各自拥有独特的开发环境和工具。本文将深入探讨两者的开发环境差异,从编程语言、开发工具、用户界面设计、API支持以及生态系统五个维度进行比较分析。通过数据支撑和案例研究,揭示各自的优势和局限性,为开发者选择适合自己项目需求的平台提供参考依据。
13 1
|
7天前
|
Java Android开发 iOS开发
探索安卓与iOS开发的差异:平台特性与用户体验的对比分析
【7月更文挑战第19天】在移动开发的广阔天地中,安卓与iOS两大阵营各据一方,它们在开发环境、用户界面设计、性能优化等方面展现出独特的魅力与挑战。本文旨在深入探讨这两个平台在技术开发和用户体验上的根本差异,并分析这些差异如何影响开发者的策略和最终用户的选择。通过比较两者的编程语言、工具、框架以及设计理念,我们将揭示各自平台的优势与局限,为开发者提供实用的参考,并为消费者呈现一个更加清晰的平台选择视角。
|
10天前
|
开发工具 Android开发 Swift
安卓与iOS开发环境对比分析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自占据半壁江山。本文深入探讨了这两个操作系统的开发环境,从编程语言、开发工具到用户界面设计等多个维度进行比较。通过丰富的数据支持和案例研究,揭示了不同平台的优势与挑战,为开发者提供了宝贵的参考信息。
|
9天前
|
安全 开发工具 Android开发
安卓与iOS开发环境对比分析
本文通过深入探讨和比较安卓与iOS两大主流移动操作系统的开发环境,旨在为开发者提供一个全面的视角。我们将从开发工具、编程语言、用户界面设计、性能优化、安全性考量等多个维度进行细致分析,揭示各自平台的优势与挑战。通过统计数据支持的实证研究,本文将展示两个系统在实际应用中的技术差异及其对项目开发周期的影响,并基于市场数据评估各自的商业潜力。
15 1
|
13天前
|
Java 开发工具 Android开发
安卓与iOS开发环境对比分析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自占据半壁江山。本文深入探讨了两者的开发环境差异,从编程语言、工具框架到用户群体和市场份额进行了全面比较。通过数据支撑和案例分析,揭示了不同平台的优势与局限,旨在为开发者提供决策参考,同时预测未来发展趋势。
|
15天前
|
API 开发工具 Android开发
安卓与iOS开发环境对比分析
在移动操作系统的两大阵营中,安卓和iOS各占据着重要的地位。本文旨在深入探讨两种系统在开发环境方面的异同,通过对开发工具、语言、框架、API以及生态系统的综合比较,揭示各自在应用开发上的优势与挑战。文章将基于最新的市场数据和技术发展进行论述,以期为开发者提供有价值的参考信息,并预测未来可能的发展趋势。
22 1
|
23天前
|
算法 Java API
Android性能优化面试题经典之ANR的分析和优化
Android ANR发生于应用无法在限定时间内响应用户输入或完成操作。主要条件包括:输入超时(5秒)、广播超时(前台10秒/后台60秒)、服务超时及ContentProvider超时。常见原因有网络、数据库、文件操作、计算任务、UI渲染、锁等待、ContentProvider和BroadcastReceiver的不当使用。分析ANR可借助logcat和traces.txt。主线程执行生命周期回调、Service、BroadcastReceiver等,避免主线程耗时操作
25 3