转自:http://blog.csdn.net/tankai19880619/article/details/17147125

一、看看调用时序图

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.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.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;
}

安卓camera拍照时序的更多相关文章

  1. android Camera拍照 及 MediaRecorder录像 预览图像差90度

    Camera拍照: 今天做照相机程序,结果写好了发现出问题了,预览的图像差90度.相关源代码如下: Camera.Parameters params = camera.getParameters(); ...

  2. [置顶] android系统如何在静音模式下关闭camera拍照声音(2)

    之前写过一篇“android系统如何在静音模式下关闭camera拍照声音”的博客,今天来写他的续篇,继续探讨这个问题. 公司新需求,要求在camera应用中添加一个开关,可以进行拍照声音的关闭和开启. ...

  3. Android开发技巧——Camera拍照功能

    本篇是我对开发项目的拍照功能过程中,对Camera拍照使用的总结.由于camera2是在api level 21(5.0.1)才引入的,而Camera到6.0仍可使用,所以暂未考虑camera2. 文 ...

  4. Android--使用Camera拍照

    前言 在开发Android应用的时候,如果需要调用摄像头获取拍摄的照片,除了通过Intent调用系统现有相机应用拍摄照片之外,还可以通过直接调用Camera硬件去去获取摄像头拍摄的照片.本篇博客将讲解 ...

  5. Android 修改Camera拍照的默认保存路径

    前言          欢迎大家我分享和推荐好用的代码段~~ 声明          欢迎转载,但请保留文章原始出处:          CSDN:http://www.csdn.net        ...

  6. 腾讯优测-优社区干货精选 |  那些年,我们在Android机型适配上遇到的坑之Camera拍照时快门咔嚓声

    文/腾讯优测研发工程师 吴宇焕 优测小优有话说: android机型适配的坑自然是不少,不想掉坑快来优测优社区~ 现在Android手机一般都会带有照相功能,有很多朋友就发现手机照相时快门声音很响,想 ...

  7. 安卓Camera APP

    一.Camera package android.hardware            该类用于设定图像捕获设置,开启/关闭预览,抓拍图片以及获取帧用于编码视频.这个类是Camera服务的客户端,用 ...

  8. Android Camera 拍照 三星BUG总结

    Android Camera 三星BUG  : 近期在Android项目中使用拍照功能 , 其他型号的手机执行成功了  只有在三星的相机上遇到了bug . BUG详细体现为 : (1) 摄像头拍照后图 ...

  9. 【Python】Camera拍照休眠唤醒测试

    #!/usr/bin/python # -*- coding: UTF-8 -*- import os import sys import time rebootCount = int(input(& ...

随机推荐

  1. 【BZOJ 1052】 1052: [HAOI2007]覆盖问题 (乱搞)

    1052: [HAOI2007]覆盖问题 Description 某人在山上种了N棵小树苗.冬天来了,温度急速下降,小树苗脆弱得不堪一击,于是树主人想用一些塑料薄 膜把这些小树遮盖起来,经过一番长久的 ...

  2. 【状态压缩DP】NOIP2005-river过河

    [问题描述] 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看 ...

  3. python3-开发进阶-RESTful 软件架构风格

    一. 什么是RESTful REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移” REST从资源的角 ...

  4. 找出N个数中最小的k个数问题(复杂度O(N*logk))

    这是一个经典的算法题,下面给出的算法都在给定的数组基础上进行,好处时不用分配新的空间,坏处是会破坏原有的数组,可以自己分配新的空间以避免对原有数组的破坏. 思路一 先直接排序,再取排序后数据的前k个数 ...

  5. html5上传图片php特殊处理一下

    $file=$_POST['file']; if($file) { preg_match('|data:image/([a-zA-Z]+);base64,|s',$file,$match); $fil ...

  6. Codeforces Round #127 (Div. 1) B. Guess That Car! 扫描线

    B. Guess That Car! 题目连接: http://codeforces.com/contest/201/problem/B Description A widely known amon ...

  7. SQL Server--CheckPoint

    http://www.cnblogs.com/TeyGao/category/526201.html

  8. 邮件发送过去24小时的自增长事件(MSSQL)

    此脚本需要启用DBMail以支持邮件的发送.可设为每日运行的JOB以追踪自增长事件,以便做出适当的调整. -- Email the Auto-growth events that have occur ...

  9. 虚函数&纯虚函数&抽象类&虚继承

    C++ 虚函数&纯虚函数&抽象类&接口&虚基类   1. 多态 在面向对象语言中,接口的多种不同实现方式即为多态.多态是指,用父类的指针指向子类的实例(对象),然后通过 ...

  10. jquery ajax 中不能给变量赋值的原因及解决办法

    我们在用JQuery的Ajax从后台提取数据后想把它赋值给全局变量,但是却怎么都赋不进,为什么呢? 原因其实很简单,我们用的Ajax是异步操作,也就是说在你赋值的时候数据还没提取出来,你当然赋不进去, ...