bool PreviewWindow::onNextFrameAvailableHW(const void* frame,
                                         nsecs_t timestamp,
                                         V4L2Camera* camera_dev)
{
    int res;
	V4L2BUF_t * pv4l2_buf = (V4L2BUF_t *)frame;
	
    Mutex::Autolock locker(&mObjectLock);

	if (!isPreviewEnabled() || mPreviewWindow == NULL) 
	{
        return true;
    }
	
    /* Make sure that preview window dimensions are OK with the camera device */
    if (adjustPreviewDimensions(camera_dev) || mShouldAdjustDimensions) 
	{
        ALOGD("%s: Adjusting preview windows %p geometry to %dx%d",
             __FUNCTION__, mPreviewWindow, mPreviewFrameWidth,
             mPreviewFrameHeight);
        res = mPreviewWindow->set_buffers_geometryex(mPreviewWindow,
                                                   mPreviewFrameWidth,
                                                   mPreviewFrameHeight,
                                                   HWC_FORMAT_DEFAULT,
                                                   mScreenID);
        if (res != NO_ERROR) {
            ALOGE("%s: Error in set_buffers_geometry %d -> %s",
                 __FUNCTION__, -res, strerror(-res));

			mShouldAdjustDimensions = true;
            return false;
        }

		mPreviewWindow->perform(mPreviewWindow, NATIVE_WINDOW_SETPARAMETER, HWC_LAYER_SETFORMAT, mLayerFormat);
		mShouldAdjustDimensions = false;

		mPreviewWindow->set_crop(mPreviewWindow, 
			mRectCrop.left, mRectCrop.top, mRectCrop.right, mRectCrop.bottom);

		mNewCrop = false;

		ALOGV("first hw: [%d, %d, %d, %d]", mRectCrop.left,
										mRectCrop.top,
										mRectCrop.right,
										mRectCrop.bottom);
    }

	libhwclayerpara_t overlay_para;

	overlay_para.bProgressiveSrc = 1;
	overlay_para.bTopFieldFirst = 1;
	overlay_para.pVideoInfo.frame_rate = 25000;

	overlay_para.top_y 		= (unsigned int)pv4l2_buf->addrPhyY;
	overlay_para.top_c 		= (unsigned int)pv4l2_buf->addrPhyY + mPreviewFrameWidth * mPreviewFrameHeight;
	overlay_para.bottom_y 	= 0;
	overlay_para.bottom_c 	= 0;
	overlay_para.number 	= 0;

	if (mOverlayFirstFrame)
	{
		ALOGV("first frame true");
		overlay_para.first_frame_flg = 1;
		mOverlayFirstFrame = false;
	}
	else
	{
		overlay_para.first_frame_flg = 0;
	}
	
	// ALOGV("addrY: %x, addrC: %x, WXH: %dx%d", overlay_para.top_y, overlay_para.top_c, mPreviewFrameWidth, mPreviewFrameHeight);

	if (mNewCrop)
	{
		mPreviewWindow->set_crop(mPreviewWindow, 
			mRectCrop.left, mRectCrop.top, mRectCrop.right, mRectCrop.bottom);

		mNewCrop = false;
	}

	res = mPreviewWindow->perform(mPreviewWindow, NATIVE_WINDOW_SETPARAMETER, HWC_LAYER_SETFRAMEPARA, (uint32_t)&overlay_para);
	if (res != OK)
	{
		ALOGE("NATIVE_WINDOW_SETPARAMETER failed");
		return false;
	}

	if (mLayerShowHW == 0)
	{
		showLayer(true);
	}

	return true;
}
bool PreviewWindow::onNextFrameAvailableSW(const void* frame,
                                         nsecs_t timestamp,
                                         V4L2Camera* camera_dev)
{
    int res;
    Mutex::Autolock locker(&mObjectLock);

	// ALOGD("%s, timestamp: %lld", __FUNCTION__, timestamp);

    if (!isPreviewEnabled() || mPreviewWindow == NULL) 
	{
        return true;
    }

    /* Make sure that preview window dimensions are OK with the camera device */
    if (adjustPreviewDimensions(camera_dev) || mShouldAdjustDimensions) {
        /* Need to set / adjust buffer geometry for the preview window.
         * Note that in the emulator preview window uses only RGB for pixel
         * formats. */
        ALOGD("%s: Adjusting preview windows %p geometry to %dx%d",
             __FUNCTION__, mPreviewWindow, mPreviewFrameWidth,
             mPreviewFrameHeight);
		
#if PREVIEW_FMT_RGBA32
		int format = HAL_PIXEL_FORMAT_RGBA_8888;
		ALOGV("preview format: HAL_PIXEL_FORMAT_RGBA_8888");
#else
		int format = HAL_PIXEL_FORMAT_YCrCb_420_SP;
		ALOGV("preview format: HAL_PIXEL_FORMAT_YCrCb_420_SP");
#endif
        res = mPreviewWindow->set_buffers_geometry(mPreviewWindow,
                                                   mPreviewFrameWidth,
                                                   mPreviewFrameHeight,
												   format);
        if (res != NO_ERROR) {
            ALOGE("%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) 
		{
	        ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-res), -res);

	        if ( ENODEV == res ) {
	            ALOGE("Preview surface abandoned!");
	            mPreviewWindow = NULL;
	        }

	        return false;
	    }

		mPreviewWindow->set_crop(mPreviewWindow, 
			mRectCrop.left, mRectCrop.top, mRectCrop.right, mRectCrop.bottom);

		mNewCrop = false;

		ALOGV("first sw: [%d, %d, %d, %d]", mRectCrop.left,
										mRectCrop.top,
										mRectCrop.right,
										mRectCrop.bottom);
    }

    /*
     * Push new frame to the preview window.
     */

    /* 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) {
        ALOGE("%s: Unable to dequeue preview window buffer: %d -> %s",
            __FUNCTION__, -res, strerror(-res));

		int undequeued = 0;
		mPreviewWindow->get_min_undequeued_buffer_count(mPreviewWindow, &undequeued);
		ALOGW("now undequeued: %d", undequeued);
		
        return false;
    }

    /* Let the preview window to lock the buffer. */
    res = mPreviewWindow->lock_buffer(mPreviewWindow, buffer);
    if (res != NO_ERROR) {
        ALOGE("%s: Unable to lock preview window buffer: %d -> %s",
             __FUNCTION__, -res, strerror(-res));
        mPreviewWindow->cancel_buffer(mPreviewWindow, buffer);
        return false;
    }

    /* 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) {
        ALOGE("%s: grbuffer_mapper.lock failure: %d -> %s",
             __FUNCTION__, res, strerror(res));
        mPreviewWindow->cancel_buffer(mPreviewWindow, buffer);
        return false;
    }

	if (mNewCrop)
	{
		mPreviewWindow->set_crop(mPreviewWindow, 
			mRectCrop.left, mRectCrop.top, mRectCrop.right, mRectCrop.bottom);

		mNewCrop = false;
	}

    /* Frames come in in YV12/NV12/NV21 format. Since preview window doesn't
     * supports those formats, we need to obtain the frame in RGB565. */
    res = camera_dev->getCurrentPreviewFrame(img);
    if (res == NO_ERROR) {
        /* Show it. */
        mPreviewWindow->enqueue_buffer(mPreviewWindow, buffer);
    } else {
        ALOGE("%s: Unable to obtain preview frame: %d", __FUNCTION__, res);
        mPreviewWindow->cancel_buffer(mPreviewWindow, buffer);
    }

    grbuffer_mapper.unlock(*buffer);

	return true;
}
bool PreviewWindow::onNextFrameAvailableSW(const void* frame,
										 int video_fmt,
                                         nsecs_t timestamp,
                                         V4L2Camera* camera_dev)
{
    int res;
    Mutex::Autolock locker(&mObjectLock);

	V4L2BUF_t * pv4l2_buf = (V4L2BUF_t *)frame;

	// LOGD("%s, timestamp: %lld", __FUNCTION__, timestamp);

    if (!isPreviewEnabled() || mPreviewWindow == NULL) 
	{
        return true;
    }

    /* Make sure that preview window dimensions are OK with the camera device */
    if (adjustPreviewDimensions(camera_dev) || mShouldAdjustDimensions) {
        /* Need to set / adjust buffer geometry for the preview window.
         * Note that in the emulator preview window uses only RGB for pixel
         * formats. */
        LOGD("%s: Adjusting preview windows %p geometry to %dx%d",
             __FUNCTION__, mPreviewWindow, mPreviewFrameWidth,
             mPreviewFrameHeight);
		
		int format = HAL_PIXEL_FORMAT_YCrCb_420_SP;
		LOGV("preview format: HAL_PIXEL_FORMAT_YCrCb_420_SP");

        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;
	    }

		mPreviewWindow->set_crop(mPreviewWindow, 
			mRectCrop.left, mRectCrop.top, mRectCrop.right, mRectCrop.bottom);

		mNewCrop = false;

		LOGV("first sw: [%d, %d, %d, %d]", mRectCrop.left,
										mRectCrop.top,
										mRectCrop.right,
										mRectCrop.bottom);
    }

    /*
     * Push new frame to the preview window.
     */

    /* 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;
    }

    /* 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;
    }

    /* 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;
    }

	if (mNewCrop)
	{
		mPreviewWindow->set_crop(mPreviewWindow, 
			mRectCrop.left, mRectCrop.top, mRectCrop.right, mRectCrop.bottom);

		mNewCrop = false;
	}

	if (pv4l2_buf->format == V4L2_PIX_FMT_NV21)
	{
		memcpy(img, (void*)pv4l2_buf->addrVirY, mPreviewFrameWidth * mPreviewFrameHeight * 3/2);
	}
	else
	{
		NV12ToNV21_shift((void*)pv4l2_buf->addrVirY, img, mPreviewFrameWidth, mPreviewFrameHeight);
	}
	mPreviewWindow->enqueue_buffer(mPreviewWindow, buffer);

    grbuffer_mapper.unlock(*buffer);

	return true;
}