Home | History | Annotate | Download | only in 3_4
      1 /*
      2  * Copyright 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "v4l2_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 
     37 namespace v4l2_camera_hal {
     38 
     39 // Helper function for managing metadata.
     40 static 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 
     51 V4L2Camera* 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 
     70 V4L2Camera::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 
     85 V4L2Camera::~V4L2Camera() {
     86   HAL_LOG_ENTER();
     87 }
     88 
     89 int 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 
    115 void 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 
    124 int 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 
    138 int 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 
    164 int V4L2Camera::initTemplate(int type, android::CameraMetadata* out) {
    165   HAL_LOG_ENTER();
    166 
    167   return metadata_->GetRequestTemplate(type, out);
    168 }
    169 
    170 void 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 
    180 int 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 
    202 int 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 
    217 std::shared_ptr<default_camera_hal::CaptureRequest>
    218 V4L2Camera::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 
    230 bool 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 
    295 bool 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 
    328 bool 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 
    344 int 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 
    442 bool 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