已阅读5页,还剩16页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Android Camera HAL3中预览preview模式下的控制流本文均属自己阅读源码的点滴总结,转账请注明出处谢谢。欢迎和大家交流。qq:1037701636 email:Software:系统源码Android5.1Camera3研读前沿: 当初在研读Camera1.0相关的内容时,主要围绕着CameraClient、CameraHardwareInterface等方面进行工作的开展,无论是数据流还是控制流看起来都很简单、明了,一系列的流程化操作使得整个框架学起来特别的容易。因为没有Camera2.0相关的基础,所以这次直接看3.0相关的源码时,显得十分的吃紧,再加上底层高通HAL3.0实现的过程也是相当的复杂,都给整个研读过程带来了很多的困难。可以说,自身目前对Camera3.0框架的熟悉度也大概只有70%左右,希望通过总结来进一步梳理他的工作原理与整个框架,并进一步熟悉与加深理解。1.Camera3下的整体架构图。整个CameraService建立起一个可用操作底层Camera device大致需要经过Camera2Client、Camera3Device以及HAL层的camera3_device_t三个部分。从上图中可以发现Camera3架构看上去明显比camera1来的复杂,但他更加的模块化。对比起Android4.2.2 Camer系统架构图(HAL和回调处理)一文中描述的单顺序执行流程,Camera3将更多的工作集中在了Framework去完成,将更多的控制权掌握在自己的手里,从而与HAL的交互的数据信息更少,也进一步减轻了一些在旧版本中HAL层所需要做的事情。2. Camera2Client的建立与初始化过程在建立好Camera2Client后会进行initialize操作,完成各个处理模块的创建:cppview plaincopy1. .2. StreamingProcessor=newStreamingProcessor(this);/preview和recorder3. threadName=String8:format(C2-%d-StreamProc,4. mCameraId);5. mStreamingProcessor-run(threadName.string();/预览与录像6. 7. mFrameProcessor=newFrameProcessor(mDevice,this);/3A8. threadName=String8:format(C2-%d-FrameProc,9. mCameraId);10. mFrameProcessor-run(threadName.string();/3A11. 12. mCaptureSequencer=newCaptureSequencer(this);13. threadName=String8:format(C2-%d-CaptureSeq,14. mCameraId);15. mCaptureSequencer-run(threadName.string();/录像,拍照16. 17. mJpegProcessor=newJpegProcessor(this,mCaptureSequencer);18. threadName=String8:format(C2-%d-JpegProc,19. mCameraId);20. mJpegProcessor-run(threadName.string();21. .22. mCallbackProcessor=newCallbackProcessor(this);/回调处理23. threadName=String8:format(C2-%d-CallbkProc,24. mCameraId);25. mCallbackProcessor-run(threadName.string();依次分别创建了:StreamingProcessor并启动一个他所属的thread,该模块主要负责处理previews与record两种视频流的处理,用于从hal层获取原始的视频数据FrameProcessor并启动一个thread,该模块专门用于处理回调回来的每一帧的3A等信息,即每一帧视频除去原始视频数据外,还应该有其他附加的数据信息,如3A值。CaptureSequencer并启动一个thread,该模块需要和其他模块配合使用,主要用于向APP层告知capture到的picture。JpegProcessor并启动一个thread,该模块和streamprocessor类似,他启动一个拍照流,一般用于从HAL层获取jpeg编码后的图像照片数据。此外ZslProcessor模块称之为0秒快拍,其本质是直接从原始的Preview流中获取预存着的最近的几帧,直接编码后返回给APP,而不需要再经过take picture去请求获取jpeg数据。0秒快拍技术得意于当下处理器CSI2 MIPI性能的提升以及Sensor支持全像素高帧率的实时输出。一般手机拍照在按下快门后都会有一定的延时,是因为需要切换底层Camera以及ISP等的工作模式,并重新设置参数以及重新对焦等等,都需要花一定时间后才抓取一帧用于编码为jpeg图像。以上5个模块整合在一起基本上实现了Camera应用开发所需的基本业务功能。3. 预览Preview下的控制流研读Camera具体的业务处理功能,一般从视频实时预览Preview入手。一般熟悉Camera架构的人,可以从一个app端的一个api一直连续打通到底层hal的一个控制命令。大致可以如下图所示:对于preview部分到CameraService的控制流可以参考博文Android4.2.2的preview的数据流和控制流以及最终的预览显示,本文将直接从Camera2Client:startPreview() 作为入口来分析整个Framework层中Preview相关的数据流。cppview plaincopy1. status_tCamera2Client:startPreview()2. ATRACE_CALL();3. ALOGV(%s:E,_FUNCTION_);4. Mutex:Autolockicl(mBinderSerializationLock);5. status_tres;6. if(res=checkPid(_FUNCTION_)!=OK)returnres;7. SharedParameters:Lockl(mParameters);8. returnstartPreviewL(l.mParameters,false);9. startPreview通过startPreviewL提取参数后真正的开始执行Preview相关的控制流。该函数看上去内容虽然较多,但基本采用了同一种处理方式:cppview plaincopy1. status_tCamera2Client:startPreviewL(Parametersms,boolrestart)/restart=false2. ATRACE_CALL();3. status_tres;4. .5. intlastPreviewStreamId=mStreamingProcessor-getPreviewStreamId();/获取上一层Previewstreamid6. 7. res=mStreamingProcessor-updatePreviewStream(params);/创建camera3devicestream,Camera3OutputStream8. .9. intlastJpegStreamId=mJpegProcessor-getStreamId();10. res=updateProcessorStream(mJpegProcessor,params);/预览启动时就建立一个jpeg的outstream11. .12. res=mCallbackProcessor-updateStream(params);/回调处理建立一个Camera3outputstream13. if(res!=OK)14. ALOGE(%s:Camera%d:Unabletoupdatecallbackstream:%s(%d),15. _FUNCTION_,mCameraId,strerror(-res),res);16. returnres;17. 18. outputStreams.push(getCallbackStreamId();19. .20. outputStreams.push(getPreviewStreamId();/预览stream21. .22. if(!params.recordingHint)23. if(!restart)24. res=mStreamingProcessor-updatePreviewRequest(params);/request处理,更新了mPreviewrequest25. if(res!=OK)26. ALOGE(%s:Camera%d:Cantsetuppreviewrequest:27. %s(%d),_FUNCTION_,mCameraId,28. strerror(-res),res);29. returnres;30. 31. 32. res=mStreamingProcessor-startStream(StreamingProcessor:PREVIEW,33. outputStreams);/启动stream,传入outputStreams即stream的id34. else35. if(!restart)36. res=mStreamingProcessor-updateRecordingRequest(params);37. if(res!=OK)38. ALOGE(%s:Camera%d:Cantsetuppreviewrequestwith39. recordhint:%s(%d),_FUNCTION_,mCameraId,40. strerror(-res),res);41. returnres;42. 43. 44. res=mStreamingProcessor-startStream(StreamingProcessor:RECORD,45. outputStreams);46. 47. .48. (1). mStreamingProcessor-updatePreviewStream()由预览与录像处理模块更新一个预览流,其实现过程如下:cppview plaincopy1. status_tStreamingProcessor:updatePreviewStream(constParametersms)2. ATRACE_CALL();3. Mutex:Autolockm(mMutex);4. 5. status_tres;6. spdevice=mDmote();/Camera3Device7. if(device=0)8. ALOGE(%s:Camera%d:Devicedoesnotexist,_FUNCTION_,mId);9. returnINVALID_OPERATION;10. 11. 12. if(mPreviewStreamId!=NO_STREAM)13. /Checkifstreamparametershavetochange14. uint32_tcurrentWidth,currentHeight;15. res=device-getStreamInfo(mPreviewStreamId,16. tWidth,tHeight,0);17. if(res!=OK)18. ALOGE(%s:Camera%d:Errorqueryingpreviewstreaminfo:19. %s(%d),_FUNCTION_,mId,strerror(-res),res);20. returnres;21. 22. if(currentWidth!=(uint32_t)params.previewWidth|23. currentHeight!=(uint32_t)params.previewHeight)24. ALOGV(%s:Camera%d:Previewsizeswitch:%dx%d-%dx%d,25. _FUNCTION_,mId,currentWidth,currentHeight,26. params.previewWidth,params.previewHeight);27. res=device-waitUntilDrained();28. if(res!=OK)29. ALOGE(%s:Camera%d:Errorwaitingforpreviewtodrain:30. %s(%d),_FUNCTION_,mId,strerror(-res),res);31. returnres;32. 33. res=device-deleteStream(mPreviewStreamId);34. if(res!=OK)35. ALOGE(%s:Camera%d:Unabletodeleteoldoutputstream36. forpreview:%s(%d),_FUNCTION_,mId,37. strerror(-res),res);38. returnres;39. 40. mPreviewStreamId=NO_STREAM;41. 42. 43. 44. if(mPreviewStreamId=NO_STREAM)/首次createstream45. res=device-createStream(mPreviewWindow,46. params.previewWidth,params.previewHeight,47. CAMERA2_HAL_PIXEL_FORMAT_OPAQUE,&mPreviewStreamId);/创建一个Camera3OutputStream48. if(res!=OK)49. ALOGE(%s:Camera%d:Unabletocreatepreviewstream:%s(%d),50. _FUNCTION_,mId,strerror(-res),res);51. returnres;52. 53. 54. 55. res=device-setStreamTransform(mPreviewStreamId,56. params.previewTransform);57. if(res!=OK)58. ALOGE(%s:Camera%d:Unabletosetpreviewstreamtransform:59. %s(%d),_FUNCTION_,mId,strerror(-res),res);60. returnres;61. 62. 63. returnOK;64. 该函数首先是查看当前StreamingProcessor模块下是否存在Stream,没有的话,则交由Camera3Device创建一个stream。显然,一个StreamingProcessor只能拥有一个PreviewStream,而一个Camera3Device显然控制着所有的Stream。注意:在Camera2Client中,Stream大行其道,5大模块的数据交互均以stream作为基础。下面我们来重点关注Camera3Device的接口createStream,他是5个模块创建stream的基础:cppview plaincopy1. status_tCamera3Device:createStream(spconsumer,2. uint32_twidth,uint32_theight,intformat,int*id)3. ATRACE_CALL();4. Mutex:Autolockil(mInterfaceLock);5. Mutex:Autolockl(mLock);6. ALOGV(Camera%d:Creatingnewstream%d:%dx%d,format%d,7. mId,mNextStreamId,width,height,format);8. 9. status_tres;10. boolwasActive=false;11. 12. switch(mStatus)13. caseSTATUS_ERROR:14. CLOGE(Devicehasencounteredaseriouserror);15. returnINVALID_OPERATION;16. caseSTATUS_UNINITIALIZED:17. CLOGE(Devicenotinitialized);18. returnINVALID_OPERATION;19. caseSTATUS_UNCONFIGURED:20. caseSTATUS_CONFIGURED:21. /OK22. break;23. caseSTATUS_ACTIVE:24. ALOGV(%s:Stoppingactivitytoreconfigurestreams,_FUNCTION_);25. res=internalPauseAndWaitLocked();26. if(res!=OK)27. SET_ERR_L(Cantpausecapturestoreconfigurestreams!);28. returnres;29. 30. wasActive=true;31. break;32. default:33. SET_ERR_L(Unexpectedstatus:%d,mStatus);34. returnINVALID_OPERATION;35. 36. assert(mStatus!=STATUS_ACTIVE);37. 38. spnewStream;39. if(format=HAL_PIXEL_FORMAT_BLOB)/图片40. ssize_tjpegBufferSize=getJpegBufferSize(width,height);41. if(jpegBufferSizesetStatusTracker(mStatusTracker);53. 54. res=mOutputStreams.add(mNextStreamId,newStream);/一个streamid与Camera3OutputStream绑定55. if(res0)56. SET_ERR_L(Cantaddnewstreamtoset:%s(%d),strerror(-res),res);57. returnres;58. 59. 60. *id=mNextStreamId+;/至少一个previewstream一般还有CallbackStream61. mNeedConfig=true;62. 63. /Continuecapturesifactiveatstart64. if(wasActive)65. ALOGV(%s:Restartingactivitytoreconfigurestreams,_FUNCTION_);66. res=configureStreamsLocked();67. if(res!=OK)68. CLOGE(Cantreconfiguredevicefornewstream%d:%s(%d),69. mNextStreamId,strerror(-res),res);70. returnres;71. 72. internalResumeLocked();73. 74. ALOGV(Camera%d:Creatednewstream,mId);75. returnOK;76. 该函数重点是关注一个new Camera3OutputStream,在Camera3Device主要存在Camera3OutputStream和Camera3InputStream两种stream,前者主要作为HAL的输出,是请求HAL填充数据的OutPutStream,后者是由Framework将Stream进行填充。无论是Preview、record还是capture均是从HAL层获取数据,故都会以OutPutStream的形式存在,是我们关注的重点,后面在描述Preview的数据流时还会进一步的阐述。每当创建一个OutPutStream后,相关的stream信息被push维护在一个mOutputStreams的KeyedVectorint, sp 表中,分别是该stream在Camera3Device中创建时的ID以及Camera3OutputStream的sp值。同时对mNextStreamId记录下一个Stream的ID号。上述过程完成StreamingProcessor模块中一个PreviewStream的创建,其中Camera3OutputStream创建时的ID值被返回记录作为mPreviewStreamId的值,此外每个Stream都会有一个对应的ANativeWindow,这里称之为Consumer。(2)mCallbackProcessor-updateStream(params)对比StreamingProcessor模块创建previewstream的过程,很容易定位到Callback模块是需要建立一个callback流,同样需要创建一个Camera3OutputStream来接收HAL返回的每一帧帧数据,是否需要callback可以通过callbackenable来控制。一般但预览阶段可能不需要回调每一帧的数据到APP,但涉及到相应的其他业务如视频处理时,就需要进行callback的enable。cppview plaincopy1. status_tCallbackProcessor:updateStream(constParametersms)2. ATRACE_CALL();3. status_tres;4. 5. Mutex:Autolockl(mInputMutex);6. 7. spdevice=mDmote();8. if(device=0)9. ALOGE(%s:Camera%d:Devicedoesnotexist,_FUNCTION_,mId);10. returnINVALID_OPERATION;11. 12. 13. /Ifpossible,usetheflexibleYUVformat14. int32_tcallbackFormat=params.previewFormat;15. if(mCallbackToApp)16. /TODO:etalvala:ThisshouldusetheflexibleYUVformataswell,but17. /needtoreconcileHAL2/HAL3requirements.18. callbackFormat=HAL_PIXEL_FORMAT_YV12;19. elseif(params.fastInfo.useFlexibleYuv&20. (params.previewFormat=HAL_PIXEL_FORMAT_YCrCb_420_SP|21. params.previewFormat=HAL_PIXEL_FORMAT_YV12)22. callbackFormat=HAL_PIXEL_FORMAT_YCbCr_420_888;23. 24. 25. if(!mCallbackToApp&mCallbackConsumer=0)26. /CreateCPUbufferqueueendpoint,sinceapphasntgivenusone27. /Makeitasynctoavoiddisconnectdeadlocks28. spproducer;29. spconsumer;30. BufferQueue:createBufferQueue(&producer,&consumer);/BufferQueueProducer与BufferQueueConsumer31. mCallbackConsumer=newCpuConsumer(consumer,kCallbackHeapCount);32. mCallbackConsumer-setFrameAvailableListener(this);/当前CallbackProcessor继承于CpuConsumer:FrameAvailableListener33. mCallbackConsumer-setName(String8(Camera2Client:CallbackConsumer);34. mCallbackWindow=newSurface(producer);/用于queue操作,这里直接进行本地的buffer操作35. 36. 37. if(mCallbackStreamId!=NO_STREAM)38. /Checkifstreamparametershavetochange39. uint32_tcurrentWidth,currentHeight,currentFormat;40. res=device-getStreamInfo(mCallbackStreamId,41. tWidth,tHeight,tFormat);42. if(res!=OK)43. ALOGE(%s:Camera%d:Errorqueryingcallbackoutputstreaminfo:44. %s(%d),_FUNCTION_,mId,45. strerror(-res),res);46. returnres;47. 48. if(currentWidth!=(uint32_t)params.previewWidth|49. currentHeight!=(uint32_t)params.previewHeight|50. currentFormat!=(uint32_t)callbackFormat)51. /Sincesizeshouldonlychangewhilepreviewisnotrunning,52. /assumingthatallexistinguseofoldcallbackstreamis53. /completed.54. ALOGV(%s:Camera%d:Deletingstream%dsincethebuffer55. parameterschanged,_FUNCTION_,mId,mCallbackStreamId);56. res=device-deleteStream(mCallbackStreamId);57. if(res!=OK)58. ALOGE(%s:Camera%d:Unabletodeleteoldoutputstream59. forcallbacks:%s(%d),_FUNCTION_,60. mId,strerror(-res),res);61. returnres;62. 63. mCallbackStreamId=NO_STREAM;64. 65. 66. 67. if(mCallbackStreamId=NO_STREAM)68. ALOGV(Creatingcallbackstream:%dx%d,format0x%x,APIformat0x%x,69. params.previewWidth,params.previewHeight,70. callbackFormat,params.previewFormat);71. res=device-createStream(mCallbackWindow,72. params.previewWidth,params.previewHeight,73. callbackFormat,&mCallbackStreamId);/Creatingcallbackstream74. if(res!=OK)75. ALOGE(%s:Camera%d:Cantcreateoutputstreamforcallbacks:76. %s(%d),_FUNCTION_,mId,77. strerror(-res),res);78. returnres;79. 80. 81. 82. returnOK;83. 对比updatePreviewStream可以发现,该函数自助创建了一套surface/BufferQueue/CpuConsumer的机制,这套类似SurfaceFlinger的buffer管理机制可参看一文Android5.1中surface生产者和消费者间的处理框架简述。此外通过createStream请求Camera3Device建立一个Stream,其中Stream的ID值保存在mCallBackStreamId当中,并将一个CallbackWindow和当前的Stream绑定。通过这个对比,也需要重点关注到,对于每个Camera3OutPutStream来说,每一个stream都被一个Consumer,而在此处都是Surface(ANativeWindow)所拥有,这个Consumer和HAL相匹配来说是消费者,但对于真正的处理Buffer的Consumer来说如CPUConsumer,Surface却又是以一个Product的角色存在的。(3)updateProcessorStream(mJpegProcessor, params)cppview plaincopy1. status_tCamera2Client:updateProcessorStream(spprocessor,2. camera2:Parametersparams)3.
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 棉花育种项目可行性研究报告
- 南通科技面试题目及答案
- 中医药发竞赛题目及答案
- 2026年中国高性能云服务器行业市场规模及投资前景预测分析报告
- 2026年中国高强模具石膏粉行业市场规模及投资前景预测分析报告
- 医疗集团分公司总经理面试问题及应答技巧
- 2026年智能工厂设计合同
- 电子绝缘材料上胶工安全生产基础知识能力考核试卷含答案
- 异丁烷装置操作工复试测试考核试卷含答案
- 乳清工安全行为测试考核试卷含答案
- 青兰高速甘肃平凉段“7·26”重大道路交通事故调查报告
- 国有土地上房屋征收社会稳定风险评估报告
- 设计部经理转正汇报
- 银发经济创业项目计划书
- 陕旅版三年级英语下册教案导学案
- T-CNITA 05103-2018 袋式除尘用水刺非织造滤料
- 老年人春季常见病预防
- 《调查报告》课件
- 2025届高考语文一轮复习散文阅读考点二概括内容分析形象教学案
- 社区管理第四版 课件全套 汪大海 第1-19章 社区与社区管理 -突发事件与社区应急管理
- 幕墙工程专项施工方案(危大工程专家论证)
评论
0/150
提交评论