blob: 2b1374074ad04a5c64c1fa24ff08152564816328 [file] [log] [blame]
/*
* Copyright (C) 2016-2017 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 "CommonBuffer"
#include <sys/mman.h>
#include <sstream>
#include <iomanip> // std::setw, setfill
#include "LogHelper.h"
#include "CommonBuffer.h"
#include "UtilityMacros.h"
#include "Camera3V4l2Format.h"
namespace cros {
namespace intel {
/**
* CommonBuffer
*
* Default constructor
* This constructor is used when we pre-allocate the CommonBuffer object
* The initialization will be done as a second stage with the method
* init()
*/
CommonBuffer::CommonBuffer() :
mWidth(0),
mHeight(0),
mStride(0),
mType(BMT_HEAP),
mSize(0),
mDataPtr(nullptr),
mHandle(nullptr),
mFd(-1),
mOffset(0),
mV4L2Fmt(0),
mInit(false),
mIsOwner(false)
{
LOG1("%s default constructor for buf %p", __FUNCTION__, this);
}
/**
* constructor for using user ptr
* buffer is initialized in contructor, no need to call init()
*
* \param fmt [IN]: v4l2 format
* \param data [IN]: user data pointer
* \param w/h/s [IN]: width/height/stride
*/
CommonBuffer::CommonBuffer(const BufferProps &props, void *data) :
mSize(0),
mDataPtr(nullptr),
mHandle(nullptr),
mFd(-1),
mOffset(0),
mInit(false),
mIsOwner(false)
{
LOG1("%s constructor with usrptr %p", __FUNCTION__, data);
init(props, data);
}
/**
* initialization
* Used for object constructed with default constructor
*
* \param fmt [IN]: v4l2 format
* \param data [IN]: user data pointer
* \param w/h/s [IN]: width/height/stride
*/
status_t CommonBuffer::init(const BufferProps &props, void* data)
{
mWidth = props.width;
mHeight = props.height;
mStride = props.stride;
mV4L2Fmt = props.format;
mType = props.type;
if (mType == BMT_HEAP) {
mDataPtr = data;
LOG1("%s with %dx%d s:%d fmt:%x heap data: %p", __FUNCTION__,
mWidth, mHeight, mStride, mV4L2Fmt, mDataPtr);
} else if (mType == BMT_GFX) {
mHandle = data;
LOG1("%s with %dx%d s:%d fmt:%x gfx handle: %p", __FUNCTION__,
mWidth, mHeight, mStride, mV4L2Fmt, mHandle);
} else if (mType == BMT_MMAP) {
mDataPtr = data;
mFd = props.fd;
mOffset = props.offset;
LOG1("%s with %dx%d s:%d fmt:%x fd:%d offset:%d addr: %p", __FUNCTION__,
mWidth, mHeight, mStride, mV4L2Fmt, mFd, mOffset, mDataPtr);
}
if (props.size > 0) {
mSize = props.size;
LOG1("%s size override:%d", __FUNCTION__, mSize);
} else {
mSize = frameSize(mV4L2Fmt, mStride, mHeight);
}
mInit = true;
return NO_ERROR;
}
CommonBuffer::~CommonBuffer()
{
LOG1("%s destroying buf %p", __FUNCTION__, this);
if (mIsOwner)
freeMemory();
}
/**
* free memory for self-ownded buffer
*/
status_t CommonBuffer::freeMemory()
{
switch(mType) {
case BMT_HEAP:
if (mDataPtr) {
LOG1("%s release memory %p", __FUNCTION__, mDataPtr);
free(mDataPtr);
mDataPtr = nullptr;
}
break;
case BMT_MMAP:
if (mDataPtr != nullptr) {
LOG1("%s munmap memory %p", __FUNCTION__, mDataPtr);
munmap(mDataPtr, mSize);
mDataPtr = nullptr;
}
break;
case BMT_GFX:
default:
LOGE("Not supported yet for type:%d", mType);
break;
}
return NO_ERROR;
}
/**
* allocate memory for an initialized buffer
*
* The buffer should be initialized with an empty user pointer
* The allocated memory is released in CommonBuffer destructor
*/
status_t CommonBuffer::allocMemory()
{
if (!mInit) {
LOGE("alloc error: buffer is not initialized");
return NO_INIT;
}
switch(mType) {
case BMT_HEAP:
if (mDataPtr && mIsOwner) {
LOG1("%s reallocate with size:%u", __FUNCTION__, mSize);
free(mDataPtr);
} else if (mDataPtr && !mIsOwner) {
LOGW("trying to allocate memory for an userptr buffer");
return UNKNOWN_ERROR;
}
mDataPtr = malloc(mSize);
if (!mDataPtr) {
LOGE("fail to malloc for size:%d", mSize);
return NO_MEMORY;
}
LOG1("%s size:%u addr:%p", __FUNCTION__, mSize, mDataPtr);
break;
case BMT_MMAP:
if (mDataPtr) {
LOGD("already mapped add:%p owner:%d", mDataPtr, mIsOwner);
return NO_ERROR;
}
mDataPtr = mmap(nullptr, mSize, PROT_READ | PROT_WRITE, MAP_SHARED, mFd, mOffset);
if (mDataPtr == MAP_FAILED) {
LOGE("Failed to MAP buffer, fd:%d error: %s", mFd, strerror(errno));
mDataPtr = nullptr;
return UNKNOWN_ERROR;
}
LOG1("%s mmap size:%u addr:%p", __FUNCTION__, mSize, mDataPtr);
break;
case BMT_GFX:
default:
LOGW("Alloc memory not supported yet for %d", mType);
return UNKNOWN_ERROR;
}
mIsOwner = true;
return NO_ERROR;
}
} /* namespace intel */
} /* namespace cros */