blob: f7c75d21dab4fda369b39bb8e8ddd88d3d50979a [file] [log] [blame]
Ari Hausman-Cohen73442152016-06-08 15:50:49 -07001/*
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
Ari Hausman-Cohen3841a7f2016-07-19 17:27:52 -070017#include "v4l2_camera.h"
Ari Hausman-Cohen73442152016-06-08 15:50:49 -070018
Ari Hausman-Cohen345bd3a2016-06-13 15:33:53 -070019#include <fcntl.h>
Ari Hausman-Cohen49925842016-06-21 14:07:58 -070020#include <linux/videodev2.h>
Ari Hausman-Cohen345bd3a2016-06-13 15:33:53 -070021#include <sys/stat.h>
Ari Hausman-Cohen9430ad92016-08-24 14:00:32 -070022#include <sys/types.h>
Ari Hausman-Cohen345bd3a2016-06-13 15:33:53 -070023
Ari Hausman-Cohen49925842016-06-21 14:07:58 -070024#include <cstdlib>
25
Ari Hausman-Cohen73442152016-06-08 15:50:49 -070026#include <camera/CameraMetadata.h>
27#include <hardware/camera3.h>
28
Ari Hausman-Cohen3841a7f2016-07-19 17:27:52 -070029#include "common.h"
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -070030#include "metadata/metadata_common.h"
Ari Hausman-Cohen3841a7f2016-07-19 17:27:52 -070031#include "stream_format.h"
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -070032#include "v4l2_metadata_factory.h"
Ari Hausman-Cohen73442152016-06-08 15:50:49 -070033
Ari Hausman-Cohen900c1e32016-06-20 16:52:41 -070034#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
35
Ari Hausman-Cohen73442152016-06-08 15:50:49 -070036namespace v4l2_camera_hal {
37
Ari Hausman-Cohendde80172016-07-01 16:20:36 -070038// Helper function for managing metadata.
Ari Hausman-Cohen9430ad92016-08-24 14:00:32 -070039static std::vector<int32_t> getMetadataKeys(const camera_metadata_t* metadata) {
Ari Hausman-Cohendde80172016-07-01 16:20:36 -070040 std::vector<int32_t> keys;
41 size_t num_entries = get_camera_metadata_entry_count(metadata);
42 for (size_t i = 0; i < num_entries; ++i) {
43 camera_metadata_ro_entry_t entry;
44 get_camera_metadata_ro_entry(metadata, i, &entry);
45 keys.push_back(entry.tag);
46 }
47 return keys;
48}
49
Ari Hausman-Cohen681eaa22016-07-21 16:28:17 -070050V4L2Camera* V4L2Camera::NewV4L2Camera(int id, const std::string path) {
51 HAL_LOG_ENTER();
52
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070053 std::shared_ptr<V4L2Wrapper> v4l2_wrapper(V4L2Wrapper::NewV4L2Wrapper(path));
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -070054 if (!v4l2_wrapper) {
55 HAL_LOGE("Failed to initialize V4L2 wrapper.");
Ari Hausman-Cohen681eaa22016-07-21 16:28:17 -070056 return nullptr;
57 }
58
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -070059 std::unique_ptr<Metadata> metadata;
60 int res = GetV4L2Metadata(v4l2_wrapper, &metadata);
61 if (res) {
62 HAL_LOGE("Failed to initialize V4L2 metadata: %d", res);
63 return nullptr;
64 }
65
66 return new V4L2Camera(id, std::move(v4l2_wrapper), std::move(metadata));
Ari Hausman-Cohen681eaa22016-07-21 16:28:17 -070067}
68
Ari Hausman-Cohen9430ad92016-08-24 14:00:32 -070069V4L2Camera::V4L2Camera(int id,
70 std::shared_ptr<V4L2Wrapper> v4l2_wrapper,
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -070071 std::unique_ptr<Metadata> metadata)
Ari Hausman-Cohen49925842016-06-21 14:07:58 -070072 : default_camera_hal::Camera(id),
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -070073 device_(std::move(v4l2_wrapper)),
74 metadata_(std::move(metadata)),
75 max_input_streams_(0),
76 max_output_streams_({{0, 0, 0}}) {
Ari Hausman-Cohen73442152016-06-08 15:50:49 -070077 HAL_LOG_ENTER();
78}
79
80V4L2Camera::~V4L2Camera() {
81 HAL_LOG_ENTER();
82}
83
Ari Hausman-Cohen345bd3a2016-06-13 15:33:53 -070084int V4L2Camera::connect() {
85 HAL_LOG_ENTER();
86
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -070087 if (connection_) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070088 HAL_LOGE("Already connected. Please disconnect and try again.");
89 return -EIO;
90 }
91
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -070092 connection_.reset(new V4L2Wrapper::Connection(device_));
93 if (connection_->status()) {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -070094 HAL_LOGE("Failed to connect to device.");
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -070095 return connection_->status();
Ari Hausman-Cohen345bd3a2016-06-13 15:33:53 -070096 }
97
Ari Hausman-Cohen345bd3a2016-06-13 15:33:53 -070098 // TODO(b/29185945): confirm this is a supported device.
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -070099 // This is checked by the HAL, but the device at |device_|'s path may
Ari Hausman-Cohen49925842016-06-21 14:07:58 -0700100 // not be the same one that was there when the HAL was loaded.
101 // (Alternatively, better hotplugging support may make this unecessary
102 // by disabling cameras that get disconnected and checking newly connected
103 // cameras, so connect() is never called on an unsupported camera)
Ari Hausman-Cohen900c1e32016-06-20 16:52:41 -0700104
Ari Hausman-Cohen9430ad92016-08-24 14:00:32 -0700105 // TODO(b/29158098): Inform service of any flashes that are no longer
106 // available because this camera is in use.
Ari Hausman-Cohen345bd3a2016-06-13 15:33:53 -0700107 return 0;
108}
109
110void V4L2Camera::disconnect() {
111 HAL_LOG_ENTER();
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700112
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -0700113 connection_.reset();
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700114
Ari Hausman-Cohen900c1e32016-06-20 16:52:41 -0700115 // TODO(b/29158098): Inform service of any flashes that are available again
Ari Hausman-Cohen49925842016-06-21 14:07:58 -0700116 // because this camera is no longer in use.
Ari Hausman-Cohen345bd3a2016-06-13 15:33:53 -0700117}
118
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -0700119int V4L2Camera::initStaticInfo(android::CameraMetadata* out) {
Ari Hausman-Cohen73442152016-06-08 15:50:49 -0700120 HAL_LOG_ENTER();
121
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -0700122 int res = metadata_->FillStaticMetadata(out);
123 if (res) {
124 HAL_LOGE("Failed to get static metadata.");
Ari Hausman-Cohendde80172016-07-01 16:20:36 -0700125 return res;
126 }
Ari Hausman-Cohen900c1e32016-06-20 16:52:41 -0700127
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -0700128 // Extract max streams for use in verifying stream configs.
Ari Hausman-Cohen9430ad92016-08-24 14:00:32 -0700129 res = SingleTagValue(
130 *out, ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS, &max_input_streams_);
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -0700131 if (res) {
132 HAL_LOGE("Failed to get max num input streams from static metadata.");
133 return res;
134 }
Ari Hausman-Cohen9430ad92016-08-24 14:00:32 -0700135 res = SingleTagValue(
136 *out, ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS, &max_output_streams_);
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -0700137 if (res) {
138 HAL_LOGE("Failed to get max num output streams from static metadata.");
Ari Hausman-Cohendde80172016-07-01 16:20:36 -0700139 return res;
140 }
Ari Hausman-Cohen900c1e32016-06-20 16:52:41 -0700141
Ari Hausman-Cohen900c1e32016-06-20 16:52:41 -0700142 return 0;
Ari Hausman-Cohen73442152016-06-08 15:50:49 -0700143}
144
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -0700145int V4L2Camera::initTemplate(int type, android::CameraMetadata* out) {
146 HAL_LOG_ENTER();
147
148 return metadata_->GetRequestTemplate(type, out);
149}
150
Ari Hausman-Cohen73442152016-06-08 15:50:49 -0700151void V4L2Camera::initDeviceInfo(camera_info_t* info) {
152 HAL_LOG_ENTER();
153
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -0700154 // TODO(b/31044975): move this into device interface.
Ari Hausman-Cohen73442152016-06-08 15:50:49 -0700155 // For now, just constants.
Ari Hausman-Cohen73442152016-06-08 15:50:49 -0700156 info->resource_cost = 100;
157 info->conflicting_devices = nullptr;
158 info->conflicting_devices_length = 0;
159}
160
161int V4L2Camera::initDevice() {
162 HAL_LOG_ENTER();
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -0700163 // Nothing to do.
Ari Hausman-Cohen49925842016-06-21 14:07:58 -0700164 return 0;
165}
166
Ari Hausman-Cohen2738a9c2016-09-21 15:03:49 -0700167int V4L2Camera::enqueueRequest(
168 std::shared_ptr<default_camera_hal::CaptureRequest> request) {
Ari Hausman-Cohen24e541c2016-07-21 11:20:30 -0700169 HAL_LOG_ENTER();
170
Ari Hausman-Cohen2738a9c2016-09-21 15:03:49 -0700171 // Assume request validated before calling this function.
172 // (For now, always exactly 1 output buffer, no inputs).
173
174 {
175 std::lock_guard<std::mutex> guard(request_queue_lock_);
176 request_queue_.push(request);
Ari Hausman-Cohen24e541c2016-07-21 11:20:30 -0700177 }
Ari Hausman-Cohen24e541c2016-07-21 11:20:30 -0700178
Ari Hausman-Cohen2738a9c2016-09-21 15:03:49 -0700179 // TODO(b/29334616): Enqueueing of request buffers should be
180 // done by a consumer thread loop instead of here
181 enqueueRequestBuffers();
Ari Hausman-Cohen24e541c2016-07-21 11:20:30 -0700182
Ari Hausman-Cohen24e541c2016-07-21 11:20:30 -0700183 return 0;
184}
185
Ari Hausman-Cohen2738a9c2016-09-21 15:03:49 -0700186std::shared_ptr<default_camera_hal::CaptureRequest>
187V4L2Camera::dequeueRequest() {
188 std::lock_guard<std::mutex> guard(request_queue_lock_);
189 if (request_queue_.empty()) {
190 return nullptr;
191 }
192 std::shared_ptr<default_camera_hal::CaptureRequest> request =
193 request_queue_.front();
194 request_queue_.pop();
195 return request;
196}
Ari Hausman-Cohen24e541c2016-07-21 11:20:30 -0700197
Ari Hausman-Cohen2738a9c2016-09-21 15:03:49 -0700198void V4L2Camera::enqueueRequestBuffers() {
199 // Get a request from the queue.
200 std::shared_ptr<default_camera_hal::CaptureRequest> request =
201 dequeueRequest();
202 if (!request) {
203 return;
Ari Hausman-Cohen24e541c2016-07-21 11:20:30 -0700204 }
205
Ari Hausman-Cohen2738a9c2016-09-21 15:03:49 -0700206 // Assume request validated before being added to the queue
207 // (For now, always exactly 1 output buffer, no inputs).
208 {
209 std::lock_guard<std::mutex> guard(in_flight_lock_);
Ari Hausman-Cohen49925842016-06-21 14:07:58 -0700210
Ari Hausman-Cohen2738a9c2016-09-21 15:03:49 -0700211 // Set the requested settings
212 int res = metadata_->SetRequestSettings(request->settings);
213 if (res) {
214 HAL_LOGE("Failed to set settings.");
215 completeRequest(request, res);
216 return;
217 }
218
219 // Replace the requested settings with a snapshot of
220 // the used settings/state.
221 res = metadata_->FillResultMetadata(&request->settings);
222 if (res) {
223 HAL_LOGE("Failed to fill result metadata.");
224 completeRequest(request, res);
225 return;
226 }
227
228 // Actually enqueue the buffer for capture.
229 res = device_->EnqueueBuffer(&request->output_buffers[0]);
230 if (res) {
231 HAL_LOGE("Device failed to enqueue buffer.");
232 completeRequest(request, res);
233 return;
234 }
235
236 if (in_flight_.empty()) {
237 // Nothing in flight, stream should be off, so it needs to be turned on.
238 res = device_->StreamOn();
239 if (res) {
240 HAL_LOGE("Device failed to turn on stream.");
241 completeRequest(request, res);
242 return;
243 }
244 }
245 in_flight_.push(request);
246 }
247
248 // TODO(b/29334616): Dequeueing of request buffers should be
249 // done by a consumer thread loop instead of here
250 dequeueRequestBuffers();
251}
252
253void V4L2Camera::dequeueRequestBuffers() {
254 std::shared_ptr<default_camera_hal::CaptureRequest> request;
255 {
256 std::lock_guard<std::mutex> guard(in_flight_lock_);
257 if (in_flight_.empty()) {
258 return;
259 }
260
261 request = in_flight_.front();
262 in_flight_.pop();
263
264 // Dequeue the buffer. For now, since each request has only 1 buffer,
265 // and the in_flight_lock_ is held while enqueueing and dequeuing
266 // from the device, just assume that the dequeued buffer corresponds
267 // to the dequeued request.
268 // TODO(b/31657008): in_flight_ should map buffer handles to requests;
269 // this consumer should just dequeue whatever it gets, then match
270 // that to a handle.
271 v4l2_buffer result_buffer;
272 int res = device_->DequeueBuffer(&result_buffer);
273 if (res) {
274 HAL_LOGE("Device failed to dequeue buffer.");
275 completeRequest(request, res);
276 return;
277 }
278
279 // All done, turn off the stream if it's empty.
280 if (in_flight_.empty()) {
281 res = device_->StreamOff();
282 if (res) {
283 HAL_LOGE("Device failed to turn off stream.");
284 completeRequest(request, res);
285 return;
286 }
287 }
288 }
289
290 completeRequest(request, 0);
Ari Hausman-Cohen73442152016-06-08 15:50:49 -0700291}
292
Ari Hausman-Cohen72fddb32016-06-30 16:53:31 -0700293bool V4L2Camera::isSupportedStreamSet(default_camera_hal::Stream** streams,
Ari Hausman-Cohen9430ad92016-08-24 14:00:32 -0700294 int count,
295 uint32_t mode) {
Ari Hausman-Cohen72fddb32016-06-30 16:53:31 -0700296 HAL_LOG_ENTER();
297
298 if (mode != CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE) {
299 HAL_LOGE("Unsupported stream configuration mode: %d", mode);
300 return false;
301 }
302
303 // This should be checked by the caller, but put here as a sanity check.
304 if (count < 1) {
305 HAL_LOGE("Must request at least 1 stream");
306 return false;
307 }
308
309 // Count the number of streams of each type.
310 int32_t num_input = 0;
311 int32_t num_raw = 0;
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700312 int32_t num_stalling = 0;
313 int32_t num_non_stalling = 0;
Ari Hausman-Cohen72fddb32016-06-30 16:53:31 -0700314 for (int i = 0; i < count; ++i) {
315 default_camera_hal::Stream* stream = streams[i];
316
317 if (stream->isInputType()) {
318 ++num_input;
319 }
320
321 if (stream->isOutputType()) {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700322 StreamFormat format(*stream);
323 switch (format.Category()) {
324 case kFormatCategoryRaw:
325 ++num_raw;
326 case kFormatCategoryStalling:
327 ++num_stalling;
Ari Hausman-Cohen72fddb32016-06-30 16:53:31 -0700328 break;
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700329 case kFormatCategoryNonStalling:
330 ++num_non_stalling;
Ari Hausman-Cohen72fddb32016-06-30 16:53:31 -0700331 break;
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700332 case kFormatCategoryUnknown: // Fall through.
Ari Hausman-Cohen72fddb32016-06-30 16:53:31 -0700333 default:
Ari Hausman-Cohen9430ad92016-08-24 14:00:32 -0700334 HAL_LOGE(
335 "Unsupported format for stream %d: %d", i, stream->getFormat());
Ari Hausman-Cohen72fddb32016-06-30 16:53:31 -0700336 return false;
337 }
338 }
339 }
340
Ari Hausman-Cohen9430ad92016-08-24 14:00:32 -0700341 if (num_input > max_input_streams_ || num_raw > max_output_streams_[0] ||
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -0700342 num_non_stalling > max_output_streams_[1] ||
343 num_stalling > max_output_streams_[2]) {
Ari Hausman-Cohen9430ad92016-08-24 14:00:32 -0700344 HAL_LOGE(
345 "Invalid stream configuration: %d input, %d RAW, %d non-stalling, "
346 "%d stalling (max supported: %d input, %d RAW, %d non-stalling, "
347 "%d stalling)",
348 max_input_streams_,
349 max_output_streams_[0],
350 max_output_streams_[1],
351 max_output_streams_[2],
352 num_input,
353 num_raw,
354 num_non_stalling,
355 num_stalling);
Ari Hausman-Cohen72fddb32016-06-30 16:53:31 -0700356 return false;
357 }
358
359 // TODO(b/29939583): The above logic should be all that's necessary,
360 // but V4L2 doesn't actually support more than 1 stream at a time. So for now,
361 // if not all streams are the same format and size, error. Note that this
362 // means the HAL is not spec-compliant; the requested streams are technically
363 // valid and it is not technically allowed to error once it has reached this
364 // point.
365 int format = streams[0]->getFormat();
366 uint32_t width = streams[0]->getWidth();
367 uint32_t height = streams[0]->getHeight();
368 for (int i = 1; i < count; ++i) {
369 const default_camera_hal::Stream* stream = streams[i];
370 if (stream->getFormat() != format || stream->getWidth() != width ||
371 stream->getHeight() != height) {
Ari Hausman-Cohen9430ad92016-08-24 14:00:32 -0700372 HAL_LOGE(
373 "V4L2 only supports 1 stream configuration at a time "
374 "(stream 0 is format %d, width %u, height %u, "
375 "stream %d is format %d, width %u, height %u).",
376 format,
377 width,
378 height,
379 i,
380 stream->getFormat(),
381 stream->getWidth(),
382 stream->getHeight());
Ari Hausman-Cohen72fddb32016-06-30 16:53:31 -0700383 return false;
384 }
385 }
386
387 return true;
388}
389
390int V4L2Camera::setupStream(default_camera_hal::Stream* stream,
391 uint32_t* max_buffers) {
392 HAL_LOG_ENTER();
393
394 if (stream->getRotation() != CAMERA3_STREAM_ROTATION_0) {
395 HAL_LOGE("Rotation %d not supported", stream->getRotation());
396 return -EINVAL;
397 }
398
399 // Doesn't matter what was requested, we always use dataspace V0_JFIF.
400 // Note: according to camera3.h, this isn't allowed, but etalvala@google.com
401 // claims it's underdocumented; the implementation lets the HAL overwrite it.
402 stream->setDataSpace(HAL_DATASPACE_V0_JFIF);
403
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -0700404 int res = device_->SetFormat(*stream, max_buffers);
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700405 if (res) {
406 HAL_LOGE("Failed to set device to correct format for stream.");
407 return res;
Ari Hausman-Cohen72fddb32016-06-30 16:53:31 -0700408 }
Ari Hausman-Cohen72fddb32016-06-30 16:53:31 -0700409 // Sanity check.
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700410 if (*max_buffers < 1) {
411 HAL_LOGE("Setting format resulted in an invalid maximum of %u buffers.",
412 *max_buffers);
Ari Hausman-Cohen72fddb32016-06-30 16:53:31 -0700413 return -ENODEV;
414 }
415
Ari Hausman-Cohen72fddb32016-06-30 16:53:31 -0700416 return 0;
417}
418
Ari Hausman-Cohen2738a9c2016-09-21 15:03:49 -0700419bool V4L2Camera::isValidRequest(
420 const default_camera_hal::CaptureRequest& request) {
Ari Hausman-Cohen73442152016-06-08 15:50:49 -0700421 HAL_LOG_ENTER();
422
Ari Hausman-Cohen2738a9c2016-09-21 15:03:49 -0700423 if (request.input_buffer != nullptr) {
424 HAL_LOGE("Input buffer reprocessing not implemented.");
425 return false;
426 } else if (request.output_buffers.size() > 1) {
427 HAL_LOGE("Only 1 output buffer allowed per request.");
428 return false;
429 } else if (!metadata_->IsValidRequest(request.settings)) {
430 HAL_LOGE("Invalid request settings.");
431 return false;
432 }
Ari Hausman-Cohen73442152016-06-08 15:50:49 -0700433
Ari Hausman-Cohen2738a9c2016-09-21 15:03:49 -0700434 return true;
Ari Hausman-Cohen49925842016-06-21 14:07:58 -0700435}
436
Ari Hausman-Cohen3841a7f2016-07-19 17:27:52 -0700437} // namespace v4l2_camera_hal