一、看看调用时序图
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.cpp status_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.cpp int FrameProvider::enableFrameNotification(int32_t frameTypes){ mFrameNotifier->enableMsgType(frameTypes<<MessageNotifier::FRAME_BIT_FIELD_POSITION , mFrameCallback , NULL , mCookie); } hardware/amlogic/camera/BaseCameraAdapter.cpp void 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.cpp int 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.cpp int FrameProvider::enableFrameNotification(int32_t frameTypes){ mFrameNotifier->enableMsgType(frameTypes<<MessageNotifier::FRAME_BIT_FIELD_POSITION , mFrameCallback , NULL , mCookie); } hardware/amlogic/camera/BaseCameraAdapter.cpp void 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.cppvoid 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.cppstatus_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.cpp status_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.cpp status_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; }