188 lines
4.9 KiB
C++
188 lines
4.9 KiB
C++
/* Copyright 2017 The Chromium OS Authors. All rights reserved.
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#include "arc/frame_buffer.h"
|
|
|
|
#include <utility>
|
|
|
|
#include <sys/mman.h>
|
|
#include "arc/common.h"
|
|
#include "arc/image_processor.h"
|
|
|
|
namespace arc {
|
|
|
|
FrameBuffer::FrameBuffer()
|
|
: data_(nullptr),
|
|
data_size_(0),
|
|
buffer_size_(0),
|
|
width_(0),
|
|
height_(0),
|
|
fourcc_(0) {}
|
|
|
|
FrameBuffer::~FrameBuffer() {}
|
|
|
|
int FrameBuffer::SetDataSize(size_t data_size) {
|
|
if (data_size > buffer_size_) {
|
|
LOGF(ERROR) << "Buffer overflow: Buffer only has " << buffer_size_
|
|
<< ", but data needs " << data_size;
|
|
return -EINVAL;
|
|
}
|
|
data_size_ = data_size;
|
|
return 0;
|
|
}
|
|
|
|
AllocatedFrameBuffer::AllocatedFrameBuffer(int buffer_size) {
|
|
buffer_.reset(new uint8_t[buffer_size]);
|
|
buffer_size_ = buffer_size;
|
|
data_ = buffer_.get();
|
|
}
|
|
|
|
AllocatedFrameBuffer::AllocatedFrameBuffer(uint8_t* buffer, int buffer_size) {
|
|
buffer_.reset(buffer);
|
|
buffer_size_ = buffer_size;
|
|
data_ = buffer_.get();
|
|
}
|
|
|
|
AllocatedFrameBuffer::~AllocatedFrameBuffer() {}
|
|
|
|
int AllocatedFrameBuffer::SetDataSize(size_t size) {
|
|
if (size > buffer_size_) {
|
|
buffer_.reset(new uint8_t[size]);
|
|
buffer_size_ = size;
|
|
data_ = buffer_.get();
|
|
}
|
|
data_size_ = size;
|
|
return 0;
|
|
}
|
|
|
|
void AllocatedFrameBuffer::Reset() { memset(data_, 0, buffer_size_); }
|
|
|
|
V4L2FrameBuffer::V4L2FrameBuffer(base::ScopedFD fd, int buffer_size,
|
|
uint32_t width, uint32_t height,
|
|
uint32_t fourcc)
|
|
: fd_(std::move(fd)), is_mapped_(false) {
|
|
buffer_size_ = buffer_size;
|
|
width_ = width;
|
|
height_ = height;
|
|
fourcc_ = fourcc;
|
|
}
|
|
|
|
V4L2FrameBuffer::~V4L2FrameBuffer() {
|
|
if (Unmap()) {
|
|
LOGF(ERROR) << "Unmap failed";
|
|
}
|
|
}
|
|
|
|
int V4L2FrameBuffer::Map() {
|
|
base::AutoLock l(lock_);
|
|
if (is_mapped_) {
|
|
LOGF(ERROR) << "The buffer is already mapped";
|
|
return -EINVAL;
|
|
}
|
|
void* addr = mmap(NULL, buffer_size_, PROT_READ, MAP_SHARED, fd_.get(), 0);
|
|
if (addr == MAP_FAILED) {
|
|
LOGF(ERROR) << "mmap() failed: " << strerror(errno);
|
|
return -EINVAL;
|
|
}
|
|
data_ = static_cast<uint8_t*>(addr);
|
|
is_mapped_ = true;
|
|
return 0;
|
|
}
|
|
|
|
int V4L2FrameBuffer::Unmap() {
|
|
base::AutoLock l(lock_);
|
|
if (is_mapped_ && munmap(data_, buffer_size_)) {
|
|
LOGF(ERROR) << "mummap() failed: " << strerror(errno);
|
|
return -EINVAL;
|
|
}
|
|
is_mapped_ = false;
|
|
return 0;
|
|
}
|
|
|
|
GrallocFrameBuffer::GrallocFrameBuffer(buffer_handle_t buffer, uint32_t width,
|
|
uint32_t height, uint32_t fourcc,
|
|
uint32_t device_buffer_length,
|
|
uint32_t stream_usage)
|
|
: buffer_(buffer),
|
|
is_mapped_(false),
|
|
device_buffer_length_(device_buffer_length),
|
|
stream_usage_(stream_usage) {
|
|
const hw_module_t* module = nullptr;
|
|
int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
|
|
if (ret || !module) {
|
|
LOGF(ERROR) << "Failed to get gralloc module.";
|
|
return;
|
|
}
|
|
gralloc_module_ = reinterpret_cast<const gralloc_module_t*>(module);
|
|
width_ = width;
|
|
height_ = height;
|
|
fourcc_ = fourcc;
|
|
}
|
|
|
|
GrallocFrameBuffer::~GrallocFrameBuffer() {
|
|
if (Unmap()) {
|
|
LOGF(ERROR) << "Unmap failed";
|
|
}
|
|
}
|
|
|
|
int GrallocFrameBuffer::Map() {
|
|
base::AutoLock l(lock_);
|
|
if (is_mapped_) {
|
|
LOGF(ERROR) << "The buffer is already mapped";
|
|
return -EINVAL;
|
|
}
|
|
|
|
void* addr;
|
|
int ret = 0;
|
|
switch (fourcc_) {
|
|
case V4L2_PIX_FMT_YUV420:
|
|
case V4L2_PIX_FMT_YVU420:
|
|
case V4L2_PIX_FMT_YUYV:
|
|
android_ycbcr yuv_data;
|
|
ret = gralloc_module_->lock_ycbcr(gralloc_module_, buffer_, stream_usage_,
|
|
0, 0, width_, height_, &yuv_data);
|
|
addr = yuv_data.y;
|
|
break;
|
|
case V4L2_PIX_FMT_JPEG:
|
|
ret = gralloc_module_->lock(gralloc_module_, buffer_, stream_usage_, 0, 0,
|
|
device_buffer_length_, 1, &addr);
|
|
break;
|
|
case V4L2_PIX_FMT_BGR32:
|
|
case V4L2_PIX_FMT_RGB32:
|
|
ret = gralloc_module_->lock(gralloc_module_, buffer_, stream_usage_, 0, 0,
|
|
width_, height_, &addr);
|
|
break;
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (ret) {
|
|
LOGF(ERROR) << "Failed to gralloc lock buffer: " << ret;
|
|
return ret;
|
|
}
|
|
|
|
data_ = static_cast<uint8_t*>(addr);
|
|
if (fourcc_ == V4L2_PIX_FMT_YVU420 || fourcc_ == V4L2_PIX_FMT_YUV420 ||
|
|
fourcc_ == V4L2_PIX_FMT_NV21 || fourcc_ == V4L2_PIX_FMT_RGB32 ||
|
|
fourcc_ == V4L2_PIX_FMT_BGR32) {
|
|
buffer_size_ = ImageProcessor::GetConvertedSize(fourcc_, width_, height_);
|
|
}
|
|
|
|
is_mapped_ = true;
|
|
return 0;
|
|
}
|
|
|
|
int GrallocFrameBuffer::Unmap() {
|
|
base::AutoLock l(lock_);
|
|
if (is_mapped_ && gralloc_module_->unlock(gralloc_module_, buffer_)) {
|
|
LOGF(ERROR) << "Failed to unmap buffer: ";
|
|
return -EINVAL;
|
|
}
|
|
is_mapped_ = false;
|
|
return 0;
|
|
}
|
|
|
|
} // namespace arc
|