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