Android系统Camera参数设置&&Android之Camera拍照 && Android之Camera预览过程中插拔摄像头节点后移

本文详细解析了Android Camera应用中的参数对象、使用方法及CameraHAL的调用时序图,同时探讨了MediaRecorder在CameraSource使用的参数对象及实际应用。深入剖析了Camera拍照、录像及预览过程,包括数据回调时序图和声音回调机制。最后解决了拍照后应用程序不调用startPreview导致预览界面不再刷新的问题,并提供了预览画面刷屏机制的分析与解决方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://blog.youkuaiyun.com/tankai19880619/article/details/17120827

一、应用程序

1.Camera应用使用的参数对象

frameworks/base/core/java/android/hardware/Camera.java
  1. public class Parameters {  
  2.    
  3. }  

2.使用

Camera拍照预览:

packages/apps/Camera/src/com/android/camera/CameraModule.java

  1. mInitialParams = mCameraDevice.getParameters();  
  2. mInitialParams.getSupportedPreviewSizes();  
  3. mInitialParams.setPreviewSize(maxSize.width,maxSize.height);  
Camera拍照:
  1. mInitialParams.setPictureSize(maxSize.width,maxSize.height);  
  2. mCameraDevice.setParameters(mInitialParams);  
Camera录像预览:

packages/apps/Camera/src/com/android/camera/VideoModule.java

  1. InitialParams = vCameraDevice.getParameters();  
  2. vInitialParams.getSupportedVideoSizes();  
  3. mParameters.setPreviewSize();  
  4. vCameraDevice.setParameters(mParameters);  

二、MediaRecorder

1.CameraSource使用的参数对象

frameworks/av/camera/CameraParameters.cpp

  1. void CameraParameters::getVideoSize(int *width, int *height) const{  
  2.   
  3. }  

2.使用

frameworks/av/media/libstagefright/CameraSource.cpp

  1. status_t CameraSource::checkVideoSize(  
  2.          const CameraParameters& params,  
  3.          int32_t width, int32_t height) {  
  4.   params.getVideoSize(&frameWidthActual, &frameHeightActual);  
  5.   if (frameWidthActual != width || frameHeightActual != height) {  
  6.     ALOGE("Failed to set video frame size to %dx%d. " "The actual video size is %dx%d ", width, height, frameWidthActual, frameHeightActual);  
  7.   }  
  8. }  
三、CameraHAL

1.CameraHAL使用的参数对象

frameworks/av/camera/CameraParameters.cpp

2.使用

hardware/amlogic/camera/CameraHal.cpp

  1. int CameraHal::setParameters(const CameraParameters& params){  
  2.   //add by tank for CameraSource video recorder  
  3.   mParameters.setVideoSize(w,h);  
  4.   //end tan 2013-12-3  
  5.   // Handle RECORDING_HINT to Set/Reset Video Mode Parameters  

Android之Camera拍照


http://blog.youkuaiyun.com/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。

Android之Camera预览过程中插拔摄像头节点后移

http://blog.youkuaiyun.com/tankai19880619/article/details/17259257

现象:

在使用Camera Preview时;热插拔摄像头会导致设备节点由/dev/video0变为/dev/video1,或者插入多个video设备时,会变为/dev/video1、/dev/video2......。

一、首先看设备节点的创建

drivers/media/video/uvc/uvc_driver.c

  1. static int uvc_probe(struct usb_interface *intf,  
  2.               const struct usb_device_id *id){  
  3.   if (v4l2_device_register(&intf->dev, &dev->vdev) < 0)  
  4.     goto error;  
  5. }  

drivers/media/video/v4l2-devices.c

  1. int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)  
  2. {  
  3.   err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,  sd->owner);  
  4. }  

drivers/media/video/v4l2-dev.c

  1. int __video_register_device(struct video_device *vdev, int type, int nr,  
  2.          int warn_if_nr_in_use, struct module *owner){  
  3.   int nr = -1; int minor_cnt = 64;  
  4.   nr = devnode_find(vdev, nr == -1 ? 0 : nr, minor_cnt); //设备节点名,即“/dev/video*”  
  5.   vdev->num = nr;  
  6.   devnode_set(vdev); //该vdev->numd对应的符号被置为1  
  7.   /* 
  8.   devnode_set(vdev); //该vdev->numd对应的符号被置为1 
  9.   devnode_clear(vdev); //该vdev->numd对应的符号被置为0 
  10.   */  
  11.   name_base = "video";  
  12.   dev_set_name(&vdev->dev, "%s%d", name_base, vdev->num);  
  13.   ret = device_register(&vdev->dev);  
  14.   vdev->dev.release = v4l2_device_release; //该接口会调用devnode_clear(vdev)  
  15. }  

二、问题解决

最终修改,问题解决:

drivers/media/video/uvc/uvc_driver.c

  1. static void uvc_disconnect(struct usb_interface *intf){  
  2.   uvc_unregister_video(dev);  
  3. }  
  4. static void uvc_unregister_video(struct uvc_device *dev){  
  5.   video_unregister_device(stream->vdev); //修改该接口函数  
  6.   if (atomic_dec_and_test(&dev->nstreams)){  //这里也有些问题,但不是根本原因  
  7.     uvc_delete(dev);  
  8.   }  
  9. }  

我的修改:

drivers/media/video/v4l2-dev.c

  1. void video_unregister_device(struct video_device *vdev){  
  2.   devnode_clear(vdev);//add by tankai  
  3.   device_unregister(&vdev->dev); //该接口本身会调用v4l2_device_release,但却没有  
  4. }  
三、其他解决办法

1.这是一个网友在HAL层的解决办法

http://blog.youkuaiyun.com/rachel_rq/article/details/7545332

2.我们在HAL的解决办法

hardware/amlogic/camera/AppCallbackNotifier.cpp

  1. //All sub-components of Camera HAL call this whenever any error happens  
  2. void AppCallbackNotifier::errorNotify(int error)  
  3. {  
  4.     LOG_FUNCTION_NAME;  
  5.   
  6.   
  7.     CAMHAL_LOGEB("AppCallbackNotifier received error %d", error);  
  8.   
  9.   
  10.     // If it is a fatal error abort here!  
  11.     if((error == CAMERA_ERROR_FATAL) || (error == CAMERA_ERROR_HARD)) {  
  12.         //We kill media server if we encounter these errors as there is  
  13.         //no point continuing and apps also don't handle errors other  
  14.         //than media server death always.  
  15.         abort();  
  16.         return;  
  17.     }  
  18.   
  19.   
  20.     if (  ( NULL != mCameraHal ) &&  
  21.           ( NULL != mNotifyCb ) &&  
  22.           ( mCameraHal->msgTypeEnabled(CAMERA_MSG_ERROR) ) )  
  23.       {  
  24.         CAMHAL_LOGEB("AppCallbackNotifier mNotifyCb %d", error);  
  25.         mNotifyCb(CAMERA_MSG_ERROR, CAMERA_ERROR_UNKNOWN, 0, mCallbackCookie);  
  26.         mCameraHal->release(); //add by tankai  
  27.       }  
  28.   
  29.   
  30.     LOG_FUNCTION_NAME_EXIT;  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值