status_t QCameraStream_preview::getBufferFromSurface() { int err = 0; int numMinUndequeuedBufs = 0; int format = 0; status_t ret = NO_ERROR; ALOGI(" %s : E ", __FUNCTION__); if( mPreviewWindow == NULL) { ALOGE("%s: mPreviewWindow = NULL", __func__); return INVALID_OPERATION; } cam_ctrl_dimension_t dim; //mDisplayLock.lock(); cam_config_get_parm(mCameraId, MM_CAMERA_PARM_DIMENSION,&dim); format = mHalCamCtrl->getPreviewFormatInfo().Hal_format; if(ret != NO_ERROR) { ALOGE("%s: display format %d is not supported", __func__, dim.prev_format); goto end; } numMinUndequeuedBufs = 0; if(mPreviewWindow->get_min_undequeued_buffer_count) { err = mPreviewWindow->get_min_undequeued_buffer_count(mPreviewWindow, &numMinUndequeuedBufs); if (err != 0) { ALOGE("get_min_undequeued_buffer_count failed: %s (%d)", strerror(-err), -err); ret = UNKNOWN_ERROR; goto end; } } mHalCamCtrl->mPreviewMemoryLock.lock(); mHalCamCtrl->mPreviewMemory.buffer_count = kPreviewBufferCount + numMinUndequeuedBufs;; err = mPreviewWindow->set_buffer_count(mPreviewWindow, mHalCamCtrl->mPreviewMemory.buffer_count ); if (err != 0) { ALOGE("set_buffer_count failed: %s (%d)", strerror(-err), -err); ret = UNKNOWN_ERROR; goto end; } err = mPreviewWindow->set_buffers_geometry(mPreviewWindow, dim.display_width, dim.display_height, format); if (err != 0) { ALOGE("set_buffers_geometry failed: %s (%d)", strerror(-err), -err); ret = UNKNOWN_ERROR; goto end; } err = mPreviewWindow->set_usage(mPreviewWindow, GRALLOC_USAGE_PRIVATE_ADSP_HEAP | GRALLOC_USAGE_PRIVATE_UNCACHED); if(err != 0) { /* set_usage error out */ ALOGE("%s: set_usage rc = %d", __func__, err); ret = UNKNOWN_ERROR; goto end; } for (int cnt = 0; cnt < mHalCamCtrl->mPreviewMemory.buffer_count; cnt++) { int stride; err = mPreviewWindow->dequeue_buffer(mPreviewWindow, &mHalCamCtrl->mPreviewMemory.buffer_handle[cnt], &mHalCamCtrl->mPreviewMemory.stride[cnt]); if(!err) { err = mPreviewWindow->lock_buffer(this->mPreviewWindow, mHalCamCtrl->mPreviewMemory.buffer_handle[cnt]); // lock the buffer using genlock ALOGD("%s: camera call genlock_lock", __FUNCTION__); if (GENLOCK_NO_ERROR != genlock_lock_buffer((native_handle_t *)(*mHalCamCtrl->mPreviewMemory.buffer_handle[cnt]), GENLOCK_WRITE_LOCK, GENLOCK_MAX_TIMEOUT)) { ALOGE("%s: genlock_lock_buffer(WRITE) failed", __FUNCTION__); mHalCamCtrl->mPreviewMemory.local_flag[cnt] = BUFFER_UNLOCKED; mHalCamCtrl->mPreviewMemoryLock.unlock(); return -EINVAL; } mHalCamCtrl->mPreviewMemory.local_flag[cnt] = BUFFER_LOCKED; } else ALOGE("%s: dequeue_buffer idx = %d err = %d", __func__, cnt, err); ALOGE("%s: dequeue buf: %u\n", __func__, (unsigned int)mHalCamCtrl->mPreviewMemory.buffer_handle[cnt]); if(err != 0) { ALOGE("%s: dequeue_buffer failed: %s (%d)", __func__, strerror(-err), -err); ret = UNKNOWN_ERROR; for(int i = 0; i < cnt; i++) { ALOGD("%s: camera call genlock_unlock", __FUNCTION__); if (BUFFER_LOCKED == mHalCamCtrl->mPreviewMemory.local_flag[i]) { if (GENLOCK_FAILURE == genlock_unlock_buffer((native_handle_t *) (*(mHalCamCtrl->mPreviewMemory.buffer_handle[i])))) { ALOGE("%s: genlock_unlock_buffer failed", __FUNCTION__); mHalCamCtrl->mPreviewMemoryLock.unlock(); return -EINVAL; } } err = mPreviewWindow->cancel_buffer(mPreviewWindow, mHalCamCtrl->mPreviewMemory.buffer_handle[i]); mHalCamCtrl->mPreviewMemory.buffer_handle[i] = NULL; mHalCamCtrl->mPreviewMemory.local_flag[i] = BUFFER_UNLOCKED; } goto end; } mHalCamCtrl->mPreviewMemory.private_buffer_handle[cnt] = (struct private_handle_t *)(*mHalCamCtrl->mPreviewMemory.buffer_handle[cnt]); mHalCamCtrl->mPreviewMemory.camera_memory[cnt] = mHalCamCtrl->mGetMemory(mHalCamCtrl->mPreviewMemory.private_buffer_handle[cnt]->fd, mHalCamCtrl->mPreviewMemory.private_buffer_handle[cnt]->size, 1, (void *)this); ALOGE("%s: idx = %d, fd = %d, size = %d, offset = %d", __func__, cnt, mHalCamCtrl->mPreviewMemory.private_buffer_handle[cnt]->fd, mHalCamCtrl->mPreviewMemory.private_buffer_handle[cnt]->size, mHalCamCtrl->mPreviewMemory.private_buffer_handle[cnt]->offset); } memset(&mHalCamCtrl->mMetadata, 0, sizeof(mHalCamCtrl->mMetadata)); memset(mHalCamCtrl->mFace, 0, sizeof(mHalCamCtrl->mFace)); ALOGI(" %s : X ",__FUNCTION__); end: //mDisplayLock.unlock(); mHalCamCtrl->mPreviewMemoryLock.unlock(); return NO_ERROR; }
int CopyBit::drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer, EGLDisplay dpy, EGLSurface surface, functype_eglGetRenderBufferANDROID& LINK_eglGetRenderBufferANDROID, functype_eglGetCurrentSurface LINK_eglGetCurrentSurface) { hwc_context_t* ctx = (hwc_context_t*)(dev); if(!ctx) { ALOGE("%s: null context ", __FUNCTION__); return -1; } private_handle_t *hnd = (private_handle_t *)layer->handle; if(!hnd) { ALOGE("%s: invalid handle", __FUNCTION__); return -1; } // Lock this buffer for read. genlock_lock_type lockType = GENLOCK_READ_LOCK; int err = genlock_lock_buffer(hnd, lockType, GENLOCK_MAX_TIMEOUT); if (GENLOCK_FAILURE == err) { ALOGE("%s: genlock_lock_buffer(READ) failed", __FUNCTION__); return -1; } //render buffer EGLSurface eglSurface = LINK_eglGetCurrentSurface(EGL_DRAW); android_native_buffer_t *renderBuffer = (android_native_buffer_t *)LINK_eglGetRenderBufferANDROID(dpy, eglSurface); if (!renderBuffer) { ALOGE("%s: eglGetRenderBuffer returned NULL buffer", __FUNCTION__); genlock_unlock_buffer(hnd); return -1; } private_handle_t *fbHandle = (private_handle_t *)renderBuffer->handle; if(!fbHandle) { ALOGE("%s: Framebuffer handle is NULL", __FUNCTION__); genlock_unlock_buffer(hnd); return -1; } // Set the copybit source: copybit_image_t src; src.w = hnd->width; src.h = hnd->height; src.format = hnd->format; src.base = (void *)hnd->base; src.handle = (native_handle_t *)layer->handle; src.horiz_padding = src.w - hnd->width; // Initialize vertical padding to zero for now, // this needs to change to accomodate vertical stride // if needed in the future src.vert_padding = 0; // Remove the srcBufferTransform if any layer->transform = (layer->transform & FINAL_TRANSFORM_MASK); // Copybit source rect hwc_rect_t sourceCrop = layer->sourceCrop; copybit_rect_t srcRect = {sourceCrop.left, sourceCrop.top, sourceCrop.right, sourceCrop.bottom}; // Copybit destination rect hwc_rect_t displayFrame = layer->displayFrame; copybit_rect_t dstRect = {displayFrame.left, displayFrame.top, displayFrame.right, displayFrame.bottom}; // Copybit dst copybit_image_t dst; dst.w = ALIGN(fbHandle->width,32); dst.h = fbHandle->height; dst.format = fbHandle->format; dst.base = (void *)fbHandle->base; dst.handle = (native_handle_t *)renderBuffer->handle; copybit_device_t *copybit = ctx->mCopybitEngine->getEngine(); int32_t screen_w = displayFrame.right - displayFrame.left; int32_t screen_h = displayFrame.bottom - displayFrame.top; int32_t src_crop_width = sourceCrop.right - sourceCrop.left; int32_t src_crop_height = sourceCrop.bottom -sourceCrop.top; // Copybit dst float copybitsMaxScale = (float)copybit->get(copybit,COPYBIT_MAGNIFICATION_LIMIT); float copybitsMinScale = (float)copybit->get(copybit,COPYBIT_MINIFICATION_LIMIT); if((layer->transform == HWC_TRANSFORM_ROT_90) || (layer->transform == HWC_TRANSFORM_ROT_270)) { //swap screen width and height int tmp = screen_w; screen_w = screen_h; screen_h = tmp; } private_handle_t *tmpHnd = NULL; if(screen_w <=0 || screen_h<=0 ||src_crop_width<=0 || src_crop_height<=0 ) { ALOGE("%s: wrong params for display screen_w=%d src_crop_width=%d \ screen_w=%d src_crop_width=%d", __FUNCTION__, screen_w, src_crop_width,screen_w,src_crop_width); genlock_unlock_buffer(hnd); return -1; }
status_t QCameraStream_preview::processPreviewFrame(mm_camera_ch_data_buf_t *frame) { ALOGV("%s",__func__); int err = 0; int msgType = 0; camera_memory_t *data = NULL; camera_frame_metadata_t *metadata = NULL; Mutex::Autolock lock(mStopCallbackLock); if(!mActive) { ALOGE("Preview Stopped. Returning callback"); return NO_ERROR; } if(mHalCamCtrl==NULL) { ALOGE("%s: X: HAL control object not set",__func__); /*Call buf done*/ return BAD_VALUE; } mHalCamCtrl->mCallbackLock.lock(); camera_data_timestamp_callback rcb = mHalCamCtrl->mDataCbTimestamp; void *rdata = mHalCamCtrl->mCallbackCookie; mHalCamCtrl->mCallbackLock.unlock(); if (UNLIKELY(mHalCamCtrl->mDebugFps)) { mHalCamCtrl->debugShowPreviewFPS(); } //dumpFrameToFile(frame->def.frame); mHalCamCtrl->dumpFrameToFile(frame->def.frame, HAL_DUMP_FRM_PREVIEW); nsecs_t timeStamp = systemTime(); mHalCamCtrl->mPreviewMemoryLock.lock(); mNotifyBuffer[frame->def.idx] = *frame; // mzhu fix me, need to check meta data also. ALOGI("Enqueue buf handle %p\n", mHalCamCtrl->mPreviewMemory.buffer_handle[frame->def.idx]); ALOGD("%s: camera call genlock_unlock", __FUNCTION__); if (BUFFER_LOCKED == mHalCamCtrl->mPreviewMemory.local_flag[frame->def.idx]) { if (GENLOCK_FAILURE == genlock_unlock_buffer((native_handle_t*) (*mHalCamCtrl->mPreviewMemory.buffer_handle[frame->def.idx]))) { ALOGE("%s: genlock_unlock_buffer failed", __FUNCTION__); mHalCamCtrl->mPreviewMemoryLock.unlock(); return -EINVAL; } else { mHalCamCtrl->mPreviewMemory.local_flag[frame->def.idx] = BUFFER_UNLOCKED; } } else { ALOGE("%s: buffer to be enqueued is not locked", __FUNCTION__); mHalCamCtrl->mPreviewMemoryLock.unlock(); return -EINVAL; } err = this->mPreviewWindow->enqueue_buffer(this->mPreviewWindow, (buffer_handle_t *)mHalCamCtrl->mPreviewMemory.buffer_handle[frame->def.idx]); if(err != 0) { ALOGE("%s: enqueue_buffer failed, err = %d", __func__, err); } buffer_handle_t *buffer_handle = NULL; int tmp_stride = 0; err = this->mPreviewWindow->dequeue_buffer(this->mPreviewWindow, &buffer_handle, &tmp_stride); if (err == NO_ERROR && buffer_handle != NULL) { err = this->mPreviewWindow->lock_buffer(this->mPreviewWindow, buffer_handle); ALOGD("%s: camera call genlock_lock", __FUNCTION__); if (GENLOCK_FAILURE == genlock_lock_buffer((native_handle_t*)(*buffer_handle), GENLOCK_WRITE_LOCK, GENLOCK_MAX_TIMEOUT)) { ALOGE("%s: genlock_lock_buffer(WRITE) failed", __FUNCTION__); mHalCamCtrl->mPreviewMemoryLock.unlock(); return -EINVAL; } for(int i = 0; i < mHalCamCtrl->mPreviewMemory.buffer_count; i++) { ALOGD("h1: %p h2: %p\n", mHalCamCtrl->mPreviewMemory.buffer_handle[i], buffer_handle); if(mHalCamCtrl->mPreviewMemory.buffer_handle[i] == buffer_handle) { mm_camera_ch_data_buf_t tmp_frame; mHalCamCtrl->mPreviewMemory.local_flag[i] = BUFFER_LOCKED; if(MM_CAMERA_OK != cam_evt_buf_done(mCameraId, &mNotifyBuffer[i])) { ALOGD("BUF DONE FAILED"); mHalCamCtrl->mPreviewMemoryLock.unlock(); return BAD_VALUE; } break; } } } else ALOGE("%s: error in dequeue_buffer, enqueue_buffer idx = %d, no free buffer now", __func__, frame->def.idx); /* Save the last displayed frame. We'll be using it to fill the gap between when preview stops and postview start during snapshot.*/ mLastQueuedFrame = &(mDisplayStreamBuf.frame[frame->def.idx]); mHalCamCtrl->mPreviewMemoryLock.unlock(); mHalCamCtrl->mCallbackLock.lock(); camera_data_callback pcb = mHalCamCtrl->mDataCb; mHalCamCtrl->mCallbackLock.unlock(); ALOGD("Message enabled = 0x%x", mHalCamCtrl->mMsgEnabled); if (pcb != NULL) { //Sending preview callback if corresponding Msgs are enabled if(mHalCamCtrl->mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) { msgType |= CAMERA_MSG_PREVIEW_FRAME; data = mHalCamCtrl->mPreviewMemory.camera_memory[frame->def.idx];//mPreviewHeap->mBuffers[frame->def.idx]; } else { data = NULL; } if(msgType) { mStopCallbackLock.unlock(); pcb(msgType, data, 0, metadata, mHalCamCtrl->mCallbackCookie); } ALOGD("end of cb"); } if(rcb != NULL) { if (mHalCamCtrl->mStoreMetaDataInFrame) { mStopCallbackLock.unlock(); if(mHalCamCtrl->mStartRecording == true &&( mHalCamCtrl->mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) rcb(timeStamp, CAMERA_MSG_VIDEO_FRAME, mHalCamCtrl->mRecordingMemory.metadata_memory[frame->def.idx], 0, mHalCamCtrl->mCallbackCookie); } else { if(mHalCamCtrl->mStartRecording == true &&( mHalCamCtrl->mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) { mStopCallbackLock.unlock(); rcb(timeStamp, CAMERA_MSG_VIDEO_FRAME, mHalCamCtrl->mPreviewMemory.camera_memory[frame->def.idx], 0, mHalCamCtrl->mCallbackCookie); } } } /* Save the last displayed frame. We'll be using it to fill the gap between when preview stops and postview start during snapshot.*/ //mLastQueuedFrame = frame->def.frame; /* if(MM_CAMERA_OK != cam_evt_buf_done(mCameraId, frame)) { ALOGE("BUF DONE FAILED"); return BAD_VALUE; } */ return NO_ERROR; }