Android Camera 系统架构源码分析(3)---->Camera的显示流程

Preview的显示流程
这次我们要从最开始startPreview的时候开始,在starPreview之间就setPreviewWindow()。

    
 
  1. //CameraClient.cpp
  2. status_t CameraClient::startPreviewMode() {
  3. mHardware->previewEnabled();
  4. mHardware->setPreviewWindow(mPreviewWindow);
  5. result = mHardware->startPreview();
  6. }

最后会调用到Cam1DeviceBase的setPreviewWindow(),其中的调用过程和startPreview()的一样,不再赘述

     
 
  1. Cam1DeviceBase::setPreviewWindow(preview_stream_ops* window)
  2. {
  3. //(1) 初始化显示
  4. status_t status = initDisplayClient(window);
  5. //(2) 开始显示
  6. status = enableDisplayClient();
  7. }

initDisplayClient(); 在之前说的Cam1DeviceBase::startPreview()的(2)也调用 了
initDisplayClient();

    
 
  1. Cam1DeviceBase::initDisplayClient(preview_stream_ops* window)
  2. {
  3. Size previewSize;
  4. // [1] Check to see whether the passed window is NULL or not.
  5. //...
  6. // [2] Get preview size. 获得预览参数
  7. queryPreviewSize(previewSize.width, previewSize.height);
  8. // [3] Initialize Display Client.
  9. // [3.1] create a Display Client. 仅是初始化变量
  10. mpDisplayClient = IDisplayClient::createInstance();
  11. // [3.2] initialize the newly-created Display Client.
  12. mpDisplayClient->init();
  13. // [3.3] set preview_stream_ops & related window info.
  14. mpDisplayClient->setWindow(window, previewSize.width, previewSize.height, queryDisplayBufCount());
  15. // [3.4] set Image Buffer Provider Client if it exist.
  16. mpCamAdapter != 0 && ! mpDisplayClient->setImgBufProviderClient(mpCamAdapter);
  17. }

下面是
initDisplayClient();的细节分析

    
 
  1. DisplayClient::init()
  2. {
  3. /**
  4. 构造DisplayThread并让它run起来,注意构造时传入的handle参数为dispalyClient
  5. 构造ImgBufQueue,它的id为eID_DISPLAY
  6. 在previewClient init()时,也创建了一个ImgBufQueue,而ID是eID_PRV_CB
  7. **/
  8. ret = createDisplayThread() && createImgBufQueue();
  9. }
  10. DisplayClient::setWindow(preview_stream_ops*const window, int32_t const wndWidth,
  11. int32_t const wndHeight, int32_t const i4MaxImgBufCount)
  12. { return set_preview_stream_ops(window, wndWidth, wndHeight, i4MaxImgBufCount);
  13. }
  14. DisplayClient::set_preview_stream_ops(preview_stream_ops*const window, int32_t const wndWidth,
  15. int32_t const wndHeight, int32_t const i4MaxImgBufCount)
  16. {
  17. int32_t min_undequeued_buf_count = 0;
  18. //
  19. // (2) Check
  20. //....
  21. // (3) Sava info.
  22. mpStreamImgInfo.clear();
  23. mpStreamImgInfo = new ImgInfo(wndWidth, wndHeight, CAMERA_DISPLAY_FORMAT, CAMERA_DISPLAY_FORMAT_HAL, "Camera@Display");
  24. mpStreamOps = window;
  25. mi4MaxImgBufCount = i4MaxImgBufCount;
  26. // (4.1) Set gralloc usage bits for window.
  27. err = mpStreamOps->set_usage(mpStreamOps, CAMERA_GRALLOC_USAGE);
  28. // (4.2) Get minimum undequeue buffer count
  29. err = mpStreamOps->get_min_undequeued_buffer_count(mpStreamOps, &min_undequeued_buf_count);
  30. // (4.3) Set the number of buffers needed for display.
  31. err = mpStreamOps->set_buffer_count(mpStreamOps, mi4MaxImgBufCount+min_undequeued_buf_count);
  32. // (4.4) Set window geometry
  33. err = mpStreamOps->set_buffers_geometry(mpStreamOps, mpStreamImgInfo->mu4ImgWidth,
  34. mpStreamImgInfo->mu4ImgHeight, mpStreamImgInfo->mi4ImgFormat);
  35. }
  36. DisplayClient::setImgBufProviderClient(sp<IImgBufProviderClient>const& rpClient)
  37. {
  38. rpClient->onImgBufProviderCreated(mpImgBufQueue);
  39. mpImgBufPvdrClient = rpClient;
  40. }
  41. //BaseCamAdapter.cpp
  42. BaseCamAdapter::onImgBufProviderCreated(sp<IImgBufProvider>const& rpProvider)
  43. {
  44. int32_t const i4ProviderId = rpProvider->getProviderId();
  45. mpImgBufProvidersMgr->setProvider(i4ProviderId, rpProvider);
  46. }

DispalyClient的初始化就这么完成了,从但是我们并不知道上面已经初始化的参数有什么作用,又是如何开始刷显示的呢?我们返回到enableDisplayClient()继续跟踪

    
 
  1. Cam1DeviceBase::enableDisplayClient()
  2. {
  3. Size previewSize;
  4. // [1] Get preview size. 获取预览参数
  5. queryPreviewSize(previewSize.width, previewSize.height);
  6. // [2] Enable
  7. mpDisplayClient->enableDisplay(previewSize.width, previewSize.height, queryDisplayBufCount(), mpCamAdapter);
  8. }

    
 
  1. Cam1DeviceBase::enableDisplayClient()
  2. {
  3. Size previewSize;
  4. // [1] Get preview size. 获取预览参数
  5. queryPreviewSize(previewSize.width, previewSize.height);
  6. // [2] Enable
  7. mpDisplayClient->enableDisplay(previewSize.width, previewSize.height, queryDisplayBufCount(), mpCamAdapter);
  8. }
  9. DisplayClient::enableDisplay(int32_t const i4Width, int32_t const i4Height,
  10. int32_t const i4BufCount, sp<IImgBufProviderClient>const& rpClient)
  11. {
  12. // Enable.
  13. enableDisplay();
  14. }
  15. DisplayClient::enableDisplay()
  16. {
  17. //Post a command to wake up the thread. 向DisplayThread发送消息
  18. mpDisplayThread->postCommand(Command(Command::eID_WAKEUP));
  19. }
  20. DisplayThread::threadLoop()
  21. {
  22. Command cmd;
  23. if ( getCommand(cmd) )
  24. {
  25. switch (cmd.eId)
  26. {
  27. case Command::eID_EXIT:
  28. //....
  29. case Command::eID_WAKEUP:
  30. default:
  31. //调用的是handler的onThreadloop
  32. //在前面已知DisplayThread的handler被设置成了DisplayClient
  33. mpThreadHandler->onThreadLoop(cmd);
  34. break;
  35. }
  36. }
  37. }

DisplayClient的onThreadLoop()在DisplayClient.BufOps.cpp里,仔细观察下面的函数是不会有似曾相识的感觉,原来下面函数的结构和Preview的onClientThreadLoop的函数结构一模一样,边里面使用的函数名都一样,虽然不是同一个函数

    
 
  1. DisplayClient::onThreadLoop(Command const& rCmd)
  2. {
  3. // (0) lock Processor.
  4. sp<IImgBufQueue> pImgBufQueue;
  5. // (1) Prepare all TODO buffers. 准备buf,把buf放入队列里
  6. if ( ! prepareAllTodoBuffers(pImgBufQueue) )
  7. {
  8. return true;
  9. }
  10. // (2) Start 通知开始处理
  11. pImgBufQueue->startProcessor();
  12. // (3) Do until disabled.
  13. while ( 1 )
  14. {
  15. // (.1) 阻塞等待通知,并开始处理buf
  16. waitAndHandleReturnBuffers(pImgBufQueue);
  17. // (.2) break if disabled.
  18. if ( ! isDisplayEnabled() )
  19. {
  20. MY_LOGI("Display disabled");
  21. break;
  22. }
  23. // (.3) re-prepare all TODO buffers, if possible,
  24. // since some DONE/CANCEL buffers return. 准备buf,把buf放入队列里
  25. prepareAllTodoBuffers(pImgBufQueue);
  26. }
  27. //
  28. // (4) Stop
  29. pImgBufQueue->pauseProcessor();
  30. pImgBufQueue->flushProcessor();
  31. pImgBufQueue->stopProcessor();
  32. //
  33. // (5) Cancel all un-returned buffers.
  34. cancelAllUnreturnBuffers();
  35. //
  36. {
  37. Mutex::Autolock _l(mStateMutex);
  38. mState = eState_Suspend;
  39. mStateCond.broadcast();
  40. }
  41. }

根据之前的经验很直觉地找到了waitAndHandleReturnBuffers()函数,正是里面处理了数据,但是又怎么样把数据显示出来的呢?继续看

    
 
  1. DisplayClient::waitAndHandleReturnBuffers(sp<IImgBufQueue>const& rpBufQueue)
  2. {
  3. Vector<ImgBufQueNode> vQueNode;
  4. // (1) deque buffers from processor. 阻塞等待通知读取Buf
  5. rpBufQueue->dequeProcessor(vQueNode);
  6. // (2) handle buffers dequed from processor.
  7. ret = handleReturnBuffers(vQueNode);
  8. }
  9. DisplayClient::handleReturnBuffers(Vector<ImgBufQueNode>const& rvQueNode)
  10. {
  11. /*
  12. * Notes:
  13. * For 30 fps, we just enque (display) the latest frame,
  14. * and cancel the others.
  15. * For frame rate > 30 fps, we should judge the timestamp here or source.
  16. */
  17. //
  18. // (3) Remove from List and enquePrvOps/cancelPrvOps, one by one.
  19. int32_t const queSize = rvQueNode.size();
  20. for (int32_t i = 0; i < queSize; i++)
  21. {
  22. sp<IImgBuf>const& rpQueImgBuf = rvQueNode[i].getImgBuf(); // ImgBuf in Queue.
  23. sp<StreamImgBuf>const pStreamImgBuf = *mStreamBufList.begin(); // ImgBuf in List.
  24. // (.1) Check valid pointers to image buffers in Queue & List
  25. if ( rpQueImgBuf == 0 || pStreamImgBuf == 0 )
  26. {
  27. MY_LOGW("Bad ImgBuf:(Que[%d], List.begin)=(%p, %p)", i, rpQueImgBuf.get(), pStreamImgBuf.get());
  28. continue;
  29. }
  30. // (.2) Check the equality of image buffers between Queue & List.
  31. if ( rpQueImgBuf->getVirAddr() != pStreamImgBuf->getVirAddr() )
  32. {
  33. MY_LOGW("Bad address in ImgBuf:(Que[%d], List.begin)=(%p, %p)", i, rpQueImgBuf->getVirAddr(), pStreamImgBuf->getVirAddr());
  34. continue;
  35. }
  36. // (.3) Every check is ok. Now remove the node from the list.
  37. mStreamBufList.erase(mStreamBufList.begin());
  38. //
  39. // (.4) enquePrvOps/cancelPrvOps
  40. if ( i == idxToDisp ) {
  41. //
  42. if(mpExtImgProc != NULL)
  43. {
  44. if(mpExtImgProc->getImgMask() & ExtImgProc::BufType_Display)
  45. {
  46. IExtImgProc::ImgInfo img;
  47. //
  48. img.bufType = ExtImgProc::BufType_Display;
  49. img.format = pStreamImgBuf->getImgFormat();
  50. img.width = pStreamImgBuf->getImgWidth();
  51. img.height = pStreamImgBuf->getImgHeight();
  52. img.stride[0] = pStreamImgBuf->getImgWidthStride(0);
  53. img.stride[1] = pStreamImgBuf->getImgWidthStride(1);
  54. img.stride[2] = pStreamImgBuf->getImgWidthStride(2);
  55. img.virtAddr = (MUINT32)(pStreamImgBuf->getVirAddr());
  56. img.bufSize = pStreamImgBuf->getBufSize();
  57. //预留的处理接口,用户可自行填充
  58. mpExtImgProc->doImgProc(img);
  59. }
  60. }
  61. //处理将要显示的Buf
  62. enquePrvOps(pStreamImgBuf);
  63. }
  64. else {
  65. //处理被忽略的buf
  66. cancelPrvOps(pStreamImgBuf);
  67. }
  68. }
  69. }
  70. DisplayClient::enquePrvOps(sp<StreamImgBuf>const& rpImgBuf)
  71. {
  72. // [1] unlock buffer before sending to display
  73. GraphicBufferMapper::get().unlock(rpImgBuf->getBufHndl());
  74. // [2] Dump image if wanted.
  75. dumpImgBuf_If(rpImgBuf);
  76. // [3] set timestamp.
  77. err = mpStreamOps->set_timestamp(mpStreamOps, rpImgBuf->getTimestamp());
  78. // [4] set gralloc buffer type & dirty 设置buf的参数
  79. ::gralloc_extra_setBufParameter(rpImgBuf->getBufHndl(),
  80. GRALLOC_EXTRA_MASK_TYPE | GRALLOC_EXTRA_MASK_DIRTY, GRALLOC_EXTRA_BIT_TYPE_CAMERA | GRALLOC_EXTRA_BIT_DIRTY);
  81. // [5] unlocks and post the buffer to display.
  82. //此处我们的mpStreamOps在之前的set_preview_stream_ops()被初始化为window,即setWindow()传下来的window参数。
  83. //所以我们得往上找,这个window是什么东西。
  84. err = mpStreamOps->enqueue_buffer(mpStreamOps, rpImgBuf->getBufHndlPtr());
  85. }

再往回找,setPreviewWindow传入了一个window,这个是一个Surface,这个surface通过App层的Surface传下来的buf重新构建的

     
 
  1. // set the buffer consumer that the preview will use
  2. status_t CameraClient::setPreviewTarget(
  3. const sp<IGraphicBufferProducer>& bufferProducer) {
  4. sp<IBinder> binder;
  5. sp<ANativeWindow> window;
  6. if (bufferProducer != 0) {
  7. binder = bufferProducer->asBinder();
  8. // Using controlledByApp flag to ensure that the buffer queue remains in
  9. // async mode for the old camera API, where many applications depend
  10. // on that behavior.
  11. window = new Surface(bufferProducer, /*controlledByApp*/ true);
  12. }
  13. return setPreviewWindow(binder, window);
  14. }



setPreviewTarget
()在最开始的
android_hardware_Camera.cpp里被调用,这里传进来 的bufferProduce是从App层的surface里面获取出来的一个buf

      
 
  1. static void android_hardware_Camera_setPreviewSurface(JNIEnv *env, jobject thiz, jobject jSurface)
  2. {
  3. sp<IGraphicBufferProducer> gbp;
  4. sp<Surface> surface;
  5. surface = android_view_Surface_getSurface(env, jSurface);
  6. gbp = surface->getIGraphicBufferProducer();
  7. if (camera->setPreviewTarget(gbp) != NO_ERROR) {
  8. jniThrowException(env, "java/io/IOException", "setPreviewTexture failed");
  9. }
  10. }

你会以为上面的pStreamOps->enqueue_buffer用的就是这个surface,其实不是,这里又转了一下

      
 
  1. status_t setPreviewWindow(const sp<ANativeWindow>& buf)
  2. {
  3. mPreviewWindow = buf;
  4. mHalPreviewWindow.user = this;
  5. return mDevice->ops->set_preview_window(mDevice,
  6. buf.get() ? &mHalPreviewWindow.nw : 0);
  7. }

这里判断surface的传下来的buf是否为空,如果不为空则把mHalPreviewWindow.nw传下去,这个nw是一个操作方法的集合。相对应的
enqueue_buffer被初始化为下面这个函数

      
 
  1. static int __enqueue_buffer(struct preview_stream_ops* w,
  2. buffer_handle_t* buffer)
  3. {
  4. ANativeWindow *a = anw(w);
  5. return a->queueBuffer(a,
  6. container_of(buffer, ANativeWindowBuffer, handle), -1);
  7. }

pStreamOps->enqueue_buffer就是执行了一下上面的方法。其实就是把camera里面的数据填进surface的buf队列里

写过APP的都知道,这个Surface是Android上层用于显示的一个辅助类。而Camera的预览也相当于调用了Surface的操作函数。那问题又来了,调用这些Surface是如何去显示的呢?……我就到此为止了,完成了我做知识储备的目的,日后要是工作有需要深入再深入了,有兴趣的朋友可以自行……….深入。我们还是再继续看,这些数据是如何来的呢?



现在回头看看现在涉及到的几个大类做一下总结。
Cam1DeviceBase(包括其子类和父类)包含了所有的Camera的操作函数,如Open,显示,拍照,录像,自动对焦的操作,以及这些Camera操作和Camera硬件涉及到的参数,可以说,Cam1Device对Frameworks及App层来说就是一个Camera了。
在Cam1DeviceBase里包含了ParamsManager,顾名思义就是Camera的参数管理,我们之前也没去理会他,就让它飘会吧。Cam1DeviceBase还包含了几个Client,用于负责所有的功能操作。DisplayClient用来负责显示,CamClient则是一个大统一,把Camera的操作都归集于此。CamClient又把自己的功能分成几个 Client去负责,其中PreviewClient负责显示,RecordClient负责录制,在拍照的功能里FDClient,OTClient,PreviewClient都参了一脚,具体有什么用,有空再研究。但还有一个CameraAdapter,这也非常重要的

    原文作者:Android源码分析
    原文地址: https://blog.csdn.net/shell812/article/details/49425763
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞