Android Camera AppNotifier工作机制分析
这里我们以mFrameQ为例子先做一下说明
- void AppCallbackNotifier::frameCallbackRelay(CameraFrame* caFrame)
- {
- LOG_FUNCTION_NAME;
- AppCallbackNotifier *appcbn = (AppCallbackNotifier*) (caFrame->mCookie);
- appcbn->frameCallback(caFrame);
- LOG_FUNCTION_NAME_EXIT;
- }
- void AppCallbackNotifier::frameCallback(CameraFrame* caFrame)
- {
- ///Post the event to the event queue of AppCallbackNotifier
- TIUTILS::Message msg;
- CameraFrame *frame;
- LOG_FUNCTION_NAME;
- if ( NULL != caFrame )
- {
- frame = new CameraFrame(*caFrame);
- if ( NULL != frame )
- {
- msg.command = AppCallbackNotifier::NOTIFIER_CMD_PROCESS_FRAME;
- msg.arg1 = frame;
- mFrameQ.put(&msg);
- }
- else
- {
- CAMHAL_LOGEA("Not enough resources to allocate CameraFrame");
- }
- }
- LOG_FUNCTION_NAME_EXIT;
- }
那么我们真正关注的是,这个 frameCallbackRelay是怎么与底层实现关联的啊?地层是怎样通过这个方法实现回调的呢?
这里我们就要追究一下这个frameCallbackRelay是怎么样和底层实现关联的了
mFrameProvider = new FrameProvider(frameNotifier, this, frameCallbackRelay);
先看这里,在new FrameProvider的时候传入了这个framecallback方法,在FrameProvider的构造函数中将这个函数指针保存到mFrameCallback中,方法如下:
- FrameProvider(FrameNotifier *fn, void* cookie, frame_callback frameCallback)
- :mFrameNotifier(fn), mCookie(cookie),mFrameCallback(frameCallback) { }
mFrameProvider - > enableFrameNotification ( CameraFrame : : IMAGE_FRAME ) ;
mFrameProvider - > enableFrameNotification ( CameraFrame : : RAW_FRAME ) ;
我们就看看enableFrameNotification的实现吧,他的实现在CameraHalUtilClasses中
- int FrameProvider::enableFrameNotification(int32_t frameTypes)
- {
- LOG_FUNCTION_NAME;
- status_t ret = NO_ERROR;
- ///Enable the frame notification to CameraAdapter (which implements FrameNotifier interface)
- mFrameNotifier->enableMsgType(frameTypes<<MessageNotifier::FRAME_BIT_FIELD_POSITION, mFrameCallback , NULL, mCookie);
- LOG_FUNCTION_NAME_EXIT;
- return ret;
- }
- void BaseCameraAdapter::enableMsgType(int32_t msgs, frame_callback callback, event_callback eventCb, void* cookie)
- {
- Mutex::Autolock lock(mSubscriberLock);
- LOG_FUNCTION_NAME;
- int32_t frameMsg = ((msgs >> MessageNotifier::FRAME_BIT_FIELD_POSITION) & EVENT_MASK);
- int32_t eventMsg = ((msgs >> MessageNotifier::EVENT_BIT_FIELD_POSITION) & EVENT_MASK);
- if ( frameMsg != 0 )
- {
- CAMHAL_LOGVB("Frame message type id=0x%x subscription request", frameMsg);
- switch ( frameMsg )
- {
- case CameraFrame::PREVIEW_FRAME_SYNC:
- mFrameSubscribers.add((int) cookie, callback);
- break;
- case CameraFrame::FRAME_DATA_SYNC:
- mFrameDataSubscribers.add((int) cookie, callback);
- break;
- case CameraFrame::SNAPSHOT_FRAME:
- mSnapshotSubscribers.add((int) cookie, callback);
- break;
- case CameraFrame::IMAGE_FRAME:
- mImageSubscribers.add((int) cookie, callback);
- break;
- case CameraFrame::RAW_FRAME:
- mRawSubscribers.add((int) cookie, callback);
- break;
- case CameraFrame::VIDEO_FRAME_SYNC:
- mVideoSubscribers.add((int) cookie, callback);
- break;
- case CameraFrame::REPROCESS_INPUT_FRAME:
- mVideoInSubscribers.add((int) cookie, callback);
- break;
- default:
- CAMHAL_LOGEA("Frame message type id=0x%x subscription no supported yet!", frameMsg);
- break;
- }
- }
- if ( eventMsg != 0)
- {
- CAMHAL_LOGVB("Event message type id=0x%x subscription request", eventMsg);
- if ( CameraHalEvent::ALL_EVENTS == eventMsg )
- {
- mFocusSubscribers.add((int) cookie, eventCb);
- mShutterSubscribers.add((int) cookie, eventCb);
- mZoomSubscribers.add((int) cookie, eventCb);
- mMetadataSubscribers.add((int) cookie, eventCb);
- }
- else
- {
- CAMHAL_LOGEA("Event message type id=0x%x subscription no supported yet!", eventMsg);
- }
- }
- LOG_FUNCTION_NAME_EXIT;
- }
在这里将我们初始化定义好的callback方法加入向量表中,底层到底怎么调用到还是不知道啊,接着找啊找
跟上一篇文章是一样的,之前采用V4LCameraAdapter的方式分析其实我们早就在之前文章中说过了,这里这篇文章我们针对OMXCameraAdapter做分析
在 OMXCameraAdapter中有这样一个方法
- status_t OMXCameraAdapter::sendCallBacks(CameraFrame frame, OMX_IN OMX_BUFFERHEADERTYPE *pBuffHeader, unsigned int mask, OMXCameraPortParameters *port)
- {
- status_t ret = NO_ERROR;
- LOG_FUNCTION_NAME;
- if ( NULL == port)
- {
- CAMHAL_LOGEA("Invalid portParam");
- return -EINVAL;
- }
- if ( NULL == pBuffHeader )
- {
- CAMHAL_LOGEA("Invalid Buffer header");
- return -EINVAL;
- }
- Mutex::Autolock lock(mSubscriberLock);
- //frame.mFrameType = typeOfFrame;
- frame.mFrameMask = mask;
- frame.mBuffer = (CameraBuffer *)pBuffHeader->pAppPrivate;
- frame.mLength = pBuffHeader->nFilledLen;
- frame.mAlignment = port->mStride;
- frame.mOffset = pBuffHeader->nOffset;
- frame.mWidth = port->mWidth;
- frame.mHeight = port->mHeight;
- frame.mYuv[0] = NULL;
- frame.mYuv[1] = NULL;
- if ( onlyOnce && mRecording )
- {
- mTimeSourceDelta = (pBuffHeader->nTimeStamp * 1000) - systemTime(SYSTEM_TIME_MONOTONIC);
- onlyOnce = false;
- }
- frame.mTimestamp = (pBuffHeader->nTimeStamp * 1000) - mTimeSourceDelta;
- ret = setInitFrameRefCount(frame.mBuffer, mask);
- if (ret != NO_ERROR) {
- CAMHAL_LOGDB("Error in setInitFrameRefCount %d", ret);
- } else {
- ret = sendFrameToSubscribers(&frame);
- }
- CAMHAL_LOGVB("B 0x%x T %llu", frame.mBuffer, pBuffHeader->nTimeStamp);
- LOG_FUNCTION_NAME_EXIT;
- return ret;
- }
这个方法在BaseCameraAdapter中实现
- status_t BaseCameraAdapter::sendFrameToSubscribers(CameraFrame *frame)
- {
- status_t ret = NO_ERROR;
- unsigned int mask;
- if ( NULL == frame )
- {
- CAMHAL_LOGEA("Invalid CameraFrame");
- return -EINVAL;
- }
- for( mask = 1; mask < CameraFrame::ALL_FRAMES; mask <<= 1){
- if( mask & frame->mFrameMask ){
- switch( mask ){
- case CameraFrame::IMAGE_FRAME:
- {
- #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
- CameraHal::PPM("Shot to Jpeg: ", &mStartCapture);
- #endif
- ret = __sendFrameToSubscribers(frame, &mImageSubscribers, CameraFrame::IMAGE_FRAME);
- }
- break;
- case CameraFrame::RAW_FRAME:
- {
- ret = __sendFrameToSubscribers(frame, &mRawSubscribers, CameraFrame::RAW_FRAME);
- }
- break;
- case CameraFrame::PREVIEW_FRAME_SYNC:
- {
- ret = __sendFrameToSubscribers(frame, &mFrameSubscribers, CameraFrame::PREVIEW_FRAME_SYNC);
- }
- break;
- case CameraFrame::SNAPSHOT_FRAME:
- {
- ret = __sendFrameToSubscribers(frame, &mSnapshotSubscribers, CameraFrame::SNAPSHOT_FRAME);
- }
- break;
- case CameraFrame::VIDEO_FRAME_SYNC:
- {
- ret = __sendFrameToSubscribers(frame, &mVideoSubscribers, CameraFrame::VIDEO_FRAME_SYNC);
- }
- break;
- case CameraFrame::FRAME_DATA_SYNC:
- {
- ret = __sendFrameToSubscribers(frame, &mFrameDataSubscribers, CameraFrame::FRAME_DATA_SYNC);
- }
- break;
- case CameraFrame::REPROCESS_INPUT_FRAME:
- {
- ret = __sendFrameToSubscribers(frame, &mVideoInSubscribers, CameraFrame::REPROCESS_INPUT_FRAME);
- }
- break;
- default:
- CAMHAL_LOGEB("FRAMETYPE NOT SUPPORTED 0x%x", mask);
- break;
- }//SWITCH
- frame->mFrameMask &= ~mask;
- if (ret != NO_ERROR) {
- goto EXIT;
- }
- }//IF
- }//FOR
- EXIT:
- return ret;
- }
我们接着看看上面标注部分的实现,其实之前早就说过了
- status_t BaseCameraAdapter::__sendFrameToSubscribers(CameraFrame* frame,
- KeyedVector<int, frame_callback> *subscribers,
- CameraFrame::FrameType frameType)
- {
- size_t refCount = 0;
- status_t ret = NO_ERROR;
- frame_callback callback = NULL;
- frame->mFrameType = frameType;
- if ( (frameType == CameraFrame::PREVIEW_FRAME_SYNC) ||
- (frameType == CameraFrame::VIDEO_FRAME_SYNC) ||
- (frameType == CameraFrame::SNAPSHOT_FRAME) ){
- if (mFrameQueue.size() > 0){
- CameraFrame *lframe = (CameraFrame *)mFrameQueue.valueFor(frame->mBuffer);
- frame->mYuv[0] = lframe->mYuv[0];
- frame->mYuv[1] = frame->mYuv[0] + (frame->mLength + frame->mOffset)*2/3;
- }
- else{
- CAMHAL_LOGDA("Empty Frame Queue");
- return -EINVAL;
- }
- }
- if (NULL != subscribers) {
- refCount = getFrameRefCount(frame->mBuffer, frameType);
- if (refCount == 0) {
- CAMHAL_LOGDA("Invalid ref count of 0");
- return -EINVAL;
- }
- if (refCount > subscribers->size()) {
- CAMHAL_LOGEB("Invalid ref count for frame type: 0x%x", frameType);
- return -EINVAL;
- }
- CAMHAL_LOGVB("Type of Frame: 0x%x address: 0x%x refCount start %d",
- frame->mFrameType,
- ( uint32_t ) frame->mBuffer,
- refCount);
- for ( unsigned int i = 0 ; i < refCount; i++ ) {
- frame->mCookie = ( void * ) subscribers->keyAt(i);
- callback = (frame_callback) subscribers->valueAt(i);
- if (!callback) {
- CAMHAL_LOGEB("callback not set for frame type: 0x%x", frameType);
- return -EINVAL;
- }
- callback(frame);
- }
- } else {
- CAMHAL_LOGEA("Subscribers is null??");
- return -EINVAL;
- }
- return ret;
- }
上面已经说过了,AppNotifier在构造的时候会创建并启动一个线程检查是否有消息到达,消息到达则进行相应的分类处理
这里只针对notifyFrame进行分析
- void AppCallbackNotifier::notifyFrame()
- {
- ///Receive and send the frame notifications to app
- TIUTILS::Message msg;
- CameraFrame *frame;
- MemoryHeapBase *heap;
- MemoryBase *buffer = NULL;
- sp<MemoryBase> memBase;
- void *buf = NULL;
- LOG_FUNCTION_NAME;
- {
- Mutex::Autolock lock(mLock);
- if(!mFrameQ.isEmpty()) {
- mFrameQ.get(&msg);
- } else {
- return;
- }
- }
- bool ret = true;
- frame = NULL;
- switch(msg.command)
- {
- case AppCallbackNotifier::NOTIFIER_CMD_PROCESS_FRAME:
- frame = (CameraFrame *) msg.arg1;
- if(!frame)
- {
- break;
- }
- if ( (CameraFrame::RAW_FRAME == frame->mFrameType )&&
- ( NULL != mCameraHal ) &&
- ( NULL != mDataCb) &&
- ( NULL != mNotifyCb ) )
- {
- if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_RAW_IMAGE) )
- {
- #ifdef COPY_IMAGE_BUFFER
- copyAndSendPictureFrame(frame, CAMERA_MSG_RAW_IMAGE);
- #else
- //TODO: Find a way to map a Tiler buffer to a MemoryHeapBase
- #endif
- }
- else {
- if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_RAW_IMAGE_NOTIFY) ) {
- mNotifyCb(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mCallbackCookie);
- }
- mFrameProvider->returnFrame(frame->mBuffer,
- (CameraFrame::FrameType) frame->mFrameType);
- }
- mRawAvailable = true;
- }
- else if ( (CameraFrame::IMAGE_FRAME == frame->mFrameType) &&
- (NULL != mCameraHal) &&
- (NULL != mDataCb) &&
- (CameraFrame::ENCODE_RAW_YUV422I_TO_JPEG & frame->mQuirks) )
- {
- int encode_quality = 100, tn_quality = 100;
- int tn_width, tn_height;
- unsigned int current_snapshot = 0;
- Encoder_libjpeg::params *main_jpeg = NULL, *tn_jpeg = NULL;
- void* exif_data = NULL;
- const char *previewFormat = NULL;
- camera_memory_t* raw_picture = mRequestMemory(-1, frame->mLength, 1, NULL);
- if(raw_picture) {
- buf = raw_picture->data;
- }
- CameraParameters parameters;
- char *params = mCameraHal->getParameters();
- const String8 strParams(params);
- parameters.unflatten(strParams);
- encode_quality = parameters.getInt(CameraParameters::KEY_JPEG_QUALITY);
- if (encode_quality < 0 || encode_quality > 100) {
- encode_quality = 100;
- }
- tn_quality = parameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
- if (tn_quality < 0 || tn_quality > 100) {
- tn_quality = 100;
- }
- if (CameraFrame::HAS_EXIF_DATA & frame->mQuirks) {
- exif_data = frame->mCookie2;
- }
- main_jpeg = (Encoder_libjpeg::params*)
- malloc(sizeof(Encoder_libjpeg::params));
- // Video snapshot with LDCNSF on adds a few bytes start offset
- // and a few bytes on every line. They must be skipped.
- int rightCrop = frame->mAlignment/2 - frame->mWidth;
- CAMHAL_LOGDB("Video snapshot right crop = %d", rightCrop);
- CAMHAL_LOGDB("Video snapshot offset = %d", frame->mOffset);
- if (main_jpeg) {
- main_jpeg->src = (uint8_t *)frame->mBuffer->mapped;
- main_jpeg->src_size = frame->mLength;
- main_jpeg->dst = (uint8_t*) buf;
- main_jpeg->dst_size = frame->mLength;
- main_jpeg->quality = encode_quality;
- main_jpeg->in_width = frame->mAlignment/2; // use stride here
- main_jpeg->in_height = frame->mHeight;
- main_jpeg->out_width = frame->mAlignment/2;
- main_jpeg->out_height = frame->mHeight;
- main_jpeg->right_crop = rightCrop;
- main_jpeg->start_offset = frame->mOffset;
- if ( CameraFrame::FORMAT_YUV422I_UYVY & frame->mQuirks) {
- main_jpeg->format = TICameraParameters::PIXEL_FORMAT_YUV422I_UYVY;
- }
- else { //if ( CameraFrame::FORMAT_YUV422I_YUYV & frame->mQuirks)
- main_jpeg->format = CameraParameters::PIXEL_FORMAT_YUV422I;
- }
- }
- tn_width = parameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
- tn_height = parameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
- previewFormat = parameters.getPreviewFormat();
- if ((tn_width > 0) && (tn_height > 0) && ( NULL != previewFormat )) {
- tn_jpeg = (Encoder_libjpeg::params*)
- malloc(sizeof(Encoder_libjpeg::params));
- // if malloc fails just keep going and encode main jpeg
- if (!tn_jpeg) {
- tn_jpeg = NULL;
- }
- }
- if (tn_jpeg) {
- int width, height;
- parameters.getPreviewSize(&width,&height);
- current_snapshot = (mPreviewBufCount + MAX_BUFFERS - 1) % MAX_BUFFERS;
- tn_jpeg->src = (uint8_t *)mPreviewBuffers[current_snapshot].mapped;
- tn_jpeg->src_size = mPreviewMemory->size / MAX_BUFFERS;
- tn_jpeg->dst_size = calculateBufferSize(tn_width,
- tn_height,
- previewFormat);
- tn_jpeg->dst = (uint8_t*) malloc(tn_jpeg->dst_size);
- tn_jpeg->quality = tn_quality;
- tn_jpeg->in_width = width;
- tn_jpeg->in_height = height;
- tn_jpeg->out_width = tn_width;
- tn_jpeg->out_height = tn_height;
- tn_jpeg->right_crop = 0;
- tn_jpeg->start_offset = 0;
- tn_jpeg->format = CameraParameters::PIXEL_FORMAT_YUV420SP;;
- }
- sp<Encoder_libjpeg> encoder = new Encoder_libjpeg(main_jpeg,
- tn_jpeg,
- AppCallbackNotifierEncoderCallback,
- (CameraFrame::FrameType)frame->mFrameType,
- this,
- raw_picture,
- exif_data, frame->mBuffer);
- gEncoderQueue.add(frame->mBuffer->mapped, encoder);
- encoder->run();
- encoder.clear();
- if (params != NULL)
- {
- mCameraHal->putParameters(params);
- }
- }
- else if ( ( CameraFrame::IMAGE_FRAME == frame->mFrameType ) &&
- ( NULL != mCameraHal ) &&
- ( NULL != mDataCb) )
- {
- // CTS, MTS requirements: Every 'takePicture()' call
- // who registers a raw callback should receive one
- // as well. This is not always the case with
- // CameraAdapters though.
- if (!mCameraHal->msgTypeEnabled(CAMERA_MSG_RAW_IMAGE)) {
- dummyRaw();
- } else {
- mRawAvailable = false;
- }
- #ifdef COPY_IMAGE_BUFFER
- {
- Mutex::Autolock lock(mBurstLock);
- #if defined(OMAP_ENHANCEMENT)
- if ( mBurst )
- {
- copyAndSendPictureFrame(frame, CAMERA_MSG_COMPRESSED_BURST_IMAGE);
- }
- else
- #endif
- {
- copyAndSendPictureFrame(frame, CAMERA_MSG_COMPRESSED_IMAGE);
- }
- }
- #else
- //TODO: Find a way to map a Tiler buffer to a MemoryHeapBase
- #endif
- }
- else if ( ( CameraFrame::VIDEO_FRAME_SYNC == frame->mFrameType ) &&
- ( NULL != mCameraHal ) &&
- ( NULL != mDataCb) &&
- ( mCameraHal->msgTypeEnabled(CAMERA_MSG_VIDEO_FRAME) ) )
- {
- AutoMutex locker(mRecordingLock);
- if(mRecording)
- {
- if(mUseMetaDataBufferMode)
- {
- camera_memory_t *videoMedatadaBufferMemory =
- mVideoMetadataBufferMemoryMap.valueFor(frame->mBuffer->opaque);
- video_metadata_t *videoMetadataBuffer = (video_metadata_t *) videoMedatadaBufferMemory->data;
- if( (NULL == videoMedatadaBufferMemory) || (NULL == videoMetadataBuffer) || (NULL == frame->mBuffer) )
- {
- CAMHAL_LOGEA("Error! One of the video buffers is NULL");
- break;
- }
- if ( mUseVideoBuffers )
- {
- CameraBuffer *vBuf = mVideoMap.valueFor(frame->mBuffer->opaque);
- GraphicBufferMapper &mapper = GraphicBufferMapper::get();
- Rect bounds;
- bounds.left = 0;
- bounds.top = 0;
- bounds.right = mVideoWidth;
- bounds.bottom = mVideoHeight;
- void *y_uv[2];
- mapper.lock((buffer_handle_t)vBuf, CAMHAL_GRALLOC_USAGE, bounds, y_uv);
- y_uv[1] = y_uv[0] + mVideoHeight*4096;
- structConvImage input = {frame->mWidth,
- frame->mHeight,
- 4096,
- IC_FORMAT_YCbCr420_lp,
- (mmByte *)frame->mYuv[0],
- (mmByte *)frame->mYuv[1],
- frame->mOffset};
- structConvImage output = {mVideoWidth,
- mVideoHeight,
- 4096,
- IC_FORMAT_YCbCr420_lp,
- (mmByte *)y_uv[0],
- (mmByte *)y_uv[1],
- 0};
- VT_resizeFrame_Video_opt2_lp(&input, &output, NULL, 0);
- mapper.unlock((buffer_handle_t)vBuf->opaque);
- videoMetadataBuffer->metadataBufferType = (int) kMetadataBufferTypeCameraSource;
- /* FIXME remove cast */
- videoMetadataBuffer->handle = (void *)vBuf->opaque;
- videoMetadataBuffer->offset = 0;
- }
- else
- {
- videoMetadataBuffer->metadataBufferType = (int) kMetadataBufferTypeCameraSource;
- videoMetadataBuffer->handle = camera_buffer_get_omx_ptr(frame->mBuffer);
- videoMetadataBuffer->offset = frame->mOffset;
- }
- CAMHAL_LOGVB("mDataCbTimestamp : frame->mBuffer=0x%x, videoMetadataBuffer=0x%x, videoMedatadaBufferMemory=0x%x",
- frame->mBuffer->opaque, videoMetadataBuffer, videoMedatadaBufferMemory);
- mDataCbTimestamp(frame->mTimestamp, CAMERA_MSG_VIDEO_FRAME,
- videoMedatadaBufferMemory, 0, mCallbackCookie);
- }
- else
- {
- //TODO: Need to revisit this, should ideally be mapping the TILER buffer using mRequestMemory
- camera_memory_t* fakebuf = mRequestMemory(-1, sizeof(buffer_handle_t), 1, NULL);
- if( (NULL == fakebuf) || ( NULL == fakebuf->data) || ( NULL == frame->mBuffer))
- {
- CAMHAL_LOGEA("Error! One of the video buffers is NULL");
- break;
- }
- *reinterpret_cast<buffer_handle_t*>(fakebuf->data) = reinterpret_cast<buffer_handle_t>(frame->mBuffer->mapped);
- mDataCbTimestamp(frame->mTimestamp, CAMERA_MSG_VIDEO_FRAME, fakebuf, 0, mCallbackCookie);
- fakebuf->release(fakebuf);
- }
- }
- }
- else if(( CameraFrame::SNAPSHOT_FRAME == frame->mFrameType ) &&
- ( NULL != mCameraHal ) &&
- ( NULL != mDataCb) &&
- ( NULL != mNotifyCb)) {
- //When enabled, measurement data is sent instead of video data
- if ( !mMeasurementEnabled ) {
- copyAndSendPreviewFrame(frame, CAMERA_MSG_POSTVIEW_FRAME);
- } else {
- mFrameProvider->returnFrame(frame->mBuffer,
- (CameraFrame::FrameType) frame->mFrameType);
- }
- }
- else if ( ( CameraFrame::PREVIEW_FRAME_SYNC== frame->mFrameType ) &&
- ( NULL != mCameraHal ) &&
- ( NULL != mDataCb) &&
- ( mCameraHal->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME)) ) {
- //When enabled, measurement data is sent instead of video data
- if ( !mMeasurementEnabled ) {
- copyAndSendPreviewFrame(frame, CAMERA_MSG_PREVIEW_FRAME);
- } else {
- mFrameProvider->returnFrame(frame->mBuffer,
- (CameraFrame::FrameType) frame->mFrameType);
- }
- }
- else if ( ( CameraFrame::FRAME_DATA_SYNC == frame->mFrameType ) &&
- ( NULL != mCameraHal ) &&
- ( NULL != mDataCb) &&
- ( mCameraHal->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME)) ) {
- copyAndSendPreviewFrame(frame, CAMERA_MSG_PREVIEW_FRAME);
- } else {
- mFrameProvider->returnFrame(frame->mBuffer,
- ( CameraFrame::FrameType ) frame->mFrameType);
- CAMHAL_LOGDB("Frame type 0x%x is still unsupported!", frame->mFrameType);
- }
- break;
- default:
- break;
- };
- exit:
- if ( NULL != frame )
- {
- delete frame;
- }
- LOG_FUNCTION_NAME_EXIT;
- }
待续。。。