blob: 9652d6558405c7ad286338ddb08bb6cf355097a6 [file] [log] [blame]
/*
* Copyright (C) 2015-2020 Intel Corporation.
*
* 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_TAG "SwImageProcessor"
#include "iutils/Utils.h"
#include "iutils/SwImageConverter.h"
#include "iutils/CameraLog.h"
#include "iutils/CameraDump.h"
#include "PlatformData.h"
#include "CameraBuffer.h"
#include "SwImageProcessor.h"
namespace icamera {
SwImageProcessor::SwImageProcessor(int cameraId) : mCameraId(cameraId)
{
LOGW("@%s: You are running the SwProcessor instead of PSYS pipeline. SwProcessor is for debug only", __func__);
LOG1("@%s camera id:%d", __func__, mCameraId);
mProcessThread = new ProcessThread(this);
}
SwImageProcessor::~SwImageProcessor()
{
LOGW("@%s: You are running the SwProcessor instead of PSYS pipeline. SwProcessor is for debug only", __func__);
mProcessThread->join();
delete mProcessThread;
}
int SwImageProcessor::start()
{
PERF_CAMERA_ATRACE();
LOG1("%s", __func__);
AutoMutex l(mBufferQueueLock);
int memType = mOutputFrameInfo.begin()->second.memType;
CheckError(memType == V4L2_MEMORY_DMABUF, BAD_VALUE,
"@%s: DMABUF is not supported in SwProcessor as output", __func__);
int ret = allocProducerBuffers(mCameraId, MAX_BUFFER_COUNT);
CheckError(ret != OK, ret, "@%s: Allocate Buffer failed", __func__);
mThreadRunning = true;
mProcessThread->run("SwImageProcessor", PRIORITY_NORMAL);
return 0;
}
void SwImageProcessor::stop()
{
PERF_CAMERA_ATRACE();
LOG1("%s", __func__);
mProcessThread->requestExit();
{
AutoMutex l(mBufferQueueLock);
mThreadRunning = false;
//Wakeup the thread to exit
mFrameAvailableSignal.signal();
mOutputAvailableSignal.signal();
}
mProcessThread->requestExitAndWait();
// Thread is not running. It is safe to clear the Queue
clearBufferQueues();
}
int SwImageProcessor::processNewFrame()
{
PERF_CAMERA_ATRACE();
LOG2("%s", __func__);
int ret = OK;
std::map<Port, std::shared_ptr<CameraBuffer> > srcBuffers, dstBuffers;
std::shared_ptr<CameraBuffer> cInBuffer;
Port inputPort = INVALID_PORT;
{ // Auto lock mBufferQueueLock scope
ConditionLock lock(mBufferQueueLock);
ret = waitFreeBuffersInQueue(lock, srcBuffers, dstBuffers);
if (!mThreadRunning) return -1;
CheckError((ret < 0), -1, "@%s: wake up from the wait abnomal such as stop", __func__);
inputPort = srcBuffers.begin()->first;
cInBuffer = srcBuffers[inputPort];
for (auto& output: mOutputQueue) {
output.second.pop();
}
for (auto& input: mInputQueue) {
input.second.pop();
}
} // End of auto lock mBufferQueueLock scope
CheckError(!cInBuffer, BAD_VALUE, "Invalid input buffer.");
for (auto& dst : dstBuffers) {
Port port = dst.first;
std::shared_ptr<CameraBuffer> cOutBuffer = dst.second;
// If the output buffer is nullptr, that means user doesn't request that buffer,
// so it doesn't need to be handled here.
if (!cOutBuffer) {
continue;
}
//No Lock for this function make sure buffers are not freed before the stop
ret = SwImageConverter::convertFormat(cInBuffer->getWidth(), cInBuffer->getHeight(),
(unsigned char *)cInBuffer->getBufferAddr(), cInBuffer->getBufferSize(), cInBuffer->getFormat(),
(unsigned char *)cOutBuffer->getBufferAddr(), cOutBuffer->getBufferSize(), cOutBuffer->getFormat());
CheckError((ret < 0), ret, "format convertion failed with %d", ret);
if (CameraDump::isDumpTypeEnable(DUMP_SW_IMG_PROC_OUTPUT)) {
CameraDump::dumpImage(mCameraId, cOutBuffer, M_SWIPOP);
}
//update the interlaced field, sequence, and timestamp from the src buf to dst buf
cOutBuffer->updateV4l2Buffer(*cInBuffer->getV4L2Buffer().Get());
//Notify listener: No lock here: mBufferConsumerList will not updated in this state
for (auto &it : mBufferConsumerList) {
it->onFrameAvailable(port, cOutBuffer);
}
}
{
PERF_CAMERA_ATRACE_PARAM3("sof.sequence", cInBuffer->getSequence(), "csi2_port", cInBuffer->getCsi2Port(), \
"virtual_channel", cInBuffer->getVirtualChannel());
}
// Return the buffers to the producer
if (mBufferProducer) {
mBufferProducer->qbuf(inputPort, cInBuffer);
}
return OK;
}
} //namespace icamera