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