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;
- }
- 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);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- }
- 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
-
- 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);
-
- callback(frame);
- k = 0;
- is_find = true;
- break;
- }
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
如上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);
- 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);
-
-
-
-
-
-
- if ( NO_ERROR != ret ){
- CAMHAL_LOGEB("Display adapter resume failed %x", ret);
- }
- }
-
- if(mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME){
- mAppCallbackNotifier->enableMsgType (CAMERA_MSG_PREVIEW_FRAME);
- }
- return ret;
- }
- }
-
- 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);
-
-
-
-
-
-
-
- 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;
-
-
- 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;
- }