18a94683196406b83b14218d1beef66067f126a16keunyoung/*
28a94683196406b83b14218d1beef66067f126a16keunyoung * Copyright (C) 2011 The Android Open Source Project
38a94683196406b83b14218d1beef66067f126a16keunyoung *
48a94683196406b83b14218d1beef66067f126a16keunyoung * Licensed under the Apache License, Version 2.0 (the "License");
58a94683196406b83b14218d1beef66067f126a16keunyoung * you may not use this file except in compliance with the License.
68a94683196406b83b14218d1beef66067f126a16keunyoung * You may obtain a copy of the License at
78a94683196406b83b14218d1beef66067f126a16keunyoung *
88a94683196406b83b14218d1beef66067f126a16keunyoung *      http://www.apache.org/licenses/LICENSE-2.0
98a94683196406b83b14218d1beef66067f126a16keunyoung *
108a94683196406b83b14218d1beef66067f126a16keunyoung * Unless required by applicable law or agreed to in writing, software
118a94683196406b83b14218d1beef66067f126a16keunyoung * distributed under the License is distributed on an "AS IS" BASIS,
128a94683196406b83b14218d1beef66067f126a16keunyoung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138a94683196406b83b14218d1beef66067f126a16keunyoung * See the License for the specific language governing permissions and
148a94683196406b83b14218d1beef66067f126a16keunyoung * limitations under the License.
158a94683196406b83b14218d1beef66067f126a16keunyoung */
168a94683196406b83b14218d1beef66067f126a16keunyoung
178a94683196406b83b14218d1beef66067f126a16keunyoung/*
188a94683196406b83b14218d1beef66067f126a16keunyoung * Contains implementation of a class EmulatedFakeCameraDevice that encapsulates
198a94683196406b83b14218d1beef66067f126a16keunyoung * fake camera device.
208a94683196406b83b14218d1beef66067f126a16keunyoung */
218a94683196406b83b14218d1beef66067f126a16keunyoung
228a94683196406b83b14218d1beef66067f126a16keunyoung#define LOG_NDEBUG 0
238a94683196406b83b14218d1beef66067f126a16keunyoung#define LOG_TAG "EmulatedCamera_FakeDevice"
248a94683196406b83b14218d1beef66067f126a16keunyoung#include <cutils/log.h>
258a94683196406b83b14218d1beef66067f126a16keunyoung#include "EmulatedFakeCamera.h"
268a94683196406b83b14218d1beef66067f126a16keunyoung#include "EmulatedFakeCameraDevice.h"
278a94683196406b83b14218d1beef66067f126a16keunyoung
288a94683196406b83b14218d1beef66067f126a16keunyoungnamespace android {
298a94683196406b83b14218d1beef66067f126a16keunyoung
308a94683196406b83b14218d1beef66067f126a16keunyoungEmulatedFakeCameraDevice::EmulatedFakeCameraDevice(EmulatedFakeCamera* camera_hal)
318a94683196406b83b14218d1beef66067f126a16keunyoung    : EmulatedCameraDevice(camera_hal),
328a94683196406b83b14218d1beef66067f126a16keunyoung      mBlackYUV(kBlack32),
338a94683196406b83b14218d1beef66067f126a16keunyoung      mWhiteYUV(kWhite32),
348a94683196406b83b14218d1beef66067f126a16keunyoung      mRedYUV(kRed8),
358a94683196406b83b14218d1beef66067f126a16keunyoung      mGreenYUV(kGreen8),
368a94683196406b83b14218d1beef66067f126a16keunyoung      mBlueYUV(kBlue8),
378a94683196406b83b14218d1beef66067f126a16keunyoung      mLastRedrawn(0),
388a94683196406b83b14218d1beef66067f126a16keunyoung      mCheckX(0),
398a94683196406b83b14218d1beef66067f126a16keunyoung      mCheckY(0),
408a94683196406b83b14218d1beef66067f126a16keunyoung      mCcounter(0)
418a94683196406b83b14218d1beef66067f126a16keunyoung#if EFCD_ROTATE_FRAME
428a94683196406b83b14218d1beef66067f126a16keunyoung      , mLastRotatedAt(0),
438a94683196406b83b14218d1beef66067f126a16keunyoung        mCurrentFrameType(0),
448a94683196406b83b14218d1beef66067f126a16keunyoung        mCurrentColor(&mWhiteYUV)
458a94683196406b83b14218d1beef66067f126a16keunyoung#endif  // EFCD_ROTATE_FRAME
468a94683196406b83b14218d1beef66067f126a16keunyoung{
478a94683196406b83b14218d1beef66067f126a16keunyoung    // Makes the image with the original exposure compensation darker.
488a94683196406b83b14218d1beef66067f126a16keunyoung    // So the effects of changing the exposure compensation can be seen.
498a94683196406b83b14218d1beef66067f126a16keunyoung    mBlackYUV.Y = mBlackYUV.Y / 2;
508a94683196406b83b14218d1beef66067f126a16keunyoung    mWhiteYUV.Y = mWhiteYUV.Y / 2;
518a94683196406b83b14218d1beef66067f126a16keunyoung    mRedYUV.Y = mRedYUV.Y / 2;
528a94683196406b83b14218d1beef66067f126a16keunyoung    mGreenYUV.Y = mGreenYUV.Y / 2;
538a94683196406b83b14218d1beef66067f126a16keunyoung    mBlueYUV.Y = mBlueYUV.Y / 2;
548a94683196406b83b14218d1beef66067f126a16keunyoung}
558a94683196406b83b14218d1beef66067f126a16keunyoung
568a94683196406b83b14218d1beef66067f126a16keunyoungEmulatedFakeCameraDevice::~EmulatedFakeCameraDevice()
578a94683196406b83b14218d1beef66067f126a16keunyoung{
588a94683196406b83b14218d1beef66067f126a16keunyoung}
598a94683196406b83b14218d1beef66067f126a16keunyoung
608a94683196406b83b14218d1beef66067f126a16keunyoung/****************************************************************************
618a94683196406b83b14218d1beef66067f126a16keunyoung * Emulated camera device abstract interface implementation.
628a94683196406b83b14218d1beef66067f126a16keunyoung ***************************************************************************/
638a94683196406b83b14218d1beef66067f126a16keunyoung
648a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedFakeCameraDevice::connectDevice()
658a94683196406b83b14218d1beef66067f126a16keunyoung{
668a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGV("%s", __FUNCTION__);
678a94683196406b83b14218d1beef66067f126a16keunyoung
688a94683196406b83b14218d1beef66067f126a16keunyoung    Mutex::Autolock locker(&mObjectLock);
698a94683196406b83b14218d1beef66067f126a16keunyoung    if (!isInitialized()) {
708a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGE("%s: Fake camera device is not initialized.", __FUNCTION__);
718a94683196406b83b14218d1beef66067f126a16keunyoung        return EINVAL;
728a94683196406b83b14218d1beef66067f126a16keunyoung    }
738a94683196406b83b14218d1beef66067f126a16keunyoung    if (isConnected()) {
748a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGW("%s: Fake camera device is already connected.", __FUNCTION__);
758a94683196406b83b14218d1beef66067f126a16keunyoung        return NO_ERROR;
768a94683196406b83b14218d1beef66067f126a16keunyoung    }
778a94683196406b83b14218d1beef66067f126a16keunyoung
788a94683196406b83b14218d1beef66067f126a16keunyoung    /* There is no device to connect to. */
798a94683196406b83b14218d1beef66067f126a16keunyoung    mState = ECDS_CONNECTED;
808a94683196406b83b14218d1beef66067f126a16keunyoung
818a94683196406b83b14218d1beef66067f126a16keunyoung    return NO_ERROR;
828a94683196406b83b14218d1beef66067f126a16keunyoung}
838a94683196406b83b14218d1beef66067f126a16keunyoung
848a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedFakeCameraDevice::disconnectDevice()
858a94683196406b83b14218d1beef66067f126a16keunyoung{
868a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGV("%s", __FUNCTION__);
878a94683196406b83b14218d1beef66067f126a16keunyoung
888a94683196406b83b14218d1beef66067f126a16keunyoung    Mutex::Autolock locker(&mObjectLock);
898a94683196406b83b14218d1beef66067f126a16keunyoung    if (!isConnected()) {
908a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGW("%s: Fake camera device is already disconnected.", __FUNCTION__);
918a94683196406b83b14218d1beef66067f126a16keunyoung        return NO_ERROR;
928a94683196406b83b14218d1beef66067f126a16keunyoung    }
938a94683196406b83b14218d1beef66067f126a16keunyoung    if (isStarted()) {
948a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGE("%s: Cannot disconnect from the started device.", __FUNCTION__);
958a94683196406b83b14218d1beef66067f126a16keunyoung        return EINVAL;
968a94683196406b83b14218d1beef66067f126a16keunyoung    }
978a94683196406b83b14218d1beef66067f126a16keunyoung
988a94683196406b83b14218d1beef66067f126a16keunyoung    /* There is no device to disconnect from. */
998a94683196406b83b14218d1beef66067f126a16keunyoung    mState = ECDS_INITIALIZED;
1008a94683196406b83b14218d1beef66067f126a16keunyoung
1018a94683196406b83b14218d1beef66067f126a16keunyoung    return NO_ERROR;
1028a94683196406b83b14218d1beef66067f126a16keunyoung}
1038a94683196406b83b14218d1beef66067f126a16keunyoung
1048a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedFakeCameraDevice::startDevice(int width,
1058a94683196406b83b14218d1beef66067f126a16keunyoung                                               int height,
1068a94683196406b83b14218d1beef66067f126a16keunyoung                                               uint32_t pix_fmt)
1078a94683196406b83b14218d1beef66067f126a16keunyoung{
1088a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGV("%s", __FUNCTION__);
1098a94683196406b83b14218d1beef66067f126a16keunyoung
1108a94683196406b83b14218d1beef66067f126a16keunyoung    Mutex::Autolock locker(&mObjectLock);
1118a94683196406b83b14218d1beef66067f126a16keunyoung    if (!isConnected()) {
1128a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGE("%s: Fake camera device is not connected.", __FUNCTION__);
1138a94683196406b83b14218d1beef66067f126a16keunyoung        return EINVAL;
1148a94683196406b83b14218d1beef66067f126a16keunyoung    }
1158a94683196406b83b14218d1beef66067f126a16keunyoung    if (isStarted()) {
1168a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGE("%s: Fake camera device is already started.", __FUNCTION__);
1178a94683196406b83b14218d1beef66067f126a16keunyoung        return EINVAL;
1188a94683196406b83b14218d1beef66067f126a16keunyoung    }
1198a94683196406b83b14218d1beef66067f126a16keunyoung
1208a94683196406b83b14218d1beef66067f126a16keunyoung    /* Initialize the base class. */
1218a94683196406b83b14218d1beef66067f126a16keunyoung    const status_t res =
1228a94683196406b83b14218d1beef66067f126a16keunyoung        EmulatedCameraDevice::commonStartDevice(width, height, pix_fmt);
1238a94683196406b83b14218d1beef66067f126a16keunyoung    if (res == NO_ERROR) {
1248a94683196406b83b14218d1beef66067f126a16keunyoung        /* Calculate U/V panes inside the framebuffer. */
1258a94683196406b83b14218d1beef66067f126a16keunyoung        switch (mPixelFormat) {
1268a94683196406b83b14218d1beef66067f126a16keunyoung            case V4L2_PIX_FMT_YVU420:
1278a94683196406b83b14218d1beef66067f126a16keunyoung                mFrameV = mCurrentFrame + mTotalPixels;
1288a94683196406b83b14218d1beef66067f126a16keunyoung                mFrameU = mFrameU + mTotalPixels / 4;
1298a94683196406b83b14218d1beef66067f126a16keunyoung                mUVStep = 1;
1308a94683196406b83b14218d1beef66067f126a16keunyoung                mUVTotalNum = mTotalPixels / 4;
1318a94683196406b83b14218d1beef66067f126a16keunyoung                break;
1328a94683196406b83b14218d1beef66067f126a16keunyoung
1338a94683196406b83b14218d1beef66067f126a16keunyoung            case V4L2_PIX_FMT_YUV420:
1348a94683196406b83b14218d1beef66067f126a16keunyoung                mFrameU = mCurrentFrame + mTotalPixels;
1358a94683196406b83b14218d1beef66067f126a16keunyoung                mFrameV = mFrameU + mTotalPixels / 4;
1368a94683196406b83b14218d1beef66067f126a16keunyoung                mUVStep = 1;
1378a94683196406b83b14218d1beef66067f126a16keunyoung                mUVTotalNum = mTotalPixels / 4;
1388a94683196406b83b14218d1beef66067f126a16keunyoung                break;
1398a94683196406b83b14218d1beef66067f126a16keunyoung
1408a94683196406b83b14218d1beef66067f126a16keunyoung            case V4L2_PIX_FMT_NV21:
1418a94683196406b83b14218d1beef66067f126a16keunyoung                /* Interleaved UV pane, V first. */
1428a94683196406b83b14218d1beef66067f126a16keunyoung                mFrameV = mCurrentFrame + mTotalPixels;
1438a94683196406b83b14218d1beef66067f126a16keunyoung                mFrameU = mFrameV + 1;
1448a94683196406b83b14218d1beef66067f126a16keunyoung                mUVStep = 2;
1458a94683196406b83b14218d1beef66067f126a16keunyoung                mUVTotalNum = mTotalPixels / 4;
1468a94683196406b83b14218d1beef66067f126a16keunyoung                break;
1478a94683196406b83b14218d1beef66067f126a16keunyoung
1488a94683196406b83b14218d1beef66067f126a16keunyoung            case V4L2_PIX_FMT_NV12:
1498a94683196406b83b14218d1beef66067f126a16keunyoung                /* Interleaved UV pane, U first. */
1508a94683196406b83b14218d1beef66067f126a16keunyoung                mFrameU = mCurrentFrame + mTotalPixels;
1518a94683196406b83b14218d1beef66067f126a16keunyoung                mFrameV = mFrameU + 1;
1528a94683196406b83b14218d1beef66067f126a16keunyoung                mUVStep = 2;
1538a94683196406b83b14218d1beef66067f126a16keunyoung                mUVTotalNum = mTotalPixels / 4;
1548a94683196406b83b14218d1beef66067f126a16keunyoung                break;
1558a94683196406b83b14218d1beef66067f126a16keunyoung
1568a94683196406b83b14218d1beef66067f126a16keunyoung            default:
1578a94683196406b83b14218d1beef66067f126a16keunyoung                ALOGE("%s: Unknown pixel format %.4s", __FUNCTION__,
1588a94683196406b83b14218d1beef66067f126a16keunyoung                     reinterpret_cast<const char*>(&mPixelFormat));
1598a94683196406b83b14218d1beef66067f126a16keunyoung                return EINVAL;
1608a94683196406b83b14218d1beef66067f126a16keunyoung        }
1618a94683196406b83b14218d1beef66067f126a16keunyoung        /* Number of items in a single row inside U/V panes. */
1628a94683196406b83b14218d1beef66067f126a16keunyoung        mUVInRow = (width / 2) * mUVStep;
1638a94683196406b83b14218d1beef66067f126a16keunyoung        mState = ECDS_STARTED;
1648a94683196406b83b14218d1beef66067f126a16keunyoung    } else {
1658a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGE("%s: commonStartDevice failed", __FUNCTION__);
1668a94683196406b83b14218d1beef66067f126a16keunyoung    }
1678a94683196406b83b14218d1beef66067f126a16keunyoung
1688a94683196406b83b14218d1beef66067f126a16keunyoung    return res;
1698a94683196406b83b14218d1beef66067f126a16keunyoung}
1708a94683196406b83b14218d1beef66067f126a16keunyoung
1718a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedFakeCameraDevice::stopDevice()
1728a94683196406b83b14218d1beef66067f126a16keunyoung{
1738a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGV("%s", __FUNCTION__);
1748a94683196406b83b14218d1beef66067f126a16keunyoung
1758a94683196406b83b14218d1beef66067f126a16keunyoung    Mutex::Autolock locker(&mObjectLock);
1768a94683196406b83b14218d1beef66067f126a16keunyoung    if (!isStarted()) {
1778a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGW("%s: Fake camera device is not started.", __FUNCTION__);
1788a94683196406b83b14218d1beef66067f126a16keunyoung        return NO_ERROR;
1798a94683196406b83b14218d1beef66067f126a16keunyoung    }
1808a94683196406b83b14218d1beef66067f126a16keunyoung
1818a94683196406b83b14218d1beef66067f126a16keunyoung    mFrameU = mFrameV = NULL;
1828a94683196406b83b14218d1beef66067f126a16keunyoung    EmulatedCameraDevice::commonStopDevice();
1838a94683196406b83b14218d1beef66067f126a16keunyoung    mState = ECDS_CONNECTED;
1848a94683196406b83b14218d1beef66067f126a16keunyoung
1858a94683196406b83b14218d1beef66067f126a16keunyoung    return NO_ERROR;
1868a94683196406b83b14218d1beef66067f126a16keunyoung}
1878a94683196406b83b14218d1beef66067f126a16keunyoung
1888a94683196406b83b14218d1beef66067f126a16keunyoung/****************************************************************************
1898a94683196406b83b14218d1beef66067f126a16keunyoung * Worker thread management overrides.
1908a94683196406b83b14218d1beef66067f126a16keunyoung ***************************************************************************/
1918a94683196406b83b14218d1beef66067f126a16keunyoung
1928a94683196406b83b14218d1beef66067f126a16keunyoungbool EmulatedFakeCameraDevice::inWorkerThread()
1938a94683196406b83b14218d1beef66067f126a16keunyoung{
1948a94683196406b83b14218d1beef66067f126a16keunyoung    /* Wait till FPS timeout expires, or thread exit message is received. */
1958a94683196406b83b14218d1beef66067f126a16keunyoung    WorkerThread::SelectRes res =
1968a94683196406b83b14218d1beef66067f126a16keunyoung        getWorkerThread()->Select(-1, 1000000 / mEmulatedFPS);
1978a94683196406b83b14218d1beef66067f126a16keunyoung    if (res == WorkerThread::EXIT_THREAD) {
1988a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGV("%s: Worker thread has been terminated.", __FUNCTION__);
1998a94683196406b83b14218d1beef66067f126a16keunyoung        return false;
2008a94683196406b83b14218d1beef66067f126a16keunyoung    }
2018a94683196406b83b14218d1beef66067f126a16keunyoung
2028a94683196406b83b14218d1beef66067f126a16keunyoung    /* Lets see if we need to generate a new frame. */
2038a94683196406b83b14218d1beef66067f126a16keunyoung    if ((systemTime(SYSTEM_TIME_MONOTONIC) - mLastRedrawn) >= mRedrawAfter) {
2048a94683196406b83b14218d1beef66067f126a16keunyoung        /*
2058a94683196406b83b14218d1beef66067f126a16keunyoung         * Time to generate a new frame.
2068a94683196406b83b14218d1beef66067f126a16keunyoung         */
2078a94683196406b83b14218d1beef66067f126a16keunyoung
2088a94683196406b83b14218d1beef66067f126a16keunyoung#if EFCD_ROTATE_FRAME
2098a94683196406b83b14218d1beef66067f126a16keunyoung        const int frame_type = rotateFrame();
2108a94683196406b83b14218d1beef66067f126a16keunyoung        switch (frame_type) {
2118a94683196406b83b14218d1beef66067f126a16keunyoung            case 0:
2128a94683196406b83b14218d1beef66067f126a16keunyoung                drawCheckerboard();
2138a94683196406b83b14218d1beef66067f126a16keunyoung                break;
2148a94683196406b83b14218d1beef66067f126a16keunyoung            case 1:
2158a94683196406b83b14218d1beef66067f126a16keunyoung                drawStripes();
2168a94683196406b83b14218d1beef66067f126a16keunyoung                break;
2178a94683196406b83b14218d1beef66067f126a16keunyoung            case 2:
2188a94683196406b83b14218d1beef66067f126a16keunyoung                drawSolid(mCurrentColor);
2198a94683196406b83b14218d1beef66067f126a16keunyoung                break;
2208a94683196406b83b14218d1beef66067f126a16keunyoung        }
2218a94683196406b83b14218d1beef66067f126a16keunyoung#else
2228a94683196406b83b14218d1beef66067f126a16keunyoung        /* Draw the checker board. */
2238a94683196406b83b14218d1beef66067f126a16keunyoung        drawCheckerboard();
2248a94683196406b83b14218d1beef66067f126a16keunyoung
2258a94683196406b83b14218d1beef66067f126a16keunyoung#endif  // EFCD_ROTATE_FRAME
2268a94683196406b83b14218d1beef66067f126a16keunyoung
2278a94683196406b83b14218d1beef66067f126a16keunyoung        mLastRedrawn = systemTime(SYSTEM_TIME_MONOTONIC);
2288a94683196406b83b14218d1beef66067f126a16keunyoung    }
2298a94683196406b83b14218d1beef66067f126a16keunyoung
2308a94683196406b83b14218d1beef66067f126a16keunyoung    /* Timestamp the current frame, and notify the camera HAL about new frame. */
2318a94683196406b83b14218d1beef66067f126a16keunyoung    mCurFrameTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
2328a94683196406b83b14218d1beef66067f126a16keunyoung    mCameraHAL->onNextFrameAvailable(mCurrentFrame, mCurFrameTimestamp, this);
2338a94683196406b83b14218d1beef66067f126a16keunyoung
2348a94683196406b83b14218d1beef66067f126a16keunyoung    return true;
2358a94683196406b83b14218d1beef66067f126a16keunyoung}
2368a94683196406b83b14218d1beef66067f126a16keunyoung
2378a94683196406b83b14218d1beef66067f126a16keunyoung/****************************************************************************
2388a94683196406b83b14218d1beef66067f126a16keunyoung * Fake camera device private API
2398a94683196406b83b14218d1beef66067f126a16keunyoung ***************************************************************************/
2408a94683196406b83b14218d1beef66067f126a16keunyoung
2418a94683196406b83b14218d1beef66067f126a16keunyoungvoid EmulatedFakeCameraDevice::drawCheckerboard()
2428a94683196406b83b14218d1beef66067f126a16keunyoung{
2438a94683196406b83b14218d1beef66067f126a16keunyoung    const int size = mFrameWidth / 10;
2448a94683196406b83b14218d1beef66067f126a16keunyoung    bool black = true;
2458a94683196406b83b14218d1beef66067f126a16keunyoung
246b0b6afb44269263afa080ecc643f2c4866adfb38Douglas Leung    if (size == 0) {
247b0b6afb44269263afa080ecc643f2c4866adfb38Douglas Leung        // When this happens, it happens at a very high rate,
248b0b6afb44269263afa080ecc643f2c4866adfb38Douglas Leung        //     so don't log any messages and just return.
249b0b6afb44269263afa080ecc643f2c4866adfb38Douglas Leung        return;
250b0b6afb44269263afa080ecc643f2c4866adfb38Douglas Leung    }
251b0b6afb44269263afa080ecc643f2c4866adfb38Douglas Leung
252b0b6afb44269263afa080ecc643f2c4866adfb38Douglas Leung
2538a94683196406b83b14218d1beef66067f126a16keunyoung    if((mCheckX / size) & 1)
2548a94683196406b83b14218d1beef66067f126a16keunyoung        black = false;
2558a94683196406b83b14218d1beef66067f126a16keunyoung    if((mCheckY / size) & 1)
2568a94683196406b83b14218d1beef66067f126a16keunyoung        black = !black;
2578a94683196406b83b14218d1beef66067f126a16keunyoung
2588a94683196406b83b14218d1beef66067f126a16keunyoung    int county = mCheckY % size;
2598a94683196406b83b14218d1beef66067f126a16keunyoung    int checkxremainder = mCheckX % size;
2608a94683196406b83b14218d1beef66067f126a16keunyoung    uint8_t* Y = mCurrentFrame;
2618a94683196406b83b14218d1beef66067f126a16keunyoung    uint8_t* U_pos = mFrameU;
2628a94683196406b83b14218d1beef66067f126a16keunyoung    uint8_t* V_pos = mFrameV;
2638a94683196406b83b14218d1beef66067f126a16keunyoung    uint8_t* U = U_pos;
2648a94683196406b83b14218d1beef66067f126a16keunyoung    uint8_t* V = V_pos;
2658a94683196406b83b14218d1beef66067f126a16keunyoung
2668a94683196406b83b14218d1beef66067f126a16keunyoung    YUVPixel adjustedWhite = YUVPixel(mWhiteYUV);
2678a94683196406b83b14218d1beef66067f126a16keunyoung    changeWhiteBalance(adjustedWhite.Y, adjustedWhite.U, adjustedWhite.V);
2688a94683196406b83b14218d1beef66067f126a16keunyoung
2698a94683196406b83b14218d1beef66067f126a16keunyoung    for(int y = 0; y < mFrameHeight; y++) {
2708a94683196406b83b14218d1beef66067f126a16keunyoung        int countx = checkxremainder;
2718a94683196406b83b14218d1beef66067f126a16keunyoung        bool current = black;
2728a94683196406b83b14218d1beef66067f126a16keunyoung        for(int x = 0; x < mFrameWidth; x += 2) {
2738a94683196406b83b14218d1beef66067f126a16keunyoung            if (current) {
2748a94683196406b83b14218d1beef66067f126a16keunyoung                mBlackYUV.get(Y, U, V);
2758a94683196406b83b14218d1beef66067f126a16keunyoung            } else {
2768a94683196406b83b14218d1beef66067f126a16keunyoung                adjustedWhite.get(Y, U, V);
2778a94683196406b83b14218d1beef66067f126a16keunyoung            }
2788a94683196406b83b14218d1beef66067f126a16keunyoung            *Y = changeExposure(*Y);
2798a94683196406b83b14218d1beef66067f126a16keunyoung            Y[1] = *Y;
2808a94683196406b83b14218d1beef66067f126a16keunyoung            Y += 2; U += mUVStep; V += mUVStep;
2818a94683196406b83b14218d1beef66067f126a16keunyoung            countx += 2;
2828a94683196406b83b14218d1beef66067f126a16keunyoung            if(countx >= size) {
2838a94683196406b83b14218d1beef66067f126a16keunyoung                countx = 0;
2848a94683196406b83b14218d1beef66067f126a16keunyoung                current = !current;
2858a94683196406b83b14218d1beef66067f126a16keunyoung            }
2868a94683196406b83b14218d1beef66067f126a16keunyoung        }
2878a94683196406b83b14218d1beef66067f126a16keunyoung        if (y & 0x1) {
2888a94683196406b83b14218d1beef66067f126a16keunyoung            U_pos = U;
2898a94683196406b83b14218d1beef66067f126a16keunyoung            V_pos = V;
2908a94683196406b83b14218d1beef66067f126a16keunyoung        } else {
2918a94683196406b83b14218d1beef66067f126a16keunyoung            U = U_pos;
2928a94683196406b83b14218d1beef66067f126a16keunyoung            V = V_pos;
2938a94683196406b83b14218d1beef66067f126a16keunyoung        }
2948a94683196406b83b14218d1beef66067f126a16keunyoung        if(county++ >= size) {
2958a94683196406b83b14218d1beef66067f126a16keunyoung            county = 0;
2968a94683196406b83b14218d1beef66067f126a16keunyoung            black = !black;
2978a94683196406b83b14218d1beef66067f126a16keunyoung        }
2988a94683196406b83b14218d1beef66067f126a16keunyoung    }
2998a94683196406b83b14218d1beef66067f126a16keunyoung    mCheckX += 3;
3008a94683196406b83b14218d1beef66067f126a16keunyoung    mCheckY++;
3018a94683196406b83b14218d1beef66067f126a16keunyoung
3028a94683196406b83b14218d1beef66067f126a16keunyoung    /* Run the square. */
3038a94683196406b83b14218d1beef66067f126a16keunyoung    int sqx = ((mCcounter * 3) & 255);
3048a94683196406b83b14218d1beef66067f126a16keunyoung    if(sqx > 128) sqx = 255 - sqx;
3058a94683196406b83b14218d1beef66067f126a16keunyoung    int sqy = ((mCcounter * 5) & 255);
3068a94683196406b83b14218d1beef66067f126a16keunyoung    if(sqy > 128) sqy = 255 - sqy;
3078a94683196406b83b14218d1beef66067f126a16keunyoung    const int sqsize = mFrameWidth / 10;
3088a94683196406b83b14218d1beef66067f126a16keunyoung    drawSquare(sqx * sqsize / 32, sqy * sqsize / 32, (sqsize * 5) >> 1,
3098a94683196406b83b14218d1beef66067f126a16keunyoung               (mCcounter & 0x100) ? &mRedYUV : &mGreenYUV);
3108a94683196406b83b14218d1beef66067f126a16keunyoung    mCcounter++;
3118a94683196406b83b14218d1beef66067f126a16keunyoung}
3128a94683196406b83b14218d1beef66067f126a16keunyoung
3138a94683196406b83b14218d1beef66067f126a16keunyoungvoid EmulatedFakeCameraDevice::drawSquare(int x,
3148a94683196406b83b14218d1beef66067f126a16keunyoung                                          int y,
3158a94683196406b83b14218d1beef66067f126a16keunyoung                                          int size,
3168a94683196406b83b14218d1beef66067f126a16keunyoung                                          const YUVPixel* color)
3178a94683196406b83b14218d1beef66067f126a16keunyoung{
3188a94683196406b83b14218d1beef66067f126a16keunyoung    const int square_xstop = min(mFrameWidth, x + size);
3198a94683196406b83b14218d1beef66067f126a16keunyoung    const int square_ystop = min(mFrameHeight, y + size);
3208a94683196406b83b14218d1beef66067f126a16keunyoung    uint8_t* Y_pos = mCurrentFrame + y * mFrameWidth + x;
3218a94683196406b83b14218d1beef66067f126a16keunyoung
3228a94683196406b83b14218d1beef66067f126a16keunyoung    YUVPixel adjustedColor = *color;
3238a94683196406b83b14218d1beef66067f126a16keunyoung    changeWhiteBalance(adjustedColor.Y, adjustedColor.U, adjustedColor.V);
3248a94683196406b83b14218d1beef66067f126a16keunyoung
3258a94683196406b83b14218d1beef66067f126a16keunyoung    // Draw the square.
3268a94683196406b83b14218d1beef66067f126a16keunyoung    for (; y < square_ystop; y++) {
3278a94683196406b83b14218d1beef66067f126a16keunyoung        const int iUV = (y / 2) * mUVInRow + (x / 2) * mUVStep;
3288a94683196406b83b14218d1beef66067f126a16keunyoung        uint8_t* sqU = mFrameU + iUV;
3298a94683196406b83b14218d1beef66067f126a16keunyoung        uint8_t* sqV = mFrameV + iUV;
3308a94683196406b83b14218d1beef66067f126a16keunyoung        uint8_t* sqY = Y_pos;
3318a94683196406b83b14218d1beef66067f126a16keunyoung        for (int i = x; i < square_xstop; i += 2) {
3328a94683196406b83b14218d1beef66067f126a16keunyoung            adjustedColor.get(sqY, sqU, sqV);
3338a94683196406b83b14218d1beef66067f126a16keunyoung            *sqY = changeExposure(*sqY);
3348a94683196406b83b14218d1beef66067f126a16keunyoung            sqY[1] = *sqY;
3358a94683196406b83b14218d1beef66067f126a16keunyoung            sqY += 2; sqU += mUVStep; sqV += mUVStep;
3368a94683196406b83b14218d1beef66067f126a16keunyoung        }
3378a94683196406b83b14218d1beef66067f126a16keunyoung        Y_pos += mFrameWidth;
3388a94683196406b83b14218d1beef66067f126a16keunyoung    }
3398a94683196406b83b14218d1beef66067f126a16keunyoung}
3408a94683196406b83b14218d1beef66067f126a16keunyoung
3418a94683196406b83b14218d1beef66067f126a16keunyoung#if EFCD_ROTATE_FRAME
3428a94683196406b83b14218d1beef66067f126a16keunyoung
3438a94683196406b83b14218d1beef66067f126a16keunyoungvoid EmulatedFakeCameraDevice::drawSolid(YUVPixel* color)
3448a94683196406b83b14218d1beef66067f126a16keunyoung{
3458a94683196406b83b14218d1beef66067f126a16keunyoung    YUVPixel adjustedColor = *color;
3468a94683196406b83b14218d1beef66067f126a16keunyoung    changeWhiteBalance(adjustedColor.Y, adjustedColor.U, adjustedColor.V);
3478a94683196406b83b14218d1beef66067f126a16keunyoung
3488a94683196406b83b14218d1beef66067f126a16keunyoung    /* All Ys are the same. */
3498a94683196406b83b14218d1beef66067f126a16keunyoung    memset(mCurrentFrame, changeExposure(adjustedColor.Y), mTotalPixels);
3508a94683196406b83b14218d1beef66067f126a16keunyoung
3518a94683196406b83b14218d1beef66067f126a16keunyoung    /* Fill U, and V panes. */
3528a94683196406b83b14218d1beef66067f126a16keunyoung    uint8_t* U = mFrameU;
3538a94683196406b83b14218d1beef66067f126a16keunyoung    uint8_t* V = mFrameV;
3548a94683196406b83b14218d1beef66067f126a16keunyoung    for (int k = 0; k < mUVTotalNum; k++, U += mUVStep, V += mUVStep) {
3558a94683196406b83b14218d1beef66067f126a16keunyoung        *U = color->U;
3568a94683196406b83b14218d1beef66067f126a16keunyoung        *V = color->V;
3578a94683196406b83b14218d1beef66067f126a16keunyoung    }
3588a94683196406b83b14218d1beef66067f126a16keunyoung}
3598a94683196406b83b14218d1beef66067f126a16keunyoung
3608a94683196406b83b14218d1beef66067f126a16keunyoungvoid EmulatedFakeCameraDevice::drawStripes()
3618a94683196406b83b14218d1beef66067f126a16keunyoung{
3628a94683196406b83b14218d1beef66067f126a16keunyoung    /* Divide frame into 4 stripes. */
3638a94683196406b83b14218d1beef66067f126a16keunyoung    const int change_color_at = mFrameHeight / 4;
3648a94683196406b83b14218d1beef66067f126a16keunyoung    const int each_in_row = mUVInRow / mUVStep;
3658a94683196406b83b14218d1beef66067f126a16keunyoung    uint8_t* pY = mCurrentFrame;
3668a94683196406b83b14218d1beef66067f126a16keunyoung    for (int y = 0; y < mFrameHeight; y++, pY += mFrameWidth) {
3678a94683196406b83b14218d1beef66067f126a16keunyoung        /* Select the color. */
3688a94683196406b83b14218d1beef66067f126a16keunyoung        YUVPixel* color;
3698a94683196406b83b14218d1beef66067f126a16keunyoung        const int color_index = y / change_color_at;
3708a94683196406b83b14218d1beef66067f126a16keunyoung        if (color_index == 0) {
3718a94683196406b83b14218d1beef66067f126a16keunyoung            /* White stripe on top. */
3728a94683196406b83b14218d1beef66067f126a16keunyoung            color = &mWhiteYUV;
3738a94683196406b83b14218d1beef66067f126a16keunyoung        } else if (color_index == 1) {
3748a94683196406b83b14218d1beef66067f126a16keunyoung            /* Then the red stripe. */
3758a94683196406b83b14218d1beef66067f126a16keunyoung            color = &mRedYUV;
3768a94683196406b83b14218d1beef66067f126a16keunyoung        } else if (color_index == 2) {
3778a94683196406b83b14218d1beef66067f126a16keunyoung            /* Then the green stripe. */
3788a94683196406b83b14218d1beef66067f126a16keunyoung            color = &mGreenYUV;
3798a94683196406b83b14218d1beef66067f126a16keunyoung        } else {
3808a94683196406b83b14218d1beef66067f126a16keunyoung            /* And the blue stripe at the bottom. */
3818a94683196406b83b14218d1beef66067f126a16keunyoung            color = &mBlueYUV;
3828a94683196406b83b14218d1beef66067f126a16keunyoung        }
3838a94683196406b83b14218d1beef66067f126a16keunyoung        changeWhiteBalance(color->Y, color->U, color->V);
3848a94683196406b83b14218d1beef66067f126a16keunyoung
3858a94683196406b83b14218d1beef66067f126a16keunyoung        /* All Ys at the row are the same. */
3868a94683196406b83b14218d1beef66067f126a16keunyoung        memset(pY, changeExposure(color->Y), mFrameWidth);
3878a94683196406b83b14218d1beef66067f126a16keunyoung
3888a94683196406b83b14218d1beef66067f126a16keunyoung        /* Offset of the current row inside U/V panes. */
3898a94683196406b83b14218d1beef66067f126a16keunyoung        const int uv_off = (y / 2) * mUVInRow;
3908a94683196406b83b14218d1beef66067f126a16keunyoung        /* Fill U, and V panes. */
3918a94683196406b83b14218d1beef66067f126a16keunyoung        uint8_t* U = mFrameU + uv_off;
3928a94683196406b83b14218d1beef66067f126a16keunyoung        uint8_t* V = mFrameV + uv_off;
3938a94683196406b83b14218d1beef66067f126a16keunyoung        for (int k = 0; k < each_in_row; k++, U += mUVStep, V += mUVStep) {
3948a94683196406b83b14218d1beef66067f126a16keunyoung            *U = color->U;
3958a94683196406b83b14218d1beef66067f126a16keunyoung            *V = color->V;
3968a94683196406b83b14218d1beef66067f126a16keunyoung        }
3978a94683196406b83b14218d1beef66067f126a16keunyoung    }
3988a94683196406b83b14218d1beef66067f126a16keunyoung}
3998a94683196406b83b14218d1beef66067f126a16keunyoung
4008a94683196406b83b14218d1beef66067f126a16keunyoungint EmulatedFakeCameraDevice::rotateFrame()
4018a94683196406b83b14218d1beef66067f126a16keunyoung{
4028a94683196406b83b14218d1beef66067f126a16keunyoung    if ((systemTime(SYSTEM_TIME_MONOTONIC) - mLastRotatedAt) >= mRotateFreq) {
4038a94683196406b83b14218d1beef66067f126a16keunyoung        mLastRotatedAt = systemTime(SYSTEM_TIME_MONOTONIC);
4048a94683196406b83b14218d1beef66067f126a16keunyoung        mCurrentFrameType++;
4058a94683196406b83b14218d1beef66067f126a16keunyoung        if (mCurrentFrameType > 2) {
4068a94683196406b83b14218d1beef66067f126a16keunyoung            mCurrentFrameType = 0;
4078a94683196406b83b14218d1beef66067f126a16keunyoung        }
4088a94683196406b83b14218d1beef66067f126a16keunyoung        if (mCurrentFrameType == 2) {
4098a94683196406b83b14218d1beef66067f126a16keunyoung            ALOGD("********** Rotated to the SOLID COLOR frame **********");
4108a94683196406b83b14218d1beef66067f126a16keunyoung            /* Solid color: lets rotate color too. */
4118a94683196406b83b14218d1beef66067f126a16keunyoung            if (mCurrentColor == &mWhiteYUV) {
4128a94683196406b83b14218d1beef66067f126a16keunyoung                ALOGD("----- Painting a solid RED frame -----");
4138a94683196406b83b14218d1beef66067f126a16keunyoung                mCurrentColor = &mRedYUV;
4148a94683196406b83b14218d1beef66067f126a16keunyoung            } else if (mCurrentColor == &mRedYUV) {
4158a94683196406b83b14218d1beef66067f126a16keunyoung                ALOGD("----- Painting a solid GREEN frame -----");
4168a94683196406b83b14218d1beef66067f126a16keunyoung                mCurrentColor = &mGreenYUV;
4178a94683196406b83b14218d1beef66067f126a16keunyoung            } else if (mCurrentColor == &mGreenYUV) {
4188a94683196406b83b14218d1beef66067f126a16keunyoung                ALOGD("----- Painting a solid BLUE frame -----");
4198a94683196406b83b14218d1beef66067f126a16keunyoung                mCurrentColor = &mBlueYUV;
4208a94683196406b83b14218d1beef66067f126a16keunyoung            } else {
4218a94683196406b83b14218d1beef66067f126a16keunyoung                /* Back to white. */
4228a94683196406b83b14218d1beef66067f126a16keunyoung                ALOGD("----- Painting a solid WHITE frame -----");
4238a94683196406b83b14218d1beef66067f126a16keunyoung                mCurrentColor = &mWhiteYUV;
4248a94683196406b83b14218d1beef66067f126a16keunyoung            }
4258a94683196406b83b14218d1beef66067f126a16keunyoung        } else if (mCurrentFrameType == 0) {
4268a94683196406b83b14218d1beef66067f126a16keunyoung            ALOGD("********** Rotated to the CHECKERBOARD frame **********");
4278a94683196406b83b14218d1beef66067f126a16keunyoung        } else if (mCurrentFrameType == 1) {
4288a94683196406b83b14218d1beef66067f126a16keunyoung            ALOGD("********** Rotated to the STRIPED frame **********");
4298a94683196406b83b14218d1beef66067f126a16keunyoung        }
4308a94683196406b83b14218d1beef66067f126a16keunyoung    }
4318a94683196406b83b14218d1beef66067f126a16keunyoung
4328a94683196406b83b14218d1beef66067f126a16keunyoung    return mCurrentFrameType;
4338a94683196406b83b14218d1beef66067f126a16keunyoung}
4348a94683196406b83b14218d1beef66067f126a16keunyoung
4358a94683196406b83b14218d1beef66067f126a16keunyoung#endif  // EFCD_ROTATE_FRAME
4368a94683196406b83b14218d1beef66067f126a16keunyoung
4378a94683196406b83b14218d1beef66067f126a16keunyoung}; /* namespace android */
438