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