Android之Camera拍照

来源:互联网 发布:oracle找回删除数据 编辑:程序博客网 时间:2024/04/26 19:20

一、看看调用时序图

1.拍照命令时序图


2.拍照数据回调时序图


二、看看源码分析

hardware/amlogic/camera/CameraHal.cpp

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

调用父类方法:

hardware/amlogic/camera/BaseCameraAdapter.cpp

status_t BaseCameraAdapter::sendCommand(CameraCommands operation, int value1, int value2, int value3){  switch ( operation ) {    case CameraAdapter::CAMERA_START_IMAGE_CAPTURE:      ret = takePicture();  }}

调用子类方法:

hardware/amlogic/camera/V4LCameraAdapter/V4LCameraAdapter.cpp

status_t V4LCameraAdapter::takePicture(){  if (createThread(beginPictureThread, this) == false)    return -1;}/*static*/ int V4LCameraAdapter::beginPictureThread(void *cookie){  V4LCameraAdapter *c = (V4LCameraAdapter *)cookie;  return c->pictureThread();}int V4LCameraAdapter::pictureThread(){  ret = sendFrameToSubscribers(&frame);}

调用父类方法:

hardware/amlogic/camera/BaseCameraAdapter.cpp

status_t BaseCameraAdapter::sendFrameToSubscribers(CameraFrame *frame){  ret = __sendFrameToSubscribers(frame, &mImageSubscribers, CameraFrame::IMAGE_FRAME);/*//如上callback的设置hardware/amlogic/camera/CameraHal.cppstatus_t CameraHal::initialize(CameraProperties::Properties* properties){  mAppCallbackNotifier->setEventProvider(eventMask, mCameraAdapter);  mAppCallbackNotifier->setFrameProvider(mCameraAdapter);}hardware/amlogic/camera/AppCallbackNotifier.cpp void AppCallbackNotifier::setFrameProvider(FrameNotifier *frameNotifier){  mFrameProvider = new FrameProvider(frameNotifier, this, frameCallbackRelay);  mFrameProvider->enableFrameNotification(CameraFrame::IMAGE_FRAME);  mFrameProvider->enableFrameNotification(CameraFrame::RAW_FRAME);}hardware/amlogic/camera/inc/CamerHal.h class FrameProvider{  public:    FrameProvider(FrameNotifier *fn, void* cookie, frame_callback frameCallback)                  :mFrameNotifier(fn), mCookie(cookie),mFrameCallback(frameCallback) { }}hardware/amlogic/camera/CameraHalUtilClasses.cppint FrameProvider::enableFrameNotification(int32_t frameTypes){  mFrameNotifier->enableMsgType(frameTypes<<MessageNotifier::FRAME_BIT_FIELD_POSITION                                , mFrameCallback                                , NULL                                , mCookie);}hardware/amlogic/camera/BaseCameraAdapter.cppvoid BaseCameraAdapter::enableMsgType(int32_t msgs, frame_callback callback, event_callback eventCb, void* cookie){  if ( CameraFrame::PREVIEW_FRAME_SYNC == msgs ){    mFrameSubscribers.add((int) cookie, callback);  }  else if ( CameraFrame::IMAGE_FRAME == msgs){    mImageSubscribers.add((int) cookie, callback);  }  else if ( CameraFrame::RAW_FRAME == msgs){    mRawSubscribers.add((int) cookie, callback);  }}//以下callback就是frameCallbackRelay//callbak-》subscribers-》mImageSubscribers-》mImageSubscribers.add((int) cookie, callback)-》mFrameCallback-》frameCallbackRelay*/}status_t BaseCameraAdapter::__sendFrameToSubscribers(CameraFrame* frame,     KeyedVector<int, frame_callback> *subscribers,     CameraFrame::FrameType frameType){  callback = (frame_callback) subscribers->valueAt(k);  callback(frame);}

该回调函数即是:

hardware/amlogic/camera/AppCallbackNotifier.cpp

void AppCallbackNotifier::frameCallbackRelay(CameraFrame* caFrame){  appcbn->frameCallback(caFrame);}void AppCallbackNotifier::frameCallback(CameraFrame* caFrame){  msg.command = AppCallbackNotifier::NOTIFIER_CMD_PROCESS_FRAME;  msg.arg1 = frame;  mFrameQ.put(&msg);}void AppCallbackNotifier::notifyFrame(){  mFrameQ.get(&msg);  sp<Encoder_libjpeg> encoder = new Encoder_libjpeg(main_jpeg, tn_jpeg,    AppCallbackNotifierEncoderCallback,    (CameraFrame::FrameType)frame->mFrameType,    this,raw_picture,exif_data);}

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

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

void CameraClient::handleShutter(void) {  mCameraService->playSound(CameraService::SOUND_SHUTTER);}
frameworks/av/services/camera/libcameraservice/CameraService.cpp
//mSoundPlayer[SOUND_SHUTTER] = newMediaPlayer("/system/media/audio/ui/camera_click.ogg");void CameraService::playSound(sound_kind kind) {}
源码中位置:

frameworks/base/data/sounds/OriginalAudio.mk

$(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

int V4LCameraAdapter::previewThread(){  frame.mFrameMask |= CameraFrame::PREVIEW_FRAME_SYNC;  ret = sendFrameToSubscribers(&frame);}
hardware/amlogic/camera/BaseCameraAdapter.cpp
status_t BaseCameraAdapter::sendFrameToSubscribers(CameraFrame *frame){  ret = __sendFrameToSubscribers(frame, &mFrameSubscribers, CameraFrame::PREVIEW_FRAME_SYNC);}status_t BaseCameraAdapter::__sendFrameToSubscribers(CameraFrame* frame,                                                      KeyedVector<int, frame_callback> *subscribers,                                                      CameraFrame::FrameType frameType){  while(k<subscribers->size()){    callback = (frame_callback) subscribers->valueAt(k);    for(uint32_t i = 0; i<subscribers_ref.size();i++){      if((frame->mCookie == ( void * ) subscribers_ref.keyAt(i))&&(subscribers_ref.valueAt(i) == 0)){      subscribers_ref.replaceValueFor((uint32_t)frame->mCookie,1);      //CAMHAL_LOGDB("Frame callbback is available, cookie:0x%x, callback:0x%x",(uint32_t)frame->mCookie,(uint32_t)callback);      callback(frame);      k = 0;      is_find = true;      break;    }  }}/*//如上callback的设置hardware/amlogic/camera/CameraHal.cpp//设置APP回调函数status_t CameraHal::initialize(CameraProperties::Properties* properties){  mAppCallbackNotifier->setEventProvider(eventMask, mCameraAdapter);  mAppCallbackNotifier->setFrameProvider(mCameraAdapter);}//设置刷屏回调函数status_t CameraHal::setPreviewWindow(struct preview_stream_ops *window){  mDisplayAdapter->setFrameProvider(mCameraAdapter);  mDisplayAdapter->setErrorHandler(mAppCallbackNotifier.get());  ret  = mDisplayAdapter->setPreviewWindow(window);}status_t CameraHal::startPreview(){  ret = mDisplayAdapter->enableDisplay(width, height, NULL, isS3d ? &s3dParams : NULL);}//设置APP回调函数hardware/amlogic/camera/AppCallbackNotifier.cpp void AppCallbackNotifier::setFrameProvider(FrameNotifier *frameNotifier){  mFrameProvider = new FrameProvider(frameNotifier, this, frameCallbackRelay);  mFrameProvider->enableFrameNotification(CameraFrame::IMAGE_FRAME);  mFrameProvider->enableFrameNotification(CameraFrame::RAW_FRAME);}//设置刷屏回调函数hardware/amlogic/camera/ANativeWindowDisplayAdapter.cppint ANativeWindowDisplayAdapter::setFrameProvider(FrameNotifier *frameProvider){  mFrameProvider = new FrameProvider(frameProvider, this, frameCallbackRelay);}int ANativeWindowDisplayAdapter::enableDisplay(int width, int height, struct timeval *refTime, S3DParameters *s3dParams){  mFrameProvider->enableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC);}//最终设置地方hardware/amlogic/camera/inc/CamerHal.h class FrameProvider{  public:    FrameProvider(FrameNotifier *fn, void* cookie, frame_callback frameCallback)                  :mFrameNotifier(fn), mCookie(cookie),mFrameCallback(frameCallback) { }}hardware/amlogic/camera/CameraHalUtilClasses.cppint FrameProvider::enableFrameNotification(int32_t frameTypes){  mFrameNotifier->enableMsgType(frameTypes<<MessageNotifier::FRAME_BIT_FIELD_POSITION                                , mFrameCallback                                , NULL                                , mCookie);}hardware/amlogic/camera/BaseCameraAdapter.cppvoid BaseCameraAdapter::enableMsgType(int32_t msgs, frame_callback callback, event_callback eventCb, void* cookie){  if ( CameraFrame::PREVIEW_FRAME_SYNC == msgs ){    mFrameSubscribers.add((int) cookie, callback);  }  else if ( CameraFrame::IMAGE_FRAME == msgs){    mImageSubscribers.add((int) cookie, callback);  }  else if ( CameraFrame::RAW_FRAME == msgs){    mRawSubscribers.add((int) cookie, callback);}}*/

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

hardware/amlogic/camera/ANativeWindowDisplayAdapter.cpp
void ANativeWindowDisplayAdapter::frameCallbackRelay(CameraFrame* caFrame){  da->frameCallback(caFrame);}void ANativeWindowDisplayAdapter::frameCallback(CameraFrame* caFrame){  PostFrame(df);}status_t ANativeWindowDisplayAdapter::PostFrame(ANativeWindowDisplayAdapter::DisplayFrame &dispFrame){  LOGD("TK----->>>>mPaused is %d\n",mPaused);//add by tankai  if ( mDisplayState == ANativeWindowDisplayAdapter::DISPLAY_STARTED &&                (!mPaused ||  CameraFrame::CameraFrame::SNAPSHOT_FRAME == dispFrame.mType) &&                !mSuspend){    ret = mANativeWindow->enqueue_buffer(mANativeWindow, mBufferHandleMap[i]);    mFramesWithCameraAdapterMap.removeItem((int) dispFrame.mBuffer);  }  else{    ret = mANativeWindow->cancel_buffer(mANativeWindow, mBufferHandleMap[i]);    mFramesWithCameraAdapterMap.removeItem((int) dispFrame.mBuffer);  }}
2.问题分析

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

hardware/camera/CameraHal.cpp
status_t CameraHal::startPreview(){  if( (mDisplayAdapter.get() != NULL) && ( !mPreviewEnabled ) && ( mDisplayPaused ) ){    CAMHAL_LOGDA("Preview is in paused state");    mDisplayPaused = false;    mPreviewEnabled = true;    if ( NO_ERROR == ret ){      ret = mDisplayAdapter->pauseDisplay(mDisplayPaused); //重新开始预览/*hardware/amlogic/camera/ANativeWindowDisplayAdapter.cppstatus_t ANativeWindowDisplayAdapter::pauseDisplay(bool pause){  mPaused = pause;}*/      if ( NO_ERROR != ret ){        CAMHAL_LOGEB("Display adapter resume failed %x", ret);      }    }    //restart preview callbacks    if(mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME){      mAppCallbackNotifier->enableMsgType (CAMERA_MSG_PREVIEW_FRAME);    }    return ret;  }}//拍照时将mPaused置为false,暂停刷屏:status_t CameraHal::takePicture( ){  if (NO_ERROR == ret &&    NULL != mDisplayAdapter.get() && burst < 1) {    if (mCameraAdapter->getState() != CameraAdapter::VIDEO_STATE) {      mDisplayPaused = true;      mPreviewEnabled = false;      ret = mDisplayAdapter->pauseDisplay(mDisplayPaused); //暂停预览/*hardware/amlogic/camera/ANativeWindowDisplayAdapter.cppstatus_t ANativeWindowDisplayAdapter::pauseDisplay(bool pause){  mPaused = pause;}*/      // since preview is paused we should stop sending preview frames too      if(mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) {        mAppCallbackNotifier->disableMsgType (mMsgEnabled & CAMERA_MSG_POSTVIEW_FRAME);        CAMHAL_LOGDA("disable MSG_PREVIEW_FRAME");      }    }#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS     mDisplayAdapter->setSnapshotTimeRef(&mStartCapture);#endif  }}
3.问题解决

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

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

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

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

原理如下:

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

public final void takePicture(ShutterCallback shutter, PictureCallback raw,            PictureCallback postview, PictureCallback jpeg) {        mShutterCallback = shutter;        mRawImageCallback = raw;        mPostviewCallback = postview;        mJpegCallback = jpeg;        // If callback is not set, do not send me callbacks.        int msgType = 0;        if (mShutterCallback != null) {            msgType |= CAMERA_MSG_SHUTTER;        }        if (mRawImageCallback != null) {            msgType |= CAMERA_MSG_RAW_IMAGE;        }        if (mPostviewCallback != null) {            msgType |= CAMERA_MSG_POSTVIEW_FRAME;        }        if (mJpegCallback != null) {            msgType |= CAMERA_MSG_COMPRESSED_IMAGE;        }        native_takePicture(msgType);        mFaceDetectionRunning = false;    }


原创粉丝点击