咱們就仍是看看在這裏都作了些什麼事情 java
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { // Make sure we have a surface in the holder before proceeding. if (holder.getSurface() == null) { Log.d(TAG, "holder.getSurface() == null"); return; } Log.v(TAG, "surfaceChanged. w=" + w + ". h=" + h); // We need to save the holder for later use, even when the mCameraDevice // is null. This could happen if onResume() is invoked after this // function. mSurfaceHolder = holder; // The mCameraDevice will be null if it fails to connect to the camera // hardware. In this case we will show a dialog and then finish the // activity, so it's OK to ignore it. if (mCameraDevice == null) return; // Sometimes surfaceChanged is called after onPause or before onResume. // Ignore it. if (mPausing || isFinishing()) return; setSurfaceLayout(); // Set preview display if the surface is being created. Preview was // already started. Also restart the preview if display rotation has // changed. Sometimes this happens when the device is held in portrait // and camera app is opened. Rotation animation takes some time and // display rotation in onCreate may not be what we want. if (mCameraState == PREVIEW_STOPPED) {//這裏表示第一次打開camera時,那麼調用startpreview startPreview(true); startFaceDetection(); } else {//這裏則表示camera已經打開過程當中發生的顯示變化,好比橫屏豎頻轉換,因此zheli只須要從新設置previewdisplay if (Util.getDisplayRotation(this) != mDisplayRotation) { setDisplayOrientation(); } if (holder.isCreating()) { // Set preview display if the surface is being created and preview // was already started. That means preview display was set to null // and we need to set it now. setPreviewDisplay(holder); } } // If first time initialization is not finished, send a message to do // it later. We want to finish surfaceChanged as soon as possible to let // user see preview first. if (!mFirstTimeInitialized) { mHandler.sendEmptyMessage(FIRST_TIME_INIT); } else { initializeSecondTime(); } SurfaceView preview = (SurfaceView) findViewById(R.id.camera_preview); CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId]; boolean mirror = (info.facing == CameraInfo.CAMERA_FACING_FRONT); int displayRotation = Util.getDisplayRotation(this); int displayOrientation = Util.getDisplayOrientation(displayRotation, mCameraId); mTouchManager.initialize(preview.getHeight() / 3, preview.getHeight() / 3, preview, this, mirror, displayOrientation); }從上面代碼咱們必須知道,在surface發生變化時必須調用setPreviewDisplay,根據以後的學習,在startpreview方式中真正startpreview以前一樣要調用setPreviewDisplay,在setPreviewDisplay的方法中完成了不少初始化,也是在這裏決定是否使用overlay方式的,咱們就先看看startpreview這個方法吧
private void startPreview(boolean updateAll) { if (mPausing || isFinishing()) return; mFocusManager.resetTouchFocus(); mCameraDevice.setErrorCallback(mErrorCallback); // If we're previewing already, stop the preview first (this will blank // the screen). if (mCameraState != PREVIEW_STOPPED) stopPreview(); setPreviewDisplay(mSurfaceHolder); setDisplayOrientation(); if (!mSnapshotOnIdle) { // If the focus mode is continuous autofocus, call cancelAutoFocus to // resume it because it may have been paused by autoFocus call. if (Parameters.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mFocusManager.getFocusMode())) { mCameraDevice.cancelAutoFocus(); } mFocusManager.setAeAwbLock(false); // Unlock AE and AWB. } if ( updateAll ) { Log.v(TAG, "Updating all parameters!"); setCameraParameters(UPDATE_PARAM_INITIALIZE | UPDATE_PARAM_ZOOM | UPDATE_PARAM_PREFERENCE); } else { setCameraParameters(UPDATE_PARAM_MODE); } //setCameraParameters(UPDATE_PARAM_ALL); // Inform the mainthread to go on the UI initialization. if (mCameraPreviewThread != null) { synchronized (mCameraPreviewThread) { mCameraPreviewThread.notify(); } } try { Log.v(TAG, "startPreview"); mCameraDevice.startPreview(); } catch (Throwable ex) { closeCamera(); throw new RuntimeException("startPreview failed", ex); } mZoomState = ZOOM_STOPPED; setCameraState(IDLE); mFocusManager.onPreviewStarted(); if ( mTempBracketingEnabled ) { mFocusManager.setTempBracketingState(FocusManager.TempBracketingStates.ACTIVE); } if (mSnapshotOnIdle) { mHandler.post(mDoSnapRunnable); } }上面你們看到了,先調用了setPreviewDisplay,最後調用mCameraDevice.startPreview()開始preview
/** @brief Sets ANativeWindow object. Preview buffers provided to CameraHal via this object. DisplayAdapter will be interfacing with it to render buffers to display. @param[in] window The ANativeWindow object created by Surface flinger @return NO_ERROR If the ANativeWindow object passes validation criteria @todo Define validation criteria for ANativeWindow object. Define error codes for scenarios */ status_t CameraHal::setPreviewWindow(struct preview_stream_ops *window) { status_t ret = NO_ERROR; CameraAdapter::BuffersDescriptor desc; LOG_FUNCTION_NAME; mSetPreviewWindowCalled = true; ///If the Camera service passes a null window, we destroy existing window and free the DisplayAdapter if(!window)//這種狀況下,window是null,表示不採用overlay方式,則不須要新建displayadapter { if(mDisplayAdapter.get() != NULL) { ///NULL window passed, destroy the display adapter if present CAMHAL_LOGD("NULL window passed, destroying display adapter"); mDisplayAdapter.clear(); ///@remarks If there was a window previously existing, we usually expect another valid window to be passed by the client ///@remarks so, we will wait until it passes a valid window to begin the preview again mSetPreviewWindowCalled = false; } CAMHAL_LOGD("NULL ANativeWindow passed to setPreviewWindow"); return NO_ERROR; } else if(mDisplayAdapter.get() == NULL)//傳入的window不是null,可是尚未未使用overlay方式建立displayadapter,建立displayadapter { // Need to create the display adapter since it has not been created // Create display adapter mDisplayAdapter = new ANativeWindowDisplayAdapter(); ret = NO_ERROR; if(!mDisplayAdapter.get() || ((ret=mDisplayAdapter->initialize())!=NO_ERROR)) { if(ret!=NO_ERROR) { mDisplayAdapter.clear(); CAMHAL_LOGEA("DisplayAdapter initialize failed"); LOG_FUNCTION_NAME_EXIT; return ret; } else { CAMHAL_LOGEA("Couldn't create DisplayAdapter"); LOG_FUNCTION_NAME_EXIT; return NO_MEMORY; } } // DisplayAdapter needs to know where to get the CameraFrames from inorder to display // Since CameraAdapter is the one that provides the frames, set it as the frame provider for DisplayAdapter mDisplayAdapter->setFrameProvider(mCameraAdapter); // Any dynamic errors that happen during the camera use case has to be propagated back to the application // via CAMERA_MSG_ERROR. AppCallbackNotifier is the class that notifies such errors to the application // Set it as the error handler for the DisplayAdapter mDisplayAdapter->setErrorHandler(mAppCallbackNotifier.get()); // Update the display adapter with the new window that is passed from CameraService ret = mDisplayAdapter->setPreviewWindow(window); if(ret!=NO_ERROR) { CAMHAL_LOGEB("DisplayAdapter setPreviewWindow returned error %d", ret); } if(mPreviewStartInProgress) { CAMHAL_LOGDA("setPreviewWindow called when preview running"); // Start the preview since the window is now available ret = startPreview(); } } else {//傳入的window不是null,而且displaadaper已經建立好,那麼這裏只須要將新的window與已經建立好的displayadapter關聯便可 // Update the display adapter with the new window that is passed from CameraService ret = mDisplayAdapter->setPreviewWindow(window); if ( (NO_ERROR == ret) && previewEnabled() ) { restartPreview(); } else if (ret == ALREADY_EXISTS) { // ALREADY_EXISTS should be treated as a noop in this case ret = NO_ERROR; } } LOG_FUNCTION_NAME_EXIT; return ret; }
/** @brief Start preview mode. @param none @return NO_ERROR Camera switched to VF mode @todo Update function header with the different errors that are possible */ status_t CameraHal::startPreview() { LOG_FUNCTION_NAME; // When tunneling is enabled during VTC, startPreview happens in 2 steps: // When the application sends the command CAMERA_CMD_PREVIEW_INITIALIZATION, // cameraPreviewInitialization() is called, which in turn causes the CameraAdapter // to move from loaded to idle state. And when the application calls startPreview, // the CameraAdapter moves from idle to executing state. // // If the application calls startPreview() without sending the command // CAMERA_CMD_PREVIEW_INITIALIZATION, then the function cameraPreviewInitialization() // AND startPreview() are executed. In other words, if the application calls // startPreview() without sending the command CAMERA_CMD_PREVIEW_INITIALIZATION, // then the CameraAdapter moves from loaded to idle to executing state in one shot. status_t ret = cameraPreviewInitialization(); // The flag mPreviewInitializationDone is set to true at the end of the function // cameraPreviewInitialization(). Therefore, if everything goes alright, then the // flag will be set. Sometimes, the function cameraPreviewInitialization() may // return prematurely if all the resources are not available for starting preview. // For example, if the preview window is not set, then it would return NO_ERROR. // Under such circumstances, one should return from startPreview as well and should // not continue execution. That is why, we check the flag and not the return value. if (!mPreviewInitializationDone) return ret; // Once startPreview is called, there is no need to continue to remember whether // the function cameraPreviewInitialization() was called earlier or not. And so // the flag mPreviewInitializationDone is reset here. Plus, this preserves the // current behavior of startPreview under the circumstances where the application // calls startPreview twice or more. mPreviewInitializationDone = false; ///Enable the display adapter if present, actual overlay enable happens when we post the buffer if(mDisplayAdapter.get() != NULL) { CAMHAL_LOGDA("Enabling display"); int width, height; mParameters.getPreviewSize(&width, &height); #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS ret = mDisplayAdapter->enableDisplay(width, height, &mStartPreview); #else ret = mDisplayAdapter->enableDisplay(width, height, NULL); #endif if ( ret != NO_ERROR ) { CAMHAL_LOGEA("Couldn't enable display"); // FIXME: At this stage mStateSwitchLock is locked and unlock is supposed to be called // only from mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_PREVIEW) // below. But this will never happen because of goto error. Thus at next // startPreview() call CameraHAL will be deadlocked. // Need to revisit mStateSwitch lock, for now just abort the process. CAMHAL_ASSERT_X(false, "At this stage mCameraAdapter->mStateSwitchLock is still locked, " "deadlock is guaranteed"); goto error; } } ///Send START_PREVIEW command to adapter CAMHAL_LOGDA("Starting CameraAdapter preview mode"); ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_PREVIEW); if(ret!=NO_ERROR) { CAMHAL_LOGEA("Couldn't start preview w/ CameraAdapter"); goto error; } CAMHAL_LOGDA("Started preview"); mPreviewEnabled = true; mPreviewStartInProgress = false; return ret; error: CAMHAL_LOGEA("Performing cleanup after error"); //Do all the cleanup freePreviewBufs(); mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_PREVIEW); if(mDisplayAdapter.get() != NULL) { mDisplayAdapter->disableDisplay(false); } mAppCallbackNotifier->stop(); mPreviewStartInProgress = false; mPreviewEnabled = false; LOG_FUNCTION_NAME_EXIT; return ret; }
調用到v4l2層的startpreview,下面看看他的具體是實現 android
status_t V4LCameraAdapter::startPreview() { status_t ret = NO_ERROR; LOG_FUNCTION_NAME; Mutex::Autolock lock(mPreviewBufsLock); if(mPreviewing) { ret = BAD_VALUE; goto EXIT; } for (int i = 0; i < mPreviewBufferCountQueueable; i++) { mVideoInfo->buf.index = i; mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; mVideoInfo->buf.memory = V4L2_MEMORY_MMAP; ret = v4lIoctl(mCameraHandle, VIDIOC_QBUF, &mVideoInfo->buf);//請求分配內存 if (ret < 0) { CAMHAL_LOGEA("VIDIOC_QBUF Failed"); goto EXIT; } nQueued++; } ret = v4lStartStreaming(); // Create and start preview thread for receiving buffers from V4L Camera if(!mCapturing) { mPreviewThread = new PreviewThread(this);//開啓PreviewThread CAMHAL_LOGDA("Created preview thread"); } //Update the flag to indicate we are previewing mPreviewing = true; mCapturing = false; EXIT: LOG_FUNCTION_NAME_EXIT; return ret; } int V4LCameraAdapter::previewThread() { status_t ret = NO_ERROR; int width, height; CameraFrame frame; void *y_uv[2]; int index = 0; int stride = 4096; char *fp = NULL; mParams.getPreviewSize(&width, &height); if (mPreviewing) { fp = this->GetFrame(index); if(!fp) { ret = BAD_VALUE; goto EXIT; } CameraBuffer *buffer = mPreviewBufs.keyAt(index);//獲取camerabuffer CameraFrame *lframe = (CameraFrame *)mFrameQueue.valueFor(buffer);//獲取cameraframe if (!lframe) { ret = BAD_VALUE; goto EXIT; } debugShowFPS(); if ( mFrameSubscribers.size() == 0 ) { ret = BAD_VALUE; goto EXIT; } y_uv[0] = (void*) lframe->mYuv[0]; //y_uv[1] = (void*) lframe->mYuv[1]; //y_uv[1] = (void*) (lframe->mYuv[0] + height*stride); convertYUV422ToNV12Tiler ( (unsigned char*)fp, (unsigned char*)y_uv[0], width, height);//convert the data CAMHAL_LOGVB("##...index= %d.;camera buffer= 0x%x; y= 0x%x; UV= 0x%x.",index, buffer, y_uv[0], y_uv[1] ); #ifdef SAVE_RAW_FRAMES unsigned char* nv12_buff = (unsigned char*) malloc(width*height*3/2); //Convert yuv422i to yuv420sp(NV12) & dump the frame to a file convertYUV422ToNV12 ( (unsigned char*)fp, nv12_buff, width, height); saveFile( nv12_buff, ((width*height)*3/2) );//if you want to save the data,save it free (nv12_buff); #endif //填充frame結構,用於數據處理 frame.mFrameType = CameraFrame::PREVIEW_FRAME_SYNC; frame.mBuffer = buffer; frame.mLength = width*height*3/2; frame.mAlignment = stride; frame.mOffset = 0; frame.mTimestamp = systemTime(SYSTEM_TIME_MONOTONIC); frame.mFrameMask = (unsigned int)CameraFrame::PREVIEW_FRAME_SYNC; if (mRecording) { frame.mFrameMask |= (unsigned int)CameraFrame::VIDEO_FRAME_SYNC; mFramesWithEncoder++; } //這裏是重點,數據回調,或者使用overlay方式顯示這裏是決定性調用 ret = setInitFrameRefCount(frame.mBuffer, frame.mFrameMask); if (ret != NO_ERROR) { CAMHAL_LOGDB("Error in setInitFrameRefCount %d", ret); } else { ret = sendFrameToSubscribers(&frame); } } EXIT: return ret; }如今就開始看看setInitFrameCount方法都作了些什麼
int BaseCameraAdapter::setInitFrameRefCount(CameraBuffer * buf, unsigned int mask) { int ret = NO_ERROR; unsigned int lmask; LOG_FUNCTION_NAME; if (buf == NULL) { return -EINVAL; } for( lmask = 1; lmask < CameraFrame::ALL_FRAMES; lmask <<= 1){ if( lmask & mask ){ switch( lmask ){ case CameraFrame::IMAGE_FRAME: { setFrameRefCount(buf, CameraFrame::IMAGE_FRAME, (int) mImageSubscribers.size()); } break; case CameraFrame::RAW_FRAME: { setFrameRefCount(buf, CameraFrame::RAW_FRAME, mRawSubscribers.size()); } break; case CameraFrame::PREVIEW_FRAME_SYNC: { setFrameRefCount(buf, CameraFrame::PREVIEW_FRAME_SYNC, mFrameSubscribers.size());//這裏這個mFrameSubscribers對應的key上保存着響應的callback方法 } break; case CameraFrame::SNAPSHOT_FRAME: { setFrameRefCount(buf, CameraFrame::SNAPSHOT_FRAME, mSnapshotSubscribers.size()); } break; case CameraFrame::VIDEO_FRAME_SYNC: { setFrameRefCount(buf,CameraFrame::VIDEO_FRAME_SYNC, mVideoSubscribers.size()); } break; case CameraFrame::FRAME_DATA_SYNC: { setFrameRefCount(buf, CameraFrame::FRAME_DATA_SYNC, mFrameDataSubscribers.size()); } break; case CameraFrame::REPROCESS_INPUT_FRAME: { setFrameRefCount(buf,CameraFrame::REPROCESS_INPUT_FRAME, mVideoInSubscribers.size()); } break; default: CAMHAL_LOGEB("FRAMETYPE NOT SUPPORTED 0x%x", lmask); break; }//SWITCH mask &= ~lmask; }//IF }//FOR LOG_FUNCTION_NAME_EXIT; return ret; }上面我標註的部分經過enableMsgType方法實現mFrameSubscribers.add的,經callback添加到對應的key處,算是實現關聯,
1. void BaseCameraAdapter::setFrameRefCount(CameraBuffer * frameBuf, CameraFrame::FrameType frameType, int refCount) 2. { 3. 4. LOG_FUNCTION_NAME; 5. 6. switch ( frameType ) 7. { 8. case CameraFrame::IMAGE_FRAME: 9. case CameraFrame::RAW_FRAME: 10. { 11. Mutex::Autolock lock(mCaptureBufferLock); 12. mCaptureBuffersAvailable.replaceValueFor(frameBuf, refCount); 13. } 14. break; 15. case CameraFrame::SNAPSHOT_FRAME: 16. { 17. Mutex::Autolock lock(mSnapshotBufferLock); 18. mSnapshotBuffersAvailable.replaceValueFor( ( unsigned int ) frameBuf, refCount); 19. } 20. break; 21. case CameraFrame::PREVIEW_FRAME_SYNC: 22. { 23. Mutex::Autolock lock(mPreviewBufferLock) 24. mPreviewBuffersAvailable.replaceValueFor(frameBuf, refCount);//這裏個人理解是refCount和frameBuf實現了綁定,即camerabuf保存在mPreviewBuffersAvailable對應的key處 25. } 26. break; 27. case CameraFrame::FRAME_DATA_SYNC: 28. { 29. Mutex::Autolock lock(mPreviewDataBufferLock); 30. mPreviewDataBuffersAvailable.replaceValueFor(frameBuf, refCount); 31. } 32. break; 33. case CameraFrame::VIDEO_FRAME_SYNC: 34. { 35. Mutex::Autolock lock(mVideoBufferLock); 36. mVideoBuffersAvailable.replaceValueFor(frameBuf, refCount); 37. } 38. break; 39. case CameraFrame::REPROCESS_INPUT_FRAME: { 40. Mutex::Autolock lock(mVideoInBufferLock); 41. mVideoInBuffersAvailable.replaceValueFor(frameBuf, refCount); 42. } 43. break; 44. default: 45. break; 46. }; 47. 48. LOG_FUNCTION_NAME_EXIT; 49. 50. }接下咱們看看sendFrameToSubscribers方法的具體實現過程
1. status_t BaseCameraAdapter::sendFrameToSubscribers(CameraFrame *frame) 2. { 3. status_t ret = NO_ERROR; 4. unsigned int mask; 5. 6. if ( NULL == frame ) 7. { 8. CAMHAL_LOGEA("Invalid CameraFrame"); 9. return -EINVAL; 10. } 11. 12. for( mask = 1; mask < CameraFrame::ALL_FRAMES; mask <<= 1){ 13. if( mask & frame->mFrameMask ){ 14. switch( mask ){ 15. 16. case CameraFrame::IMAGE_FRAME: 17. { 18. #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS 19. CameraHal::PPM("Shot to Jpeg: ", &mStartCapture); 20. #endif 21. ret = __sendFrameToSubscribers(frame, &mImageSubscribers, CameraFrame::IMAGE_FRAME); 22. } 23. break; 24. case CameraFrame::RAW_FRAME: 25. { 26. ret = __sendFrameToSubscribers(frame, &mRawSubscribers, CameraFrame::RAW_FRAME); 27. } 28. break; 29. case CameraFrame::PREVIEW_FRAME_SYNC: 30. { 31. ret = __sendFrameToSubscribers(frame, &mFrameSubscribers, CameraFrame::PREVIEW_FRAME_SYNC); 32. } 33. break; 34. case CameraFrame::SNAPSHOT_FRAME: 35. { 36. ret = __sendFrameToSubscribers(frame, &mSnapshotSubscribers, CameraFrame::SNAPSHOT_FRAME); 37. } 38. break; 39. case CameraFrame::VIDEO_FRAME_SYNC: 40. { 41. ret = __sendFrameToSubscribers(frame, &mVideoSubscribers, CameraFrame::VIDEO_FRAME_SYNC); 42. } 43. break; 44. case CameraFrame::FRAME_DATA_SYNC: 45. { 46. ret = __sendFrameToSubscribers(frame, &mFrameDataSubscribers, CameraFrame::FRAME_DATA_SYNC); 47. } 48. break; 49. case CameraFrame::REPROCESS_INPUT_FRAME: 50. { 51. ret = __sendFrameToSubscribers(frame, &mVideoInSubscribers, CameraFrame::REPROCESS_INPUT_FRAME); 52. } 53. break; 54. default: 55. CAMHAL_LOGEB("FRAMETYPE NOT SUPPORTED 0x%x", mask); 56. break; 57. }//SWITCH 58. frame->mFrameMask &= ~mask; 59. 60. if (ret != NO_ERROR) { 61. goto EXIT; 62. } 63. }//IF 64. }//FOR 65. 66. EXIT: 67. return ret; 68. }
1. status_t BaseCameraAdapter::__sendFrameToSubscribers(CameraFrame* frame, 2. KeyedVector<int, frame_callback> *subscribers, 3. CameraFrame::FrameType frameType) 4. { 5. size_t refCount = 0; 6. status_t ret = NO_ERROR; 7. frame_callback callback = NULL; 8. 9. frame->mFrameType = frameType; 10. 11. if ( (frameType == CameraFrame::PREVIEW_FRAME_SYNC) || 12. (frameType == CameraFrame::VIDEO_FRAME_SYNC) || 13. (frameType == CameraFrame::SNAPSHOT_FRAME) ){ 14. if (mFrameQueue.size() > 0){ 15. CameraFrame *lframe = (CameraFrame *)mFrameQueue.valueFor(frame->mBuffer); 16. frame->mYuv[0] = lframe->mYuv[0]; 17. frame->mYuv[1] = frame->mYuv[0] + (frame->mLength + frame->mOffset)*2/3; 18. } 19. else{ 20. CAMHAL_LOGDA("Empty Frame Queue"); 21. return -EINVAL; 22. } 23. } 24. 25. if (NULL != subscribers) { 26. refCount = getFrameRefCount(frame->mBuffer, frameType);//經過這個refCount能夠找到對應的callback方法 27. 28. if (refCount == 0) { 29. CAMHAL_LOGDA("Invalid ref count of 0"); 30. return -EINVAL; 31. } 32. 33. if (refCount > subscribers->size()) { 34. CAMHAL_LOGEB("Invalid ref count for frame type: 0x%x", frameType); 35. return -EINVAL; 36. } 37. 38. CAMHAL_LOGVB("Type of Frame: 0x%x address: 0x%x refCount start %d", 39. frame->mFrameType, 40. ( uint32_t ) frame->mBuffer, 41. refCount); 42. 43. for ( unsigned int i = 0 ; i < refCount; i++ ) { 44. frame->mCookie = ( void * ) subscribers->keyAt(i); 45. callback = (frame_callback) subscribers->valueAt(i); 46. 47. if (!callback) { 48. CAMHAL_LOGEB("callback not set for frame type: 0x%x", frameType); 49. return -EINVAL; 50. } 51. 52. callback(frame); 53. } 54. } else { 55. CAMHAL_LOGEA("Subscribers is null??"); 56. return -EINVAL; 57. } 58. 59. return ret; 60. }這裏別的咱們先暫且不分析,可是callback究竟是從哪裏來的,這個咱們必須說清楚
1. int ANativeWindowDisplayAdapter::setFrameProvider(FrameNotifier *frameProvider) 2. { 3. LOG_FUNCTION_NAME; 4. 5. // Check for NULL pointer 6. if ( !frameProvider ) { 7. CAMHAL_LOGEA("NULL passed for frame provider"); 8. LOG_FUNCTION_NAME_EXIT; 9. return BAD_VALUE; 10. } 11. 12. //Release any previous frame providers 13. if ( NULL != mFrameProvider ) { 14. delete mFrameProvider; 15. } 16. 17. /** Dont do anything here, Just save the pointer for use when display is 18. actually enabled or disabled 19. */ 20. mFrameProvider = new FrameProvider(frameProvider, this, frameCallbackRelay);//實例化一個FrameProvider,這其中有一個參數很是重要:frameCallbackRelay,他的定義在下面給出 21. 22. LOG_FUNCTION_NAME_EXIT; 23. 24. return NO_ERROR; 25. } 1. void ANativeWindowDisplayAdapter::frameCallbackRelay(CameraFrame* caFrame) 2. { 3. 4. if ( NULL != caFrame ) 5. { 6. if ( NULL != caFrame->mCookie ) 7. { 8. ANativeWindowDisplayAdapter *da = (ANativeWindowDisplayAdapter*) caFrame->mCookie; 9. da->frameCallback(caFrame); 10. } 11. else 12. { 13. CAMHAL_LOGEB("Invalid Cookie in Camera Frame = %p, Cookie = %p", caFrame, caFrame->mCookie); 14. } 15. } 16. else 17. { 18. CAMHAL_LOGEB("Invalid Camera Frame = %p", caFrame); 19. } 20. 21. } 1. void ANativeWindowDisplayAdapter::frameCallback(CameraFrame* caFrame) 2. { 3. ///Call queueBuffer of overlay in the context of the callback thread 4. DisplayFrame df; 5. df.mBuffer = caFrame->mBuffer; 6. df.mType = (CameraFrame::FrameType) caFrame->mFrameType; 7. df.mOffset = caFrame->mOffset; 8. df.mWidthStride = caFrame->mAlignment; 9. df.mLength = caFrame->mLength; 10. df.mWidth = caFrame->mWidth; 11. df.mHeight = caFrame->mHeight; 12. PostFrame(df); 13. }這個回調函數在這裏設置,等待數據回調,咱們頗有必要去看看FrameProvider這個類的構造函數,他是怎樣讓其餘方法調用到這個回調函數的呢
1. FrameProvider(FrameNotifier *fn, void* cookie, frame_callback frameCallback) 2. :mFrameNotifier(fn), mCookie(cookie),mFrameCallback(frameCallback) { }這個構造函數仍是頗有意思,沒有任何實現,只是經過傳入的三個參數實例化了三個對象而已
1. //////////// 2. /** 3. @brief Set preview mode related initialization 4. -> Camera Adapter set params 5. -> Allocate buffers 6. -> Set use buffers for preview 7. @param none 8. @return NO_ERROR 9. @todo Update function header with the different errors that are possible 10. 11. */ 12. status_t CameraHal::cameraPreviewInitialization() 13. { 14. 15. status_t ret = NO_ERROR; 16. CameraAdapter::BuffersDescriptor desc; 17. CameraFrame frame; 18. unsigned int required_buffer_count; 19. unsigned int max_queueble_buffers; 20. 21. #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS 22. gettimeofday(&mStartPreview, NULL); 23. #endif 24. 25. LOG_FUNCTION_NAME; 26. 27. if (mPreviewInitializationDone) { 28. return NO_ERROR; 29. } 30. 31. if ( mPreviewEnabled ){ 32. CAMHAL_LOGDA("Preview already running"); 33. LOG_FUNCTION_NAME_EXIT; 34. return ALREADY_EXISTS; 35. } 36. 37. if ( NULL != mCameraAdapter ) { 38. ret = mCameraAdapter->setParameters(mParameters); 39. } 40. 41. if ((mPreviewStartInProgress == false) && (mDisplayPaused == false)){ 42. ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_QUERY_RESOLUTION_PREVIEW,( int ) &frame); 43. if ( NO_ERROR != ret ){ 44. CAMHAL_LOGEB("Error: CAMERA_QUERY_RESOLUTION_PREVIEW %d", ret); 45. return ret; 46. } 47. 48. ///Update the current preview width and height 49. mPreviewWidth = frame.mWidth; 50. mPreviewHeight = frame.mHeight; 51. } 52. 53. ///If we don't have the preview callback enabled and display adapter, 54. if(!mSetPreviewWindowCalled || (mDisplayAdapter.get() == NULL)){ 55. CAMHAL_LOGD("Preview not started. Preview in progress flag set"); 56. mPreviewStartInProgress = true; 57. ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_SWITCH_TO_EXECUTING); 58. if ( NO_ERROR != ret ){ 59. CAMHAL_LOGEB("Error: CAMERA_SWITCH_TO_EXECUTING %d", ret); 60. return ret; 61. } 62. return NO_ERROR; 63. } 64. 65. if( (mDisplayAdapter.get() != NULL) && ( !mPreviewEnabled ) && ( mDisplayPaused ) ) 66. { 67. CAMHAL_LOGDA("Preview is in paused state"); 68. 69. mDisplayPaused = false; 70. mPreviewEnabled = true; 71. if ( NO_ERROR == ret ) 72. { 73. ret = mDisplayAdapter->pauseDisplay(mDisplayPaused); 74. 75. if ( NO_ERROR != ret ) 76. { 77. CAMHAL_LOGEB("Display adapter resume failed %x", ret); 78. } 79. } 80. //restart preview callbacks 81. if(mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) 82. { 83. mAppCallbackNotifier->enableMsgType (CAMERA_MSG_PREVIEW_FRAME); 84. } 85. 86. signalEndImageCapture(); 87. return ret; 88. } 89. 90. required_buffer_count = atoi(mCameraProperties->get(CameraProperties::REQUIRED_PREVIEW_BUFS)); 91. 92. ///Allocate the preview buffers 93. ret = allocPreviewBufs(mPreviewWidth, mPreviewHeight, mParameters.getPreviewFormat(), required_buffer_count, max_queueble_buffers); 94. 95. if ( NO_ERROR != ret ) 96. { 97. CAMHAL_LOGEA("Couldn't allocate buffers for Preview"); 98. goto error; 99. } 100. 101. if ( mMeasurementEnabled ) 102. { 103. 104. ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_QUERY_BUFFER_SIZE_PREVIEW_DATA, 105. ( int ) &frame, 106. required_buffer_count); 107. if ( NO_ERROR != ret ) 108. { 109. return ret; 110. } 111. 112. ///Allocate the preview data buffers 113. ret = allocPreviewDataBufs(frame.mLength, required_buffer_count); 114. if ( NO_ERROR != ret ) { 115. CAMHAL_LOGEA("Couldn't allocate preview data buffers"); 116. goto error; 117. } 118. 119. if ( NO_ERROR == ret ) 120. { 121. desc.mBuffers = mPreviewDataBuffers; 122. desc.mOffsets = mPreviewDataOffsets; 123. desc.mFd = mPreviewDataFd; 124. desc.mLength = mPreviewDataLength; 125. desc.mCount = ( size_t ) required_buffer_count; 126. desc.mMaxQueueable = (size_t) required_buffer_count; 127. 128. mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_PREVIEW_DATA, 129. ( int ) &desc); 130. } 131. 132. } 133. 134. ///Pass the buffers to Camera Adapter 135. desc.mBuffers = mPreviewBuffers; 136. desc.mOffsets = mPreviewOffsets; 137. desc.mFd = mPreviewFd; 138. desc.mLength = mPreviewLength; 139. desc.mCount = ( size_t ) required_buffer_count; 140. desc.mMaxQueueable = (size_t) max_queueble_buffers; 141. 142. ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_PREVIEW, 143. ( int ) &desc); 144. 145. if ( NO_ERROR != ret ) 146. { 147. CAMHAL_LOGEB("Failed to register preview buffers: 0x%x", ret); 148. freePreviewBufs(); 149. return ret; 150. } 151. 152. mAppCallbackNotifier->startPreviewCallbacks(mParameters, mPreviewBuffers, mPreviewOffsets, mPreviewFd, mPreviewLength, required_buffer_count); 153. 154. ///Start the callback notifier 155. ret = mAppCallbackNotifier->start(); 156. 157. if( ALREADY_EXISTS == ret ) 158. { 159. //Already running, do nothing 160. CAMHAL_LOGDA("AppCallbackNotifier already running"); 161. ret = NO_ERROR; 162. } 163. else if ( NO_ERROR == ret ) { 164. CAMHAL_LOGDA("Started AppCallbackNotifier.."); 165. mAppCallbackNotifier->setMeasurements(mMeasurementEnabled); 166. } 167. else 168. { 169. CAMHAL_LOGDA("Couldn't start AppCallbackNotifier"); 170. goto error; 171. } 172. 173. if (ret == NO_ERROR) mPreviewInitializationDone = true; 174. return ret; 175. 176. error: 177. 178. CAMHAL_LOGEA("Performing cleanup after error"); 179. 180. //Do all the cleanup 181. freePreviewBufs(); 182. mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_PREVIEW); 183. if(mDisplayAdapter.get() != NULL) 184. { 185. mDisplayAdapter->disableDisplay(false); 186. } 187. mAppCallbackNotifier->stop(); 188. mPreviewStartInProgress = false; 189. mPreviewEnabled = false; 190. LOG_FUNCTION_NAME_EXIT; 191. 192. return ret; 193. }咱們就看看這個方法的是實現吧:mAppCallbackNotifier->enableMsgType (CAMERA_MSG_PREVIEW_FRAME);
1. status_t AppCallbackNotifier::enableMsgType(int32_t msgType) 2. { 3. if( msgType & CAMERA_MSG_PREVIEW_FRAME ) { 4. mFrameProvider->enableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC); 5. } 6. 7. if( msgType & CAMERA_MSG_POSTVIEW_FRAME ) { 8. mFrameProvider->enableFrameNotification(CameraFrame::SNAPSHOT_FRAME); 9. } 10. 11. if(msgType & CAMERA_MSG_RAW_IMAGE) { 12. mFrameProvider->enableFrameNotification(CameraFrame::RAW_FRAME); 13. } 14. 15. return NO_ERROR; 16. } 1. int FrameProvider::enableFrameNotification(int32_t frameTypes) 2. { 3. LOG_FUNCTION_NAME; 4. status_t ret = NO_ERROR; 5. 6. ///Enable the frame notification to CameraAdapter (which implements FrameNotifier interface) 7. mFrameNotifier->enableMsgType(frameTypes<<MessageNotifier::FRAME_BIT_FIELD_POSITION, mFrameCallback, NULL, mCookie); 8. 9. LOG_FUNCTION_NAME_EXIT; 10. return ret; 11. }這裏這個enableMsgType其實就是前面已經提到過的那個enableMsgType方法,實現callback方法add到響應的key上
1. void BaseCameraAdapter::enableMsgType(int32_t msgs, frame_callback callback, event_callback eventCb, void* cookie) 2. { 3. Mutex::Autolock lock(mSubscriberLock); 4. 5. LOG_FUNCTION_NAME; 6. 7. int32_t frameMsg = ((msgs >> MessageNotifier::FRAME_BIT_FIELD_POSITION) & EVENT_MASK); 8. int32_t eventMsg = ((msgs >> MessageNotifier::EVENT_BIT_FIELD_POSITION) & EVENT_MASK); 9. 10. if ( frameMsg != 0 ) 11. { 12. CAMHAL_LOGVB("Frame message type id=0x%x subscription request", frameMsg); 13. switch ( frameMsg ) 14. { 15. case CameraFrame::PREVIEW_FRAME_SYNC: 16. mFrameSubscribers.add((int) cookie, callback); 17. break; 18. case CameraFrame::FRAME_DATA_SYNC: 19. mFrameDataSubscribers.add((int) cookie, callback); 20. break; 21. case CameraFrame::SNAPSHOT_FRAME: 22. mSnapshotSubscribers.add((int) cookie, callback); 23. break; 24. case CameraFrame::IMAGE_FRAME: 25. mImageSubscribers.add((int) cookie, callback); 26. break; 27. case CameraFrame::RAW_FRAME: 28. mRawSubscribers.add((int) cookie, callback); 29. break; 30. case CameraFrame::VIDEO_FRAME_SYNC: 31. mVideoSubscribers.add((int) cookie, callback); 32. break; 33. case CameraFrame::REPROCESS_INPUT_FRAME: 34. mVideoInSubscribers.add((int) cookie, callback); 35. break; 36. default: 37. CAMHAL_LOGEA("Frame message type id=0x%x subscription no supported yet!", frameMsg); 38. break; 39. } 40. } 41. 42. if ( eventMsg != 0) 43. { 44. CAMHAL_LOGVB("Event message type id=0x%x subscription request", eventMsg); 45. if ( CameraHalEvent::ALL_EVENTS == eventMsg ) 46. { 47. mFocusSubscribers.add((int) cookie, eventCb); 48. mShutterSubscribers.add((int) cookie, eventCb); 49. mZoomSubscribers.add((int) cookie, eventCb); 50. mMetadataSubscribers.add((int) cookie, eventCb); 51. } 52. else 53. { 54. CAMHAL_LOGEA("Event message type id=0x%x subscription no supported yet!", eventMsg); 55. } 56. } 57. 58. LOG_FUNCTION_NAME_EXIT; 59. }這裏經過mFrameSubscribers.add((int) cookie, callback)這個方法將mFrameCallback回調函數與key相關聯
1. void ANativeWindowDisplayAdapter::frameCallback(CameraFrame* caFrame) 2. { 3. ///Call queueBuffer of overlay in the context of the callback thread 4. DisplayFrame df; 5. df.mBuffer = caFrame->mBuffer; 6. df.mType = (CameraFrame::FrameType) caFrame->mFrameType; 7. df.mOffset = caFrame->mOffset; 8. df.mWidthStride = caFrame->mAlignment; 9. df.mLength = caFrame->mLength; 10. df.mWidth = caFrame->mWidth; 11. df.mHeight = caFrame->mHeight; 12. PostFrame(df);//這裏填充了DisplayFrame這個結構,並調用PostFrome實現顯示 13. }這裏PostFrame成了我要研究的主要內容,將數據以DisplayFrame結構的方式打包以後究竟是怎麼實現顯示的呢??
1. status_t ANativeWindowDisplayAdapter::PostFrame(ANativeWindowDisplayAdapter::DisplayFrame &dispFrame) 2. { 3. status_t ret = NO_ERROR; 4. uint32_t actualFramesWithDisplay = 0; 5. android_native_buffer_t *buffer = NULL; 6. GraphicBufferMapper &mapper = GraphicBufferMapper::get(); 7. int i; 8. 9. ///@todo Do cropping based on the stabilized frame coordinates 10. ///@todo Insert logic to drop frames here based on refresh rate of 11. ///display or rendering rate whichever is lower 12. ///Queue the buffer to overlay 13. 14. if ( NULL == mANativeWindow ) { 15. return NO_INIT; 16. } 17. 18. if (!mBuffers || !dispFrame.mBuffer) { 19. CAMHAL_LOGEA("NULL sent to PostFrame"); 20. return BAD_VALUE; 21. } 22. 23. for ( i = 0; i < mBufferCount; i++ ) 24. { 25. if ( dispFrame.mBuffer == &mBuffers[i] ) 26. { 27. break; 28. } 29. } 30. 31. 32. mFramesType.add( (int)mBuffers[i].opaque ,dispFrame.mType ); 33. 34. if ( mDisplayState == ANativeWindowDisplayAdapter::DISPLAY_STARTED && 35. (!mPaused || CameraFrame::CameraFrame::SNAPSHOT_FRAME == dispFrame.mType) && 36. !mSuspend) 37. { 38. Mutex::Autolock lock(mLock); 39. uint32_t xOff = (dispFrame.mOffset% PAGE_SIZE); 40. uint32_t yOff = (dispFrame.mOffset / PAGE_SIZE); 41. 42. // Set crop only if current x and y offsets do not match with frame offsets 43. if((mXOff!=xOff) || (mYOff!=yOff)) 44. { 45. CAMHAL_LOGDB("Offset %d xOff = %d, yOff = %d", dispFrame.mOffset, xOff, yOff); 46. uint8_t bytesPerPixel; 47. ///Calculate bytes per pixel based on the pixel format 48. if(strcmp(mPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV422I) == 0) 49. { 50. bytesPerPixel = 2; 51. } 52. else if(strcmp(mPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_RGB565) == 0) 53. { 54. bytesPerPixel = 2; 55. } 56. else if(strcmp(mPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) 57. { 58. bytesPerPixel = 1; 59. } 60. else 61. { 62. bytesPerPixel = 1; 63. } 64. 65. CAMHAL_LOGVB(" crop.left = %d crop.top = %d crop.right = %d crop.bottom = %d", 66. xOff/bytesPerPixel, yOff , (xOff/bytesPerPixel)+mPreviewWidth, yOff+mPreviewHeight); 67. // We'll ignore any errors here, if the surface is 68. // already invalid, we'll know soon enough. 69. mANativeWindow->set_crop(mANativeWindow, xOff/bytesPerPixel, yOff, 70. (xOff/bytesPerPixel)+mPreviewWidth, yOff+mPreviewHeight); 71. 72. ///Update the current x and y offsets 73. mXOff = xOff; 74. mYOff = yOff; 75. } 76. 77. { 78. buffer_handle_t *handle = (buffer_handle_t *) mBuffers[i].opaque; 79. // unlock buffer before sending to display 80. mapper.unlock(*handle); 81. ret = mANativeWindow->enqueue_buffer(mANativeWindow, handle); 82. } 83. if ( NO_ERROR != ret ) { 84. CAMHAL_LOGE("Surface::queueBuffer returned error %d", ret); 85. } 86. 87. mFramesWithCameraAdapterMap.removeItem((buffer_handle_t *) dispFrame.mBuffer->opaque); 88. 89. 90. // HWComposer has not minimum buffer requirement. We should be able to dequeue 91. // the buffer immediately 92. TIUTILS::Message msg; 93. mDisplayQ.put(&msg); 94. 95. 96. #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS 97. 98. if ( mMeasureStandby ) 99. { 100. CameraHal::PPM("Standby to first shot: Sensor Change completed - ", &mStandbyToShot); 101. mMeasureStandby = false; 102. } 103. else if (CameraFrame::CameraFrame::SNAPSHOT_FRAME == dispFrame.mType) 104. { 105. CameraHal::PPM("Shot to snapshot: ", &mStartCapture); 106. mShotToShot = true; 107. } 108. else if ( mShotToShot ) 109. { 110. CameraHal::PPM("Shot to shot: ", &mStartCapture); 111. mShotToShot = false; 112. } 113. #endif 114. 115. } 116. else 117. { 118. Mutex::Autolock lock(mLock); 119. buffer_handle_t *handle = (buffer_handle_t *) mBuffers[i].opaque; 120. 121. // unlock buffer before giving it up 122. mapper.unlock(*handle); 123. 124. // cancel buffer and dequeue another one 125. ret = mANativeWindow->cancel_buffer(mANativeWindow, handle); 126. if ( NO_ERROR != ret ) { 127. CAMHAL_LOGE("Surface::cancelBuffer returned error %d", ret); 128. } 129. 130. mFramesWithCameraAdapterMap.removeItem((buffer_handle_t *) dispFrame.mBuffer->opaque); 131. 132. TIUTILS::Message msg; 133. mDisplayQ.put(&msg); 134. ret = NO_ERROR; 135. } 136. 137. return ret; 138. }