Home | History | Annotate | Download | only in 3_4
      1 /*
      2  * Copyright 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 //#define LOG_NDEBUG 0
     18 #define LOG_TAG "V4L2Wrapper"
     19 
     20 #include "v4l2_wrapper.h"
     21 
     22 #include <algorithm>
     23 #include <fcntl.h>
     24 #include <limits>
     25 
     26 #include <android-base/unique_fd.h>
     27 #include <linux/videodev2.h>
     28 #include <sys/stat.h>
     29 #include <sys/types.h>
     30 #include "arc/cached_frame.h"
     31 
     32 namespace v4l2_camera_hal {
     33 
     34 using arc::AllocatedFrameBuffer;
     35 using arc::SupportedFormat;
     36 using arc::SupportedFormats;
     37 using default_camera_hal::CaptureRequest;
     38 
     39 const int32_t kStandardSizes[][2] = {
     40   {4096, 2160}, // 4KDCI (for USB camera)
     41   {3840, 2160}, // 4KUHD (for USB camera)
     42   {3280, 2464}, // 8MP
     43   {2560, 1440}, // QHD
     44   {1920, 1080}, // HD1080
     45   {1640, 1232}, // 2MP
     46   {1280,  720}, // HD
     47   {1024,  768}, // XGA
     48   { 640,  480}, // VGA
     49   { 320,  240}, // QVGA
     50   { 176,  144}  // QCIF
     51 };
     52 
     53 V4L2Wrapper* V4L2Wrapper::NewV4L2Wrapper(const std::string device_path) {
     54   return new V4L2Wrapper(device_path);
     55 }
     56 
     57 V4L2Wrapper::V4L2Wrapper(const std::string device_path)
     58     : device_path_(std::move(device_path)), connection_count_(0) {}
     59 
     60 V4L2Wrapper::~V4L2Wrapper() {}
     61 
     62 int V4L2Wrapper::Connect() {
     63   HAL_LOG_ENTER();
     64   std::lock_guard<std::mutex> lock(connection_lock_);
     65 
     66   if (connected()) {
     67     HAL_LOGV("Camera device %s is already connected.", device_path_.c_str());
     68     ++connection_count_;
     69     return 0;
     70   }
     71 
     72   // Open in nonblocking mode (DQBUF may return EAGAIN).
     73   int fd = TEMP_FAILURE_RETRY(open(device_path_.c_str(), O_RDWR | O_NONBLOCK));
     74   if (fd < 0) {
     75     HAL_LOGE("failed to open %s (%s)", device_path_.c_str(), strerror(errno));
     76     return -ENODEV;
     77   }
     78   device_fd_.reset(fd);
     79   ++connection_count_;
     80 
     81   // Check if this connection has the extended control query capability.
     82   v4l2_query_ext_ctrl query;
     83   query.id = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND;
     84   extended_query_supported_ = (IoctlLocked(VIDIOC_QUERY_EXT_CTRL, &query) == 0);
     85 
     86   // TODO(b/29185945): confirm this is a supported device.
     87   // This is checked by the HAL, but the device at device_path_ may
     88   // not be the same one that was there when the HAL was loaded.
     89   // (Alternatively, better hotplugging support may make this unecessary
     90   // by disabling cameras that get disconnected and checking newly connected
     91   // cameras, so Connect() is never called on an unsupported camera)
     92 
     93   supported_formats_ = GetSupportedFormats();
     94   qualified_formats_ = StreamFormat::GetQualifiedFormats(supported_formats_);
     95 
     96   return 0;
     97 }
     98 
     99 void V4L2Wrapper::Disconnect() {
    100   HAL_LOG_ENTER();
    101   std::lock_guard<std::mutex> lock(connection_lock_);
    102 
    103   if (connection_count_ == 0) {
    104     // Not connected.
    105     HAL_LOGE("Camera device %s is not connected, cannot disconnect.",
    106              device_path_.c_str());
    107     return;
    108   }
    109 
    110   --connection_count_;
    111   if (connection_count_ > 0) {
    112     HAL_LOGV("Disconnected from camera device %s. %d connections remain.",
    113              device_path_.c_str(), connection_count_);
    114     return;
    115   }
    116 
    117   device_fd_.reset(-1);  // Includes close().
    118   format_.reset();
    119   {
    120     std::lock_guard<std::mutex> buffer_lock(buffer_queue_lock_);
    121     buffers_.clear();
    122   }
    123 }
    124 
    125 // Helper function. Should be used instead of ioctl throughout this class.
    126 template <typename T>
    127 int V4L2Wrapper::IoctlLocked(unsigned long request, T data) {
    128   // Potentially called so many times logging entry is a bad idea.
    129   std::lock_guard<std::mutex> lock(device_lock_);
    130 
    131   if (!connected()) {
    132     HAL_LOGE("Device %s not connected.", device_path_.c_str());
    133     return -ENODEV;
    134   }
    135   return TEMP_FAILURE_RETRY(ioctl(device_fd_.get(), request, data));
    136 }
    137 
    138 int V4L2Wrapper::StreamOn() {
    139   if (!format_) {
    140     HAL_LOGE("Stream format must be set before turning on stream.");
    141     return -EINVAL;
    142   }
    143 
    144   int32_t type = format_->type();
    145   if (IoctlLocked(VIDIOC_STREAMON, &type) < 0) {
    146     HAL_LOGE("STREAMON fails (%d): %s", errno, strerror(errno));
    147     return -ENODEV;
    148   }
    149 
    150   HAL_LOGV("Stream turned on.");
    151   return 0;
    152 }
    153 
    154 int V4L2Wrapper::StreamOff() {
    155   if (!format_) {
    156     // Can't have turned on the stream without format being set,
    157     // so nothing to turn off here.
    158     return 0;
    159   }
    160 
    161   int32_t type = format_->type();
    162   int res = IoctlLocked(VIDIOC_STREAMOFF, &type);
    163   // Calling STREAMOFF releases all queued buffers back to the user.
    164   // No buffers in flight.
    165   if (res < 0) {
    166     HAL_LOGE("STREAMOFF fails: %s", strerror(errno));
    167     return -ENODEV;
    168   }
    169   std::lock_guard<std::mutex> lock(buffer_queue_lock_);
    170   for (auto& buffer : buffers_) {
    171     buffer.active = false;
    172     buffer.request.reset();
    173   }
    174   HAL_LOGV("Stream turned off.");
    175   return 0;
    176 }
    177 
    178 int V4L2Wrapper::QueryControl(uint32_t control_id,
    179                               v4l2_query_ext_ctrl* result) {
    180   int res;
    181 
    182   memset(result, 0, sizeof(*result));
    183 
    184   if (extended_query_supported_) {
    185     result->id = control_id;
    186     res = IoctlLocked(VIDIOC_QUERY_EXT_CTRL, result);
    187     // Assuming the operation was supported (not ENOTTY), no more to do.
    188     if (errno != ENOTTY) {
    189       if (res) {
    190         HAL_LOGE("QUERY_EXT_CTRL fails: %s", strerror(errno));
    191         return -ENODEV;
    192       }
    193       return 0;
    194     }
    195   }
    196 
    197   // Extended control querying not supported, fall back to basic control query.
    198   v4l2_queryctrl query;
    199   query.id = control_id;
    200   if (IoctlLocked(VIDIOC_QUERYCTRL, &query)) {
    201     HAL_LOGE("QUERYCTRL fails: %s", strerror(errno));
    202     return -ENODEV;
    203   }
    204 
    205   // Convert the basic result to the extended result.
    206   result->id = query.id;
    207   result->type = query.type;
    208   memcpy(result->name, query.name, sizeof(query.name));
    209   result->minimum = query.minimum;
    210   if (query.type == V4L2_CTRL_TYPE_BITMASK) {
    211     // According to the V4L2 documentation, when type is BITMASK,
    212     // max and default should be interpreted as __u32. Practically,
    213     // this means the conversion from 32 bit to 64 will pad with 0s not 1s.
    214     result->maximum = static_cast<uint32_t>(query.maximum);
    215     result->default_value = static_cast<uint32_t>(query.default_value);
    216   } else {
    217     result->maximum = query.maximum;
    218     result->default_value = query.default_value;
    219   }
    220   result->step = static_cast<uint32_t>(query.step);
    221   result->flags = query.flags;
    222   result->elems = 1;
    223   switch (result->type) {
    224     case V4L2_CTRL_TYPE_INTEGER64:
    225       result->elem_size = sizeof(int64_t);
    226       break;
    227     case V4L2_CTRL_TYPE_STRING:
    228       result->elem_size = result->maximum + 1;
    229       break;
    230     default:
    231       result->elem_size = sizeof(int32_t);
    232       break;
    233   }
    234 
    235   return 0;
    236 }
    237 
    238 int V4L2Wrapper::GetControl(uint32_t control_id, int32_t* value) {
    239   // For extended controls (any control class other than "user"),
    240   // G_EXT_CTRL must be used instead of G_CTRL.
    241   if (V4L2_CTRL_ID2CLASS(control_id) != V4L2_CTRL_CLASS_USER) {
    242     v4l2_ext_control control;
    243     v4l2_ext_controls controls;
    244     memset(&control, 0, sizeof(control));
    245     memset(&controls, 0, sizeof(controls));
    246 
    247     control.id = control_id;
    248     controls.ctrl_class = V4L2_CTRL_ID2CLASS(control_id);
    249     controls.count = 1;
    250     controls.controls = &control;
    251 
    252     if (IoctlLocked(VIDIOC_G_EXT_CTRLS, &controls) < 0) {
    253       HAL_LOGE("G_EXT_CTRLS fails: %s", strerror(errno));
    254       return -ENODEV;
    255     }
    256     *value = control.value;
    257   } else {
    258     v4l2_control control{control_id, 0};
    259     if (IoctlLocked(VIDIOC_G_CTRL, &control) < 0) {
    260       HAL_LOGE("G_CTRL fails: %s", strerror(errno));
    261       return -ENODEV;
    262     }
    263     *value = control.value;
    264   }
    265   return 0;
    266 }
    267 
    268 int V4L2Wrapper::SetControl(uint32_t control_id,
    269                             int32_t desired,
    270                             int32_t* result) {
    271   int32_t result_value = 0;
    272 
    273   // TODO(b/29334616): When async, this may need to check if the stream
    274   // is on, and if so, lock it off while setting format. Need to look
    275   // into if V4L2 supports adjusting controls while the stream is on.
    276 
    277   // For extended controls (any control class other than "user"),
    278   // S_EXT_CTRL must be used instead of S_CTRL.
    279   if (V4L2_CTRL_ID2CLASS(control_id) != V4L2_CTRL_CLASS_USER) {
    280     v4l2_ext_control control;
    281     v4l2_ext_controls controls;
    282     memset(&control, 0, sizeof(control));
    283     memset(&controls, 0, sizeof(controls));
    284 
    285     control.id = control_id;
    286     control.value = desired;
    287     controls.ctrl_class = V4L2_CTRL_ID2CLASS(control_id);
    288     controls.count = 1;
    289     controls.controls = &control;
    290 
    291     if (IoctlLocked(VIDIOC_S_EXT_CTRLS, &controls) < 0) {
    292       HAL_LOGE("S_EXT_CTRLS fails: %s", strerror(errno));
    293       return -ENODEV;
    294     }
    295     result_value = control.value;
    296   } else {
    297     v4l2_control control{control_id, desired};
    298     if (IoctlLocked(VIDIOC_S_CTRL, &control) < 0) {
    299       HAL_LOGE("S_CTRL fails: %s", strerror(errno));
    300       return -ENODEV;
    301     }
    302     result_value = control.value;
    303   }
    304 
    305   // If the caller wants to know the result, pass it back.
    306   if (result != nullptr) {
    307     *result = result_value;
    308   }
    309   return 0;
    310 }
    311 
    312 const SupportedFormats V4L2Wrapper::GetSupportedFormats() {
    313   SupportedFormats formats;
    314   std::set<uint32_t> pixel_formats;
    315   int res = GetFormats(&pixel_formats);
    316   if (res) {
    317     HAL_LOGE("Failed to get device formats.");
    318     return formats;
    319   }
    320 
    321   arc::SupportedFormat supported_format;
    322   std::set<std::array<int32_t, 2>> frame_sizes;
    323 
    324   for (auto pixel_format : pixel_formats) {
    325     supported_format.fourcc = pixel_format;
    326 
    327     frame_sizes.clear();
    328     res = GetFormatFrameSizes(pixel_format, &frame_sizes);
    329     if (res) {
    330       HAL_LOGE("Failed to get frame sizes for format: 0x%x", pixel_format);
    331       continue;
    332     }
    333     for (auto frame_size : frame_sizes) {
    334       supported_format.width = frame_size[0];
    335       supported_format.height = frame_size[1];
    336       formats.push_back(supported_format);
    337     }
    338   }
    339   return formats;
    340 }
    341 
    342 int V4L2Wrapper::GetFormats(std::set<uint32_t>* v4l2_formats) {
    343   HAL_LOG_ENTER();
    344 
    345   v4l2_fmtdesc format_query;
    346   memset(&format_query, 0, sizeof(format_query));
    347   // TODO(b/30000211): multiplanar support.
    348   format_query.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    349   while (IoctlLocked(VIDIOC_ENUM_FMT, &format_query) >= 0) {
    350     v4l2_formats->insert(format_query.pixelformat);
    351     ++format_query.index;
    352   }
    353 
    354   if (errno != EINVAL) {
    355     HAL_LOGE(
    356         "ENUM_FMT fails at index %d: %s", format_query.index, strerror(errno));
    357     return -ENODEV;
    358   }
    359   return 0;
    360 }
    361 
    362 int V4L2Wrapper::GetQualifiedFormats(std::vector<uint32_t>* v4l2_formats) {
    363   HAL_LOG_ENTER();
    364   if (!connected()) {
    365     HAL_LOGE(
    366         "Device is not connected, qualified formats may not have been set.");
    367     return -EINVAL;
    368   }
    369   v4l2_formats->clear();
    370   std::set<uint32_t> unique_fourccs;
    371   for (auto& format : qualified_formats_) {
    372     unique_fourccs.insert(format.fourcc);
    373   }
    374   v4l2_formats->assign(unique_fourccs.begin(), unique_fourccs.end());
    375   return 0;
    376 }
    377 
    378 int V4L2Wrapper::GetFormatFrameSizes(uint32_t v4l2_format,
    379                                      std::set<std::array<int32_t, 2>>* sizes) {
    380   v4l2_frmsizeenum size_query;
    381   memset(&size_query, 0, sizeof(size_query));
    382   size_query.pixel_format = v4l2_format;
    383   if (IoctlLocked(VIDIOC_ENUM_FRAMESIZES, &size_query) < 0) {
    384     HAL_LOGE("ENUM_FRAMESIZES failed: %s", strerror(errno));
    385     return -ENODEV;
    386   }
    387   if (size_query.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
    388     // Discrete: enumerate all sizes using VIDIOC_ENUM_FRAMESIZES.
    389     // Assuming that a driver with discrete frame sizes has a reasonable number
    390     // of them.
    391     do {
    392       sizes->insert({{{static_cast<int32_t>(size_query.discrete.width),
    393                        static_cast<int32_t>(size_query.discrete.height)}}});
    394       ++size_query.index;
    395     } while (IoctlLocked(VIDIOC_ENUM_FRAMESIZES, &size_query) >= 0);
    396     if (errno != EINVAL) {
    397       HAL_LOGE("ENUM_FRAMESIZES fails at index %d: %s",
    398                size_query.index,
    399                strerror(errno));
    400       return -ENODEV;
    401     }
    402   } else {
    403     // Continuous/Step-wise: based on the stepwise struct returned by the query.
    404     // Fully listing all possible sizes, with large enough range/small enough
    405     // step size, may produce far too many potential sizes. Instead, find the
    406     // closest to a set of standard sizes.
    407     for (const auto size : kStandardSizes) {
    408       // Find the closest size, rounding up.
    409       uint32_t desired_width = size[0];
    410       uint32_t desired_height = size[1];
    411       if (desired_width < size_query.stepwise.min_width ||
    412           desired_height < size_query.stepwise.min_height) {
    413         HAL_LOGV("Standard size %u x %u is too small for format %d",
    414                  desired_width,
    415                  desired_height,
    416                  v4l2_format);
    417         continue;
    418       } else if (desired_width > size_query.stepwise.max_width ||
    419                  desired_height > size_query.stepwise.max_height) {
    420         HAL_LOGV("Standard size %u x %u is too big for format %d",
    421                  desired_width,
    422                  desired_height,
    423                  v4l2_format);
    424         continue;
    425       }
    426 
    427       // Round up.
    428       uint32_t width_steps = (desired_width - size_query.stepwise.min_width +
    429                               size_query.stepwise.step_width - 1) /
    430                              size_query.stepwise.step_width;
    431       uint32_t height_steps = (desired_height - size_query.stepwise.min_height +
    432                                size_query.stepwise.step_height - 1) /
    433                               size_query.stepwise.step_height;
    434       sizes->insert(
    435           {{{static_cast<int32_t>(size_query.stepwise.min_width +
    436                                   width_steps * size_query.stepwise.step_width),
    437              static_cast<int32_t>(size_query.stepwise.min_height +
    438                                   height_steps *
    439                                       size_query.stepwise.step_height)}}});
    440     }
    441   }
    442   return 0;
    443 }
    444 
    445 // Converts a v4l2_fract with units of seconds to an int64_t with units of ns.
    446 inline int64_t FractToNs(const v4l2_fract& fract) {
    447   return (1000000000LL * fract.numerator) / fract.denominator;
    448 }
    449 
    450 int V4L2Wrapper::GetFormatFrameDurationRange(
    451     uint32_t v4l2_format,
    452     const std::array<int32_t, 2>& size,
    453     std::array<int64_t, 2>* duration_range) {
    454   // Potentially called so many times logging entry is a bad idea.
    455 
    456   v4l2_frmivalenum duration_query;
    457   memset(&duration_query, 0, sizeof(duration_query));
    458   duration_query.pixel_format = v4l2_format;
    459   duration_query.width = size[0];
    460   duration_query.height = size[1];
    461   if (IoctlLocked(VIDIOC_ENUM_FRAMEINTERVALS, &duration_query) < 0) {
    462     HAL_LOGE("ENUM_FRAMEINTERVALS failed: %s", strerror(errno));
    463     return -ENODEV;
    464   }
    465 
    466   int64_t min = std::numeric_limits<int64_t>::max();
    467   int64_t max = std::numeric_limits<int64_t>::min();
    468   if (duration_query.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
    469     // Discrete: enumerate all durations using VIDIOC_ENUM_FRAMEINTERVALS.
    470     do {
    471       min = std::min(min, FractToNs(duration_query.discrete));
    472       max = std::max(max, FractToNs(duration_query.discrete));
    473       ++duration_query.index;
    474     } while (IoctlLocked(VIDIOC_ENUM_FRAMEINTERVALS, &duration_query) >= 0);
    475     if (errno != EINVAL) {
    476       HAL_LOGE("ENUM_FRAMEINTERVALS fails at index %d: %s",
    477                duration_query.index,
    478                strerror(errno));
    479       return -ENODEV;
    480     }
    481   } else {
    482     // Continuous/Step-wise: simply convert the given min and max.
    483     min = FractToNs(duration_query.stepwise.min);
    484     max = FractToNs(duration_query.stepwise.max);
    485   }
    486   (*duration_range)[0] = min;
    487   (*duration_range)[1] = max;
    488   return 0;
    489 }
    490 
    491 int V4L2Wrapper::SetFormat(const StreamFormat& desired_format,
    492                            uint32_t* result_max_buffers) {
    493   HAL_LOG_ENTER();
    494 
    495   if (format_ && desired_format == *format_) {
    496     HAL_LOGV("Already in correct format, skipping format setting.");
    497     *result_max_buffers = buffers_.size();
    498     return 0;
    499   }
    500 
    501   if (format_) {
    502     // If we had an old format, first request 0 buffers to inform the device
    503     // we're no longer using any previously "allocated" buffers from the old
    504     // format. This seems like it shouldn't be necessary for USERPTR memory,
    505     // and/or should happen from turning the stream off, but the driver
    506     // complained. May be a driver issue, or may be intended behavior.
    507     int res = RequestBuffers(0);
    508     if (res) {
    509       return res;
    510     }
    511   }
    512 
    513   // Select the matching format, or if not available, select a qualified format
    514   // we can convert from.
    515   SupportedFormat format;
    516   if (!StreamFormat::FindBestFitFormat(supported_formats_, qualified_formats_,
    517                                        desired_format.v4l2_pixel_format(),
    518                                        desired_format.width(),
    519                                        desired_format.height(), &format)) {
    520     HAL_LOGE(
    521         "Unable to find supported resolution in list, "
    522         "width: %d, height: %d",
    523         desired_format.width(), desired_format.height());
    524     return -EINVAL;
    525   }
    526 
    527   // Set the camera to the new format.
    528   v4l2_format new_format;
    529   const StreamFormat resolved_format(format);
    530   resolved_format.FillFormatRequest(&new_format);
    531 
    532   // TODO(b/29334616): When async, this will need to check if the stream
    533   // is on, and if so, lock it off while setting format.
    534   if (IoctlLocked(VIDIOC_S_FMT, &new_format) < 0) {
    535     HAL_LOGE("S_FMT failed: %s", strerror(errno));
    536     return -ENODEV;
    537   }
    538 
    539   // Check that the driver actually set to the requested values.
    540   if (resolved_format != new_format) {
    541     HAL_LOGE("Device doesn't support desired stream configuration.");
    542     return -EINVAL;
    543   }
    544 
    545   // Keep track of our new format.
    546   format_.reset(new StreamFormat(new_format));
    547 
    548   // Format changed, request new buffers.
    549   int res = RequestBuffers(1);
    550   if (res) {
    551     HAL_LOGE("Requesting buffers for new format failed.");
    552     return res;
    553   }
    554   *result_max_buffers = buffers_.size();
    555   return 0;
    556 }
    557 
    558 int V4L2Wrapper::RequestBuffers(uint32_t num_requested) {
    559   v4l2_requestbuffers req_buffers;
    560   memset(&req_buffers, 0, sizeof(req_buffers));
    561   req_buffers.type = format_->type();
    562   req_buffers.memory = V4L2_MEMORY_USERPTR;
    563   req_buffers.count = num_requested;
    564 
    565   int res = IoctlLocked(VIDIOC_REQBUFS, &req_buffers);
    566   // Calling REQBUFS releases all queued buffers back to the user.
    567   if (res < 0) {
    568     HAL_LOGE("REQBUFS failed: %s", strerror(errno));
    569     return -ENODEV;
    570   }
    571 
    572   // V4L2 will set req_buffers.count to a number of buffers it can handle.
    573   if (num_requested > 0 && req_buffers.count < 1) {
    574     HAL_LOGE("REQBUFS claims it can't handle any buffers.");
    575     return -ENODEV;
    576   }
    577   buffers_.resize(req_buffers.count);
    578   return 0;
    579 }
    580 
    581 int V4L2Wrapper::EnqueueRequest(
    582     std::shared_ptr<default_camera_hal::CaptureRequest> request) {
    583   if (!format_) {
    584     HAL_LOGE("Stream format must be set before enqueuing buffers.");
    585     return -ENODEV;
    586   }
    587 
    588   // Find a free buffer index. Could use some sort of persistent hinting
    589   // here to improve expected efficiency, but buffers_.size() is expected
    590   // to be low enough (<10 experimentally) that it's not worth it.
    591   int index = -1;
    592   {
    593     std::lock_guard<std::mutex> guard(buffer_queue_lock_);
    594     for (size_t i = 0; i < buffers_.size(); ++i) {
    595       if (!buffers_[i].active) {
    596         index = i;
    597         break;
    598       }
    599     }
    600   }
    601   if (index < 0) {
    602     // Note: The HAL should be tracking the number of buffers in flight
    603     // for each stream, and should never overflow the device.
    604     HAL_LOGE("Cannot enqueue buffer: stream is already full.");
    605     return -ENODEV;
    606   }
    607 
    608   // Set up a v4l2 buffer struct.
    609   v4l2_buffer device_buffer;
    610   memset(&device_buffer, 0, sizeof(device_buffer));
    611   device_buffer.type = format_->type();
    612   device_buffer.index = index;
    613 
    614   // Use QUERYBUF to ensure our buffer/device is in good shape,
    615   // and fill out remaining fields.
    616   if (IoctlLocked(VIDIOC_QUERYBUF, &device_buffer) < 0) {
    617     HAL_LOGE("QUERYBUF fails: %s", strerror(errno));
    618     // Return buffer index.
    619     std::lock_guard<std::mutex> guard(buffer_queue_lock_);
    620     buffers_[index].active = false;
    621     return -ENODEV;
    622   }
    623 
    624   // Setup our request context and fill in the user pointer field.
    625   RequestContext* request_context;
    626   void* data;
    627   {
    628     std::lock_guard<std::mutex> guard(buffer_queue_lock_);
    629     request_context = &buffers_[index];
    630     request_context->camera_buffer->SetDataSize(device_buffer.length);
    631     request_context->camera_buffer->Reset();
    632     request_context->camera_buffer->SetFourcc(format_->v4l2_pixel_format());
    633     request_context->camera_buffer->SetWidth(format_->width());
    634     request_context->camera_buffer->SetHeight(format_->height());
    635     request_context->request = request;
    636     data = request_context->camera_buffer->GetData();
    637   }
    638   device_buffer.m.userptr = reinterpret_cast<unsigned long>(data);
    639 
    640   // Pass the buffer to the camera.
    641   if (IoctlLocked(VIDIOC_QBUF, &device_buffer) < 0) {
    642     HAL_LOGE("QBUF fails: %s", strerror(errno));
    643     return -ENODEV;
    644   }
    645 
    646   // Mark the buffer as in flight.
    647   std::lock_guard<std::mutex> guard(buffer_queue_lock_);
    648   request_context->active = true;
    649 
    650   return 0;
    651 }
    652 
    653 int V4L2Wrapper::DequeueRequest(std::shared_ptr<CaptureRequest>* request) {
    654   if (!format_) {
    655     HAL_LOGV(
    656         "Format not set, so stream can't be on, "
    657         "so no buffers available for dequeueing");
    658     return -EAGAIN;
    659   }
    660 
    661   v4l2_buffer buffer;
    662   memset(&buffer, 0, sizeof(buffer));
    663   buffer.type = format_->type();
    664   buffer.memory = V4L2_MEMORY_USERPTR;
    665   int res = IoctlLocked(VIDIOC_DQBUF, &buffer);
    666   if (res) {
    667     if (errno == EAGAIN) {
    668       // Expected failure.
    669       return -EAGAIN;
    670     } else {
    671       // Unexpected failure.
    672       HAL_LOGE("DQBUF fails: %s", strerror(errno));
    673       return -ENODEV;
    674     }
    675   }
    676 
    677   std::lock_guard<std::mutex> guard(buffer_queue_lock_);
    678   RequestContext* request_context = &buffers_[buffer.index];
    679 
    680   // Lock the camera stream buffer for painting.
    681   const camera3_stream_buffer_t* stream_buffer =
    682       &request_context->request->output_buffers[0];
    683   uint32_t fourcc =
    684       StreamFormat::HalToV4L2PixelFormat(stream_buffer->stream->format);
    685 
    686   if (request) {
    687     *request = request_context->request;
    688   }
    689 
    690   // Note that the device buffer length is passed to the output frame. If the
    691   // GrallocFrameBuffer does not have support for the transformation to
    692   // |fourcc|, it will assume that the amount of data to lock is based on
    693   // |buffer.length|, otherwise it will use the ImageProcessor::ConvertedSize.
    694   arc::GrallocFrameBuffer output_frame(
    695       *stream_buffer->buffer, stream_buffer->stream->width,
    696       stream_buffer->stream->height, fourcc, buffer.length,
    697       stream_buffer->stream->usage);
    698   res = output_frame.Map();
    699   if (res) {
    700     HAL_LOGE("Failed to map output frame.");
    701     request_context->request.reset();
    702     return -EINVAL;
    703   }
    704   if (request_context->camera_buffer->GetFourcc() == fourcc &&
    705       request_context->camera_buffer->GetWidth() ==
    706           stream_buffer->stream->width &&
    707       request_context->camera_buffer->GetHeight() ==
    708           stream_buffer->stream->height) {
    709     // If no format conversion needs to be applied, directly copy the data over.
    710     memcpy(output_frame.GetData(), request_context->camera_buffer->GetData(),
    711            request_context->camera_buffer->GetDataSize());
    712   } else {
    713     // Perform the format conversion.
    714     arc::CachedFrame cached_frame;
    715     cached_frame.SetSource(request_context->camera_buffer.get(), 0);
    716     cached_frame.Convert(request_context->request->settings, &output_frame);
    717   }
    718 
    719   request_context->request.reset();
    720   // Mark the buffer as not in flight.
    721   request_context->active = false;
    722   return 0;
    723 }
    724 
    725 int V4L2Wrapper::GetInFlightBufferCount() {
    726   int count = 0;
    727   std::lock_guard<std::mutex> guard(buffer_queue_lock_);
    728   for (auto& buffer : buffers_) {
    729     if (buffer.active) {
    730       count++;
    731     }
    732   }
    733   return count;
    734 }
    735 
    736 }  // namespace v4l2_camera_hal
    737