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_camera.h" 18 19#include <fcntl.h> 20#include <linux/videodev2.h> 21#include <sys/stat.h> 22#include <sys/types.h> 23 24#include <cstdlib> 25 26#include <camera/CameraMetadata.h> 27#include <hardware/camera3.h> 28 29#include "common.h" 30#include "function_thread.h" 31#include "metadata/metadata_common.h" 32#include "stream_format.h" 33#include "v4l2_metadata_factory.h" 34 35#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) 36 37namespace v4l2_camera_hal { 38 39// Helper function for managing metadata. 40static std::vector<int32_t> getMetadataKeys(const camera_metadata_t* metadata) { 41 std::vector<int32_t> keys; 42 size_t num_entries = get_camera_metadata_entry_count(metadata); 43 for (size_t i = 0; i < num_entries; ++i) { 44 camera_metadata_ro_entry_t entry; 45 get_camera_metadata_ro_entry(metadata, i, &entry); 46 keys.push_back(entry.tag); 47 } 48 return keys; 49} 50 51V4L2Camera* V4L2Camera::NewV4L2Camera(int id, const std::string path) { 52 HAL_LOG_ENTER(); 53 54 std::shared_ptr<V4L2Wrapper> v4l2_wrapper(V4L2Wrapper::NewV4L2Wrapper(path)); 55 if (!v4l2_wrapper) { 56 HAL_LOGE("Failed to initialize V4L2 wrapper."); 57 return nullptr; 58 } 59 60 std::unique_ptr<Metadata> metadata; 61 int res = GetV4L2Metadata(v4l2_wrapper, &metadata); 62 if (res) { 63 HAL_LOGE("Failed to initialize V4L2 metadata: %d", res); 64 return nullptr; 65 } 66 67 return new V4L2Camera(id, std::move(v4l2_wrapper), std::move(metadata)); 68} 69 70V4L2Camera::V4L2Camera(int id, 71 std::shared_ptr<V4L2Wrapper> v4l2_wrapper, 72 std::unique_ptr<Metadata> metadata) 73 : default_camera_hal::Camera(id), 74 device_(std::move(v4l2_wrapper)), 75 metadata_(std::move(metadata)), 76 max_input_streams_(0), 77 max_output_streams_({{0, 0, 0}}), 78 buffer_enqueuer_(new FunctionThread( 79 std::bind(&V4L2Camera::enqueueRequestBuffers, this))), 80 buffer_dequeuer_(new FunctionThread( 81 std::bind(&V4L2Camera::dequeueRequestBuffers, this))) { 82 HAL_LOG_ENTER(); 83} 84 85V4L2Camera::~V4L2Camera() { 86 HAL_LOG_ENTER(); 87} 88 89int V4L2Camera::connect() { 90 HAL_LOG_ENTER(); 91 92 if (connection_) { 93 HAL_LOGE("Already connected. Please disconnect and try again."); 94 return -EIO; 95 } 96 97 connection_.reset(new V4L2Wrapper::Connection(device_)); 98 if (connection_->status()) { 99 HAL_LOGE("Failed to connect to device."); 100 return connection_->status(); 101 } 102 103 // TODO(b/29185945): confirm this is a supported device. 104 // This is checked by the HAL, but the device at |device_|'s path may 105 // not be the same one that was there when the HAL was loaded. 106 // (Alternatively, better hotplugging support may make this unecessary 107 // by disabling cameras that get disconnected and checking newly connected 108 // cameras, so connect() is never called on an unsupported camera) 109 110 // TODO(b/29158098): Inform service of any flashes that are no longer 111 // available because this camera is in use. 112 return 0; 113} 114 115void V4L2Camera::disconnect() { 116 HAL_LOG_ENTER(); 117 118 connection_.reset(); 119 120 // TODO(b/29158098): Inform service of any flashes that are available again 121 // because this camera is no longer in use. 122} 123 124int V4L2Camera::flushBuffers() { 125 HAL_LOG_ENTER(); 126 127 int res = device_->StreamOff(); 128 129 // This is not strictly necessary, but prevents a buildup of aborted 130 // requests in the in_flight_ map. These should be cleared 131 // whenever the stream is turned off. 132 std::lock_guard<std::mutex> guard(in_flight_lock_); 133 in_flight_.clear(); 134 135 return res; 136} 137 138int V4L2Camera::initStaticInfo(android::CameraMetadata* out) { 139 HAL_LOG_ENTER(); 140 141 int res = metadata_->FillStaticMetadata(out); 142 if (res) { 143 HAL_LOGE("Failed to get static metadata."); 144 return res; 145 } 146 147 // Extract max streams for use in verifying stream configs. 148 res = SingleTagValue( 149 *out, ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS, &max_input_streams_); 150 if (res) { 151 HAL_LOGE("Failed to get max num input streams from static metadata."); 152 return res; 153 } 154 res = SingleTagValue( 155 *out, ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS, &max_output_streams_); 156 if (res) { 157 HAL_LOGE("Failed to get max num output streams from static metadata."); 158 return res; 159 } 160 161 return 0; 162} 163 164int V4L2Camera::initTemplate(int type, android::CameraMetadata* out) { 165 HAL_LOG_ENTER(); 166 167 return metadata_->GetRequestTemplate(type, out); 168} 169 170void V4L2Camera::initDeviceInfo(camera_info_t* info) { 171 HAL_LOG_ENTER(); 172 173 // TODO(b/31044975): move this into device interface. 174 // For now, just constants. 175 info->resource_cost = 100; 176 info->conflicting_devices = nullptr; 177 info->conflicting_devices_length = 0; 178} 179 180int V4L2Camera::initDevice() { 181 HAL_LOG_ENTER(); 182 183 // Start the buffer enqueue/dequeue threads if they're not already running. 184 if (!buffer_enqueuer_->isRunning()) { 185 android::status_t res = buffer_enqueuer_->run("Enqueue buffers"); 186 if (res != android::OK) { 187 HAL_LOGE("Failed to start buffer enqueue thread: %d", res); 188 return -ENODEV; 189 } 190 } 191 if (!buffer_dequeuer_->isRunning()) { 192 android::status_t res = buffer_dequeuer_->run("Dequeue buffers"); 193 if (res != android::OK) { 194 HAL_LOGE("Failed to start buffer dequeue thread: %d", res); 195 return -ENODEV; 196 } 197 } 198 199 return 0; 200} 201 202int V4L2Camera::enqueueRequest( 203 std::shared_ptr<default_camera_hal::CaptureRequest> request) { 204 HAL_LOG_ENTER(); 205 206 // Assume request validated before calling this function. 207 // (For now, always exactly 1 output buffer, no inputs). 208 { 209 std::lock_guard<std::mutex> guard(request_queue_lock_); 210 request_queue_.push(request); 211 requests_available_.notify_one(); 212 } 213 214 return 0; 215} 216 217std::shared_ptr<default_camera_hal::CaptureRequest> 218V4L2Camera::dequeueRequest() { 219 std::unique_lock<std::mutex> lock(request_queue_lock_); 220 while (request_queue_.empty()) { 221 requests_available_.wait(lock); 222 } 223 224 std::shared_ptr<default_camera_hal::CaptureRequest> request = 225 request_queue_.front(); 226 request_queue_.pop(); 227 return request; 228} 229 230bool V4L2Camera::enqueueRequestBuffers() { 231 // Get a request from the queue (blocks this thread until one is available). 232 std::shared_ptr<default_camera_hal::CaptureRequest> request = 233 dequeueRequest(); 234 235 // Assume request validated before being added to the queue 236 // (For now, always exactly 1 output buffer, no inputs). 237 238 // Setting and getting settings are best effort here, 239 // since there's no way to know through V4L2 exactly what 240 // settings are used for a buffer unless we were to enqueue them 241 // one at a time, which would be too slow. 242 243 // Set the requested settings 244 int res = metadata_->SetRequestSettings(request->settings); 245 if (res) { 246 HAL_LOGE("Failed to set settings."); 247 completeRequest(request, res); 248 return true; 249 } 250 251 // Replace the requested settings with a snapshot of 252 // the used settings/state immediately before enqueue. 253 res = metadata_->FillResultMetadata(&request->settings); 254 if (res) { 255 // Note: since request is a shared pointer, this may happen if another 256 // thread has already decided to complete the request (e.g. via flushing), 257 // since that locks the metadata (in that case, this failing is fine, 258 // and completeRequest will simply do nothing). 259 HAL_LOGE("Failed to fill result metadata."); 260 completeRequest(request, res); 261 return true; 262 } 263 264 // Actually enqueue the buffer for capture. 265 { 266 std::lock_guard<std::mutex> guard(in_flight_lock_); 267 268 uint32_t index; 269 res = device_->EnqueueBuffer(&request->output_buffers[0], &index); 270 if (res) { 271 HAL_LOGE("Device failed to enqueue buffer."); 272 completeRequest(request, res); 273 return true; 274 } 275 276 // Make sure the stream is on (no effect if already on). 277 res = device_->StreamOn(); 278 if (res) { 279 HAL_LOGE("Device failed to turn on stream."); 280 // Don't really want to send an error for only the request here, 281 // since this is a full device error. 282 // TODO: Should trigger full flush. 283 return true; 284 } 285 286 // Note: the request should be dequeued/flushed from the device 287 // before removal from in_flight_. 288 in_flight_.emplace(index, request); 289 buffers_in_flight_.notify_one(); 290 } 291 292 return true; 293} 294 295bool V4L2Camera::dequeueRequestBuffers() { 296 // Dequeue a buffer. 297 uint32_t result_index; 298 int res = device_->DequeueBuffer(&result_index); 299 if (res) { 300 if (res == -EAGAIN) { 301 // EAGAIN just means nothing to dequeue right now. 302 // Wait until something is available before looping again. 303 std::unique_lock<std::mutex> lock(in_flight_lock_); 304 while (in_flight_.empty()) { 305 buffers_in_flight_.wait(lock); 306 } 307 } else { 308 HAL_LOGW("Device failed to dequeue buffer: %d", res); 309 } 310 return true; 311 } 312 313 // Find the associated request and complete it. 314 std::lock_guard<std::mutex> guard(in_flight_lock_); 315 auto index_request = in_flight_.find(result_index); 316 if (index_request != in_flight_.end()) { 317 completeRequest(index_request->second, 0); 318 in_flight_.erase(index_request); 319 } else { 320 HAL_LOGW( 321 "Dequeued non in-flight buffer index %d. " 322 "This buffer may have been flushed from the HAL but not the device.", 323 index_request->first); 324 } 325 return true; 326} 327 328bool V4L2Camera::validateDataspacesAndRotations( 329 const camera3_stream_configuration_t* stream_config) { 330 HAL_LOG_ENTER(); 331 332 for (uint32_t i = 0; i < stream_config->num_streams; ++i) { 333 if (stream_config->streams[i]->rotation != CAMERA3_STREAM_ROTATION_0) { 334 HAL_LOGV("Rotation %d for stream %d not supported", 335 stream_config->streams[i]->rotation, 336 i); 337 return false; 338 } 339 // Accept all dataspaces, as it will just be overwritten below anyways. 340 } 341 return true; 342} 343 344int V4L2Camera::setupStreams(camera3_stream_configuration_t* stream_config) { 345 HAL_LOG_ENTER(); 346 347 std::lock_guard<std::mutex> guard(in_flight_lock_); 348 // The framework should be enforcing this, but doesn't hurt to be safe. 349 if (!in_flight_.empty()) { 350 HAL_LOGE("Can't set device format while frames are in flight."); 351 return -EINVAL; 352 } 353 354 // stream_config should have been validated; assume at least 1 stream. 355 camera3_stream_t* stream = stream_config->streams[0]; 356 int format = stream->format; 357 uint32_t width = stream->width; 358 uint32_t height = stream->height; 359 360 if (stream_config->num_streams > 1) { 361 // TODO(b/29939583): V4L2 doesn't actually support more than 1 362 // stream at a time. If not all streams are the same format 363 // and size, error. Note that this means the HAL is not spec-compliant. 364 // Technically, this error should be thrown during validation, but 365 // since it isn't a spec-valid error validation isn't set up to check it. 366 for (uint32_t i = 1; i < stream_config->num_streams; ++i) { 367 stream = stream_config->streams[i]; 368 if (stream->format != format || stream->width != width || 369 stream->height != height) { 370 HAL_LOGE( 371 "V4L2 only supports 1 stream configuration at a time " 372 "(stream 0 is format %d, width %u, height %u, " 373 "stream %d is format %d, width %u, height %u).", 374 format, 375 width, 376 height, 377 i, 378 stream->format, 379 stream->width, 380 stream->height); 381 return -EINVAL; 382 } 383 } 384 } 385 386 // Ensure the stream is off. 387 int res = device_->StreamOff(); 388 if (res) { 389 HAL_LOGE("Device failed to turn off stream for reconfiguration: %d.", res); 390 return -ENODEV; 391 } 392 393 StreamFormat stream_format(format, width, height); 394 uint32_t max_buffers = 0; 395 res = device_->SetFormat(stream_format, &max_buffers); 396 if (res) { 397 HAL_LOGE("Failed to set device to correct format for stream: %d.", res); 398 return -ENODEV; 399 } 400 401 // Sanity check. 402 if (max_buffers < 1) { 403 HAL_LOGE("Setting format resulted in an invalid maximum of %u buffers.", 404 max_buffers); 405 return -ENODEV; 406 } 407 408 // Set all the streams dataspaces, usages, and max buffers. 409 for (uint32_t i = 0; i < stream_config->num_streams; ++i) { 410 stream = stream_config->streams[i]; 411 412 // Max buffers as reported by the device. 413 stream->max_buffers = max_buffers; 414 415 // Usage: currently using sw graphics. 416 switch (stream->stream_type) { 417 case CAMERA3_STREAM_INPUT: 418 stream->usage = GRALLOC_USAGE_SW_READ_OFTEN; 419 break; 420 case CAMERA3_STREAM_OUTPUT: 421 stream->usage = GRALLOC_USAGE_SW_WRITE_OFTEN; 422 break; 423 case CAMERA3_STREAM_BIDIRECTIONAL: 424 stream->usage = 425 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN; 426 break; 427 default: 428 // nothing to do. 429 break; 430 } 431 432 // Doesn't matter what was requested, we always use dataspace V0_JFIF. 433 // Note: according to camera3.h, this isn't allowed, but the camera 434 // framework team claims it's underdocumented; the implementation lets the 435 // HAL overwrite it. If this is changed, change the validation above. 436 stream->data_space = HAL_DATASPACE_V0_JFIF; 437 } 438 439 return 0; 440} 441 442bool V4L2Camera::isValidRequestSettings( 443 const android::CameraMetadata& settings) { 444 if (!metadata_->IsValidRequest(settings)) { 445 HAL_LOGE("Invalid request settings."); 446 return false; 447 } 448 return true; 449} 450 451} // namespace v4l2_camera_hal 452