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

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

备注:转自 - conceptcon-ChinaUnix博客


这里为什么要研究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.  

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

  9.  

  10.         // We need to save the holder for later use, even when the mCameraDevice

  11.         //isnull. This could happen if onResume()is invoked after this

  12.         //function.

  13.         mSurfaceHolder = holder;

  14.  

  15.         // The mCameraDevice will be nullif it fails to connect to the camera

  16.         // hardware.In this case we will show a dialog andthen finish the

  17.         // activity, so it's OK to ignore it.

  18.         if(mCameraDevice ==null) return;

  19.  

  20.         // Sometimes surfaceChanged is called after onPause or before onResume.

  21.         // Ignore it.

  22.         if(mPausing || isFinishing()) return;

  23.  

  24.         setSurfaceLayout();

  25.  

  26.         //Set preview display if the surface is being created. Preview was

  27.         // already started. Also restart the preview if display rotation has

  28.         // changed. Sometimes this happens when the device is held in portrait

  29.         //and camera app is opened. Rotation animation takes some timeand

  30.         // display rotation in onCreate may not be what we want.

  31.         if(mCameraState == PREVIEW_STOPPED){//这里表示第一次打开camera时,那么调用startpreview

  32.             startPreview(true);

  33.             startFaceDetection();

  34.         }else{//这里则表示camera已经打开过程中发生的显示变化,比如横屏竖频转换,所以zheli只需要重新设置previewdisplay

  35.             if(Util.getDisplayRotation(this)!= mDisplayRotation){

  36.                 setDisplayOrientation();

  37.             }

  38.             if(holder.isCreating()){

  39.                 //Set preview display if the surface is being created and preview

  40.                 // was already started. That means preview display was settonull

  41.                 //and we need toset it now.

  42.                 setPreviewDisplay(holder);

  43.             }

  44.         }

  45.  

  46.         //If first time initialization isnot finished, send a message todo

  47.         // it later. We want to finish surfaceChanged as soon as possible tolet

  48.         // user see preview first.

  49.         if(!mFirstTimeInitialized){

  50.             mHandler.sendEmptyMessage(FIRST_TIME_INIT);

  51.         }else{

  52.             initializeSecondTime();

  53.         }

  54.  

  55.         SurfaceView preview =(SurfaceView) findViewById(R.id.camera_preview);

  56.         CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];

  57.         boolean mirror =(info.facing == CameraInfo.CAMERA_FACING_FRONT);

  58.         int displayRotation = Util.getDisplayRotation(this);

  59.         int displayOrientation = Util.getDisplayOrientation(displayRotation, mCameraId);

  60.  

  61.         mTouchManager.initialize(preview.getHeight()/ 3, preview.getHeight()/ 3,

  62.                preview, this, mirror, displayOrientation);

  63.  

  64.     }

从上面代码我们必须知道,在surface发生变化时必须调用setPreviewDisplay,根据之后的学习,在startpreview方式中真正startpreview之前同样要调用setPreviewDisplay,在setPreviewDisplay的方法中完成了很多初始化,也是在这里决定是否使用overlay方式的,我们就先看看startpreview这个方法吧

  1. private void startPreview(boolean updateAll){

  2.         if(mPausing || isFinishing()) return;

  3.  

  4.         mFocusManager.resetTouchFocus();

  5.  

  6.         mCameraDevice.setErrorCallback(mErrorCallback);

  7.  

  8.         //If we're previewing already, stop the preview first (this will blank

  9.         // the screen).

  10.         if(mCameraState != PREVIEW_STOPPED) stopPreview();

  11.  

  12.         setPreviewDisplay(mSurfaceHolder);

  13.         setDisplayOrientation();

  14.  

  15.         if(!mSnapshotOnIdle){

  16.             //If the focus mode is continuous autofocus,call cancelAutoFocus to

  17.             //resume it because it may have been paused by autoFocus call.

  18.             if(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mFocusManager.getFocusMode())){

  19.                 mCameraDevice.cancelAutoFocus();

  20.             }

  21.             mFocusManager.setAeAwbLock(false);// Unlock AE and AWB.

  22.         }

  23.  

  24.         if( updateAll ){

  25.             Log.v(TAG,"Updating all parameters!");

  26.             setCameraParameters(UPDATE_PARAM_INITIALIZE | UPDATE_PARAM_ZOOM | UPDATE_PARAM_PREFERENCE);

  27.         }else{

  28.             setCameraParameters(UPDATE_PARAM_MODE);

  29.         }

  30.  

  31.         //setCameraParameters(UPDATE_PARAM_ALL);

  32.  

  33.         // Inform the mainthread to go on the UI initialization.

  34.         if(mCameraPreviewThread !=null){

  35.             synchronized (mCameraPreviewThread){

  36.                 mCameraPreviewThread.notify();

  37.             }

  38.         }

  39.  

  40.         try {

  41.             Log.v(TAG,"startPreview");

  42.             mCameraDevice.startPreview();

  43.         } catch (Throwable ex){

  44.             closeCamera();

  45.             throw new RuntimeException("startPreview failed", ex);

  46.         }

  47.  

  48.         mZoomState = ZOOM_STOPPED;

  49.         setCameraState(IDLE);

  50.         mFocusManager.onPreviewStarted();

  51.         if( mTempBracketingEnabled ){

  52.             mFocusManager.setTempBracketingState(FocusManager.TempBracketingStates.ACTIVE);

  53.         }

  54.  

  55.         if(mSnapshotOnIdle){

  56.             mHandler.post(mDoSnapRunnable);

  57.         }

  58.     }

上面大家看到了,先调用了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层
spbinder(surface != 0 ? surface->asBinder() : 0);
spwindow(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.  

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

  5.    to render buffers to display.

  6.  

  7.    @param[in]window The ANativeWindow object created by Surface flinger

  8.    @return NO_ERROR If the ANativeWindow object passes validation criteria

  9.    @todo Define validation criteria for ANativeWindow object. Define error codes for scenarios

  10.  

  11.  */

  12. status_t CameraHal::setPreviewWindow(struct preview_stream_ops *window)

  13. {

  14.     status_t ret = NO_ERROR;

  15.     CameraAdapter::BuffersDescriptor desc;

  16.  

  17.     LOG_FUNCTION_NAME;

  18.     mSetPreviewWindowCalled =true;

  19.  

  20.    ///If the Camera service passes a nullwindow, we destroy existing windowand free the DisplayAdapter

  21.     if(!window)//这种情况下,window是null,表示不采用overlay方式,则不需要新建displayadapter

  22.     {

  23.         if(mDisplayAdapter.get()!=NULL)

  24.         {

  25.             ///NULLwindow passed, destroy the display adapter if present

  26.             CAMHAL_LOGD("NULL window passed, destroying display adapter");

  27.             mDisplayAdapter.clear();

  28.             ///@remarks If there was a window previously existing, we usually expect another valid windowto be passed by the client

  29.             ///@remarks so, we will wait until it passes a valid windowto begin the preview again

  30.             mSetPreviewWindowCalled =false;

  31.         }

  32.         CAMHAL_LOGD("NULL ANativeWindow passed to setPreviewWindow");

  33.         return NO_ERROR;

  34.     }elseif(mDisplayAdapter.get()==NULL)//传入的window不是null,但是还没有未使用overlay方式创建displayadapter,创建displayadapter

  35.     {

  36.         // Need to create the display adapter since it has not been created

  37.         // Create display adapter

  38.         mDisplayAdapter = new ANativeWindowDisplayAdapter();

  39.         ret = NO_ERROR;

  40.         if(!mDisplayAdapter.get()||((ret=mDisplayAdapter->initialize())!=NO_ERROR))

  41.         {

  42.             if(ret!=NO_ERROR)

  43.             {

  44.                 mDisplayAdapter.clear();

  45.                 CAMHAL_LOGEA("DisplayAdapter initialize failed");

  46.                 LOG_FUNCTION_NAME_EXIT;

  47.                 return ret;

  48.             }

  49.             else

  50.             {

  51.                 CAMHAL_LOGEA("Couldn't create DisplayAdapter");

  52.                 LOG_FUNCTION_NAME_EXIT;

  53.                 return NO_MEMORY;

  54.             }

  55.         }

  56.  

  57.         // DisplayAdapter needs to know where toget the CameraFrames from inorder to display

  58.         // Since CameraAdapter is the one that provides the frames,set it as the frame provider for DisplayAdapter

  59.         mDisplayAdapter->setFrameProvider(mCameraAdapter);

  60.  

  61.         // Any dynamic errors that happen during the camera use case has to be propagated back to the application

  62.         // via CAMERA_MSG_ERROR. AppCallbackNotifier is the class that  notifies such errors to the application

  63.         //Set it as the error handler for the DisplayAdapter

  64.         mDisplayAdapter->setErrorHandler(mAppCallbackNotifier.get());

  65.  

  66.         // Update the display adapter with the new window that is passed from CameraService

  67.         ret = mDisplayAdapter->setPreviewWindow(window);

  68.         if(ret!=NO_ERROR)

  69.             {

  70.             CAMHAL_LOGEB("DisplayAdapter setPreviewWindow returned error %d", ret);

  71.             }

  72.  

  73.         if(mPreviewStartInProgress)

  74.         {

  75.             CAMHAL_LOGDA("setPreviewWindow called when preview running");

  76.             // Start the preview since the windowisnow available

  77.             ret = startPreview();

  78.         }

  79.     }else{//传入的window不是null,并且displaadaper已经创建好,那么这里只需要将新的window与已经创建好的displayadapter关联即可

  80.         // Update the display adapter with the new window that is passed from CameraService

  81.         ret = mDisplayAdapter->setPreviewWindow(window);

  82.         if((NO_ERROR == ret)&& previewEnabled()){

  83.             restartPreview();

  84.         }elseif(ret == ALREADY_EXISTS){

  85.             // ALREADY_EXISTS should be treated as a noop in this case

  86.             ret = NO_ERROR;

  87.         }

  88.     }

  89.     LOG_FUNCTION_NAME_EXIT;

  90.  

  91.     return ret;

  92.  

  93. }

这里我们重点看看新建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.  

  4.    @param none

  5.    @return NO_ERROR Camera switched to VF mode

  6.    @todo Update function header with the different errors that are possible

  7.  

  8.  */

  9. status_t CameraHal::startPreview(){

  10.     LOG_FUNCTION_NAME;

  11.  

  12.     // When tunneling is enabled during VTC, startPreview happens in 2 steps:

  13.     // When the application sends the command CAMERA_CMD_PREVIEW_INITIALIZATION,

  14.     // cameraPreviewInitialization()is called, which in turn causes the CameraAdapter

  15.     //to move from loaded to idle state.And when the application calls startPreview,

  16.     // the CameraAdapter moves from idle to executing state.

  17.     //

  18.     //If the application calls startPreview() without sending the command

  19.     // CAMERA_CMD_PREVIEW_INITIALIZATION,then the function cameraPreviewInitialization()

  20.     //AND startPreview() are executed.In other words,if the application calls

  21.     // startPreview() without sending the command CAMERA_CMD_PREVIEW_INITIALIZATION,

  22.     //then the CameraAdapter moves from loaded to idle to executing state in one shot.

  23.     status_t ret = cameraPreviewInitialization();

  24.  

  25.     // The flag mPreviewInitializationDone issettotrue at the end of the function

  26.     // cameraPreviewInitialization(). Therefore,if everything goes alright,then the

  27.     // flag will be set. Sometimes, the function cameraPreviewInitialization() may

  28.     // return prematurely if all the resources are not available for starting preview.

  29.     //For example,if the preview windowisnotset,then it would return NO_ERROR.

  30.     // Under such circumstances, one should return from startPreview as well and should

  31.     //not continue execution. That is why, we check the flag andnot the return value.

  32.     if(!mPreviewInitializationDone) return ret;

  33.  

  34.     // Once startPreview is called, there is no need to continue to remember whether

  35.     // the function cameraPreviewInitialization() was called earlier ornot.And so

  36.     // the flag mPreviewInitializationDone is reset here. Plus, this preserves the

  37.     // current behavior of startPreview under the circumstances where the application

  38.     // calls startPreview twice or more.

  39.     mPreviewInitializationDone =false;

  40.  

  41.     ///Enable the display adapter if present, actual overlay enable happens when we post the buffer

  42.     if(mDisplayAdapter.get()!=NULL){

  43.         CAMHAL_LOGDA("Enabling display");

  44.         int width, height;

  45.         mParameters.getPreviewSize(&width,&height);

  46.  

  47. #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS

  48.         ret = mDisplayAdapter->enableDisplay(width, height,&mStartPreview);

  49. #else

  50.         ret = mDisplayAdapter->enableDisplay(width, height,NULL);

  51. #endif

  52.  

  53.         if( ret != NO_ERROR ){

  54.             CAMHAL_LOGEA("Couldn't enable display");

  55.  

  56.             // FIXME: At this stage mStateSwitchLock is locked and unlock is supposed to be called

  57.             // only from mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_PREVIEW)

  58.             // below. But this will never happen because of goto error. Thus at next

  59.             // startPreview()call CameraHAL will be deadlocked.

  60.             // Need to revisit mStateSwitch lock,fornow just abort the process.

  61.             CAMHAL_ASSERT_X(false,

  62.                 "At this stage mCameraAdapter->mStateSwitchLock is still locked, "

  63.                 "deadlock is guaranteed");

  64.  

  65.             goto error;

  66.         }

  67.  

  68.     }

  69.  

  70.     ///Send START_PREVIEW command to adapter

  71.     CAMHAL_LOGDA("Starting CameraAdapter preview mode");

  72.  

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

  74.  

  75.     if(ret!=NO_ERROR){

  76.         CAMHAL_LOGEA("Couldn't start preview w/ CameraAdapter");

  77.         goto error;

  78.     }

  79.     CAMHAL_LOGDA("Started preview");

  80.  

  81.     mPreviewEnabled =true;

  82.     mPreviewStartInProgress =false;

  83.     return ret;

  84.  

  85.     error:

  86.  

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

  88.  

  89.         //Do all the cleanup

  90.         freePreviewBufs();

  91.         mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_PREVIEW);

  92.         if(mDisplayAdapter.get()!=NULL){

  93.             mDisplayAdapter->disableDisplay(false);

  94.         }

  95.         mAppCallbackNotifier->stop();

  96.         mPreviewStartInProgress =false;

  97.         mPreviewEnabled =false;

  98.         LOG_FUNCTION_NAME_EXIT;

  99.  

  100.         return ret;

  101. }

上面标出的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.  

  5.     LOG_FUNCTION_NAME;

  6.     Mutex::Autolock lock(mPreviewBufsLock);

  7.  

  8.     if(mPreviewing){

  9.         ret = BAD_VALUE;

  10.         goto EXIT;

  11.     }

  12.  

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

  14.  

  15.         mVideoInfo->buf.index = i;

  16.         mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

  17.         mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;

  18.  

  19.         ret = v4lIoctl(mCameraHandle, VIDIOC_QBUF,&mVideoInfo->buf);//请求分配内存

  20.         if(ret 0){

  21.             CAMHAL_LOGEA("VIDIOC_QBUF Failed");

  22.             goto EXIT;

  23.         }

  24.         nQueued++;

  25.     }

  26.  

  27.     ret = v4lStartStreaming();

  28.  

  29.     // Create and start preview thread for receiving buffers from V4L Camera

  30.     if(!mCapturing){

  31.         mPreviewThread = new PreviewThread(this);//开启PreviewThread

  32.         CAMHAL_LOGDA("Created preview thread");

  33.     }

  34.  

  35.     //Update the flag to indicate we are previewing

  36.     mPreviewing =true;

  37.     mCapturing =false;

  38.  

  39. EXIT:

  40.     LOG_FUNCTION_NAME_EXIT;

  41.     return ret;

  42. }

  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.  

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

  12.  

  13.     if(mPreviewing){

  14.  

  15.         fp = this->GetFrame(index);

  16.         if(!fp){

  17.             ret = BAD_VALUE;

  18.             goto EXIT;

  19.         }

  20.         CameraBuffer *buffer = mPreviewBufs.keyAt(index);//获取camerabuffer

  21.         CameraFrame *lframe =(CameraFrame *)mFrameQueue.valueFor(buffer);//获取cameraframe

  22.         if(!lframe){

  23.             ret = BAD_VALUE;

  24.             goto EXIT;

  25.         }

  26.  

  27.         debugShowFPS();

  28.  

  29.         if( mFrameSubscribers.size()== 0 ){

  30.             ret = BAD_VALUE;

  31.             goto EXIT;

  32.         }

  33.         y_uv[0]=(void*) lframe->mYuv[0];

  34.         //y_uv[1]=(void*) lframe->mYuv[1];

  35.         //y_uv[1]=(void*)(lframe->mYuv[0]+ height*stride);

  36.         convertYUV422ToNV12Tiler ((unsigned char*)fp,(unsigned char*)y_uv[0], width, height);//convert the data

  37.         CAMHAL_LOGVB("##...index= %d.;camera buffer= 0x%x; y= 0x%x; UV= 0x%x.",index, buffer, y_uv[0], y_uv[1]);

  38.  

  39. #ifdef SAVE_RAW_FRAMES

  40.         unsigned char* nv12_buff =(unsigned char*) malloc(width*height*3/2);

  41.         //Convert yuv422i to yuv420sp(NV12)& dump the frame to a file

  42.         convertYUV422ToNV12 ((unsigned char*)fp, nv12_buff, width, height);

  43.         saveFile( nv12_buff,((width*height)*3/2));//if you want to save the data,save it

  44.         free (nv12_buff);

  45. #endif

  46.         //填充frame结构,用于数据处理

  47.         frame.mFrameType = CameraFrame::PREVIEW_FRAME_SYNC;

  48.         frame.mBuffer = buffer;

  49.         frame.mLength = width*height*3/2;

  50.         frame.mAlignment = stride;

  51.         frame.mOffset = 0;

  52.         frame.mTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);

  53.         frame.mFrameMask =(unsigned int)CameraFrame::PREVIEW_FRAME_SYNC;

  54.  

  55.         if(mRecording)

  56.         {

  57.             frame.mFrameMask |=(unsigned int)CameraFrame::VIDEO_FRAME_SYNC;

  58.             mFramesWithEncoder++;

  59.         }

  60.     

  61.         //这里是重点,数据回调,或者使用overlay方式显示这里是决定性调用

  62.         ret = setInitFrameRefCount(frame.mBuffer, frame.mFrameMask);

  63.         if(ret != NO_ERROR){

  64.             CAMHAL_LOGDB("Error in setInitFrameRefCount %d", ret);

  65.         }else{

  66.             ret = sendFrameToSubscribers(&frame);

  67.         }

  68.     }

  69. EXIT:

  70.  

  71.     return ret;

  72. }

现在就开始看看setInitFrameCount方法都做了些什么

  1. int BaseCameraAdapter::setInitFrameRefCount(CameraBuffer * buf, unsigned int mask)

  2. {

  3.   int ret = NO_ERROR;

  4.   unsigned int lmask;

  5.  

  6.   LOG_FUNCTION_NAME;

  7.  

  8.   if(buf ==NULL)

  9.     {

  10.       return -EINVAL;

  11.     }

  12.  

  13.   for( lmask = 1; lmask CameraFrame::ALL_FRAMES; lmask = 1){

  14.     if( lmask & mask ){

  15.       switch( lmask ){

  16.  

  17.       case CameraFrame::IMAGE_FRAME:

  18.         {

  19.           setFrameRefCount(buf, CameraFrame::IMAGE_FRAME,(int) mImageSubscribers.size());

  20.         }

  21.         break;

  22.       case CameraFrame::RAW_FRAME:

  23.         {

  24.           setFrameRefCount(buf, CameraFrame::RAW_FRAME, mRawSubscribers.size());

  25.         }

  26.         break;

  27.       case CameraFrame::PREVIEW_FRAME_SYNC:

  28.         {

  29.           setFrameRefCount(buf, CameraFrame::PREVIEW_FRAME_SYNC, mFrameSubscribers.size());//这里这个mFrameSubscribers对应的key上保存着响应的callback方法

  30.         }

  31.         break;

  32.       case CameraFrame::SNAPSHOT_FRAME:

  33.         {

  34.           setFrameRefCount(buf, CameraFrame::SNAPSHOT_FRAME, mSnapshotSubscribers.size());

  35.         }

  36.         break;

  37.       case CameraFrame::VIDEO_FRAME_SYNC:

  38.         {

  39.           setFrameRefCount(buf,CameraFrame::VIDEO_FRAME_SYNC, mVideoSubscribers.size());

  40.         }

  41.         break;

  42.       case CameraFrame::FRAME_DATA_SYNC:

  43.         {

  44.           setFrameRefCount(buf, CameraFrame::FRAME_DATA_SYNC, mFrameDataSubscribers.size());

  45.         }

  46.         break;

  47.       case CameraFrame::REPROCESS_INPUT_FRAME:

  48.         {

  49.           setFrameRefCount(buf,CameraFrame::REPROCESS_INPUT_FRAME, mVideoInSubscribers.size());

  50.         }

  51.         break;

  52.       default:

  53.         CAMHAL_LOGEB("FRAMETYPE NOT SUPPORTED 0x%x", lmask);

  54.         break;

  55.       }//SWITCH

  56.       mask &=~lmask;

  57.     }//IF

  58.   }//FOR

  59.   LOG_FUNCTION_NAME_EXIT;

  60.   return ret;

  61. }

上面我标注的部分通过enableMsgType方法实现mFrameSubscribers.add的,经callback添加到对应的key处,算是实现关联,
同样的通过disableMsgType方法实现mFrameSubscribers.removeItem的,具体在哪里调用enableMsgType和disableMsgType之后再给予说明

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

  2. {

  3.  

  4.     LOG_FUNCTION_NAME;

  5.  

  6.     switch ( frameType )

  7.         {

  8.         case CameraFrame::IMAGE_FRAME:

  9.         case CameraFrame::RAW_FRAME:

  10.                 {

  11.                 Mutex::Autolock lock(mCaptureBufferLock);

  12.                 mCaptureBuffersAvailable.replaceValueFor(frameBuf, refCount);

  13.                 }

  14.             break;

  15.         case CameraFrame::SNAPSHOT_FRAME:

  16.                 {

  17.                 Mutex::Autolock lock(mSnapshotBufferLock);

  18.                 mSnapshotBuffersAvailable.replaceValueFor(( unsigned int) frameBuf, refCount);

  19.                 }

  20.             break;

  21.         case CameraFrame::PREVIEW_FRAME_SYNC:

  22.                 {

  23.                 Mutex::Autolock lock(mPreviewBufferLock)

  24.                 mPreviewBuffersAvailable.replaceValueFor(frameBuf, refCount);//这里我的理解是refCount和frameBuf实现了绑定,即camerabuf保存在mPreviewBuffersAvailable对应的key处

  25.                 }

  26.             break;

  27.         case CameraFrame::FRAME_DATA_SYNC:

  28.                 {

  29.                 Mutex::Autolock lock(mPreviewDataBufferLock);

  30.                 mPreviewDataBuffersAvailable.replaceValueFor(frameBuf, refCount);

  31.                 }

  32.             break;

  33.         case CameraFrame::VIDEO_FRAME_SYNC:

  34.                 {

  35.                 Mutex::Autolock lock(mVideoBufferLock);

  36.                 mVideoBuffersAvailable.replaceValueFor(frameBuf, refCount);

  37.                 }

  38.             break;

  39.         case CameraFrame::REPROCESS_INPUT_FRAME:{

  40.             Mutex::Autolock lock(mVideoInBufferLock);

  41.             mVideoInBuffersAvailable.replaceValueFor(frameBuf, refCount);

  42.         }

  43.             break;

  44.         default:

  45.             break;

  46.         };

  47.  

  48.     LOG_FUNCTION_NAME_EXIT;

  49.  

  50. }

接下我们看看sendFrameToSubscribers方法的具体实现过程

  1. status_t BaseCameraAdapter::sendFrameToSubscribers(CameraFrame *frame)

  2. {

  3.     status_t ret = NO_ERROR;

  4.     unsigned int mask;

  5.  

  6.     if(NULL== frame )

  7.         {

  8.         CAMHAL_LOGEA("Invalid CameraFrame");

  9.         return -EINVAL;

  10.         }

  11.  

  12.     for( mask = 1; mask CameraFrame::ALL_FRAMES; mask = 1){

  13.       if( mask & frame->mFrameMask ){

  14.         switch( mask ){

  15.  

  16.         case CameraFrame::IMAGE_FRAME:

  17.           {

  18. #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS

  19.             CameraHal::PPM("Shot to Jpeg: ",&mStartCapture);

  20. #endif

  21.             ret = __sendFrameToSubscribers(frame,&mImageSubscribers, CameraFrame::IMAGE_FRAME);

  22.           }

  23.           break;

  24.         case CameraFrame::RAW_FRAME:

  25.           {

  26.             ret = __sendFrameToSubscribers(frame,&mRawSubscribers, CameraFrame::RAW_FRAME);

  27.           }

  28.           break;

  29.         case CameraFrame::PREVIEW_FRAME_SYNC:

  30.           {

  31.             ret = __sendFrameToSubscribers(frame,&mFrameSubscribers, CameraFrame::PREVIEW_FRAME_SYNC);

  32.           }

  33.           break;

  34.         case CameraFrame::SNAPSHOT_FRAME:

  35.           {

  36.             ret = __sendFrameToSubscribers(frame,&mSnapshotSubscribers, CameraFrame::SNAPSHOT_FRAME);

  37.           }

  38.           break;

  39.         case CameraFrame::VIDEO_FRAME_SYNC:

  40.           {

  41.             ret = __sendFrameToSubscribers(frame,&mVideoSubscribers, CameraFrame::VIDEO_FRAME_SYNC);

  42.           }

  43.           break;

  44.         case CameraFrame::FRAME_DATA_SYNC:

  45.           {

  46.             ret = __sendFrameToSubscribers(frame,&mFrameDataSubscribers, CameraFrame::FRAME_DATA_SYNC);

  47.           }

  48.           break;

  49.         case CameraFrame::REPROCESS_INPUT_FRAME:

  50.           {

  51.             ret = __sendFrameToSubscribers(frame,&mVideoInSubscribers, CameraFrame::REPROCESS_INPUT_FRAME);

  52.           }

  53.           break;

  54.         default:

  55.           CAMHAL_LOGEB("FRAMETYPE NOT SUPPORTED 0x%x", mask);

  56.         break;

  57.         }//SWITCH

  58.         frame->mFrameMask &=~mask;

  59.  

  60.         if(ret != NO_ERROR){

  61.             goto EXIT;

  62.         }

  63.       }//IF

  64.     }//FOR

  65.  

  66.  EXIT:

  67.     return ret;

  68. }

  1. status_t BaseCameraAdapter::__sendFrameToSubscribers(CameraFrame* frame,

  2.                                                      KeyedVectorint, frame_callback>*subscribers,

  3.                                                      CameraFrame::FrameType frameType)

  4. {

  5.     size_t refCount = 0;

  6.     status_t ret = NO_ERROR;

  7.     frame_callback callback =NULL;

  8.  

  9.     frame->mFrameType = frameType;

  10.  

  11.     if((frameType == CameraFrame::PREVIEW_FRAME_SYNC)||

  12.          (frameType == CameraFrame::VIDEO_FRAME_SYNC)||

  13.          (frameType == CameraFrame::SNAPSHOT_FRAME)){

  14.         if(mFrameQueue.size()> 0){

  15.           CameraFrame *lframe =(CameraFrame *)mFrameQueue.valueFor(frame->mBuffer);

  16.           frame->mYuv[0]= lframe->mYuv[0];

  17.           frame->mYuv[1]= frame->mYuv[0]+(frame->mLength + frame->mOffset)*2/3;

  18.         }

  19.         else{

  20.           CAMHAL_LOGDA("Empty Frame Queue");

  21.           return -EINVAL;

  22.         }

  23.       }

  24.  

  25.     if(NULL!= subscribers){

  26.         refCount = getFrameRefCount(frame->mBuffer, frameType);//通过这个refCount可以找到对应的callback方法

  27.  

  28.         if(refCount == 0){

  29.             CAMHAL_LOGDA("Invalid ref count of 0");

  30.             return -EINVAL;

  31.         }

  32.  

  33.         if(refCount > subscribers->size()){

  34.             CAMHAL_LOGEB("Invalid ref count for frame type: 0x%x", frameType);

  35.             return -EINVAL;

  36.         }

  37.  

  38.         CAMHAL_LOGVB("Type of Frame: 0x%x address: 0x%x refCount start %d",

  39.                      frame->mFrameType,

  40.                      ( uint32_t ) frame->mBuffer,

  41.                      refCount);

  42.  

  43.         for( unsigned int i = 0 ; i refCount; i++){

  44.             frame->mCookie =( void *) subscribers->keyAt(i);

  45.             callback =(frame_callback) subscribers->valueAt(i);

  46.  

  47.             if(!callback){

  48.                 CAMHAL_LOGEB("callback not set for frame type: 0x%x", frameType);

  49.                 return -EINVAL;

  50.             }

  51.  

  52.             callback(frame);

  53.         }

  54.     }else{

  55.         CAMHAL_LOGEA("Subscribers is null??");

  56.         return -EINVAL;

  57.     }

  58.  

  59.     return ret;

  60. }

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

  1. int ANativeWindowDisplayAdapter::setFrameProvider(FrameNotifier *frameProvider)

  2. {

  3.     LOG_FUNCTION_NAME;

  4.  

  5.     // Check forNULL pointer

  6.     if(!frameProvider ){

  7.         CAMHAL_LOGEA("NULL passed for frame provider");

  8.         LOG_FUNCTION_NAME_EXIT;

  9.         return BAD_VALUE;

  10.     }

  11.  

  12.     //Release any previous frame providers

  13.     if(NULL!= mFrameProvider ){

  14.         delete mFrameProvider;

  15.     }

  16.  

  17.     /** Dont do anything here, Just save the pointer for use when display is

  18.          actually enabled or disabled

  19.     */

  20.     mFrameProvider = new FrameProvider(frameProvider, this, frameCallbackRelay);//实例化一个FrameProvider,这其中有一个参数非常重要:frameCallbackRelay,他的定义在下面给出

  21.  

  22.     LOG_FUNCTION_NAME_EXIT;

  23.  

  24.     return NO_ERROR;

  25. }

  1. void ANativeWindowDisplayAdapter::frameCallbackRelay(CameraFrame* caFrame)

  2. {

  3.  

  4.     if(NULL!= caFrame )

  5.         {

  6.         if(NULL!= caFrame->mCookie )

  7.             {

  8.             ANativeWindowDisplayAdapter *da =(ANativeWindowDisplayAdapter*) caFrame->mCookie;

  9.             da->frameCallback(caFrame);

  10.         }

  11.         else

  12.             {

  13.             CAMHAL_LOGEB("Invalid Cookie in Camera Frame = %p, Cookie = %p", caFrame, caFrame->mCookie);

  14.             }

  15.         }

  16.     else

  17.         {

  18.         CAMHAL_LOGEB("Invalid Camera Frame = %p", caFrame);

  19.     }

  20.  

  21. }

  1. void ANativeWindowDisplayAdapter::frameCallback(CameraFrame* caFrame)

  2. {

  3.     ///Call queueBuffer of overlay in the context of the callback thread

  4.     DisplayFrame df;

  5.     df.mBuffer = caFrame->mBuffer;

  6.     df.mType =(CameraFrame::FrameType) caFrame->mFrameType;

  7.     df.mOffset = caFrame->mOffset;

  8.     df.mWidthStride = caFrame->mAlignment;

  9.     df.mLength = caFrame->mLength;

  10.     df.mWidth = caFrame->mWidth;

  11.     df.mHeight = caFrame->mHeight;

  12.     PostFrame(df);

  13. }

这个回调函数在这里设置,等待数据回调,我们很有必要去看看FrameProvider这个类的构造函数,他是怎样让其他方法调用到这个回调函数的呢

  1. FrameProvider(FrameNotifier *fn, void* cookie, frame_callback frameCallback)

  2.         :mFrameNotifier(fn), mCookie(cookie),mFrameCallback(frameCallback){}

这个构造函数还是很有意思,没有任何实现,只是通过传入的三个参数实例化了三个对象而已
1.mFrameNotifier(fn), //这里mFrameNotifier就是camerasdapter
2.mCookie(cookie),
3.mFrameCallback(frameCallback)//mFrameCallback指向我们定义好的callback方法
我们接着就需要到之前已经提到过的startPreview方法中cameraPreviewInitialization的方法中去看了

  1. /**

  2.    @brief Set preview mode related initialization

  3.           -> Camera Adapter set params

  4.           -> Allocate buffers

  5.           ->Set use buffers for preview

  6.    @param none

  7.    @return NO_ERROR

  8.    @todo Update function header with the different errors that are possible

  9.  

  10.  */

  11. status_t CameraHal::cameraPreviewInitialization()

  12. {

  13.  

  14.     status_t ret = NO_ERROR;

  15.     CameraAdapter::BuffersDescriptor desc;

  16.     CameraFrame frame;

  17.     unsigned int required_buffer_count;

  18.     unsigned int max_queueble_buffers;

  19.  

  20. #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS

  21.         gettimeofday(&mStartPreview,NULL);

  22. #endif

  23.  

  24.     LOG_FUNCTION_NAME;

  25.  

  26.     if(mPreviewInitializationDone){

  27.         return NO_ERROR;

  28.     }

  29.  

  30.     if( mPreviewEnabled ){

  31.       CAMHAL_LOGDA("Preview already running");

  32.       LOG_FUNCTION_NAME_EXIT;

  33.       return ALREADY_EXISTS;

  34.     }

  35.  

  36.     if(NULL!= mCameraAdapter ){

  37.       ret = mCameraAdapter->setParameters(mParameters);

  38.     }

  39.  

  40.     if((mPreviewStartInProgress ==false)&&(mDisplayPaused ==false)){

  41.       ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_QUERY_RESOLUTION_PREVIEW,(int)&frame);

  42.       if( NO_ERROR != ret ){

  43.         CAMHAL_LOGEB("Error: CAMERA_QUERY_RESOLUTION_PREVIEW %d", ret);

  44.         return ret;

  45.       }

  46.  

  47.       ///Update the current preview width and height

  48.       mPreviewWidth = frame.mWidth;

  49.       mPreviewHeight = frame.mHeight;

  50.     }

  51.  

  52.     ///If we don't have the preview callback enabled and display adapter,

  53.     if(!mSetPreviewWindowCalled ||(mDisplayAdapter.get()==NULL)){

  54.       CAMHAL_LOGD("Preview not started. Preview in progress flag set");

  55.       mPreviewStartInProgress =true;

  56.       ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_SWITCH_TO_EXECUTING);

  57.       if( NO_ERROR != ret ){

  58.         CAMHAL_LOGEB("Error: CAMERA_SWITCH_TO_EXECUTING %d", ret);

  59.         return ret;

  60.       }

  61.       return NO_ERROR;

  62.     }

  63.  

  64.     if((mDisplayAdapter.get()!=NULL)&&(!mPreviewEnabled )&&( mDisplayPaused ))

  65.         {

  66.         CAMHAL_LOGDA("Preview is in paused state");

  67.  

  68.         mDisplayPaused =false;

  69.         mPreviewEnabled =true;

  70.         if( NO_ERROR == ret )

  71.             {

  72.             ret = mDisplayAdapter->pauseDisplay(mDisplayPaused);

  73.  

  74.             if( NO_ERROR != ret )

  75.                 {

  76.                 CAMHAL_LOGEB("Display adapter resume failed %x", ret);

  77.                 }

  78.             }

  79.         //restart preview callbacks

  80.         if(mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)

  81.         {

  82.             mAppCallbackNotifier->enableMsgType (CAMERA_MSG_PREVIEW_FRAME);

  83.         }

  84.  

  85.         signalEndImageCapture();

  86.         return ret;

  87.         }

  88.  

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

  90.  

  91.     ///Allocate the preview buffers

  92.     ret = allocPreviewBufs(mPreviewWidth, mPreviewHeight, mParameters.getPreviewFormat(), required_buffer_count, max_queueble_buffers);

  93.  

  94.     if( NO_ERROR != ret )

  95.         {

  96.         CAMHAL_LOGEA("Couldn't allocate buffers for Preview");

  97.         goto error;

  98.         }

  99.  

  100.     if( mMeasurementEnabled )

  101.         {

  102.  

  103.         ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_QUERY_BUFFER_SIZE_PREVIEW_DATA,

  104.                                           (int)&frame,

  105.                                           required_buffer_count);

  106.         if( NO_ERROR != ret )

  107.             {

  108.             return ret;

  109.             }

  110.  

  111.          ///Allocate the preview data buffers

  112.         ret = allocPreviewDataBufs(frame.mLength, required_buffer_count);

  113.         if( NO_ERROR != ret ){

  114.             CAMHAL_LOGEA("Couldn't allocate preview data buffers");

  115.             goto error;

  116.            }

  117.  

  118.         if( NO_ERROR == ret )

  119.             {

  120.             desc.mBuffers = mPreviewDataBuffers;

  121.             desc.mOffsets = mPreviewDataOffsets;

  122.             desc.mFd = mPreviewDataFd;

  123.             desc.mLength = mPreviewDataLength;

  124.             desc.mCount =( size_t ) required_buffer_count;

  125.             desc.mMaxQueueable =(size_t) required_buffer_count;

  126.  

  127.             mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_PREVIEW_DATA,

  128.                                         (int)&desc);

  129.             }

  130.  

  131.         }

  132.  

  133.     ///Pass the buffers to Camera Adapter

  134.     desc.mBuffers = mPreviewBuffers;

  135.     desc.mOffsets = mPreviewOffsets;

  136.     desc.mFd = mPreviewFd;

  137.     desc.mLength = mPreviewLength;

  138.     desc.mCount =( size_t ) required_buffer_count;

  139.     desc.mMaxQueueable =(size_t) max_queueble_buffers;

  140.  

  141.     ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_PREVIEW,

  142.                                       (int)&desc);

  143.  

  144.     if( NO_ERROR != ret )

  145.         {

  146.         CAMHAL_LOGEB("Failed to register preview buffers: 0x%x", ret);

  147.         freePreviewBufs();

  148.         return ret;

  149.         }

  150.  

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

  152.  

  153.     ///Start the callback notifier

  154.     ret = mAppCallbackNotifier->start();

  155.  

  156.     if( ALREADY_EXISTS == ret )

  157.         {

  158.         //Already running,donothing

  159.         CAMHAL_LOGDA("AppCallbackNotifier already running");

  160.         ret = NO_ERROR;

  161.         }

  162.     elseif( NO_ERROR == ret ){

  163.         CAMHAL_LOGDA("Started AppCallbackNotifier..");

  164.         mAppCallbackNotifier->setMeasurements(mMeasurementEnabled);

  165.         }

  166.     else

  167.         {

  168.         CAMHAL_LOGDA("Couldn't start AppCallbackNotifier");

  169.         goto error;

  170.         }

  171.  

  172.     if(ret == NO_ERROR) mPreviewInitializationDone =true;

  173.     return ret;

  174.  

  175.     error:

  176.  

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

  178.  

  179.         //Do all the cleanup

  180.         freePreviewBufs();

  181.         mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_PREVIEW);

  182.         if(mDisplayAdapter.get()!=NULL)

  183.             {

  184.             mDisplayAdapter->disableDisplay(false);

  185.             }

  186.         mAppCallbackNotifier->stop();

  187.         mPreviewStartInProgress =false;

  188.         mPreviewEnabled =false;

  189.         LOG_FUNCTION_NAME_EXIT;

  190.  

  191.         return ret;

  192. }

我们就看看这个方法的是实现吧:mAppCallbackNotifier->enableMsgType (CAMERA_MSG_PREVIEW_FRAME);

  1. status_t AppCallbackNotifier::enableMsgType(int32_t msgType)

  2. {

  3.     if( msgType & CAMERA_MSG_PREVIEW_FRAME ){

  4.         mFrameProvider->enableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC);

  5.     }

  6.  

  7.     if( msgType & CAMERA_MSG_POSTVIEW_FRAME ){

  8.         mFrameProvider->enableFrameNotification(CameraFrame::SNAPSHOT_FRAME);

  9.     }

  10.  

  11.     if(msgType & CAMERA_MSG_RAW_IMAGE){

  12.         mFrameProvider->enableFrameNotification(CameraFrame::RAW_FRAME);

  13.     }

  14.  

  15.     return NO_ERROR;

  16. }

  1. int FrameProvider::enableFrameNotification(int32_t frameTypes)

  2. {

  3.     LOG_FUNCTION_NAME;

  4.     status_t ret = NO_ERROR;

  5.  

  6.     ///Enable the frame notification to CameraAdapter (which implements FrameNotifier interface)

  7.     mFrameNotifier->enableMsgType(frameTypesMessageNotifier::FRAME_BIT_FIELD_POSITION, mFrameCallback,NULL, mCookie);

  8.  

  9.     LOG_FUNCTION_NAME_EXIT;

  10.     return ret;

  11. }

这里这个enableMsgType其实就是前面已经提到过的那个enableMsgType方法,实现callback方法add到响应的key上
这里这个mFrameNotifier是FrameNotifier的对象,FrameNotifier这个类继承于MessageNotifier
而BaseCameraAdapter继承于CameraAdapter,CameraAdapter又继承于FrameNotifier,所以mFrameNotifier对象调用的enableMsgType方法其实是一个虚函数,
最终调用的是BaseCameraAdapter这个类中定义的enableMsgType方法,我们来看一看他的实现:

  1. void BaseCameraAdapter::enableMsgType(int32_t msgs, frame_callback callback, event_callback eventCb, void* cookie)

  2. {

  3.     Mutex::Autolock lock(mSubscriberLock);

  4.  

  5.     LOG_FUNCTION_NAME;

  6.  

  7.     int32_t frameMsg =((msgs >> MessageNotifier::FRAME_BIT_FIELD_POSITION)& EVENT_MASK);

  8.     int32_t eventMsg =((msgs >> MessageNotifier::EVENT_BIT_FIELD_POSITION)& EVENT_MASK);

  9.  

  10.     if( frameMsg != 0 )

  11.         {

  12.         CAMHAL_LOGVB("Frame message type id=0x%x subscription request", frameMsg);

  13.         switch ( frameMsg )

  14.             {

  15.             case CameraFrame::PREVIEW_FRAME_SYNC:

  16.                 mFrameSubscribers.add((int) cookie, callback);

  17.                 break;

  18.             case CameraFrame::FRAME_DATA_SYNC:

  19.                 mFrameDataSubscribers.add((int) cookie, callback);

  20.                 break;

  21.             case CameraFrame::SNAPSHOT_FRAME:

  22.                 mSnapshotSubscribers.add((int) cookie, callback);

  23.                 break;

  24.             case CameraFrame::IMAGE_FRAME:

  25.                 mImageSubscribers.add((int) cookie, callback);

  26.                 break;

  27.             case CameraFrame::RAW_FRAME:

  28.                 mRawSubscribers.add((int) cookie, callback);

  29.                 break;

  30.             case CameraFrame::VIDEO_FRAME_SYNC:

  31.                 mVideoSubscribers.add((int) cookie, callback);

  32.                 break;

  33.             case CameraFrame::REPROCESS_INPUT_FRAME:

  34.                 mVideoInSubscribers.add((int) cookie, callback);

  35.                 break;

  36.             default:

  37.                 CAMHAL_LOGEA("Frame message type id=0x%x subscription no supported yet!", frameMsg);

  38.                 break;

  39.             }

  40.         }

  41.  

  42.     if( eventMsg != 0)

  43.         {

  44.         CAMHAL_LOGVB("Event message type id=0x%x subscription request", eventMsg);

  45.         if( CameraHalEvent::ALL_EVENTS == eventMsg )

  46.             {

  47.             mFocusSubscribers.add((int) cookie, eventCb);

  48.             mShutterSubscribers.add((int) cookie, eventCb);

  49.             mZoomSubscribers.add((int) cookie, eventCb);

  50.             mMetadataSubscribers.add((int) cookie, eventCb);

  51.             }

  52.         else

  53.             {

  54.             CAMHAL_LOGEA("Event message type id=0x%x subscription no supported yet!", eventMsg);

  55.             }

  56.         }

  57.  

  58.     LOG_FUNCTION_NAME_EXIT;

  59. }

这里通过mFrameSubscribers.add((int) cookie, callback)这个方法将mFrameCallback回调函数与key相关联
所以上面可以通过callback = (frame_callback) subscribers->valueAt(i);
这个方法获取callback的实现,因为上面已经实现了关联,所以数据最终是通过上面分析道的方法继续进行数据流显示

  1. void ANativeWindowDisplayAdapter::frameCallback(CameraFrame* caFrame)

  2. {

  3.     ///Call queueBuffer of overlay in the context of the callback thread

  4.     DisplayFrame df;

  5.     df.mBuffer = caFrame->mBuffer;

  6.     df.mType = (CameraFrame::FrameType) caFrame->mFrameType;

  7.     df.mOffset = caFrame->mOffset;

  8.     df.mWidthStride = caFrame->mAlignment;

  9.     df.mLength = caFrame->mLength;

  10.     df.mWidth = caFrame->mWidth;

  11.     df.mHeight = caFrame->mHeight;

  12.     PostFrame(df);//这里填充了DisplayFrame这个结构,并调用PostFrome实现显示

  13. }

这里PostFrame成了我要研究的主要内容,将数据以DisplayFrame结构的方式打包之后到底是怎么实现显示的呢??

  1. status_t ANativeWindowDisplayAdapter::PostFrame(ANativeWindowDisplayAdapter::DisplayFrame &dispFrame)

  2. {

  3.     status_t ret = NO_ERROR;

  4.     uint32_t actualFramesWithDisplay = 0;

  5.     android_native_buffer_t *buffer =NULL;

  6.     GraphicBufferMapper &mapper = GraphicBufferMapper::get();

  7.     int i;

  8.  

  9.     ///@todo Do cropping based on the stabilized frame coordinates

  10.     ///@todo Insert logic to drop frames here based on refresh rate of

  11.     ///display or rendering rate whichever is lower

  12.     ///Queue the buffer to overlay

  13.     if(NULL== mANativeWindow ){

  14.         return NO_INIT;

  15.     }

  16.  

  17.     if(!mBuffers ||!dispFrame.mBuffer){

  18.         CAMHAL_LOGEA("NULL sent to PostFrame");

  19.         return BAD_VALUE;

  20.     }

  21.  

  22.     for( i = 0; i mBufferCount; i++)

  23.         {

  24.         if( dispFrame.mBuffer ==&mBuffers[i])

  25.             {

  26.             break;

  27.         }

  28.     }

  29.  

  30.  

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

  32.  

  33.     if( mDisplayState == ANativeWindowDisplayAdapter::DISPLAY_STARTED &&

  34.                 (!mPaused || CameraFrame::CameraFrame::SNAPSHOT_FRAME == dispFrame.mType)&&

  35.                 !mSuspend)

  36.     {

  37.         Mutex::Autolock lock(mLock);

  38.         uint32_t xOff =(dispFrame.mOffset% PAGE_SIZE);

  39.         uint32_t yOff =(dispFrame.mOffset / PAGE_SIZE);

  40.  

  41.         //Set crop only if current x and y offsets donot match with frame offsets

  42.         if((mXOff!=xOff)||(mYOff!=yOff))

  43.         {

  44.             CAMHAL_LOGDB("Offset %d xOff = %d, yOff = %d", dispFrame.mOffset, xOff, yOff);

  45.             uint8_t bytesPerPixel;

  46.             ///Calculate bytes per pixel based on the pixel format

  47.             if(strcmp(mPixelFormat,(const char *) CameraParameters::PIXEL_FORMAT_YUV422I)== 0)

  48.                 {

  49.                 bytesPerPixel = 2;

  50.                 }

  51.             elseif(strcmp(mPixelFormat,(const char *) CameraParameters::PIXEL_FORMAT_RGB565)== 0)

  52.                 {

  53.                 bytesPerPixel = 2;

  54.                 }

  55.             elseif(strcmp(mPixelFormat,(const char *) CameraParameters::PIXEL_FORMAT_YUV420SP)== 0)

  56.                 {

  57.                 bytesPerPixel = 1;

  58.                 }

  59.             else

  60.                 {

  61.                 bytesPerPixel = 1;

  62.             }

  63.  

  64.             CAMHAL_LOGVB(" crop.left = %d crop.top = %d crop.right = %d crop.bottom = %d",

  65.                           xOff/bytesPerPixel, yOff ,(xOff/bytesPerPixel)+mPreviewWidth, yOff+mPreviewHeight);

  66.             // We'll ignore any errors here,if the surface is

  67.             // already invalid, we'll know soon enough.

  68.             mANativeWindow->set_crop(mANativeWindow, xOff/bytesPerPixel, yOff,

  69.                                      (xOff/bytesPerPixel)+mPreviewWidth, yOff+mPreviewHeight);

  70.  

  71.             ///Update the current x and y offsets

  72.             mXOff = xOff;

  73.             mYOff = yOff;

  74.         }

  75.  

  76.         {

  77.             buffer_handle_t *handle =(buffer_handle_t *) mBuffers[i].opaque;

  78.             // unlock buffer before sending to display

  79.             mapper.unlock(*handle);

  80.             ret = mANativeWindow->enqueue_buffer(mANativeWindow, handle);

  81.         }

  82.         if( NO_ERROR != ret ){

  83.             CAMHAL_LOGE("Surface::queueBuffer returned error %d", ret);

  84.         }

  85.  

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

  87.  

  88.  

  89.         // HWComposer has not minimum buffer requirement. We should be able to dequeue

  90.         // the buffer immediately

  91.         TIUTILS::Message msg;

  92.         mDisplayQ.put(&msg);

  93.  

  94.  

  95. #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS

  96.  

  97.         if( mMeasureStandby )

  98.             {

  99.             CameraHal::PPM("Standby to first shot: Sensor Change completed - ",&mStandbyToShot);

  100.             mMeasureStandby =false;

  101.             }

  102.         elseif(CameraFrame::CameraFrame::SNAPSHOT_FRAME == dispFrame.mType)

  103.             {

  104.             CameraHal::PPM("Shot to snapshot: ",&mStartCapture);

  105.             mShotToShot =true;

  106.             }

  107.         elseif( mShotToShot )

  108.             {

  109.             CameraHal::PPM("Shot to shot: ",&mStartCapture);

  110.             mShotToShot =false;

  111.         }

  112. #endif

  113.  

  114.     }

  115.     else

  116.     {

  117.         Mutex::Autolock lock(mLock);

  118.         buffer_handle_t *handle =(buffer_handle_t *) mBuffers[i].opaque;

  119.  

  120.         // unlock buffer before giving it up

  121.         mapper.unlock(*handle);

  122.  

  123.         // cancel buffer and dequeue another one

  124.         ret = mANativeWindow->cancel_buffer(mANativeWindow, handle);

  125.         if( NO_ERROR != ret ){

  126.             CAMHAL_LOGE("Surface::cancelBuffer returned error %d", ret);

  127.         }

  128.  

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

  130.  

  131.         TIUTILS::Message msg;

  132.         mDisplayQ.put(&msg);

  133.         ret = NO_ERROR;

  134.     }

  135.  

  136.     return ret;

  137. }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值