Home | History | Annotate | Download | only in arc
      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