allwinner_a64/android/hardware/aw/camera/PreviewWindow.cpp
2018-08-08 17:00:29 +08:00

782 lines
26 KiB
C++

#include "CameraDebug.h"
#if DBG_PREVIEW
#define LOG_NDEBUG 0
#endif
#define LOG_TAG "PreviewWindow"
#include <cutils/log.h>
#include <ui/Rect.h>
#include <ui/GraphicBufferMapper.h>
#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<const char*>(&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 */