• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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