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 17 FrameBuffer::FrameBuffer() 18 : data_(nullptr), 19 data_size_(0), 20 buffer_size_(0), 21 width_(0), 22 height_(0), 23 fourcc_(0) {} 24 25 FrameBuffer::~FrameBuffer() {} 26 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 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 43 AllocatedFrameBuffer::AllocatedFrameBuffer(uint8_t* buffer, int buffer_size) { 44 buffer_.reset(buffer); 45 buffer_size_ = buffer_size; 46 data_ = buffer_.get(); 47 } 48 49 AllocatedFrameBuffer::~AllocatedFrameBuffer() {} 50 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 61 void AllocatedFrameBuffer::Reset() { memset(data_, 0, buffer_size_); } 62 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 73 V4L2FrameBuffer::~V4L2FrameBuffer() { 74 if (Unmap()) { 75 LOGF(ERROR) << "Unmap failed"; 76 } 77 } 78 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 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 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 125 GrallocFrameBuffer::~GrallocFrameBuffer() { 126 if (Unmap()) { 127 LOGF(ERROR) << "Unmap failed"; 128 } 129 } 130 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 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