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