Android Camera HAL3中预览preview模式下的控制流.docx
《Android Camera HAL3中预览preview模式下的控制流.docx》由会员分享,可在线阅读,更多相关《Android Camera HAL3中预览preview模式下的控制流.docx(34页珍藏版)》请在冰豆网上搜索。
AndroidCameraHAL3中预览preview模式下的控制流
AndroidCameraHAL3中预览preview模式下的控制流
本文均属自己阅读源码的点滴总结,转账请注明出处谢谢。
欢迎和大家交流。
qq:
1037701636email:
gzzaigcn2009@
Software:
系统源码Android5.1
Camera3研读前沿:
当初在研读Camera1.0相关的内容时,主要围绕着CameraClient、CameraHardwareInterface等方面进行工作的开展,无论是数据流还是控制流看起来都很简单、明了,一系列的流程化操作使得整个框架学起来特别的容易。
因为没有Camera2.0相关的基础,所以这次直接看3.0相关的源码时,显得十分的吃紧,再加上底层高通HAL3.0实现的过程也是相当的复杂,都给整个研读过程带来了很多的困难。
可以说,自身目前对Camera3.0框架的熟悉度也大概只有70%左右,希望通过总结来进一步梳理他的工作原理与整个框架,并进一步熟悉与加深理解。
1.Camera3下的整体架构图。
整个CameraService建立起一个可用操作底层Cameradevice大致需要经过Camera2Client、Camera3Device以及HAL层的camera3_device_t三个部分。
从上图中可以发现Camera3架构看上去明显比camera1来的复杂,但他更加的模块化。
对比起Android4.2.2Camer系统架构图(HAL和回调处理)一文中描述的单顺序执行流程,Camera3将更多的工作集中在了Framework去完成,将更多的控制权掌握在自己的手里,从而与HAL的交互的数据信息更少,也进一步减轻了一些在旧版本中HAL层所需要做的事情。
2.Camera2Client的建立与初始化过程
在建立好Camera2Client后会进行initialize操作,完成各个处理模块的创建:
[cpp] viewplaincopy
1. ....
2.StreamingProcessor = new StreamingProcessor(this);//preview和recorder
3. threadName = String8:
:
format("C2-%d-StreamProc",
4. mCameraId);
5. mStreamingProcessor->run(threadName.string());//预览与录像
6.
7. mFrameProcessor = new FrameProcessor(mDevice, this);// 3A
8. threadName = String8:
:
format("C2-%d-FrameProc",
9. mCameraId);
10. mFrameProcessor->run(threadName.string()); //3A
11.
12. mCaptureSequencer = new CaptureSequencer(this);
13. threadName = String8:
:
format("C2-%d-CaptureSeq",
14. mCameraId);
15. mCaptureSequencer->run(threadName.string());//录像,拍照
16.
17. mJpegProcessor = new JpegProcessor(this, mCaptureSequencer);
18. threadName = String8:
:
format("C2-%d-JpegProc",
19. mCameraId);
20. mJpegProcessor->run(threadName.string());
21....
22.mCallbackProcessor = new CallbackProcessor(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,而不需要再经过takepicture去请求获取jpeg数据。
0秒快拍技术得意于当下处理器CSI2MIPI性能的提升以及Sensor支持全像素高帧率的实时输出。
一般手机拍照在按下快门后都会有一定的延时,是因为需要切换底层Camera以及ISP等的工作模式,并重新设置参数以及重新对焦等等,都需要花一定时间后才抓取一帧用于编码为jpeg图像。
以上5个模块整合在一起基本上实现了Camera应用开发所需的基本业务功能。
3.预览Preview下的控制流
研读Camera具体的业务处理功能,一般从视频实时预览Preview入手。
一般熟悉Camera架构的人,可以从一个app端的一个api一直连续打通到底层hal的一个控制命令。
大致可以如下图所示:
对于preview部分到CameraService的控制流可以参考博文Android4.2.2的preview的数据流和控制流以及最终的预览显示,本文将直接从Camera2Client:
:
startPreview()作为入口来分析整个Framework层中Preview相关的数据流。
[cpp] viewplaincopy
1.status_t Camera2Client:
:
startPreview() {
2. ATRACE_CALL();
3. ALOGV("%s:
E", __FUNCTION__);
4. Mutex:
:
Autolock icl(mBinderSerializationLock);
5. status_t res;
6. if ( (res = checkPid(__FUNCTION__) ) !
= OK) return res;
7. SharedParameters:
:
Lock l(mParameters);
8. return startPreviewL(l.mParameters, false);
9.}
startPreview通过startPreviewL提取参数后真正的开始执行Preview相关的控制流。
该函数看上去内容虽然较多,但基本采用了同一种处理方式:
[cpp] viewplaincopy
1.status_t Camera2Client:
:
startPreviewL(Parameters ¶ms, bool restart) {//restart == false
2. ATRACE_CALL();
3. status_t res;
4.......
5. int lastPreviewStreamId = mStreamingProcessor->getPreviewStreamId();//获取上一层Preview stream id
6.
7. res = mStreamingProcessor->updatePreviewStream(params);//创建camera3device stream, Camera3OutputStream
8......
9. int lastJpegStreamId = mJpegProcessor->getStreamId();
10. res = updateProcessorStream(mJpegProcessor, params);//预览启动时就建立一个jpeg的outstream
11......
12. res = mCallbackProcessor->updateStream(params);//回调处理建立一个Camera3outputstream
13. if (res !
= OK) {
14. ALOGE("%s:
Camera %d:
Unable to update callback stream:
%s (%d)",
15. __FUNCTION__, mCameraId, strerror(-res), res);
16. return res;
17. }
18. outputStreams.push(getCallbackStreamId());
19.......
20. outputStreams.push(getPreviewStreamId());//预览stream
21.......
22. if (!
params.recordingHint) {
23. if (!
restart) {
24. res = mStreamingProcessor->updatePreviewRequest(params);//request处理,更新了mPreviewrequest
25. if (res !
= OK) {
26. ALOGE("%s:
Camera %d:
Can't set up preview request:
"
27. "%s (%d)", __FUNCTION__, mCameraId,
28. strerror(-res), res);
29. return res;
30. }
31. }
32. res = mStreamingProcessor->startStream(StreamingProcessor:
:
PREVIEW,
33. outputStreams);//启动stream,传入outputStreams即stream 的id
34. } else {
35. if (!
restart) {
36. res = mStreamingProcessor->updateRecordingRequest(params);
37. if (res !
= OK) {
38. ALOGE("%s:
Camera %d:
Can't set up preview request with "
39. "record hint:
%s (%d)", __FUNCTION__, mCameraId,
40. strerror(-res), res);
41. return res;
42. }
43. }
44. res = mStreamingProcessor->startStream(StreamingProcessor:
:
RECORD,
45. outputStreams);
46. }
47.......
48.}
(1).mStreamingProcessor->updatePreviewStream()
由预览与录像处理模块更新一个预览流,其实现过程如下:
[cpp] viewplaincopy
1.status_t StreamingProcessor:
:
updatePreviewStream(const Parameters ¶ms) {
2. ATRACE_CALL();
3. Mutex:
:
Autolock m(mMutex);
4.
5. status_t res;
6. sp device = mDevice.promote();//Camera3Device
7. if (device == 0) {
8. ALOGE("%s:
Camera %d:
Device does not exist", __FUNCTION__, mId);
9. return INVALID_OPERATION;
10. }
11.
12. if (mPreviewStreamId !
= NO_STREAM) {
13. // Check if stream parameters have to change
14. uint32_t currentWidth, currentHeight;
15. res = device->getStreamInfo(mPreviewStreamId,
16. ¤tWidth, ¤tHeight, 0);
17. if (res !
= OK) {
18. ALOGE("%s:
Camera %d:
Error querying preview stream info:
"
19. "%s (%d)", __FUNCTION__, mId, strerror(-res), res);
20. return res;
21. }
22. if (currentWidth !
= (uint32_t)params.previewWidth ||
23. currentHeight !
= (uint32_t)params.previewHeight) {
24. ALOGV("%s:
Camera %d:
Preview size switch:
%d x %d -> %d x %d",
25. __FUNCTION__, mId, currentWidth, currentHeight,
26. params.previewWidth, params.previewHeight);
27. res = device->waitUntilDrained();
28. if (res !
= OK) {
29. ALOGE("%s:
Camera %d:
Error waiting for preview to drain:
"
30. "%s (%d)", __FUNCTION__, mId, strerror(-res), res);
31. return res;
32. }
33. res = device->deleteStream(mPreviewStreamId);
34. if (res !
= OK) {
35. ALOGE("%s:
Camera %d:
Unable to delete old output stream "
36. "for preview:
%s (%d)", __FUNCTION__, mId,
37. strerror(-res), res);
38. return res;
39. }
40. mPreviewStreamId = NO_STREAM;
41. }
42. }
43.
44. if (mPreviewStreamId == NO_STREAM) {//首次create stream
45. res = device->createStream(mPreviewWindow,
46. params.previewWidth, params.previewHeight,
47. CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, &mPreviewStreamId);//创建一个Camera3OutputStream
48. if (res !
= OK) {
49. ALOGE("%s:
Camera %d:
Unable to create preview stream:
%s (%d)",
50. __FUNCTION__, mId, strerror(-res), res);
51. return res;
52. }
53. }
54.
55. res = device->setStreamTransform(mPreviewStreamId,
56. params.previewTransform);
57. if (res !
= OK) {
58. ALOGE("%s:
Camera %d:
Unable to set preview stream transform:
"
59. "%s (%d)", __FUNCTION__, mId, strerror(-res), res);
60. return res;
61. }
62.
63. return OK;
64.}
该函数首先是查看当前StreamingProcessor模块下是否存在Stream,没有的话,则交由Camera3Device创建一个stream。
显然,一个StreamingProcessor只能拥有一个PreviewStream,而一个Camera3Device显然控制着所有的Stream。
注意:
在Camera2Client中,Stream大行其道,5大模块的数据交互均以stream作为基础。
下面我们来重点关注Camera3Device的接口createStream,他是5个模块创建stream的基础:
[cpp] viewplaincopy
1.status_t Camera3Device:
:
createStream(sp consumer,
2. uint32_t width, uint32_t height, int format, int *id) {
3. ATRACE_CALL();
4. Mutex:
:
Autolock il(mInterfaceLock);
5. Mutex:
:
Autolock l(mLock);
6. ALOGV("Camera %d:
Creating new stream %d:
%d x %d, format %d",
7. mId, mNextStreamId, width, height, format);
8.
9. status_t res;
10. bool wasActive = false;
11.
12. switch (mStatus) {
13. case STATUS_ERROR:
14. CLOGE("Device has encountered a serious error");
15. return INVALID_OPERATION;
16. case STATUS_UNINITIALIZED:
17. CLOGE("Device not initialized");
18. return INVALID_OPERATION;
19. case STATUS_UNCONFIGURED:
20. case STATUS_CONFIGURED:
21. // OK
22. break;
23. case STATUS_ACTIVE:
24. ALOGV("%s:
Stopping activity to reconf