安卓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\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
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 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了