安卓camera拍照时序

转自:http://blog.csdn.net/tankai19880619/article/details/17147125

一、看看调用时序图

1.拍照命令时序图

2.拍照数据回调时序图

二、看看源码分析

hardware/amlogic/camera/CameraHal.cpp

1 status_t CameraHal::takePicture( ){
2   ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_IMAGE_CAPTURE,  (int) &mStartCapture);
3 }

调用父类方法:

hardware/amlogic/camera/BaseCameraAdapter.cpp

1 status_t BaseCameraAdapter::sendCommand(CameraCommands operation, int value1, int value2, int value3){
2   switch ( operation ) {
3     case CameraAdapter::CAMERA_START_IMAGE_CAPTURE:
4       ret = takePicture();
5   }
6 }

调用子类方法:

hardware/amlogic/camera/V4LCameraAdapter/V4LCameraAdapter.cpp

 
 1 status_t V4LCameraAdapter::takePicture(){
 2   if (createThread(beginPictureThread, this) == false)
 3     return -1;
 4 }
 5 /*static*/ int V4LCameraAdapter::beginPictureThread(void *cookie){
 6   V4LCameraAdapter *c = (V4LCameraAdapter *)cookie;
 7   return c->pictureThread();
 8 }
 9 int V4LCameraAdapter::pictureThread(){
10   ret = sendFrameToSubscribers(&frame);
11 }

调用父类方法:

hardware/amlogic/camera/BaseCameraAdapter.cpp

 1 status_t BaseCameraAdapter::sendFrameToSubscribers(CameraFrame *frame){
 2   ret = __sendFrameToSubscribers(frame, &mImageSubscribers, CameraFrame::IMAGE_FRAME);
 3 /*
 4 //如上callback的设置
 5 hardware/amlogic/camera/CameraHal.cpp
 6 status_t CameraHal::initialize(CameraProperties::Properties* properties){
 7   mAppCallbackNotifier->setEventProvider(eventMask, mCameraAdapter);
 8   mAppCallbackNotifier->setFrameProvider(mCameraAdapter);
 9 }
10 
11 hardware/amlogic/camera/AppCallbackNotifier.cpp 
12 void AppCallbackNotifier::setFrameProvider(FrameNotifier *frameNotifier){
13   mFrameProvider = new FrameProvider(frameNotifier, this, frameCallbackRelay);
14   mFrameProvider->enableFrameNotification(CameraFrame::IMAGE_FRAME);
15   mFrameProvider->enableFrameNotification(CameraFrame::RAW_FRAME);
16 }
17 
18 hardware/amlogic/camera/inc/CamerHal.h 
19 class FrameProvider{
20   public:
21     FrameProvider(FrameNotifier *fn, void* cookie, frame_callback frameCallback)
22                   :mFrameNotifier(fn), mCookie(cookie),mFrameCallback(frameCallback) { }
23 }
24 hardware/amlogic/camera/CameraHalUtilClasses.cpp
25 int FrameProvider::enableFrameNotification(int32_t frameTypes){
26   mFrameNotifier->enableMsgType(frameTypes<<MessageNotifier::FRAME_BIT_FIELD_POSITION
27                                 , mFrameCallback
28                                 , NULL
29                                 , mCookie);
30 }
31 hardware/amlogic/camera/BaseCameraAdapter.cpp
32 void BaseCameraAdapter::enableMsgType(int32_t msgs, frame_callback callback, event_callback eventCb, void* cookie){
33   if ( CameraFrame::PREVIEW_FRAME_SYNC == msgs ){
34     mFrameSubscribers.add((int) cookie, callback);
35   }
36   else if ( CameraFrame::IMAGE_FRAME == msgs){
37     mImageSubscribers.add((int) cookie, callback);
38   }
39   else if ( CameraFrame::RAW_FRAME == msgs){
40     mRawSubscribers.add((int) cookie, callback);
41   }
42 }
43 //以下callback就是frameCallbackRelay
44 //callbak-》subscribers-》mImageSubscribers-》mImageSubscribers.add((int) cookie, callback)-》mFrameCallback-》frameCallbackRelay
45 */
46 }
47 status_t BaseCameraAdapter::__sendFrameToSubscribers(CameraFrame* frame,
48      KeyedVector<int, frame_callback> *subscribers,
49      CameraFrame::FrameType frameType){
50   callback = (frame_callback) subscribers->valueAt(k);
51   callback(frame);
52 }

该回调函数即是:

hardware/amlogic/camera/AppCallbackNotifier.cpp

 1 void AppCallbackNotifier::frameCallbackRelay(CameraFrame* caFrame){
 2   appcbn->frameCallback(caFrame);
 3 }
 4 void AppCallbackNotifier::frameCallback(CameraFrame* caFrame){
 5   msg.command = AppCallbackNotifier::NOTIFIER_CMD_PROCESS_FRAME;
 6   msg.arg1 = frame;
 7   mFrameQ.put(&msg);
 8 }
 9 void AppCallbackNotifier::notifyFrame(){
10   mFrameQ.get(&msg);
11   sp<Encoder_libjpeg> encoder = new Encoder_libjpeg(main_jpeg, tn_jpeg,
12     AppCallbackNotifierEncoderCallback,
13     (CameraFrame::FrameType)frame->mFrameType,
14     this,raw_picture,exif_data);
15 }

补充——拍照是声音的回调如下:

frameworks/av/services/camera/libcameraservice/CameraClient.cpp

1 void CameraClient::handleShutter(void) {
2   mCameraService->playSound(CameraService::SOUND_SHUTTER);
3 }

frameworks/av/services/camera/libcameraservice/CameraService.cpp

1 //mSoundPlayer[SOUND_SHUTTER] = newMediaPlayer("/system/media/audio/ui/camera_click.ogg");
2 void CameraService::playSound(sound_kind kind) {
3 
4 
5 }

源码中位置:

frameworks/base/data/sounds/OriginalAudio.mk

1 $(LOCAL_PATH)/effects/camera_click.ogg:system/media/audio/ui/camera_click.ogg

frameworks/base/data/sounds/effects/camera_click.ogg

三、项目问题

拍照后,应用程序不调用startPreview导致预览界面不再刷新:

1.看看预览部分CameraHAL的处理

hardware/amlogic/camera/V4LCameraAdapter/V4LCameraAdapter.cpp

1 int V4LCameraAdapter::previewThread(){
2   frame.mFrameMask |= CameraFrame::PREVIEW_FRAME_SYNC;
3   ret = sendFrameToSubscribers(&frame);
4 }

hardware/amlogic/camera/BaseCameraAdapter.cpp

 
 1 status_t BaseCameraAdapter::sendFrameToSubscribers(CameraFrame *frame){
 2   ret = __sendFrameToSubscribers(frame, &mFrameSubscribers, CameraFrame::PREVIEW_FRAME_SYNC);
 3 }
 4 status_t BaseCameraAdapter::__sendFrameToSubscribers(CameraFrame* frame,
 5                                                       KeyedVector<int, frame_callback> *subscribers,
 6                                                       CameraFrame::FrameType frameType){
 7   while(k<subscribers->size()){
 8     callback = (frame_callback) subscribers->valueAt(k);
 9     for(uint32_t i = 0; i<subscribers_ref.size();i++){
10       if((frame->mCookie == ( void * ) subscribers_ref.keyAt(i))&&(subscribers_ref.valueAt(i) == 0)){
11       subscribers_ref.replaceValueFor((uint32_t)frame->mCookie,1);
12       //CAMHAL_LOGDB("Frame callbback is available, cookie:0x%x, callback:0x%x",(uint32_t)frame->mCookie,(uint32_t)callback);
13       callback(frame);
14       k = 0;
15       is_find = true;
16       break;
17     }
18   }
19 }
20 /*
21 //如上callback的设置
22 hardware/amlogic/camera/CameraHal.cpp
23 //设置APP回调函数
24 status_t CameraHal::initialize(CameraProperties::Properties* properties){
25   mAppCallbackNotifier->setEventProvider(eventMask, mCameraAdapter);
26   mAppCallbackNotifier->setFrameProvider(mCameraAdapter);
27 }
28 //设置刷屏回调函数
29 status_t CameraHal::setPreviewWindow(struct preview_stream_ops *window){
30   mDisplayAdapter->setFrameProvider(mCameraAdapter);
31   mDisplayAdapter->setErrorHandler(mAppCallbackNotifier.get());
32   ret  = mDisplayAdapter->setPreviewWindow(window);
33 }
34 status_t CameraHal::startPreview(){
35   ret = mDisplayAdapter->enableDisplay(width, height, NULL, isS3d ? &s3dParams : NULL);
36 }
37 
38 //设置APP回调函数
39 hardware/amlogic/camera/AppCallbackNotifier.cpp 
40 void AppCallbackNotifier::setFrameProvider(FrameNotifier *frameNotifier){
41   mFrameProvider = new FrameProvider(frameNotifier, this, frameCallbackRelay);
42   mFrameProvider->enableFrameNotification(CameraFrame::IMAGE_FRAME);
43   mFrameProvider->enableFrameNotification(CameraFrame::RAW_FRAME);
44 }
45 
46 //设置刷屏回调函数
47 hardware/amlogic/camera/ANativeWindowDisplayAdapter.cpp
48 int ANativeWindowDisplayAdapter::setFrameProvider(FrameNotifier *frameProvider){
49   mFrameProvider = new FrameProvider(frameProvider, this, frameCallbackRelay);
50 }
51 int ANativeWindowDisplayAdapter::enableDisplay(int width, int height, struct timeval *refTime, S3DParameters *s3dParams){
52   mFrameProvider->enableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC);
53 }
54 
55 //最终设置地方
56 hardware/amlogic/camera/inc/CamerHal.h 
57 class FrameProvider{
58   public:
59     FrameProvider(FrameNotifier *fn, void* cookie, frame_callback frameCallback)
60                   :mFrameNotifier(fn), mCookie(cookie),mFrameCallback(frameCallback) { }
61 }
62 hardware/amlogic/camera/CameraHalUtilClasses.cpp
63 int FrameProvider::enableFrameNotification(int32_t frameTypes){
64   mFrameNotifier->enableMsgType(frameTypes<<MessageNotifier::FRAME_BIT_FIELD_POSITION
65                                 , mFrameCallback
66                                 , NULL
67                                 , mCookie);
68 }
69 hardware/amlogic/camera/BaseCameraAdapter.cpp
70 void BaseCameraAdapter::enableMsgType(int32_t msgs, frame_callback callback, event_callback eventCb, void* cookie){
71   if ( CameraFrame::PREVIEW_FRAME_SYNC == msgs ){
72     mFrameSubscribers.add((int) cookie, callback);
73   }
74   else if ( CameraFrame::IMAGE_FRAME == msgs){
75     mImageSubscribers.add((int) cookie, callback);
76   }
77   else if ( CameraFrame::RAW_FRAME == msgs){
78     mRawSubscribers.add((int) cookie, callback);
79 }
80 }
81 */

如上callback即是ANativeWindowDisplayAdapter.cpp/AppCallbackNotifier.cpp中的frameCallbackRelay,我们分析预览画面只需要关心ANativeWindowDisplayAdapter.cpp(AppCallbackNotifier.cpp是例如拍照和录像,需要将数据送给APP):

hardware/amlogic/camera/ANativeWindowDisplayAdapter.cpp

 1 void ANativeWindowDisplayAdapter::frameCallbackRelay(CameraFrame* caFrame){
 2   da->frameCallback(caFrame);
 3 }
 4 void ANativeWindowDisplayAdapter::frameCallback(CameraFrame* caFrame){
 5   PostFrame(df);
 6 }
 7 status_t ANativeWindowDisplayAdapter::PostFrame(ANativeWindowDisplayAdapter::DisplayFrame &dispFrame){
 8   LOGD("TK----->>>>mPaused is %d
",mPaused);//add by tankai
 9   if ( mDisplayState == ANativeWindowDisplayAdapter::DISPLAY_STARTED &&
10                 (!mPaused ||  CameraFrame::CameraFrame::SNAPSHOT_FRAME == dispFrame.mType) &&
11                 !mSuspend){
12     ret = mANativeWindow->enqueue_buffer(mANativeWindow, mBufferHandleMap[i]);
13     mFramesWithCameraAdapterMap.removeItem((int) dispFrame.mBuffer);
14   }
15   else{
16     ret = mANativeWindow->cancel_buffer(mANativeWindow, mBufferHandleMap[i]);
17     mFramesWithCameraAdapterMap.removeItem((int) dispFrame.mBuffer);
18   }
19 }

2.问题分析

从如上可以看出:mPaused为true表示暂停刷屏,mPaused为false表示开始刷屏;我们的问题就出在这里。

hardware/camera/CameraHal.cpp

 1 status_t CameraHal::startPreview(){
 2   if( (mDisplayAdapter.get() != NULL) && ( !mPreviewEnabled ) && ( mDisplayPaused ) ){
 3     CAMHAL_LOGDA("Preview is in paused state");
 4     mDisplayPaused = false;
 5     mPreviewEnabled = true;
 6     if ( NO_ERROR == ret ){
 7       ret = mDisplayAdapter->pauseDisplay(mDisplayPaused); //重新开始预览
 8 /*
 9 hardware/amlogic/camera/ANativeWindowDisplayAdapter.cpp
10 status_t ANativeWindowDisplayAdapter::pauseDisplay(bool pause){
11   mPaused = pause;
12 }
13 */
14       if ( NO_ERROR != ret ){
15         CAMHAL_LOGEB("Display adapter resume failed %x", ret);
16       }
17     }
18     //restart preview callbacks
19     if(mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME){
20       mAppCallbackNotifier->enableMsgType (CAMERA_MSG_PREVIEW_FRAME);
21     }
22     return ret;
23   }
24 }
25 //拍照时将mPaused置为false,暂停刷屏:
26 status_t CameraHal::takePicture( ){
27   if (NO_ERROR == ret &&
28     NULL != mDisplayAdapter.get() && burst < 1) {
29     if (mCameraAdapter->getState() != CameraAdapter::VIDEO_STATE) {
30       mDisplayPaused = true;
31       mPreviewEnabled = false;
32       ret = mDisplayAdapter->pauseDisplay(mDisplayPaused); //暂停预览
33 /*
34 hardware/amlogic/camera/ANativeWindowDisplayAdapter.cpp
35 status_t ANativeWindowDisplayAdapter::pauseDisplay(bool pause){
36   mPaused = pause;
37 }
38 */
39       // since preview is paused we should stop sending preview frames too
40       if(mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) {
41         mAppCallbackNotifier->disableMsgType (mMsgEnabled & CAMERA_MSG_POSTVIEW_FRAME);
42         CAMHAL_LOGDA("disable MSG_PREVIEW_FRAME");
43       }
44     }
45 
46 #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
47      mDisplayAdapter->setSnapshotTimeRef(&mStartCapture);
48 #endif
49   }
50 
51 }

3.问题解决

应用层在take_picture之后主动调用startpreview将mPaused改为false;

如果不需要应用主动调用,则需要在HAL将startpreview设为false。

4.如何在应用层取消掉拍照的回调

1 camera.takePicture(shutterCallback, rawCallback, jpegCallback);
2 改为
3 camera.takePicture(null, null, jpegCallback);

原理如下:

frameworks/base/core/java/android/hardware/Camera.java

 1 public final void takePicture(ShutterCallback shutter, PictureCallback raw,
 2             PictureCallback postview, PictureCallback jpeg) {
 3         mShutterCallback = shutter;
 4         mRawImageCallback = raw;
 5         mPostviewCallback = postview;
 6         mJpegCallback = jpeg;
 7 
 8         // If callback is not set, do not send me callbacks.
 9         int msgType = 0;
10         if (mShutterCallback != null) {
11             msgType |= CAMERA_MSG_SHUTTER;
12         }
13         if (mRawImageCallback != null) {
14             msgType |= CAMERA_MSG_RAW_IMAGE;
15         }
16         if (mPostviewCallback != null) {
17             msgType |= CAMERA_MSG_POSTVIEW_FRAME;
18         }
19         if (mJpegCallback != null) {
20             msgType |= CAMERA_MSG_COMPRESSED_IMAGE;
21         }
22 
23         native_takePicture(msgType);
24         mFaceDetectionRunning = false;
25     }
原文地址:https://www.cnblogs.com/zl1991/p/5151343.html