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