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
1732d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johanssonstatus_t EmulatedCameraDevice::getCurrentFrameImpl(const uint8_t* source,
1742d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson                                                   uint8_t* 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) {
1812d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson        // Convert from YV12 to YUV420 without alignment
1826ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson        const int ySize = mYStride * mFrameHeight;
1836ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson        const int uvSize = mUVStride * (mFrameHeight / 2);
1842d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson        if (mYStride == mFrameWidth) {
1852d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson            // Copy Y straight up
1862d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson            memcpy(dest, source, ySize);
1872d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson        } else {
1882d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson            // Strip alignment
1892d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson            for (int y = 0; y < mFrameHeight; ++y) {
1902d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson                memcpy(dest + y * mFrameWidth,
1912d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson                       source + y * mYStride,
1922d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson                       mFrameWidth);
1932d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson            }
1942d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson        }
1952d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson
1962d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson        if (mUVStride == mFrameWidth / 2) {
1972d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson            // Swap U and V
1982d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson            memcpy(dest + ySize, source + ySize + uvSize, uvSize);
1992d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson            memcpy(dest + ySize + uvSize, source + ySize, uvSize);
2002d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson        } else {
2012d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson            // Strip alignment
2022d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson            uint8_t* uvDest = dest + mFrameWidth * mFrameHeight;
2032d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson            const uint8_t* uvSource = source + ySize + uvSize;
2042d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson
2052d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson            for (int i = 0; i < 2; ++i) {
2062d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson                for (int y = 0; y < mFrameHeight / 2; ++y) {
2072d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson                    memcpy(uvDest + y * (mFrameWidth / 2),
2082d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson                           uvSource + y * mUVStride,
2092d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson                           mFrameWidth / 2);
2102d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson                }
2112d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson                uvDest += (mFrameHeight / 2) * (mFrameWidth / 2);
2122d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson                uvSource -= uvSize;
2132d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson            }
2142d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson        }
2156ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson        return NO_ERROR;
2166ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson    }
2176ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson    ALOGE("%s: Invalid pixel format conversion [%.4s to %.4s] requested",
2186ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson          __FUNCTION__, reinterpret_cast<const char*>(&mPixelFormat),
2196ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson          reinterpret_cast<const char*>(&pixelFormat));
2206ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson    return EINVAL;
2216ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson}
2226ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson
2236ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johanssonstatus_t EmulatedCameraDevice::getCurrentFrame(void* buffer,
2246ab39a68026a9a65dcdf190511bab50335a55d17Bjoern Johansson                                               uint32_t pixelFormat)
225d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson{
226d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    if (!isStarted()) {
227d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        ALOGE("%s: Device is not started", __FUNCTION__);
228d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        return EINVAL;
229d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    }
230d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    if (buffer == nullptr) {
231d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        ALOGE("%s: Invalid buffer provided", __FUNCTION__);
232d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        return EINVAL;
233d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    }
234d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
235d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    FrameLock lock(*this);
236d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    const void* source = mCameraThread->getPrimaryBuffer();
237d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    if (source == nullptr) {
238d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        ALOGE("%s: No framebuffer", __FUNCTION__);
239d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        return EINVAL;
240d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    }
2412d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson    return getCurrentFrameImpl(reinterpret_cast<const uint8_t*>(source),
2422d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson                               reinterpret_cast<uint8_t*>(buffer),
2432d473c27a2a5fbda9bdc473d67f45023e9a2dfe8Bjoern Johansson                               pixelFormat);
244d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson}
245d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
2468a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedCameraDevice::getCurrentPreviewFrame(void* buffer)
2478a94683196406b83b14218d1beef66067f126a16keunyoung{
2488a94683196406b83b14218d1beef66067f126a16keunyoung    if (!isStarted()) {
2498a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGE("%s: Device is not started", __FUNCTION__);
2508a94683196406b83b14218d1beef66067f126a16keunyoung        return EINVAL;
2518a94683196406b83b14218d1beef66067f126a16keunyoung    }
252d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    if (buffer == nullptr) {
253d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        ALOGE("%s: Invalid buffer provided", __FUNCTION__);
254d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        return EINVAL;
255d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    }
256d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
257d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    FrameLock lock(*this);
258d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    const void* currentFrame = mCameraThread->getPrimaryBuffer();
259d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    if (currentFrame == nullptr) {
2608a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGE("%s: No framebuffer", __FUNCTION__);
2618a94683196406b83b14218d1beef66067f126a16keunyoung        return EINVAL;
2628a94683196406b83b14218d1beef66067f126a16keunyoung    }
2638a94683196406b83b14218d1beef66067f126a16keunyoung
2648a94683196406b83b14218d1beef66067f126a16keunyoung    /* In emulation the framebuffer is never RGB. */
2658a94683196406b83b14218d1beef66067f126a16keunyoung    switch (mPixelFormat) {
2668a94683196406b83b14218d1beef66067f126a16keunyoung        case V4L2_PIX_FMT_YVU420:
267d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson            YV12ToRGB32(currentFrame, buffer, mFrameWidth, mFrameHeight);
2688a94683196406b83b14218d1beef66067f126a16keunyoung            return NO_ERROR;
2698a94683196406b83b14218d1beef66067f126a16keunyoung        case V4L2_PIX_FMT_YUV420:
270d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson            YU12ToRGB32(currentFrame, buffer, mFrameWidth, mFrameHeight);
2718a94683196406b83b14218d1beef66067f126a16keunyoung            return NO_ERROR;
2728a94683196406b83b14218d1beef66067f126a16keunyoung        case V4L2_PIX_FMT_NV21:
273d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson            NV21ToRGB32(currentFrame, buffer, mFrameWidth, mFrameHeight);
2748a94683196406b83b14218d1beef66067f126a16keunyoung            return NO_ERROR;
2758a94683196406b83b14218d1beef66067f126a16keunyoung        case V4L2_PIX_FMT_NV12:
276d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson            NV12ToRGB32(currentFrame, buffer, mFrameWidth, mFrameHeight);
2778a94683196406b83b14218d1beef66067f126a16keunyoung            return NO_ERROR;
2788a94683196406b83b14218d1beef66067f126a16keunyoung
2798a94683196406b83b14218d1beef66067f126a16keunyoung        default:
2808a94683196406b83b14218d1beef66067f126a16keunyoung            ALOGE("%s: Unknown pixel format %.4s",
2818a94683196406b83b14218d1beef66067f126a16keunyoung                 __FUNCTION__, reinterpret_cast<const char*>(&mPixelFormat));
2828a94683196406b83b14218d1beef66067f126a16keunyoung            return EINVAL;
2838a94683196406b83b14218d1beef66067f126a16keunyoung    }
2848a94683196406b83b14218d1beef66067f126a16keunyoung}
2858a94683196406b83b14218d1beef66067f126a16keunyoung
286d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johanssonconst void* EmulatedCameraDevice::getCurrentFrame() {
287d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    if (mCameraThread.get()) {
288d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        return mCameraThread->getPrimaryBuffer();
289d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    }
290d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    return nullptr;
291d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson}
292d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
293d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern JohanssonEmulatedCameraDevice::FrameLock::FrameLock(EmulatedCameraDevice& cameraDevice)
294d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    : mCameraDevice(cameraDevice) {
295d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        mCameraDevice.lockCurrentFrame();
296d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson}
297d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
298d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern JohanssonEmulatedCameraDevice::FrameLock::~FrameLock() {
299d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    mCameraDevice.unlockCurrentFrame();
300d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson}
301d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
302dac82a5541140e3de6a20223530a406be4828b87Bjoern Johanssonstatus_t EmulatedCameraDevice::setAutoFocus() {
303dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson    mTriggerAutoFocus = true;
304dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson    return NO_ERROR;
305dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson}
306dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson
307dac82a5541140e3de6a20223530a406be4828b87Bjoern Johanssonstatus_t EmulatedCameraDevice::cancelAutoFocus() {
308dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson    mTriggerAutoFocus = false;
309dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson    return NO_ERROR;
310dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson}
311dac82a5541140e3de6a20223530a406be4828b87Bjoern Johansson
312d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonbool EmulatedCameraDevice::requestRestart(int width, int height,
313d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson                                          uint32_t pixelFormat,
314d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson                                          bool takingPicture, bool oneBurst) {
315d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    if (mCameraThread.get() == nullptr) {
316d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        ALOGE("%s: No thread alive to perform the restart, is preview on?",
317d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson              __FUNCTION__);
318d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        return false;
319d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    }
320d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mCameraThread->requestRestart(width, height, pixelFormat,
321d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson                                  takingPicture, oneBurst);
322d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    return true;
323d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson}
324d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson
3258a94683196406b83b14218d1beef66067f126a16keunyoung/****************************************************************************
3268a94683196406b83b14218d1beef66067f126a16keunyoung * Emulated camera device private API
3278a94683196406b83b14218d1beef66067f126a16keunyoung ***************************************************************************/
3288a94683196406b83b14218d1beef66067f126a16keunyoung
3298a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedCameraDevice::commonStartDevice(int width,
3308a94683196406b83b14218d1beef66067f126a16keunyoung                                                 int height,
3318a94683196406b83b14218d1beef66067f126a16keunyoung                                                 uint32_t pix_fmt)
3328a94683196406b83b14218d1beef66067f126a16keunyoung{
3338a94683196406b83b14218d1beef66067f126a16keunyoung    /* Validate pixel format, and calculate framebuffer size at the same time. */
3348a94683196406b83b14218d1beef66067f126a16keunyoung    switch (pix_fmt) {
3358a94683196406b83b14218d1beef66067f126a16keunyoung        case V4L2_PIX_FMT_YVU420:
3368a94683196406b83b14218d1beef66067f126a16keunyoung        case V4L2_PIX_FMT_YUV420:
33723fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            // For these pixel formats the strides have to be aligned to 16 byte
33823fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            // boundaries as per the format specification
33923fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            // https://developer.android.com/reference/android/graphics/ImageFormat.html#YV12
34023fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            mYStride = align(width, 16);
34123fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            mUVStride = align(mYStride / 2, 16);
34223fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            // The second term should use half the height but since there are
34323fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            // two planes the multiplication with two cancels that out
34423fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            mFrameBufferSize = mYStride * height + mUVStride * height;
34523fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            break;
3468a94683196406b83b14218d1beef66067f126a16keunyoung        case V4L2_PIX_FMT_NV21:
3478a94683196406b83b14218d1beef66067f126a16keunyoung        case V4L2_PIX_FMT_NV12:
34823fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            mYStride = width;
34923fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            // Because of interleaving the UV stride is the same as the Y stride
35023fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            // since it covers two pixels, one U and one V.
35123fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            mUVStride = mYStride;
35223fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            // Since the U/V stride covers both U and V we don't multiply by two
35323fc09071da1874cd14ae67fda8d546810220166Bjoern Johansson            mFrameBufferSize = mYStride * height + mUVStride * (height / 2);
3548a94683196406b83b14218d1beef66067f126a16keunyoung            break;
3558a94683196406b83b14218d1beef66067f126a16keunyoung        default:
3568a94683196406b83b14218d1beef66067f126a16keunyoung            ALOGE("%s: Unknown pixel format %.4s",
3578a94683196406b83b14218d1beef66067f126a16keunyoung                 __FUNCTION__, reinterpret_cast<const char*>(&pix_fmt));
3588a94683196406b83b14218d1beef66067f126a16keunyoung            return EINVAL;
3598a94683196406b83b14218d1beef66067f126a16keunyoung    }
3608a94683196406b83b14218d1beef66067f126a16keunyoung
3618a94683196406b83b14218d1beef66067f126a16keunyoung    /* Cache framebuffer info. */
3628a94683196406b83b14218d1beef66067f126a16keunyoung    mFrameWidth = width;
3638a94683196406b83b14218d1beef66067f126a16keunyoung    mFrameHeight = height;
3648a94683196406b83b14218d1beef66067f126a16keunyoung    mPixelFormat = pix_fmt;
3658a94683196406b83b14218d1beef66067f126a16keunyoung    mTotalPixels = width * height;
3668a94683196406b83b14218d1beef66067f126a16keunyoung
3678a94683196406b83b14218d1beef66067f126a16keunyoung    /* Allocate framebuffer. */
368d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    mFrameBuffers[0].resize(mFrameBufferSize);
369d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    mFrameBuffers[1].resize(mFrameBufferSize);
370d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    ALOGV("%s: Allocated %zu bytes for %d pixels in %.4s[%dx%d] frame",
371d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson         __FUNCTION__, mFrameBufferSize, mTotalPixels,
3728a94683196406b83b14218d1beef66067f126a16keunyoung         reinterpret_cast<const char*>(&mPixelFormat), mFrameWidth, mFrameHeight);
3738a94683196406b83b14218d1beef66067f126a16keunyoung    return NO_ERROR;
3748a94683196406b83b14218d1beef66067f126a16keunyoung}
3758a94683196406b83b14218d1beef66067f126a16keunyoung
3768a94683196406b83b14218d1beef66067f126a16keunyoungvoid EmulatedCameraDevice::commonStopDevice()
3778a94683196406b83b14218d1beef66067f126a16keunyoung{
3788a94683196406b83b14218d1beef66067f126a16keunyoung    mFrameWidth = mFrameHeight = mTotalPixels = 0;
3798a94683196406b83b14218d1beef66067f126a16keunyoung    mPixelFormat = 0;
3808a94683196406b83b14218d1beef66067f126a16keunyoung
381d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    mFrameBuffers[0].clear();
382d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    mFrameBuffers[1].clear();
383d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    // No need to keep all that memory allocated if the camera isn't running
384d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    mFrameBuffers[0].shrink_to_fit();
385d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    mFrameBuffers[1].shrink_to_fit();
3868a94683196406b83b14218d1beef66067f126a16keunyoung}
3878a94683196406b83b14218d1beef66067f126a16keunyoung
3888a94683196406b83b14218d1beef66067f126a16keunyoung/****************************************************************************
3898a94683196406b83b14218d1beef66067f126a16keunyoung * Worker thread management.
3908a94683196406b83b14218d1beef66067f126a16keunyoung ***************************************************************************/
3918a94683196406b83b14218d1beef66067f126a16keunyoung
392d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonstatus_t EmulatedCameraDevice::startWorkerThread(bool one_burst)
3938a94683196406b83b14218d1beef66067f126a16keunyoung{
3948a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGV("%s", __FUNCTION__);
3958a94683196406b83b14218d1beef66067f126a16keunyoung
3968a94683196406b83b14218d1beef66067f126a16keunyoung    if (!isInitialized()) {
3978a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGE("%s: Emulated camera device is not initialized", __FUNCTION__);
3988a94683196406b83b14218d1beef66067f126a16keunyoung        return EINVAL;
3998a94683196406b83b14218d1beef66067f126a16keunyoung    }
4008a94683196406b83b14218d1beef66067f126a16keunyoung
401d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mCameraThread = new CameraThread(this, staticProduceFrame, this);
402d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    if (mCameraThread == NULL) {
403d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        ALOGE("%s: Unable to instantiate CameraThread object", __FUNCTION__);
404d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        return ENOMEM;
405d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    }
406d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    status_t res = mCameraThread->startThread(one_burst);
407d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    if (res != NO_ERROR) {
408d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        ALOGE("%s: Unable to start CameraThread: %s",
409d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson              __FUNCTION__, strerror(res));
410d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        return res;
411d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    }
412d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
4138a94683196406b83b14218d1beef66067f126a16keunyoung    return res;
4148a94683196406b83b14218d1beef66067f126a16keunyoung}
4158a94683196406b83b14218d1beef66067f126a16keunyoung
416d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonstatus_t EmulatedCameraDevice::stopWorkerThread()
4178a94683196406b83b14218d1beef66067f126a16keunyoung{
4188a94683196406b83b14218d1beef66067f126a16keunyoung    ALOGV("%s", __FUNCTION__);
4198a94683196406b83b14218d1beef66067f126a16keunyoung
4208a94683196406b83b14218d1beef66067f126a16keunyoung    if (!isInitialized()) {
4218a94683196406b83b14218d1beef66067f126a16keunyoung        ALOGE("%s: Emulated camera device is not initialized", __FUNCTION__);
4228a94683196406b83b14218d1beef66067f126a16keunyoung        return EINVAL;
4238a94683196406b83b14218d1beef66067f126a16keunyoung    }
4248a94683196406b83b14218d1beef66067f126a16keunyoung
425d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    status_t res = mCameraThread->stopThread();
426d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    if (res != NO_ERROR) {
427d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        ALOGE("%s: Unable to stop CameraThread", __FUNCTION__);
428d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        return res;
429d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    }
430d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    res = mCameraThread->joinThread();
431d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    if (res != NO_ERROR) {
432d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        ALOGE("%s: Unable to join CameraThread", __FUNCTION__);
433d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        return res;
434d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    }
435d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
436d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    // Destroy the thread as well
437d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mCameraThread.clear();
4388a94683196406b83b14218d1beef66067f126a16keunyoung    return res;
4398a94683196406b83b14218d1beef66067f126a16keunyoung}
4408a94683196406b83b14218d1beef66067f126a16keunyoung
441d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern JohanssonEmulatedCameraDevice::CameraThread::CameraThread(EmulatedCameraDevice* dev,
442d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson                                                 ProduceFrameFunc producer,
443d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson                                                 void* producerOpaque)
444d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    : WorkerThread("Camera_CameraThread", dev, dev->mCameraHAL),
445d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson      mCurFrameTimestamp(0),
446d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson      mProducerFunc(producer),
447d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson      mProducerOpaque(producerOpaque),
448d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson      mRestartWidth(0),
449d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson      mRestartHeight(0),
450d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson      mRestartPixelFormat(0),
451d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson      mRestartOneBurst(false),
452d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson      mRestartTakingPicture(false),
453d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson      mRestartRequested(false) {
454d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
4558a94683196406b83b14218d1beef66067f126a16keunyoung}
4568a94683196406b83b14218d1beef66067f126a16keunyoung
457d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonconst void* EmulatedCameraDevice::CameraThread::getPrimaryBuffer() const {
458d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    if (mFrameProducer.get()) {
459d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        return mFrameProducer->getPrimaryBuffer();
460d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    }
461d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    return nullptr;
462d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson}
463d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson
464d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonvoid EmulatedCameraDevice::CameraThread::lockPrimaryBuffer() {
465d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mFrameProducer->lockPrimaryBuffer();
466d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson}
467d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson
468d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonvoid EmulatedCameraDevice::CameraThread::unlockPrimaryBuffer() {
469d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mFrameProducer->unlockPrimaryBuffer();
470d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson}
471d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
472d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonbool
473d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern JohanssonEmulatedCameraDevice::CameraThread::waitForFrameOrTimeout(nsecs_t timeout) {
474d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    // Keep waiting until the frame producer indicates that a frame is available
475d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    // This does introduce some unnecessary latency to the first frame delivery
476d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    // but avoids a lot of thread synchronization.
477d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    do {
478d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        // We don't have any specific fd we want to select so we pass in -1
479d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        // timeout is in nanoseconds but Select expects microseconds
480d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        Mutex::Autolock lock(mRunningMutex);
481d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        mRunningCondition.waitRelative(mRunningMutex, timeout);
482d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        if (!mRunning) {
483d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            ALOGV("%s: CameraThread has been terminated.", __FUNCTION__);
484d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson            return false;
485d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        }
486d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        // Set a short timeout in case there is no frame available and we are
487d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        // going to loop. This way we ensure a sleep but keep a decent latency
488d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        timeout = milliseconds(5);
489d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    } while (!mFrameProducer->hasFrame());
4908a94683196406b83b14218d1beef66067f126a16keunyoung
491d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    return true;
492d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson}
493d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson
494d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonbool EmulatedCameraDevice::CameraThread::inWorkerThread() {
495d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    /* Wait till FPS timeout expires, or thread exit message is received. */
496d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    nsecs_t wakeAt =
497d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        mCurFrameTimestamp + 1000000000.0 / mCameraDevice->mFramesPerSecond;
498d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
499d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    nsecs_t timeout = std::max<nsecs_t>(0, wakeAt - now);
500d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson
501d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    if (!waitForFrameOrTimeout(timeout)) {
502d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        return false;
503d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    }
504d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson
505d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    /* Check if a restart and potentially apply the requested changes */
506d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    if (!checkRestartRequest()) {
507d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        return false;
508d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    }
509d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson
510d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    /* Check if an auto-focus event needs to be triggered */
511d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    mCameraDevice->checkAutoFocusTrigger();
512d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
513d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    mCurFrameTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
514d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mCameraHAL->onNextFrameAvailable(mCurFrameTimestamp, mCameraDevice);
515b3f642f2a22cd58e64e0dc6326e946ef7fd7589fDouglas Leung
516d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    return true;
5178a94683196406b83b14218d1beef66067f126a16keunyoung}
5188a94683196406b83b14218d1beef66067f126a16keunyoung
519d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonstatus_t EmulatedCameraDevice::CameraThread::onThreadStart() {
520d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    void* primaryBuffer = mCameraDevice->getPrimaryBuffer();
521d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    void* secondaryBuffer = mCameraDevice->getSecondaryBuffer();
522d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mFrameProducer = new FrameProducer(mCameraDevice,
523d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson                                       mProducerFunc, mProducerOpaque,
524d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson                                       primaryBuffer, secondaryBuffer);
525d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    if (mFrameProducer.get() == nullptr) {
526d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        ALOGE("%s: Could not instantiate FrameProducer object", __FUNCTION__);
527d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        return ENOMEM;
528d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    }
529d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    return mFrameProducer->startThread(mOneBurst);
530d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson}
531d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson
532d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonvoid EmulatedCameraDevice::CameraThread::onThreadExit() {
533d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    if (mFrameProducer.get()) {
534d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        if (mFrameProducer->stopThread() == NO_ERROR) {
535d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            mFrameProducer->joinThread();
536d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            mFrameProducer.clear();
537d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        }
538d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    }
539d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson}
540d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson
541d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern JohanssonEmulatedCameraDevice::CameraThread::FrameProducer::FrameProducer(
542d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        EmulatedCameraDevice* dev,
543d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        ProduceFrameFunc producer,
544d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        void* opaque,
545d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        void* primaryBuffer,
546d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        void* secondaryBuffer)
547d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    : WorkerThread("Camera_FrameProducer", dev, dev->mCameraHAL),
548d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson      mProducer(producer),
549d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson      mOpaque(opaque),
550d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson      mPrimaryBuffer(primaryBuffer),
551d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson      mSecondaryBuffer(secondaryBuffer),
552d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson      mLastFrame(0),
553d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson      mHasFrame(false) {
5548a94683196406b83b14218d1beef66067f126a16keunyoung
555d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson}
556b3f642f2a22cd58e64e0dc6326e946ef7fd7589fDouglas Leung
557d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonconst void*
558d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern JohanssonEmulatedCameraDevice::CameraThread::FrameProducer::getPrimaryBuffer() const {
559d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    return mPrimaryBuffer;
560d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson}
561d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
562d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonvoid EmulatedCameraDevice::CameraThread::FrameProducer::lockPrimaryBuffer() {
563d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    mBufferMutex.lock();
564d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson}
565d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonvoid EmulatedCameraDevice::CameraThread::FrameProducer::unlockPrimaryBuffer() {
566d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    mBufferMutex.unlock();
567d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson}
568d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
569d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonvoid EmulatedCameraDevice::CameraThread::requestRestart(int width,
570d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson                                                        int height,
571d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson                                                        uint32_t pixelFormat,
572d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson                                                        bool takingPicture,
573d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson                                                        bool oneBurst) {
574d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    Mutex::Autolock lock(mRequestMutex);
575d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mRestartWidth = width;
576d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mRestartHeight = height;
577d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mRestartPixelFormat = pixelFormat;
578d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mRestartTakingPicture = takingPicture;
579d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mRestartOneBurst = oneBurst;
580d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mRestartRequested = true;
581d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson}
582d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson
583d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonbool EmulatedCameraDevice::CameraThread::FrameProducer::hasFrame() const {
584d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    return mHasFrame;
585d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson}
586d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
587d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonbool EmulatedCameraDevice::CameraThread::checkRestartRequest() {
588d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    Mutex::Autolock lock(mRequestMutex);
589d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    if (mRestartRequested) {
590d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        mRestartRequested = false;
591d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        status_t res = mFrameProducer->stopThread();
592d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        if (res != NO_ERROR) {
593d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            ALOGE("%s: Could not stop frame producer thread", __FUNCTION__);
594d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            mCameraHAL->onCameraDeviceError(CAMERA_ERROR_SERVER_DIED);
595d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            return false;
596d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        }
597d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        res = mFrameProducer->joinThread();
598d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        if (res != NO_ERROR) {
599d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            ALOGE("%s: Could not join frame producer thread", __FUNCTION__);
600d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            mCameraHAL->onCameraDeviceError(CAMERA_ERROR_SERVER_DIED);
601d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            return false;
602d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        }
603d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        mFrameProducer.clear();
604d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        res = mCameraDevice->stopDevice();
605d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        if (res != NO_ERROR) {
606d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            ALOGE("%s: Could not stop device", __FUNCTION__);
607d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            mCameraHAL->onCameraDeviceError(CAMERA_ERROR_SERVER_DIED);
608d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            return false;
609d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        }
610d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        res = mCameraDevice->startDevice(mRestartWidth,
611d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson                                         mRestartHeight,
612d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson                                         mRestartPixelFormat);
613d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        if (res != NO_ERROR) {
614d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            ALOGE("%s: Could not start device", __FUNCTION__);
615d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            mCameraHAL->onCameraDeviceError(CAMERA_ERROR_SERVER_DIED);
616d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            return false;
617d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        }
618d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        if (mRestartTakingPicture) {
619d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            mCameraHAL->setTakingPicture(true);
620d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        }
621d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        mOneBurst = mRestartOneBurst;
622d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson
623d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        // Pretend like this a thread start, performs the remaining setup
624d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        if (onThreadStart() != NO_ERROR) {
625d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            mCameraDevice->stopDevice();
626d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            mCameraHAL->onCameraDeviceError(CAMERA_ERROR_SERVER_DIED);
627d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            return false;
628d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        }
629d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson
630d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        // Now wait for the frame producer to start producing before we proceed
631d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        return waitForFrameOrTimeout(0);
632d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    }
633d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    return true;
634d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson}
635d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson
636d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johanssonbool EmulatedCameraDevice::CameraThread::FrameProducer::inWorkerThread() {
637d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    nsecs_t nextFrame =
638d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        mLastFrame + 1000000000 / mCameraDevice->mFramesPerSecond;
639d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
640d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    nsecs_t timeout = std::max<nsecs_t>(0, nextFrame - now);
641d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
642d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    {
643d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        Mutex::Autolock lock(mRunningMutex);
644d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        mRunningCondition.waitRelative(mRunningMutex, timeout);
645d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        if (!mRunning) {
646d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            ALOGV("%s: FrameProducer has been terminated.", __FUNCTION__);
647d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson            return false;
648d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        }
649b3f642f2a22cd58e64e0dc6326e946ef7fd7589fDouglas Leung    }
650b3f642f2a22cd58e64e0dc6326e946ef7fd7589fDouglas Leung
651d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    // Produce one frame and place it in the secondary buffer
652d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    mLastFrame = systemTime(SYSTEM_TIME_MONOTONIC);
653d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    if (!mProducer(mOpaque, mSecondaryBuffer)) {
654d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        ALOGE("FrameProducer could not produce frame, exiting thread");
655d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson        mCameraHAL->onCameraDeviceError(CAMERA_ERROR_SERVER_DIED);
656d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        return false;
6578a94683196406b83b14218d1beef66067f126a16keunyoung    }
6588a94683196406b83b14218d1beef66067f126a16keunyoung
659d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    {
660d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        // Switch buffers now that the secondary buffer is ready
661d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        Mutex::Autolock lock(mBufferMutex);
662d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson        std::swap(mPrimaryBuffer, mSecondaryBuffer);
663d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    }
664d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    mHasFrame = true;
665d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson    return true;
6668a94683196406b83b14218d1beef66067f126a16keunyoung}
6678a94683196406b83b14218d1beef66067f126a16keunyoung
668d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johanssonvoid EmulatedCameraDevice::lockCurrentFrame() {
669d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mCameraThread->lockPrimaryBuffer();
670d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson}
671d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johansson
672d9753c9a91259d70aac0079aab9a47db91e19f05Bjoern Johanssonvoid EmulatedCameraDevice::unlockCurrentFrame() {
673d17319e5eb181b728484e4c95b3c53b8e38c601dBjoern Johansson    mCameraThread->unlockPrimaryBuffer();
6748a94683196406b83b14218d1beef66067f126a16keunyoung}
6758a94683196406b83b14218d1beef66067f126a16keunyoung
6768a94683196406b83b14218d1beef66067f126a16keunyoung};  /* namespace android */
677