mx53 camera HAL preview(接口层)

首先,android有个camera的server frameworks/base/services/camera/libcameraservice,如果不想用他默认的fakeCamera,则要实现自己的libcamera.so,就是所说的camera HAL: /hardware/mx5x/libcamera,而这个HAL,其实就是要继承并实现
frameworks/base/include/camera/CameraHardwareInterface.h中的类:
calss CameraHardwareInterface

CameraHal.h:

  1. classCameraHal:publicCameraHardwareInterface{
  2. public:
  3. virtualsp<IMemoryHeap>getPreviewHeap()const;
  4. virtualsp<IMemoryHeap>getRawHeap()const;
  5. virtualvoidsetCallbacks(notify_callbacknotify_cb,
  6. data_callbackdata_cb,
  7. data_callback_timestampdata_cb_timestamp,
  8. void*user);
  9. virtualvoidenableMsgType(int32_tmsgType);
  10. virtualvoiddisableMsgType(int32_tmsgType);
  11. virtualboolmsgTypeEnabled(int32_tmsgType);
  12. virtualbooluseOverlay(){returntrue;}
  13. virtualstatus_tsetOverlay(constsp<Overlay>&overlay);
  14. virtualstatus_tstartPreview();
  15. virtualvoidstopPreview();
  16. virtualboolpreviewEnabled();
  17. virtualstatus_tstartRecording();
  18. virtualvoidstopRecording();
  19. virtualboolrecordingEnabled();
  20. virtualvoidreleaseRecordingFrame(constsp<IMemory>&mem);
  21. virtualstatus_tautoFocus();
  22. virtualstatus_tcancelAutoFocus();
  23. virtualstatus_ttakePicture();
  24. virtualstatus_tcancelPicture();
  25. virtualstatus_tdump(intfd,constVector<String16>&args)const;
  26. virtualstatus_tsetParameters(constCameraParameters&params);
  27. virtualCameraParametersgetParameters()const;
  28. virtualstatus_tsendCommand(int32_tcommand,int32_targ1,
  29. int32_targ2);
  30. virtualvoidrelease();
  31. CAMERA_HAL_ERR_RETsetCaptureDevice(sp<CaptureDeviceInterface>capturedevice);
  32. CAMERA_HAL_ERR_RETsetPostProcessDevice(sp<PostProcessDeviceInterface>postprocessdevice);
  33. CAMERA_HAL_ERR_RETsetJpegEncoder(sp<JpegEncoderInterface>jpegencoder);
  34. CAMERA_HAL_ERR_RETInit();
  35. voidsetPreviewRotate(CAMERA_PREVIEW_ROTATEpreviewRotate);
  36. CameraHal();
  37. virtual~CameraHal();
  38. private:
  39. //私有的成员太多就不列了
  40. };
CameraHal.cpp


getPreiwHeap: 获取preview data所在的内存地址。

这里有个类MemroyHeapBase,它是Android搞的一套基于Binder机制的对内存操作的类。用于创建共享内存。

  1. sp<IMemoryHeap>CameraHal::getPreviewHeap()const
  2. {
  3. CAMERA_HAL_LOG_FUNC;
  4. returnmPreviewHeap;
  5. }

mPreviewHeap 初始化:

  1. status_tCameraHal::PreparePreviwBuf()
  2. {
  3. CAMERA_HAL_LOG_FUNC;
  4. status_tret=NO_ERROR;
  5. unsignedinti=0;
  6. //templyhardcodehere
  7. if(mTakePicFlag==0){
  8. if(V4L2_PIX_FMT_NV12)
  9. mPreviewFrameSize=mCaptureDeviceCfg.width*mCaptureDeviceCfg.height*3/2;
  10. else
  11. mPreviewFrameSize=mCaptureDeviceCfg.width*mCaptureDeviceCfg.height*2;//获取preview帧大小
  12. //nowthepreviewfmtissupposedtobeYUV420SP,so,itisnowhardcodehere
  13. mPreviewHeap.clear();
  14. for(i=0;i<mPreviewHeapBufNum;i++)
  15. mPreviewBuffers[i].clear();
  16. mPreviewHeap=newMemoryHeapBase(mPreviewFrameSize*mPreviewHeapBufNum);
  17. if(mPreviewHeap==NULL)
  18. returnNO_MEMORY;
  19. for(i=0;i<mPreviewHeapBufNum;i++)
  20. mPreviewBuffers[i]=newMemoryBase(mPreviewHeap,mPreviewFrameSize*i,mPreviewFrameSize);
  21. }
  22. /*allocatethebufferforIPUprocess*/
  23. if(mPPDeviceNeed||mPPDeviceNeedForPic){
  24. mPmemAllocator=newPmemAllocator(mPPbufNum,mCaptureFrameSize);
  25. if(mPmemAllocator==NULL||mPmemAllocator->err_ret<0){
  26. returnNO_MEMORY;
  27. }
  28. for(i=0;i<mPPbufNum;i++){
  29. if(mPmemAllocator->allocate(&(mPPbuf[i]),mCaptureFrameSize)<0){
  30. returnNO_MEMORY;
  31. }
  32. }
  33. }
  34. returnret;
  35. }


  1. sp<IMemoryHeap>CameraHal::getRawHeap()const
  2. {
  3. returnNULL;
  4. }
  1. voidCameraHal::setCallbacks(notify_callbacknotify_cb,
  2. data_callbackdata_cb,
  3. data_callback_timestampdata_cb_timestamp,
  4. void*user)
  5. {
  6. Mutex::Autolocklock(mLock);
  7. mNotifyCb=notify_cb;
  8. mDataCb=data_cb;
  9. mDataCbTimestamp=data_cb_timestamp;
  10. mCallbackCookie=user;
  11. }
  12. /*
  13. 注册callback函数,callback的作用是在进行某些操作是可以返回相关的数据,例如takePicture时:
  14. 调用mDataCb(CAMERA_MSG_COMPRESSED_IMAGE,JpegMemBase,mCallbackCookie);则是告诉上层应用现在返回压缩好的jpeg数据(数据在JpegMemBase中)
  15. 但其实mx53的preiw是用overlay做,data_cb在preiw是没用
  16. */

virtual void enableMsgType(int32_t msgType);
virtual void disableMsgType(int32_t msgType);
virtual bool msgTypeEnabled(int32_t msgType);

这三个函数是设定在按下快门或对焦好或拍好照等之后要不要把相关的信息告诉上层(调用相关的callback)

virtual bool useOverlay() { return true; }
virtual status_t setOverlay(const sp<Overlay> &overlay);

使用overlay, overlay的概念? 太多内容了,简单地说就是把camera的数据直接写到framebuffer 而不经过android层,这在preview中很有用

这里有编博文可以参考http://zhougaofeng.ixiezi.com/2009/12/02/android-camera-preview-and-take-picture-with-v4l2/


virtual status_t startPreview();

看名称就知道是开始preview:

主要实现:

  1. status_tCameraHal::CameraHALStartPreview()
  2. {
  3. CAMERA_HAL_LOG_FUNC;
  4. status_tret=NO_ERROR;
  5. intmax_fps,min_fps;
  6. //一些基本参数,大小,旋转,名字(因为可能有多个camera)
  7. mParameters.getPreviewSize((int*)&(mCaptureDeviceCfg.width),(int*)&(mCaptureDeviceCfg.height));
  8. mCaptureDeviceCfg.fmt=mPreviewCapturedFormat;
  9. mCaptureDeviceCfg.rotate=(SENSOR_PREVIEW_ROTATE)mPreviewRotate;
  10. mCaptureDeviceCfg.tv.numerator=1;
  11. mCaptureDevice->GetDevName(mCameraSensorName);
  12. //camera有uvc和csi两种,具体是什么有什么区别我还真不知道
  13. if(strstr(mCameraSensorName,"uvc")==NULL){
  14. //accordingtogoogle'sdocgetPreviewFrameRate&getPreviewFpsRangeshouldsupportboth.
  15. //soherejustawalkaround,iftheappsettheframeRate,willfollowthisframerate.
  16. if(mParameters.getPreviewFrameRate()>=15)
  17. mCaptureDeviceCfg.tv.denominator=mParameters.getPreviewFrameRate();
  18. else{
  19. mParameters.getPreviewFpsRange(&min_fps,&max_fps);
  20. CAMERA_HAL_LOG_INFO("###startthecapturethefpsis%d###",max_fps);
  21. mCaptureDeviceCfg.tv.denominator=max_fps/1000;
  22. }
  23. }else{
  24. mCaptureDeviceCfg.tv.denominator=15;
  25. }
  26. mCaptureBufNum=PREVIEW_CAPTURE_BUFFER_NUM;
  27. mPPbufNum=POST_PROCESS_BUFFER_NUM;
  28. mTakePicFlag=false;
  29. //上一篇博文(驱动部分)有提到camerav4l2的使用
  30. if((ret=PrepareCaptureDevices())<0){
  31. CAMERA_HAL_ERR("PrepareCaptureDeviceserror");
  32. returnret;
  33. }
  34. if(mPPDeviceNeed){
  35. //预处理?不清楚。
  36. if((ret=PreparePostProssDevice())<0){
  37. CAMERA_HAL_ERR("PreparePostProssDeviceerror");
  38. returnret;
  39. }
  40. }
  41. if((ret=PreparePreviwBuf())<0){
  42. CAMERA_HAL_ERR("PreparePreviwBuferror");
  43. returnret;
  44. }
  45. //注册一下锁变量,主要是为了overlay和capture不冲突
  46. if((ret=PreparePreviwMisc())<0){
  47. CAMERA_HAL_ERR("PreparePreviwMiscerror");
  48. returnret;
  49. }
  50. //
  51. if((ret=CameraHALPreviewStart())<0){
  52. CAMERA_HAL_ERR("CameraHALPreviewStarterror");
  53. returnret;
  54. }
  55. returnret;
  56. }
  57. status_tCameraHal::CameraHALPreviewStart()
  58. {
  59. CAMERA_HAL_LOG_FUNC;
  60. status_tret=NO_ERROR;
  61. if(mCaptureDevice->DevStart()<0)//就是ioctl(mCameraDevice,VIDIOC_STREAMON,&type),此处fslmx53支持同时打开overlay和capture
  62. returnINVALID_OPERATION;
  63. mCaptureFrameThread=newCaptureFrameThread(this);
  64. mPreviewShowFrameThread=newPreviewShowFrameThread(this);
  65. mEncodeFrameThread=newEncodeFrameThread(this);
  66. if(mPPDeviceNeed){
  67. mPostProcessThread=newPostProcessThread(this);
  68. if(mPostProcessThread==NULL)
  69. returnUNKNOWN_ERROR;
  70. }
  71. if(mCaptureFrameThread==NULL||
  72. mPreviewShowFrameThread==NULL||
  73. mEncodeFrameThread==NULL){
  74. returnUNKNOWN_ERROR;
  75. }
  76. mPreviewRunning=true;
  77. returnret;
  78. }
  79. //上面函数的4条thread,其中postprocessthread没看不明白是做什么的(自动对焦?),下面稍微解析一下capture和showthread
  80. intCameraHal::captureframeThread()
  81. {
  82. CAMERA_HAL_LOG_FUNC;
  83. unsignedintDeqBufIdx=0;
  84. structtimespects;
  85. do{
  86. clock_gettime(CLOCK_REALTIME,&ts);
  87. ts.tv_nsec+=100000;//100ms
  88. }while(mPreviewRunning&&!error_status&&(sem_timedwait(&avab_dequeue_frame,&ts)!=0));
  89. //因为是几条thread一起工作,当然要做同步啦,其中avab_dequeue_frame就要去DevQueue之后才avaliable
  90. if(!mPreviewRunning||error_status)
  91. returnUNKNOWN_ERROR;
  92. mCaptureDevice->DevDequeue(&DeqBufIdx);//这个当然就是capture一帧数据到buffer中以备后用
  93. nCameraBuffersQueued--;
  94. buffer_index_maps[dequeue_head]=DeqBufIdx;//PrepareCaptureDevices时会query几个buffer,这里记住他的index
  95. dequeue_head++;
  96. dequeue_head%=mCaptureBufNum;
  97. //下面是同步的东西,没什么好说的。
  98. if(!mPPDeviceNeed){
  99. sem_post(&avab_show_frame);
  100. sem_post(&avab_enc_frame);
  101. }else{
  102. sem_post(&avab_pp_in_frame);
  103. }
  104. returnNO_ERROR;
  105. }
  106. intCameraHal::previewshowFrameThread()
  107. {
  108. CAMERA_HAL_LOG_FUNC;
  109. structtimespects;
  110. intdisplay_index=0;
  111. DMA_BUFFERInBuf;
  112. intqueue_back_index=0;
  113. do{
  114. clock_gettime(CLOCK_REALTIME,&ts);
  115. ts.tv_nsec+=100000;//100ms
  116. }while(!error_status&&mPreviewRunning&&(sem_timedwait(&avab_show_frame,&ts)!=0));
  117. if((mPreviewRunning==0)||error_status)
  118. returnUNKNOWN_ERROR;
  119. if(!mPPDeviceNeed){
  120. display_index=buffer_index_maps[display_head];
  121. InBuf=mCaptureBuffers[display_index];
  122. display_head++;
  123. display_head%=mCaptureBufNum;
  124. }else{
  125. display_index=display_head;
  126. InBuf=mPPbuf[display_index];
  127. display_head++;
  128. display_head%=mPPbufNum;
  129. }
  130. if(mMsgEnabled&CAMERA_MSG_PREVIEW_FRAME){
  131. convertNV12toYUV420SP((uint8_t*)(InBuf.virt_start),
  132. (uint8_t*)(mPreviewBuffers[preview_heap_buf_head]->pointer()),mCaptureDeviceCfg.width,mCaptureDeviceCfg.height);
  133. mDataCb(CAMERA_MSG_PREVIEW_FRAME,mPreviewBuffers[preview_heap_buf_head],mCallbackCookie);
  134. preview_heap_buf_head++;
  135. preview_heap_buf_head%=mPreviewHeapBufNum;
  136. }
  137. pthread_mutex_lock(&mOverlayMutex);
  138. if(mOverlay!=0){
  139. InBuf是从capture中QueueBuffer来的,放进了overlay之后怎么做其实没有看懂,fsl这方面写得很复杂,只知道它初始化时就分配了共享内存
  140. //ctx->data_shared,然后把buffer的地址传进去data_shared->queued_bufs[data_shared->queued_tail]=phy_addr,而有个很纠结的事情
  141. //是,它只调用了queueBuffer而没有调用DqueueBuffer,overlay中有一条专门的thread去处理queueBuffer后的数据。
  142. if(mOverlay->queueBuffer((overlay_buffer_t)InBuf.phy_offset)<0){
  143. CAMERA_HAL_ERR("queueBufferfailed.Maybebcosstreamwasnotturnedonyet.");
  144. }
  145. if(is_first_buffer){
  146. is_first_buffer=0;
  147. last_display_index=display_index;
  148. pthread_mutex_unlock(&mOverlayMutex);
  149. gotoshow_out;
  150. }
  151. }
  152. if(!mPPDeviceNeed){
  153. if(mOverlay!=0){
  154. queue_back_index=last_display_index;
  155. }else{
  156. queue_back_index=display_index;
  157. }
  158. }
  159. pthread_mutex_unlock(&mOverlayMutex);
  160. do{
  161. clock_gettime(CLOCK_REALTIME,&ts);
  162. ts.tv_nsec+=200000;//100ms
  163. }while((sem_timedwait(&avab_enc_frame_finish,&ts)!=0)&&!error_status&&mPreviewRunning);
  164. if(!mPPDeviceNeed){
  165. //queuethev4l2bufback
  166. if(mCaptureDevice->DevQueue(queue_back_index)<0){
  167. CAMERA_HAL_ERR("TheCapturedevicequeuebuferror!!!!");
  168. returnINVALID_OPERATION;
  169. }
  170. last_display_index=display_index;
  171. nCameraBuffersQueued++;
  172. sem_post(&avab_dequeue_frame);
  173. }else{
  174. sem_post(&avab_pp_out_frame);
  175. }
  176. show_out:
  177. returnNO_ERROR;
  178. }


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值