EmulatedCameraDevice.cpp revision 3725c7c982eac52ec64a625e82f306822452941c
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> 318a94683196406b83b14218d1beef66067f126a16keunyoung#include "EmulatedCameraDevice.h" 328a94683196406b83b14218d1beef66067f126a16keunyoung 338a94683196406b83b14218d1beef66067f126a16keunyoungnamespace android { 348a94683196406b83b14218d1beef66067f126a16keunyoung 358a94683196406b83b14218d1beef66067f126a16keunyoungconst float GAMMA_CORRECTION = 2.2f; 368a94683196406b83b14218d1beef66067f126a16keunyoungEmulatedCameraDevice::EmulatedCameraDevice(EmulatedCamera* camera_hal) 378a94683196406b83b14218d1beef66067f126a16keunyoung : mObjectLock(), 388a94683196406b83b14218d1beef66067f126a16keunyoung mCurFrameTimestamp(0), 398a94683196406b83b14218d1beef66067f126a16keunyoung mCameraHAL(camera_hal), 408a94683196406b83b14218d1beef66067f126a16keunyoung mCurrentFrame(NULL), 418a94683196406b83b14218d1beef66067f126a16keunyoung mExposureCompensation(1.0f), 428a94683196406b83b14218d1beef66067f126a16keunyoung mWhiteBalanceScale(NULL), 438a94683196406b83b14218d1beef66067f126a16keunyoung mSupportedWhiteBalanceScale(), 448a94683196406b83b14218d1beef66067f126a16keunyoung mState(ECDS_CONSTRUCTED) 458a94683196406b83b14218d1beef66067f126a16keunyoung{ 468a94683196406b83b14218d1beef66067f126a16keunyoung} 478a94683196406b83b14218d1beef66067f126a16keunyoung 488a94683196406b83b14218d1beef66067f126a16keunyoungEmulatedCameraDevice::~EmulatedCameraDevice() 498a94683196406b83b14218d1beef66067f126a16keunyoung{ 508a94683196406b83b14218d1beef66067f126a16keunyoung ALOGV("EmulatedCameraDevice destructor"); 518a94683196406b83b14218d1beef66067f126a16keunyoung if (mCurrentFrame != NULL) { 528a94683196406b83b14218d1beef66067f126a16keunyoung delete[] mCurrentFrame; 538a94683196406b83b14218d1beef66067f126a16keunyoung } 543725c7c982eac52ec64a625e82f306822452941cColin Cross for (size_t i = 0; i < mSupportedWhiteBalanceScale.size(); ++i) { 558a94683196406b83b14218d1beef66067f126a16keunyoung if (mSupportedWhiteBalanceScale.valueAt(i) != NULL) { 568a94683196406b83b14218d1beef66067f126a16keunyoung delete[] mSupportedWhiteBalanceScale.valueAt(i); 578a94683196406b83b14218d1beef66067f126a16keunyoung } 588a94683196406b83b14218d1beef66067f126a16keunyoung } 598a94683196406b83b14218d1beef66067f126a16keunyoung} 608a94683196406b83b14218d1beef66067f126a16keunyoung 618a94683196406b83b14218d1beef66067f126a16keunyoung/**************************************************************************** 628a94683196406b83b14218d1beef66067f126a16keunyoung * Emulated camera device public API 638a94683196406b83b14218d1beef66067f126a16keunyoung ***************************************************************************/ 648a94683196406b83b14218d1beef66067f126a16keunyoung 658a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedCameraDevice::Initialize() 668a94683196406b83b14218d1beef66067f126a16keunyoung{ 678a94683196406b83b14218d1beef66067f126a16keunyoung if (isInitialized()) { 688a94683196406b83b14218d1beef66067f126a16keunyoung ALOGW("%s: Emulated camera device is already initialized: mState = %d", 698a94683196406b83b14218d1beef66067f126a16keunyoung __FUNCTION__, mState); 708a94683196406b83b14218d1beef66067f126a16keunyoung return NO_ERROR; 718a94683196406b83b14218d1beef66067f126a16keunyoung } 728a94683196406b83b14218d1beef66067f126a16keunyoung 738a94683196406b83b14218d1beef66067f126a16keunyoung /* Instantiate worker thread object. */ 748a94683196406b83b14218d1beef66067f126a16keunyoung mWorkerThread = new WorkerThread(this); 758a94683196406b83b14218d1beef66067f126a16keunyoung if (getWorkerThread() == NULL) { 768a94683196406b83b14218d1beef66067f126a16keunyoung ALOGE("%s: Unable to instantiate worker thread object", __FUNCTION__); 778a94683196406b83b14218d1beef66067f126a16keunyoung return ENOMEM; 788a94683196406b83b14218d1beef66067f126a16keunyoung } 798a94683196406b83b14218d1beef66067f126a16keunyoung 808a94683196406b83b14218d1beef66067f126a16keunyoung mState = ECDS_INITIALIZED; 818a94683196406b83b14218d1beef66067f126a16keunyoung 828a94683196406b83b14218d1beef66067f126a16keunyoung return NO_ERROR; 838a94683196406b83b14218d1beef66067f126a16keunyoung} 848a94683196406b83b14218d1beef66067f126a16keunyoung 858a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedCameraDevice::startDeliveringFrames(bool one_burst) 868a94683196406b83b14218d1beef66067f126a16keunyoung{ 878a94683196406b83b14218d1beef66067f126a16keunyoung ALOGV("%s", __FUNCTION__); 888a94683196406b83b14218d1beef66067f126a16keunyoung 898a94683196406b83b14218d1beef66067f126a16keunyoung if (!isStarted()) { 908a94683196406b83b14218d1beef66067f126a16keunyoung ALOGE("%s: Device is not started", __FUNCTION__); 918a94683196406b83b14218d1beef66067f126a16keunyoung return EINVAL; 928a94683196406b83b14218d1beef66067f126a16keunyoung } 938a94683196406b83b14218d1beef66067f126a16keunyoung 948a94683196406b83b14218d1beef66067f126a16keunyoung /* Frames will be delivered from the thread routine. */ 958a94683196406b83b14218d1beef66067f126a16keunyoung const status_t res = startWorkerThread(one_burst); 968a94683196406b83b14218d1beef66067f126a16keunyoung ALOGE_IF(res != NO_ERROR, "%s: startWorkerThread failed", __FUNCTION__); 978a94683196406b83b14218d1beef66067f126a16keunyoung return res; 988a94683196406b83b14218d1beef66067f126a16keunyoung} 998a94683196406b83b14218d1beef66067f126a16keunyoung 1008a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedCameraDevice::stopDeliveringFrames() 1018a94683196406b83b14218d1beef66067f126a16keunyoung{ 1028a94683196406b83b14218d1beef66067f126a16keunyoung ALOGV("%s", __FUNCTION__); 1038a94683196406b83b14218d1beef66067f126a16keunyoung 1048a94683196406b83b14218d1beef66067f126a16keunyoung if (!isStarted()) { 1058a94683196406b83b14218d1beef66067f126a16keunyoung ALOGW("%s: Device is not started", __FUNCTION__); 1068a94683196406b83b14218d1beef66067f126a16keunyoung return NO_ERROR; 1078a94683196406b83b14218d1beef66067f126a16keunyoung } 1088a94683196406b83b14218d1beef66067f126a16keunyoung 1098a94683196406b83b14218d1beef66067f126a16keunyoung const status_t res = stopWorkerThread(); 1108a94683196406b83b14218d1beef66067f126a16keunyoung ALOGE_IF(res != NO_ERROR, "%s: startWorkerThread failed", __FUNCTION__); 1118a94683196406b83b14218d1beef66067f126a16keunyoung return res; 1128a94683196406b83b14218d1beef66067f126a16keunyoung} 1138a94683196406b83b14218d1beef66067f126a16keunyoung 1148a94683196406b83b14218d1beef66067f126a16keunyoungvoid EmulatedCameraDevice::setExposureCompensation(const float ev) { 1158a94683196406b83b14218d1beef66067f126a16keunyoung ALOGV("%s", __FUNCTION__); 1168a94683196406b83b14218d1beef66067f126a16keunyoung 1178a94683196406b83b14218d1beef66067f126a16keunyoung if (!isStarted()) { 1188a94683196406b83b14218d1beef66067f126a16keunyoung ALOGW("%s: Fake camera device is not started.", __FUNCTION__); 1198a94683196406b83b14218d1beef66067f126a16keunyoung } 1208a94683196406b83b14218d1beef66067f126a16keunyoung 1218a94683196406b83b14218d1beef66067f126a16keunyoung mExposureCompensation = std::pow(2.0f, ev / GAMMA_CORRECTION); 1228a94683196406b83b14218d1beef66067f126a16keunyoung ALOGV("New exposure compensation is %f", mExposureCompensation); 1238a94683196406b83b14218d1beef66067f126a16keunyoung} 1248a94683196406b83b14218d1beef66067f126a16keunyoung 1258a94683196406b83b14218d1beef66067f126a16keunyoungvoid EmulatedCameraDevice::initializeWhiteBalanceModes(const char* mode, 1268a94683196406b83b14218d1beef66067f126a16keunyoung const float r_scale, 1278a94683196406b83b14218d1beef66067f126a16keunyoung const float b_scale) { 1288a94683196406b83b14218d1beef66067f126a16keunyoung ALOGV("%s with %s, %f, %f", __FUNCTION__, mode, r_scale, b_scale); 1298a94683196406b83b14218d1beef66067f126a16keunyoung float* value = new float[3]; 1308a94683196406b83b14218d1beef66067f126a16keunyoung value[0] = r_scale; value[1] = 1.0f; value[2] = b_scale; 1318a94683196406b83b14218d1beef66067f126a16keunyoung mSupportedWhiteBalanceScale.add(String8(mode), value); 1328a94683196406b83b14218d1beef66067f126a16keunyoung} 1338a94683196406b83b14218d1beef66067f126a16keunyoung 1348a94683196406b83b14218d1beef66067f126a16keunyoungvoid EmulatedCameraDevice::setWhiteBalanceMode(const char* mode) { 1358a94683196406b83b14218d1beef66067f126a16keunyoung ALOGV("%s with white balance %s", __FUNCTION__, mode); 1368a94683196406b83b14218d1beef66067f126a16keunyoung mWhiteBalanceScale = 1378a94683196406b83b14218d1beef66067f126a16keunyoung mSupportedWhiteBalanceScale.valueFor(String8(mode)); 1388a94683196406b83b14218d1beef66067f126a16keunyoung} 1398a94683196406b83b14218d1beef66067f126a16keunyoung 1408a94683196406b83b14218d1beef66067f126a16keunyoung/* Computes the pixel value after adjusting the white balance to the current 1418a94683196406b83b14218d1beef66067f126a16keunyoung * one. The input the y, u, v channel of the pixel and the adjusted value will 1428a94683196406b83b14218d1beef66067f126a16keunyoung * be stored in place. The adjustment is done in RGB space. 1438a94683196406b83b14218d1beef66067f126a16keunyoung */ 1448a94683196406b83b14218d1beef66067f126a16keunyoungvoid EmulatedCameraDevice::changeWhiteBalance(uint8_t& y, 1458a94683196406b83b14218d1beef66067f126a16keunyoung uint8_t& u, 1468a94683196406b83b14218d1beef66067f126a16keunyoung uint8_t& v) const { 1478a94683196406b83b14218d1beef66067f126a16keunyoung float r_scale = mWhiteBalanceScale[0]; 1488a94683196406b83b14218d1beef66067f126a16keunyoung float b_scale = mWhiteBalanceScale[2]; 1498a94683196406b83b14218d1beef66067f126a16keunyoung int r = static_cast<float>(YUV2R(y, u, v)) / r_scale; 1508a94683196406b83b14218d1beef66067f126a16keunyoung int g = YUV2G(y, u, v); 1518a94683196406b83b14218d1beef66067f126a16keunyoung int b = static_cast<float>(YUV2B(y, u, v)) / b_scale; 1528a94683196406b83b14218d1beef66067f126a16keunyoung 1538a94683196406b83b14218d1beef66067f126a16keunyoung y = RGB2Y(r, g, b); 1548a94683196406b83b14218d1beef66067f126a16keunyoung u = RGB2U(r, g, b); 1558a94683196406b83b14218d1beef66067f126a16keunyoung v = RGB2V(r, g, b); 1568a94683196406b83b14218d1beef66067f126a16keunyoung} 1578a94683196406b83b14218d1beef66067f126a16keunyoung 1588a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedCameraDevice::getCurrentPreviewFrame(void* buffer) 1598a94683196406b83b14218d1beef66067f126a16keunyoung{ 1608a94683196406b83b14218d1beef66067f126a16keunyoung if (!isStarted()) { 1618a94683196406b83b14218d1beef66067f126a16keunyoung ALOGE("%s: Device is not started", __FUNCTION__); 1628a94683196406b83b14218d1beef66067f126a16keunyoung return EINVAL; 1638a94683196406b83b14218d1beef66067f126a16keunyoung } 1648a94683196406b83b14218d1beef66067f126a16keunyoung if (mCurrentFrame == NULL || buffer == NULL) { 1658a94683196406b83b14218d1beef66067f126a16keunyoung ALOGE("%s: No framebuffer", __FUNCTION__); 1668a94683196406b83b14218d1beef66067f126a16keunyoung return EINVAL; 1678a94683196406b83b14218d1beef66067f126a16keunyoung } 1688a94683196406b83b14218d1beef66067f126a16keunyoung 1698a94683196406b83b14218d1beef66067f126a16keunyoung /* In emulation the framebuffer is never RGB. */ 1708a94683196406b83b14218d1beef66067f126a16keunyoung switch (mPixelFormat) { 1718a94683196406b83b14218d1beef66067f126a16keunyoung case V4L2_PIX_FMT_YVU420: 1728a94683196406b83b14218d1beef66067f126a16keunyoung YV12ToRGB32(mCurrentFrame, buffer, mFrameWidth, mFrameHeight); 1738a94683196406b83b14218d1beef66067f126a16keunyoung return NO_ERROR; 1748a94683196406b83b14218d1beef66067f126a16keunyoung case V4L2_PIX_FMT_YUV420: 1758a94683196406b83b14218d1beef66067f126a16keunyoung YU12ToRGB32(mCurrentFrame, buffer, mFrameWidth, mFrameHeight); 1768a94683196406b83b14218d1beef66067f126a16keunyoung return NO_ERROR; 1778a94683196406b83b14218d1beef66067f126a16keunyoung case V4L2_PIX_FMT_NV21: 1788a94683196406b83b14218d1beef66067f126a16keunyoung NV21ToRGB32(mCurrentFrame, buffer, mFrameWidth, mFrameHeight); 1798a94683196406b83b14218d1beef66067f126a16keunyoung return NO_ERROR; 1808a94683196406b83b14218d1beef66067f126a16keunyoung case V4L2_PIX_FMT_NV12: 1818a94683196406b83b14218d1beef66067f126a16keunyoung NV12ToRGB32(mCurrentFrame, buffer, mFrameWidth, mFrameHeight); 1828a94683196406b83b14218d1beef66067f126a16keunyoung return NO_ERROR; 1838a94683196406b83b14218d1beef66067f126a16keunyoung 1848a94683196406b83b14218d1beef66067f126a16keunyoung default: 1858a94683196406b83b14218d1beef66067f126a16keunyoung ALOGE("%s: Unknown pixel format %.4s", 1868a94683196406b83b14218d1beef66067f126a16keunyoung __FUNCTION__, reinterpret_cast<const char*>(&mPixelFormat)); 1878a94683196406b83b14218d1beef66067f126a16keunyoung return EINVAL; 1888a94683196406b83b14218d1beef66067f126a16keunyoung } 1898a94683196406b83b14218d1beef66067f126a16keunyoung} 1908a94683196406b83b14218d1beef66067f126a16keunyoung 1918a94683196406b83b14218d1beef66067f126a16keunyoung/**************************************************************************** 1928a94683196406b83b14218d1beef66067f126a16keunyoung * Emulated camera device private API 1938a94683196406b83b14218d1beef66067f126a16keunyoung ***************************************************************************/ 1948a94683196406b83b14218d1beef66067f126a16keunyoung 1958a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedCameraDevice::commonStartDevice(int width, 1968a94683196406b83b14218d1beef66067f126a16keunyoung int height, 1978a94683196406b83b14218d1beef66067f126a16keunyoung uint32_t pix_fmt) 1988a94683196406b83b14218d1beef66067f126a16keunyoung{ 1998a94683196406b83b14218d1beef66067f126a16keunyoung /* Validate pixel format, and calculate framebuffer size at the same time. */ 2008a94683196406b83b14218d1beef66067f126a16keunyoung switch (pix_fmt) { 2018a94683196406b83b14218d1beef66067f126a16keunyoung case V4L2_PIX_FMT_YVU420: 2028a94683196406b83b14218d1beef66067f126a16keunyoung case V4L2_PIX_FMT_YUV420: 2038a94683196406b83b14218d1beef66067f126a16keunyoung case V4L2_PIX_FMT_NV21: 2048a94683196406b83b14218d1beef66067f126a16keunyoung case V4L2_PIX_FMT_NV12: 2058a94683196406b83b14218d1beef66067f126a16keunyoung mFrameBufferSize = (width * height * 12) / 8; 2068a94683196406b83b14218d1beef66067f126a16keunyoung break; 2078a94683196406b83b14218d1beef66067f126a16keunyoung 2088a94683196406b83b14218d1beef66067f126a16keunyoung default: 2098a94683196406b83b14218d1beef66067f126a16keunyoung ALOGE("%s: Unknown pixel format %.4s", 2108a94683196406b83b14218d1beef66067f126a16keunyoung __FUNCTION__, reinterpret_cast<const char*>(&pix_fmt)); 2118a94683196406b83b14218d1beef66067f126a16keunyoung return EINVAL; 2128a94683196406b83b14218d1beef66067f126a16keunyoung } 2138a94683196406b83b14218d1beef66067f126a16keunyoung 2148a94683196406b83b14218d1beef66067f126a16keunyoung /* Cache framebuffer info. */ 2158a94683196406b83b14218d1beef66067f126a16keunyoung mFrameWidth = width; 2168a94683196406b83b14218d1beef66067f126a16keunyoung mFrameHeight = height; 2178a94683196406b83b14218d1beef66067f126a16keunyoung mPixelFormat = pix_fmt; 2188a94683196406b83b14218d1beef66067f126a16keunyoung mTotalPixels = width * height; 2198a94683196406b83b14218d1beef66067f126a16keunyoung 2208a94683196406b83b14218d1beef66067f126a16keunyoung /* Allocate framebuffer. */ 2218a94683196406b83b14218d1beef66067f126a16keunyoung mCurrentFrame = new uint8_t[mFrameBufferSize]; 2228a94683196406b83b14218d1beef66067f126a16keunyoung if (mCurrentFrame == NULL) { 2238a94683196406b83b14218d1beef66067f126a16keunyoung ALOGE("%s: Unable to allocate framebuffer", __FUNCTION__); 2248a94683196406b83b14218d1beef66067f126a16keunyoung return ENOMEM; 2258a94683196406b83b14218d1beef66067f126a16keunyoung } 2263725c7c982eac52ec64a625e82f306822452941cColin Cross ALOGV("%s: Allocated %p %zu bytes for %d pixels in %.4s[%dx%d] frame", 2278a94683196406b83b14218d1beef66067f126a16keunyoung __FUNCTION__, mCurrentFrame, mFrameBufferSize, mTotalPixels, 2288a94683196406b83b14218d1beef66067f126a16keunyoung reinterpret_cast<const char*>(&mPixelFormat), mFrameWidth, mFrameHeight); 2298a94683196406b83b14218d1beef66067f126a16keunyoung return NO_ERROR; 2308a94683196406b83b14218d1beef66067f126a16keunyoung} 2318a94683196406b83b14218d1beef66067f126a16keunyoung 2328a94683196406b83b14218d1beef66067f126a16keunyoungvoid EmulatedCameraDevice::commonStopDevice() 2338a94683196406b83b14218d1beef66067f126a16keunyoung{ 2348a94683196406b83b14218d1beef66067f126a16keunyoung mFrameWidth = mFrameHeight = mTotalPixels = 0; 2358a94683196406b83b14218d1beef66067f126a16keunyoung mPixelFormat = 0; 2368a94683196406b83b14218d1beef66067f126a16keunyoung 2378a94683196406b83b14218d1beef66067f126a16keunyoung if (mCurrentFrame != NULL) { 2388a94683196406b83b14218d1beef66067f126a16keunyoung delete[] mCurrentFrame; 2398a94683196406b83b14218d1beef66067f126a16keunyoung mCurrentFrame = NULL; 2408a94683196406b83b14218d1beef66067f126a16keunyoung } 2418a94683196406b83b14218d1beef66067f126a16keunyoung} 2428a94683196406b83b14218d1beef66067f126a16keunyoung 2438a94683196406b83b14218d1beef66067f126a16keunyoung/**************************************************************************** 2448a94683196406b83b14218d1beef66067f126a16keunyoung * Worker thread management. 2458a94683196406b83b14218d1beef66067f126a16keunyoung ***************************************************************************/ 2468a94683196406b83b14218d1beef66067f126a16keunyoung 2478a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedCameraDevice::startWorkerThread(bool one_burst) 2488a94683196406b83b14218d1beef66067f126a16keunyoung{ 2498a94683196406b83b14218d1beef66067f126a16keunyoung ALOGV("%s", __FUNCTION__); 2508a94683196406b83b14218d1beef66067f126a16keunyoung 2518a94683196406b83b14218d1beef66067f126a16keunyoung if (!isInitialized()) { 2528a94683196406b83b14218d1beef66067f126a16keunyoung ALOGE("%s: Emulated camera device is not initialized", __FUNCTION__); 2538a94683196406b83b14218d1beef66067f126a16keunyoung return EINVAL; 2548a94683196406b83b14218d1beef66067f126a16keunyoung } 2558a94683196406b83b14218d1beef66067f126a16keunyoung 2568a94683196406b83b14218d1beef66067f126a16keunyoung const status_t res = getWorkerThread()->startThread(one_burst); 2578a94683196406b83b14218d1beef66067f126a16keunyoung ALOGE_IF(res != NO_ERROR, "%s: Unable to start worker thread", __FUNCTION__); 2588a94683196406b83b14218d1beef66067f126a16keunyoung return res; 2598a94683196406b83b14218d1beef66067f126a16keunyoung} 2608a94683196406b83b14218d1beef66067f126a16keunyoung 2618a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedCameraDevice::stopWorkerThread() 2628a94683196406b83b14218d1beef66067f126a16keunyoung{ 2638a94683196406b83b14218d1beef66067f126a16keunyoung ALOGV("%s", __FUNCTION__); 2648a94683196406b83b14218d1beef66067f126a16keunyoung 2658a94683196406b83b14218d1beef66067f126a16keunyoung if (!isInitialized()) { 2668a94683196406b83b14218d1beef66067f126a16keunyoung ALOGE("%s: Emulated camera device is not initialized", __FUNCTION__); 2678a94683196406b83b14218d1beef66067f126a16keunyoung return EINVAL; 2688a94683196406b83b14218d1beef66067f126a16keunyoung } 2698a94683196406b83b14218d1beef66067f126a16keunyoung 2708a94683196406b83b14218d1beef66067f126a16keunyoung const status_t res = getWorkerThread()->stopThread(); 2718a94683196406b83b14218d1beef66067f126a16keunyoung ALOGE_IF(res != NO_ERROR, "%s: Unable to stop worker thread", __FUNCTION__); 2728a94683196406b83b14218d1beef66067f126a16keunyoung return res; 2738a94683196406b83b14218d1beef66067f126a16keunyoung} 2748a94683196406b83b14218d1beef66067f126a16keunyoung 2758a94683196406b83b14218d1beef66067f126a16keunyoungbool EmulatedCameraDevice::inWorkerThread() 2768a94683196406b83b14218d1beef66067f126a16keunyoung{ 2778a94683196406b83b14218d1beef66067f126a16keunyoung /* This will end the thread loop, and will terminate the thread. Derived 2788a94683196406b83b14218d1beef66067f126a16keunyoung * classes must override this method. */ 2798a94683196406b83b14218d1beef66067f126a16keunyoung return false; 2808a94683196406b83b14218d1beef66067f126a16keunyoung} 2818a94683196406b83b14218d1beef66067f126a16keunyoung 2828a94683196406b83b14218d1beef66067f126a16keunyoung/**************************************************************************** 2838a94683196406b83b14218d1beef66067f126a16keunyoung * Worker thread implementation. 2848a94683196406b83b14218d1beef66067f126a16keunyoung ***************************************************************************/ 2858a94683196406b83b14218d1beef66067f126a16keunyoung 2868a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedCameraDevice::WorkerThread::readyToRun() 2878a94683196406b83b14218d1beef66067f126a16keunyoung{ 2888a94683196406b83b14218d1beef66067f126a16keunyoung ALOGV("Starting emulated camera device worker thread..."); 2898a94683196406b83b14218d1beef66067f126a16keunyoung 2908a94683196406b83b14218d1beef66067f126a16keunyoung ALOGW_IF(mThreadControl >= 0 || mControlFD >= 0, 2918a94683196406b83b14218d1beef66067f126a16keunyoung "%s: Thread control FDs are opened", __FUNCTION__); 2928a94683196406b83b14218d1beef66067f126a16keunyoung /* Create a pair of FDs that would be used to control the thread. */ 2938a94683196406b83b14218d1beef66067f126a16keunyoung int thread_fds[2]; 2948a94683196406b83b14218d1beef66067f126a16keunyoung if (pipe(thread_fds) == 0) { 2958a94683196406b83b14218d1beef66067f126a16keunyoung mThreadControl = thread_fds[1]; 2968a94683196406b83b14218d1beef66067f126a16keunyoung mControlFD = thread_fds[0]; 2978a94683196406b83b14218d1beef66067f126a16keunyoung ALOGV("Emulated device's worker thread has been started."); 2988a94683196406b83b14218d1beef66067f126a16keunyoung return NO_ERROR; 2998a94683196406b83b14218d1beef66067f126a16keunyoung } else { 3008a94683196406b83b14218d1beef66067f126a16keunyoung ALOGE("%s: Unable to create thread control FDs: %d -> %s", 3018a94683196406b83b14218d1beef66067f126a16keunyoung __FUNCTION__, errno, strerror(errno)); 3028a94683196406b83b14218d1beef66067f126a16keunyoung return errno; 3038a94683196406b83b14218d1beef66067f126a16keunyoung } 3048a94683196406b83b14218d1beef66067f126a16keunyoung} 3058a94683196406b83b14218d1beef66067f126a16keunyoung 3068a94683196406b83b14218d1beef66067f126a16keunyoungstatus_t EmulatedCameraDevice::WorkerThread::stopThread() 3078a94683196406b83b14218d1beef66067f126a16keunyoung{ 3088a94683196406b83b14218d1beef66067f126a16keunyoung ALOGV("Stopping emulated camera device's worker thread..."); 3098a94683196406b83b14218d1beef66067f126a16keunyoung 3108a94683196406b83b14218d1beef66067f126a16keunyoung status_t res = EINVAL; 3118a94683196406b83b14218d1beef66067f126a16keunyoung if (mThreadControl >= 0) { 3128a94683196406b83b14218d1beef66067f126a16keunyoung /* Send "stop" message to the thread loop. */ 3138a94683196406b83b14218d1beef66067f126a16keunyoung const ControlMessage msg = THREAD_STOP; 3148a94683196406b83b14218d1beef66067f126a16keunyoung const int wres = 3158a94683196406b83b14218d1beef66067f126a16keunyoung TEMP_FAILURE_RETRY(write(mThreadControl, &msg, sizeof(msg))); 3168a94683196406b83b14218d1beef66067f126a16keunyoung if (wres == sizeof(msg)) { 3178a94683196406b83b14218d1beef66067f126a16keunyoung /* Stop the thread, and wait till it's terminated. */ 3188a94683196406b83b14218d1beef66067f126a16keunyoung res = requestExitAndWait(); 3198a94683196406b83b14218d1beef66067f126a16keunyoung if (res == NO_ERROR) { 3208a94683196406b83b14218d1beef66067f126a16keunyoung /* Close control FDs. */ 3218a94683196406b83b14218d1beef66067f126a16keunyoung if (mThreadControl >= 0) { 3228a94683196406b83b14218d1beef66067f126a16keunyoung close(mThreadControl); 3238a94683196406b83b14218d1beef66067f126a16keunyoung mThreadControl = -1; 3248a94683196406b83b14218d1beef66067f126a16keunyoung } 3258a94683196406b83b14218d1beef66067f126a16keunyoung if (mControlFD >= 0) { 3268a94683196406b83b14218d1beef66067f126a16keunyoung close(mControlFD); 3278a94683196406b83b14218d1beef66067f126a16keunyoung mControlFD = -1; 3288a94683196406b83b14218d1beef66067f126a16keunyoung } 3298a94683196406b83b14218d1beef66067f126a16keunyoung ALOGV("Emulated camera device's worker thread has been stopped."); 3308a94683196406b83b14218d1beef66067f126a16keunyoung } else { 3318a94683196406b83b14218d1beef66067f126a16keunyoung ALOGE("%s: requestExitAndWait failed: %d -> %s", 3328a94683196406b83b14218d1beef66067f126a16keunyoung __FUNCTION__, res, strerror(-res)); 3338a94683196406b83b14218d1beef66067f126a16keunyoung } 3348a94683196406b83b14218d1beef66067f126a16keunyoung } else { 3358a94683196406b83b14218d1beef66067f126a16keunyoung ALOGE("%s: Unable to send THREAD_STOP message: %d -> %s", 3368a94683196406b83b14218d1beef66067f126a16keunyoung __FUNCTION__, errno, strerror(errno)); 3378a94683196406b83b14218d1beef66067f126a16keunyoung res = errno ? errno : EINVAL; 3388a94683196406b83b14218d1beef66067f126a16keunyoung } 3398a94683196406b83b14218d1beef66067f126a16keunyoung } else { 3408a94683196406b83b14218d1beef66067f126a16keunyoung ALOGE("%s: Thread control FDs are not opened", __FUNCTION__); 3418a94683196406b83b14218d1beef66067f126a16keunyoung } 3428a94683196406b83b14218d1beef66067f126a16keunyoung 3438a94683196406b83b14218d1beef66067f126a16keunyoung return res; 3448a94683196406b83b14218d1beef66067f126a16keunyoung} 3458a94683196406b83b14218d1beef66067f126a16keunyoung 3468a94683196406b83b14218d1beef66067f126a16keunyoungEmulatedCameraDevice::WorkerThread::SelectRes 3478a94683196406b83b14218d1beef66067f126a16keunyoungEmulatedCameraDevice::WorkerThread::Select(int fd, int timeout) 3488a94683196406b83b14218d1beef66067f126a16keunyoung{ 3498a94683196406b83b14218d1beef66067f126a16keunyoung fd_set fds[1]; 3508a94683196406b83b14218d1beef66067f126a16keunyoung struct timeval tv, *tvp = NULL; 3518a94683196406b83b14218d1beef66067f126a16keunyoung 3528a94683196406b83b14218d1beef66067f126a16keunyoung const int fd_num = (fd >= 0) ? max(fd, mControlFD) + 1 : 3538a94683196406b83b14218d1beef66067f126a16keunyoung mControlFD + 1; 3548a94683196406b83b14218d1beef66067f126a16keunyoung FD_ZERO(fds); 3558a94683196406b83b14218d1beef66067f126a16keunyoung FD_SET(mControlFD, fds); 3568a94683196406b83b14218d1beef66067f126a16keunyoung if (fd >= 0) { 3578a94683196406b83b14218d1beef66067f126a16keunyoung FD_SET(fd, fds); 3588a94683196406b83b14218d1beef66067f126a16keunyoung } 3598a94683196406b83b14218d1beef66067f126a16keunyoung if (timeout) { 3608a94683196406b83b14218d1beef66067f126a16keunyoung tv.tv_sec = timeout / 1000000; 3618a94683196406b83b14218d1beef66067f126a16keunyoung tv.tv_usec = timeout % 1000000; 3628a94683196406b83b14218d1beef66067f126a16keunyoung tvp = &tv; 3638a94683196406b83b14218d1beef66067f126a16keunyoung } 3648a94683196406b83b14218d1beef66067f126a16keunyoung int res = TEMP_FAILURE_RETRY(select(fd_num, fds, NULL, NULL, tvp)); 3658a94683196406b83b14218d1beef66067f126a16keunyoung if (res < 0) { 3668a94683196406b83b14218d1beef66067f126a16keunyoung ALOGE("%s: select returned %d and failed: %d -> %s", 3678a94683196406b83b14218d1beef66067f126a16keunyoung __FUNCTION__, res, errno, strerror(errno)); 3688a94683196406b83b14218d1beef66067f126a16keunyoung return ERROR; 3698a94683196406b83b14218d1beef66067f126a16keunyoung } else if (res == 0) { 3708a94683196406b83b14218d1beef66067f126a16keunyoung /* Timeout. */ 3718a94683196406b83b14218d1beef66067f126a16keunyoung return TIMEOUT; 3728a94683196406b83b14218d1beef66067f126a16keunyoung } else if (FD_ISSET(mControlFD, fds)) { 3738a94683196406b83b14218d1beef66067f126a16keunyoung /* A control event. Lets read the message. */ 3748a94683196406b83b14218d1beef66067f126a16keunyoung ControlMessage msg; 3758a94683196406b83b14218d1beef66067f126a16keunyoung res = TEMP_FAILURE_RETRY(read(mControlFD, &msg, sizeof(msg))); 3768a94683196406b83b14218d1beef66067f126a16keunyoung if (res != sizeof(msg)) { 3778a94683196406b83b14218d1beef66067f126a16keunyoung ALOGE("%s: Unexpected message size %d, or an error %d -> %s", 3788a94683196406b83b14218d1beef66067f126a16keunyoung __FUNCTION__, res, errno, strerror(errno)); 3798a94683196406b83b14218d1beef66067f126a16keunyoung return ERROR; 3808a94683196406b83b14218d1beef66067f126a16keunyoung } 3818a94683196406b83b14218d1beef66067f126a16keunyoung /* THREAD_STOP is the only message expected here. */ 3828a94683196406b83b14218d1beef66067f126a16keunyoung if (msg == THREAD_STOP) { 3838a94683196406b83b14218d1beef66067f126a16keunyoung ALOGV("%s: THREAD_STOP message is received", __FUNCTION__); 3848a94683196406b83b14218d1beef66067f126a16keunyoung return EXIT_THREAD; 3858a94683196406b83b14218d1beef66067f126a16keunyoung } else { 3868a94683196406b83b14218d1beef66067f126a16keunyoung ALOGE("Unknown worker thread message %d", msg); 3878a94683196406b83b14218d1beef66067f126a16keunyoung return ERROR; 3888a94683196406b83b14218d1beef66067f126a16keunyoung } 3898a94683196406b83b14218d1beef66067f126a16keunyoung } else { 3908a94683196406b83b14218d1beef66067f126a16keunyoung /* Must be an FD. */ 3918a94683196406b83b14218d1beef66067f126a16keunyoung ALOGW_IF(fd < 0 || !FD_ISSET(fd, fds), "%s: Undefined 'select' result", 3928a94683196406b83b14218d1beef66067f126a16keunyoung __FUNCTION__); 3938a94683196406b83b14218d1beef66067f126a16keunyoung return READY; 3948a94683196406b83b14218d1beef66067f126a16keunyoung } 3958a94683196406b83b14218d1beef66067f126a16keunyoung} 3968a94683196406b83b14218d1beef66067f126a16keunyoung 3978a94683196406b83b14218d1beef66067f126a16keunyoung}; /* namespace android */ 398