1b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine/* 2b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * Copyright (C) 2011 The Android Open Source Project 3b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * 4b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * Licensed under the Apache License, Version 2.0 (the "License"); 5b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * you may not use this file except in compliance with the License. 6b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * You may obtain a copy of the License at 7b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * 8b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * http://www.apache.org/licenses/LICENSE-2.0 9b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * 10b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * Unless required by applicable law or agreed to in writing, software 11b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * distributed under the License is distributed on an "AS IS" BASIS, 12b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * See the License for the specific language governing permissions and 14b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * limitations under the License. 15b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine */ 16b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 17b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine/* 18b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * Contains implementation of an abstract class EmulatedCameraDevice that defines 19b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * functionality expected from an emulated physical camera device: 20b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * - Obtaining and setting camera parameters 21b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * - Capturing frames 22b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * - Streaming video 23b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * - etc. 24b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine */ 25b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 26b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine#define LOG_NDEBUG 0 27b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine#define LOG_TAG "EmulatedCamera_Device" 28b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine#include <cutils/log.h> 29b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine#include <sys/select.h> 30366396d9b001c7a1abf2b73161a9b7b05e9022ecChristine Chen#include <cmath> 315467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine#include "EmulatedCameraDevice.h" 32b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 33b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkinenamespace android { 34b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 3512c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chenconst float GAMMA_CORRECTION = 2.2f; 36b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir ChtchetkineEmulatedCameraDevice::EmulatedCameraDevice(EmulatedCamera* camera_hal) 375467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine : mObjectLock(), 385467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine mCurFrameTimestamp(0), 395467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine mCameraHAL(camera_hal), 405467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine mCurrentFrame(NULL), 41366396d9b001c7a1abf2b73161a9b7b05e9022ecChristine Chen mExposureCompensation(1.0f), 4212c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen mWhiteBalanceScale(NULL), 4312c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen mSupportedWhiteBalanceScale(), 445467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine mState(ECDS_CONSTRUCTED) 45b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine{ 46b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine} 47b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 48b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir ChtchetkineEmulatedCameraDevice::~EmulatedCameraDevice() 49b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine{ 50629719e390ce66be822c3563bbd248ce15eaae7bSteve Block ALOGV("EmulatedCameraDevice destructor"); 515467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine if (mCurrentFrame != NULL) { 525467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine delete[] mCurrentFrame; 53b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine } 5412c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen for (int i = 0; i < mSupportedWhiteBalanceScale.size(); ++i) { 5512c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen if (mSupportedWhiteBalanceScale.valueAt(i) != NULL) { 5612c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen delete[] mSupportedWhiteBalanceScale.valueAt(i); 5712c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen } 5812c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen } 59b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine} 60b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 61b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine/**************************************************************************** 62b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * Emulated camera device public API 63b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine ***************************************************************************/ 64b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 65b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkinestatus_t EmulatedCameraDevice::Initialize() 66b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine{ 675467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine if (isInitialized()) { 686aff44c27ee487bd65d5a1c74faf4b7165530bd4Steve Block ALOGW("%s: Emulated camera device is already initialized: mState = %d", 695467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine __FUNCTION__, mState); 70b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine return NO_ERROR; 71b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine } 72b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 73b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine /* Instantiate worker thread object. */ 745467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine mWorkerThread = new WorkerThread(this); 755467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine if (getWorkerThread() == NULL) { 765a622cba8c5287d5e6577f940a22343a7cae977fSteve Block ALOGE("%s: Unable to instantiate worker thread object", __FUNCTION__); 77b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine return ENOMEM; 78b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine } 79b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 805467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine mState = ECDS_INITIALIZED; 81b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 82b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine return NO_ERROR; 83b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine} 84b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 8549842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkinestatus_t EmulatedCameraDevice::startDeliveringFrames(bool one_burst) 86b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine{ 87629719e390ce66be822c3563bbd248ce15eaae7bSteve Block ALOGV("%s", __FUNCTION__); 88b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 8949842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine if (!isStarted()) { 905a622cba8c5287d5e6577f940a22343a7cae977fSteve Block ALOGE("%s: Device is not started", __FUNCTION__); 9149842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine return EINVAL; 9249842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine } 9349842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine 9449842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine /* Frames will be delivered from the thread routine. */ 9549842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine const status_t res = startWorkerThread(one_burst); 965a622cba8c5287d5e6577f940a22343a7cae977fSteve Block ALOGE_IF(res != NO_ERROR, "%s: startWorkerThread failed", __FUNCTION__); 9749842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine return res; 9849842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine} 9949842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine 10049842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkinestatus_t EmulatedCameraDevice::stopDeliveringFrames() 10149842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine{ 102629719e390ce66be822c3563bbd248ce15eaae7bSteve Block ALOGV("%s", __FUNCTION__); 10349842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine 10449842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine if (!isStarted()) { 1056aff44c27ee487bd65d5a1c74faf4b7165530bd4Steve Block ALOGW("%s: Device is not started", __FUNCTION__); 10649842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine return NO_ERROR; 10749842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine } 10849842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine 10949842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine const status_t res = stopWorkerThread(); 1105a622cba8c5287d5e6577f940a22343a7cae977fSteve Block ALOGE_IF(res != NO_ERROR, "%s: startWorkerThread failed", __FUNCTION__); 11149842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine return res; 11249842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine} 11349842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine 114366396d9b001c7a1abf2b73161a9b7b05e9022ecChristine Chenvoid EmulatedCameraDevice::setExposureCompensation(const float ev) { 115629719e390ce66be822c3563bbd248ce15eaae7bSteve Block ALOGV("%s", __FUNCTION__); 116366396d9b001c7a1abf2b73161a9b7b05e9022ecChristine Chen 117366396d9b001c7a1abf2b73161a9b7b05e9022ecChristine Chen if (!isStarted()) { 1186aff44c27ee487bd65d5a1c74faf4b7165530bd4Steve Block ALOGW("%s: Fake camera device is not started.", __FUNCTION__); 119366396d9b001c7a1abf2b73161a9b7b05e9022ecChristine Chen } 120366396d9b001c7a1abf2b73161a9b7b05e9022ecChristine Chen 12112c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen mExposureCompensation = std::pow(2.0f, ev / GAMMA_CORRECTION); 122629719e390ce66be822c3563bbd248ce15eaae7bSteve Block ALOGV("New exposure compensation is %f", mExposureCompensation); 123366396d9b001c7a1abf2b73161a9b7b05e9022ecChristine Chen} 124366396d9b001c7a1abf2b73161a9b7b05e9022ecChristine Chen 12512c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chenvoid EmulatedCameraDevice::initializeWhiteBalanceModes(const char* mode, 12612c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen const float r_scale, 12712c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen const float b_scale) { 128629719e390ce66be822c3563bbd248ce15eaae7bSteve Block ALOGV("%s with %s, %f, %f", __FUNCTION__, mode, r_scale, b_scale); 12912c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen float* value = new float[3]; 13012c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen value[0] = r_scale; value[1] = 1.0f; value[2] = b_scale; 13112c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen mSupportedWhiteBalanceScale.add(String8(mode), value); 13212c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen} 13312c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen 13412c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chenvoid EmulatedCameraDevice::setWhiteBalanceMode(const char* mode) { 135629719e390ce66be822c3563bbd248ce15eaae7bSteve Block ALOGV("%s with white balance %s", __FUNCTION__, mode); 13612c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen mWhiteBalanceScale = 13712c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen mSupportedWhiteBalanceScale.valueFor(String8(mode)); 13812c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen} 13912c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen 14012c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen/* Computes the pixel value after adjusting the white balance to the current 14112c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen * one. The input the y, u, v channel of the pixel and the adjusted value will 14212c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen * be stored in place. The adjustment is done in RGB space. 14312c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen */ 14412c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chenvoid EmulatedCameraDevice::changeWhiteBalance(uint8_t& y, 14512c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen uint8_t& u, 14612c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen uint8_t& v) const { 14712c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen float r_scale = mWhiteBalanceScale[0]; 14812c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen float b_scale = mWhiteBalanceScale[2]; 14912c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen int r = static_cast<float>(YUV2R(y, u, v)) / r_scale; 15012c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen int g = YUV2G(y, u, v); 15112c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen int b = static_cast<float>(YUV2B(y, u, v)) / b_scale; 15212c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen 15312c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen y = RGB2Y(r, g, b); 15412c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen u = RGB2U(r, g, b); 15512c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen v = RGB2V(r, g, b); 15612c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen} 15712c0b21abeea8f07cdcab3bf9a79b0791590f537Christine Chen 15849842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkinestatus_t EmulatedCameraDevice::getCurrentPreviewFrame(void* buffer) 15949842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine{ 16049842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine if (!isStarted()) { 1615a622cba8c5287d5e6577f940a22343a7cae977fSteve Block ALOGE("%s: Device is not started", __FUNCTION__); 16249842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine return EINVAL; 16349842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine } 16449842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine if (mCurrentFrame == NULL || buffer == NULL) { 1655a622cba8c5287d5e6577f940a22343a7cae977fSteve Block ALOGE("%s: No framebuffer", __FUNCTION__); 16649842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine return EINVAL; 16749842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine } 16849842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine 16949842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine /* In emulation the framebuffer is never RGB. */ 17049842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine switch (mPixelFormat) { 17149842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine case V4L2_PIX_FMT_YVU420: 17249842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine YV12ToRGB32(mCurrentFrame, buffer, mFrameWidth, mFrameHeight); 17349842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine return NO_ERROR; 17468ec4ac828762745155be9662285d2174a7eff1eVladimir Chtchetkine case V4L2_PIX_FMT_YUV420: 17568ec4ac828762745155be9662285d2174a7eff1eVladimir Chtchetkine YU12ToRGB32(mCurrentFrame, buffer, mFrameWidth, mFrameHeight); 17668ec4ac828762745155be9662285d2174a7eff1eVladimir Chtchetkine return NO_ERROR; 1772a532ee388828120a5a11fba0087a1ed2539a159Vladimir Chtchetkine case V4L2_PIX_FMT_NV21: 1782a532ee388828120a5a11fba0087a1ed2539a159Vladimir Chtchetkine NV21ToRGB32(mCurrentFrame, buffer, mFrameWidth, mFrameHeight); 1792a532ee388828120a5a11fba0087a1ed2539a159Vladimir Chtchetkine return NO_ERROR; 1802a532ee388828120a5a11fba0087a1ed2539a159Vladimir Chtchetkine case V4L2_PIX_FMT_NV12: 1812a532ee388828120a5a11fba0087a1ed2539a159Vladimir Chtchetkine NV12ToRGB32(mCurrentFrame, buffer, mFrameWidth, mFrameHeight); 1822a532ee388828120a5a11fba0087a1ed2539a159Vladimir Chtchetkine return NO_ERROR; 18349842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine 18449842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine default: 1855a622cba8c5287d5e6577f940a22343a7cae977fSteve Block ALOGE("%s: Unknown pixel format %.4s", 18649842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine __FUNCTION__, reinterpret_cast<const char*>(&mPixelFormat)); 18749842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine return EINVAL; 18849842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine } 18949842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine} 19049842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine 19149842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine/**************************************************************************** 19249842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine * Emulated camera device private API 19349842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine ***************************************************************************/ 19449842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine 19549842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkinestatus_t EmulatedCameraDevice::commonStartDevice(int width, 19649842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine int height, 19749842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine uint32_t pix_fmt) 19849842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine{ 199b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine /* Validate pixel format, and calculate framebuffer size at the same time. */ 200b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine switch (pix_fmt) { 201b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine case V4L2_PIX_FMT_YVU420: 20268ec4ac828762745155be9662285d2174a7eff1eVladimir Chtchetkine case V4L2_PIX_FMT_YUV420: 2032a532ee388828120a5a11fba0087a1ed2539a159Vladimir Chtchetkine case V4L2_PIX_FMT_NV21: 2042a532ee388828120a5a11fba0087a1ed2539a159Vladimir Chtchetkine case V4L2_PIX_FMT_NV12: 2055467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine mFrameBufferSize = (width * height * 12) / 8; 206b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine break; 207b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 208b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine default: 2095a622cba8c5287d5e6577f940a22343a7cae977fSteve Block ALOGE("%s: Unknown pixel format %.4s", 210b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine __FUNCTION__, reinterpret_cast<const char*>(&pix_fmt)); 211b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine return EINVAL; 212b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine } 213b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 214b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine /* Cache framebuffer info. */ 2155467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine mFrameWidth = width; 2165467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine mFrameHeight = height; 2175467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine mPixelFormat = pix_fmt; 2185467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine mTotalPixels = width * height; 219b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 220b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine /* Allocate framebuffer. */ 2215467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine mCurrentFrame = new uint8_t[mFrameBufferSize]; 2225467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine if (mCurrentFrame == NULL) { 2235a622cba8c5287d5e6577f940a22343a7cae977fSteve Block ALOGE("%s: Unable to allocate framebuffer", __FUNCTION__); 224b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine return ENOMEM; 225b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine } 226629719e390ce66be822c3563bbd248ce15eaae7bSteve Block ALOGV("%s: Allocated %p %d bytes for %d pixels in %.4s[%dx%d] frame", 2272a532ee388828120a5a11fba0087a1ed2539a159Vladimir Chtchetkine __FUNCTION__, mCurrentFrame, mFrameBufferSize, mTotalPixels, 2282a532ee388828120a5a11fba0087a1ed2539a159Vladimir Chtchetkine reinterpret_cast<const char*>(&mPixelFormat), mFrameWidth, mFrameHeight); 229b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine return NO_ERROR; 230b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine} 231b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 23249842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkinevoid EmulatedCameraDevice::commonStopDevice() 233b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine{ 23449842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine mFrameWidth = mFrameHeight = mTotalPixels = 0; 23549842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine mPixelFormat = 0; 236b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 23749842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine if (mCurrentFrame != NULL) { 23849842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine delete[] mCurrentFrame; 23949842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine mCurrentFrame = NULL; 240b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine } 241b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine} 242b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 243b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine/**************************************************************************** 244b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * Worker thread management. 245b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine ***************************************************************************/ 246b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 24749842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkinestatus_t EmulatedCameraDevice::startWorkerThread(bool one_burst) 248b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine{ 249629719e390ce66be822c3563bbd248ce15eaae7bSteve Block ALOGV("%s", __FUNCTION__); 250b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 2515467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine if (!isInitialized()) { 2525a622cba8c5287d5e6577f940a22343a7cae977fSteve Block ALOGE("%s: Emulated camera device is not initialized", __FUNCTION__); 253b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine return EINVAL; 254b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine } 255b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 25649842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine const status_t res = getWorkerThread()->startThread(one_burst); 2575a622cba8c5287d5e6577f940a22343a7cae977fSteve Block ALOGE_IF(res != NO_ERROR, "%s: Unable to start worker thread", __FUNCTION__); 25849842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine return res; 259b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine} 260b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 2615467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkinestatus_t EmulatedCameraDevice::stopWorkerThread() 262b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine{ 263629719e390ce66be822c3563bbd248ce15eaae7bSteve Block ALOGV("%s", __FUNCTION__); 264b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 2655467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine if (!isInitialized()) { 2665a622cba8c5287d5e6577f940a22343a7cae977fSteve Block ALOGE("%s: Emulated camera device is not initialized", __FUNCTION__); 267b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine return EINVAL; 268b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine } 269b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 27049842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine const status_t res = getWorkerThread()->stopThread(); 2715a622cba8c5287d5e6577f940a22343a7cae977fSteve Block ALOGE_IF(res != NO_ERROR, "%s: Unable to stop worker thread", __FUNCTION__); 27249842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine return res; 273b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine} 274b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 2755467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkinebool EmulatedCameraDevice::inWorkerThread() 276b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine{ 27749842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine /* This will end the thread loop, and will terminate the thread. Derived 27849842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine * classes must override this method. */ 279b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine return false; 280b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine} 281b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 282b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine/**************************************************************************** 283b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine * Worker thread implementation. 284b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine ***************************************************************************/ 285b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 286b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkinestatus_t EmulatedCameraDevice::WorkerThread::readyToRun() 287b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine{ 288629719e390ce66be822c3563bbd248ce15eaae7bSteve Block ALOGV("Starting emulated camera device worker thread..."); 289b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 2906aff44c27ee487bd65d5a1c74faf4b7165530bd4Steve Block ALOGW_IF(mThreadControl >= 0 || mControlFD >= 0, 291b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine "%s: Thread control FDs are opened", __FUNCTION__); 292b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine /* Create a pair of FDs that would be used to control the thread. */ 293b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine int thread_fds[2]; 294b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine if (pipe(thread_fds) == 0) { 2955467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine mThreadControl = thread_fds[1]; 2965467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine mControlFD = thread_fds[0]; 297629719e390ce66be822c3563bbd248ce15eaae7bSteve Block ALOGV("Emulated device's worker thread has been started."); 298b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine return NO_ERROR; 299b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine } else { 3005a622cba8c5287d5e6577f940a22343a7cae977fSteve Block ALOGE("%s: Unable to create thread control FDs: %d -> %s", 301b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine __FUNCTION__, errno, strerror(errno)); 302b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine return errno; 303b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine } 304b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine} 305b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 3065467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkinestatus_t EmulatedCameraDevice::WorkerThread::stopThread() 307b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine{ 308629719e390ce66be822c3563bbd248ce15eaae7bSteve Block ALOGV("Stopping emulated camera device's worker thread..."); 309b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 310b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine status_t res = EINVAL; 3115467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine if (mThreadControl >= 0) { 312b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine /* Send "stop" message to the thread loop. */ 313b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine const ControlMessage msg = THREAD_STOP; 314b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine const int wres = 3155467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine TEMP_FAILURE_RETRY(write(mThreadControl, &msg, sizeof(msg))); 316b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine if (wres == sizeof(msg)) { 317b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine /* Stop the thread, and wait till it's terminated. */ 318b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine res = requestExitAndWait(); 319b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine if (res == NO_ERROR) { 320b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine /* Close control FDs. */ 3215467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine if (mThreadControl >= 0) { 3225467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine close(mThreadControl); 3235467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine mThreadControl = -1; 324b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine } 3255467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine if (mControlFD >= 0) { 3265467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine close(mControlFD); 3275467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine mControlFD = -1; 328b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine } 329629719e390ce66be822c3563bbd248ce15eaae7bSteve Block ALOGV("Emulated camera device's worker thread has been stopped."); 330b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine } else { 3315a622cba8c5287d5e6577f940a22343a7cae977fSteve Block ALOGE("%s: requestExitAndWait failed: %d -> %s", 33249842cee0549befb6d7a4353247190820037e1c4Vladimir Chtchetkine __FUNCTION__, res, strerror(-res)); 333b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine } 334b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine } else { 3355a622cba8c5287d5e6577f940a22343a7cae977fSteve Block ALOGE("%s: Unable to send THREAD_STOP message: %d -> %s", 336b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine __FUNCTION__, errno, strerror(errno)); 337b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine res = errno ? errno : EINVAL; 338b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine } 339b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine } else { 3405a622cba8c5287d5e6577f940a22343a7cae977fSteve Block ALOGE("%s: Thread control FDs are not opened", __FUNCTION__); 341b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine } 342b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 343b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine return res; 344b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine} 345b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 346b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir ChtchetkineEmulatedCameraDevice::WorkerThread::SelectRes 347b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir ChtchetkineEmulatedCameraDevice::WorkerThread::Select(int fd, int timeout) 348b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine{ 349b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine fd_set fds[1]; 350b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine struct timeval tv, *tvp = NULL; 351b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 3525467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine const int fd_num = (fd >= 0) ? max(fd, mControlFD) + 1 : 3535467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine mControlFD + 1; 354b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine FD_ZERO(fds); 3555467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine FD_SET(mControlFD, fds); 356b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine if (fd >= 0) { 357b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine FD_SET(fd, fds); 358b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine } 359b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine if (timeout) { 360b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine tv.tv_sec = timeout / 1000000; 361b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine tv.tv_usec = timeout % 1000000; 362b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine tvp = &tv; 363b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine } 364b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine int res = TEMP_FAILURE_RETRY(select(fd_num, fds, NULL, NULL, tvp)); 365b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine if (res < 0) { 3665a622cba8c5287d5e6577f940a22343a7cae977fSteve Block ALOGE("%s: select returned %d and failed: %d -> %s", 367b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine __FUNCTION__, res, errno, strerror(errno)); 368b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine return ERROR; 369b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine } else if (res == 0) { 370b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine /* Timeout. */ 371b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine return TIMEOUT; 3725467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine } else if (FD_ISSET(mControlFD, fds)) { 373b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine /* A control event. Lets read the message. */ 374b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine ControlMessage msg; 3755467be2eefc007ebf09baf109dafe058abc1ffc5Vladimir Chtchetkine res = TEMP_FAILURE_RETRY(read(mControlFD, &msg, sizeof(msg))); 376b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine if (res != sizeof(msg)) { 3775a622cba8c5287d5e6577f940a22343a7cae977fSteve Block ALOGE("%s: Unexpected message size %d, or an error %d -> %s", 378b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine __FUNCTION__, res, errno, strerror(errno)); 379b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine return ERROR; 380b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine } 381b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine /* THREAD_STOP is the only message expected here. */ 382b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine if (msg == THREAD_STOP) { 383629719e390ce66be822c3563bbd248ce15eaae7bSteve Block ALOGV("%s: THREAD_STOP message is received", __FUNCTION__); 384b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine return EXIT_THREAD; 385b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine } else { 3865a622cba8c5287d5e6577f940a22343a7cae977fSteve Block ALOGE("Unknown worker thread message %d", msg); 387b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine return ERROR; 388b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine } 389b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine } else { 390b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine /* Must be an FD. */ 3916aff44c27ee487bd65d5a1c74faf4b7165530bd4Steve Block ALOGW_IF(fd < 0 || !FD_ISSET(fd, fds), "%s: Undefined 'select' result", 392b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine __FUNCTION__); 393b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine return READY; 394b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine } 395b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine} 396b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine 397b97c2f0b5919b716ba5433e6153a29d7e1e357feVladimir Chtchetkine}; /* namespace android */ 398