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