blob: d76e5c220bd36df4afb956027f15f0d480ad3351 [file] [log] [blame]
/*
**
** Copyright 2014, Samsung Electronics Co. LTD
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/* #define LOG_NDEBUG 0 */
#define LOG_TAG "ExynosCameraFrameManager"
#include <cutils/log.h>
#include "ExynosCameraFrameManager.h"
namespace android {
#define CREATE_WORKER_DEFAULT_MARGIN_MAX 200
#define CREATE_WORKER_DEFAULT_MARGIN_MIN 100
#define DELETE_WORKER_DEFAULT_MARGIN_MAX 200
#define RUN_THREAD_TIMEOUT (5000000000L) /* 5 sec */
FrameWorker::FrameWorker(const char* name, int cameraid, FRAMEMGR_OPER::MODE operMode)
{
m_cameraId = cameraid;
strncpy(m_name, name, EXYNOS_CAMERA_NAME_STR_SIZE - 1);
m_operMode = operMode;
m_init();
}
FrameWorker::~FrameWorker()
{
m_deinit();
}
status_t FrameWorker::m_init()
{
m_key = 0;
m_enable = false;
return 0;
}
status_t FrameWorker::m_deinit()
{
return 0;
}
uint32_t FrameWorker::getKey()
{
return m_key;
}
status_t FrameWorker::setKey(uint32_t key)
{
m_key = key;
return 0;
}
status_t FrameWorker::dump()
{
CLOGE(" do not support dump function.");
return NO_ERROR;
}
frame_key_queue_t* FrameWorker::getQueue()
{
CLOGE(" do not support getQueue function.");
return NULL;
}
status_t FrameWorker::m_setEnable(bool enable)
{
Mutex::Autolock lock(m_enableLock);
status_t ret = FRAMEMGR_ERRCODE::OK;
m_enable = enable;
return ret;
}
bool FrameWorker::m_getEnable()
{
Mutex::Autolock lock(m_enableLock);
return m_enable;
}
status_t FrameWorker::m_setMargin(int32_t maxMargin, int32_t minMargin)
{
int32_t ret = FRAMEMGR_ERRCODE::OK;
int32_t oldMin = m_nMinMargin;
int32_t oldMax = m_nMaxMargin;
if (minMargin <= 0)
m_nMinMargin = CREATE_WORKER_DEFAULT_MARGIN_MIN;
else
m_nMinMargin = minMargin;
if (maxMargin <= 0)
m_nMaxMargin = CREATE_WORKER_DEFAULT_MARGIN_MAX;
else
m_nMaxMargin = maxMargin;
if ((oldMin != m_nMinMargin) || (oldMax != m_nMaxMargin)) {
CLOGD("margin is updated, margin[MAX/MIN]=(%d x %d) -> (%d x %d)", oldMax, oldMin, m_nMaxMargin, m_nMinMargin);
}
return ret;
}
int32_t FrameWorker::m_getMargin(FrameMargin marginType)
{
int32_t ret = 0;
switch(marginType) {
case FRAME_MARGIN_MIN:
ret = m_nMinMargin;
break;
case FRAME_MARGIN_MAX:
ret = m_nMaxMargin;
break;
}
return ret;
}
CreateWorker::CreateWorker(const char* name,
int cameraid,
FRAMEMGR_OPER::MODE operMode,
int32_t maxMargin,
int32_t minMargin):FrameWorker(name, cameraid, operMode)
{
CLOGD(" Worker CREATE(name(%s) cameraid(%d) mode(%d) min_margin(%d) max_margin(%d) ",
name, cameraid, operMode, minMargin, maxMargin);
m_init();
m_setMargin(maxMargin, minMargin);
}
CreateWorker::~CreateWorker()
{
CLOGD(" Worker DELETE(name(%s) cameraid(%d) mode(%d) ",
m_name, m_cameraId, m_operMode);
m_deinit();
}
status_t CreateWorker::m_deinit()
{
int32_t ret = FRAMEMGR_ERRCODE::OK;
ExynosCameraFrameSP_sptr_t frame = NULL;
switch (m_operMode) {
case FRAMEMGR_OPER::ONDEMAND:
m_setEnable(false);
if (m_worklist != NULL) {
delete m_worklist;
m_worklist = NULL;
}
if (m_lock != NULL) {
delete m_lock;
m_lock = NULL;
}
break;
case FRAMEMGR_OPER::SLIENT:
m_setEnable(false);
m_command.sendCommand(FrameWorkerCommand::STOP);
m_thread->requestExitAndWait();
m_command.cmdQ.release();
m_setMargin(0, 0);
if (m_worklist != NULL) {
while (m_worklist->getSizeOfProcessQ() > 0) {
m_worklist->popProcessQ(&frame);
frame = NULL;
}
delete m_worklist;
m_worklist = NULL;
}
if (m_lock != NULL) {
delete m_lock;
m_lock = NULL;
}
break;
case FRAMEMGR_OPER::NONE:
default:
CLOGE(" operMode is invalid operMode(%d)", m_operMode);
break;
}
return ret;
}
Mutex* CreateWorker::getLock()
{
return m_lock;
}
status_t CreateWorker::execute(__unused ExynosCameraFrameSP_sptr_t inframe, ExynosCameraFrameSP_dptr_t outframe)
{
int32_t ret = FRAMEMGR_ERRCODE::OK;
if (m_getEnable() == false) {
CLOGE(" invalid state, Need to start Worker before execute");
ret = FRAMEMGR_ERRCODE::ERR;
return ret;
}
outframe = m_execute();
if (outframe == NULL) {
CLOGE(" m_execute is invalid (outframe = NULL)");
ret = FRAMEMGR_ERRCODE::ERR;
}
return ret;
}
status_t CreateWorker::setMargin(int32_t max, int32_t min)
{
int32_t ret = FRAMEMGR_ERRCODE::OK;
if (m_getEnable() == true) {
CLOGE("invalid state, Need to stop Worker before update Info(%d %d)", min, max);
ret = FRAMEMGR_ERRCODE::ERR;
return ret;
}
m_setMargin(max, min);
return ret;
}
status_t CreateWorker::start()
{
if (m_worklist->getSizeOfProcessQ() > 0) {
CLOGD("previous worklist size(%d)",
m_worklist->getSizeOfProcessQ());
m_worklist->release();
}
switch (m_operMode) {
case FRAMEMGR_OPER::ONDEMAND:
m_setEnable(true);
break;
case FRAMEMGR_OPER::SLIENT:
m_setEnable(true);
m_command.sendCommand(FrameWorkerCommand::START);
if (m_thread->isRunning() == false) {
m_command.sendCommand(FrameWorkerCommand::START);
}
break;
case FRAMEMGR_OPER::NONE:
default:
CLOGE(" operMode is invalid operMode(%d)", m_operMode);
break;
}
return 0;
}
status_t CreateWorker::stop()
{
ExynosCameraFrameSP_sptr_t frame = NULL;
switch (m_operMode) {
case FRAMEMGR_OPER::ONDEMAND:
m_setEnable(false);
break;
case FRAMEMGR_OPER::SLIENT:
m_setEnable(false);
m_command.sendCommand(FrameWorkerCommand::STOP);
m_thread->requestExitAndWait();
CLOGD(" worker stopped remove ths remained frames(%d)",
m_worklist->getSizeOfProcessQ());
while (m_worklist->getSizeOfProcessQ() > 0) {
m_worklist->popProcessQ(&frame);
frame = NULL;
}
break;
case FRAMEMGR_OPER::NONE:
default:
CLOGE(" operMode is invalid operMode(%d)", m_operMode);
break;
}
return 0;
}
ExynosCameraFrameSP_sptr_t CreateWorker::m_execute()
{
ExynosCameraFrameSP_sptr_t frame = NULL;
int32_t ret = NO_ERROR;
switch (m_operMode) {
case FRAMEMGR_OPER::ONDEMAND:
frame = new ExynosCameraFrame(m_cameraId);
break;
case FRAMEMGR_OPER::SLIENT:
m_worklist->popProcessQ(&frame);
if (frame == NULL) {
m_command.sendCommand(FrameWorkerCommand::START);
m_worklist->waitAndPopProcessQ(&frame);
}
if (frame == NULL) {
CLOGE("waitAndPopProcessQ failed, processQ size (%d) Thread return (%d) Status (%d)", m_worklist->getSizeOfProcessQ(), ret, m_thread->isRunning());
}
if (m_worklist->getSizeOfProcessQ() <= m_getMargin(FRAME_MARGIN_MIN))
m_command.sendCommand(FrameWorkerCommand::START);
break;
case FRAMEMGR_OPER::NONE:
default:
CLOGE(" operMode is invalid operMode(%d)", m_operMode);
break;
}
return frame;
}
status_t CreateWorker::m_init()
{
int32_t ret = FRAMEMGR_ERRCODE::OK;
switch (m_operMode) {
case FRAMEMGR_OPER::ONDEMAND:
m_worklist = new frame_manager_queue_t;
m_lock = new Mutex();
break;
case FRAMEMGR_OPER::SLIENT:
m_thread = new FrameManagerThread(this,
static_cast<func_ptr_t_>(&CreateWorker::workerMain),
"Create Frame Thread",
PRIORITY_URGENT_DISPLAY);
m_worklist = new frame_manager_queue_t;
m_lock = new Mutex();
m_command.cmdQ.setWaitTime(RUN_THREAD_TIMEOUT);
m_command.cmdQ.setup(m_thread);
break;
case FRAMEMGR_OPER::NONE:
default:
m_worklist = NULL;
m_lock = NULL;
CLOGE(" operMode is invalid operMode(%d)", m_operMode);
ret = FRAMEMGR_ERRCODE::ERR;
break;
}
return ret;
}
bool CreateWorker::workerMain()
{
#ifdef DEBUG
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
#endif
int32_t ret = FRAMEMGR_ERRCODE::OK;
bool loop = true;
ExynosCameraFrameSP_sptr_t frame = NULL;
uint32_t cmd = 0;
#if defined EXYNOS_CAMERA_FRAME_CREATE_PERFORMANCE
uint32_t count = 0;
#endif
if ((ret = m_command.waitCommand(&cmd)) < 0) {
if (ret == TIMED_OUT)
CLOGD("waiting time is expired");
else
CLOGE("wait and pop fail, restart, ret(%s(%d))", "ERROR", ret);
return loop;
}
#if defined EXYNOS_CAMERA_FRAME_CREATE_PERFORMANCE
count = 0;
m_createTimer.start();
#endif
while ((m_getEnable() == true) && (cmd == FrameWorkerCommand::START)
&& (m_worklist->getSizeOfProcessQ() < m_getMargin(FRAME_MARGIN_MAX))) {
frame = NULL;
frame = new ExynosCameraFrame(m_cameraId);
m_worklist->pushProcessQ(&frame);
#if defined EXYNOS_CAMERA_FRAME_CREATE_PERFORMANCE
count++;
#endif
}
#if defined EXYNOS_CAMERA_FRAME_CREATE_PERFORMANCE
m_createTimer.stop();
/* check performance frame create, total generated frame count * 1ms */
if ((count > 0) && (m_createTimer.durationMsecs() > count))
CLOGE("Total generated frameCount(%d) duration(%ju msec)", count, m_createTimer.durationMsecs());
#endif
if ((m_getEnable() == false) && (cmd == FrameWorkerCommand::STOP)) {
loop = false;
CLOGD(" Create worker stopped delete current frame(%d)",
m_worklist->getSizeOfProcessQ());
m_worklist->release();
}
return loop;
}
DeleteWorker::DeleteWorker(const char* name,
int cameraid,
FRAMEMGR_OPER::MODE operMode,
int32_t maxMargin):FrameWorker(name, cameraid, operMode)
{
CLOGD(" Worker CREATE(name(%s) cameraid(%d) mode(%d) ",
name, cameraid, operMode);
m_operMode = operMode;
m_setMargin(maxMargin, 0);
m_init();
}
DeleteWorker::~DeleteWorker()
{
CLOGD(" Worker DELETE(name(%s) cameraid(%d) mode(%d) ",
m_name, m_cameraId, m_operMode);
m_deinit();
}
status_t DeleteWorker::m_deinit()
{
int32_t ret = FRAMEMGR_ERRCODE::OK;
ExynosCameraFrameSP_sptr_t frame = NULL;
switch (m_operMode) {
case FRAMEMGR_OPER::ONDEMAND:
m_setEnable(false);
if (m_worklist != NULL) {
delete m_worklist;
m_worklist = NULL;
}
if (m_lock != NULL) {
delete m_lock;
m_lock = NULL;
}
break;
case FRAMEMGR_OPER::SLIENT:
m_setEnable(false);
m_command.sendCommand(FrameWorkerCommand::STOP);
m_thread->requestExitAndWait();
m_command.cmdQ.release();
m_setMargin(0, 0);
if (m_worklist != NULL) {
m_worklist->release();
delete m_worklist;
m_worklist = NULL;
}
if (m_lock != NULL) {
delete m_lock;
m_lock = NULL;
}
break;
case FRAMEMGR_OPER::NONE:
default:
CLOGE(" operMode is invalid operMode(%d)", m_operMode);
break;
}
return ret;
}
Mutex* DeleteWorker::getLock()
{
return m_lock;
}
status_t DeleteWorker::execute(ExynosCameraFrameSP_sptr_t inframe, __unused ExynosCameraFrameSP_dptr_t outframe)
{
status_t ret = FRAMEMGR_ERRCODE::OK;
if (m_getEnable() == false) {
CLOGE(" invalid state, Need to start Worker before execute");
ret = FRAMEMGR_ERRCODE::ERR;
return ret;
}
ret = m_execute(inframe);
if (ret < 0) {
CLOGE(" m_execute is invalid ret(%d)", ret);
ret = FRAMEMGR_ERRCODE::ERR;
}
return ret;
}
status_t DeleteWorker::start()
{
if (m_worklist->getSizeOfProcessQ() > 0) {
CLOGD("previous worklist size(%d), clear worklist",
m_worklist->getSizeOfProcessQ());
m_worklist->release();
}
switch (m_operMode) {
case FRAMEMGR_OPER::ONDEMAND:
m_setEnable(true);
break;
case FRAMEMGR_OPER::SLIENT:
m_setEnable(true);
m_command.sendCommand(FrameWorkerCommand::START);
if (m_thread->isRunning() == false)
m_command.sendCommand(FrameWorkerCommand::START);
break;
case FRAMEMGR_OPER::NONE:
default:
CLOGE(" operMode is invalid operMode(%d)", m_operMode);
break;
}
return 0;
}
status_t DeleteWorker::stop()
{
ExynosCameraFrameSP_sptr_t frame = NULL;
switch (m_operMode) {
case FRAMEMGR_OPER::ONDEMAND:
m_setEnable(false);
break;
case FRAMEMGR_OPER::SLIENT:
m_setEnable(false);
m_command.sendCommand(FrameWorkerCommand::STOP);
m_thread->requestExitAndWait();
CLOGD(" worker stopped remove ths remained frames(%d)",
m_worklist->getSizeOfProcessQ());
m_worklist->release();
break;
case FRAMEMGR_OPER::NONE:
default:
CLOGE(" operMode is invalid operMode(%d)", m_operMode);
break;
}
return 0;
}
status_t DeleteWorker::m_setMargin(int32_t maxMargin, int32_t minMargin)
{
int32_t ret = FRAMEMGR_ERRCODE::OK;
m_nMinMargin = minMargin;
if (maxMargin <= 0)
m_nMaxMargin = DELETE_WORKER_DEFAULT_MARGIN_MAX;
return ret;
}
status_t DeleteWorker::m_execute(ExynosCameraFrameSP_sptr_t frame)
{
int32_t ret = FRAMEMGR_ERRCODE::OK;
switch (m_operMode) {
case FRAMEMGR_OPER::ONDEMAND:
frame = NULL;
break;
case FRAMEMGR_OPER::SLIENT:
m_worklist->pushProcessQ(&frame);
if (m_worklist->getSizeOfProcessQ() > m_getMargin(FRAME_MARGIN_MAX))
m_command.sendCommand(FrameWorkerCommand::START);
break;
case FRAMEMGR_OPER::NONE:
default:
ret = FRAMEMGR_ERRCODE::ERR;
CLOGE(" operMode is invalid operMode(%d)", m_operMode);
break;
}
return ret;
}
status_t DeleteWorker::m_init()
{
int32_t ret = FRAMEMGR_ERRCODE::OK;
switch (m_operMode) {
case FRAMEMGR_OPER::ONDEMAND:
m_worklist = new frame_manager_queue_t;
m_lock = new Mutex();
break;
case FRAMEMGR_OPER::SLIENT:
m_thread = new FrameManagerThread(this,
static_cast<func_ptr_t_>(&DeleteWorker::workerMain),
"Delete Frame Thread",
PRIORITY_URGENT_DISPLAY);
m_worklist = new frame_manager_queue_t;
m_lock = new Mutex();
m_command.cmdQ.setWaitTime(RUN_THREAD_TIMEOUT);
m_command.cmdQ.setup(m_thread);
break;
case FRAMEMGR_OPER::NONE:
default:
m_worklist = NULL;
m_lock = NULL;
ret = FRAMEMGR_ERRCODE::ERR;
CLOGE(" operMode is invalid operMode(%d)", m_operMode);
break;
}
return ret;
}
bool DeleteWorker::workerMain()
{
#ifdef DEBUG
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
#endif
int32_t ret = FRAMEMGR_ERRCODE::OK;
bool loop = true;
ExynosCameraFrameSP_sptr_t frame = NULL;
uint32_t cmd = 0;
if ((ret = m_command.waitCommand(&cmd)) < 0) {
if (ret == TIMED_OUT)
CLOGD("waiting time is expired");
else
CLOGE("wait and pop fail, restart, ret(%s(%d))", "ERROR", ret);
return loop;
}
m_worklist->release();
if ((m_getEnable() == false) && (cmd == FrameWorkerCommand::STOP)) {
loop = false;
}
return loop;
}
RunWorker::RunWorker(const char* name,
int cameraid,
FRAMEMGR_OPER::MODE operMode,
int32_t margin,
uint32_t dumpMargin):FrameWorker(name, cameraid, operMode)
{
CLOGD(" Worker CREATE(name(%s) cameraid(%d) mode(%d) ", name, cameraid, operMode);
m_framekeyQueue = NULL;
m_numOfMargin = margin;
m_numOfDumpMargin = dumpMargin;
m_init();
}
RunWorker::~RunWorker()
{
CLOGD(" Worker DELETE(name(%s) cameraid(%d) mode(%d) ", m_name, m_cameraId, m_operMode);
m_deinit();
}
status_t RunWorker::m_deinit()
{
int32_t ret = FRAMEMGR_ERRCODE::OK;
ExynosCameraFrameSP_sptr_t frame = NULL;
switch (m_operMode) {
case FRAMEMGR_OPER::ONDEMAND:
m_setEnable(false);
m_worklist.clear();
if (m_framekeyQueue != NULL) {
m_framekeyQueue->release();
delete m_framekeyQueue;
m_framekeyQueue = NULL;
}
break;
case FRAMEMGR_OPER::SLIENT:
m_setEnable(false);
m_thread->requestExit();
m_framekeyQueue->wakeupAll();
m_thread->requestExitAndWait();
m_worklist.clear();
if (m_framekeyQueue != NULL) {
m_framekeyQueue->release();
delete m_framekeyQueue;
m_framekeyQueue = NULL;
}
break;
case FRAMEMGR_OPER::NONE:
default:
CLOGE(" operMode is invalid operMode(%d)", m_operMode);
break;
}
return ret;
}
Mutex* RunWorker::getLock()
{
return &m_lock;
}
status_t RunWorker::execute(ExynosCameraFrameSP_sptr_t inframe, __unused ExynosCameraFrameSP_dptr_t outframe)
{
status_t ret = FRAMEMGR_ERRCODE::OK;
if (m_getEnable() == false) {
CLOGE(" invalid state, Need to start Worker before execute");
ret = FRAMEMGR_ERRCODE::ERR;
return ret;
}
ret = m_execute(inframe);
if (ret < 0) {
CLOGE(" m_execute is invalid ret(%d)", ret);
ret = FRAMEMGR_ERRCODE::ERR;
}
return ret;
}
status_t RunWorker::setMargin(int32_t max, int32_t min)
{
int32_t ret = FRAMEMGR_ERRCODE::OK;
CLOGD("worker(%d) do not support change margin(min(%d), max(%d))", FRAMEMGR_WORKER::RUNNING, min, max);
return ret;
}
status_t RunWorker::start()
{
if (m_worklist.size() > 0) {
CLOGD(" previous worklist size(%d), clear worklist", (int)m_worklist.size());
m_worklist.clear();
}
if (m_framekeyQueue->getSizeOfProcessQ() > 0) {
CLOGD(" previous framekeyQueue size(%d), clear framekeyQueue", m_framekeyQueue->getSizeOfProcessQ());
m_framekeyQueue->release();
}
switch (m_operMode) {
case FRAMEMGR_OPER::ONDEMAND:
m_setEnable(true);
break;
case FRAMEMGR_OPER::SLIENT:
m_setEnable(true);
if (m_thread->isRunning() == false)
m_thread->run();
break;
case FRAMEMGR_OPER::NONE:
default:
CLOGE(" operMode is invalid operMode(%d)", m_operMode);
break;
}
return 0;
}
status_t RunWorker::stop()
{
ExynosCameraFrameSP_sptr_t frame = NULL;
uint32_t framekey = 0;
status_t ret = NO_ERROR;
switch (m_operMode) {
case FRAMEMGR_OPER::ONDEMAND:
m_setEnable(false);
break;
case FRAMEMGR_OPER::SLIENT:
m_setEnable(false);
m_thread->requestExit();
m_framekeyQueue->wakeupAll();
m_thread->requestExitAndWait();
CLOGD(" worker stopped remove ths remained frames(%d) queue(%d)", (int)m_worklist.size(), (int)m_framekeyQueue->getSizeOfProcessQ());
while (m_framekeyQueue->getSizeOfProcessQ() > 0) {
framekey = 0;
ret = m_framekeyQueue->popProcessQ(&framekey);
if (ret < 0) {
CLOGE(" wait and pop fail, ret(%d)", ret);
continue;
}
ret = m_removeFrame(framekey, &m_worklist, &m_lock);
if (ret < 0){
CLOGE(" m_removeFrame fail, ret(%d)", ret);
continue;
}
}
break;
case FRAMEMGR_OPER::NONE:
default:
CLOGE(" operMode is invalid operMode(%d)", m_operMode);
break;
}
return NO_ERROR;
}
status_t RunWorker::dump()
{
Mutex::Autolock lock(m_lock);
status_t ret = NO_ERROR;
map<uint32_t, ExynosCameraFrameWP_t>::iterator iter;
pair<map<uint32_t, ExynosCameraFrameWP_t>::iterator,bool> listRet;
ExynosCameraFrameWP_t item = NULL;
ExynosCameraFrameSP_t detect = NULL;
int frameSize = m_worklist.size();
if (frameSize == 0) {
CLOGD(" No memory leak detected m_runningFrameList.size()(%d)", frameSize);
} else {
CLOGW(" %d memory leak detected m_runningFrameList.size()(%d)", frameSize, frameSize);
}
for (iter = m_worklist.begin() ; iter != m_worklist.end() ;) {
item = iter->second;
detect = item.promote();
if (detect == 0) {
CLOGW(" promote failed, already delete frame");
} else {
CLOGW(" delete memory leak detected FrameKey(%d) HAL-FrameCnt(%d) FrameType(%u)", detect->getUniqueKey(), detect->getFrameCount(), detect->getFrameType());
detect.clear();
}
m_worklist.erase(iter++);
item = NULL;
}
m_worklist.clear();
return ret;
}
frame_key_queue_t* RunWorker::getQueue()
{
if (m_framekeyQueue == NULL) {
CLOGE(" getQueue fail, Queue == NULL ");
}
return m_framekeyQueue;
}
status_t RunWorker::m_execute(ExynosCameraFrameSP_dptr_t frame)
{
int32_t ret = FRAMEMGR_ERRCODE::OK;
switch (m_operMode) {
case FRAMEMGR_OPER::ONDEMAND:
ret = m_insertFrame(frame, &m_worklist, &m_lock);
if (ret < 0) {
CLOGE(" m_insertFrame fail, ret(%d)", ret);
}
break;
case FRAMEMGR_OPER::SLIENT:
ret = m_insertFrame(frame, &m_worklist, &m_lock);
if (ret < 0) {
CLOGE(" m_insertFrame fail, ret(%d)", ret);
}
if (m_thread->isRunning() == false){
m_thread->run();
}
break;
case FRAMEMGR_OPER::NONE:
default:
ret = FRAMEMGR_ERRCODE::ERR;
CLOGE(" operMode is invalid operMode(%d)", m_operMode);
break;
}
return ret;
}
status_t RunWorker::m_init()
{
int32_t ret = FRAMEMGR_ERRCODE::OK;
switch (m_operMode) {
case FRAMEMGR_OPER::ONDEMAND:
m_worklist.clear();
m_framekeyQueue = new frame_key_queue_t(m_numOfMargin);
m_framekeyQueue->setWaitTime(RUN_THREAD_TIMEOUT);
break;
case FRAMEMGR_OPER::SLIENT:
m_thread = new FrameManagerThread(this,
static_cast<func_ptr_t_>(&RunWorker::workerMain),
"Run Frame Thread",
PRIORITY_URGENT_DISPLAY);
m_worklist.clear();
m_framekeyQueue = new frame_key_queue_t(m_numOfMargin);
m_framekeyQueue->setWaitTime(RUN_THREAD_TIMEOUT);
break;
case FRAMEMGR_OPER::NONE:
default:
m_worklist.clear();
m_framekeyQueue = NULL;
ret = FRAMEMGR_ERRCODE::ERR;
CLOGE(" operMode is invalid operMode(%d)", m_operMode);
break;
}
return ret;
}
bool RunWorker::workerMain()
{
#ifdef DEBUG
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
#endif
int32_t ret = FRAMEMGR_ERRCODE::OK;
bool loop = true;
uint32_t framekey = 0;
int size = 0;
if (m_getEnable() == false) {
loop = false;
CLOGD(" Run worker stopped delete current frame(%d)", m_framekeyQueue->getSizeOfProcessQ());
while (m_framekeyQueue->getSizeOfProcessQ() > 0) {
framekey = 0;
ret = m_framekeyQueue->popProcessQ(&framekey);
if (ret < 0) {
CLOGE(" wait and pop fail, ret(%d)", ret);
continue;
}
ret = m_removeFrame(framekey, &m_worklist, &m_lock);
if (ret < 0){
CLOGE(" m_removeFrame fail, ret(%d)", ret);
continue;
}
}
return loop;
}
ret = m_framekeyQueue->waitAndPopProcessQ(&framekey);
if (ret < 0) {
CLOGI(" wait and pop fail, ret(%d)", ret);
goto func_exit;
}
ret = m_removeFrame(framekey, &m_worklist, &m_lock);
if (ret < 0){
CLOGE(" m_removeFrame fail, ret(%d)", ret);
goto func_exit;
}
size = m_framekeyQueue->getSizeOfProcessQ();
for (int i = 0 ; i < size ; i++) {
framekey = 0;
ret = m_framekeyQueue->popProcessQ(&framekey);
if (ret < 0) {
CLOGE(" wait and pop fail, ret(%d)", ret);
continue;
}
ret = m_removeFrame(framekey, &m_worklist, &m_lock);
if (ret < 0){
CLOGE(" m_removeFrame fail, ret(%d)", ret);
continue;
}
}
if (m_getSizeList() > m_numOfDumpMargin){
m_dumpFrame();
}
func_exit:
if (m_framekeyQueue->getSizeOfProcessQ() > 0)
loop = true;
return loop;
}
status_t RunWorker::m_insertFrame(ExynosCameraFrameSP_dptr_t frame,
map<uint32_t, ExynosCameraFrameWP_t> *list,
Mutex *lock)
{
lock->lock();
pair<map<uint32_t, ExynosCameraFrameWP_t>::iterator,bool> listRet;
status_t ret = FRAMEMGR_ERRCODE::OK;
listRet = list->insert( pair<uint32_t, ExynosCameraFrameWP_t>(frame->getUniqueKey(), frame));
if (listRet.second == false) {
ret = FRAMEMGR_ERRCODE::ERR;
CLOGE(" insertFrame fail frame already exist!! HAL frameCnt(%d) UniqueKey (%u) ", frame->getFrameCount(), frame->getUniqueKey());
}
lock->unlock();
return ret;
}
status_t RunWorker::m_removeFrame(ExynosCameraFrameSP_dptr_t frame, map<uint32_t, ExynosCameraFrameWP_t> *list, Mutex *lock)
{
return m_removeFrame(frame->getUniqueKey(), list, lock);
}
status_t RunWorker::m_removeFrame(uint32_t frameKey, map<uint32_t, ExynosCameraFrameWP_t> *list, Mutex *lock)
{
lock->lock();
status_t ret = NO_ERROR;
map<uint32_t, ExynosCameraFrameWP_t>::iterator iter;
pair<map<uint32_t, ExynosCameraFrameWP_t>::iterator,bool> listRet;
ExynosCameraFrameWP_t item = NULL;
iter = list->find(frameKey);
if (iter != list->end()) {
item = iter->second;
list->erase(iter);
} else {
ret = FRAMEMGR_ERRCODE::ERR;
CLOGE(" frame is not EXIST UniqueKey(%d)", frameKey);
ret = INVALID_OPERATION;
}
lock->unlock();
return ret;
}
status_t RunWorker::m_setMargin(int32_t numOfMargin)
{
int32_t ret = FRAMEMGR_ERRCODE::OK;
m_numOfMargin = numOfMargin;
return ret;
}
int32_t RunWorker::m_getMargin()
{
return m_numOfMargin;
}
status_t RunWorker::m_dumpFrame()
{
Mutex::Autolock lock(m_lock);
status_t ret = NO_ERROR;
map<uint32_t, ExynosCameraFrameWP_t>::iterator iter;
ExynosCameraFrameWP_t frame = NULL;
ExynosCameraFrameSP_sptr_t item = NULL;
CLOGD("++++++++++++++++++++++++++++++");
CLOGD("m_numOfDumpMargin(%d) m_runningFrameList.size()(%zu)",
m_numOfDumpMargin, m_worklist.size());
int testCount = 0;
for (iter = m_worklist.begin() ; iter != m_worklist.end() ; ++iter) {
frame = iter->second;
item = frame.promote();
if (item == 0) {
CLOGW(" promote failed, already delete frame");
} else {
CLOGW(" delete memory leak detected FrameKey(%d) HAL-FrameCnt(%d) FrameType(%u)", item->getUniqueKey(), item->getFrameCount(), item->getFrameType());
}
if (++testCount >= 5)
break;
}
CLOGD("------------------------------");
#ifdef AVOID_ASSERT_FRAME
CLOGE(" too many frames - m_runningFrameList.size(%zu)",
m_worklist.size());
#else
android_printAssert(NULL, LOG_TAG, "HACK For ANR DEBUGGING");
#endif
return ret;
}
uint32_t RunWorker::m_getSizeList()
{
Mutex::Autolock lock(m_lock);
return m_worklist.size();
}
ExynosCameraFrameManager::ExynosCameraFrameManager(const char* name,
int cameraid,
FRAMEMGR_OPER::MODE operMode)
{
m_cameraId = cameraid;
CLOGD(" FrameManager CREATE(name(%s) cameraid(%d) mode(%d)",
name, cameraid, operMode);
strncpy(m_name, name, EXYNOS_CAMERA_NAME_STR_SIZE - 1);
m_setOperMode(operMode);
m_init();
}
ExynosCameraFrameManager::~ExynosCameraFrameManager()
{
CLOGD(" FrameManager DELETE(name(%s) cameraid(%d) mode(%d)",
m_name, m_cameraId, m_operMode);
m_deinit();
}
ExynosCameraFrameSP_sptr_t ExynosCameraFrameManager::createFrame(ExynosCameraParameters *param, uint32_t framecnt, uint32_t frametype)
{
return m_createFrame(param, framecnt, frametype);
}
status_t ExynosCameraFrameManager::setKeybox(sp<KeyBox> keybox)
{
Mutex::Autolock lock(m_stateLock);
m_keybox = keybox;
return 0;
}
sp<KeyBox> ExynosCameraFrameManager::getKeybox()
{
Mutex::Autolock lock(m_stateLock);
return m_keybox;
}
status_t ExynosCameraFrameManager::setWorker(int key, sp<FrameWorker> worker)
{
Mutex::Autolock lock(m_stateLock);
map<uint32_t, sp<FrameWorker> >::iterator iter;
pair<map<uint32_t, sp<FrameWorker> >::iterator,bool> workerRet;
pair<map<uint32_t, Mutex*>::iterator,bool> mutexRet;
iter = m_workerList.find(key);
if (iter != m_workerList.end()) {
CLOGE(" already worker is EXIST(%d)", key);
} else {
m_setupWorkerInfo(key, worker);
}
return 0;
}
status_t ExynosCameraFrameManager::setOperMode(FRAMEMGR_OPER::MODE mode)
{
return m_setOperMode(mode);
}
int ExynosCameraFrameManager::getOperMode()
{
return m_getOperMode();
}
status_t ExynosCameraFrameManager::m_init()
{
int ret = FRAMEMGR_ERRCODE::OK;
m_keybox = NULL;
m_framekeyQueue = NULL;
m_setEnable(false);
return ret;
}
status_t ExynosCameraFrameManager::m_setupWorkerInfo(int key, sp<FrameWorker> worker)
{
int ret = FRAMEMGR_ERRCODE::OK;
pair<map<uint32_t, sp<FrameWorker> >::iterator,bool> workerRet;
pair<map<uint32_t, Mutex*>::iterator,bool> mutexRet;
workerRet = m_workerList.insert( pair<uint32_t, sp<FrameWorker> >(key, worker));
if (workerRet.second == false) {
ret = FRAMEMGR_ERRCODE::ERR;
CLOGE(" work insert failed(%d)", key);
}
return ret;
}
sp<FrameWorker> ExynosCameraFrameManager::getWorker(int key)
{
Mutex::Autolock lock(m_stateLock);
sp<FrameWorker> ret;
map<uint32_t, sp<FrameWorker> >::iterator iter;
if (m_getEnable() == true) {
CLOGE("invalid state, Need to stop FrameMgr before getWorker(%d)", key);
return NULL;
}
iter = m_workerList.find(key);
if (iter != m_workerList.end()) {
ret = iter->second;
} else {
CLOGE(" worker is not EXIST(%d)", key);
ret = NULL;
}
return ret;
}
sp<FrameWorker> ExynosCameraFrameManager::eraseWorker(int key)
{
Mutex::Autolock lock(m_stateLock);
sp<FrameWorker> ret;
map<uint32_t, sp<FrameWorker> >::iterator iter;
iter = m_workerList.find(key);
if (iter != m_workerList.end()) {
ret = iter->second;
m_workerList.erase(iter);
} else {
CLOGE(" worker is not EXIST(%d)", key);
ret = NULL;
}
return ret;
}
status_t ExynosCameraFrameManager::start()
{
Mutex::Autolock lock(m_stateLock);
status_t ret = FRAMEMGR_ERRCODE::OK;
sp<FrameWorker> worker = NULL;
map<uint32_t, sp<FrameWorker> >::iterator iter;
if (m_getEnable() == true) {
CLOGD("frameManager already start!!");
ret = INVALID_OPERATION;
goto func_exit;
}
{
iter = m_workerList.find(FRAMEMGR_WORKER::RUNNING);
if (iter == m_workerList.end()) {
CLOGE("do not find worker(%d) !!", FRAMEMGR_WORKER::RUNNING);
ret = INVALID_OPERATION;
goto func_exit;
}
worker = iter->second;
m_framekeyQueue = worker->getQueue();
}
for (iter = m_workerList.begin() ; iter != m_workerList.end() ; ++iter) {
worker = iter->second;
ret = worker->start();
}
m_setEnable(true);
func_exit:
return ret;
}
status_t ExynosCameraFrameManager::stop()
{
Mutex::Autolock lock(m_stateLock);
status_t ret = FRAMEMGR_ERRCODE::OK;
sp<FrameWorker> worker;
if (m_getEnable() == false) {
CLOGD("frameManager already stop!!");
return ret;
}
m_setEnable(false);
map<uint32_t, sp<FrameWorker> >::iterator iter;
for (iter = m_workerList.begin() ; iter != m_workerList.end() ; ++iter) {
worker = iter->second;
ret = worker->stop();
}
return ret;
}
int ExynosCameraFrameManager::deleteAllFrame()
{
Mutex::Autolock lock(m_stateLock);
status_t ret = NO_ERROR;
ExynosCameraFrameSP_sptr_t frame = NULL;
if (m_getEnable() == true) {
CLOGE(" invalid state, module state enabled, state must disabled");
ret = INVALID_OPERATION;
return ret;
}
sp<FrameWorker> worker = NULL;
map<uint32_t, sp<FrameWorker> >::iterator iter;
iter = m_workerList.find(FRAMEMGR_WORKER::RUNNING);
if (iter == m_workerList.end()) {
CLOGE("do not find worker(%d) !!", FRAMEMGR_WORKER::RUNNING);
ret = INVALID_OPERATION;
goto func_exit;
}
worker = iter->second;
worker->dump();
func_exit:
return ret;
}
ExynosCameraFrameSP_sptr_t ExynosCameraFrameManager::m_createFrame(ExynosCameraParameters *param,
uint32_t framecnt,
uint32_t frametype)
{
int ret = FRAMEMGR_ERRCODE::OK;
uint32_t nextKey = 0;
ExynosCameraFrameSP_sptr_t frame = NULL;
ExynosCameraFrameSP_sptr_t outframe = NULL;
map<uint32_t, sp<FrameWorker> >::iterator iter;
sp<FrameWorker> worker = NULL;
if (m_getEnable() == false) {
CLOGE(" module state disabled");
return frame;
}
iter = m_workerList.find(FRAMEMGR_WORKER::CREATE);
worker = iter->second;
switch (m_operMode) {
case FRAMEMGR_OPER::ONDEMAND:
case FRAMEMGR_OPER::SLIENT:
worker->execute(NULL, frame);
if (frame == NULL) {
CLOGE("Frame is NULL");
return frame;
}
frame->setUniqueKey(m_keybox->createKey());
nextKey = m_keybox->getKey();
if (nextKey == frame->getUniqueKey()) {
CLOGW("[F%d]Failed to increase frameUniqueKey. curKey %d nextKey %d",
framecnt, frame->getUniqueKey(), nextKey);
/* Increase the next frameUniqueKey forcely */
nextKey += 1;
m_keybox->setKey(nextKey);
}
frame->setFrameInfo(param ,framecnt, frametype);
frame->setFrameMgrInfo(m_framekeyQueue);
iter = m_workerList.find(FRAMEMGR_WORKER::RUNNING);
if (iter != m_workerList.end()) {
worker = iter->second;
} else {
CLOGE(" worker is not EXIST FRAMEMGR_WORKER::RUNNING");
}
ret = worker->execute(frame, outframe);
if (ret < 0) {
CLOGE("m_insertFrame is Failed ");
return NULL;
}
break;
}
return frame;
}
status_t ExynosCameraFrameManager::dump()
{
status_t ret = FRAMEMGR_ERRCODE::OK;
return ret;
}
status_t ExynosCameraFrameManager::m_deinit()
{
status_t ret = FRAMEMGR_ERRCODE::OK;
ExynosCameraFrameSP_sptr_t frame = NULL;
sp<FrameWorker> worker;
map<uint32_t, sp<FrameWorker> >::iterator iter;
for (iter = m_workerList.begin() ; iter != m_workerList.end() ; ++iter) {
worker = iter->second;
m_workerList.erase(iter++);
worker = NULL;
}
m_workerList.clear();
if (m_keybox != NULL) {
CLOGD(" delete m_keybox");
m_keybox = NULL;
}
m_framekeyQueue = NULL;
return ret;
}
status_t ExynosCameraFrameManager::m_setOperMode(FRAMEMGR_OPER::MODE mode)
{
int32_t ret = FRAMEMGR_ERRCODE::OK;
switch (mode) {
case FRAMEMGR_OPER::ONDEMAND:
case FRAMEMGR_OPER::SLIENT:
m_operMode = mode;
break;
default:
m_operMode = -1;
ret = FRAMEMGR_ERRCODE::ERR;
CLOGE(" operMode is invalid operMode(%d)", m_operMode);
break;
}
return ret;
}
int ExynosCameraFrameManager::m_getOperMode()
{
return m_operMode;
}
status_t ExynosCameraFrameManager::m_setEnable(bool enable)
{
Mutex::Autolock lock(m_enableLock);
status_t ret = FRAMEMGR_ERRCODE::OK;
m_enable = enable;
return ret;
}
bool ExynosCameraFrameManager::m_getEnable()
{
Mutex::Autolock lock(m_enableLock);
return m_enable;
}
//************FrameManager END *************************//
}; /* namespace android */