#include "CameraDebug.h" #if DBG_PREVIEW #define LOG_NDEBUG 0 #endif #define LOG_TAG "PreviewWindow" #include #include #include #include "V4L2CameraDevice2.h" #include "PreviewWindow.h" namespace android { #define CAMHAL_GRALLOC_USAGE GRALLOC_USAGE_HW_TEXTURE | \ GRALLOC_USAGE_HW_RENDER | \ GRALLOC_USAGE_SW_READ_RARELY | \ GRALLOC_USAGE_SW_WRITE_NEVER //#define CAMHAL_GRALLOC_USAGE GRALLOC_USAGE_HW_FB static int calculateFrameSize(int width, int height, uint32_t pix_fmt) { int frame_size = 0; switch (pix_fmt) { case V4L2_PIX_FMT_YVU420: case V4L2_PIX_FMT_YUV420: case V4L2_PIX_FMT_NV21: case V4L2_PIX_FMT_NV12: frame_size = (ALIGN_16B(width) * height * 12) / 8; break; case V4L2_PIX_FMT_YUYV: frame_size = (width * height) << 1; break; default: ALOGE("%s: Unknown pixel format %d(%.4s)", __FUNCTION__, pix_fmt, reinterpret_cast(&pix_fmt)); break; } return frame_size; } DBG_TIME_AVG_BEGIN(TAG_CPY); DBG_TIME_AVG_BEGIN(TAG_DQBUF); DBG_TIME_AVG_BEGIN(TAG_LKBUF); DBG_TIME_AVG_BEGIN(TAG_MAPPER); DBG_TIME_AVG_BEGIN(TAG_EQBUF); DBG_TIME_AVG_BEGIN(TAG_UNLKBUF); PreviewWindow::PreviewWindow() : mPreviewWindow(NULL), mPreviewFrameWidth(0), mPreviewFrameHeight(0), mPreviewFrameSize(0), mCurPixelFormat(0), mPreviewEnabled(false), mShouldAdjustDimensions(true) { F_LOG; for (int i = 0; i < NB_BUFFER; i ++) { mBufferHandle[i] = NULL; mPrivateHandle[i] = NULL; ddr_vir[i] = NULL; min_undequeued_num = 0; enqueue_buffer_num = 0; } } PreviewWindow::~PreviewWindow() { F_LOG; mPreviewWindow = NULL; } /**************************************************************************** * Camera API ***************************************************************************/ int PreviewWindow::allocate(int cnt,int width, int height, uint32_t pixformat) { LOGV("%s:cnt:%d, width:%d, height:%d",__FUNCTION__,cnt,width,height); enqueue_buffer_num = 0; int err = 0; int ret; struct ion_handle_data ion_handle; struct ion_fd_data ion_info_fd; memset(&ion_info_fd, 0, sizeof(ion_info_fd)); int format = V4L2_PIX_FMT_NV21; if (!mPreviewWindow) { LOGE("Invalid native window"); return -1; } switch (pixformat) { case V4L2_PIX_FMT_NV21: LOGV("preview format: HAL_PIXEL_FORMAT_YCrCb_420_SP"); format = HAL_PIXEL_FORMAT_YCrCb_420_SP; break; case V4L2_PIX_FMT_NV12: LOGV("preview format: V4L2_PIX_FMT_NV12"); format = 0x101; // NV12 break; case V4L2_PIX_FMT_YVU420: case V4L2_PIX_FMT_YUV420: // to do LOGV("preview format: HAL_PIXEL_FORMAT_YV12"); format = HAL_PIXEL_FORMAT_YV12; break; case V4L2_PIX_FMT_YUYV: LOGV("preview format: HAL_PIXEL_FORMAT_YCbCr_422_I"); format = HAL_PIXEL_FORMAT_YCbCr_422_I; break; default: LOGE("preview unknown pixel format: %08x", pixformat); return -1; } mPreviewWindow->get_min_undequeued_buffer_count(mPreviewWindow, &min_undequeued_num); ret = mPreviewWindow->set_buffers_geometry(mPreviewWindow, width, height, format); if (ret != NO_ERROR) { LOGE("%s: Error in set_buffers_geometry %d -> %s", __FUNCTION__, -ret, strerror(-ret)); return ret; } ret = mPreviewWindow->set_crop(mPreviewWindow,0,0,width,height); if (cnt == 1) { ret = mPreviewWindow->set_buffer_count(mPreviewWindow, cnt + 2); } else { ret = mPreviewWindow->set_buffer_count(mPreviewWindow, cnt); } if (ret != NO_ERROR) { LOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-ret), -ret); if ( ENODEV == ret ) { LOGE("Preview surface abandoned!"); mPreviewWindow = NULL; } return ret; } GraphicBufferMapper& grbuffer_mapper(GraphicBufferMapper::get()); /* Allocate cnt number of buffers from native window */ for(int i = 0; i < cnt; i++){ int stride = 0; ret = mPreviewWindow->dequeue_buffer(mPreviewWindow, &mBufferHandle[i], &stride); if (ret != NO_ERROR) { LOGE("dequeue preview idx = %d err = %d",i,ret); return ret; } LOGV("dequeue buf hdl%d =%p", i, mBufferHandle[i]); mPrivateHandle[i] = (private_handle_t *)(*mBufferHandle[i]); /* Let the preview window to lock the buffer. */ ret = mPreviewWindow->lock_buffer(mPreviewWindow, mBufferHandle[i]); if (ret != NO_ERROR) { LOGE("%s: Unable to lock preview window buffer: %d -> %s", __FUNCTION__, -ret, strerror(-ret)); mPreviewWindow->cancel_buffer(mPreviewWindow, mBufferHandle[i]); return ret; } /* let the graphics framework to lock the buffer, and get the virtual address. */ const Rect rect(width, height); //GraphicBufferMapper& grbuffer_mapper(GraphicBufferMapper::get()); ret = grbuffer_mapper.lock(*mBufferHandle[i], CAMHAL_GRALLOC_USAGE, rect, &ddr_vir[i]); if (ret != NO_ERROR) { LOGE("%s: grbuffer_mapper.lock failure: %d -> %s", __FUNCTION__, ret, strerror(ret)); mPreviewWindow->cancel_buffer(mPreviewWindow, mBufferHandle[i]); return ret; } //ddr_vir[i] = mPrivateHandle[i]->base; mBufferFlag[i] = BUFFER_OWNED; LOGV("index:%d,width:%d,height:%d,pri_p:%p,fd:%d,vir:%p,aw_buf_id:%lld", i, mPrivateHandle[i]->width, mPrivateHandle[i]->height, mPrivateHandle[i], mPrivateHandle[i]->share_fd, ddr_vir[i], mPrivateHandle[i]->aw_buf_id); #if 0 mMemInfo[i].main_ion_fd = open("/dev/ion", O_RDONLY); ion_info_fd.fd = mPrivateHandle[i]->share_fd; if (ioctl(mMemInfo[i].main_ion_fd,ION_IOC_IMPORT, &ion_info_fd) < 0) { LOGE("ION import failed\n"); close(mMemInfo[i].main_ion_fd); }else{ mMemInfo[i].fd = mPrivateHandle[i]->share_fd; //mMemInfo[i].size = mPrivateHandle[i]->size; mMemInfo[i].handle = ion_info_fd.handle; LOGD("mMemInfo[%d]:main_ion_fd:%d,share_fd:%d,size:%d,ion_info_fd.handle:%d",mMemInfo[i].main_ion_fd,i,mMemInfo[i].fd,mMemInfo[i].size,mMemInfo[i].handle); } #endif } return NO_ERROR; } void PreviewWindow::deallocate(int cnt) { for (int i = 0; i < cnt; i++) { #if 0 struct ion_handle_data ion_handle; memset(&ion_handle, 0, sizeof(ion_handle)); ion_handle.handle = mMemInfo[i].handle; if (ioctl(mMemInfo[i].main_ion_fd, ION_IOC_FREE, &ion_handle) < 0) { LOGE("ion free failed"); } close(mMemInfo[i].main_ion_fd); #endif if(mBufferFlag[i] != BUFFER_NOT_OWNED) { int err = NO_ERROR; err = unlockBuffer(i); if(err != NO_ERROR) { LOGE("unlockBuffer failed, err = %d \n", err); } if (mPreviewWindow) { mPreviewWindow->cancel_buffer(mPreviewWindow, mBufferHandle[i]); LOGV("cancel_buffer: hdl =%p", (*mBufferHandle[i])); } else { LOGE("Preview window is NULL, cannot cancel_buffer: hdl =%p", (*mBufferHandle[i])); } } mBufferFlag[i] = BUFFER_NOT_OWNED; LOGV("put buffer:%d successfully", i); } } int PreviewWindow::lockBuffer(int index) { int ret = -1; void * virFromGralloc; /* let the graphics framework to lock the buffer, and get the virtual address. */ const Rect rect(mPrivateHandle[index]->width, mPrivateHandle[index]->height); GraphicBufferMapper& grbuffer_mapper(GraphicBufferMapper::get()); ret = grbuffer_mapper.lock(*mBufferHandle[index], CAMHAL_GRALLOC_USAGE, rect, &virFromGralloc); LOGV("%s: virFromGralloc = %p ",__FUNCTION__, virFromGralloc); if ((ret != NO_ERROR)||(ddr_vir[index] != virFromGralloc)) { LOGE("%s: grbuffer_mapper.lock failure: %d -> %s", __FUNCTION__, ret, strerror(ret)); //Maybe the buffer queue has been abandoned,we should not cancel buffer. //mPreviewWindow->cancel_buffer(mPreviewWindow, mBufferHandle[index]); return false; } return NO_ERROR; } int PreviewWindow::unlockBuffer(int index) { int ret = -1; /* let the graphics framework to lock the buffer, and get the virtual address. */ const Rect rect(mPrivateHandle[index]->width, mPrivateHandle[index]->height); GraphicBufferMapper& grbuffer_mapper(GraphicBufferMapper::get()); ret = grbuffer_mapper.unlock(*mBufferHandle[index]/* *buffer */); if ((ret != NO_ERROR)) { LOGE("%s: grbuffer_mapper.unlock failure: %d -> %s", __FUNCTION__, ret, strerror(ret)); mPreviewWindow->cancel_buffer(mPreviewWindow, mBufferHandle[index]); return false; } return NO_ERROR; } status_t PreviewWindow::setPreviewWindow(struct preview_stream_ops* window) { LOGD("%s: current: %p -> new: %p", __FUNCTION__, mPreviewWindow, window); status_t res = NO_ERROR; Mutex::Autolock locker(&mObjectLock); /* Reset preview info. */ mPreviewFrameWidth = mPreviewFrameHeight = 0; if (window != NULL && mPreviewWindow != NULL && mPreviewWindow != window) { LOGD("%s:changed ! Current: %p -> new: %p", __FUNCTION__, mPreviewWindow, window); /* The CPU will write each frame to the preview window buffer. * Note that we delay setting preview window buffer geometry until * frames start to come in. */ res = window->set_usage(window, /*GRALLOC_USAGE_SW_WRITE_OFTEN*/CAMHAL_GRALLOC_USAGE); if (res != NO_ERROR) { window = NULL; res = -res; // set_usage returns a negative errno. LOGE("%s: Error setting preview window usage %d -> %s", __FUNCTION__, res, strerror(res)); } } mPreviewWindow = window; return res; } status_t PreviewWindow::startPreview() { F_LOG; Mutex::Autolock locker(&mObjectLock); mPreviewEnabled = true; DBG_TIME_AVG_INIT(TAG_CPY); DBG_TIME_AVG_INIT(TAG_DQBUF); DBG_TIME_AVG_INIT(TAG_LKBUF); DBG_TIME_AVG_INIT(TAG_MAPPER); DBG_TIME_AVG_INIT(TAG_EQBUF); DBG_TIME_AVG_INIT(TAG_UNLKBUF); return NO_ERROR; } void PreviewWindow::stopPreview() { F_LOG; Mutex::Autolock locker(&mObjectLock); mPreviewEnabled = false; mShouldAdjustDimensions = true; DBG_TIME_AVG_END(TAG_CPY, "copy "); DBG_TIME_AVG_END(TAG_DQBUF, "deque "); DBG_TIME_AVG_END(TAG_LKBUF, "lock "); DBG_TIME_AVG_END(TAG_MAPPER, "mapper "); DBG_TIME_AVG_END(TAG_EQBUF, "enque "); DBG_TIME_AVG_END(TAG_UNLKBUF, "unlock "); } /**************************************************************************** * Public API ***************************************************************************/ /*=========================================================================== * FUNCTION : onNextFrameAvailable * * DESCRIPTION: send received frame to display * * PARAMETERS : * @index : index of preview frame * * RETURN : int dequeuedIdx * dequeue_buffer index * if can not dequeue buffer,return -1 */ int PreviewWindow::onNextFrameAvailable2(int index, RECT_t preview_crop) { F_LOG; Mutex::Autolock locker(&mObjectLock); int err = NO_ERROR; int dequeuedIdx = -1; mPreviewWindow->set_crop(mPreviewWindow, preview_crop.left, preview_crop.top, preview_crop.left + preview_crop.width, preview_crop.top + preview_crop.height); err = unlockBuffer(index); if(err != NO_ERROR) { LOGE("lockBuffer failed, err = %d \n", err); } err = mPreviewWindow->enqueue_buffer(mPreviewWindow, (buffer_handle_t *)mBufferHandle[index]); LOGV("now enqueue num:%d,min unenqueue num:%d",enqueue_buffer_num,min_undequeued_num); if(err != 0) { LOGE("enqueue_buffer failed, err = %d", err); } else { LOGV("enqueue_buffer hdl=%p", *mBufferHandle[index]); mBufferFlag[index] = BUFFER_NOT_OWNED; enqueue_buffer_num ++; } buffer_handle_t *buffer_handle = NULL; int stride = 0; if(enqueue_buffer_num > min_undequeued_num){ err = mPreviewWindow->dequeue_buffer(mPreviewWindow, &buffer_handle, &stride); if (err == NO_ERROR && buffer_handle != NULL) { enqueue_buffer_num --; int i; LOGV("dequed buf hdl =%p", *buffer_handle); for(i = 0; i < NB_BUFFER; i++) { if(mBufferHandle[i] == buffer_handle) { LOGV("Found buffer in idx:%d", i); mBufferFlag[i] = BUFFER_OWNED; dequeuedIdx = i; break; } } } err = lockBuffer(dequeuedIdx); if(err != NO_ERROR) { LOGE("Oh,lockBuffer failed, err = %d,maybe buffer queue has been abandon.But we do not care.Right?\n", err); dequeuedIdx = -1; } } return dequeuedIdx; } bool PreviewWindow::onNextFrameAvailable(const void* frame) { int res; Mutex::Autolock locker(&mObjectLock); V4L2BUF_t * pv4l2_buf = (V4L2BUF_t *)frame; int preview_format = 0; unsigned long preview_addr_phy = NULL; unsigned long preview_addr_vir = NULL; int preview_width = 0; int preview_height = 0; RECT_t preview_crop; if (!isPreviewEnabled() || mPreviewWindow == NULL) { return true; } if ((pv4l2_buf->isThumbAvailable == 1) && (pv4l2_buf->thumbUsedForPreview == 1)) { preview_format = pv4l2_buf->thumbFormat; preview_addr_phy = pv4l2_buf->thumbAddrPhyY; preview_addr_vir = pv4l2_buf->thumbAddrVirY; preview_width = pv4l2_buf->thumbWidth; preview_height= pv4l2_buf->thumbHeight; memcpy((void*)&preview_crop, (void*)&pv4l2_buf->thumb_crop_rect, sizeof(RECT_t)); } else { preview_format = pv4l2_buf->format; preview_addr_phy = pv4l2_buf->addrPhyY; preview_addr_vir = pv4l2_buf->addrVirY; preview_width = pv4l2_buf->width; preview_height= pv4l2_buf->height; memcpy((void*)&preview_crop, (void*)&pv4l2_buf->crop_rect, sizeof(RECT_t)); } /* Make sure that preview window dimensions are OK with the camera device */ if (adjustPreviewDimensions(pv4l2_buf) || mShouldAdjustDimensions) { LOGD("%s: Adjusting preview windows %p geometry to %dx%d", __FUNCTION__, mPreviewWindow, mPreviewFrameWidth, mPreviewFrameHeight); int format = V4L2_PIX_FMT_NV21; switch (preview_format) { case V4L2_PIX_FMT_NV21: LOGV("preview format: HAL_PIXEL_FORMAT_YCrCb_420_SP"); format = HAL_PIXEL_FORMAT_YCrCb_420_SP; break; case V4L2_PIX_FMT_NV12: LOGV("preview format: V4L2_PIX_FMT_NV12"); format = 0x101; // NV12 break; case V4L2_PIX_FMT_YVU420: case V4L2_PIX_FMT_YUV420: // to do LOGV("preview format: HAL_PIXEL_FORMAT_YV12"); format = HAL_PIXEL_FORMAT_YV12; break; case V4L2_PIX_FMT_YUYV: LOGV("preview format: HAL_PIXEL_FORMAT_YCbCr_422_I"); format = HAL_PIXEL_FORMAT_YCbCr_422_I; break; default: LOGE("preview unknown pixel format: %08x", preview_format); return false; } res = mPreviewWindow->set_buffers_geometry(mPreviewWindow, mPreviewFrameWidth, mPreviewFrameHeight, format); if (res != NO_ERROR) { LOGE("%s: Error in set_buffers_geometry %d -> %s", __FUNCTION__, -res, strerror(-res)); return false; } mShouldAdjustDimensions = false; res = mPreviewWindow->set_buffer_count(mPreviewWindow, 3); if (res != 0) { LOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-res), -res); if ( ENODEV == res ) { LOGE("Preview surface abandoned!"); mPreviewWindow = NULL; } return false; } } /* * Push new frame to the preview window. */ DBG_TIME_AVG_AREA_IN(TAG_DQBUF); /* Dequeue preview window buffer for the frame. */ buffer_handle_t* buffer = NULL; int stride = 0; res = mPreviewWindow->dequeue_buffer(mPreviewWindow, &buffer, &stride); if (res != NO_ERROR || buffer == NULL) { LOGE("%s: Unable to dequeue preview window buffer: %d -> %s", __FUNCTION__, -res, strerror(-res)); int undequeued = 0; mPreviewWindow->get_min_undequeued_buffer_count(mPreviewWindow, &undequeued); LOGW("now undequeued: %d", undequeued); return false; } DBG_TIME_AVG_AREA_OUT(TAG_DQBUF); DBG_TIME_AVG_AREA_IN(TAG_LKBUF); /* Let the preview window to lock the buffer. */ res = mPreviewWindow->lock_buffer(mPreviewWindow, buffer); if (res != NO_ERROR) { LOGE("%s: Unable to lock preview window buffer: %d -> %s", __FUNCTION__, -res, strerror(-res)); mPreviewWindow->cancel_buffer(mPreviewWindow, buffer); return false; } DBG_TIME_AVG_AREA_OUT(TAG_LKBUF); DBG_TIME_AVG_AREA_IN(TAG_MAPPER); /* Now let the graphics framework to lock the buffer, and provide * us with the framebuffer data address. */ void* img = NULL; const Rect rect(mPreviewFrameWidth, mPreviewFrameHeight); GraphicBufferMapper& grbuffer_mapper(GraphicBufferMapper::get()); res = grbuffer_mapper.lock(*buffer, GRALLOC_USAGE_SW_WRITE_OFTEN, rect, &img); if (res != NO_ERROR) { LOGE("%s: grbuffer_mapper.lock failure: %d -> %s", __FUNCTION__, res, strerror(res)); mPreviewWindow->cancel_buffer(mPreviewWindow, buffer); return false; } DBG_TIME_AVG_AREA_OUT(TAG_MAPPER); mPreviewWindow->set_crop(mPreviewWindow, preview_crop.left, preview_crop.top, preview_crop.left + preview_crop.width, preview_crop.top + preview_crop.height); DBG_TIME_AVG_AREA_IN(TAG_CPY); //camera_phy_flush_cache((void*)preview_addr_vir, mPreviewFrameSize); if (preview_format == V4L2_PIX_FMT_NV21 || preview_format == V4L2_PIX_FMT_NV12) { char * src = (char *)preview_addr_vir; char * dst = (char *)img; if (stride == ALIGN_16B(preview_width)) { // y memcpy(dst, src, ALIGN_16B(preview_width) * preview_height); // uv src = (char *)preview_addr_vir + ALIGN_16B(preview_width) * preview_height; dst = (char *)img + GPU_BUFFER_ALIGN(ALIGN_16B(preview_width)*preview_height); memcpy(dst, src, ALIGN_16B(preview_width) * preview_height >> 1); //camera_phy_flush_cache((void*)dst, GPU_BUFFER_ALIGN(ALIGN_16B(preview_width)*preview_height) + \ // ALIGN_16B(preview_width) * preview_height >> 1); } else if (stride == ALIGN_32B(preview_width)) { // y for (int h = 0; h < preview_height; h++) { memcpy(dst, src, preview_width); src += ALIGN_16B(preview_width); dst += ALIGN_32B(preview_width); } // uv dst = (char *)img + GPU_BUFFER_ALIGN(ALIGN_32B(preview_width)*preview_height); for (int h = 0; h < preview_height/2; h++) { memcpy(dst, src, preview_width); src += ALIGN_16B(preview_width); dst += ALIGN_32B(preview_width); } } } else if(preview_format == V4L2_PIX_FMT_YUV420) { // YU12 to YV12 char * src = (char *)preview_addr_vir; char * dst = (char *)img; if (stride == ALIGN_16B(preview_width)) { // y memcpy(dst, src, ALIGN_16B(preview_width)*preview_height); // v src = (char *)preview_addr_vir + ALIGN_16B(preview_width) * preview_height + ALIGN_16B(ALIGN_16B(preview_width)/2)*preview_height/2; dst = (char *)img + ALIGN_16B(preview_width)*preview_height; for (int h = 0; h < preview_height/2; h++) { memcpy(dst, src, preview_width/2); src += ALIGN_16B(preview_width/2); dst += ALIGN_8B(preview_width/2); } // u src = (char *)preview_addr_vir + ALIGN_16B(preview_width) * preview_height; for (int h = 0; h < preview_height/2; h++) { memcpy(dst, src, preview_width/2); src += ALIGN_16B(preview_width/2); dst += ALIGN_8B(preview_width/2); } } else if (stride == ALIGN_32B(preview_width)) { // y for (int h = 0; h < preview_height; h++) { memcpy(dst, src, preview_width); src += ALIGN_16B(preview_width); dst += ALIGN_32B(preview_width); } // v src = (char *)preview_addr_vir + ALIGN_16B(preview_width)*preview_height + ALIGN_16B(ALIGN_16B(preview_width)/2)*preview_height/2; dst = (char *)img + ALIGN_32B(preview_width)*preview_height; memcpy(dst, src, ALIGN_16B(preview_width/2)*preview_height >> 1); // u src = (char *)preview_addr_vir + ALIGN_16B(preview_width)*preview_height; dst = (char *)img + ALIGN_32B(preview_width)*preview_height + (ALIGN_16B(preview_width/2)*preview_height >> 1); memcpy(dst, src, ALIGN_16B(preview_width/2)*preview_height >> 1); } } else if(preview_format == V4L2_PIX_FMT_YVU420) { // YV12 char * src = (char *)preview_addr_vir; char * dst = (char *)img; if (stride == ALIGN_32B(preview_width)) { // y for (int h = 0; h < preview_height; h++) { memcpy(dst, src, preview_width); src += ALIGN_16B(preview_width); dst += ALIGN_32B(preview_width); } // u & v memcpy(dst, src, ALIGN_16B(preview_width/2)*preview_height); } else if (stride == ALIGN_16B(preview_width)) { // y memcpy(dst, src, ALIGN_16B(preview_width)*preview_height); src = (char *)preview_addr_vir + ALIGN_16B(preview_width) * preview_height; dst = (char *)img + ALIGN_16B(preview_width)*preview_height; // u for (int h = 0; h < preview_height/2; h++) { memcpy(dst, src, preview_width/2); src += ALIGN_16B(preview_width/2); dst += ALIGN_8B(preview_width/2); } // v for (int h = 0; h < preview_height/2; h++) { memcpy(dst, src, preview_width/2); src += ALIGN_16B(preview_width/2); dst += ALIGN_8B(preview_width/2); } } } else { LOGE("unknown preview format"); } DBG_TIME_AVG_AREA_OUT(TAG_CPY); DBG_TIME_AVG_AREA_IN(TAG_EQBUF); //mPreviewWindow->set_timestamp(mPreviewWindow, pv4l2_buf->timeStamp); mPreviewWindow->enqueue_buffer(mPreviewWindow, buffer); DBG_TIME_AVG_AREA_OUT(TAG_EQBUF); DBG_TIME_AVG_AREA_IN(TAG_UNLKBUF); grbuffer_mapper.unlock(*buffer); DBG_TIME_AVG_AREA_OUT(TAG_UNLKBUF); return true; } /*************************************************************************** * Private API **************************************************************************/ bool PreviewWindow::adjustPreviewDimensions(V4L2BUF_t* pbuf) { /* Match the cached frame dimensions against the actual ones. */ if ((pbuf->isThumbAvailable == 1) && (pbuf->thumbUsedForPreview == 1)) // use thumb frame for preview { if ((mPreviewFrameWidth == pbuf->thumbWidth) && (mPreviewFrameHeight == pbuf->thumbHeight) && (mCurPixelFormat == pbuf->thumbFormat)) { /* They match. */ return false; } LOGV("cru: [%d, %d], get: [%d, %d]", mPreviewFrameWidth, mPreviewFrameHeight, pbuf->thumbWidth, pbuf->thumbHeight); /* They don't match: adjust the cache. */ mPreviewFrameWidth = pbuf->thumbWidth; mPreviewFrameHeight = pbuf->thumbHeight; mCurPixelFormat = pbuf->thumbFormat; mPreviewFrameSize = calculateFrameSize(pbuf->thumbWidth, pbuf->thumbHeight, pbuf->thumbFormat); } else { if ((mPreviewFrameWidth == pbuf->width) && (mPreviewFrameHeight == pbuf->height) && (mCurPixelFormat == pbuf->format)) { /* They match. */ return false; } LOGV("cru: [%d, %d], get: [%d, %d]", mPreviewFrameWidth, mPreviewFrameHeight, pbuf->width, pbuf->height); /* They don't match: adjust the cache. */ mPreviewFrameWidth = pbuf->width; mPreviewFrameHeight = pbuf->height; mCurPixelFormat = pbuf->format; mPreviewFrameSize = calculateFrameSize(pbuf->width, pbuf->height, pbuf->format); } mShouldAdjustDimensions = false; return true; } }; /* namespace android */