/* * 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 namespace android { namespace camera2 { namespace rkisp2 { RKISP2FrameWorker::RKISP2FrameWorker(std::shared_ptr 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 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 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(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(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 */