1c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen/* 2c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen * Copyright 2016 The Android Open Source Project 3c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen * 4c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen * Licensed under the Apache License, Version 2.0 (the "License"); 5c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen * you may not use this file except in compliance with the License. 6c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen * You may obtain a copy of the License at 7c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen * 8c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen * http://www.apache.org/licenses/LICENSE-2.0 9c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen * 10c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen * Unless required by applicable law or agreed to in writing, software 11c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen * distributed under the License is distributed on an "AS IS" BASIS, 12c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen * See the License for the specific language governing permissions and 14c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen * limitations under the License. 15c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen */ 16c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 173841a7f4951fe1498bf5ba88466def3ea18f8867Ari Hausman-Cohen#include "v4l2_wrapper.h" 18c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 199e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen#include <algorithm> 20abbf9cc0bd4160642c36f7bd47c0277a8bf17adfAri Hausman-Cohen#include <array> 219e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen#include <limits> 222d1ea3a164de3d5908b2f3c127b8979e906d37b9Ari Hausman-Cohen#include <mutex> 239e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen#include <vector> 249e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen 25c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen#include <fcntl.h> 26c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen#include <linux/videodev2.h> 27c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen#include <sys/stat.h> 28c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen#include <sys/types.h> 29c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 302d1ea3a164de3d5908b2f3c127b8979e906d37b9Ari Hausman-Cohen#include <android-base/unique_fd.h> 31c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 3228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan#include "arc/cached_frame.h" 33c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 34c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohennamespace v4l2_camera_hal { 35c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 3628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathanusing arc::AllocatedFrameBuffer; 3728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathanusing arc::SupportedFormat; 3828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathanusing arc::SupportedFormats; 3928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathanusing default_camera_hal::CaptureRequest; 4028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 41932d4dddd97ca2c690363a2245cfab46dab6496fJaesung Chungconst int32_t kStandardSizes[][2] = { 42932d4dddd97ca2c690363a2245cfab46dab6496fJaesung Chung {4096, 2160}, // 4KDCI (for USB camera) 43932d4dddd97ca2c690363a2245cfab46dab6496fJaesung Chung {3840, 2160}, // 4KUHD (for USB camera) 44932d4dddd97ca2c690363a2245cfab46dab6496fJaesung Chung {3280, 2464}, // 8MP 45932d4dddd97ca2c690363a2245cfab46dab6496fJaesung Chung {2560, 1440}, // QHD 46932d4dddd97ca2c690363a2245cfab46dab6496fJaesung Chung {1920, 1080}, // HD1080 47932d4dddd97ca2c690363a2245cfab46dab6496fJaesung Chung {1640, 1232}, // 2MP 48932d4dddd97ca2c690363a2245cfab46dab6496fJaesung Chung {1280, 720}, // HD 49932d4dddd97ca2c690363a2245cfab46dab6496fJaesung Chung {1024, 768}, // XGA 50932d4dddd97ca2c690363a2245cfab46dab6496fJaesung Chung { 640, 480}, // VGA 51932d4dddd97ca2c690363a2245cfab46dab6496fJaesung Chung { 320, 240}, // QVGA 52932d4dddd97ca2c690363a2245cfab46dab6496fJaesung Chung { 176, 144} // QCIF 53932d4dddd97ca2c690363a2245cfab46dab6496fJaesung Chung}; 549e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen 554ab49624207319ac99a75d7272d968c172064422Ari Hausman-CohenV4L2Wrapper* V4L2Wrapper::NewV4L2Wrapper(const std::string device_path) { 5628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan return new V4L2Wrapper(device_path); 574ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen} 584ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen 5928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth SwaminathanV4L2Wrapper::V4L2Wrapper(const std::string device_path) 6028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan : device_path_(std::move(device_path)), connection_count_(0) {} 61c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 62ad6fe2b033997ab0401b0a519b18cea6e957dac0Ari Hausman-CohenV4L2Wrapper::~V4L2Wrapper() {} 63c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 64c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohenint V4L2Wrapper::Connect() { 65c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen HAL_LOG_ENTER(); 669e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen std::lock_guard<std::mutex> lock(connection_lock_); 67c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 68c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen if (connected()) { 699e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen HAL_LOGV("Camera device %s is already connected.", device_path_.c_str()); 709e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen ++connection_count_; 719e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen return 0; 72c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen } 73c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 74c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen // Open in nonblocking mode (DQBUF may return EAGAIN). 75c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen int fd = TEMP_FAILURE_RETRY(open(device_path_.c_str(), O_RDWR | O_NONBLOCK)); 76c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen if (fd < 0) { 77c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen HAL_LOGE("failed to open %s (%s)", device_path_.c_str(), strerror(errno)); 789e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen return -ENODEV; 79c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen } 80c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen device_fd_.reset(fd); 819e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen ++connection_count_; 82c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 83c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen // Check if this connection has the extended control query capability. 84c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen v4l2_query_ext_ctrl query; 85c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen query.id = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND; 869e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen extended_query_supported_ = (IoctlLocked(VIDIOC_QUERY_EXT_CTRL, &query) == 0); 87c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 88c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen // TODO(b/29185945): confirm this is a supported device. 89c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen // This is checked by the HAL, but the device at device_path_ may 90c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen // not be the same one that was there when the HAL was loaded. 91c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen // (Alternatively, better hotplugging support may make this unecessary 92c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen // by disabling cameras that get disconnected and checking newly connected 93c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen // cameras, so Connect() is never called on an unsupported camera) 9428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 9528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan supported_formats_ = GetSupportedFormats(); 9628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan qualified_formats_ = StreamFormat::GetQualifiedFormats(supported_formats_); 9728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 98c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen return 0; 99c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen} 100c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 101c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohenvoid V4L2Wrapper::Disconnect() { 102c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen HAL_LOG_ENTER(); 1039e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen std::lock_guard<std::mutex> lock(connection_lock_); 1049e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen 1059e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen if (connection_count_ == 0) { 1069e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen // Not connected. 1079e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen HAL_LOGE("Camera device %s is not connected, cannot disconnect.", 108abbf9cc0bd4160642c36f7bd47c0277a8bf17adfAri Hausman-Cohen device_path_.c_str()); 1099e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen return; 1109e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen } 1119e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen 1129e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen --connection_count_; 1139e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen if (connection_count_ > 0) { 1149e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen HAL_LOGV("Disconnected from camera device %s. %d connections remain.", 11528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan device_path_.c_str(), connection_count_); 1169e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen return; 1179e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen } 118c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 1192d1ea3a164de3d5908b2f3c127b8979e906d37b9Ari Hausman-Cohen device_fd_.reset(-1); // Includes close(). 120c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen format_.reset(); 12128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan { 12228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan std::lock_guard<std::mutex> buffer_lock(buffer_queue_lock_); 12328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan buffers_.clear(); 12428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan } 125c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen} 126c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 127c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen// Helper function. Should be used instead of ioctl throughout this class. 128c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohentemplate <typename T> 129c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohenint V4L2Wrapper::IoctlLocked(int request, T data) { 1309e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen // Potentially called so many times logging entry is a bad idea. 131c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen std::lock_guard<std::mutex> lock(device_lock_); 132c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 133c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen if (!connected()) { 134c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen HAL_LOGE("Device %s not connected.", device_path_.c_str()); 135c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen return -ENODEV; 136c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen } 137c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen return TEMP_FAILURE_RETRY(ioctl(device_fd_.get(), request, data)); 138c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen} 139c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 140c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohenint V4L2Wrapper::StreamOn() { 141c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen if (!format_) { 142c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen HAL_LOGE("Stream format must be set before turning on stream."); 143c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen return -EINVAL; 144c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen } 145c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 1464ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen int32_t type = format_->type(); 147c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen if (IoctlLocked(VIDIOC_STREAMON, &type) < 0) { 14828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan HAL_LOGE("STREAMON fails (%d): %s", errno, strerror(errno)); 149c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen return -ENODEV; 150c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen } 151c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 152ad6fe2b033997ab0401b0a519b18cea6e957dac0Ari Hausman-Cohen HAL_LOGV("Stream turned on."); 153c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen return 0; 154c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen} 155c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 156c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohenint V4L2Wrapper::StreamOff() { 157660f8b858d6523064f150fd54a163b9673d685e1Ari Hausman-Cohen if (!format_) { 158ad6fe2b033997ab0401b0a519b18cea6e957dac0Ari Hausman-Cohen // Can't have turned on the stream without format being set, 15971cb874e349b296312e6cfb15d419977340b7e94Ari Hausman-Cohen // so nothing to turn off here. 16071cb874e349b296312e6cfb15d419977340b7e94Ari Hausman-Cohen return 0; 161660f8b858d6523064f150fd54a163b9673d685e1Ari Hausman-Cohen } 162660f8b858d6523064f150fd54a163b9673d685e1Ari Hausman-Cohen 1634ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen int32_t type = format_->type(); 1644ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen int res = IoctlLocked(VIDIOC_STREAMOFF, &type); 1654ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen // Calling STREAMOFF releases all queued buffers back to the user. 166c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen // No buffers in flight. 1674ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen if (res < 0) { 168c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen HAL_LOGE("STREAMOFF fails: %s", strerror(errno)); 169c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen return -ENODEV; 170c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen } 17128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan std::lock_guard<std::mutex> lock(buffer_queue_lock_); 17228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan for (auto& buffer : buffers_) { 17328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan buffer.active = false; 17428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan buffer.request.reset(); 1754ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen } 176ad6fe2b033997ab0401b0a519b18cea6e957dac0Ari Hausman-Cohen HAL_LOGV("Stream turned off."); 177c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen return 0; 178c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen} 179c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 180c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohenint V4L2Wrapper::QueryControl(uint32_t control_id, 181c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen v4l2_query_ext_ctrl* result) { 182c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen int res; 183c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 184c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen memset(result, 0, sizeof(*result)); 185c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 186c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen if (extended_query_supported_) { 187c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen result->id = control_id; 188c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen res = IoctlLocked(VIDIOC_QUERY_EXT_CTRL, result); 189c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen // Assuming the operation was supported (not ENOTTY), no more to do. 190c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen if (errno != ENOTTY) { 191c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen if (res) { 192c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen HAL_LOGE("QUERY_EXT_CTRL fails: %s", strerror(errno)); 193c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen return -ENODEV; 194c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen } 195c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen return 0; 196c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen } 197c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen } 198c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 199c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen // Extended control querying not supported, fall back to basic control query. 200c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen v4l2_queryctrl query; 201c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen query.id = control_id; 202c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen if (IoctlLocked(VIDIOC_QUERYCTRL, &query)) { 203c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen HAL_LOGE("QUERYCTRL fails: %s", strerror(errno)); 204c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen return -ENODEV; 205c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen } 206c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 207c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen // Convert the basic result to the extended result. 208c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen result->id = query.id; 209c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen result->type = query.type; 210c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen memcpy(result->name, query.name, sizeof(query.name)); 211c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen result->minimum = query.minimum; 212c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen if (query.type == V4L2_CTRL_TYPE_BITMASK) { 213c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen // According to the V4L2 documentation, when type is BITMASK, 214c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen // max and default should be interpreted as __u32. Practically, 215c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen // this means the conversion from 32 bit to 64 will pad with 0s not 1s. 216c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen result->maximum = static_cast<uint32_t>(query.maximum); 217c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen result->default_value = static_cast<uint32_t>(query.default_value); 218c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen } else { 219c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen result->maximum = query.maximum; 220c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen result->default_value = query.default_value; 221c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen } 222c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen result->step = static_cast<uint32_t>(query.step); 223c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen result->flags = query.flags; 224c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen result->elems = 1; 225c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen switch (result->type) { 226c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen case V4L2_CTRL_TYPE_INTEGER64: 227c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen result->elem_size = sizeof(int64_t); 228c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen break; 229c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen case V4L2_CTRL_TYPE_STRING: 230c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen result->elem_size = result->maximum + 1; 231c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen break; 232c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen default: 233c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen result->elem_size = sizeof(int32_t); 234c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen break; 235c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen } 236c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 237c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen return 0; 238c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen} 239c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 240c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohenint V4L2Wrapper::GetControl(uint32_t control_id, int32_t* value) { 2417a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen // For extended controls (any control class other than "user"), 2427a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen // G_EXT_CTRL must be used instead of G_CTRL. 2437a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen if (V4L2_CTRL_ID2CLASS(control_id) != V4L2_CTRL_CLASS_USER) { 2447a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen v4l2_ext_control control; 2457a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen v4l2_ext_controls controls; 2467a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen memset(&control, 0, sizeof(control)); 2477a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen memset(&controls, 0, sizeof(controls)); 2487a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen 2497a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen control.id = control_id; 2507a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen controls.ctrl_class = V4L2_CTRL_ID2CLASS(control_id); 2517a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen controls.count = 1; 2527a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen controls.controls = &control; 2537a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen 2547a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen if (IoctlLocked(VIDIOC_G_EXT_CTRLS, &controls) < 0) { 2557a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen HAL_LOGE("G_EXT_CTRLS fails: %s", strerror(errno)); 2567a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen return -ENODEV; 2577a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen } 2587a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen *value = control.value; 2597a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen } else { 2607a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen v4l2_control control{control_id, 0}; 2617a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen if (IoctlLocked(VIDIOC_G_CTRL, &control) < 0) { 2627a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen HAL_LOGE("G_CTRL fails: %s", strerror(errno)); 2637a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen return -ENODEV; 2647a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen } 2657a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen *value = control.value; 266c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen } 267c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen return 0; 268c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen} 269c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 2705d7532337a245450434203c5a6cf67005a001208Ari Hausman-Cohenint V4L2Wrapper::SetControl(uint32_t control_id, 2715d7532337a245450434203c5a6cf67005a001208Ari Hausman-Cohen int32_t desired, 272c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen int32_t* result) { 2737a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen int32_t result_value = 0; 274c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 27599f3ea02d08d5263214ad3667d7929daa7c6ce27Ari Hausman-Cohen // TODO(b/29334616): When async, this may need to check if the stream 27699f3ea02d08d5263214ad3667d7929daa7c6ce27Ari Hausman-Cohen // is on, and if so, lock it off while setting format. Need to look 27799f3ea02d08d5263214ad3667d7929daa7c6ce27Ari Hausman-Cohen // into if V4L2 supports adjusting controls while the stream is on. 27899f3ea02d08d5263214ad3667d7929daa7c6ce27Ari Hausman-Cohen 2797a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen // For extended controls (any control class other than "user"), 2807a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen // S_EXT_CTRL must be used instead of S_CTRL. 2817a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen if (V4L2_CTRL_ID2CLASS(control_id) != V4L2_CTRL_CLASS_USER) { 2827a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen v4l2_ext_control control; 2837a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen v4l2_ext_controls controls; 2847a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen memset(&control, 0, sizeof(control)); 2857a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen memset(&controls, 0, sizeof(controls)); 2867a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen 2877a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen control.id = control_id; 2887a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen control.value = desired; 2897a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen controls.ctrl_class = V4L2_CTRL_ID2CLASS(control_id); 2907a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen controls.count = 1; 2917a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen controls.controls = &control; 2927a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen 2937a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen if (IoctlLocked(VIDIOC_S_EXT_CTRLS, &controls) < 0) { 2947a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen HAL_LOGE("S_EXT_CTRLS fails: %s", strerror(errno)); 2957a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen return -ENODEV; 2967a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen } 2977a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen result_value = control.value; 2987a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen } else { 2997a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen v4l2_control control{control_id, desired}; 3007a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen if (IoctlLocked(VIDIOC_S_CTRL, &control) < 0) { 3017a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen HAL_LOGE("S_CTRL fails: %s", strerror(errno)); 3027a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen return -ENODEV; 3037a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen } 3047a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen result_value = control.value; 305c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen } 3067a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen 30799f3ea02d08d5263214ad3667d7929daa7c6ce27Ari Hausman-Cohen // If the caller wants to know the result, pass it back. 30899f3ea02d08d5263214ad3667d7929daa7c6ce27Ari Hausman-Cohen if (result != nullptr) { 3097a1fba6127333481259d88fd3764e1660e60398bAri Hausman-Cohen *result = result_value; 31099f3ea02d08d5263214ad3667d7929daa7c6ce27Ari Hausman-Cohen } 311c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen return 0; 312c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen} 313c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 31428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathanconst SupportedFormats V4L2Wrapper::GetSupportedFormats() { 31528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan SupportedFormats formats; 31628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan std::set<uint32_t> pixel_formats; 31728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan int res = GetFormats(&pixel_formats); 31828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan if (res) { 31928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan HAL_LOGE("Failed to get device formats."); 32028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan return formats; 32128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan } 32228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 32328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan arc::SupportedFormat supported_format; 32428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan std::set<std::array<int32_t, 2>> frame_sizes; 32528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 32628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan for (auto pixel_format : pixel_formats) { 32728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan supported_format.fourcc = pixel_format; 32828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 32928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan frame_sizes.clear(); 33028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan res = GetFormatFrameSizes(pixel_format, &frame_sizes); 33128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan if (res) { 33228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan HAL_LOGE("Failed to get frame sizes for format: 0x%x", pixel_format); 33328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan continue; 33428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan } 33528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan for (auto frame_size : frame_sizes) { 33628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan supported_format.width = frame_size[0]; 33728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan supported_format.height = frame_size[1]; 33828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan formats.push_back(supported_format); 33928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan } 34028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan } 34128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan return formats; 34228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan} 34328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 3449e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohenint V4L2Wrapper::GetFormats(std::set<uint32_t>* v4l2_formats) { 3459e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen HAL_LOG_ENTER(); 3469e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen 3479e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen v4l2_fmtdesc format_query; 3489e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen memset(&format_query, 0, sizeof(format_query)); 3499e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen // TODO(b/30000211): multiplanar support. 3509e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen format_query.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 3519e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen while (IoctlLocked(VIDIOC_ENUM_FMT, &format_query) >= 0) { 3529e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen v4l2_formats->insert(format_query.pixelformat); 3539e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen ++format_query.index; 3549e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen } 3559e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen 3569e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen if (errno != EINVAL) { 3575d7532337a245450434203c5a6cf67005a001208Ari Hausman-Cohen HAL_LOGE( 3585d7532337a245450434203c5a6cf67005a001208Ari Hausman-Cohen "ENUM_FMT fails at index %d: %s", format_query.index, strerror(errno)); 3599e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen return -ENODEV; 3609e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen } 3619e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen return 0; 3629e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen} 3639e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen 36428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathanint V4L2Wrapper::GetQualifiedFormats(std::vector<uint32_t>* v4l2_formats) { 36528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan HAL_LOG_ENTER(); 36628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan if (!connected()) { 36728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan HAL_LOGE( 36828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan "Device is not connected, qualified formats may not have been set."); 36928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan return -EINVAL; 37028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan } 37128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan v4l2_formats->clear(); 37228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan std::set<uint32_t> unique_fourccs; 37328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan for (auto& format : qualified_formats_) { 37428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan unique_fourccs.insert(format.fourcc); 37528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan } 37628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan v4l2_formats->assign(unique_fourccs.begin(), unique_fourccs.end()); 37728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan return 0; 37828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan} 37928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 3809e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohenint V4L2Wrapper::GetFormatFrameSizes(uint32_t v4l2_format, 3819e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen std::set<std::array<int32_t, 2>>* sizes) { 3829e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen v4l2_frmsizeenum size_query; 3839e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen memset(&size_query, 0, sizeof(size_query)); 3849e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen size_query.pixel_format = v4l2_format; 3859e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen if (IoctlLocked(VIDIOC_ENUM_FRAMESIZES, &size_query) < 0) { 3869e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen HAL_LOGE("ENUM_FRAMESIZES failed: %s", strerror(errno)); 3879e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen return -ENODEV; 3889e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen } 3899e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen if (size_query.type == V4L2_FRMSIZE_TYPE_DISCRETE) { 3909e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen // Discrete: enumerate all sizes using VIDIOC_ENUM_FRAMESIZES. 3919e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen // Assuming that a driver with discrete frame sizes has a reasonable number 3929e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen // of them. 3939e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen do { 3949e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen sizes->insert({{{static_cast<int32_t>(size_query.discrete.width), 3959e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen static_cast<int32_t>(size_query.discrete.height)}}}); 3969e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen ++size_query.index; 3979e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen } while (IoctlLocked(VIDIOC_ENUM_FRAMESIZES, &size_query) >= 0); 3989e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen if (errno != EINVAL) { 3995d7532337a245450434203c5a6cf67005a001208Ari Hausman-Cohen HAL_LOGE("ENUM_FRAMESIZES fails at index %d: %s", 4005d7532337a245450434203c5a6cf67005a001208Ari Hausman-Cohen size_query.index, 4019e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen strerror(errno)); 4029e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen return -ENODEV; 4039e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen } 4049e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen } else { 4059e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen // Continuous/Step-wise: based on the stepwise struct returned by the query. 4069e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen // Fully listing all possible sizes, with large enough range/small enough 4079e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen // step size, may produce far too many potential sizes. Instead, find the 408c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen // closest to a set of standard sizes. 409abbf9cc0bd4160642c36f7bd47c0277a8bf17adfAri Hausman-Cohen for (const auto size : kStandardSizes) { 4109e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen // Find the closest size, rounding up. 4119e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen uint32_t desired_width = size[0]; 4129e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen uint32_t desired_height = size[1]; 4139e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen if (desired_width < size_query.stepwise.min_width || 4149e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen desired_height < size_query.stepwise.min_height) { 4159e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen HAL_LOGV("Standard size %u x %u is too small for format %d", 4165d7532337a245450434203c5a6cf67005a001208Ari Hausman-Cohen desired_width, 4175d7532337a245450434203c5a6cf67005a001208Ari Hausman-Cohen desired_height, 4185d7532337a245450434203c5a6cf67005a001208Ari Hausman-Cohen v4l2_format); 4199e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen continue; 420932d4dddd97ca2c690363a2245cfab46dab6496fJaesung Chung } else if (desired_width > size_query.stepwise.max_width || 4219e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen desired_height > size_query.stepwise.max_height) { 4229e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen HAL_LOGV("Standard size %u x %u is too big for format %d", 4235d7532337a245450434203c5a6cf67005a001208Ari Hausman-Cohen desired_width, 4245d7532337a245450434203c5a6cf67005a001208Ari Hausman-Cohen desired_height, 4255d7532337a245450434203c5a6cf67005a001208Ari Hausman-Cohen v4l2_format); 4269e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen continue; 4279e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen } 4289e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen 4299e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen // Round up. 4309e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen uint32_t width_steps = (desired_width - size_query.stepwise.min_width + 4319e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen size_query.stepwise.step_width - 1) / 4329e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen size_query.stepwise.step_width; 4339e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen uint32_t height_steps = (desired_height - size_query.stepwise.min_height + 4349e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen size_query.stepwise.step_height - 1) / 4359e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen size_query.stepwise.step_height; 4369e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen sizes->insert( 4379e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen {{{static_cast<int32_t>(size_query.stepwise.min_width + 4389e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen width_steps * size_query.stepwise.step_width), 4399e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen static_cast<int32_t>(size_query.stepwise.min_height + 4409e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen height_steps * 4419e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen size_query.stepwise.step_height)}}}); 4429e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen } 4439e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen } 4449e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen return 0; 4459e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen} 4469e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen 4479e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen// Converts a v4l2_fract with units of seconds to an int64_t with units of ns. 4489e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Coheninline int64_t FractToNs(const v4l2_fract& fract) { 4499e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen return (1000000000LL * fract.numerator) / fract.denominator; 4509e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen} 4519e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen 4529e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohenint V4L2Wrapper::GetFormatFrameDurationRange( 4535d7532337a245450434203c5a6cf67005a001208Ari Hausman-Cohen uint32_t v4l2_format, 4545d7532337a245450434203c5a6cf67005a001208Ari Hausman-Cohen const std::array<int32_t, 2>& size, 4559e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen std::array<int64_t, 2>* duration_range) { 4569e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen // Potentially called so many times logging entry is a bad idea. 4579e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen 4589e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen v4l2_frmivalenum duration_query; 4599e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen memset(&duration_query, 0, sizeof(duration_query)); 4609e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen duration_query.pixel_format = v4l2_format; 4619e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen duration_query.width = size[0]; 4629e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen duration_query.height = size[1]; 4639e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen if (IoctlLocked(VIDIOC_ENUM_FRAMEINTERVALS, &duration_query) < 0) { 4649e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen HAL_LOGE("ENUM_FRAMEINTERVALS failed: %s", strerror(errno)); 4659e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen return -ENODEV; 4669e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen } 4679e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen 4689e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen int64_t min = std::numeric_limits<int64_t>::max(); 4699e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen int64_t max = std::numeric_limits<int64_t>::min(); 4709e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen if (duration_query.type == V4L2_FRMSIZE_TYPE_DISCRETE) { 4719e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen // Discrete: enumerate all durations using VIDIOC_ENUM_FRAMEINTERVALS. 4729e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen do { 4739e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen min = std::min(min, FractToNs(duration_query.discrete)); 4749e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen max = std::max(max, FractToNs(duration_query.discrete)); 4759e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen ++duration_query.index; 4769e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen } while (IoctlLocked(VIDIOC_ENUM_FRAMEINTERVALS, &duration_query) >= 0); 4779e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen if (errno != EINVAL) { 4789e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen HAL_LOGE("ENUM_FRAMEINTERVALS fails at index %d: %s", 4795d7532337a245450434203c5a6cf67005a001208Ari Hausman-Cohen duration_query.index, 4805d7532337a245450434203c5a6cf67005a001208Ari Hausman-Cohen strerror(errno)); 4819e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen return -ENODEV; 4829e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen } 4839e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen } else { 4849e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen // Continuous/Step-wise: simply convert the given min and max. 4859e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen min = FractToNs(duration_query.stepwise.min); 4869e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen max = FractToNs(duration_query.stepwise.max); 4879e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen } 4889e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen (*duration_range)[0] = min; 4899e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen (*duration_range)[1] = max; 4909e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen return 0; 4919e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen} 4929e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen 493ef52310613342dd51a928af92e3287f6783ae8c7Ari Hausman-Cohenint V4L2Wrapper::SetFormat(const StreamFormat& desired_format, 494660f8b858d6523064f150fd54a163b9673d685e1Ari Hausman-Cohen uint32_t* result_max_buffers) { 495c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen HAL_LOG_ENTER(); 496c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 497660f8b858d6523064f150fd54a163b9673d685e1Ari Hausman-Cohen if (format_ && desired_format == *format_) { 498c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen HAL_LOGV("Already in correct format, skipping format setting."); 499a5c9bfde31bd8b7ae541783094e6ed90f842cf32Ari Hausman-Cohen *result_max_buffers = buffers_.size(); 500c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen return 0; 501c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen } 502c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 503c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen if (format_) { 504c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen // If we had an old format, first request 0 buffers to inform the device 505c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen // we're no longer using any previously "allocated" buffers from the old 506c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen // format. This seems like it shouldn't be necessary for USERPTR memory, 507c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen // and/or should happen from turning the stream off, but the driver 508c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen // complained. May be a driver issue, or may be intended behavior. 509c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen int res = RequestBuffers(0); 510c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen if (res) { 511c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen return res; 512c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen } 513c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen } 514c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen 51528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Select the matching format, or if not available, select a qualified format 51628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // we can convert from. 51728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan SupportedFormat format; 51828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan if (!StreamFormat::FindBestFitFormat(supported_formats_, qualified_formats_, 51928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan desired_format.v4l2_pixel_format(), 52028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan desired_format.width(), 52128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan desired_format.height(), &format)) { 52228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan HAL_LOGE( 52328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan "Unable to find supported resolution in list, " 52428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan "width: %d, height: %d", 52528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan desired_format.width(), desired_format.height()); 52628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan return -EINVAL; 52728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan } 52828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 529c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen // Set the camera to the new format. 530c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen v4l2_format new_format; 53128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan const StreamFormat resolved_format(format); 53228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan resolved_format.FillFormatRequest(&new_format); 53328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 534c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen // TODO(b/29334616): When async, this will need to check if the stream 535c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen // is on, and if so, lock it off while setting format. 536c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen if (IoctlLocked(VIDIOC_S_FMT, &new_format) < 0) { 537c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen HAL_LOGE("S_FMT failed: %s", strerror(errno)); 538c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen return -ENODEV; 539c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen } 540c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 541c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen // Check that the driver actually set to the requested values. 54228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan if (resolved_format != new_format) { 543c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen HAL_LOGE("Device doesn't support desired stream configuration."); 544c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen return -EINVAL; 545c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen } 546c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 547c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen // Keep track of our new format. 548c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen format_.reset(new StreamFormat(new_format)); 549c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 550c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen // Format changed, request new buffers. 551c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen int res = RequestBuffers(1); 552660f8b858d6523064f150fd54a163b9673d685e1Ari Hausman-Cohen if (res) { 553c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen HAL_LOGE("Requesting buffers for new format failed."); 554660f8b858d6523064f150fd54a163b9673d685e1Ari Hausman-Cohen return res; 555660f8b858d6523064f150fd54a163b9673d685e1Ari Hausman-Cohen } 5560fbcaf53ca9802fd58f1a51ac94be70a50cbcd04Ari Hausman-Cohen *result_max_buffers = buffers_.size(); 557c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen return 0; 558c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen} 559c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 560c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohenint V4L2Wrapper::RequestBuffers(uint32_t num_requested) { 561c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen v4l2_requestbuffers req_buffers; 562c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen memset(&req_buffers, 0, sizeof(req_buffers)); 5634ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen req_buffers.type = format_->type(); 564c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen req_buffers.memory = V4L2_MEMORY_USERPTR; 565c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen req_buffers.count = num_requested; 5664ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen 5674ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen int res = IoctlLocked(VIDIOC_REQBUFS, &req_buffers); 5684ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen // Calling REQBUFS releases all queued buffers back to the user. 5694ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen if (res < 0) { 570c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen HAL_LOGE("REQBUFS failed: %s", strerror(errno)); 571c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen return -ENODEV; 572c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen } 573c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 574c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen // V4L2 will set req_buffers.count to a number of buffers it can handle. 575c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen if (num_requested > 0 && req_buffers.count < 1) { 576660f8b858d6523064f150fd54a163b9673d685e1Ari Hausman-Cohen HAL_LOGE("REQBUFS claims it can't handle any buffers."); 577660f8b858d6523064f150fd54a163b9673d685e1Ari Hausman-Cohen return -ENODEV; 578660f8b858d6523064f150fd54a163b9673d685e1Ari Hausman-Cohen } 57928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan buffers_.resize(req_buffers.count); 580c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen return 0; 581c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen} 582c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen 58328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathanint V4L2Wrapper::EnqueueRequest( 58428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan std::shared_ptr<default_camera_hal::CaptureRequest> request) { 585660f8b858d6523064f150fd54a163b9673d685e1Ari Hausman-Cohen if (!format_) { 586660f8b858d6523064f150fd54a163b9673d685e1Ari Hausman-Cohen HAL_LOGE("Stream format must be set before enqueuing buffers."); 587660f8b858d6523064f150fd54a163b9673d685e1Ari Hausman-Cohen return -ENODEV; 588660f8b858d6523064f150fd54a163b9673d685e1Ari Hausman-Cohen } 589660f8b858d6523064f150fd54a163b9673d685e1Ari Hausman-Cohen 5900fbcaf53ca9802fd58f1a51ac94be70a50cbcd04Ari Hausman-Cohen // Find a free buffer index. Could use some sort of persistent hinting 5910fbcaf53ca9802fd58f1a51ac94be70a50cbcd04Ari Hausman-Cohen // here to improve expected efficiency, but buffers_.size() is expected 5920fbcaf53ca9802fd58f1a51ac94be70a50cbcd04Ari Hausman-Cohen // to be low enough (<10 experimentally) that it's not worth it. 5930fbcaf53ca9802fd58f1a51ac94be70a50cbcd04Ari Hausman-Cohen int index = -1; 5940fbcaf53ca9802fd58f1a51ac94be70a50cbcd04Ari Hausman-Cohen { 5950fbcaf53ca9802fd58f1a51ac94be70a50cbcd04Ari Hausman-Cohen std::lock_guard<std::mutex> guard(buffer_queue_lock_); 59628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan for (size_t i = 0; i < buffers_.size(); ++i) { 59728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan if (!buffers_[i].active) { 5980fbcaf53ca9802fd58f1a51ac94be70a50cbcd04Ari Hausman-Cohen index = i; 5990fbcaf53ca9802fd58f1a51ac94be70a50cbcd04Ari Hausman-Cohen break; 6000fbcaf53ca9802fd58f1a51ac94be70a50cbcd04Ari Hausman-Cohen } 6010fbcaf53ca9802fd58f1a51ac94be70a50cbcd04Ari Hausman-Cohen } 6020fbcaf53ca9802fd58f1a51ac94be70a50cbcd04Ari Hausman-Cohen } 6030fbcaf53ca9802fd58f1a51ac94be70a50cbcd04Ari Hausman-Cohen if (index < 0) { 6040fbcaf53ca9802fd58f1a51ac94be70a50cbcd04Ari Hausman-Cohen // Note: The HAL should be tracking the number of buffers in flight 6050fbcaf53ca9802fd58f1a51ac94be70a50cbcd04Ari Hausman-Cohen // for each stream, and should never overflow the device. 6060fbcaf53ca9802fd58f1a51ac94be70a50cbcd04Ari Hausman-Cohen HAL_LOGE("Cannot enqueue buffer: stream is already full."); 6070fbcaf53ca9802fd58f1a51ac94be70a50cbcd04Ari Hausman-Cohen return -ENODEV; 6080fbcaf53ca9802fd58f1a51ac94be70a50cbcd04Ari Hausman-Cohen } 6090fbcaf53ca9802fd58f1a51ac94be70a50cbcd04Ari Hausman-Cohen 6104ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen // Set up a v4l2 buffer struct. 6114ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen v4l2_buffer device_buffer; 6124ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen memset(&device_buffer, 0, sizeof(device_buffer)); 6134ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen device_buffer.type = format_->type(); 6140fbcaf53ca9802fd58f1a51ac94be70a50cbcd04Ari Hausman-Cohen device_buffer.index = index; 6154ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen 6169e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen // Use QUERYBUF to ensure our buffer/device is in good shape, 6179e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen // and fill out remaining fields. 6184ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen if (IoctlLocked(VIDIOC_QUERYBUF, &device_buffer) < 0) { 6194ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen HAL_LOGE("QUERYBUF fails: %s", strerror(errno)); 6201fc9b614b86534e5173b7861a2f1284d5eedd9deJaesung Chung // Return buffer index. 6211fc9b614b86534e5173b7861a2f1284d5eedd9deJaesung Chung std::lock_guard<std::mutex> guard(buffer_queue_lock_); 62228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan buffers_[index].active = false; 6234ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen return -ENODEV; 6244ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen } 6254ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen 62628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Setup our request context and fill in the user pointer field. 62728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan RequestContext* request_context; 62828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan void* data; 62928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan { 6301fc9b614b86534e5173b7861a2f1284d5eedd9deJaesung Chung std::lock_guard<std::mutex> guard(buffer_queue_lock_); 63128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan request_context = &buffers_[index]; 63228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan request_context->camera_buffer->SetDataSize(device_buffer.length); 63328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan request_context->camera_buffer->Reset(); 63428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan request_context->camera_buffer->SetFourcc(format_->v4l2_pixel_format()); 63528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan request_context->camera_buffer->SetWidth(format_->width()); 63628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan request_context->camera_buffer->SetHeight(format_->height()); 63728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan request_context->request = request; 63828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan data = request_context->camera_buffer->GetData(); 63928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan } 64028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan device_buffer.m.userptr = reinterpret_cast<unsigned long>(data); 64128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 64228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Pass the buffer to the camera. 6434ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen if (IoctlLocked(VIDIOC_QBUF, &device_buffer) < 0) { 6449e6fd989450917be4d506114f1c1d6f1644b0f34Ari Hausman-Cohen HAL_LOGE("QBUF fails: %s", strerror(errno)); 6454ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen return -ENODEV; 6464ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen } 6474ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen 64828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Mark the buffer as in flight. 64928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan std::lock_guard<std::mutex> guard(buffer_queue_lock_); 65028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan request_context->active = true; 65128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 6524ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen return 0; 6534ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen} 6544ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen 65528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathanint V4L2Wrapper::DequeueRequest(std::shared_ptr<CaptureRequest>* request) { 656660f8b858d6523064f150fd54a163b9673d685e1Ari Hausman-Cohen if (!format_) { 657c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen HAL_LOGV( 658c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen "Format not set, so stream can't be on, " 659c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen "so no buffers available for dequeueing"); 660c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen return -EAGAIN; 661660f8b858d6523064f150fd54a163b9673d685e1Ari Hausman-Cohen } 662660f8b858d6523064f150fd54a163b9673d685e1Ari Hausman-Cohen 663c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen v4l2_buffer buffer; 664c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen memset(&buffer, 0, sizeof(buffer)); 665c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen buffer.type = format_->type(); 666c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen buffer.memory = V4L2_MEMORY_USERPTR; 667c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen int res = IoctlLocked(VIDIOC_DQBUF, &buffer); 668c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen if (res) { 669c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen if (errno == EAGAIN) { 670c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen // Expected failure. 671c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen return -EAGAIN; 672c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen } else { 673c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen // Unexpected failure. 674c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen HAL_LOGE("DQBUF fails: %s", strerror(errno)); 675c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen return -ENODEV; 676c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen } 6774ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen } 6784ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen 67928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan std::lock_guard<std::mutex> guard(buffer_queue_lock_); 68028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan RequestContext* request_context = &buffers_[buffer.index]; 68128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 68228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Lock the camera stream buffer for painting. 68328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan const camera3_stream_buffer_t* stream_buffer = 68428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan &request_context->request->output_buffers[0]; 68528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan uint32_t fourcc = 68628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan StreamFormat::HalToV4L2PixelFormat(stream_buffer->stream->format); 68728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 68828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan if (request) { 68928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan *request = request_context->request; 6900fbcaf53ca9802fd58f1a51ac94be70a50cbcd04Ari Hausman-Cohen } 6910fbcaf53ca9802fd58f1a51ac94be70a50cbcd04Ari Hausman-Cohen 69228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Note that the device buffer length is passed to the output frame. If the 69328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // GrallocFrameBuffer does not have support for the transformation to 69428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // |fourcc|, it will assume that the amount of data to lock is based on 69528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // |buffer.length|, otherwise it will use the ImageProcessor::ConvertedSize. 69628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan arc::GrallocFrameBuffer output_frame( 69728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan *stream_buffer->buffer, stream_buffer->stream->width, 69828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan stream_buffer->stream->height, fourcc, buffer.length, 69928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan stream_buffer->stream->usage); 70028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan res = output_frame.Map(); 7014ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen if (res) { 70228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan HAL_LOGE("Failed to map output frame."); 70328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan request_context->request.reset(); 70428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan return -EINVAL; 7054ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen } 70628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan if (request_context->camera_buffer->GetFourcc() == fourcc && 70728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan request_context->camera_buffer->GetWidth() == 70828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan stream_buffer->stream->width && 70928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan request_context->camera_buffer->GetHeight() == 71028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan stream_buffer->stream->height) { 71128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // If no format conversion needs to be applied, directly copy the data over. 71228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan memcpy(output_frame.GetData(), request_context->camera_buffer->GetData(), 71328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan request_context->camera_buffer->GetDataSize()); 71428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan } else { 71528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Perform the format conversion. 71628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan arc::CachedFrame cached_frame; 71728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan cached_frame.SetSource(request_context->camera_buffer.get(), 0); 71828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan cached_frame.Convert(request_context->request->settings, &output_frame); 719c5a485245169c1da02c4a5bfb80876cff68882ebAri Hausman-Cohen } 72028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 72128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan request_context->request.reset(); 72228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Mark the buffer as not in flight. 72328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan request_context->active = false; 7244ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen return 0; 7254ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen} 7264ab49624207319ac99a75d7272d968c172064422Ari Hausman-Cohen 72728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathanint V4L2Wrapper::GetInFlightBufferCount() { 72828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan int count = 0; 72928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan std::lock_guard<std::mutex> guard(buffer_queue_lock_); 73028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan for (auto& buffer : buffers_) { 73128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan if (buffer.active) { 73228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan count++; 73328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan } 73428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan } 73528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan return count; 73628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan} 73728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 738c17fd09be838b093d3de3033c3a65a75b1813e19Ari Hausman-Cohen} // namespace v4l2_camera_hal 739