blob: 5bb7ff1e5b9f4de5466c34a2b3522a99928c50b6 [file] [log] [blame]
/*
**
** Copyright 2017, 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 "ExynosCameraFrameSelector"
#include "ExynosCameraFrameSelector.h"
#define FLASHED_LLS_COUNT 4
namespace android {
ExynosCameraFrameSelector::ExynosCameraFrameSelector(int cameraId,
ExynosCameraParameters *param,
ExynosCameraBufferSupplier *bufferSupplier,
ExynosCameraFrameManager *manager
#ifdef SAMSUNG_DNG_DIRTY_BAYER
, ExynosCameraBufferManager *DNGbufMgr
#endif
)
{
m_frameMgr = manager;
m_parameters = param;
m_bufferSupplier = bufferSupplier;
m_activityControl = m_parameters->getActivityControl();
m_frameHoldList.setWaitTime(2000000000);
#ifdef OIS_CAPTURE
m_OISFrameHoldList.setWaitTime(130000000);
#endif
#ifdef RAWDUMP_CAPTURE
m_RawFrameHoldList.setWaitTime(2000000000);
#endif
m_reprocessingCount = 0;
m_frameHoldCount = 1;
m_isFirstFrame = true;
isCanceled = false;
removeFlags = false;
#ifdef SAMSUNG_DNG
m_DNGFrameCount = 0;
m_preDNGFrameCount = 0;
m_preDNGFrame = NULL;
#ifdef SAMSUNG_DNG_DIRTY_BAYER
m_DNGbufMgr = DNGbufMgr;
#endif
#endif
#ifdef SUPPORT_DEPTH_MAP
m_depthCallbackQ = NULL;
m_depthMapbufMgr = NULL;
#endif
m_CaptureCount = 0;
m_cameraId = cameraId;
memset(m_name, 0x00, sizeof(m_name));
m_state = STATE_BASE;
}
ExynosCameraFrameSelector::~ExynosCameraFrameSelector()
{
/* empty destructor */
}
status_t ExynosCameraFrameSelector::m_release(frame_queue_t *list)
{
int ret = 0;
ExynosCameraFrameSP_sptr_t frame = NULL;
while (list->getSizeOfProcessQ() > 0) {
ret = m_popQ(list, frame, true, 1);
if (ret != NO_ERROR) {
CLOGE("getBufferToManageQ fail");
#if 0
m_bufMgr->printBufferState();
m_bufMgr->printBufferQState();
#endif
} else {
m_frameComplete(frame, true);
}
}
return ret;
}
status_t ExynosCameraFrameSelector::manageFrameHoldListForDynamicBayer(ExynosCameraFrameSP_sptr_t frame)
{
int ret = 0;
if (frame == NULL) {
CLOGE(" frame is NULL");
return BAD_VALUE;
}
m_pushQ(&m_frameHoldList, frame, true);
CLOGI(" frameCount(%d) m_frameHoldList size(%d)",
frame->getFrameCount(), m_frameHoldList.getSizeOfProcessQ());
return ret;
}
status_t ExynosCameraFrameSelector::m_manageHdrFrameHoldList(ExynosCameraFrameSP_sptr_t frame,
int pipeID,
bool isSrc,
int32_t dstPos)
{
int ret = 0;
ExynosCameraBuffer buffer;
ExynosCameraFrameSP_sptr_t newFrame = NULL;
ExynosCameraActivitySpecialCapture *m_sCaptureMgr = NULL;
unsigned int hdrFcount = 0;
unsigned int fliteFcount = 0;
newFrame = frame;
m_sCaptureMgr = m_activityControl->getSpecialCaptureMgr();
hdrFcount = m_sCaptureMgr->getHdrDropFcount();
hdrFcount += m_parameters->getHDRDelay();
ret = m_getBufferFromFrame(newFrame, pipeID, isSrc, &buffer, dstPos);
if( ret != NO_ERROR ) {
CLOGE("m_getBufferFromFrame fail pipeID(%d) BufferType(%s)",
pipeID, (isSrc)?"Src":"Dst");
}
if (m_parameters->getUsePureBayerReprocessing() == true) {
camera2_shot_ext *shot_ext = NULL;
shot_ext = (camera2_shot_ext *)(buffer.addr[buffer.getMetaPlaneIndex()]);
if (shot_ext != NULL)
fliteFcount = shot_ext->shot.dm.request.frameCount;
else
CLOGE("fliteReprocessingBuffer is null");
} else {
camera2_stream *shot_stream = NULL;
shot_stream = (camera2_stream *)(buffer.addr[buffer.getMetaPlaneIndex()]);
if (shot_stream != NULL)
fliteFcount = shot_stream->fcount;
else
CLOGE("fliteReprocessingBuffer is null");
}
if (hdrFcount + 1 == fliteFcount || hdrFcount + 2 == fliteFcount || hdrFcount + 3 == fliteFcount) {
CLOGI("hdrFcount %d, fliteFcount %d", hdrFcount, fliteFcount);
m_pushQ(&m_hdrFrameHoldList, newFrame, true);
} else {
m_frameComplete(newFrame, false, pipeID, isSrc, dstPos, true);
newFrame = NULL;
}
return ret;
}
ExynosCameraFrameSP_sptr_t ExynosCameraFrameSelector::m_selectHdrFrame(__unused int pipeID, __unused bool isSrc,
int tryCount, __unused int32_t dstPos)
{
int ret = 0;
ExynosCameraFrameSP_sptr_t selectedFrame = NULL;
ret = m_waitAndpopQ(&m_hdrFrameHoldList, selectedFrame, false, tryCount);
if( ret < 0 || selectedFrame == NULL ) {
CLOGD("getFrame Fail ret(%d)", ret);
return NULL;
}
return selectedFrame;
}
/* It's for dynamic bayer */
ExynosCameraFrameSP_sptr_t ExynosCameraFrameSelector::selectDynamicFrames(__unused int count,
int pipeID,
bool isSrc,
int tryCount,
int32_t dstPos)
{
return m_selectNormalFrame(pipeID, isSrc, tryCount, dstPos);
}
ExynosCameraFrameSP_sptr_t ExynosCameraFrameSelector::m_selectCaptureFrame(uint32_t frameCount, int pipeID, bool isSrc, int tryCount, int32_t dstPos)
{
ExynosCameraFrameSP_sptr_t selectedFrame = NULL;
for (int i = 0; i < CAPTURE_WAITING_COUNT; i++) {
selectedFrame = m_selectNormalFrame(pipeID, isSrc, tryCount, dstPos);
if (selectedFrame == NULL) {
CLOGE("selectedFrame is NULL");
break;
}
if (selectedFrame->getFrameCount() < frameCount) {
CLOGD("skip capture frame(count %d), waiting frame(count %d)",
selectedFrame->getFrameCount(), frameCount);
if (m_bufferSupplier == NULL) {
CLOGE("m_bufferSupplier is NULL");
return NULL;
} else {
m_frameComplete(selectedFrame, false, pipeID, isSrc, dstPos, true);
selectedFrame = NULL;
}
} else {
CLOGD("capture frame (count %d)", selectedFrame->getFrameCount());
break;
}
}
return selectedFrame;
}
status_t ExynosCameraFrameSelector::m_getBufferFromFrame(ExynosCameraFrameSP_sptr_t frame,
int pipeID,
bool isSrc,
ExynosCameraBuffer *outBuffer,
int32_t dstPos)
{
status_t ret = NO_ERROR;
ExynosCameraBuffer selectedBuffer;
if (frame == NULL) {
CLOGE("frame == NULL");
return BAD_VALUE;
}
if (outBuffer == NULL) {
CLOGE("outBuffer == NULL");
return BAD_VALUE;
}
if (isSrc) {
ret = frame->getSrcBuffer(pipeID, &selectedBuffer);
if (ret != NO_ERROR)
CLOGE("getSrcBuffer(pipeID %d) fail", pipeID);
} else {
if (dstPos < 0) {
ret = frame->getDstBuffer(pipeID, &selectedBuffer);
if (ret != NO_ERROR)
CLOGE("getDstBuffer(pipeID %d) fail", pipeID);
} else {
ret = frame->getDstBuffer(pipeID, &selectedBuffer, dstPos);
if (ret != NO_ERROR)
CLOGE("getDstBuffer(pipeID %d, dstPos %d) fail", pipeID, dstPos);
}
}
*outBuffer = selectedBuffer;
return ret;
}
status_t ExynosCameraFrameSelector::m_pushQ(frame_queue_t *list,
ExynosCameraFrameSP_sptr_t inframe,
bool lockflag)
{
status_t ret = NO_ERROR;
if( lockflag ) {
inframe->frameLock();
}
list->pushProcessQ(&inframe);
return ret;
}
status_t ExynosCameraFrameSelector::m_popQ(frame_queue_t *list,
ExynosCameraFrameSP_dptr_t outframe,
bool unlockflag,
int tryCount)
{
status_t ret = NO_ERROR;
int iter = 0;
do {
ret = list->popProcessQ(&outframe);
if( ret < 0 ) {
if( ret == TIMED_OUT ) {
CLOGD("PopQ Time out -> retry[max cur](%d %d)",
tryCount, iter);
iter++;
continue;
}
}
} while (ret != OK && tryCount > iter);
if( ret != OK ) {
CLOGE("popQ fail(%d)", ret);
return ret;
}
if (outframe == NULL){
CLOGE("popQ frame = NULL ");
return ret;
}
if( unlockflag ) {
outframe->frameUnlock();
}
return ret;
}
status_t ExynosCameraFrameSelector::m_frameComplete(ExynosCameraFrameSP_sptr_t frame, bool isForcelyDelete,
int pipeID, bool isSrc, int32_t dstPos, bool flagReleaseBuf)
{
int ret = OK;
if(flagReleaseBuf) {
m_releaseBuffer(frame, pipeID, isSrc, dstPos);
}
if (isForcelyDelete == true) {
CLOGD("frame deleted forcely : isComplete(%d) count(%d) LockState(%d)",
frame->isComplete(),
frame->getFrameCount(),
frame->getFrameLockState());
if (m_frameMgr != NULL) {
} else {
CLOGE("m_frameMgr is NULL (%d)", frame->getFrameCount());
}
frame = NULL;
} else {
CLOGV("frame complete, count(%d)", frame->getFrameCount());
if (m_frameMgr != NULL) {
} else {
CLOGE("m_frameMgr is NULL (%d)", frame->getFrameCount());
}
frame = NULL;
}
return ret;
}
/*
* Check complete flag of the Frame and deallocate it if it is completed.
* This function ignores lock flag of the frame(Lock flag is usually set to protect
* the frame from deallocation), so please use with caution.
* This function is required to remove a frame from frameHoldingList.
*/
status_t ExynosCameraFrameSelector::m_LockedFrameComplete(ExynosCameraFrameSP_sptr_t frame, int pipeID,
bool isSrc, int32_t dstPos)
{
int ret = OK;
m_releaseBuffer(frame, pipeID, isSrc, dstPos);
if (m_frameMgr != NULL) {
} else {
CLOGE("m_frameMgr is NULL (%d)", frame->getFrameCount());
}
return ret;
}
uint32_t ExynosCameraFrameSelector::getSizeOfHoldFrame(void)
{
uint32_t size = 0;
size += m_frameHoldList.getSizeOfProcessQ();
size += m_hdrFrameHoldList.getSizeOfProcessQ();
#ifdef OIS_CAPTURE
size += m_OISFrameHoldList.getSizeOfProcessQ();
#endif
return size;
}
status_t ExynosCameraFrameSelector::wakeupQ(void)
{
m_frameHoldList.sendCmd(WAKE_UP);
return NO_ERROR;
}
status_t ExynosCameraFrameSelector::m_clearList(frame_queue_t *list,int pipeID, bool isSrc, int32_t dstPos)
{
int ret = 0;
ExynosCameraFrameSP_sptr_t frame = NULL;
ExynosCameraBuffer buffer;
while (list->getSizeOfProcessQ() > 0) {
if (m_popQ(list, frame, false, 1) != NO_ERROR) {
CLOGE("getBufferToManageQ fail");
#if 0
m_bufMgr->printBufferState();
m_bufMgr->printBufferQState();
#endif
} else {
ret = m_getBufferFromFrame(frame, pipeID, isSrc, &buffer, dstPos);
if( ret != NO_ERROR ) {
CLOGE("m_getBufferFromFrame fail pipeID(%d) BufferType(%s)",
pipeID, (isSrc)?"Src":"Dst");
}
if (m_bufferSupplier == NULL) {
CLOGE("m_bufferSupplier is NULL");
return INVALID_OPERATION;
} else {
if (buffer.index >= 0)
ret = m_bufferSupplier->putBuffer(buffer);
if (ret < 0) {
CLOGE("putIndex is %d", buffer.index);
#if 0
m_bufMgr->printBufferState();
m_bufMgr->printBufferQState();
#endif
}
/*
Frames in m_frameHoldList and m_hdrFrameHoldList are locked when they are inserted
on the list. So we need to use m_LockedFrameComplete() to remove those frames.
Please beware that the frame might be deleted in elsewhere, epically on erroneous
conditions. So if the program encounters memory fault here, please check the other
frame deallocation(delete) routines.
*/
/* Rather than blindly deleting frame in m_LockedFrameComplete(), we do following:
* 1. Check whether frame is complete. Delete the frame if it is complete.
* 2. If the frame is not complete, unlock it. mainThread will delete this frame.
*/
//m_LockedFrameComplete(frame);
if (m_frameMgr == NULL) {
CLOGE("m_frameMgr is NULL (%d)", frame->getFrameCount());
}
}
}
}
return ret;
}
status_t ExynosCameraFrameSelector::setFrameHoldCount(int32_t count)
{
if (count < 0) {
CLOGE("frame hold count cannot be negative value, current value(%d)",
count);
return BAD_VALUE;
}
CLOGD("holdCount : %d", count);
m_frameHoldCount = count;
return NO_ERROR;
}
bool ExynosCameraFrameSelector::m_isFrameMetaTypeShotExt(void)
{
bool isShotExt = true;
if (m_parameters->isSccCapture() == true) {
if (m_parameters->isReprocessing() == true)
isShotExt = true;
else
isShotExt = false;
} else {
if (m_parameters->getUsePureBayerReprocessing() == false)
isShotExt = false;
}
return isShotExt;
}
void ExynosCameraFrameSelector::setWaitTime(uint64_t waitTime)
{
m_frameHoldList.setWaitTime(waitTime);
}
}