• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
getMetadataKeys(const camera_metadata_t * 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 
NewV4L2Camera(int id,const std::string path)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 
V4L2Camera(int id,std::shared_ptr<V4L2Wrapper> v4l2_wrapper,std::unique_ptr<Metadata> metadata)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 
~V4L2Camera()85 V4L2Camera::~V4L2Camera() {
86   HAL_LOG_ENTER();
87 }
88 
connect()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 
disconnect()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 
flushBuffers()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 
initStaticInfo(android::CameraMetadata * out)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 
initTemplate(int type,android::CameraMetadata * out)164 int V4L2Camera::initTemplate(int type, android::CameraMetadata* out) {
165   HAL_LOG_ENTER();
166 
167   return metadata_->GetRequestTemplate(type, out);
168 }
169 
initDeviceInfo(camera_info_t * info)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 
initDevice()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 
enqueueRequest(std::shared_ptr<default_camera_hal::CaptureRequest> request)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>
dequeueRequest()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 
enqueueRequestBuffers()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 
dequeueRequestBuffers()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 
validateDataspacesAndRotations(const camera3_stream_configuration_t * stream_config)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 
setupStreams(camera3_stream_configuration_t * stream_config)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 
isValidRequestSettings(const android::CameraMetadata & settings)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