1b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine/*
2b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * Copyright (C) 2011 The Android Open Source Project
3b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine *
4b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * Licensed under the Apache License, Version 2.0 (the "License");
5b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * you may not use this file except in compliance with the License.
6b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * You may obtain a copy of the License at
7b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine *
8b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine *      http://www.apache.org/licenses/LICENSE-2.0
9b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine *
10b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * Unless required by applicable law or agreed to in writing, software
11b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * distributed under the License is distributed on an "AS IS" BASIS,
12b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * See the License for the specific language governing permissions and
14b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * limitations under the License.
15b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine */
16b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
17b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine/*
18b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * Contains implementation of an abstract class EmulatedCameraDevice that defines
19b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * functionality expected from an emulated physical camera device:
20b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine *  - Obtaining and setting camera parameters
21b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine *  - Capturing frames
22b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine *  - Streaming video
23b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine *  - etc.
24b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine */
25b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
26b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine#define LOG_NDEBUG 0
27b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine#define LOG_TAG "EmulatedCamera_Device"
28b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine#include <cutils/log.h>
29b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine#include <sys/select.h>
30366396d9b001c7a1abf2b73161a9b7b05e9022ecChristine Chen#include <cmath>
315467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine#include "EmulatedCameraDevice.h"
32b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
33b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkinenamespace android {
34b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
3512c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chenconst float GAMMA_CORRECTION = 2.2f;
36b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir ChtchetkineEmulatedCameraDevice::EmulatedCameraDevice(EmulatedCamera* camera_hal)
375467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    : mObjectLock(),
385467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine      mCurFrameTimestamp(0),
395467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine      mCameraHAL(camera_hal),
405467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine      mCurrentFrame(NULL),
41366396d9b001c7a1abf2b73161a9b7b05e9022ecChristine Chen      mExposureCompensation(1.0f),
4212c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen      mWhiteBalanceScale(NULL),
4312c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen      mSupportedWhiteBalanceScale(),
445467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine      mState(ECDS_CONSTRUCTED)
45b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine{
46b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine}
47b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
48b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir ChtchetkineEmulatedCameraDevice::~EmulatedCameraDevice()
49b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine{
50629719e390ce66be822c3563bbd248ce15eaae7bSteve Block    ALOGV("EmulatedCameraDevice destructor");
515467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    if (mCurrentFrame != NULL) {
525467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        delete[] mCurrentFrame;
53b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    }
5412c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen    for (int i = 0; i < mSupportedWhiteBalanceScale.size(); ++i) {
5512c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen        if (mSupportedWhiteBalanceScale.valueAt(i) != NULL) {
5612c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen            delete[] mSupportedWhiteBalanceScale.valueAt(i);
5712c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen        }
5812c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen    }
59b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine}
60b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
61b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine/****************************************************************************
62b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * Emulated camera device public API
63b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine ***************************************************************************/
64b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
65b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkinestatus_t EmulatedCameraDevice::Initialize()
66b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine{
675467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    if (isInitialized()) {
686aff44c27ee487bd65d5a1c74faf4b7165530bd4Steve Block        ALOGW("%s: Emulated camera device is already initialized: mState = %d",
695467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine             __FUNCTION__, mState);
70b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        return NO_ERROR;
71b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    }
72b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
73b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    /* Instantiate worker thread object. */
745467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    mWorkerThread = new WorkerThread(this);
755467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    if (getWorkerThread() == NULL) {
765a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: Unable to instantiate worker thread object", __FUNCTION__);
77b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        return ENOMEM;
78b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    }
79b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
805467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    mState = ECDS_INITIALIZED;
81b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
82b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    return NO_ERROR;
83b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine}
84b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
8549842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkinestatus_t EmulatedCameraDevice::startDeliveringFrames(bool one_burst)
86b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine{
87629719e390ce66be822c3563bbd248ce15eaae7bSteve Block    ALOGV("%s", __FUNCTION__);
88b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
8949842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    if (!isStarted()) {
905a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: Device is not started", __FUNCTION__);
9149842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine        return EINVAL;
9249842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    }
9349842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine
9449842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    /* Frames will be delivered from the thread routine. */
9549842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    const status_t res = startWorkerThread(one_burst);
965a622cba8c5287d5e6577f940a22343a7cae977fSteve Block    ALOGE_IF(res != NO_ERROR, "%s: startWorkerThread failed", __FUNCTION__);
9749842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    return res;
9849842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine}
9949842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine
10049842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkinestatus_t EmulatedCameraDevice::stopDeliveringFrames()
10149842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine{
102629719e390ce66be822c3563bbd248ce15eaae7bSteve Block    ALOGV("%s", __FUNCTION__);
10349842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine
10449842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    if (!isStarted()) {
1056aff44c27ee487bd65d5a1c74faf4b7165530bd4Steve Block        ALOGW("%s: Device is not started", __FUNCTION__);
10649842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine        return NO_ERROR;
10749842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    }
10849842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine
10949842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    const status_t res = stopWorkerThread();
1105a622cba8c5287d5e6577f940a22343a7cae977fSteve Block    ALOGE_IF(res != NO_ERROR, "%s: startWorkerThread failed", __FUNCTION__);
11149842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    return res;
11249842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine}
11349842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine
114366396d9b001c7a1abf2b73161a9b7b05e9022ecChristine Chenvoid EmulatedCameraDevice::setExposureCompensation(const float ev) {
115629719e390ce66be822c3563bbd248ce15eaae7bSteve Block    ALOGV("%s", __FUNCTION__);
116366396d9b001c7a1abf2b73161a9b7b05e9022ecChristine Chen
117366396d9b001c7a1abf2b73161a9b7b05e9022ecChristine Chen    if (!isStarted()) {
1186aff44c27ee487bd65d5a1c74faf4b7165530bd4Steve Block        ALOGW("%s: Fake camera device is not started.", __FUNCTION__);
119366396d9b001c7a1abf2b73161a9b7b05e9022ecChristine Chen    }
120366396d9b001c7a1abf2b73161a9b7b05e9022ecChristine Chen
12112c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen    mExposureCompensation = std::pow(2.0f, ev / GAMMA_CORRECTION);
122629719e390ce66be822c3563bbd248ce15eaae7bSteve Block    ALOGV("New exposure compensation is %f", mExposureCompensation);
123366396d9b001c7a1abf2b73161a9b7b05e9022ecChristine Chen}
124366396d9b001c7a1abf2b73161a9b7b05e9022ecChristine Chen
12512c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chenvoid EmulatedCameraDevice::initializeWhiteBalanceModes(const char* mode,
12612c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen                                                       const float r_scale,
12712c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen                                                       const float b_scale) {
128629719e390ce66be822c3563bbd248ce15eaae7bSteve Block    ALOGV("%s with %s, %f, %f", __FUNCTION__, mode, r_scale, b_scale);
12912c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen    float* value = new float[3];
13012c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen    value[0] = r_scale; value[1] = 1.0f; value[2] = b_scale;
13112c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen    mSupportedWhiteBalanceScale.add(String8(mode), value);
13212c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen}
13312c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen
13412c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chenvoid EmulatedCameraDevice::setWhiteBalanceMode(const char* mode) {
135629719e390ce66be822c3563bbd248ce15eaae7bSteve Block    ALOGV("%s with white balance %s", __FUNCTION__, mode);
13612c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen    mWhiteBalanceScale =
13712c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen            mSupportedWhiteBalanceScale.valueFor(String8(mode));
13812c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen}
13912c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen
14012c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen/* Computes the pixel value after adjusting the white balance to the current
14112c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen * one. The input the y, u, v channel of the pixel and the adjusted value will
14212c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen * be stored in place. The adjustment is done in RGB space.
14312c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen */
14412c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chenvoid EmulatedCameraDevice::changeWhiteBalance(uint8_t& y,
14512c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen                                              uint8_t& u,
14612c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen                                              uint8_t& v) const {
14712c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen    float r_scale = mWhiteBalanceScale[0];
14812c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen    float b_scale = mWhiteBalanceScale[2];
14912c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen    int r = static_cast<float>(YUV2R(y, u, v)) / r_scale;
15012c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen    int g = YUV2G(y, u, v);
15112c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen    int b = static_cast<float>(YUV2B(y, u, v)) / b_scale;
15212c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen
15312c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen    y = RGB2Y(r, g, b);
15412c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen    u = RGB2U(r, g, b);
15512c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen    v = RGB2V(r, g, b);
15612c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen}
15712c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen
15849842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkinestatus_t EmulatedCameraDevice::getCurrentPreviewFrame(void* buffer)
15949842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine{
16049842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    if (!isStarted()) {
1615a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: Device is not started", __FUNCTION__);
16249842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine        return EINVAL;
16349842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    }
16449842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    if (mCurrentFrame == NULL || buffer == NULL) {
1655a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: No framebuffer", __FUNCTION__);
16649842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine        return EINVAL;
16749842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    }
16849842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine
16949842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    /* In emulation the framebuffer is never RGB. */
17049842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    switch (mPixelFormat) {
17149842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine        case V4L2_PIX_FMT_YVU420:
17249842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine            YV12ToRGB32(mCurrentFrame, buffer, mFrameWidth, mFrameHeight);
17349842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine            return NO_ERROR;
17468ec4ac828762745155be9662285d2174a7eff1eVladimir Chtchetkine        case V4L2_PIX_FMT_YUV420:
17568ec4ac828762745155be9662285d2174a7eff1eVladimir Chtchetkine            YU12ToRGB32(mCurrentFrame, buffer, mFrameWidth, mFrameHeight);
17668ec4ac828762745155be9662285d2174a7eff1eVladimir Chtchetkine            return NO_ERROR;
1772a532ee388828120a5a11fba0087a1ed2539a159Vladimir Chtchetkine        case V4L2_PIX_FMT_NV21:
1782a532ee388828120a5a11fba0087a1ed2539a159Vladimir Chtchetkine            NV21ToRGB32(mCurrentFrame, buffer, mFrameWidth, mFrameHeight);
1792a532ee388828120a5a11fba0087a1ed2539a159Vladimir Chtchetkine            return NO_ERROR;
1802a532ee388828120a5a11fba0087a1ed2539a159Vladimir Chtchetkine        case V4L2_PIX_FMT_NV12:
1812a532ee388828120a5a11fba0087a1ed2539a159Vladimir Chtchetkine            NV12ToRGB32(mCurrentFrame, buffer, mFrameWidth, mFrameHeight);
1822a532ee388828120a5a11fba0087a1ed2539a159Vladimir Chtchetkine            return NO_ERROR;
18349842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine
18449842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine        default:
1855a622cba8c5287d5e6577f940a22343a7cae977fSteve Block            ALOGE("%s: Unknown pixel format %.4s",
18649842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine                 __FUNCTION__, reinterpret_cast<const char*>(&mPixelFormat));
18749842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine            return EINVAL;
18849842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    }
18949842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine}
19049842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine
19149842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine/****************************************************************************
19249842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine * Emulated camera device private API
19349842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine ***************************************************************************/
19449842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine
19549842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkinestatus_t EmulatedCameraDevice::commonStartDevice(int width,
19649842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine                                                 int height,
19749842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine                                                 uint32_t pix_fmt)
19849842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine{
199b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    /* Validate pixel format, and calculate framebuffer size at the same time. */
200b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    switch (pix_fmt) {
201b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        case V4L2_PIX_FMT_YVU420:
20268ec4ac828762745155be9662285d2174a7eff1eVladimir Chtchetkine        case V4L2_PIX_FMT_YUV420:
2032a532ee388828120a5a11fba0087a1ed2539a159Vladimir Chtchetkine        case V4L2_PIX_FMT_NV21:
2042a532ee388828120a5a11fba0087a1ed2539a159Vladimir Chtchetkine        case V4L2_PIX_FMT_NV12:
2055467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine            mFrameBufferSize = (width * height * 12) / 8;
206b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine            break;
207b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
208b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        default:
2095a622cba8c5287d5e6577f940a22343a7cae977fSteve Block            ALOGE("%s: Unknown pixel format %.4s",
210b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine                 __FUNCTION__, reinterpret_cast<const char*>(&pix_fmt));
211b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine            return EINVAL;
212b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    }
213b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
214b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    /* Cache framebuffer info. */
2155467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    mFrameWidth = width;
2165467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    mFrameHeight = height;
2175467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    mPixelFormat = pix_fmt;
2185467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    mTotalPixels = width * height;
219b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
220b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    /* Allocate framebuffer. */
2215467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    mCurrentFrame = new uint8_t[mFrameBufferSize];
2225467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    if (mCurrentFrame == NULL) {
2235a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: Unable to allocate framebuffer", __FUNCTION__);
224b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        return ENOMEM;
225b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    }
226629719e390ce66be822c3563bbd248ce15eaae7bSteve Block    ALOGV("%s: Allocated %p %d bytes for %d pixels in %.4s[%dx%d] frame",
2272a532ee388828120a5a11fba0087a1ed2539a159Vladimir Chtchetkine         __FUNCTION__, mCurrentFrame, mFrameBufferSize, mTotalPixels,
2282a532ee388828120a5a11fba0087a1ed2539a159Vladimir Chtchetkine         reinterpret_cast<const char*>(&mPixelFormat), mFrameWidth, mFrameHeight);
229b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    return NO_ERROR;
230b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine}
231b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
23249842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkinevoid EmulatedCameraDevice::commonStopDevice()
233b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine{
23449842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    mFrameWidth = mFrameHeight = mTotalPixels = 0;
23549842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    mPixelFormat = 0;
236b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
23749842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    if (mCurrentFrame != NULL) {
23849842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine        delete[] mCurrentFrame;
23949842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine        mCurrentFrame = NULL;
240b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    }
241b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine}
242b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
243b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine/****************************************************************************
244b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * Worker thread management.
245b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine ***************************************************************************/
246b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
24749842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkinestatus_t EmulatedCameraDevice::startWorkerThread(bool one_burst)
248b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine{
249629719e390ce66be822c3563bbd248ce15eaae7bSteve Block    ALOGV("%s", __FUNCTION__);
250b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
2515467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    if (!isInitialized()) {
2525a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: Emulated camera device is not initialized", __FUNCTION__);
253b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        return EINVAL;
254b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    }
255b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
25649842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    const status_t res = getWorkerThread()->startThread(one_burst);
2575a622cba8c5287d5e6577f940a22343a7cae977fSteve Block    ALOGE_IF(res != NO_ERROR, "%s: Unable to start worker thread", __FUNCTION__);
25849842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    return res;
259b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine}
260b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
2615467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkinestatus_t EmulatedCameraDevice::stopWorkerThread()
262b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine{
263629719e390ce66be822c3563bbd248ce15eaae7bSteve Block    ALOGV("%s", __FUNCTION__);
264b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
2655467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    if (!isInitialized()) {
2665a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: Emulated camera device is not initialized", __FUNCTION__);
267b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        return EINVAL;
268b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    }
269b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
27049842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    const status_t res = getWorkerThread()->stopThread();
2715a622cba8c5287d5e6577f940a22343a7cae977fSteve Block    ALOGE_IF(res != NO_ERROR, "%s: Unable to stop worker thread", __FUNCTION__);
27249842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    return res;
273b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine}
274b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
2755467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkinebool EmulatedCameraDevice::inWorkerThread()
276b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine{
27749842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine    /* This will end the thread loop, and will terminate the thread. Derived
27849842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine     * classes must override this method. */
279b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    return false;
280b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine}
281b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
282b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine/****************************************************************************
283b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * Worker thread implementation.
284b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine ***************************************************************************/
285b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
286b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkinestatus_t EmulatedCameraDevice::WorkerThread::readyToRun()
287b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine{
288629719e390ce66be822c3563bbd248ce15eaae7bSteve Block    ALOGV("Starting emulated camera device worker thread...");
289b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
2906aff44c27ee487bd65d5a1c74faf4b7165530bd4Steve Block    ALOGW_IF(mThreadControl >= 0 || mControlFD >= 0,
291b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine            "%s: Thread control FDs are opened", __FUNCTION__);
292b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    /* Create a pair of FDs that would be used to control the thread. */
293b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    int thread_fds[2];
294b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    if (pipe(thread_fds) == 0) {
2955467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        mThreadControl = thread_fds[1];
2965467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        mControlFD = thread_fds[0];
297629719e390ce66be822c3563bbd248ce15eaae7bSteve Block        ALOGV("Emulated device's worker thread has been started.");
298b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        return NO_ERROR;
299b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    } else {
3005a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: Unable to create thread control FDs: %d -> %s",
301b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine             __FUNCTION__, errno, strerror(errno));
302b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        return errno;
303b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    }
304b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine}
305b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
3065467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkinestatus_t EmulatedCameraDevice::WorkerThread::stopThread()
307b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine{
308629719e390ce66be822c3563bbd248ce15eaae7bSteve Block    ALOGV("Stopping emulated camera device's worker thread...");
309b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
310b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    status_t res = EINVAL;
3115467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    if (mThreadControl >= 0) {
312b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        /* Send "stop" message to the thread loop. */
313b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        const ControlMessage msg = THREAD_STOP;
314b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        const int wres =
3155467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine            TEMP_FAILURE_RETRY(write(mThreadControl, &msg, sizeof(msg)));
316b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        if (wres == sizeof(msg)) {
317b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine            /* Stop the thread, and wait till it's terminated. */
318b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine            res = requestExitAndWait();
319b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine            if (res == NO_ERROR) {
320b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine                /* Close control FDs. */
3215467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine                if (mThreadControl >= 0) {
3225467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine                    close(mThreadControl);
3235467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine                    mThreadControl = -1;
324b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine                }
3255467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine                if (mControlFD >= 0) {
3265467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine                    close(mControlFD);
3275467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine                    mControlFD = -1;
328b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine                }
329629719e390ce66be822c3563bbd248ce15eaae7bSteve Block                ALOGV("Emulated camera device's worker thread has been stopped.");
330b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine            } else {
3315a622cba8c5287d5e6577f940a22343a7cae977fSteve Block                ALOGE("%s: requestExitAndWait failed: %d -> %s",
33249842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine                     __FUNCTION__, res, strerror(-res));
333b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine            }
334b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        } else {
3355a622cba8c5287d5e6577f940a22343a7cae977fSteve Block            ALOGE("%s: Unable to send THREAD_STOP message: %d -> %s",
336b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine                 __FUNCTION__, errno, strerror(errno));
337b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine            res = errno ? errno : EINVAL;
338b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        }
339b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    } else {
3405a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: Thread control FDs are not opened", __FUNCTION__);
341b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    }
342b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
343b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    return res;
344b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine}
345b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
346b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir ChtchetkineEmulatedCameraDevice::WorkerThread::SelectRes
347b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir ChtchetkineEmulatedCameraDevice::WorkerThread::Select(int fd, int timeout)
348b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine{
349b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    fd_set fds[1];
350b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    struct timeval tv, *tvp = NULL;
351b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
3525467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    const int fd_num = (fd >= 0) ? max(fd, mControlFD) + 1 :
3535467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine                                   mControlFD + 1;
354b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    FD_ZERO(fds);
3555467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    FD_SET(mControlFD, fds);
356b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    if (fd >= 0) {
357b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        FD_SET(fd, fds);
358b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    }
359b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    if (timeout) {
360b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        tv.tv_sec = timeout / 1000000;
361b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        tv.tv_usec = timeout % 1000000;
362b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        tvp = &tv;
363b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    }
364b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    int res = TEMP_FAILURE_RETRY(select(fd_num, fds, NULL, NULL, tvp));
365b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    if (res < 0) {
3665a622cba8c5287d5e6577f940a22343a7cae977fSteve Block        ALOGE("%s: select returned %d and failed: %d -> %s",
367b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine             __FUNCTION__, res, errno, strerror(errno));
368b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        return ERROR;
369b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    } else if (res == 0) {
370b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        /* Timeout. */
371b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        return TIMEOUT;
3725467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine    } else if (FD_ISSET(mControlFD, fds)) {
373b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        /* A control event. Lets read the message. */
374b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        ControlMessage msg;
3755467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine        res = TEMP_FAILURE_RETRY(read(mControlFD, &msg, sizeof(msg)));
376b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        if (res != sizeof(msg)) {
3775a622cba8c5287d5e6577f940a22343a7cae977fSteve Block            ALOGE("%s: Unexpected message size %d, or an error %d -> %s",
378b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine                 __FUNCTION__, res, errno, strerror(errno));
379b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine            return ERROR;
380b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        }
381b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        /* THREAD_STOP is the only message expected here. */
382b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        if (msg == THREAD_STOP) {
383629719e390ce66be822c3563bbd248ce15eaae7bSteve Block            ALOGV("%s: THREAD_STOP message is received", __FUNCTION__);
384b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine            return EXIT_THREAD;
385b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        } else {
3865a622cba8c5287d5e6577f940a22343a7cae977fSteve Block            ALOGE("Unknown worker thread message %d", msg);
387b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine            return ERROR;
388b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        }
389b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    } else {
390b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        /* Must be an FD. */
3916aff44c27ee487bd65d5a1c74faf4b7165530bd4Steve Block        ALOGW_IF(fd < 0 || !FD_ISSET(fd, fds), "%s: Undefined 'select' result",
392b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine                __FUNCTION__);
393b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine        return READY;
394b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine    }
395b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine}
396b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine
397b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine};  /* namespace android */
398