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