zoukankan      html  css  js  c++  java
  • 安卓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     }
  • 相关阅读:
    在Apache下开启SSI配置支持include shtml html和快速配置服务器
    GitHub命令精简教程
    php读取excel,以及php打包文件夹为zip文件
    Firebug中命令行栏(Commandlinie)的使用介绍和总结
    javascript判断设备类型-手机(mobile)、安卓(android)、电脑(pc)、其他(ipad/iPod/Windows)等
    jquery返回顶部-ie6配合css表达式。
    jquery.cycle.js简单用法实例
    原生javascript操作class-元素查找-元素是否存在-添加class-移除class
    常用css表达式-最小宽度-上下居中
    div模块变灰
  • 原文地址:https://www.cnblogs.com/zl1991/p/5151343.html
Copyright © 2011-2022 走看看