am 819d2aac: Merge "EmulatedFakeCamera2: Add autofocus management" into jb-mr1-dev
* commit '819d2aac43d27100df59ee009c211169787b55dd': EmulatedFakeCamera2: Add autofocus management
This commit is contained in:
@@ -305,6 +305,7 @@ int EmulatedCamera2::trigger_action(const camera2_device_t *d,
|
|||||||
int EmulatedCamera2::set_notify_callback(const camera2_device_t *d,
|
int EmulatedCamera2::set_notify_callback(const camera2_device_t *d,
|
||||||
camera2_notify_callback notify_cb, void* user) {
|
camera2_notify_callback notify_cb, void* user) {
|
||||||
EmulatedCamera2* ec = getInstance(d);
|
EmulatedCamera2* ec = getInstance(d);
|
||||||
|
Mutex::Autolock l(ec->mMutex);
|
||||||
ec->mNotifyCb = notify_cb;
|
ec->mNotifyCb = notify_cb;
|
||||||
ec->mNotifyUserPtr = user;
|
ec->mNotifyUserPtr = user;
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
@@ -355,6 +356,18 @@ int EmulatedCamera2::close(struct hw_device_t* device) {
|
|||||||
return ec->closeCamera();
|
return ec->closeCamera();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmulatedCamera2::sendNotification(int32_t msgType,
|
||||||
|
int32_t ext1, int32_t ext2, int32_t ext3) {
|
||||||
|
camera2_notify_callback notifyCb;
|
||||||
|
{
|
||||||
|
Mutex::Autolock l(mMutex);
|
||||||
|
notifyCb = mNotifyCb;
|
||||||
|
}
|
||||||
|
if (notifyCb != NULL) {
|
||||||
|
notifyCb(msgType, ext1, ext2, ext3, mNotifyUserPtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
camera2_device_ops_t EmulatedCamera2::sDeviceOps = {
|
camera2_device_ops_t EmulatedCamera2::sDeviceOps = {
|
||||||
EmulatedCamera2::set_request_queue_src_ops,
|
EmulatedCamera2::set_request_queue_src_ops,
|
||||||
EmulatedCamera2::notify_request_queue_not_empty,
|
EmulatedCamera2::notify_request_queue_not_empty,
|
||||||
|
|||||||
@@ -28,6 +28,8 @@
|
|||||||
#include "hardware/camera2.h"
|
#include "hardware/camera2.h"
|
||||||
#include "system/camera_metadata.h"
|
#include "system/camera_metadata.h"
|
||||||
#include "EmulatedBaseCamera.h"
|
#include "EmulatedBaseCamera.h"
|
||||||
|
#include <utils/Thread.h>
|
||||||
|
#include <utils/Mutex.h>
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
@@ -128,7 +130,7 @@ protected:
|
|||||||
|
|
||||||
/** 3A action triggering */
|
/** 3A action triggering */
|
||||||
virtual int triggerAction(uint32_t trigger_id,
|
virtual int triggerAction(uint32_t trigger_id,
|
||||||
int ext1, int ext2);
|
int32_t ext1, int32_t ext2);
|
||||||
|
|
||||||
/** Custom tag definitions */
|
/** Custom tag definitions */
|
||||||
virtual const char* getVendorSectionName(uint32_t tag);
|
virtual const char* getVendorSectionName(uint32_t tag);
|
||||||
@@ -232,21 +234,27 @@ private:
|
|||||||
* Data members shared with implementations
|
* Data members shared with implementations
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
protected:
|
protected:
|
||||||
|
/** Mutex for calls through camera2 device interface */
|
||||||
|
Mutex mMutex;
|
||||||
|
|
||||||
const camera2_request_queue_src_ops *mRequestQueueSrc;
|
const camera2_request_queue_src_ops *mRequestQueueSrc;
|
||||||
const camera2_frame_queue_dst_ops *mFrameQueueDst;
|
const camera2_frame_queue_dst_ops *mFrameQueueDst;
|
||||||
camera2_notify_callback mNotifyCb;
|
|
||||||
void* mNotifyUserPtr;
|
|
||||||
|
|
||||||
struct TagOps : public vendor_tag_query_ops {
|
struct TagOps : public vendor_tag_query_ops {
|
||||||
EmulatedCamera2 *parent;
|
EmulatedCamera2 *parent;
|
||||||
};
|
};
|
||||||
TagOps mVendorTagOps;
|
TagOps mVendorTagOps;
|
||||||
|
|
||||||
|
void sendNotification(int32_t msgType,
|
||||||
|
int32_t ext1, int32_t ext2, int32_t ext3);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Data members
|
* Data members
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
private:
|
private:
|
||||||
static camera2_device_ops_t sDeviceOps;
|
static camera2_device_ops_t sDeviceOps;
|
||||||
|
camera2_notify_callback mNotifyCb;
|
||||||
|
void* mNotifyUserPtr;
|
||||||
};
|
};
|
||||||
|
|
||||||
}; /* namespace android */
|
}; /* namespace android */
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ status_t EmulatedFakeCamera2::connectCamera(hw_device_t** device) {
|
|||||||
|
|
||||||
mConfigureThread = new ConfigureThread(this);
|
mConfigureThread = new ConfigureThread(this);
|
||||||
mReadoutThread = new ReadoutThread(this);
|
mReadoutThread = new ReadoutThread(this);
|
||||||
|
mControlThread = new ControlThread(this);
|
||||||
mSensor = new Sensor(this);
|
mSensor = new Sensor(this);
|
||||||
mJpegCompressor = new JpegCompressor(this);
|
mJpegCompressor = new JpegCompressor(this);
|
||||||
|
|
||||||
@@ -147,6 +148,9 @@ status_t EmulatedFakeCamera2::connectCamera(hw_device_t** device) {
|
|||||||
res = mReadoutThread->run("EmulatedFakeCamera2::readoutThread");
|
res = mReadoutThread->run("EmulatedFakeCamera2::readoutThread");
|
||||||
if (res != NO_ERROR) return res;
|
if (res != NO_ERROR) return res;
|
||||||
|
|
||||||
|
res = mControlThread->run("EmulatedFakeCamera2::controlThread");
|
||||||
|
if (res != NO_ERROR) return res;
|
||||||
|
|
||||||
return EmulatedCamera2::connectCamera(device);
|
return EmulatedCamera2::connectCamera(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,11 +168,12 @@ status_t EmulatedFakeCamera2::closeCamera() {
|
|||||||
|
|
||||||
mConfigureThread->requestExit();
|
mConfigureThread->requestExit();
|
||||||
mReadoutThread->requestExit();
|
mReadoutThread->requestExit();
|
||||||
|
mControlThread->requestExit();
|
||||||
mJpegCompressor->cancel();
|
mJpegCompressor->cancel();
|
||||||
|
|
||||||
mConfigureThread->join();
|
mConfigureThread->join();
|
||||||
mReadoutThread->join();
|
mReadoutThread->join();
|
||||||
|
mControlThread->join();
|
||||||
|
|
||||||
ALOGV("%s exit", __FUNCTION__);
|
ALOGV("%s exit", __FUNCTION__);
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
@@ -431,6 +436,14 @@ int EmulatedFakeCamera2::releaseStream(uint32_t stream_id) {
|
|||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int EmulatedFakeCamera2::triggerAction(uint32_t trigger_id,
|
||||||
|
int32_t ext1,
|
||||||
|
int32_t ext2) {
|
||||||
|
Mutex::Autolock l(mMutex);
|
||||||
|
return mControlThread->triggerAction(trigger_id,
|
||||||
|
ext1, ext2);
|
||||||
|
}
|
||||||
|
|
||||||
/** Custom tag definitions */
|
/** Custom tag definitions */
|
||||||
|
|
||||||
// Emulator camera metadata sections
|
// Emulator camera metadata sections
|
||||||
@@ -535,8 +548,8 @@ void EmulatedFakeCamera2::signalError() {
|
|||||||
EmulatedFakeCamera2::ConfigureThread::ConfigureThread(EmulatedFakeCamera2 *parent):
|
EmulatedFakeCamera2::ConfigureThread::ConfigureThread(EmulatedFakeCamera2 *parent):
|
||||||
Thread(false),
|
Thread(false),
|
||||||
mParent(parent),
|
mParent(parent),
|
||||||
mNextBuffers(NULL),
|
mRequestCount(0),
|
||||||
mRequestCount(0) {
|
mNextBuffers(NULL) {
|
||||||
mRunning = false;
|
mRunning = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -635,7 +648,7 @@ bool EmulatedFakeCamera2::ConfigureThread::threadLoop() {
|
|||||||
}
|
}
|
||||||
// Get necessary parameters for sensor config
|
// Get necessary parameters for sensor config
|
||||||
|
|
||||||
sort_camera_metadata(mRequest);
|
mParent->mControlThread->processRequest(mRequest);
|
||||||
|
|
||||||
camera_metadata_entry_t streams;
|
camera_metadata_entry_t streams;
|
||||||
res = find_camera_metadata_entry(mRequest,
|
res = find_camera_metadata_entry(mRequest,
|
||||||
@@ -803,10 +816,9 @@ EmulatedFakeCamera2::ReadoutThread::ReadoutThread(EmulatedFakeCamera2 *parent):
|
|||||||
mParent(parent),
|
mParent(parent),
|
||||||
mRunning(false),
|
mRunning(false),
|
||||||
mActive(false),
|
mActive(false),
|
||||||
|
mRequestCount(0),
|
||||||
mRequest(NULL),
|
mRequest(NULL),
|
||||||
mBuffers(NULL),
|
mBuffers(NULL) {
|
||||||
mRequestCount(0)
|
|
||||||
{
|
|
||||||
mInFlightQueue = new InFlightQueue[kInFlightQueueSize];
|
mInFlightQueue = new InFlightQueue[kInFlightQueueSize];
|
||||||
mInFlightHead = 0;
|
mInFlightHead = 0;
|
||||||
mInFlightTail = 0;
|
mInFlightTail = 0;
|
||||||
@@ -1046,6 +1058,343 @@ bool EmulatedFakeCamera2::ReadoutThread::threadLoop() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EmulatedFakeCamera2::ControlThread::ControlThread(EmulatedFakeCamera2 *parent):
|
||||||
|
Thread(false),
|
||||||
|
mParent(parent) {
|
||||||
|
mRunning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmulatedFakeCamera2::ControlThread::~ControlThread() {
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t EmulatedFakeCamera2::ControlThread::readyToRun() {
|
||||||
|
Mutex::Autolock lock(mInputMutex);
|
||||||
|
|
||||||
|
ALOGV("Starting up ControlThread");
|
||||||
|
mRunning = true;
|
||||||
|
mStartAf = false;
|
||||||
|
mCancelAf = false;
|
||||||
|
mStartPrecapture = false;
|
||||||
|
|
||||||
|
mControlMode = ANDROID_CONTROL_AUTO;
|
||||||
|
|
||||||
|
mEffectMode = ANDROID_CONTROL_EFFECT_OFF;
|
||||||
|
mSceneMode = ANDROID_CONTROL_SCENE_MODE_FACE_PRIORITY;
|
||||||
|
|
||||||
|
mAfMode = ANDROID_CONTROL_AF_AUTO;
|
||||||
|
mAfModeChange = false;
|
||||||
|
|
||||||
|
mAeMode = ANDROID_CONTROL_AE_ON;
|
||||||
|
mAwbMode = ANDROID_CONTROL_AWB_AUTO;
|
||||||
|
|
||||||
|
mAfTriggerId = 0;
|
||||||
|
mPrecaptureTriggerId = 0;
|
||||||
|
|
||||||
|
mAfState = ANDROID_CONTROL_AF_STATE_INACTIVE;
|
||||||
|
mAeState = ANDROID_CONTROL_AE_STATE_INACTIVE;
|
||||||
|
mAwbState = ANDROID_CONTROL_AWB_STATE_INACTIVE;
|
||||||
|
|
||||||
|
mInputSignal.signal();
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t EmulatedFakeCamera2::ControlThread::waitUntilRunning() {
|
||||||
|
Mutex::Autolock lock(mInputMutex);
|
||||||
|
if (!mRunning) {
|
||||||
|
ALOGV("Waiting for control thread to start");
|
||||||
|
mInputSignal.wait(mInputMutex);
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t EmulatedFakeCamera2::ControlThread::processRequest(camera_metadata_t *request) {
|
||||||
|
Mutex::Autolock lock(mInputMutex);
|
||||||
|
// TODO: Add handling for all android.control.* fields here
|
||||||
|
camera_metadata_entry_t mode;
|
||||||
|
status_t res;
|
||||||
|
|
||||||
|
res = find_camera_metadata_entry(request,
|
||||||
|
ANDROID_CONTROL_MODE,
|
||||||
|
&mode);
|
||||||
|
mControlMode = mode.data.u8[0];
|
||||||
|
|
||||||
|
res = find_camera_metadata_entry(request,
|
||||||
|
ANDROID_CONTROL_EFFECT_MODE,
|
||||||
|
&mode);
|
||||||
|
mEffectMode = mode.data.u8[0];
|
||||||
|
|
||||||
|
res = find_camera_metadata_entry(request,
|
||||||
|
ANDROID_CONTROL_SCENE_MODE,
|
||||||
|
&mode);
|
||||||
|
mSceneMode = mode.data.u8[0];
|
||||||
|
|
||||||
|
res = find_camera_metadata_entry(request,
|
||||||
|
ANDROID_CONTROL_AF_MODE,
|
||||||
|
&mode);
|
||||||
|
if (mAfMode != mode.data.u8[0]) {
|
||||||
|
ALOGV("AF new mode: %d, old mode %d", mode.data.u8[0], mAfMode);
|
||||||
|
mAfMode = mode.data.u8[0];
|
||||||
|
mAfModeChange = true;
|
||||||
|
mStartAf = false;
|
||||||
|
mCancelAf = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = find_camera_metadata_entry(request,
|
||||||
|
ANDROID_CONTROL_AE_MODE,
|
||||||
|
&mode);
|
||||||
|
mAeMode = mode.data.u8[0];
|
||||||
|
|
||||||
|
res = find_camera_metadata_entry(request,
|
||||||
|
ANDROID_CONTROL_AWB_MODE,
|
||||||
|
&mode);
|
||||||
|
mAwbMode = mode.data.u8[0];
|
||||||
|
|
||||||
|
// TODO: Override control fields
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t EmulatedFakeCamera2::ControlThread::triggerAction(uint32_t msgType,
|
||||||
|
int32_t ext1, int32_t ext2) {
|
||||||
|
Mutex::Autolock lock(mInputMutex);
|
||||||
|
switch (msgType) {
|
||||||
|
case CAMERA2_TRIGGER_AUTOFOCUS:
|
||||||
|
mAfTriggerId = ext1;
|
||||||
|
mStartAf = true;
|
||||||
|
mCancelAf = false;
|
||||||
|
break;
|
||||||
|
case CAMERA2_TRIGGER_CANCEL_AUTOFOCUS:
|
||||||
|
mAfTriggerId = ext1;
|
||||||
|
mStartAf = false;
|
||||||
|
mCancelAf = true;
|
||||||
|
break;
|
||||||
|
case CAMERA2_TRIGGER_PRECAPTURE_METERING:
|
||||||
|
mPrecaptureTriggerId = ext1;
|
||||||
|
mStartPrecapture = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ALOGE("%s: Unknown action triggered: %d (arguments %d %d)",
|
||||||
|
__FUNCTION__, msgType, ext1, ext2);
|
||||||
|
return BAD_VALUE;
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nsecs_t EmulatedFakeCamera2::ControlThread::kControlCycleDelay = 100000000;
|
||||||
|
const nsecs_t EmulatedFakeCamera2::ControlThread::kMinAfDuration = 500000000;
|
||||||
|
const nsecs_t EmulatedFakeCamera2::ControlThread::kMaxAfDuration = 900000000;
|
||||||
|
const float EmulatedFakeCamera2::ControlThread::kAfSuccessRate = 0.9;
|
||||||
|
const float EmulatedFakeCamera2::ControlThread::kContinuousAfStartRate =
|
||||||
|
kControlCycleDelay / 5000000000.0; // Once every 5 seconds
|
||||||
|
|
||||||
|
bool EmulatedFakeCamera2::ControlThread::threadLoop() {
|
||||||
|
bool afModeChange = false;
|
||||||
|
bool afTriggered = false;
|
||||||
|
bool afCancelled = false;
|
||||||
|
uint8_t afState;
|
||||||
|
uint8_t afMode;
|
||||||
|
int32_t afTriggerId;
|
||||||
|
nsecs_t nextSleep = kControlCycleDelay;
|
||||||
|
|
||||||
|
{
|
||||||
|
Mutex::Autolock lock(mInputMutex);
|
||||||
|
if (mStartAf) {
|
||||||
|
afTriggered = true;
|
||||||
|
mStartAf = false;
|
||||||
|
} else if (mCancelAf) {
|
||||||
|
afCancelled = true;
|
||||||
|
mCancelAf = false;
|
||||||
|
}
|
||||||
|
afState = mAfState;
|
||||||
|
afMode = mAfMode;
|
||||||
|
afModeChange = mAfModeChange;
|
||||||
|
mAfModeChange = false;
|
||||||
|
|
||||||
|
afTriggerId = mAfTriggerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (afCancelled || afModeChange) {
|
||||||
|
ALOGV("Resetting AF state due to cancel/mode change");
|
||||||
|
afState = ANDROID_CONTROL_AF_STATE_INACTIVE;
|
||||||
|
updateAfState(afState, afTriggerId);
|
||||||
|
mAfScanDuration = 0;
|
||||||
|
mLockAfterPassiveScan = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t oldAfState = afState;
|
||||||
|
|
||||||
|
if (afTriggered) {
|
||||||
|
afState = processAfTrigger(afMode, afState);
|
||||||
|
}
|
||||||
|
|
||||||
|
afState = maybeStartAfScan(afMode, afState);
|
||||||
|
|
||||||
|
afState = updateAfScan(afMode, afState, &nextSleep);
|
||||||
|
|
||||||
|
updateAfState(afState, afTriggerId);
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
timespec t;
|
||||||
|
t.tv_sec = 0;
|
||||||
|
t.tv_nsec = nextSleep;
|
||||||
|
do {
|
||||||
|
ret = nanosleep(&t, &t);
|
||||||
|
} while (ret != 0);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int EmulatedFakeCamera2::ControlThread::processAfTrigger(uint8_t afMode,
|
||||||
|
uint8_t afState) {
|
||||||
|
switch (afMode) {
|
||||||
|
case ANDROID_CONTROL_AF_OFF:
|
||||||
|
case ANDROID_CONTROL_AF_EDOF:
|
||||||
|
// Do nothing
|
||||||
|
break;
|
||||||
|
case ANDROID_CONTROL_AF_MACRO:
|
||||||
|
case ANDROID_CONTROL_AF_AUTO:
|
||||||
|
switch (afState) {
|
||||||
|
case ANDROID_CONTROL_AF_STATE_INACTIVE:
|
||||||
|
case ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED:
|
||||||
|
case ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED:
|
||||||
|
// Start new focusing cycle
|
||||||
|
mAfScanDuration = ((double)rand() / RAND_MAX) *
|
||||||
|
(kMaxAfDuration - kMinAfDuration) + kMinAfDuration;
|
||||||
|
afState = ANDROID_CONTROL_AF_STATE_ACTIVE_SCAN;
|
||||||
|
ALOGV("%s: AF scan start, duration %lld ms",
|
||||||
|
__FUNCTION__, mAfScanDuration / 1000000);
|
||||||
|
break;
|
||||||
|
case ANDROID_CONTROL_AF_STATE_ACTIVE_SCAN:
|
||||||
|
// Ignore new request, already scanning
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ALOGE("Unexpected AF state in AUTO/MACRO AF mode: %d",
|
||||||
|
afState);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ANDROID_CONTROL_AF_CONTINUOUS_PICTURE:
|
||||||
|
switch (afState) {
|
||||||
|
// Picture mode waits for passive scan to complete
|
||||||
|
case ANDROID_CONTROL_AF_STATE_PASSIVE_SCAN:
|
||||||
|
mLockAfterPassiveScan = true;
|
||||||
|
break;
|
||||||
|
case ANDROID_CONTROL_AF_STATE_INACTIVE:
|
||||||
|
afState = ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED;
|
||||||
|
break;
|
||||||
|
case ANDROID_CONTROL_AF_STATE_PASSIVE_FOCUSED:
|
||||||
|
afState = ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED;
|
||||||
|
break;
|
||||||
|
case ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED:
|
||||||
|
case ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED:
|
||||||
|
// Must cancel to get out of these states
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ALOGE("Unexpected AF state in CONTINUOUS_PICTURE AF mode: %d",
|
||||||
|
afState);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ANDROID_CONTROL_AF_CONTINUOUS_VIDEO:
|
||||||
|
switch (afState) {
|
||||||
|
// Video mode does not wait for passive scan to complete
|
||||||
|
case ANDROID_CONTROL_AF_STATE_PASSIVE_SCAN:
|
||||||
|
case ANDROID_CONTROL_AF_STATE_INACTIVE:
|
||||||
|
afState = ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED;
|
||||||
|
break;
|
||||||
|
case ANDROID_CONTROL_AF_STATE_PASSIVE_FOCUSED:
|
||||||
|
afState = ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED;
|
||||||
|
break;
|
||||||
|
case ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED:
|
||||||
|
case ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED:
|
||||||
|
// Must cancel to get out of these states
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ALOGE("Unexpected AF state in CONTINUOUS_VIDEO AF mode: %d",
|
||||||
|
afState);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return afState;
|
||||||
|
}
|
||||||
|
|
||||||
|
int EmulatedFakeCamera2::ControlThread::maybeStartAfScan(uint8_t afMode,
|
||||||
|
uint8_t afState) {
|
||||||
|
if ((afMode == ANDROID_CONTROL_AF_CONTINUOUS_VIDEO ||
|
||||||
|
afMode == ANDROID_CONTROL_AF_CONTINUOUS_PICTURE) &&
|
||||||
|
(afState == ANDROID_CONTROL_AF_STATE_INACTIVE ||
|
||||||
|
afState == ANDROID_CONTROL_AF_STATE_PASSIVE_FOCUSED)) {
|
||||||
|
|
||||||
|
bool startScan = ((double)rand() / RAND_MAX) < kContinuousAfStartRate;
|
||||||
|
if (startScan) {
|
||||||
|
// Start new passive focusing cycle
|
||||||
|
mAfScanDuration = ((double)rand() / RAND_MAX) *
|
||||||
|
(kMaxAfDuration - kMinAfDuration) + kMinAfDuration;
|
||||||
|
afState = ANDROID_CONTROL_AF_STATE_PASSIVE_SCAN;
|
||||||
|
ALOGV("%s: AF passive scan start, duration %lld ms",
|
||||||
|
__FUNCTION__, mAfScanDuration / 1000000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return afState;
|
||||||
|
}
|
||||||
|
|
||||||
|
int EmulatedFakeCamera2::ControlThread::updateAfScan(uint8_t afMode,
|
||||||
|
uint8_t afState, nsecs_t *maxSleep) {
|
||||||
|
if (! (afState == ANDROID_CONTROL_AF_STATE_ACTIVE_SCAN ||
|
||||||
|
afState == ANDROID_CONTROL_AF_STATE_PASSIVE_SCAN ) ) {
|
||||||
|
return afState;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mAfScanDuration == 0) {
|
||||||
|
ALOGV("%s: AF scan done", __FUNCTION__);
|
||||||
|
switch (afMode) {
|
||||||
|
case ANDROID_CONTROL_AF_MACRO:
|
||||||
|
case ANDROID_CONTROL_AF_AUTO: {
|
||||||
|
bool success = ((double)rand() / RAND_MAX) < kAfSuccessRate;
|
||||||
|
if (success) {
|
||||||
|
afState = ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED;
|
||||||
|
} else {
|
||||||
|
afState = ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ANDROID_CONTROL_AF_CONTINUOUS_PICTURE:
|
||||||
|
if (mLockAfterPassiveScan) {
|
||||||
|
afState = ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED;
|
||||||
|
mLockAfterPassiveScan = false;
|
||||||
|
} else {
|
||||||
|
afState = ANDROID_CONTROL_AF_STATE_PASSIVE_FOCUSED;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ANDROID_CONTROL_AF_CONTINUOUS_VIDEO:
|
||||||
|
afState = ANDROID_CONTROL_AF_STATE_PASSIVE_FOCUSED;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ALOGE("Unexpected AF mode in scan state");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (mAfScanDuration <= *maxSleep) {
|
||||||
|
*maxSleep = mAfScanDuration;
|
||||||
|
mAfScanDuration = 0;
|
||||||
|
} else {
|
||||||
|
mAfScanDuration -= *maxSleep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return afState;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmulatedFakeCamera2::ControlThread::updateAfState(uint8_t newState,
|
||||||
|
int32_t triggerId) {
|
||||||
|
Mutex::Autolock lock(mInputMutex);
|
||||||
|
if (mAfState != newState) {
|
||||||
|
ALOGV("%s: Autofocus state now %d, id %d", __FUNCTION__,
|
||||||
|
newState, triggerId);
|
||||||
|
mAfState = newState;
|
||||||
|
mParent->sendNotification(CAMERA2_MSG_AUTOFOCUS,
|
||||||
|
newState, triggerId, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Private methods */
|
/** Private methods */
|
||||||
|
|
||||||
status_t EmulatedFakeCamera2::constructStaticInfo(
|
status_t EmulatedFakeCamera2::constructStaticInfo(
|
||||||
@@ -1062,9 +1411,12 @@ status_t EmulatedFakeCamera2::constructStaticInfo(
|
|||||||
|
|
||||||
// android.lens
|
// android.lens
|
||||||
|
|
||||||
static const float minFocusDistance = 0;
|
// 5 cm min focus distance for back camera, infinity (fixed focus) for front
|
||||||
|
const float minFocusDistance = mFacingBack ? 1.0/0.05 : 0.0;
|
||||||
ADD_OR_SIZE(ANDROID_LENS_MINIMUM_FOCUS_DISTANCE,
|
ADD_OR_SIZE(ANDROID_LENS_MINIMUM_FOCUS_DISTANCE,
|
||||||
&minFocusDistance, 1);
|
&minFocusDistance, 1);
|
||||||
|
// 5 m hyperfocal distance for back camera, infinity (fixed focus) for front
|
||||||
|
const float hyperFocalDistance = mFacingBack ? 1.0/5.0 : 0.0;
|
||||||
ADD_OR_SIZE(ANDROID_LENS_HYPERFOCAL_DISTANCE,
|
ADD_OR_SIZE(ANDROID_LENS_HYPERFOCAL_DISTANCE,
|
||||||
&minFocusDistance, 1);
|
&minFocusDistance, 1);
|
||||||
|
|
||||||
@@ -1323,11 +1675,25 @@ status_t EmulatedFakeCamera2::constructStaticInfo(
|
|||||||
ADD_OR_SIZE(ANDROID_CONTROL_AWB_AVAILABLE_MODES,
|
ADD_OR_SIZE(ANDROID_CONTROL_AWB_AVAILABLE_MODES,
|
||||||
availableAwbModes, sizeof(availableAwbModes));
|
availableAwbModes, sizeof(availableAwbModes));
|
||||||
|
|
||||||
static const uint8_t availableAfModes[] = {
|
static const uint8_t availableAfModesBack[] = {
|
||||||
|
ANDROID_CONTROL_AF_OFF,
|
||||||
|
ANDROID_CONTROL_AF_AUTO,
|
||||||
|
ANDROID_CONTROL_AF_MACRO,
|
||||||
|
ANDROID_CONTROL_AF_CONTINUOUS_VIDEO,
|
||||||
|
ANDROID_CONTROL_AF_CONTINUOUS_PICTURE
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t availableAfModesFront[] = {
|
||||||
ANDROID_CONTROL_AF_OFF
|
ANDROID_CONTROL_AF_OFF
|
||||||
};
|
};
|
||||||
ADD_OR_SIZE(ANDROID_CONTROL_AF_AVAILABLE_MODES,
|
|
||||||
availableAfModes, sizeof(availableAfModes));
|
if (mFacingBack) {
|
||||||
|
ADD_OR_SIZE(ANDROID_CONTROL_AF_AVAILABLE_MODES,
|
||||||
|
availableAfModesBack, sizeof(availableAfModesBack));
|
||||||
|
} else {
|
||||||
|
ADD_OR_SIZE(ANDROID_CONTROL_AF_AVAILABLE_MODES,
|
||||||
|
availableAfModesFront, sizeof(availableAfModesFront));
|
||||||
|
}
|
||||||
|
|
||||||
static const uint8_t availableVstabModes[] = {
|
static const uint8_t availableVstabModes[] = {
|
||||||
ANDROID_CONTROL_VIDEO_STABILIZATION_OFF
|
ANDROID_CONTROL_VIDEO_STABILIZATION_OFF
|
||||||
|
|||||||
@@ -31,7 +31,6 @@
|
|||||||
#include <utils/KeyedVector.h>
|
#include <utils/KeyedVector.h>
|
||||||
#include <utils/String8.h>
|
#include <utils/String8.h>
|
||||||
#include <utils/String16.h>
|
#include <utils/String16.h>
|
||||||
#include <utils/Thread.h>
|
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
@@ -113,9 +112,9 @@ protected:
|
|||||||
|
|
||||||
// virtual int releaseReprocessStream(uint32_t stream_id);
|
// virtual int releaseReprocessStream(uint32_t stream_id);
|
||||||
|
|
||||||
// virtual int triggerAction(uint32_t trigger_id,
|
virtual int triggerAction(uint32_t trigger_id,
|
||||||
// int ext1,
|
int32_t ext1,
|
||||||
// int ext2);
|
int32_t ext2);
|
||||||
|
|
||||||
/** Custom tag definitions */
|
/** Custom tag definitions */
|
||||||
virtual const char* getVendorSectionName(uint32_t tag);
|
virtual const char* getVendorSectionName(uint32_t tag);
|
||||||
@@ -245,6 +244,80 @@ private:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 3A management thread (auto-exposure, focus, white balance)
|
||||||
|
class ControlThread: public Thread {
|
||||||
|
public:
|
||||||
|
ControlThread(EmulatedFakeCamera2 *parent);
|
||||||
|
~ControlThread();
|
||||||
|
|
||||||
|
status_t readyToRun();
|
||||||
|
|
||||||
|
status_t waitUntilRunning();
|
||||||
|
|
||||||
|
// Interpret request's control parameters and override
|
||||||
|
// capture settings as needed
|
||||||
|
status_t processRequest(camera_metadata_t *request);
|
||||||
|
|
||||||
|
status_t triggerAction(uint32_t msgType,
|
||||||
|
int32_t ext1, int32_t ext2);
|
||||||
|
private:
|
||||||
|
ControlThread(const ControlThread &t);
|
||||||
|
ControlThread& operator=(const ControlThread &t);
|
||||||
|
|
||||||
|
// Constants controlling fake 3A behavior
|
||||||
|
static const nsecs_t kControlCycleDelay;
|
||||||
|
static const nsecs_t kMinAfDuration;
|
||||||
|
static const nsecs_t kMaxAfDuration;
|
||||||
|
static const float kAfSuccessRate;
|
||||||
|
static const float kContinuousAfStartRate;
|
||||||
|
|
||||||
|
EmulatedFakeCamera2 *mParent;
|
||||||
|
|
||||||
|
bool mRunning;
|
||||||
|
bool threadLoop();
|
||||||
|
|
||||||
|
Mutex mInputMutex; // Protects input methods
|
||||||
|
Condition mInputSignal;
|
||||||
|
|
||||||
|
// Trigger notifications
|
||||||
|
bool mStartAf;
|
||||||
|
bool mCancelAf;
|
||||||
|
bool mStartPrecapture;
|
||||||
|
|
||||||
|
// Latest state for 3A request fields
|
||||||
|
uint8_t mControlMode;
|
||||||
|
|
||||||
|
uint8_t mEffectMode;
|
||||||
|
uint8_t mSceneMode;
|
||||||
|
|
||||||
|
uint8_t mAfMode;
|
||||||
|
bool mAfModeChange;
|
||||||
|
|
||||||
|
uint8_t mAwbMode;
|
||||||
|
uint8_t mAeMode;
|
||||||
|
|
||||||
|
// Latest trigger IDs
|
||||||
|
int32_t mAfTriggerId;
|
||||||
|
int32_t mPrecaptureTriggerId;
|
||||||
|
|
||||||
|
// Current state for 3A algorithms
|
||||||
|
uint8_t mAfState;
|
||||||
|
uint8_t mAeState;
|
||||||
|
uint8_t mAwbState;
|
||||||
|
|
||||||
|
// Private to threadLoop and its utility methods
|
||||||
|
|
||||||
|
nsecs_t mAfScanDuration;
|
||||||
|
bool mLockAfterPassiveScan;
|
||||||
|
|
||||||
|
// Utility methods
|
||||||
|
int processAfTrigger(uint8_t afMode, uint8_t afState);
|
||||||
|
int maybeStartAfScan(uint8_t afMode, uint8_t afState);
|
||||||
|
int updateAfScan(uint8_t afMode, uint8_t afState, nsecs_t *maxSleep);
|
||||||
|
void updateAfState(uint8_t newState, int32_t triggerId);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Static configuration information
|
* Static configuration information
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
@@ -271,9 +344,6 @@ protected:
|
|||||||
bool mFacingBack;
|
bool mFacingBack;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Mutex for calls through camera2 device interface */
|
|
||||||
Mutex mMutex;
|
|
||||||
|
|
||||||
/** Stream manipulation */
|
/** Stream manipulation */
|
||||||
uint32_t mNextStreamId;
|
uint32_t mNextStreamId;
|
||||||
uint32_t mRawStreamCount;
|
uint32_t mRawStreamCount;
|
||||||
@@ -289,6 +359,7 @@ private:
|
|||||||
/** Pipeline control threads */
|
/** Pipeline control threads */
|
||||||
sp<ConfigureThread> mConfigureThread;
|
sp<ConfigureThread> mConfigureThread;
|
||||||
sp<ReadoutThread> mReadoutThread;
|
sp<ReadoutThread> mReadoutThread;
|
||||||
|
sp<ControlThread> mControlThread;
|
||||||
};
|
};
|
||||||
|
|
||||||
}; /* namespace android */
|
}; /* namespace android */
|
||||||
|
|||||||
Reference in New Issue
Block a user