blob: 36d04116308e5b09b41a698a5b65febb0b3224bd [file] [log] [blame]
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -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_wrapper.h"
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070018
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070019#include <algorithm>
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -070020#include <array>
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070021#include <limits>
Ari Hausman-Cohen2d1ea3a2017-03-24 18:38:16 -070022#include <mutex>
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070023#include <vector>
24
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070025#include <fcntl.h>
26#include <linux/videodev2.h>
27#include <sys/stat.h>
28#include <sys/types.h>
29
Ari Hausman-Cohen2d1ea3a2017-03-24 18:38:16 -070030#include <android-base/unique_fd.h>
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070031
Ari Hausman-Cohen3841a7f2016-07-19 17:27:52 -070032#include "common.h"
Ari Hausman-Cohen3841a7f2016-07-19 17:27:52 -070033#include "stream_format.h"
34#include "v4l2_gralloc.h"
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070035
36namespace v4l2_camera_hal {
37
Jaesung Chung932d4dd2017-12-15 15:27:21 +090038const int32_t kStandardSizes[][2] = {
39 {4096, 2160}, // 4KDCI (for USB camera)
40 {3840, 2160}, // 4KUHD (for USB camera)
41 {3280, 2464}, // 8MP
42 {2560, 1440}, // QHD
43 {1920, 1080}, // HD1080
44 {1640, 1232}, // 2MP
45 {1280, 720}, // HD
46 {1024, 768}, // XGA
47 { 640, 480}, // VGA
48 { 320, 240}, // QVGA
49 { 176, 144} // QCIF
50};
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070051
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -070052V4L2Wrapper* V4L2Wrapper::NewV4L2Wrapper(const std::string device_path) {
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -070053 std::unique_ptr<V4L2Gralloc> gralloc(V4L2Gralloc::NewV4L2Gralloc());
54 if (!gralloc) {
55 HAL_LOGE("Failed to initialize gralloc helper.");
56 return nullptr;
57 }
58
59 return new V4L2Wrapper(device_path, std::move(gralloc));
60}
61
62V4L2Wrapper::V4L2Wrapper(const std::string device_path,
63 std::unique_ptr<V4L2Gralloc> gralloc)
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -070064 : device_path_(std::move(device_path)),
65 gralloc_(std::move(gralloc)),
Ari Hausman-Cohenad6fe2b2016-11-16 10:48:07 -080066 connection_count_(0) {}
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070067
Ari Hausman-Cohenad6fe2b2016-11-16 10:48:07 -080068V4L2Wrapper::~V4L2Wrapper() {}
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070069
70int V4L2Wrapper::Connect() {
71 HAL_LOG_ENTER();
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070072 std::lock_guard<std::mutex> lock(connection_lock_);
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070073
74 if (connected()) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070075 HAL_LOGV("Camera device %s is already connected.", device_path_.c_str());
76 ++connection_count_;
77 return 0;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070078 }
79
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -080080 // Open in nonblocking mode (DQBUF may return EAGAIN).
81 int fd = TEMP_FAILURE_RETRY(open(device_path_.c_str(), O_RDWR | O_NONBLOCK));
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070082 if (fd < 0) {
83 HAL_LOGE("failed to open %s (%s)", device_path_.c_str(), strerror(errno));
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070084 return -ENODEV;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070085 }
86 device_fd_.reset(fd);
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070087 ++connection_count_;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070088
89 // Check if this connection has the extended control query capability.
90 v4l2_query_ext_ctrl query;
91 query.id = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND;
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070092 extended_query_supported_ = (IoctlLocked(VIDIOC_QUERY_EXT_CTRL, &query) == 0);
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070093
94 // TODO(b/29185945): confirm this is a supported device.
95 // This is checked by the HAL, but the device at device_path_ may
96 // not be the same one that was there when the HAL was loaded.
97 // (Alternatively, better hotplugging support may make this unecessary
98 // by disabling cameras that get disconnected and checking newly connected
99 // cameras, so Connect() is never called on an unsupported camera)
100 return 0;
101}
102
103void V4L2Wrapper::Disconnect() {
104 HAL_LOG_ENTER();
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700105 std::lock_guard<std::mutex> lock(connection_lock_);
106
107 if (connection_count_ == 0) {
108 // Not connected.
109 HAL_LOGE("Camera device %s is not connected, cannot disconnect.",
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -0700110 device_path_.c_str());
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700111 return;
112 }
113
114 --connection_count_;
115 if (connection_count_ > 0) {
116 HAL_LOGV("Disconnected from camera device %s. %d connections remain.",
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -0700117 device_path_.c_str());
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700118 return;
119 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700120
Ari Hausman-Cohen2d1ea3a2017-03-24 18:38:16 -0700121 device_fd_.reset(-1); // Includes close().
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700122 format_.reset();
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700123 buffers_.clear();
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700124 // Closing the device releases all queued buffers back to the user.
125 gralloc_->unlockAllBuffers();
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700126}
127
128// Helper function. Should be used instead of ioctl throughout this class.
129template <typename T>
130int V4L2Wrapper::IoctlLocked(int request, T data) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700131 // Potentially called so many times logging entry is a bad idea.
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700132 std::lock_guard<std::mutex> lock(device_lock_);
133
134 if (!connected()) {
135 HAL_LOGE("Device %s not connected.", device_path_.c_str());
136 return -ENODEV;
137 }
138 return TEMP_FAILURE_RETRY(ioctl(device_fd_.get(), request, data));
139}
140
141int V4L2Wrapper::StreamOn() {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700142 if (!format_) {
143 HAL_LOGE("Stream format must be set before turning on stream.");
144 return -EINVAL;
145 }
146
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700147 int32_t type = format_->type();
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700148 if (IoctlLocked(VIDIOC_STREAMON, &type) < 0) {
149 HAL_LOGE("STREAMON fails: %s", strerror(errno));
150 return -ENODEV;
151 }
152
Ari Hausman-Cohenad6fe2b2016-11-16 10:48:07 -0800153 HAL_LOGV("Stream turned on.");
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700154 return 0;
155}
156
157int V4L2Wrapper::StreamOff() {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700158 if (!format_) {
Ari Hausman-Cohenad6fe2b2016-11-16 10:48:07 -0800159 // Can't have turned on the stream without format being set,
Ari Hausman-Cohen71cb8742016-09-22 11:12:00 -0700160 // so nothing to turn off here.
161 return 0;
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700162 }
163
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700164 int32_t type = format_->type();
165 int res = IoctlLocked(VIDIOC_STREAMOFF, &type);
166 // Calling STREAMOFF releases all queued buffers back to the user.
167 int gralloc_res = gralloc_->unlockAllBuffers();
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800168 // No buffers in flight.
169 for (size_t i = 0; i < buffers_.size(); ++i) {
170 buffers_[i] = false;
171 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700172 if (res < 0) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700173 HAL_LOGE("STREAMOFF fails: %s", strerror(errno));
174 return -ENODEV;
175 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700176 if (gralloc_res < 0) {
177 HAL_LOGE("Failed to unlock all buffers after turning stream off.");
178 return gralloc_res;
179 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700180
Ari Hausman-Cohenad6fe2b2016-11-16 10:48:07 -0800181 HAL_LOGV("Stream turned off.");
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700182 return 0;
183}
184
185int V4L2Wrapper::QueryControl(uint32_t control_id,
186 v4l2_query_ext_ctrl* result) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700187 int res;
188
189 memset(result, 0, sizeof(*result));
190
191 if (extended_query_supported_) {
192 result->id = control_id;
193 res = IoctlLocked(VIDIOC_QUERY_EXT_CTRL, result);
194 // Assuming the operation was supported (not ENOTTY), no more to do.
195 if (errno != ENOTTY) {
196 if (res) {
197 HAL_LOGE("QUERY_EXT_CTRL fails: %s", strerror(errno));
198 return -ENODEV;
199 }
200 return 0;
201 }
202 }
203
204 // Extended control querying not supported, fall back to basic control query.
205 v4l2_queryctrl query;
206 query.id = control_id;
207 if (IoctlLocked(VIDIOC_QUERYCTRL, &query)) {
208 HAL_LOGE("QUERYCTRL fails: %s", strerror(errno));
209 return -ENODEV;
210 }
211
212 // Convert the basic result to the extended result.
213 result->id = query.id;
214 result->type = query.type;
215 memcpy(result->name, query.name, sizeof(query.name));
216 result->minimum = query.minimum;
217 if (query.type == V4L2_CTRL_TYPE_BITMASK) {
218 // According to the V4L2 documentation, when type is BITMASK,
219 // max and default should be interpreted as __u32. Practically,
220 // this means the conversion from 32 bit to 64 will pad with 0s not 1s.
221 result->maximum = static_cast<uint32_t>(query.maximum);
222 result->default_value = static_cast<uint32_t>(query.default_value);
223 } else {
224 result->maximum = query.maximum;
225 result->default_value = query.default_value;
226 }
227 result->step = static_cast<uint32_t>(query.step);
228 result->flags = query.flags;
229 result->elems = 1;
230 switch (result->type) {
231 case V4L2_CTRL_TYPE_INTEGER64:
232 result->elem_size = sizeof(int64_t);
233 break;
234 case V4L2_CTRL_TYPE_STRING:
235 result->elem_size = result->maximum + 1;
236 break;
237 default:
238 result->elem_size = sizeof(int32_t);
239 break;
240 }
241
242 return 0;
243}
244
245int V4L2Wrapper::GetControl(uint32_t control_id, int32_t* value) {
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700246 // For extended controls (any control class other than "user"),
247 // G_EXT_CTRL must be used instead of G_CTRL.
248 if (V4L2_CTRL_ID2CLASS(control_id) != V4L2_CTRL_CLASS_USER) {
249 v4l2_ext_control control;
250 v4l2_ext_controls controls;
251 memset(&control, 0, sizeof(control));
252 memset(&controls, 0, sizeof(controls));
253
254 control.id = control_id;
255 controls.ctrl_class = V4L2_CTRL_ID2CLASS(control_id);
256 controls.count = 1;
257 controls.controls = &control;
258
259 if (IoctlLocked(VIDIOC_G_EXT_CTRLS, &controls) < 0) {
260 HAL_LOGE("G_EXT_CTRLS fails: %s", strerror(errno));
261 return -ENODEV;
262 }
263 *value = control.value;
264 } else {
265 v4l2_control control{control_id, 0};
266 if (IoctlLocked(VIDIOC_G_CTRL, &control) < 0) {
267 HAL_LOGE("G_CTRL fails: %s", strerror(errno));
268 return -ENODEV;
269 }
270 *value = control.value;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700271 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700272 return 0;
273}
274
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700275int V4L2Wrapper::SetControl(uint32_t control_id,
276 int32_t desired,
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700277 int32_t* result) {
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700278 int32_t result_value = 0;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700279
Ari Hausman-Cohen99f3ea02016-08-02 10:47:07 -0700280 // TODO(b/29334616): When async, this may need to check if the stream
281 // is on, and if so, lock it off while setting format. Need to look
282 // into if V4L2 supports adjusting controls while the stream is on.
283
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700284 // For extended controls (any control class other than "user"),
285 // S_EXT_CTRL must be used instead of S_CTRL.
286 if (V4L2_CTRL_ID2CLASS(control_id) != V4L2_CTRL_CLASS_USER) {
287 v4l2_ext_control control;
288 v4l2_ext_controls controls;
289 memset(&control, 0, sizeof(control));
290 memset(&controls, 0, sizeof(controls));
291
292 control.id = control_id;
293 control.value = desired;
294 controls.ctrl_class = V4L2_CTRL_ID2CLASS(control_id);
295 controls.count = 1;
296 controls.controls = &control;
297
298 if (IoctlLocked(VIDIOC_S_EXT_CTRLS, &controls) < 0) {
299 HAL_LOGE("S_EXT_CTRLS fails: %s", strerror(errno));
300 return -ENODEV;
301 }
302 result_value = control.value;
303 } else {
304 v4l2_control control{control_id, desired};
305 if (IoctlLocked(VIDIOC_S_CTRL, &control) < 0) {
306 HAL_LOGE("S_CTRL fails: %s", strerror(errno));
307 return -ENODEV;
308 }
309 result_value = control.value;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700310 }
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700311
Ari Hausman-Cohen99f3ea02016-08-02 10:47:07 -0700312 // If the caller wants to know the result, pass it back.
313 if (result != nullptr) {
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700314 *result = result_value;
Ari Hausman-Cohen99f3ea02016-08-02 10:47:07 -0700315 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700316 return 0;
317}
318
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700319int V4L2Wrapper::GetFormats(std::set<uint32_t>* v4l2_formats) {
320 HAL_LOG_ENTER();
321
322 v4l2_fmtdesc format_query;
323 memset(&format_query, 0, sizeof(format_query));
324 // TODO(b/30000211): multiplanar support.
325 format_query.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
326 while (IoctlLocked(VIDIOC_ENUM_FMT, &format_query) >= 0) {
327 v4l2_formats->insert(format_query.pixelformat);
328 ++format_query.index;
329 }
330
331 if (errno != EINVAL) {
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700332 HAL_LOGE(
333 "ENUM_FMT fails at index %d: %s", format_query.index, strerror(errno));
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700334 return -ENODEV;
335 }
336 return 0;
337}
338
339int V4L2Wrapper::GetFormatFrameSizes(uint32_t v4l2_format,
340 std::set<std::array<int32_t, 2>>* sizes) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700341 v4l2_frmsizeenum size_query;
342 memset(&size_query, 0, sizeof(size_query));
343 size_query.pixel_format = v4l2_format;
344 if (IoctlLocked(VIDIOC_ENUM_FRAMESIZES, &size_query) < 0) {
345 HAL_LOGE("ENUM_FRAMESIZES failed: %s", strerror(errno));
346 return -ENODEV;
347 }
348 if (size_query.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
349 // Discrete: enumerate all sizes using VIDIOC_ENUM_FRAMESIZES.
350 // Assuming that a driver with discrete frame sizes has a reasonable number
351 // of them.
352 do {
353 sizes->insert({{{static_cast<int32_t>(size_query.discrete.width),
354 static_cast<int32_t>(size_query.discrete.height)}}});
355 ++size_query.index;
356 } while (IoctlLocked(VIDIOC_ENUM_FRAMESIZES, &size_query) >= 0);
357 if (errno != EINVAL) {
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700358 HAL_LOGE("ENUM_FRAMESIZES fails at index %d: %s",
359 size_query.index,
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700360 strerror(errno));
361 return -ENODEV;
362 }
363 } else {
364 // Continuous/Step-wise: based on the stepwise struct returned by the query.
365 // Fully listing all possible sizes, with large enough range/small enough
366 // step size, may produce far too many potential sizes. Instead, find the
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800367 // closest to a set of standard sizes.
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -0700368 for (const auto size : kStandardSizes) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700369 // Find the closest size, rounding up.
370 uint32_t desired_width = size[0];
371 uint32_t desired_height = size[1];
372 if (desired_width < size_query.stepwise.min_width ||
373 desired_height < size_query.stepwise.min_height) {
374 HAL_LOGV("Standard size %u x %u is too small for format %d",
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700375 desired_width,
376 desired_height,
377 v4l2_format);
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700378 continue;
Jaesung Chung932d4dd2017-12-15 15:27:21 +0900379 } else if (desired_width > size_query.stepwise.max_width ||
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700380 desired_height > size_query.stepwise.max_height) {
381 HAL_LOGV("Standard size %u x %u is too big for format %d",
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700382 desired_width,
383 desired_height,
384 v4l2_format);
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700385 continue;
386 }
387
388 // Round up.
389 uint32_t width_steps = (desired_width - size_query.stepwise.min_width +
390 size_query.stepwise.step_width - 1) /
391 size_query.stepwise.step_width;
392 uint32_t height_steps = (desired_height - size_query.stepwise.min_height +
393 size_query.stepwise.step_height - 1) /
394 size_query.stepwise.step_height;
395 sizes->insert(
396 {{{static_cast<int32_t>(size_query.stepwise.min_width +
397 width_steps * size_query.stepwise.step_width),
398 static_cast<int32_t>(size_query.stepwise.min_height +
399 height_steps *
400 size_query.stepwise.step_height)}}});
401 }
402 }
403 return 0;
404}
405
406// Converts a v4l2_fract with units of seconds to an int64_t with units of ns.
407inline int64_t FractToNs(const v4l2_fract& fract) {
408 return (1000000000LL * fract.numerator) / fract.denominator;
409}
410
411int V4L2Wrapper::GetFormatFrameDurationRange(
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700412 uint32_t v4l2_format,
413 const std::array<int32_t, 2>& size,
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700414 std::array<int64_t, 2>* duration_range) {
415 // Potentially called so many times logging entry is a bad idea.
416
417 v4l2_frmivalenum duration_query;
418 memset(&duration_query, 0, sizeof(duration_query));
419 duration_query.pixel_format = v4l2_format;
420 duration_query.width = size[0];
421 duration_query.height = size[1];
422 if (IoctlLocked(VIDIOC_ENUM_FRAMEINTERVALS, &duration_query) < 0) {
423 HAL_LOGE("ENUM_FRAMEINTERVALS failed: %s", strerror(errno));
424 return -ENODEV;
425 }
426
427 int64_t min = std::numeric_limits<int64_t>::max();
428 int64_t max = std::numeric_limits<int64_t>::min();
429 if (duration_query.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
430 // Discrete: enumerate all durations using VIDIOC_ENUM_FRAMEINTERVALS.
431 do {
432 min = std::min(min, FractToNs(duration_query.discrete));
433 max = std::max(max, FractToNs(duration_query.discrete));
434 ++duration_query.index;
435 } while (IoctlLocked(VIDIOC_ENUM_FRAMEINTERVALS, &duration_query) >= 0);
436 if (errno != EINVAL) {
437 HAL_LOGE("ENUM_FRAMEINTERVALS fails at index %d: %s",
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700438 duration_query.index,
439 strerror(errno));
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700440 return -ENODEV;
441 }
442 } else {
443 // Continuous/Step-wise: simply convert the given min and max.
444 min = FractToNs(duration_query.stepwise.min);
445 max = FractToNs(duration_query.stepwise.max);
446 }
447 (*duration_range)[0] = min;
448 (*duration_range)[1] = max;
449 return 0;
450}
451
Ari Hausman-Cohenef523102016-11-21 17:02:01 -0800452int V4L2Wrapper::SetFormat(const StreamFormat& desired_format,
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700453 uint32_t* result_max_buffers) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700454 HAL_LOG_ENTER();
455
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700456 if (format_ && desired_format == *format_) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700457 HAL_LOGV("Already in correct format, skipping format setting.");
Ari Hausman-Cohena5c9bfd2016-11-18 14:57:07 -0800458 *result_max_buffers = buffers_.size();
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700459 return 0;
460 }
461
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800462 // Not in the correct format, set the new one.
463
464 if (format_) {
465 // If we had an old format, first request 0 buffers to inform the device
466 // we're no longer using any previously "allocated" buffers from the old
467 // format. This seems like it shouldn't be necessary for USERPTR memory,
468 // and/or should happen from turning the stream off, but the driver
469 // complained. May be a driver issue, or may be intended behavior.
470 int res = RequestBuffers(0);
471 if (res) {
472 return res;
473 }
474 }
475
476 // Set the camera to the new format.
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700477 v4l2_format new_format;
478 desired_format.FillFormatRequest(&new_format);
479 // TODO(b/29334616): When async, this will need to check if the stream
480 // is on, and if so, lock it off while setting format.
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800481
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700482 if (IoctlLocked(VIDIOC_S_FMT, &new_format) < 0) {
483 HAL_LOGE("S_FMT failed: %s", strerror(errno));
484 return -ENODEV;
485 }
486
487 // Check that the driver actually set to the requested values.
488 if (desired_format != new_format) {
489 HAL_LOGE("Device doesn't support desired stream configuration.");
490 return -EINVAL;
491 }
492
493 // Keep track of our new format.
494 format_.reset(new StreamFormat(new_format));
495
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800496 // Format changed, request new buffers.
497 int res = RequestBuffers(1);
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700498 if (res) {
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800499 HAL_LOGE("Requesting buffers for new format failed.");
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700500 return res;
501 }
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700502 *result_max_buffers = buffers_.size();
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700503 return 0;
504}
505
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800506int V4L2Wrapper::RequestBuffers(uint32_t num_requested) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700507 v4l2_requestbuffers req_buffers;
508 memset(&req_buffers, 0, sizeof(req_buffers));
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700509 req_buffers.type = format_->type();
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700510 req_buffers.memory = V4L2_MEMORY_USERPTR;
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800511 req_buffers.count = num_requested;
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700512
513 int res = IoctlLocked(VIDIOC_REQBUFS, &req_buffers);
514 // Calling REQBUFS releases all queued buffers back to the user.
515 int gralloc_res = gralloc_->unlockAllBuffers();
516 if (res < 0) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700517 HAL_LOGE("REQBUFS failed: %s", strerror(errno));
518 return -ENODEV;
519 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700520 if (gralloc_res < 0) {
521 HAL_LOGE("Failed to unlock all buffers when setting up new buffers.");
522 return gralloc_res;
523 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700524
525 // V4L2 will set req_buffers.count to a number of buffers it can handle.
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800526 if (num_requested > 0 && req_buffers.count < 1) {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700527 HAL_LOGE("REQBUFS claims it can't handle any buffers.");
528 return -ENODEV;
529 }
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700530 buffers_.resize(req_buffers.count, false);
531
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700532 return 0;
533}
534
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800535int V4L2Wrapper::EnqueueBuffer(const camera3_stream_buffer_t* camera_buffer,
536 uint32_t* enqueued_index) {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700537 if (!format_) {
538 HAL_LOGE("Stream format must be set before enqueuing buffers.");
539 return -ENODEV;
540 }
541
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700542 // Find a free buffer index. Could use some sort of persistent hinting
543 // here to improve expected efficiency, but buffers_.size() is expected
544 // to be low enough (<10 experimentally) that it's not worth it.
545 int index = -1;
546 {
547 std::lock_guard<std::mutex> guard(buffer_queue_lock_);
548 for (int i = 0; i < buffers_.size(); ++i) {
549 if (!buffers_[i]) {
Jaesung Chung1fc9b612017-11-10 18:09:38 +0900550 buffers_[i] = true;
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700551 index = i;
552 break;
553 }
554 }
555 }
556 if (index < 0) {
557 // Note: The HAL should be tracking the number of buffers in flight
558 // for each stream, and should never overflow the device.
559 HAL_LOGE("Cannot enqueue buffer: stream is already full.");
560 return -ENODEV;
561 }
562
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700563 // Set up a v4l2 buffer struct.
564 v4l2_buffer device_buffer;
565 memset(&device_buffer, 0, sizeof(device_buffer));
566 device_buffer.type = format_->type();
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700567 device_buffer.index = index;
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700568
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700569 // Use QUERYBUF to ensure our buffer/device is in good shape,
570 // and fill out remaining fields.
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700571 if (IoctlLocked(VIDIOC_QUERYBUF, &device_buffer) < 0) {
572 HAL_LOGE("QUERYBUF fails: %s", strerror(errno));
Jaesung Chung1fc9b612017-11-10 18:09:38 +0900573 // Return buffer index.
574 std::lock_guard<std::mutex> guard(buffer_queue_lock_);
575 buffers_[index] = false;
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700576 return -ENODEV;
577 }
578
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700579 // Lock the buffer for writing (fills in the user pointer field).
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700580 int res =
581 gralloc_->lock(camera_buffer, format_->bytes_per_line(), &device_buffer);
582 if (res) {
583 HAL_LOGE("Gralloc failed to lock buffer.");
Jaesung Chung1fc9b612017-11-10 18:09:38 +0900584 // Return buffer index.
585 std::lock_guard<std::mutex> guard(buffer_queue_lock_);
586 buffers_[index] = false;
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700587 return res;
588 }
589 if (IoctlLocked(VIDIOC_QBUF, &device_buffer) < 0) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700590 HAL_LOGE("QBUF fails: %s", strerror(errno));
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700591 gralloc_->unlock(&device_buffer);
Jaesung Chung1fc9b612017-11-10 18:09:38 +0900592 // Return buffer index.
593 std::lock_guard<std::mutex> guard(buffer_queue_lock_);
594 buffers_[index] = false;
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700595 return -ENODEV;
596 }
597
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800598 if (enqueued_index) {
599 *enqueued_index = index;
600 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700601 return 0;
602}
603
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800604int V4L2Wrapper::DequeueBuffer(uint32_t* dequeued_index) {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700605 if (!format_) {
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800606 HAL_LOGV(
607 "Format not set, so stream can't be on, "
608 "so no buffers available for dequeueing");
609 return -EAGAIN;
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700610 }
611
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800612 v4l2_buffer buffer;
613 memset(&buffer, 0, sizeof(buffer));
614 buffer.type = format_->type();
615 buffer.memory = V4L2_MEMORY_USERPTR;
616 int res = IoctlLocked(VIDIOC_DQBUF, &buffer);
617 if (res) {
618 if (errno == EAGAIN) {
619 // Expected failure.
620 return -EAGAIN;
621 } else {
622 // Unexpected failure.
623 HAL_LOGE("DQBUF fails: %s", strerror(errno));
624 return -ENODEV;
625 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700626 }
627
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700628 // Mark the buffer as no longer in flight.
629 {
630 std::lock_guard<std::mutex> guard(buffer_queue_lock_);
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800631 buffers_[buffer.index] = false;
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700632 }
633
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700634 // Now that we're done painting the buffer, we can unlock it.
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800635 res = gralloc_->unlock(&buffer);
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700636 if (res) {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700637 HAL_LOGE("Gralloc failed to unlock buffer after dequeueing.");
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700638 return res;
639 }
640
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800641 if (dequeued_index) {
642 *dequeued_index = buffer.index;
643 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700644 return 0;
645}
646
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700647} // namespace v4l2_camera_hal