blob: 24a6fafd5d6a8182c9e889d54ea07a8f7b8ff395 [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>
22#include <vector>
23
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070024#include <fcntl.h>
25#include <linux/videodev2.h>
26#include <sys/stat.h>
27#include <sys/types.h>
28
29#include <mutex>
30
31#include <nativehelper/ScopedFd.h>
32
Ari Hausman-Cohen3841a7f2016-07-19 17:27:52 -070033#include "common.h"
34#include "stream.h"
35#include "stream_format.h"
36#include "v4l2_gralloc.h"
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070037
38namespace v4l2_camera_hal {
39
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -070040const int32_t kStandardSizes[][2] = {
41 {1920, 1080}, {1280, 720}, {640, 480}, {320, 240}};
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070042
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -070043V4L2Wrapper* V4L2Wrapper::NewV4L2Wrapper(const std::string device_path) {
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -070044 std::unique_ptr<V4L2Gralloc> gralloc(V4L2Gralloc::NewV4L2Gralloc());
45 if (!gralloc) {
46 HAL_LOGE("Failed to initialize gralloc helper.");
47 return nullptr;
48 }
49
50 return new V4L2Wrapper(device_path, std::move(gralloc));
51}
52
53V4L2Wrapper::V4L2Wrapper(const std::string device_path,
54 std::unique_ptr<V4L2Gralloc> gralloc)
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -070055 : device_path_(std::move(device_path)),
56 gralloc_(std::move(gralloc)),
Ari Hausman-Cohenad6fe2b2016-11-16 10:48:07 -080057 connection_count_(0) {}
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070058
Ari Hausman-Cohenad6fe2b2016-11-16 10:48:07 -080059V4L2Wrapper::~V4L2Wrapper() {}
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070060
61int V4L2Wrapper::Connect() {
62 HAL_LOG_ENTER();
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070063 std::lock_guard<std::mutex> lock(connection_lock_);
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070064
65 if (connected()) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070066 HAL_LOGV("Camera device %s is already connected.", device_path_.c_str());
67 ++connection_count_;
68 return 0;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070069 }
70
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -080071 // Open in nonblocking mode (DQBUF may return EAGAIN).
72 int fd = TEMP_FAILURE_RETRY(open(device_path_.c_str(), O_RDWR | O_NONBLOCK));
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070073 if (fd < 0) {
74 HAL_LOGE("failed to open %s (%s)", device_path_.c_str(), strerror(errno));
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070075 return -ENODEV;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070076 }
77 device_fd_.reset(fd);
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070078 ++connection_count_;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070079
80 // Check if this connection has the extended control query capability.
81 v4l2_query_ext_ctrl query;
82 query.id = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND;
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070083 extended_query_supported_ = (IoctlLocked(VIDIOC_QUERY_EXT_CTRL, &query) == 0);
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070084
85 // TODO(b/29185945): confirm this is a supported device.
86 // This is checked by the HAL, but the device at device_path_ may
87 // not be the same one that was there when the HAL was loaded.
88 // (Alternatively, better hotplugging support may make this unecessary
89 // by disabling cameras that get disconnected and checking newly connected
90 // cameras, so Connect() is never called on an unsupported camera)
91 return 0;
92}
93
94void V4L2Wrapper::Disconnect() {
95 HAL_LOG_ENTER();
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070096 std::lock_guard<std::mutex> lock(connection_lock_);
97
98 if (connection_count_ == 0) {
99 // Not connected.
100 HAL_LOGE("Camera device %s is not connected, cannot disconnect.",
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -0700101 device_path_.c_str());
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700102 return;
103 }
104
105 --connection_count_;
106 if (connection_count_ > 0) {
107 HAL_LOGV("Disconnected from camera device %s. %d connections remain.",
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -0700108 device_path_.c_str());
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700109 return;
110 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700111
112 device_fd_.reset(); // Includes close().
113 format_.reset();
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700114 buffers_.clear();
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700115 // Closing the device releases all queued buffers back to the user.
116 gralloc_->unlockAllBuffers();
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700117}
118
119// Helper function. Should be used instead of ioctl throughout this class.
120template <typename T>
121int V4L2Wrapper::IoctlLocked(int request, T data) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700122 // Potentially called so many times logging entry is a bad idea.
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700123 std::lock_guard<std::mutex> lock(device_lock_);
124
125 if (!connected()) {
126 HAL_LOGE("Device %s not connected.", device_path_.c_str());
127 return -ENODEV;
128 }
129 return TEMP_FAILURE_RETRY(ioctl(device_fd_.get(), request, data));
130}
131
132int V4L2Wrapper::StreamOn() {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700133 if (!format_) {
134 HAL_LOGE("Stream format must be set before turning on stream.");
135 return -EINVAL;
136 }
137
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700138 int32_t type = format_->type();
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700139 if (IoctlLocked(VIDIOC_STREAMON, &type) < 0) {
140 HAL_LOGE("STREAMON fails: %s", strerror(errno));
141 return -ENODEV;
142 }
143
Ari Hausman-Cohenad6fe2b2016-11-16 10:48:07 -0800144 HAL_LOGV("Stream turned on.");
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700145 return 0;
146}
147
148int V4L2Wrapper::StreamOff() {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700149 if (!format_) {
Ari Hausman-Cohenad6fe2b2016-11-16 10:48:07 -0800150 // Can't have turned on the stream without format being set,
Ari Hausman-Cohen71cb8742016-09-22 11:12:00 -0700151 // so nothing to turn off here.
152 return 0;
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700153 }
154
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700155 int32_t type = format_->type();
156 int res = IoctlLocked(VIDIOC_STREAMOFF, &type);
157 // Calling STREAMOFF releases all queued buffers back to the user.
158 int gralloc_res = gralloc_->unlockAllBuffers();
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800159 // No buffers in flight.
160 for (size_t i = 0; i < buffers_.size(); ++i) {
161 buffers_[i] = false;
162 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700163 if (res < 0) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700164 HAL_LOGE("STREAMOFF fails: %s", strerror(errno));
165 return -ENODEV;
166 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700167 if (gralloc_res < 0) {
168 HAL_LOGE("Failed to unlock all buffers after turning stream off.");
169 return gralloc_res;
170 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700171
Ari Hausman-Cohenad6fe2b2016-11-16 10:48:07 -0800172 HAL_LOGV("Stream turned off.");
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700173 return 0;
174}
175
176int V4L2Wrapper::QueryControl(uint32_t control_id,
177 v4l2_query_ext_ctrl* result) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700178 int res;
179
180 memset(result, 0, sizeof(*result));
181
182 if (extended_query_supported_) {
183 result->id = control_id;
184 res = IoctlLocked(VIDIOC_QUERY_EXT_CTRL, result);
185 // Assuming the operation was supported (not ENOTTY), no more to do.
186 if (errno != ENOTTY) {
187 if (res) {
188 HAL_LOGE("QUERY_EXT_CTRL fails: %s", strerror(errno));
189 return -ENODEV;
190 }
191 return 0;
192 }
193 }
194
195 // Extended control querying not supported, fall back to basic control query.
196 v4l2_queryctrl query;
197 query.id = control_id;
198 if (IoctlLocked(VIDIOC_QUERYCTRL, &query)) {
199 HAL_LOGE("QUERYCTRL fails: %s", strerror(errno));
200 return -ENODEV;
201 }
202
203 // Convert the basic result to the extended result.
204 result->id = query.id;
205 result->type = query.type;
206 memcpy(result->name, query.name, sizeof(query.name));
207 result->minimum = query.minimum;
208 if (query.type == V4L2_CTRL_TYPE_BITMASK) {
209 // According to the V4L2 documentation, when type is BITMASK,
210 // max and default should be interpreted as __u32. Practically,
211 // this means the conversion from 32 bit to 64 will pad with 0s not 1s.
212 result->maximum = static_cast<uint32_t>(query.maximum);
213 result->default_value = static_cast<uint32_t>(query.default_value);
214 } else {
215 result->maximum = query.maximum;
216 result->default_value = query.default_value;
217 }
218 result->step = static_cast<uint32_t>(query.step);
219 result->flags = query.flags;
220 result->elems = 1;
221 switch (result->type) {
222 case V4L2_CTRL_TYPE_INTEGER64:
223 result->elem_size = sizeof(int64_t);
224 break;
225 case V4L2_CTRL_TYPE_STRING:
226 result->elem_size = result->maximum + 1;
227 break;
228 default:
229 result->elem_size = sizeof(int32_t);
230 break;
231 }
232
233 return 0;
234}
235
236int V4L2Wrapper::GetControl(uint32_t control_id, int32_t* value) {
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700237 // For extended controls (any control class other than "user"),
238 // G_EXT_CTRL must be used instead of G_CTRL.
239 if (V4L2_CTRL_ID2CLASS(control_id) != V4L2_CTRL_CLASS_USER) {
240 v4l2_ext_control control;
241 v4l2_ext_controls controls;
242 memset(&control, 0, sizeof(control));
243 memset(&controls, 0, sizeof(controls));
244
245 control.id = control_id;
246 controls.ctrl_class = V4L2_CTRL_ID2CLASS(control_id);
247 controls.count = 1;
248 controls.controls = &control;
249
250 if (IoctlLocked(VIDIOC_G_EXT_CTRLS, &controls) < 0) {
251 HAL_LOGE("G_EXT_CTRLS fails: %s", strerror(errno));
252 return -ENODEV;
253 }
254 *value = control.value;
255 } else {
256 v4l2_control control{control_id, 0};
257 if (IoctlLocked(VIDIOC_G_CTRL, &control) < 0) {
258 HAL_LOGE("G_CTRL fails: %s", strerror(errno));
259 return -ENODEV;
260 }
261 *value = control.value;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700262 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700263 return 0;
264}
265
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700266int V4L2Wrapper::SetControl(uint32_t control_id,
267 int32_t desired,
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700268 int32_t* result) {
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700269 int32_t result_value = 0;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700270
Ari Hausman-Cohen99f3ea02016-08-02 10:47:07 -0700271 // TODO(b/29334616): When async, this may need to check if the stream
272 // is on, and if so, lock it off while setting format. Need to look
273 // into if V4L2 supports adjusting controls while the stream is on.
274
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700275 // For extended controls (any control class other than "user"),
276 // S_EXT_CTRL must be used instead of S_CTRL.
277 if (V4L2_CTRL_ID2CLASS(control_id) != V4L2_CTRL_CLASS_USER) {
278 v4l2_ext_control control;
279 v4l2_ext_controls controls;
280 memset(&control, 0, sizeof(control));
281 memset(&controls, 0, sizeof(controls));
282
283 control.id = control_id;
284 control.value = desired;
285 controls.ctrl_class = V4L2_CTRL_ID2CLASS(control_id);
286 controls.count = 1;
287 controls.controls = &control;
288
289 if (IoctlLocked(VIDIOC_S_EXT_CTRLS, &controls) < 0) {
290 HAL_LOGE("S_EXT_CTRLS fails: %s", strerror(errno));
291 return -ENODEV;
292 }
293 result_value = control.value;
294 } else {
295 v4l2_control control{control_id, desired};
296 if (IoctlLocked(VIDIOC_S_CTRL, &control) < 0) {
297 HAL_LOGE("S_CTRL fails: %s", strerror(errno));
298 return -ENODEV;
299 }
300 result_value = control.value;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700301 }
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700302
Ari Hausman-Cohen99f3ea02016-08-02 10:47:07 -0700303 // If the caller wants to know the result, pass it back.
304 if (result != nullptr) {
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700305 *result = result_value;
Ari Hausman-Cohen99f3ea02016-08-02 10:47:07 -0700306 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700307 return 0;
308}
309
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700310int V4L2Wrapper::GetFormats(std::set<uint32_t>* v4l2_formats) {
311 HAL_LOG_ENTER();
312
313 v4l2_fmtdesc format_query;
314 memset(&format_query, 0, sizeof(format_query));
315 // TODO(b/30000211): multiplanar support.
316 format_query.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
317 while (IoctlLocked(VIDIOC_ENUM_FMT, &format_query) >= 0) {
318 v4l2_formats->insert(format_query.pixelformat);
319 ++format_query.index;
320 }
321
322 if (errno != EINVAL) {
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700323 HAL_LOGE(
324 "ENUM_FMT fails at index %d: %s", format_query.index, strerror(errno));
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700325 return -ENODEV;
326 }
327 return 0;
328}
329
330int V4L2Wrapper::GetFormatFrameSizes(uint32_t v4l2_format,
331 std::set<std::array<int32_t, 2>>* sizes) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700332 v4l2_frmsizeenum size_query;
333 memset(&size_query, 0, sizeof(size_query));
334 size_query.pixel_format = v4l2_format;
335 if (IoctlLocked(VIDIOC_ENUM_FRAMESIZES, &size_query) < 0) {
336 HAL_LOGE("ENUM_FRAMESIZES failed: %s", strerror(errno));
337 return -ENODEV;
338 }
339 if (size_query.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
340 // Discrete: enumerate all sizes using VIDIOC_ENUM_FRAMESIZES.
341 // Assuming that a driver with discrete frame sizes has a reasonable number
342 // of them.
343 do {
344 sizes->insert({{{static_cast<int32_t>(size_query.discrete.width),
345 static_cast<int32_t>(size_query.discrete.height)}}});
346 ++size_query.index;
347 } while (IoctlLocked(VIDIOC_ENUM_FRAMESIZES, &size_query) >= 0);
348 if (errno != EINVAL) {
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700349 HAL_LOGE("ENUM_FRAMESIZES fails at index %d: %s",
350 size_query.index,
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700351 strerror(errno));
352 return -ENODEV;
353 }
354 } else {
355 // Continuous/Step-wise: based on the stepwise struct returned by the query.
356 // Fully listing all possible sizes, with large enough range/small enough
357 // step size, may produce far too many potential sizes. Instead, find the
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800358 // closest to a set of standard sizes.
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -0700359 for (const auto size : kStandardSizes) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700360 // Find the closest size, rounding up.
361 uint32_t desired_width = size[0];
362 uint32_t desired_height = size[1];
363 if (desired_width < size_query.stepwise.min_width ||
364 desired_height < size_query.stepwise.min_height) {
365 HAL_LOGV("Standard size %u x %u is too small for format %d",
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700366 desired_width,
367 desired_height,
368 v4l2_format);
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700369 continue;
370 } else if (desired_width > size_query.stepwise.max_width &&
371 desired_height > size_query.stepwise.max_height) {
372 HAL_LOGV("Standard size %u x %u is too big for format %d",
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700373 desired_width,
374 desired_height,
375 v4l2_format);
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700376 continue;
377 }
378
379 // Round up.
380 uint32_t width_steps = (desired_width - size_query.stepwise.min_width +
381 size_query.stepwise.step_width - 1) /
382 size_query.stepwise.step_width;
383 uint32_t height_steps = (desired_height - size_query.stepwise.min_height +
384 size_query.stepwise.step_height - 1) /
385 size_query.stepwise.step_height;
386 sizes->insert(
387 {{{static_cast<int32_t>(size_query.stepwise.min_width +
388 width_steps * size_query.stepwise.step_width),
389 static_cast<int32_t>(size_query.stepwise.min_height +
390 height_steps *
391 size_query.stepwise.step_height)}}});
392 }
393 }
394 return 0;
395}
396
397// Converts a v4l2_fract with units of seconds to an int64_t with units of ns.
398inline int64_t FractToNs(const v4l2_fract& fract) {
399 return (1000000000LL * fract.numerator) / fract.denominator;
400}
401
402int V4L2Wrapper::GetFormatFrameDurationRange(
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700403 uint32_t v4l2_format,
404 const std::array<int32_t, 2>& size,
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700405 std::array<int64_t, 2>* duration_range) {
406 // Potentially called so many times logging entry is a bad idea.
407
408 v4l2_frmivalenum duration_query;
409 memset(&duration_query, 0, sizeof(duration_query));
410 duration_query.pixel_format = v4l2_format;
411 duration_query.width = size[0];
412 duration_query.height = size[1];
413 if (IoctlLocked(VIDIOC_ENUM_FRAMEINTERVALS, &duration_query) < 0) {
414 HAL_LOGE("ENUM_FRAMEINTERVALS failed: %s", strerror(errno));
415 return -ENODEV;
416 }
417
418 int64_t min = std::numeric_limits<int64_t>::max();
419 int64_t max = std::numeric_limits<int64_t>::min();
420 if (duration_query.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
421 // Discrete: enumerate all durations using VIDIOC_ENUM_FRAMEINTERVALS.
422 do {
423 min = std::min(min, FractToNs(duration_query.discrete));
424 max = std::max(max, FractToNs(duration_query.discrete));
425 ++duration_query.index;
426 } while (IoctlLocked(VIDIOC_ENUM_FRAMEINTERVALS, &duration_query) >= 0);
427 if (errno != EINVAL) {
428 HAL_LOGE("ENUM_FRAMEINTERVALS fails at index %d: %s",
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700429 duration_query.index,
430 strerror(errno));
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700431 return -ENODEV;
432 }
433 } else {
434 // Continuous/Step-wise: simply convert the given min and max.
435 min = FractToNs(duration_query.stepwise.min);
436 max = FractToNs(duration_query.stepwise.max);
437 }
438 (*duration_range)[0] = min;
439 (*duration_range)[1] = max;
440 return 0;
441}
442
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700443int V4L2Wrapper::SetFormat(const default_camera_hal::Stream& stream,
444 uint32_t* result_max_buffers) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700445 HAL_LOG_ENTER();
446
447 // Should be checked earlier; sanity check.
448 if (stream.isInputType()) {
449 HAL_LOGE("Input streams not supported.");
450 return -EINVAL;
451 }
452
453 StreamFormat desired_format(stream);
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700454 if (format_ && desired_format == *format_) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700455 HAL_LOGV("Already in correct format, skipping format setting.");
456 return 0;
457 }
458
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800459 // Not in the correct format, set the new one.
460
461 if (format_) {
462 // If we had an old format, first request 0 buffers to inform the device
463 // we're no longer using any previously "allocated" buffers from the old
464 // format. This seems like it shouldn't be necessary for USERPTR memory,
465 // and/or should happen from turning the stream off, but the driver
466 // complained. May be a driver issue, or may be intended behavior.
467 int res = RequestBuffers(0);
468 if (res) {
469 return res;
470 }
471 }
472
473 // Set the camera to the new format.
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700474 v4l2_format new_format;
475 desired_format.FillFormatRequest(&new_format);
476 // TODO(b/29334616): When async, this will need to check if the stream
477 // is on, and if so, lock it off while setting format.
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800478
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700479 if (IoctlLocked(VIDIOC_S_FMT, &new_format) < 0) {
480 HAL_LOGE("S_FMT failed: %s", strerror(errno));
481 return -ENODEV;
482 }
483
484 // Check that the driver actually set to the requested values.
485 if (desired_format != new_format) {
486 HAL_LOGE("Device doesn't support desired stream configuration.");
487 return -EINVAL;
488 }
489
490 // Keep track of our new format.
491 format_.reset(new StreamFormat(new_format));
492
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800493 // Format changed, request new buffers.
494 int res = RequestBuffers(1);
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700495 if (res) {
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800496 HAL_LOGE("Requesting buffers for new format failed.");
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700497 return res;
498 }
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700499 *result_max_buffers = buffers_.size();
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700500 return 0;
501}
502
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800503int V4L2Wrapper::RequestBuffers(uint32_t num_requested) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700504 v4l2_requestbuffers req_buffers;
505 memset(&req_buffers, 0, sizeof(req_buffers));
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700506 req_buffers.type = format_->type();
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700507 req_buffers.memory = V4L2_MEMORY_USERPTR;
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800508 req_buffers.count = num_requested;
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700509
510 int res = IoctlLocked(VIDIOC_REQBUFS, &req_buffers);
511 // Calling REQBUFS releases all queued buffers back to the user.
512 int gralloc_res = gralloc_->unlockAllBuffers();
513 if (res < 0) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700514 HAL_LOGE("REQBUFS failed: %s", strerror(errno));
515 return -ENODEV;
516 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700517 if (gralloc_res < 0) {
518 HAL_LOGE("Failed to unlock all buffers when setting up new buffers.");
519 return gralloc_res;
520 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700521
522 // V4L2 will set req_buffers.count to a number of buffers it can handle.
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800523 if (num_requested > 0 && req_buffers.count < 1) {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700524 HAL_LOGE("REQBUFS claims it can't handle any buffers.");
525 return -ENODEV;
526 }
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700527 buffers_.resize(req_buffers.count, false);
528
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700529 return 0;
530}
531
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800532int V4L2Wrapper::EnqueueBuffer(const camera3_stream_buffer_t* camera_buffer,
533 uint32_t* enqueued_index) {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700534 if (!format_) {
535 HAL_LOGE("Stream format must be set before enqueuing buffers.");
536 return -ENODEV;
537 }
538
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700539 // Find a free buffer index. Could use some sort of persistent hinting
540 // here to improve expected efficiency, but buffers_.size() is expected
541 // to be low enough (<10 experimentally) that it's not worth it.
542 int index = -1;
543 {
544 std::lock_guard<std::mutex> guard(buffer_queue_lock_);
545 for (int i = 0; i < buffers_.size(); ++i) {
546 if (!buffers_[i]) {
547 index = i;
548 break;
549 }
550 }
551 }
552 if (index < 0) {
553 // Note: The HAL should be tracking the number of buffers in flight
554 // for each stream, and should never overflow the device.
555 HAL_LOGE("Cannot enqueue buffer: stream is already full.");
556 return -ENODEV;
557 }
558
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700559 // Set up a v4l2 buffer struct.
560 v4l2_buffer device_buffer;
561 memset(&device_buffer, 0, sizeof(device_buffer));
562 device_buffer.type = format_->type();
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700563 device_buffer.index = index;
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700564
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700565 // Use QUERYBUF to ensure our buffer/device is in good shape,
566 // and fill out remaining fields.
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700567 if (IoctlLocked(VIDIOC_QUERYBUF, &device_buffer) < 0) {
568 HAL_LOGE("QUERYBUF fails: %s", strerror(errno));
569 return -ENODEV;
570 }
571
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700572 // Lock the buffer for writing (fills in the user pointer field).
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700573 int res =
574 gralloc_->lock(camera_buffer, format_->bytes_per_line(), &device_buffer);
575 if (res) {
576 HAL_LOGE("Gralloc failed to lock buffer.");
577 return res;
578 }
579 if (IoctlLocked(VIDIOC_QBUF, &device_buffer) < 0) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700580 HAL_LOGE("QBUF fails: %s", strerror(errno));
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700581 gralloc_->unlock(&device_buffer);
582 return -ENODEV;
583 }
584
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700585 // Mark the buffer as in flight.
586 std::lock_guard<std::mutex> guard(buffer_queue_lock_);
587 buffers_[index] = true;
588
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800589 if (enqueued_index) {
590 *enqueued_index = index;
591 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700592 return 0;
593}
594
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800595int V4L2Wrapper::DequeueBuffer(uint32_t* dequeued_index) {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700596 if (!format_) {
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800597 HAL_LOGV(
598 "Format not set, so stream can't be on, "
599 "so no buffers available for dequeueing");
600 return -EAGAIN;
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700601 }
602
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800603 v4l2_buffer buffer;
604 memset(&buffer, 0, sizeof(buffer));
605 buffer.type = format_->type();
606 buffer.memory = V4L2_MEMORY_USERPTR;
607 int res = IoctlLocked(VIDIOC_DQBUF, &buffer);
608 if (res) {
609 if (errno == EAGAIN) {
610 // Expected failure.
611 return -EAGAIN;
612 } else {
613 // Unexpected failure.
614 HAL_LOGE("DQBUF fails: %s", strerror(errno));
615 return -ENODEV;
616 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700617 }
618
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700619 // Mark the buffer as no longer in flight.
620 {
621 std::lock_guard<std::mutex> guard(buffer_queue_lock_);
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800622 buffers_[buffer.index] = false;
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700623 }
624
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700625 // Now that we're done painting the buffer, we can unlock it.
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800626 res = gralloc_->unlock(&buffer);
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700627 if (res) {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700628 HAL_LOGE("Gralloc failed to unlock buffer after dequeueing.");
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700629 return res;
630 }
631
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800632 if (dequeued_index) {
633 *dequeued_index = buffer.index;
634 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700635 return 0;
636}
637
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700638} // namespace v4l2_camera_hal