android13/hardware/rockchip/camera/psl/rkisp2/workers/RKISP2FrameWorker.cpp

225 lines
6.6 KiB
C++

/*
* Copyright (C) 2016-2017 Intel Corporation.
* Copyright (c) 2017, Fuzhou Rockchip 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_TAG "RKISP2FrameWorker"
#include "RKISP2FrameWorker.h"
#include "Camera3GFXFormat.h"
#include <sys/mman.h>
namespace android {
namespace camera2 {
namespace rkisp2 {
RKISP2FrameWorker::RKISP2FrameWorker(std::shared_ptr<V4L2VideoNode> node,
int cameraId, size_t pipelineDepth, std::string name) :
RKISP2IDeviceWorker(cameraId),
mIndex(0),
mName(name),
mNode(node),
mIsStarted(false),
mPollMe(false),
mPipelineDepth(pipelineDepth)
{
}
RKISP2FrameWorker::~RKISP2FrameWorker()
{
}
status_t RKISP2FrameWorker::attachNode(std::shared_ptr<V4L2VideoNode> node)
{
if(node.get() != NULL) {
LOGI("@%s :%s attach to node(%p) %s", __FUNCTION__, mName.c_str(), node.get(), node->name());
mNode = node;
}
return OK;
}
status_t RKISP2FrameWorker::configure(bool configChanged)
{
return OK;
}
status_t RKISP2FrameWorker::startWorker(int initialSkips)
{
HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH);
LOGI("@%s enter, %s, mIsStarted:%d", __FUNCTION__, mName.c_str(), mIsStarted);
if (mIsStarted == true)
return OK;
status_t ret = mNode->start(0);
if (ret != OK) {
LOGE("Unable to start device: %s ret: %d", mNode->name(), ret);
}
mIsStarted = true;
V4L2BufferInfo outBuf;
int index;
fd_set fds;
struct timeval tv;
int res;
ALOGI("@%s enter, %s, skipFrames: %d.", __FUNCTION__, mName.c_str(), initialSkips);
if (mNode->getBufsInDeviceCount() == 0) {
LOGE("@%s: devices: %s, mBuffersInDevice is 0, can't skip!", __FUNCTION__, mName.c_str());
return NO_ERROR;
}
FD_ZERO(&fds);
FD_SET(mNode->getFd(), &fds);
/* Timeout. */
tv.tv_sec = 3;
tv.tv_usec = 0;
for (int i = 0; i < initialSkips; i++) {
res = select(mNode->getFd() + 1, &fds, NULL, NULL, &tv);
if (res <= 0) {
LOGE("@%s(%d) error select or select time out!!",__FUNCTION__,__LINE__);
return 0;
}
index = mNode->grabFrame(&outBuf);
ALOGI("device: %s, grabFrame buf index(%d)!", mNode->name(), index);
ret = mNode->putFrame(outBuf.vbuffer);
if (ret != OK) {
LOGE("Unable to putFrame from device: %s ret: %d", mNode->name(), ret);
return ret;
}
}
return ret;
}
status_t RKISP2FrameWorker::flushWorker()
{
LOGI("@%s enter, %s", __FUNCTION__, mName.c_str());
mMsg = nullptr;
return OK;
}
status_t RKISP2FrameWorker::stopWorker()
{
LOGI("@%s enter, %s, mIsStarted:%d", __FUNCTION__, mName.c_str(), mIsStarted);
if (mIsStarted == false)
return OK;
mMsg = nullptr;
mBuffers.clear();
mCameraBuffers.clear();
//stream_off and destory the buffer pool
status_t ret = mNode->stop();
if (ret != OK) {
LOGE("stop device failed: %s ret: %d", mNode->name(), ret);
}
mIsStarted = false;
return ret;
}
status_t RKISP2FrameWorker::setWorkerDeviceFormat(FrameInfo &frame)
{
HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH);
LOGI("@%s enter, %s", __FUNCTION__, mName.c_str());
status_t ret = mNode->setFormat(frame);
CheckError(ret != NO_ERROR, ret, "@%s set worker format failed", __FUNCTION__);
ret = mNode->getFormat(mFormat);
CheckError(ret != NO_ERROR, ret, "@%s get worker format failed", __FUNCTION__);
return OK;
}
status_t RKISP2FrameWorker::setWorkerDeviceBuffers(int memType, bool cached)
{
LOGI("@%s enter, %s", __FUNCTION__, mName.c_str());
for (unsigned int i = 0; i < mPipelineDepth; i++) {
V4L2Buffer buffer;
mBuffers.push_back(buffer);
}
status_t ret = mNode->setBufferPool(mBuffers, cached, memType);
if (ret != OK) {
LOGE("Unable to set buffer pool, ret = %d", ret);
return ret;
}
return OK;
}
status_t RKISP2FrameWorker::allocateWorkerBuffers()
{
int memType = mNode->getMemoryType();
int dmaBufFd;
unsigned long userptr;
std::shared_ptr<CameraBuffer> buf = nullptr;
LOGD("@%s allocate format: %s size: %d %dx%d bytesperline: %d, memType(%d)", __func__, v4l2Fmt2Str(mFormat.pixelformat()),
mFormat.sizeimage(), mFormat.width(), mFormat.height(), mFormat.bytesperline(), memType);
for (unsigned int i = 0; i < mPipelineDepth; i++) {
switch (memType) {
case V4L2_MEMORY_USERPTR:
buf = MemoryUtils::allocateHeapBuffer(mFormat.width(),
mFormat.height(),
mFormat.bytesperline(),
mFormat.pixelformat(),
mCameraId,
PAGE_ALIGN(mFormat.sizeimage()));
if (buf.get() == nullptr)
return NO_MEMORY;
userptr = reinterpret_cast<unsigned long>(buf->data());
mBuffers[i].setUserptr(userptr);
memset(buf->data(), 0, buf->size());
LOGD("mBuffers[%d].userptr: 0x%lx", i , mBuffers[i].userptr());
break;
case V4L2_MEMORY_MMAP:
{
int prot = 0;
dmaBufFd = mNode->exportFrame(i);
if (mFormat.pixelformat() == V4L2_META_FMT_RK_ISP1_PARAMS)
prot = PROT_READ | PROT_WRITE;
else
prot = PROT_READ;
mNode->putFrame(i);
buf = std::make_shared<CameraBuffer>(mFormat.width(),
mFormat.height(),
mFormat.bytesperline(),
mNode->getFd(),
dmaBufFd,
mBuffers[i].length(),
mFormat.pixelformat(),
mBuffers[i].offset(), prot, MAP_SHARED);
if (buf.get() == nullptr)
return BAD_VALUE;
}
break;
default:
LOGE("@%s Unsupported memory type %d", __func__, memType);
return BAD_VALUE;
}
mBuffers[i].setBytesused(mFormat.sizeimage());
mCameraBuffers.push_back(buf);
}
return OK;
}
} /* namespace rkisp2 */
} /* namespace camera2 */
} /* namespace android */