EmulatedCameraDevice.cpp revision 6ab39a68026a9a65dcdf190511bab50335a55d17
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>
31d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson#include "Alignment.h"
32dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson#include "EmulatedCamera.h"
338a94683196406b83b14218d1beef66067f126a16keunyoung#include "EmulatedCameraDevice.h"
348a94683196406b83b14218d1beef66067f126a16keunyoung
35d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson#undef min
36d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson#undef max
37d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson#include <algorithm>
3823fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson
398a94683196406b83b14218d1beef66067f126a16keunyoungnamespace android {
408a94683196406b83b14218d1beef66067f126a16keunyoung
418a94683196406b83b14218d1beef66067f126a16keunyoungconst float GAMMA_CORRECTION = 2.2f;
428a94683196406b83b14218d1beef66067f126a16keunyoungEmulatedCameraDevice::EmulatedCameraDevice(EmulatedCamera* camera_hal)
438a94683196406b83b14218d1beef66067f126a16keunyoung    : mObjectLock(),
448a94683196406b83b14218d1beef66067f126a16keunyoung      mCameraHAL(camera_hal),
458a94683196406b83b14218d1beef66067f126a16keunyoung      mExposureCompensation(1.0f),
468a94683196406b83b14218d1beef66067f126a16keunyoung      mWhiteBalanceScale(NULL),
478a94683196406b83b14218d1beef66067f126a16keunyoung      mSupportedWhiteBalanceScale(),
48dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson      mState(ECDS_CONSTRUCTED),
49dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson      mTriggerAutoFocus(false)
508a94683196406b83b14218d1beef66067f126a16keunyoung{
518a94683196406b83b14218d1beef66067f126a16keunyoung}
528a94683196406b83b14218d1beef66067f126a16keunyoung
538a94683196406b83b14218d1beef66067f126a16keunyoungEmulatedCameraDevice::~EmulatedCameraDevice()
548a94683196406b83b14218d1beef66067f126a16keunyoung{
558a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGV("EmulatedCameraDevice destructor");
563725c7c982eac52ec64a625e82f306822452941cColin Cross    for (size_t i = 0; i < mSupportedWhiteBalanceScale.size(); ++i) {
578a94683196406b83b14218d1beef66067f126a16keunyoung        if (mSupportedWhiteBalanceScale.valueAt(i) != NULL) {
588a94683196406b83b14218d1beef66067f126a16keunyoung            delete[] mSupportedWhiteBalanceScale.valueAt(i);
598a94683196406b83b14218d1beef66067f126a16keunyoung        }
608a94683196406b83b14218d1beef66067f126a16keunyoung    }
618a94683196406b83b14218d1beef66067f126a16keunyoung}
628a94683196406b83b14218d1beef66067f126a16keunyoung
638a94683196406b83b14218d1beef66067f126a16keunyoung/****************************************************************************
648a94683196406b83b14218d1beef66067f126a16keunyoung * Emulated camera device public API
658a94683196406b83b14218d1beef66067f126a16keunyoung ***************************************************************************/
668a94683196406b83b14218d1beef66067f126a16keunyoung
678a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedCameraDevice::Initialize()
688a94683196406b83b14218d1beef66067f126a16keunyoung{
698a94683196406b83b14218d1beef66067f126a16keunyoung    if (isInitialized()) {
708a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGW("%s: Emulated camera device is already initialized: mState = %d",
718a94683196406b83b14218d1beef66067f126a16keunyoung             __FUNCTION__, mState);
728a94683196406b83b14218d1beef66067f126a16keunyoung        return NO_ERROR;
738a94683196406b83b14218d1beef66067f126a16keunyoung    }
748a94683196406b83b14218d1beef66067f126a16keunyoung
758a94683196406b83b14218d1beef66067f126a16keunyoung    mState = ECDS_INITIALIZED;
768a94683196406b83b14218d1beef66067f126a16keunyoung
778a94683196406b83b14218d1beef66067f126a16keunyoung    return NO_ERROR;
788a94683196406b83b14218d1beef66067f126a16keunyoung}
798a94683196406b83b14218d1beef66067f126a16keunyoung
808a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedCameraDevice::startDeliveringFrames(bool one_burst)
818a94683196406b83b14218d1beef66067f126a16keunyoung{
828a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGV("%s", __FUNCTION__);
838a94683196406b83b14218d1beef66067f126a16keunyoung
848a94683196406b83b14218d1beef66067f126a16keunyoung    if (!isStarted()) {
858a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGE("%s: Device is not started", __FUNCTION__);
868a94683196406b83b14218d1beef66067f126a16keunyoung        return EINVAL;
878a94683196406b83b14218d1beef66067f126a16keunyoung    }
888a94683196406b83b14218d1beef66067f126a16keunyoung
898a94683196406b83b14218d1beef66067f126a16keunyoung    /* Frames will be delivered from the thread routine. */
90d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    const status_t res = startWorkerThread(one_burst);
91d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    ALOGE_IF(res != NO_ERROR, "%s: startWorkerThread failed", __FUNCTION__);
928a94683196406b83b14218d1beef66067f126a16keunyoung    return res;
938a94683196406b83b14218d1beef66067f126a16keunyoung}
948a94683196406b83b14218d1beef66067f126a16keunyoung
958a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedCameraDevice::stopDeliveringFrames()
968a94683196406b83b14218d1beef66067f126a16keunyoung{
978a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGV("%s", __FUNCTION__);
988a94683196406b83b14218d1beef66067f126a16keunyoung
998a94683196406b83b14218d1beef66067f126a16keunyoung    if (!isStarted()) {
1008a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGW("%s: Device is not started", __FUNCTION__);
1018a94683196406b83b14218d1beef66067f126a16keunyoung        return NO_ERROR;
1028a94683196406b83b14218d1beef66067f126a16keunyoung    }
1038a94683196406b83b14218d1beef66067f126a16keunyoung
104d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    const status_t res = stopWorkerThread();
105d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    ALOGE_IF(res != NO_ERROR, "%s: stopWorkerThread failed", __FUNCTION__);
1068a94683196406b83b14218d1beef66067f126a16keunyoung    return res;
1078a94683196406b83b14218d1beef66067f126a16keunyoung}
1088a94683196406b83b14218d1beef66067f126a16keunyoung
109d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johanssonstatus_t EmulatedCameraDevice::setPreviewFrameRate(int framesPerSecond) {
110d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    if (framesPerSecond <= 0) {
111d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        return EINVAL;
112d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    }
113d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    mFramesPerSecond = framesPerSecond;
114d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    return NO_ERROR;
115d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson}
116d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
1178a94683196406b83b14218d1beef66067f126a16keunyoungvoid EmulatedCameraDevice::setExposureCompensation(const float ev) {
1188a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGV("%s", __FUNCTION__);
1198a94683196406b83b14218d1beef66067f126a16keunyoung
1208a94683196406b83b14218d1beef66067f126a16keunyoung    if (!isStarted()) {
1218a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGW("%s: Fake camera device is not started.", __FUNCTION__);
1228a94683196406b83b14218d1beef66067f126a16keunyoung    }
1238a94683196406b83b14218d1beef66067f126a16keunyoung
1248a94683196406b83b14218d1beef66067f126a16keunyoung    mExposureCompensation = std::pow(2.0f, ev / GAMMA_CORRECTION);
1258a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGV("New exposure compensation is %f", mExposureCompensation);
1268a94683196406b83b14218d1beef66067f126a16keunyoung}
1278a94683196406b83b14218d1beef66067f126a16keunyoung
1288a94683196406b83b14218d1beef66067f126a16keunyoungvoid EmulatedCameraDevice::initializeWhiteBalanceModes(const char* mode,
1298a94683196406b83b14218d1beef66067f126a16keunyoung                                                       const float r_scale,
1308a94683196406b83b14218d1beef66067f126a16keunyoung                                                       const float b_scale) {
1318a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGV("%s with %s, %f, %f", __FUNCTION__, mode, r_scale, b_scale);
1328a94683196406b83b14218d1beef66067f126a16keunyoung    float* value = new float[3];
1338a94683196406b83b14218d1beef66067f126a16keunyoung    value[0] = r_scale; value[1] = 1.0f; value[2] = b_scale;
1348a94683196406b83b14218d1beef66067f126a16keunyoung    mSupportedWhiteBalanceScale.add(String8(mode), value);
1358a94683196406b83b14218d1beef66067f126a16keunyoung}
1368a94683196406b83b14218d1beef66067f126a16keunyoung
1378a94683196406b83b14218d1beef66067f126a16keunyoungvoid EmulatedCameraDevice::setWhiteBalanceMode(const char* mode) {
1388a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGV("%s with white balance %s", __FUNCTION__, mode);
1398a94683196406b83b14218d1beef66067f126a16keunyoung    mWhiteBalanceScale =
1408a94683196406b83b14218d1beef66067f126a16keunyoung            mSupportedWhiteBalanceScale.valueFor(String8(mode));
1418a94683196406b83b14218d1beef66067f126a16keunyoung}
1428a94683196406b83b14218d1beef66067f126a16keunyoung
1438a94683196406b83b14218d1beef66067f126a16keunyoung/* Computes the pixel value after adjusting the white balance to the current
1448a94683196406b83b14218d1beef66067f126a16keunyoung * one. The input the y, u, v channel of the pixel and the adjusted value will
1458a94683196406b83b14218d1beef66067f126a16keunyoung * be stored in place. The adjustment is done in RGB space.
1468a94683196406b83b14218d1beef66067f126a16keunyoung */
1478a94683196406b83b14218d1beef66067f126a16keunyoungvoid EmulatedCameraDevice::changeWhiteBalance(uint8_t& y,
1488a94683196406b83b14218d1beef66067f126a16keunyoung                                              uint8_t& u,
1498a94683196406b83b14218d1beef66067f126a16keunyoung                                              uint8_t& v) const {
1508a94683196406b83b14218d1beef66067f126a16keunyoung    float r_scale = mWhiteBalanceScale[0];
1518a94683196406b83b14218d1beef66067f126a16keunyoung    float b_scale = mWhiteBalanceScale[2];
1528a94683196406b83b14218d1beef66067f126a16keunyoung    int r = static_cast<float>(YUV2R(y, u, v)) / r_scale;
1538a94683196406b83b14218d1beef66067f126a16keunyoung    int g = YUV2G(y, u, v);
1548a94683196406b83b14218d1beef66067f126a16keunyoung    int b = static_cast<float>(YUV2B(y, u, v)) / b_scale;
1558a94683196406b83b14218d1beef66067f126a16keunyoung
1568a94683196406b83b14218d1beef66067f126a16keunyoung    y = RGB2Y(r, g, b);
1578a94683196406b83b14218d1beef66067f126a16keunyoung    u = RGB2U(r, g, b);
1588a94683196406b83b14218d1beef66067f126a16keunyoung    v = RGB2V(r, g, b);
1598a94683196406b83b14218d1beef66067f126a16keunyoung}
1608a94683196406b83b14218d1beef66067f126a16keunyoung
161dac82a5541140e3de6a20223530a406be4828b87Bjoern Johanssonvoid EmulatedCameraDevice::checkAutoFocusTrigger() {
162dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson    // The expected value is a reference so we need it to be a variable
163dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson    bool expectedTrigger = true;
164dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson    if (mTriggerAutoFocus.compare_exchange_strong(expectedTrigger, false)) {
165dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson        // If the compare exchange returns true then the value was the expected
166dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson        // 'true' and was successfully set to 'false'. So that means it's time
167dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson        // to trigger an auto-focus event and that we have disabled that trigger
168dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson        // so it won't happen until another request is received.
169dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson        mCameraHAL->autoFocusComplete();
170dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson    }
171dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson}
172dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson
1736ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johanssonstatus_t EmulatedCameraDevice::getCurrentFrameImpl(const void* source,
1746ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson                                                   void* dest,
1756ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson                                                   uint32_t pixelFormat) const {
1766ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson    if (pixelFormat == mPixelFormat) {
1776ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson        memcpy(dest, source, mFrameBufferSize);
1786ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson        return NO_ERROR;
1796ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson    } else if (pixelFormat == V4L2_PIX_FMT_YUV420 &&
1806ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson               mPixelFormat == V4L2_PIX_FMT_YVU420) {
1816ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson        // Convert from YV12 to YU12
1826ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson        const int ySize = mYStride * mFrameHeight;
1836ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson        const int uvSize = mUVStride * (mFrameHeight / 2);
1846ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson        // Copy Y straight up
1856ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson        memcpy(dest, source, ySize);
1866ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson        // Swap U and V
1876ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson        memcpy(reinterpret_cast<uint8_t*>(dest) + ySize,
1886ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson               reinterpret_cast<const uint8_t*>(source) + ySize + uvSize,
1896ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson               uvSize);
1906ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson        memcpy(reinterpret_cast<uint8_t*>(dest) + ySize + uvSize,
1916ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson               reinterpret_cast<const uint8_t*>(source) + ySize,
1926ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson               uvSize);
1936ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson        return NO_ERROR;
1946ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson    }
1956ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson    ALOGE("%s: Invalid pixel format conversion [%.4s to %.4s] requested",
1966ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson          __FUNCTION__, reinterpret_cast<const char*>(&mPixelFormat),
1976ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson          reinterpret_cast<const char*>(&pixelFormat));
1986ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson    return EINVAL;
1996ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson}
2006ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson
2016ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johanssonstatus_t EmulatedCameraDevice::getCurrentFrame(void* buffer,
2026ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson                                               uint32_t pixelFormat)
203d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson{
204d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    if (!isStarted()) {
205d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        ALOGE("%s: Device is not started", __FUNCTION__);
206d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        return EINVAL;
207d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    }
208d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    if (buffer == nullptr) {
209d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        ALOGE("%s: Invalid buffer provided", __FUNCTION__);
210d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        return EINVAL;
211d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    }
212d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
213d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    FrameLock lock(*this);
214d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    const void* source = mCameraThread->getPrimaryBuffer();
215d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    if (source == nullptr) {
216d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        ALOGE("%s: No framebuffer", __FUNCTION__);
217d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        return EINVAL;
218d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    }
2196ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson    return getCurrentFrameImpl(source, buffer, pixelFormat);
220d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    return NO_ERROR;
221d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson}
222d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
2238a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedCameraDevice::getCurrentPreviewFrame(void* buffer)
2248a94683196406b83b14218d1beef66067f126a16keunyoung{
2258a94683196406b83b14218d1beef66067f126a16keunyoung    if (!isStarted()) {
2268a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGE("%s: Device is not started", __FUNCTION__);
2278a94683196406b83b14218d1beef66067f126a16keunyoung        return EINVAL;
2288a94683196406b83b14218d1beef66067f126a16keunyoung    }
229d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    if (buffer == nullptr) {
230d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        ALOGE("%s: Invalid buffer provided", __FUNCTION__);
231d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        return EINVAL;
232d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    }
233d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
234d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    FrameLock lock(*this);
235d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    const void* currentFrame = mCameraThread->getPrimaryBuffer();
236d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    if (currentFrame == nullptr) {
2378a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGE("%s: No framebuffer", __FUNCTION__);
2388a94683196406b83b14218d1beef66067f126a16keunyoung        return EINVAL;
2398a94683196406b83b14218d1beef66067f126a16keunyoung    }
2408a94683196406b83b14218d1beef66067f126a16keunyoung
2418a94683196406b83b14218d1beef66067f126a16keunyoung    /* In emulation the framebuffer is never RGB. */
2428a94683196406b83b14218d1beef66067f126a16keunyoung    switch (mPixelFormat) {
2438a94683196406b83b14218d1beef66067f126a16keunyoung        case V4L2_PIX_FMT_YVU420:
244d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson            YV12ToRGB32(currentFrame, buffer, mFrameWidth, mFrameHeight);
2458a94683196406b83b14218d1beef66067f126a16keunyoung            return NO_ERROR;
2468a94683196406b83b14218d1beef66067f126a16keunyoung        case V4L2_PIX_FMT_YUV420:
247d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson            YU12ToRGB32(currentFrame, buffer, mFrameWidth, mFrameHeight);
2488a94683196406b83b14218d1beef66067f126a16keunyoung            return NO_ERROR;
2498a94683196406b83b14218d1beef66067f126a16keunyoung        case V4L2_PIX_FMT_NV21:
250d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson            NV21ToRGB32(currentFrame, buffer, mFrameWidth, mFrameHeight);
2518a94683196406b83b14218d1beef66067f126a16keunyoung            return NO_ERROR;
2528a94683196406b83b14218d1beef66067f126a16keunyoung        case V4L2_PIX_FMT_NV12:
253d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson            NV12ToRGB32(currentFrame, buffer, mFrameWidth, mFrameHeight);
2548a94683196406b83b14218d1beef66067f126a16keunyoung            return NO_ERROR;
2558a94683196406b83b14218d1beef66067f126a16keunyoung
2568a94683196406b83b14218d1beef66067f126a16keunyoung        default:
2578a94683196406b83b14218d1beef66067f126a16keunyoung            ALOGE("%s: Unknown pixel format %.4s",
2588a94683196406b83b14218d1beef66067f126a16keunyoung                 __FUNCTION__, reinterpret_cast<const char*>(&mPixelFormat));
2598a94683196406b83b14218d1beef66067f126a16keunyoung            return EINVAL;
2608a94683196406b83b14218d1beef66067f126a16keunyoung    }
2618a94683196406b83b14218d1beef66067f126a16keunyoung}
2628a94683196406b83b14218d1beef66067f126a16keunyoung
263d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johanssonconst void* EmulatedCameraDevice::getCurrentFrame() {
264d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    if (mCameraThread.get()) {
265d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        return mCameraThread->getPrimaryBuffer();
266d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    }
267d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    return nullptr;
268d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson}
269d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
270d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern JohanssonEmulatedCameraDevice::FrameLock::FrameLock(EmulatedCameraDevice& cameraDevice)
271d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    : mCameraDevice(cameraDevice) {
272d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        mCameraDevice.lockCurrentFrame();
273d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson}
274d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
275d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern JohanssonEmulatedCameraDevice::FrameLock::~FrameLock() {
276d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    mCameraDevice.unlockCurrentFrame();
277d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson}
278d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
279dac82a5541140e3de6a20223530a406be4828b87Bjoern Johanssonstatus_t EmulatedCameraDevice::setAutoFocus() {
280dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson    mTriggerAutoFocus = true;
281dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson    return NO_ERROR;
282dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson}
283dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson
284dac82a5541140e3de6a20223530a406be4828b87Bjoern Johanssonstatus_t EmulatedCameraDevice::cancelAutoFocus() {
285dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson    mTriggerAutoFocus = false;
286dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson    return NO_ERROR;
287dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson}
288dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson
289d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonbool EmulatedCameraDevice::requestRestart(int width, int height,
290d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson                                          uint32_t pixelFormat,
291d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson                                          bool takingPicture, bool oneBurst) {
292d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    if (mCameraThread.get() == nullptr) {
293d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        ALOGE("%s: No thread alive to perform the restart, is preview on?",
294d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson              __FUNCTION__);
295d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        return false;
296d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    }
297d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mCameraThread->requestRestart(width, height, pixelFormat,
298d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson                                  takingPicture, oneBurst);
299d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    return true;
300d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson}
301d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson
3028a94683196406b83b14218d1beef66067f126a16keunyoung/****************************************************************************
3038a94683196406b83b14218d1beef66067f126a16keunyoung * Emulated camera device private API
3048a94683196406b83b14218d1beef66067f126a16keunyoung ***************************************************************************/
3058a94683196406b83b14218d1beef66067f126a16keunyoung
3068a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedCameraDevice::commonStartDevice(int width,
3078a94683196406b83b14218d1beef66067f126a16keunyoung                                                 int height,
3088a94683196406b83b14218d1beef66067f126a16keunyoung                                                 uint32_t pix_fmt)
3098a94683196406b83b14218d1beef66067f126a16keunyoung{
3108a94683196406b83b14218d1beef66067f126a16keunyoung    /* Validate pixel format, and calculate framebuffer size at the same time. */
3118a94683196406b83b14218d1beef66067f126a16keunyoung    switch (pix_fmt) {
3128a94683196406b83b14218d1beef66067f126a16keunyoung        case V4L2_PIX_FMT_YVU420:
3138a94683196406b83b14218d1beef66067f126a16keunyoung        case V4L2_PIX_FMT_YUV420:
31423fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            // For these pixel formats the strides have to be aligned to 16 byte
31523fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            // boundaries as per the format specification
31623fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            // https://developer.android.com/reference/android/graphics/ImageFormat.html#YV12
31723fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            mYStride = align(width, 16);
31823fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            mUVStride = align(mYStride / 2, 16);
31923fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            // The second term should use half the height but since there are
32023fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            // two planes the multiplication with two cancels that out
32123fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            mFrameBufferSize = mYStride * height + mUVStride * height;
32223fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            break;
3238a94683196406b83b14218d1beef66067f126a16keunyoung        case V4L2_PIX_FMT_NV21:
3248a94683196406b83b14218d1beef66067f126a16keunyoung        case V4L2_PIX_FMT_NV12:
32523fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            mYStride = width;
32623fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            // Because of interleaving the UV stride is the same as the Y stride
32723fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            // since it covers two pixels, one U and one V.
32823fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            mUVStride = mYStride;
32923fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            // Since the U/V stride covers both U and V we don't multiply by two
33023fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            mFrameBufferSize = mYStride * height + mUVStride * (height / 2);
3318a94683196406b83b14218d1beef66067f126a16keunyoung            break;
3328a94683196406b83b14218d1beef66067f126a16keunyoung        default:
3338a94683196406b83b14218d1beef66067f126a16keunyoung            ALOGE("%s: Unknown pixel format %.4s",
3348a94683196406b83b14218d1beef66067f126a16keunyoung                 __FUNCTION__, reinterpret_cast<const char*>(&pix_fmt));
3358a94683196406b83b14218d1beef66067f126a16keunyoung            return EINVAL;
3368a94683196406b83b14218d1beef66067f126a16keunyoung    }
3378a94683196406b83b14218d1beef66067f126a16keunyoung
3388a94683196406b83b14218d1beef66067f126a16keunyoung    /* Cache framebuffer info. */
3398a94683196406b83b14218d1beef66067f126a16keunyoung    mFrameWidth = width;
3408a94683196406b83b14218d1beef66067f126a16keunyoung    mFrameHeight = height;
3418a94683196406b83b14218d1beef66067f126a16keunyoung    mPixelFormat = pix_fmt;
3428a94683196406b83b14218d1beef66067f126a16keunyoung    mTotalPixels = width * height;
3438a94683196406b83b14218d1beef66067f126a16keunyoung
3448a94683196406b83b14218d1beef66067f126a16keunyoung    /* Allocate framebuffer. */
345d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    mFrameBuffers[0].resize(mFrameBufferSize);
346d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    mFrameBuffers[1].resize(mFrameBufferSize);
347d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    ALOGV("%s: Allocated %zu bytes for %d pixels in %.4s[%dx%d] frame",
348d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson         __FUNCTION__, mFrameBufferSize, mTotalPixels,
3498a94683196406b83b14218d1beef66067f126a16keunyoung         reinterpret_cast<const char*>(&mPixelFormat), mFrameWidth, mFrameHeight);
3508a94683196406b83b14218d1beef66067f126a16keunyoung    return NO_ERROR;
3518a94683196406b83b14218d1beef66067f126a16keunyoung}
3528a94683196406b83b14218d1beef66067f126a16keunyoung
3538a94683196406b83b14218d1beef66067f126a16keunyoungvoid EmulatedCameraDevice::commonStopDevice()
3548a94683196406b83b14218d1beef66067f126a16keunyoung{
3558a94683196406b83b14218d1beef66067f126a16keunyoung    mFrameWidth = mFrameHeight = mTotalPixels = 0;
3568a94683196406b83b14218d1beef66067f126a16keunyoung    mPixelFormat = 0;
3578a94683196406b83b14218d1beef66067f126a16keunyoung
358d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    mFrameBuffers[0].clear();
359d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    mFrameBuffers[1].clear();
360d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    // No need to keep all that memory allocated if the camera isn't running
361d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    mFrameBuffers[0].shrink_to_fit();
362d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    mFrameBuffers[1].shrink_to_fit();
3638a94683196406b83b14218d1beef66067f126a16keunyoung}
3648a94683196406b83b14218d1beef66067f126a16keunyoung
3658a94683196406b83b14218d1beef66067f126a16keunyoung/****************************************************************************
3668a94683196406b83b14218d1beef66067f126a16keunyoung * Worker thread management.
3678a94683196406b83b14218d1beef66067f126a16keunyoung ***************************************************************************/
3688a94683196406b83b14218d1beef66067f126a16keunyoung
369d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonstatus_t EmulatedCameraDevice::startWorkerThread(bool one_burst)
3708a94683196406b83b14218d1beef66067f126a16keunyoung{
3718a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGV("%s", __FUNCTION__);
3728a94683196406b83b14218d1beef66067f126a16keunyoung
3738a94683196406b83b14218d1beef66067f126a16keunyoung    if (!isInitialized()) {
3748a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGE("%s: Emulated camera device is not initialized", __FUNCTION__);
3758a94683196406b83b14218d1beef66067f126a16keunyoung        return EINVAL;
3768a94683196406b83b14218d1beef66067f126a16keunyoung    }
3778a94683196406b83b14218d1beef66067f126a16keunyoung
378d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mCameraThread = new CameraThread(this, staticProduceFrame, this);
379d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    if (mCameraThread == NULL) {
380d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        ALOGE("%s: Unable to instantiate CameraThread object", __FUNCTION__);
381d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        return ENOMEM;
382d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    }
383d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    status_t res = mCameraThread->startThread(one_burst);
384d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    if (res != NO_ERROR) {
385d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        ALOGE("%s: Unable to start CameraThread: %s",
386d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson              __FUNCTION__, strerror(res));
387d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        return res;
388d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    }
389d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
3908a94683196406b83b14218d1beef66067f126a16keunyoung    return res;
3918a94683196406b83b14218d1beef66067f126a16keunyoung}
3928a94683196406b83b14218d1beef66067f126a16keunyoung
393d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonstatus_t EmulatedCameraDevice::stopWorkerThread()
3948a94683196406b83b14218d1beef66067f126a16keunyoung{
3958a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGV("%s", __FUNCTION__);
3968a94683196406b83b14218d1beef66067f126a16keunyoung
3978a94683196406b83b14218d1beef66067f126a16keunyoung    if (!isInitialized()) {
3988a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGE("%s: Emulated camera device is not initialized", __FUNCTION__);
3998a94683196406b83b14218d1beef66067f126a16keunyoung        return EINVAL;
4008a94683196406b83b14218d1beef66067f126a16keunyoung    }
4018a94683196406b83b14218d1beef66067f126a16keunyoung
402d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    status_t res = mCameraThread->stopThread();
403d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    if (res != NO_ERROR) {
404d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        ALOGE("%s: Unable to stop CameraThread", __FUNCTION__);
405d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        return res;
406d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    }
407d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    res = mCameraThread->joinThread();
408d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    if (res != NO_ERROR) {
409d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        ALOGE("%s: Unable to join CameraThread", __FUNCTION__);
410d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        return res;
411d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    }
412d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
413d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    // Destroy the thread as well
414d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mCameraThread.clear();
4158a94683196406b83b14218d1beef66067f126a16keunyoung    return res;
4168a94683196406b83b14218d1beef66067f126a16keunyoung}
4178a94683196406b83b14218d1beef66067f126a16keunyoung
418d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern JohanssonEmulatedCameraDevice::CameraThread::CameraThread(EmulatedCameraDevice* dev,
419d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson                                                 ProduceFrameFunc producer,
420d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson                                                 void* producerOpaque)
421d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    : WorkerThread("Camera_CameraThread", dev, dev->mCameraHAL),
422d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson      mCurFrameTimestamp(0),
423d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson      mProducerFunc(producer),
424d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson      mProducerOpaque(producerOpaque),
425d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson      mRestartWidth(0),
426d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson      mRestartHeight(0),
427d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson      mRestartPixelFormat(0),
428d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson      mRestartOneBurst(false),
429d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson      mRestartTakingPicture(false),
430d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson      mRestartRequested(false) {
431d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
4328a94683196406b83b14218d1beef66067f126a16keunyoung}
4338a94683196406b83b14218d1beef66067f126a16keunyoung
434d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonconst void* EmulatedCameraDevice::CameraThread::getPrimaryBuffer() const {
435d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    if (mFrameProducer.get()) {
436d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        return mFrameProducer->getPrimaryBuffer();
437d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    }
438d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    return nullptr;
439d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson}
440d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson
441d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonvoid EmulatedCameraDevice::CameraThread::lockPrimaryBuffer() {
442d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mFrameProducer->lockPrimaryBuffer();
443d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson}
444d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson
445d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonvoid EmulatedCameraDevice::CameraThread::unlockPrimaryBuffer() {
446d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mFrameProducer->unlockPrimaryBuffer();
447d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson}
448d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
449d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonbool
450d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern JohanssonEmulatedCameraDevice::CameraThread::waitForFrameOrTimeout(nsecs_t timeout) {
451d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    // Keep waiting until the frame producer indicates that a frame is available
452d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    // This does introduce some unnecessary latency to the first frame delivery
453d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    // but avoids a lot of thread synchronization.
454d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    do {
455d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        // We don't have any specific fd we want to select so we pass in -1
456d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        // timeout is in nanoseconds but Select expects microseconds
457d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        Mutex::Autolock lock(mRunningMutex);
458d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        mRunningCondition.waitRelative(mRunningMutex, timeout);
459d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        if (!mRunning) {
460d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            ALOGV("%s: CameraThread has been terminated.", __FUNCTION__);
461d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson            return false;
462d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        }
463d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        // Set a short timeout in case there is no frame available and we are
464d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        // going to loop. This way we ensure a sleep but keep a decent latency
465d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        timeout = milliseconds(5);
466d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    } while (!mFrameProducer->hasFrame());
4678a94683196406b83b14218d1beef66067f126a16keunyoung
468d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    return true;
469d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson}
470d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson
471d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonbool EmulatedCameraDevice::CameraThread::inWorkerThread() {
472d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    /* Wait till FPS timeout expires, or thread exit message is received. */
473d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    nsecs_t wakeAt =
474d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        mCurFrameTimestamp + 1000000000.0 / mCameraDevice->mFramesPerSecond;
475d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
476d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    nsecs_t timeout = std::max<nsecs_t>(0, wakeAt - now);
477d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson
478d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    if (!waitForFrameOrTimeout(timeout)) {
479d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        return false;
480d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    }
481d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson
482d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    /* Check if a restart and potentially apply the requested changes */
483d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    if (!checkRestartRequest()) {
484d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        return false;
485d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    }
486d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson
487d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    /* Check if an auto-focus event needs to be triggered */
488d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    mCameraDevice->checkAutoFocusTrigger();
489d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
490d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    mCurFrameTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
491d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mCameraHAL->onNextFrameAvailable(mCurFrameTimestamp, mCameraDevice);
492b3f642f2a22cd58e64e0dc6326e946ef7fd7589fDouglas Leung
493d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    return true;
4948a94683196406b83b14218d1beef66067f126a16keunyoung}
4958a94683196406b83b14218d1beef66067f126a16keunyoung
496d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonstatus_t EmulatedCameraDevice::CameraThread::onThreadStart() {
497d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    void* primaryBuffer = mCameraDevice->getPrimaryBuffer();
498d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    void* secondaryBuffer = mCameraDevice->getSecondaryBuffer();
499d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mFrameProducer = new FrameProducer(mCameraDevice,
500d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson                                       mProducerFunc, mProducerOpaque,
501d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson                                       primaryBuffer, secondaryBuffer);
502d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    if (mFrameProducer.get() == nullptr) {
503d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        ALOGE("%s: Could not instantiate FrameProducer object", __FUNCTION__);
504d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        return ENOMEM;
505d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    }
506d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    return mFrameProducer->startThread(mOneBurst);
507d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson}
508d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson
509d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonvoid EmulatedCameraDevice::CameraThread::onThreadExit() {
510d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    if (mFrameProducer.get()) {
511d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        if (mFrameProducer->stopThread() == NO_ERROR) {
512d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            mFrameProducer->joinThread();
513d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            mFrameProducer.clear();
514d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        }
515d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    }
516d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson}
517d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson
518d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern JohanssonEmulatedCameraDevice::CameraThread::FrameProducer::FrameProducer(
519d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        EmulatedCameraDevice* dev,
520d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        ProduceFrameFunc producer,
521d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        void* opaque,
522d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        void* primaryBuffer,
523d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        void* secondaryBuffer)
524d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    : WorkerThread("Camera_FrameProducer", dev, dev->mCameraHAL),
525d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson      mProducer(producer),
526d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson      mOpaque(opaque),
527d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson      mPrimaryBuffer(primaryBuffer),
528d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson      mSecondaryBuffer(secondaryBuffer),
529d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson      mLastFrame(0),
530d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson      mHasFrame(false) {
5318a94683196406b83b14218d1beef66067f126a16keunyoung
532d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson}
533b3f642f2a22cd58e64e0dc6326e946ef7fd7589fDouglas Leung
534d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonconst void*
535d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern JohanssonEmulatedCameraDevice::CameraThread::FrameProducer::getPrimaryBuffer() const {
536d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    return mPrimaryBuffer;
537d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson}
538d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
539d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonvoid EmulatedCameraDevice::CameraThread::FrameProducer::lockPrimaryBuffer() {
540d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    mBufferMutex.lock();
541d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson}
542d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonvoid EmulatedCameraDevice::CameraThread::FrameProducer::unlockPrimaryBuffer() {
543d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    mBufferMutex.unlock();
544d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson}
545d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
546d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonvoid EmulatedCameraDevice::CameraThread::requestRestart(int width,
547d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson                                                        int height,
548d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson                                                        uint32_t pixelFormat,
549d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson                                                        bool takingPicture,
550d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson                                                        bool oneBurst) {
551d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    Mutex::Autolock lock(mRequestMutex);
552d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mRestartWidth = width;
553d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mRestartHeight = height;
554d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mRestartPixelFormat = pixelFormat;
555d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mRestartTakingPicture = takingPicture;
556d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mRestartOneBurst = oneBurst;
557d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mRestartRequested = true;
558d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson}
559d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson
560d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonbool EmulatedCameraDevice::CameraThread::FrameProducer::hasFrame() const {
561d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    return mHasFrame;
562d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson}
563d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
564d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonbool EmulatedCameraDevice::CameraThread::checkRestartRequest() {
565d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    Mutex::Autolock lock(mRequestMutex);
566d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    if (mRestartRequested) {
567d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        mRestartRequested = false;
568d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        status_t res = mFrameProducer->stopThread();
569d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        if (res != NO_ERROR) {
570d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            ALOGE("%s: Could not stop frame producer thread", __FUNCTION__);
571d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            mCameraHAL->onCameraDeviceError(CAMERA_ERROR_SERVER_DIED);
572d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            return false;
573d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        }
574d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        res = mFrameProducer->joinThread();
575d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        if (res != NO_ERROR) {
576d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            ALOGE("%s: Could not join frame producer thread", __FUNCTION__);
577d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            mCameraHAL->onCameraDeviceError(CAMERA_ERROR_SERVER_DIED);
578d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            return false;
579d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        }
580d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        mFrameProducer.clear();
581d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        res = mCameraDevice->stopDevice();
582d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        if (res != NO_ERROR) {
583d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            ALOGE("%s: Could not stop device", __FUNCTION__);
584d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            mCameraHAL->onCameraDeviceError(CAMERA_ERROR_SERVER_DIED);
585d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            return false;
586d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        }
587d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        res = mCameraDevice->startDevice(mRestartWidth,
588d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson                                         mRestartHeight,
589d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson                                         mRestartPixelFormat);
590d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        if (res != NO_ERROR) {
591d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            ALOGE("%s: Could not start device", __FUNCTION__);
592d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            mCameraHAL->onCameraDeviceError(CAMERA_ERROR_SERVER_DIED);
593d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            return false;
594d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        }
595d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        if (mRestartTakingPicture) {
596d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            mCameraHAL->setTakingPicture(true);
597d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        }
598d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        mOneBurst = mRestartOneBurst;
599d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson
600d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        // Pretend like this a thread start, performs the remaining setup
601d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        if (onThreadStart() != NO_ERROR) {
602d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            mCameraDevice->stopDevice();
603d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            mCameraHAL->onCameraDeviceError(CAMERA_ERROR_SERVER_DIED);
604d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            return false;
605d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        }
606d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson
607d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        // Now wait for the frame producer to start producing before we proceed
608d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        return waitForFrameOrTimeout(0);
609d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    }
610d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    return true;
611d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson}
612d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson
613d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonbool EmulatedCameraDevice::CameraThread::FrameProducer::inWorkerThread() {
614d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    nsecs_t nextFrame =
615d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        mLastFrame + 1000000000 / mCameraDevice->mFramesPerSecond;
616d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
617d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    nsecs_t timeout = std::max<nsecs_t>(0, nextFrame - now);
618d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
619d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    {
620d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        Mutex::Autolock lock(mRunningMutex);
621d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        mRunningCondition.waitRelative(mRunningMutex, timeout);
622d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        if (!mRunning) {
623d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            ALOGV("%s: FrameProducer has been terminated.", __FUNCTION__);
624d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            return false;
625d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        }
626b3f642f2a22cd58e64e0dc6326e946ef7fd7589fDouglas Leung    }
627b3f642f2a22cd58e64e0dc6326e946ef7fd7589fDouglas Leung
628d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    // Produce one frame and place it in the secondary buffer
629d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    mLastFrame = systemTime(SYSTEM_TIME_MONOTONIC);
630d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    if (!mProducer(mOpaque, mSecondaryBuffer)) {
631d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        ALOGE("FrameProducer could not produce frame, exiting thread");
632d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        mCameraHAL->onCameraDeviceError(CAMERA_ERROR_SERVER_DIED);
633d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        return false;
6348a94683196406b83b14218d1beef66067f126a16keunyoung    }
6358a94683196406b83b14218d1beef66067f126a16keunyoung
636d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    {
637d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        // Switch buffers now that the secondary buffer is ready
638d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        Mutex::Autolock lock(mBufferMutex);
639d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        std::swap(mPrimaryBuffer, mSecondaryBuffer);
640d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    }
641d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    mHasFrame = true;
642d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    return true;
6438a94683196406b83b14218d1beef66067f126a16keunyoung}
6448a94683196406b83b14218d1beef66067f126a16keunyoung
645d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johanssonvoid EmulatedCameraDevice::lockCurrentFrame() {
646d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mCameraThread->lockPrimaryBuffer();
647d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson}
648d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
649d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johanssonvoid EmulatedCameraDevice::unlockCurrentFrame() {
650d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mCameraThread->unlockPrimaryBuffer();
6518a94683196406b83b14218d1beef66067f126a16keunyoung}
6528a94683196406b83b14218d1beef66067f126a16keunyoung
6538a94683196406b83b14218d1beef66067f126a16keunyoung};  /* namespace android */
654