blob: 6a67cf57ae5c15d2d435b0dd77ab3d58877bcb7c [file] [log] [blame]
/*
* Copyright (C) 2016-2018 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 "BufferPools"
#include "BufferPools.h"
#include "LogHelper.h"
#include <linux/videodev2.h>
#include <sys/mman.h>
namespace cros {
namespace intel {
BufferPools::BufferPools() :
mCaptureItemsPool("CaptureItemsPool"),
mBufferPoolSize(0),
mBufferManager(cros::CameraBufferManager::GetInstance())
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);
}
BufferPools::~BufferPools()
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);
freeBuffers();
}
/**
* Creates the capture buffer pools needed by InputSystem
*
* \param[in] numBufs Number of capture buffers to allocate
* \param[in,out] isys The InputSystem object to which the allocated
* buffer pools will be assigned to
*/
status_t BufferPools::createBufferPools(int numBufs, std::shared_ptr<InputSystem> isys)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);
std::shared_ptr<cros::V4L2VideoNode> node = isys->findOutputNode(ISYS_NODE_RAW);
status_t status = NO_ERROR;
CheckError((node.get() == nullptr), UNKNOWN_ERROR,
"@%s: create buffer pool failed", __FUNCTION__);
mBufferPoolSize = numBufs;
/**
* Init the pool of capture buffer structs. This pool contains the
* V4L2 buffers that are registered to the V4L2 device.
*/
mCaptureItemsPool.init(mBufferPoolSize);
cros::V4L2Format aFormat;
node->GetFormat(&aFormat);
LOG1("@%s: creating capture buffer pool (size: %d) format: %s",
__FUNCTION__, mBufferPoolSize, v4l2Fmt2Str(aFormat.PixelFormat()));
std::vector<cros::V4L2Buffer> v4l2Buffers;
for (unsigned int i = 0; i < mBufferPoolSize; i++) {
std::shared_ptr<cros::V4L2Buffer> v4l2BufPtr = nullptr;
mCaptureItemsPool.acquireItem(v4l2BufPtr);
if (v4l2BufPtr.get() == nullptr) {
LOGE("Failed to get a capture buffer!");
return UNKNOWN_ERROR;
}
v4l2Buffers.push_back(*v4l2BufPtr);
}
status = isys->setBufferPool(ISYS_NODE_RAW, v4l2Buffers, true);
if (status != NO_ERROR) {
LOGE("Failed to set the capture buffer pool in ISYS status: 0x%X", status);
return status;
}
FrameInfo frameInfo = {};
frameInfo.format = aFormat.PixelFormat();
frameInfo.width = aFormat.Width();
frameInfo.height = aFormat.Height();
frameInfo.stride = bytesToPixels(frameInfo.format, aFormat.BytesPerLine(0));
frameInfo.size =
frameSize(frameInfo.format, frameInfo.stride, frameInfo.height);
status = allocateCaptureBuffers(node, frameInfo, v4l2Buffers);
CheckError(status != NO_ERROR, status, "Failed to allocate capture buffer: 0x%X", status);
return status;
}
/**
* Allocates CameraBuffers to each of the cros::V4L2Buffer in the
* pool for Isys node.
*
* A given number of skip buffers is also allocated, but they will share
* the same buffer memory. These buffers are taken out of the
* mCaptureItemsPool. Effectively this will mean the buffer pool has a
* proper v4l2 id for each buffer.
*
* \param[in] node the video node that owns the v4l2 buffers
* \param[in] frameInfo Width, height, stride and format info for the buffers
* being allocated
* \param[out] v4l2Buffers The allocated V4L2 buffers
* \return status of execution
*/
status_t BufferPools::allocateCaptureBuffers(
std::shared_ptr<cros::V4L2VideoNode> node,
const FrameInfo &frameInfo,
std::vector<cros::V4L2Buffer> &v4l2Buffers)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);
status_t status = NO_ERROR;
std::shared_ptr<cros::V4L2Buffer> v4l2Buf = nullptr;
if (v4l2Buffers.size() == 0) {
LOGE("v4l2 buffers where not allocated");
return NO_MEMORY;
}
if (v4l2Buffers.size() != mBufferPoolSize) {
LOGE("BufferPoolSize is not matching to requested number of v4l2 buffers, \
v4l2 Buffer size: %zu, bufferpool size: %u", \
v4l2Buffers.size(), mBufferPoolSize);
return BAD_VALUE;
}
LOG2("mBufferPoolSize: %d", mBufferPoolSize);
for (unsigned int i = 0; i < mBufferPoolSize; i++) {
mCaptureItemsPool.acquireItem(v4l2Buf);
if (v4l2Buf.get() == nullptr) {
LOGE("Failed to get a capture buffer!");
return UNKNOWN_ERROR;
}
*v4l2Buf = v4l2Buffers[i];
CheckError(v4l2Buf->Memory() != V4L2_MEMORY_DMABUF, UNKNOWN_ERROR,
"Unsupported memory type %d.", v4l2Buf->Memory());
CheckError(!mBufferManager, UNKNOWN_ERROR,
"Failed to get buffer manager instance!");
buffer_handle_t handle;
uint32_t stride;
if (mBufferManager->Allocate(
v4l2Buf->Length(0), 1, HAL_PIXEL_FORMAT_BLOB,
GRALLOC_USAGE_HW_CAMERA_READ |
GRALLOC_USAGE_HW_CAMERA_WRITE, cros::GRALLOC, &handle,
&stride) != 0) {
LOGE("Failed to allocate buffer handle!");
for (auto& it : mBufferHandles) {
mBufferManager->Free(it);
}
mBufferHandles.clear();
return UNKNOWN_ERROR;
}
mBufferHandles.push_back(handle);
v4l2Buf->SetFd(handle->data[0], 0);
LOG2("v4l2Buf->index: %d", v4l2Buf->Index());
}
return status;
}
void BufferPools::freeBuffers()
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);
for (auto& it : mBufferHandles) {
mBufferManager->Free(it);
}
mBufferHandles.clear();
}
status_t BufferPools::acquireItem(std::shared_ptr<cros::V4L2Buffer> &v4l2Buffer)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);
return mCaptureItemsPool.acquireItem(v4l2Buffer);
}
void BufferPools::returnBuffer(cros::V4L2Buffer * /* buffer */)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);
LOGW("IMPLEMENTATION MISSING");
}
} /* namespace intel */
} /* namespace cros */