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 <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