1 /* Copyright 2017 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
6 #include "arc/frame_buffer.h"
7
8 #include <sys/mman.h>
9
10 #include <utility>
11
12 #include "arc/common.h"
13 #include "arc/image_processor.h"
14
15 namespace arc {
16
FrameBuffer()17 FrameBuffer::FrameBuffer()
18 : data_(nullptr),
19 data_size_(0),
20 buffer_size_(0),
21 width_(0),
22 height_(0),
23 fourcc_(0) {}
24
~FrameBuffer()25 FrameBuffer::~FrameBuffer() {}
26
SetDataSize(size_t data_size)27 int FrameBuffer::SetDataSize(size_t data_size) {
28 if (data_size > buffer_size_) {
29 LOGF(ERROR) << "Buffer overflow: Buffer only has " << buffer_size_
30 << ", but data needs " << data_size;
31 return -EINVAL;
32 }
33 data_size_ = data_size;
34 return 0;
35 }
36
AllocatedFrameBuffer(int buffer_size)37 AllocatedFrameBuffer::AllocatedFrameBuffer(int buffer_size) {
38 buffer_.reset(new uint8_t[buffer_size]);
39 buffer_size_ = buffer_size;
40 data_ = buffer_.get();
41 }
42
AllocatedFrameBuffer(uint8_t * buffer,int buffer_size)43 AllocatedFrameBuffer::AllocatedFrameBuffer(uint8_t* buffer, int buffer_size) {
44 buffer_.reset(buffer);
45 buffer_size_ = buffer_size;
46 data_ = buffer_.get();
47 }
48
~AllocatedFrameBuffer()49 AllocatedFrameBuffer::~AllocatedFrameBuffer() {}
50
SetDataSize(size_t size)51 int AllocatedFrameBuffer::SetDataSize(size_t size) {
52 if (size > buffer_size_) {
53 buffer_.reset(new uint8_t[size]);
54 buffer_size_ = size;
55 data_ = buffer_.get();
56 }
57 data_size_ = size;
58 return 0;
59 }
60
Reset()61 void AllocatedFrameBuffer::Reset() { memset(data_, 0, buffer_size_); }
62
V4L2FrameBuffer(base::ScopedFD fd,int buffer_size,uint32_t width,uint32_t height,uint32_t fourcc)63 V4L2FrameBuffer::V4L2FrameBuffer(base::ScopedFD fd, int buffer_size,
64 uint32_t width, uint32_t height,
65 uint32_t fourcc)
66 : fd_(std::move(fd)), is_mapped_(false) {
67 buffer_size_ = buffer_size;
68 width_ = width;
69 height_ = height;
70 fourcc_ = fourcc;
71 }
72
~V4L2FrameBuffer()73 V4L2FrameBuffer::~V4L2FrameBuffer() {
74 if (Unmap()) {
75 LOGF(ERROR) << "Unmap failed";
76 }
77 }
78
Map()79 int V4L2FrameBuffer::Map() {
80 base::AutoLock l(lock_);
81 if (is_mapped_) {
82 LOGF(ERROR) << "The buffer is already mapped";
83 return -EINVAL;
84 }
85 void* addr = mmap(NULL, buffer_size_, PROT_READ, MAP_SHARED, fd_.get(), 0);
86 if (addr == MAP_FAILED) {
87 LOGF(ERROR) << "mmap() failed: " << strerror(errno);
88 return -EINVAL;
89 }
90 data_ = static_cast<uint8_t*>(addr);
91 is_mapped_ = true;
92 return 0;
93 }
94
Unmap()95 int V4L2FrameBuffer::Unmap() {
96 base::AutoLock l(lock_);
97 if (is_mapped_ && munmap(data_, buffer_size_)) {
98 LOGF(ERROR) << "mummap() failed: " << strerror(errno);
99 return -EINVAL;
100 }
101 is_mapped_ = false;
102 return 0;
103 }
104
GrallocFrameBuffer(buffer_handle_t buffer,uint32_t width,uint32_t height,uint32_t fourcc,uint32_t device_buffer_length,uint32_t stream_usage)105 GrallocFrameBuffer::GrallocFrameBuffer(buffer_handle_t buffer, uint32_t width,
106 uint32_t height, uint32_t fourcc,
107 uint32_t device_buffer_length,
108 uint32_t stream_usage)
109 : buffer_(buffer),
110 is_mapped_(false),
111 device_buffer_length_(device_buffer_length),
112 stream_usage_(stream_usage) {
113 const hw_module_t* module = nullptr;
114 int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
115 if (ret || !module) {
116 LOGF(ERROR) << "Failed to get gralloc module.";
117 return;
118 }
119 gralloc_module_ = reinterpret_cast<const gralloc_module_t*>(module);
120 width_ = width;
121 height_ = height;
122 fourcc_ = fourcc;
123 }
124
~GrallocFrameBuffer()125 GrallocFrameBuffer::~GrallocFrameBuffer() {
126 if (Unmap()) {
127 LOGF(ERROR) << "Unmap failed";
128 }
129 }
130
Map()131 int GrallocFrameBuffer::Map() {
132 base::AutoLock l(lock_);
133 if (is_mapped_) {
134 LOGF(ERROR) << "The buffer is already mapped";
135 return -EINVAL;
136 }
137
138 void* addr;
139 int ret = 0;
140 switch (fourcc_) {
141 case V4L2_PIX_FMT_YUV420:
142 case V4L2_PIX_FMT_YVU420:
143 case V4L2_PIX_FMT_YUYV:
144 android_ycbcr yuv_data;
145 ret = gralloc_module_->lock_ycbcr(gralloc_module_, buffer_, stream_usage_,
146 0, 0, width_, height_, &yuv_data);
147 addr = yuv_data.y;
148 break;
149 case V4L2_PIX_FMT_JPEG:
150 ret = gralloc_module_->lock(gralloc_module_, buffer_, stream_usage_, 0, 0,
151 device_buffer_length_, 1, &addr);
152 break;
153 case V4L2_PIX_FMT_BGR32:
154 case V4L2_PIX_FMT_RGB32:
155 ret = gralloc_module_->lock(gralloc_module_, buffer_, stream_usage_, 0, 0,
156 width_, height_, &addr);
157 break;
158 default:
159 return -EINVAL;
160 }
161
162 if (ret) {
163 LOGF(ERROR) << "Failed to gralloc lock buffer: " << ret;
164 return ret;
165 }
166
167 data_ = static_cast<uint8_t*>(addr);
168 if (fourcc_ == V4L2_PIX_FMT_YVU420 || fourcc_ == V4L2_PIX_FMT_YUV420 ||
169 fourcc_ == V4L2_PIX_FMT_NV21 || fourcc_ == V4L2_PIX_FMT_RGB32 ||
170 fourcc_ == V4L2_PIX_FMT_BGR32) {
171 buffer_size_ = ImageProcessor::GetConvertedSize(fourcc_, width_, height_);
172 }
173
174 is_mapped_ = true;
175 return 0;
176 }
177
Unmap()178 int GrallocFrameBuffer::Unmap() {
179 base::AutoLock l(lock_);
180 if (is_mapped_ && gralloc_module_->unlock(gralloc_module_, buffer_)) {
181 LOGF(ERROR) << "Failed to unmap buffer: ";
182 return -EINVAL;
183 }
184 is_mapped_ = false;
185 return 0;
186 }
187
188 } // namespace arc
189