EmulatedCameraDevice.cpp revision 3725c7c982eac52ec64a625e82f306822452941c
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 an abstract class EmulatedCameraDevice that defines
198a94683196406b83b14218d1beef66067f126a16keunyoung * functionality expected from an emulated physical camera device:
208a94683196406b83b14218d1beef66067f126a16keunyoung *  - Obtaining and setting camera parameters
218a94683196406b83b14218d1beef66067f126a16keunyoung *  - Capturing frames
228a94683196406b83b14218d1beef66067f126a16keunyoung *  - Streaming video
238a94683196406b83b14218d1beef66067f126a16keunyoung *  - etc.
248a94683196406b83b14218d1beef66067f126a16keunyoung */
258a94683196406b83b14218d1beef66067f126a16keunyoung
268a94683196406b83b14218d1beef66067f126a16keunyoung#define LOG_NDEBUG 0
278a94683196406b83b14218d1beef66067f126a16keunyoung#define LOG_TAG "EmulatedCamera_Device"
288a94683196406b83b14218d1beef66067f126a16keunyoung#include <cutils/log.h>
298a94683196406b83b14218d1beef66067f126a16keunyoung#include <sys/select.h>
308a94683196406b83b14218d1beef66067f126a16keunyoung#include <cmath>
318a94683196406b83b14218d1beef66067f126a16keunyoung#include "EmulatedCameraDevice.h"
328a94683196406b83b14218d1beef66067f126a16keunyoung
338a94683196406b83b14218d1beef66067f126a16keunyoungnamespace android {
348a94683196406b83b14218d1beef66067f126a16keunyoung
358a94683196406b83b14218d1beef66067f126a16keunyoungconst float GAMMA_CORRECTION = 2.2f;
368a94683196406b83b14218d1beef66067f126a16keunyoungEmulatedCameraDevice::EmulatedCameraDevice(EmulatedCamera* camera_hal)
378a94683196406b83b14218d1beef66067f126a16keunyoung    : mObjectLock(),
388a94683196406b83b14218d1beef66067f126a16keunyoung      mCurFrameTimestamp(0),
398a94683196406b83b14218d1beef66067f126a16keunyoung      mCameraHAL(camera_hal),
408a94683196406b83b14218d1beef66067f126a16keunyoung      mCurrentFrame(NULL),
418a94683196406b83b14218d1beef66067f126a16keunyoung      mExposureCompensation(1.0f),
428a94683196406b83b14218d1beef66067f126a16keunyoung      mWhiteBalanceScale(NULL),
438a94683196406b83b14218d1beef66067f126a16keunyoung      mSupportedWhiteBalanceScale(),
448a94683196406b83b14218d1beef66067f126a16keunyoung      mState(ECDS_CONSTRUCTED)
458a94683196406b83b14218d1beef66067f126a16keunyoung{
468a94683196406b83b14218d1beef66067f126a16keunyoung}
478a94683196406b83b14218d1beef66067f126a16keunyoung
488a94683196406b83b14218d1beef66067f126a16keunyoungEmulatedCameraDevice::~EmulatedCameraDevice()
498a94683196406b83b14218d1beef66067f126a16keunyoung{
508a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGV("EmulatedCameraDevice destructor");
518a94683196406b83b14218d1beef66067f126a16keunyoung    if (mCurrentFrame != NULL) {
528a94683196406b83b14218d1beef66067f126a16keunyoung        delete[] mCurrentFrame;
538a94683196406b83b14218d1beef66067f126a16keunyoung    }
543725c7c982eac52ec64a625e82f306822452941cColin Cross    for (size_t i = 0; i < mSupportedWhiteBalanceScale.size(); ++i) {
558a94683196406b83b14218d1beef66067f126a16keunyoung        if (mSupportedWhiteBalanceScale.valueAt(i) != NULL) {
568a94683196406b83b14218d1beef66067f126a16keunyoung            delete[] mSupportedWhiteBalanceScale.valueAt(i);
578a94683196406b83b14218d1beef66067f126a16keunyoung        }
588a94683196406b83b14218d1beef66067f126a16keunyoung    }
598a94683196406b83b14218d1beef66067f126a16keunyoung}
608a94683196406b83b14218d1beef66067f126a16keunyoung
618a94683196406b83b14218d1beef66067f126a16keunyoung/****************************************************************************
628a94683196406b83b14218d1beef66067f126a16keunyoung * Emulated camera device public API
638a94683196406b83b14218d1beef66067f126a16keunyoung ***************************************************************************/
648a94683196406b83b14218d1beef66067f126a16keunyoung
658a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedCameraDevice::Initialize()
668a94683196406b83b14218d1beef66067f126a16keunyoung{
678a94683196406b83b14218d1beef66067f126a16keunyoung    if (isInitialized()) {
688a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGW("%s: Emulated camera device is already initialized: mState = %d",
698a94683196406b83b14218d1beef66067f126a16keunyoung             __FUNCTION__, mState);
708a94683196406b83b14218d1beef66067f126a16keunyoung        return NO_ERROR;
718a94683196406b83b14218d1beef66067f126a16keunyoung    }
728a94683196406b83b14218d1beef66067f126a16keunyoung
738a94683196406b83b14218d1beef66067f126a16keunyoung    /* Instantiate worker thread object. */
748a94683196406b83b14218d1beef66067f126a16keunyoung    mWorkerThread = new WorkerThread(this);
758a94683196406b83b14218d1beef66067f126a16keunyoung    if (getWorkerThread() == NULL) {
768a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGE("%s: Unable to instantiate worker thread object", __FUNCTION__);
778a94683196406b83b14218d1beef66067f126a16keunyoung        return ENOMEM;
788a94683196406b83b14218d1beef66067f126a16keunyoung    }
798a94683196406b83b14218d1beef66067f126a16keunyoung
808a94683196406b83b14218d1beef66067f126a16keunyoung    mState = ECDS_INITIALIZED;
818a94683196406b83b14218d1beef66067f126a16keunyoung
828a94683196406b83b14218d1beef66067f126a16keunyoung    return NO_ERROR;
838a94683196406b83b14218d1beef66067f126a16keunyoung}
848a94683196406b83b14218d1beef66067f126a16keunyoung
858a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedCameraDevice::startDeliveringFrames(bool one_burst)
868a94683196406b83b14218d1beef66067f126a16keunyoung{
878a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGV("%s", __FUNCTION__);
888a94683196406b83b14218d1beef66067f126a16keunyoung
898a94683196406b83b14218d1beef66067f126a16keunyoung    if (!isStarted()) {
908a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGE("%s: Device is not started", __FUNCTION__);
918a94683196406b83b14218d1beef66067f126a16keunyoung        return EINVAL;
928a94683196406b83b14218d1beef66067f126a16keunyoung    }
938a94683196406b83b14218d1beef66067f126a16keunyoung
948a94683196406b83b14218d1beef66067f126a16keunyoung    /* Frames will be delivered from the thread routine. */
958a94683196406b83b14218d1beef66067f126a16keunyoung    const status_t res = startWorkerThread(one_burst);
968a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGE_IF(res != NO_ERROR, "%s: startWorkerThread failed", __FUNCTION__);
978a94683196406b83b14218d1beef66067f126a16keunyoung    return res;
988a94683196406b83b14218d1beef66067f126a16keunyoung}
998a94683196406b83b14218d1beef66067f126a16keunyoung
1008a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedCameraDevice::stopDeliveringFrames()
1018a94683196406b83b14218d1beef66067f126a16keunyoung{
1028a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGV("%s", __FUNCTION__);
1038a94683196406b83b14218d1beef66067f126a16keunyoung
1048a94683196406b83b14218d1beef66067f126a16keunyoung    if (!isStarted()) {
1058a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGW("%s: Device is not started", __FUNCTION__);
1068a94683196406b83b14218d1beef66067f126a16keunyoung        return NO_ERROR;
1078a94683196406b83b14218d1beef66067f126a16keunyoung    }
1088a94683196406b83b14218d1beef66067f126a16keunyoung
1098a94683196406b83b14218d1beef66067f126a16keunyoung    const status_t res = stopWorkerThread();
1108a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGE_IF(res != NO_ERROR, "%s: startWorkerThread failed", __FUNCTION__);
1118a94683196406b83b14218d1beef66067f126a16keunyoung    return res;
1128a94683196406b83b14218d1beef66067f126a16keunyoung}
1138a94683196406b83b14218d1beef66067f126a16keunyoung
1148a94683196406b83b14218d1beef66067f126a16keunyoungvoid EmulatedCameraDevice::setExposureCompensation(const float ev) {
1158a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGV("%s", __FUNCTION__);
1168a94683196406b83b14218d1beef66067f126a16keunyoung
1178a94683196406b83b14218d1beef66067f126a16keunyoung    if (!isStarted()) {
1188a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGW("%s: Fake camera device is not started.", __FUNCTION__);
1198a94683196406b83b14218d1beef66067f126a16keunyoung    }
1208a94683196406b83b14218d1beef66067f126a16keunyoung
1218a94683196406b83b14218d1beef66067f126a16keunyoung    mExposureCompensation = std::pow(2.0f, ev / GAMMA_CORRECTION);
1228a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGV("New exposure compensation is %f", mExposureCompensation);
1238a94683196406b83b14218d1beef66067f126a16keunyoung}
1248a94683196406b83b14218d1beef66067f126a16keunyoung
1258a94683196406b83b14218d1beef66067f126a16keunyoungvoid EmulatedCameraDevice::initializeWhiteBalanceModes(const char* mode,
1268a94683196406b83b14218d1beef66067f126a16keunyoung                                                       const float r_scale,
1278a94683196406b83b14218d1beef66067f126a16keunyoung                                                       const float b_scale) {
1288a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGV("%s with %s, %f, %f", __FUNCTION__, mode, r_scale, b_scale);
1298a94683196406b83b14218d1beef66067f126a16keunyoung    float* value = new float[3];
1308a94683196406b83b14218d1beef66067f126a16keunyoung    value[0] = r_scale; value[1] = 1.0f; value[2] = b_scale;
1318a94683196406b83b14218d1beef66067f126a16keunyoung    mSupportedWhiteBalanceScale.add(String8(mode), value);
1328a94683196406b83b14218d1beef66067f126a16keunyoung}
1338a94683196406b83b14218d1beef66067f126a16keunyoung
1348a94683196406b83b14218d1beef66067f126a16keunyoungvoid EmulatedCameraDevice::setWhiteBalanceMode(const char* mode) {
1358a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGV("%s with white balance %s", __FUNCTION__, mode);
1368a94683196406b83b14218d1beef66067f126a16keunyoung    mWhiteBalanceScale =
1378a94683196406b83b14218d1beef66067f126a16keunyoung            mSupportedWhiteBalanceScale.valueFor(String8(mode));
1388a94683196406b83b14218d1beef66067f126a16keunyoung}
1398a94683196406b83b14218d1beef66067f126a16keunyoung
1408a94683196406b83b14218d1beef66067f126a16keunyoung/* Computes the pixel value after adjusting the white balance to the current
1418a94683196406b83b14218d1beef66067f126a16keunyoung * one. The input the y, u, v channel of the pixel and the adjusted value will
1428a94683196406b83b14218d1beef66067f126a16keunyoung * be stored in place. The adjustment is done in RGB space.
1438a94683196406b83b14218d1beef66067f126a16keunyoung */
1448a94683196406b83b14218d1beef66067f126a16keunyoungvoid EmulatedCameraDevice::changeWhiteBalance(uint8_t& y,
1458a94683196406b83b14218d1beef66067f126a16keunyoung                                              uint8_t& u,
1468a94683196406b83b14218d1beef66067f126a16keunyoung                                              uint8_t& v) const {
1478a94683196406b83b14218d1beef66067f126a16keunyoung    float r_scale = mWhiteBalanceScale[0];
1488a94683196406b83b14218d1beef66067f126a16keunyoung    float b_scale = mWhiteBalanceScale[2];
1498a94683196406b83b14218d1beef66067f126a16keunyoung    int r = static_cast<float>(YUV2R(y, u, v)) / r_scale;
1508a94683196406b83b14218d1beef66067f126a16keunyoung    int g = YUV2G(y, u, v);
1518a94683196406b83b14218d1beef66067f126a16keunyoung    int b = static_cast<float>(YUV2B(y, u, v)) / b_scale;
1528a94683196406b83b14218d1beef66067f126a16keunyoung
1538a94683196406b83b14218d1beef66067f126a16keunyoung    y = RGB2Y(r, g, b);
1548a94683196406b83b14218d1beef66067f126a16keunyoung    u = RGB2U(r, g, b);
1558a94683196406b83b14218d1beef66067f126a16keunyoung    v = RGB2V(r, g, b);
1568a94683196406b83b14218d1beef66067f126a16keunyoung}
1578a94683196406b83b14218d1beef66067f126a16keunyoung
1588a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedCameraDevice::getCurrentPreviewFrame(void* buffer)
1598a94683196406b83b14218d1beef66067f126a16keunyoung{
1608a94683196406b83b14218d1beef66067f126a16keunyoung    if (!isStarted()) {
1618a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGE("%s: Device is not started", __FUNCTION__);
1628a94683196406b83b14218d1beef66067f126a16keunyoung        return EINVAL;
1638a94683196406b83b14218d1beef66067f126a16keunyoung    }
1648a94683196406b83b14218d1beef66067f126a16keunyoung    if (mCurrentFrame == NULL || buffer == NULL) {
1658a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGE("%s: No framebuffer", __FUNCTION__);
1668a94683196406b83b14218d1beef66067f126a16keunyoung        return EINVAL;
1678a94683196406b83b14218d1beef66067f126a16keunyoung    }
1688a94683196406b83b14218d1beef66067f126a16keunyoung
1698a94683196406b83b14218d1beef66067f126a16keunyoung    /* In emulation the framebuffer is never RGB. */
1708a94683196406b83b14218d1beef66067f126a16keunyoung    switch (mPixelFormat) {
1718a94683196406b83b14218d1beef66067f126a16keunyoung        case V4L2_PIX_FMT_YVU420:
1728a94683196406b83b14218d1beef66067f126a16keunyoung            YV12ToRGB32(mCurrentFrame, buffer, mFrameWidth, mFrameHeight);
1738a94683196406b83b14218d1beef66067f126a16keunyoung            return NO_ERROR;
1748a94683196406b83b14218d1beef66067f126a16keunyoung        case V4L2_PIX_FMT_YUV420:
1758a94683196406b83b14218d1beef66067f126a16keunyoung            YU12ToRGB32(mCurrentFrame, buffer, mFrameWidth, mFrameHeight);
1768a94683196406b83b14218d1beef66067f126a16keunyoung            return NO_ERROR;
1778a94683196406b83b14218d1beef66067f126a16keunyoung        case V4L2_PIX_FMT_NV21:
1788a94683196406b83b14218d1beef66067f126a16keunyoung            NV21ToRGB32(mCurrentFrame, buffer, mFrameWidth, mFrameHeight);
1798a94683196406b83b14218d1beef66067f126a16keunyoung            return NO_ERROR;
1808a94683196406b83b14218d1beef66067f126a16keunyoung        case V4L2_PIX_FMT_NV12:
1818a94683196406b83b14218d1beef66067f126a16keunyoung            NV12ToRGB32(mCurrentFrame, buffer, mFrameWidth, mFrameHeight);
1828a94683196406b83b14218d1beef66067f126a16keunyoung            return NO_ERROR;
1838a94683196406b83b14218d1beef66067f126a16keunyoung
1848a94683196406b83b14218d1beef66067f126a16keunyoung        default:
1858a94683196406b83b14218d1beef66067f126a16keunyoung            ALOGE("%s: Unknown pixel format %.4s",
1868a94683196406b83b14218d1beef66067f126a16keunyoung                 __FUNCTION__, reinterpret_cast<const char*>(&mPixelFormat));
1878a94683196406b83b14218d1beef66067f126a16keunyoung            return EINVAL;
1888a94683196406b83b14218d1beef66067f126a16keunyoung    }
1898a94683196406b83b14218d1beef66067f126a16keunyoung}
1908a94683196406b83b14218d1beef66067f126a16keunyoung
1918a94683196406b83b14218d1beef66067f126a16keunyoung/****************************************************************************
1928a94683196406b83b14218d1beef66067f126a16keunyoung * Emulated camera device private API
1938a94683196406b83b14218d1beef66067f126a16keunyoung ***************************************************************************/
1948a94683196406b83b14218d1beef66067f126a16keunyoung
1958a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedCameraDevice::commonStartDevice(int width,
1968a94683196406b83b14218d1beef66067f126a16keunyoung                                                 int height,
1978a94683196406b83b14218d1beef66067f126a16keunyoung                                                 uint32_t pix_fmt)
1988a94683196406b83b14218d1beef66067f126a16keunyoung{
1998a94683196406b83b14218d1beef66067f126a16keunyoung    /* Validate pixel format, and calculate framebuffer size at the same time. */
2008a94683196406b83b14218d1beef66067f126a16keunyoung    switch (pix_fmt) {
2018a94683196406b83b14218d1beef66067f126a16keunyoung        case V4L2_PIX_FMT_YVU420:
2028a94683196406b83b14218d1beef66067f126a16keunyoung        case V4L2_PIX_FMT_YUV420:
2038a94683196406b83b14218d1beef66067f126a16keunyoung        case V4L2_PIX_FMT_NV21:
2048a94683196406b83b14218d1beef66067f126a16keunyoung        case V4L2_PIX_FMT_NV12:
2058a94683196406b83b14218d1beef66067f126a16keunyoung            mFrameBufferSize = (width * height * 12) / 8;
2068a94683196406b83b14218d1beef66067f126a16keunyoung            break;
2078a94683196406b83b14218d1beef66067f126a16keunyoung
2088a94683196406b83b14218d1beef66067f126a16keunyoung        default:
2098a94683196406b83b14218d1beef66067f126a16keunyoung            ALOGE("%s: Unknown pixel format %.4s",
2108a94683196406b83b14218d1beef66067f126a16keunyoung                 __FUNCTION__, reinterpret_cast<const char*>(&pix_fmt));
2118a94683196406b83b14218d1beef66067f126a16keunyoung            return EINVAL;
2128a94683196406b83b14218d1beef66067f126a16keunyoung    }
2138a94683196406b83b14218d1beef66067f126a16keunyoung
2148a94683196406b83b14218d1beef66067f126a16keunyoung    /* Cache framebuffer info. */
2158a94683196406b83b14218d1beef66067f126a16keunyoung    mFrameWidth = width;
2168a94683196406b83b14218d1beef66067f126a16keunyoung    mFrameHeight = height;
2178a94683196406b83b14218d1beef66067f126a16keunyoung    mPixelFormat = pix_fmt;
2188a94683196406b83b14218d1beef66067f126a16keunyoung    mTotalPixels = width * height;
2198a94683196406b83b14218d1beef66067f126a16keunyoung
2208a94683196406b83b14218d1beef66067f126a16keunyoung    /* Allocate framebuffer. */
2218a94683196406b83b14218d1beef66067f126a16keunyoung    mCurrentFrame = new uint8_t[mFrameBufferSize];
2228a94683196406b83b14218d1beef66067f126a16keunyoung    if (mCurrentFrame == NULL) {
2238a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGE("%s: Unable to allocate framebuffer", __FUNCTION__);
2248a94683196406b83b14218d1beef66067f126a16keunyoung        return ENOMEM;
2258a94683196406b83b14218d1beef66067f126a16keunyoung    }
2263725c7c982eac52ec64a625e82f306822452941cColin Cross    ALOGV("%s: Allocated %p %zu bytes for %d pixels in %.4s[%dx%d] frame",
2278a94683196406b83b14218d1beef66067f126a16keunyoung         __FUNCTION__, mCurrentFrame, mFrameBufferSize, mTotalPixels,
2288a94683196406b83b14218d1beef66067f126a16keunyoung         reinterpret_cast<const char*>(&mPixelFormat), mFrameWidth, mFrameHeight);
2298a94683196406b83b14218d1beef66067f126a16keunyoung    return NO_ERROR;
2308a94683196406b83b14218d1beef66067f126a16keunyoung}
2318a94683196406b83b14218d1beef66067f126a16keunyoung
2328a94683196406b83b14218d1beef66067f126a16keunyoungvoid EmulatedCameraDevice::commonStopDevice()
2338a94683196406b83b14218d1beef66067f126a16keunyoung{
2348a94683196406b83b14218d1beef66067f126a16keunyoung    mFrameWidth = mFrameHeight = mTotalPixels = 0;
2358a94683196406b83b14218d1beef66067f126a16keunyoung    mPixelFormat = 0;
2368a94683196406b83b14218d1beef66067f126a16keunyoung
2378a94683196406b83b14218d1beef66067f126a16keunyoung    if (mCurrentFrame != NULL) {
2388a94683196406b83b14218d1beef66067f126a16keunyoung        delete[] mCurrentFrame;
2398a94683196406b83b14218d1beef66067f126a16keunyoung        mCurrentFrame = NULL;
2408a94683196406b83b14218d1beef66067f126a16keunyoung    }
2418a94683196406b83b14218d1beef66067f126a16keunyoung}
2428a94683196406b83b14218d1beef66067f126a16keunyoung
2438a94683196406b83b14218d1beef66067f126a16keunyoung/****************************************************************************
2448a94683196406b83b14218d1beef66067f126a16keunyoung * Worker thread management.
2458a94683196406b83b14218d1beef66067f126a16keunyoung ***************************************************************************/
2468a94683196406b83b14218d1beef66067f126a16keunyoung
2478a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedCameraDevice::startWorkerThread(bool one_burst)
2488a94683196406b83b14218d1beef66067f126a16keunyoung{
2498a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGV("%s", __FUNCTION__);
2508a94683196406b83b14218d1beef66067f126a16keunyoung
2518a94683196406b83b14218d1beef66067f126a16keunyoung    if (!isInitialized()) {
2528a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGE("%s: Emulated camera device is not initialized", __FUNCTION__);
2538a94683196406b83b14218d1beef66067f126a16keunyoung        return EINVAL;
2548a94683196406b83b14218d1beef66067f126a16keunyoung    }
2558a94683196406b83b14218d1beef66067f126a16keunyoung
2568a94683196406b83b14218d1beef66067f126a16keunyoung    const status_t res = getWorkerThread()->startThread(one_burst);
2578a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGE_IF(res != NO_ERROR, "%s: Unable to start worker thread", __FUNCTION__);
2588a94683196406b83b14218d1beef66067f126a16keunyoung    return res;
2598a94683196406b83b14218d1beef66067f126a16keunyoung}
2608a94683196406b83b14218d1beef66067f126a16keunyoung
2618a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedCameraDevice::stopWorkerThread()
2628a94683196406b83b14218d1beef66067f126a16keunyoung{
2638a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGV("%s", __FUNCTION__);
2648a94683196406b83b14218d1beef66067f126a16keunyoung
2658a94683196406b83b14218d1beef66067f126a16keunyoung    if (!isInitialized()) {
2668a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGE("%s: Emulated camera device is not initialized", __FUNCTION__);
2678a94683196406b83b14218d1beef66067f126a16keunyoung        return EINVAL;
2688a94683196406b83b14218d1beef66067f126a16keunyoung    }
2698a94683196406b83b14218d1beef66067f126a16keunyoung
2708a94683196406b83b14218d1beef66067f126a16keunyoung    const status_t res = getWorkerThread()->stopThread();
2718a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGE_IF(res != NO_ERROR, "%s: Unable to stop worker thread", __FUNCTION__);
2728a94683196406b83b14218d1beef66067f126a16keunyoung    return res;
2738a94683196406b83b14218d1beef66067f126a16keunyoung}
2748a94683196406b83b14218d1beef66067f126a16keunyoung
2758a94683196406b83b14218d1beef66067f126a16keunyoungbool EmulatedCameraDevice::inWorkerThread()
2768a94683196406b83b14218d1beef66067f126a16keunyoung{
2778a94683196406b83b14218d1beef66067f126a16keunyoung    /* This will end the thread loop, and will terminate the thread. Derived
2788a94683196406b83b14218d1beef66067f126a16keunyoung     * classes must override this method. */
2798a94683196406b83b14218d1beef66067f126a16keunyoung    return false;
2808a94683196406b83b14218d1beef66067f126a16keunyoung}
2818a94683196406b83b14218d1beef66067f126a16keunyoung
2828a94683196406b83b14218d1beef66067f126a16keunyoung/****************************************************************************
2838a94683196406b83b14218d1beef66067f126a16keunyoung * Worker thread implementation.
2848a94683196406b83b14218d1beef66067f126a16keunyoung ***************************************************************************/
2858a94683196406b83b14218d1beef66067f126a16keunyoung
2868a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedCameraDevice::WorkerThread::readyToRun()
2878a94683196406b83b14218d1beef66067f126a16keunyoung{
2888a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGV("Starting emulated camera device worker thread...");
2898a94683196406b83b14218d1beef66067f126a16keunyoung
2908a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGW_IF(mThreadControl >= 0 || mControlFD >= 0,
2918a94683196406b83b14218d1beef66067f126a16keunyoung            "%s: Thread control FDs are opened", __FUNCTION__);
2928a94683196406b83b14218d1beef66067f126a16keunyoung    /* Create a pair of FDs that would be used to control the thread. */
2938a94683196406b83b14218d1beef66067f126a16keunyoung    int thread_fds[2];
2948a94683196406b83b14218d1beef66067f126a16keunyoung    if (pipe(thread_fds) == 0) {
2958a94683196406b83b14218d1beef66067f126a16keunyoung        mThreadControl = thread_fds[1];
2968a94683196406b83b14218d1beef66067f126a16keunyoung        mControlFD = thread_fds[0];
2978a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGV("Emulated device's worker thread has been started.");
2988a94683196406b83b14218d1beef66067f126a16keunyoung        return NO_ERROR;
2998a94683196406b83b14218d1beef66067f126a16keunyoung    } else {
3008a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGE("%s: Unable to create thread control FDs: %d -> %s",
3018a94683196406b83b14218d1beef66067f126a16keunyoung             __FUNCTION__, errno, strerror(errno));
3028a94683196406b83b14218d1beef66067f126a16keunyoung        return errno;
3038a94683196406b83b14218d1beef66067f126a16keunyoung    }
3048a94683196406b83b14218d1beef66067f126a16keunyoung}
3058a94683196406b83b14218d1beef66067f126a16keunyoung
3068a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedCameraDevice::WorkerThread::stopThread()
3078a94683196406b83b14218d1beef66067f126a16keunyoung{
3088a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGV("Stopping emulated camera device's worker thread...");
3098a94683196406b83b14218d1beef66067f126a16keunyoung
3108a94683196406b83b14218d1beef66067f126a16keunyoung    status_t res = EINVAL;
3118a94683196406b83b14218d1beef66067f126a16keunyoung    if (mThreadControl >= 0) {
3128a94683196406b83b14218d1beef66067f126a16keunyoung        /* Send "stop" message to the thread loop. */
3138a94683196406b83b14218d1beef66067f126a16keunyoung        const ControlMessage msg = THREAD_STOP;
3148a94683196406b83b14218d1beef66067f126a16keunyoung        const int wres =
3158a94683196406b83b14218d1beef66067f126a16keunyoung            TEMP_FAILURE_RETRY(write(mThreadControl, &msg, sizeof(msg)));
3168a94683196406b83b14218d1beef66067f126a16keunyoung        if (wres == sizeof(msg)) {
3178a94683196406b83b14218d1beef66067f126a16keunyoung            /* Stop the thread, and wait till it's terminated. */
3188a94683196406b83b14218d1beef66067f126a16keunyoung            res = requestExitAndWait();
3198a94683196406b83b14218d1beef66067f126a16keunyoung            if (res == NO_ERROR) {
3208a94683196406b83b14218d1beef66067f126a16keunyoung                /* Close control FDs. */
3218a94683196406b83b14218d1beef66067f126a16keunyoung                if (mThreadControl >= 0) {
3228a94683196406b83b14218d1beef66067f126a16keunyoung                    close(mThreadControl);
3238a94683196406b83b14218d1beef66067f126a16keunyoung                    mThreadControl = -1;
3248a94683196406b83b14218d1beef66067f126a16keunyoung                }
3258a94683196406b83b14218d1beef66067f126a16keunyoung                if (mControlFD >= 0) {
3268a94683196406b83b14218d1beef66067f126a16keunyoung                    close(mControlFD);
3278a94683196406b83b14218d1beef66067f126a16keunyoung                    mControlFD = -1;
3288a94683196406b83b14218d1beef66067f126a16keunyoung                }
3298a94683196406b83b14218d1beef66067f126a16keunyoung                ALOGV("Emulated camera device's worker thread has been stopped.");
3308a94683196406b83b14218d1beef66067f126a16keunyoung            } else {
3318a94683196406b83b14218d1beef66067f126a16keunyoung                ALOGE("%s: requestExitAndWait failed: %d -> %s",
3328a94683196406b83b14218d1beef66067f126a16keunyoung                     __FUNCTION__, res, strerror(-res));
3338a94683196406b83b14218d1beef66067f126a16keunyoung            }
3348a94683196406b83b14218d1beef66067f126a16keunyoung        } else {
3358a94683196406b83b14218d1beef66067f126a16keunyoung            ALOGE("%s: Unable to send THREAD_STOP message: %d -> %s",
3368a94683196406b83b14218d1beef66067f126a16keunyoung                 __FUNCTION__, errno, strerror(errno));
3378a94683196406b83b14218d1beef66067f126a16keunyoung            res = errno ? errno : EINVAL;
3388a94683196406b83b14218d1beef66067f126a16keunyoung        }
3398a94683196406b83b14218d1beef66067f126a16keunyoung    } else {
3408a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGE("%s: Thread control FDs are not opened", __FUNCTION__);
3418a94683196406b83b14218d1beef66067f126a16keunyoung    }
3428a94683196406b83b14218d1beef66067f126a16keunyoung
3438a94683196406b83b14218d1beef66067f126a16keunyoung    return res;
3448a94683196406b83b14218d1beef66067f126a16keunyoung}
3458a94683196406b83b14218d1beef66067f126a16keunyoung
3468a94683196406b83b14218d1beef66067f126a16keunyoungEmulatedCameraDevice::WorkerThread::SelectRes
3478a94683196406b83b14218d1beef66067f126a16keunyoungEmulatedCameraDevice::WorkerThread::Select(int fd, int timeout)
3488a94683196406b83b14218d1beef66067f126a16keunyoung{
3498a94683196406b83b14218d1beef66067f126a16keunyoung    fd_set fds[1];
3508a94683196406b83b14218d1beef66067f126a16keunyoung    struct timeval tv, *tvp = NULL;
3518a94683196406b83b14218d1beef66067f126a16keunyoung
3528a94683196406b83b14218d1beef66067f126a16keunyoung    const int fd_num = (fd >= 0) ? max(fd, mControlFD) + 1 :
3538a94683196406b83b14218d1beef66067f126a16keunyoung                                   mControlFD + 1;
3548a94683196406b83b14218d1beef66067f126a16keunyoung    FD_ZERO(fds);
3558a94683196406b83b14218d1beef66067f126a16keunyoung    FD_SET(mControlFD, fds);
3568a94683196406b83b14218d1beef66067f126a16keunyoung    if (fd >= 0) {
3578a94683196406b83b14218d1beef66067f126a16keunyoung        FD_SET(fd, fds);
3588a94683196406b83b14218d1beef66067f126a16keunyoung    }
3598a94683196406b83b14218d1beef66067f126a16keunyoung    if (timeout) {
3608a94683196406b83b14218d1beef66067f126a16keunyoung        tv.tv_sec = timeout / 1000000;
3618a94683196406b83b14218d1beef66067f126a16keunyoung        tv.tv_usec = timeout % 1000000;
3628a94683196406b83b14218d1beef66067f126a16keunyoung        tvp = &tv;
3638a94683196406b83b14218d1beef66067f126a16keunyoung    }
3648a94683196406b83b14218d1beef66067f126a16keunyoung    int res = TEMP_FAILURE_RETRY(select(fd_num, fds, NULL, NULL, tvp));
3658a94683196406b83b14218d1beef66067f126a16keunyoung    if (res < 0) {
3668a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGE("%s: select returned %d and failed: %d -> %s",
3678a94683196406b83b14218d1beef66067f126a16keunyoung             __FUNCTION__, res, errno, strerror(errno));
3688a94683196406b83b14218d1beef66067f126a16keunyoung        return ERROR;
3698a94683196406b83b14218d1beef66067f126a16keunyoung    } else if (res == 0) {
3708a94683196406b83b14218d1beef66067f126a16keunyoung        /* Timeout. */
3718a94683196406b83b14218d1beef66067f126a16keunyoung        return TIMEOUT;
3728a94683196406b83b14218d1beef66067f126a16keunyoung    } else if (FD_ISSET(mControlFD, fds)) {
3738a94683196406b83b14218d1beef66067f126a16keunyoung        /* A control event. Lets read the message. */
3748a94683196406b83b14218d1beef66067f126a16keunyoung        ControlMessage msg;
3758a94683196406b83b14218d1beef66067f126a16keunyoung        res = TEMP_FAILURE_RETRY(read(mControlFD, &msg, sizeof(msg)));
3768a94683196406b83b14218d1beef66067f126a16keunyoung        if (res != sizeof(msg)) {
3778a94683196406b83b14218d1beef66067f126a16keunyoung            ALOGE("%s: Unexpected message size %d, or an error %d -> %s",
3788a94683196406b83b14218d1beef66067f126a16keunyoung                 __FUNCTION__, res, errno, strerror(errno));
3798a94683196406b83b14218d1beef66067f126a16keunyoung            return ERROR;
3808a94683196406b83b14218d1beef66067f126a16keunyoung        }
3818a94683196406b83b14218d1beef66067f126a16keunyoung        /* THREAD_STOP is the only message expected here. */
3828a94683196406b83b14218d1beef66067f126a16keunyoung        if (msg == THREAD_STOP) {
3838a94683196406b83b14218d1beef66067f126a16keunyoung            ALOGV("%s: THREAD_STOP message is received", __FUNCTION__);
3848a94683196406b83b14218d1beef66067f126a16keunyoung            return EXIT_THREAD;
3858a94683196406b83b14218d1beef66067f126a16keunyoung        } else {
3868a94683196406b83b14218d1beef66067f126a16keunyoung            ALOGE("Unknown worker thread message %d", msg);
3878a94683196406b83b14218d1beef66067f126a16keunyoung            return ERROR;
3888a94683196406b83b14218d1beef66067f126a16keunyoung        }
3898a94683196406b83b14218d1beef66067f126a16keunyoung    } else {
3908a94683196406b83b14218d1beef66067f126a16keunyoung        /* Must be an FD. */
3918a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGW_IF(fd < 0 || !FD_ISSET(fd, fds), "%s: Undefined 'select' result",
3928a94683196406b83b14218d1beef66067f126a16keunyoung                __FUNCTION__);
3938a94683196406b83b14218d1beef66067f126a16keunyoung        return READY;
3948a94683196406b83b14218d1beef66067f126a16keunyoung    }
3958a94683196406b83b14218d1beef66067f126a16keunyoung}
3968a94683196406b83b14218d1beef66067f126a16keunyoung
3978a94683196406b83b14218d1beef66067f126a16keunyoung};  /* namespace android */
398