Android之Camera拍照

来源:互联网 发布:淘宝aj正品店 编辑:程序博客网 时间:2024/04/20 07:15
一、看看调用时序图

1.拍照命令时序图


2.拍照数据回调时序图


二、看看源码分析

hardware/amlogic/camera/CameraHal.cpp

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. status_t CameraHal::takePicture( ){  
  2.   ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_IMAGE_CAPTURE,  (int) &mStartCapture);  
  3. }  

调用父类方法:

hardware/amlogic/camera/BaseCameraAdapter.cpp

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  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

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  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

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  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

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  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

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. void CameraClient::handleShutter(void) {  
  2.   mCameraService->playSound(CameraService::SOUND_SHUTTER);  
  3. }  
frameworks/av/services/camera/libcameraservice/CameraService.cpp
[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  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

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  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

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. int V4LCameraAdapter::previewThread(){  
  2.   frame.mFrameMask |= CameraFrame::PREVIEW_FRAME_SYNC;  
  3.   ret = sendFrameToSubscribers(&frame);  
  4. }  
hardware/amlogic/camera/BaseCameraAdapter.cpp
[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  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
[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  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\n",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
[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  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.如何在应用层取消掉拍照的回调

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. camera.takePicture(shutterCallback, rawCallback, jpegCallback);  
  2. 改为  
  3. camera.takePicture(null, null, jpegCallback);  

原理如下:

frameworks/base/core/Java/Android/hardware/Camera.java

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  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.     }  
0 0