blob: 64115fb5755ca22a50fd174e1290c0536ceaf564 [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"
Ari Hausman-Cohen3841a7f2016-07-19 17:27:52 -070034#include "stream_format.h"
35#include "v4l2_gralloc.h"
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070036
37namespace v4l2_camera_hal {
38
Ari Hausman-Cohenc9bfa592016-11-29 18:37:18 -080039const int32_t kStandardSizes[][2] = {{640, 480}, {320, 240}};
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070040
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -070041V4L2Wrapper* V4L2Wrapper::NewV4L2Wrapper(const std::string device_path) {
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -070042 std::unique_ptr<V4L2Gralloc> gralloc(V4L2Gralloc::NewV4L2Gralloc());
43 if (!gralloc) {
44 HAL_LOGE("Failed to initialize gralloc helper.");
45 return nullptr;
46 }
47
48 return new V4L2Wrapper(device_path, std::move(gralloc));
49}
50
51V4L2Wrapper::V4L2Wrapper(const std::string device_path,
52 std::unique_ptr<V4L2Gralloc> gralloc)
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -070053 : device_path_(std::move(device_path)),
54 gralloc_(std::move(gralloc)),
Ari Hausman-Cohenad6fe2b2016-11-16 10:48:07 -080055 connection_count_(0) {}
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070056
Ari Hausman-Cohenad6fe2b2016-11-16 10:48:07 -080057V4L2Wrapper::~V4L2Wrapper() {}
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070058
59int V4L2Wrapper::Connect() {
60 HAL_LOG_ENTER();
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070061 std::lock_guard<std::mutex> lock(connection_lock_);
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070062
63 if (connected()) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070064 HAL_LOGV("Camera device %s is already connected.", device_path_.c_str());
65 ++connection_count_;
66 return 0;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070067 }
68
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -080069 // Open in nonblocking mode (DQBUF may return EAGAIN).
70 int fd = TEMP_FAILURE_RETRY(open(device_path_.c_str(), O_RDWR | O_NONBLOCK));
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070071 if (fd < 0) {
72 HAL_LOGE("failed to open %s (%s)", device_path_.c_str(), strerror(errno));
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070073 return -ENODEV;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070074 }
75 device_fd_.reset(fd);
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070076 ++connection_count_;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070077
78 // Check if this connection has the extended control query capability.
79 v4l2_query_ext_ctrl query;
80 query.id = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND;
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070081 extended_query_supported_ = (IoctlLocked(VIDIOC_QUERY_EXT_CTRL, &query) == 0);
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070082
83 // TODO(b/29185945): confirm this is a supported device.
84 // This is checked by the HAL, but the device at device_path_ may
85 // not be the same one that was there when the HAL was loaded.
86 // (Alternatively, better hotplugging support may make this unecessary
87 // by disabling cameras that get disconnected and checking newly connected
88 // cameras, so Connect() is never called on an unsupported camera)
89 return 0;
90}
91
92void V4L2Wrapper::Disconnect() {
93 HAL_LOG_ENTER();
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070094 std::lock_guard<std::mutex> lock(connection_lock_);
95
96 if (connection_count_ == 0) {
97 // Not connected.
98 HAL_LOGE("Camera device %s is not connected, cannot disconnect.",
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -070099 device_path_.c_str());
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700100 return;
101 }
102
103 --connection_count_;
104 if (connection_count_ > 0) {
105 HAL_LOGV("Disconnected from camera device %s. %d connections remain.",
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -0700106 device_path_.c_str());
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700107 return;
108 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700109
110 device_fd_.reset(); // Includes close().
111 format_.reset();
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700112 buffers_.clear();
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700113 // Closing the device releases all queued buffers back to the user.
114 gralloc_->unlockAllBuffers();
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700115}
116
117// Helper function. Should be used instead of ioctl throughout this class.
118template <typename T>
119int V4L2Wrapper::IoctlLocked(int request, T data) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700120 // Potentially called so many times logging entry is a bad idea.
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700121 std::lock_guard<std::mutex> lock(device_lock_);
122
123 if (!connected()) {
124 HAL_LOGE("Device %s not connected.", device_path_.c_str());
125 return -ENODEV;
126 }
127 return TEMP_FAILURE_RETRY(ioctl(device_fd_.get(), request, data));
128}
129
130int V4L2Wrapper::StreamOn() {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700131 if (!format_) {
132 HAL_LOGE("Stream format must be set before turning on stream.");
133 return -EINVAL;
134 }
135
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700136 int32_t type = format_->type();
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700137 if (IoctlLocked(VIDIOC_STREAMON, &type) < 0) {
138 HAL_LOGE("STREAMON fails: %s", strerror(errno));
139 return -ENODEV;
140 }
141
Ari Hausman-Cohenad6fe2b2016-11-16 10:48:07 -0800142 HAL_LOGV("Stream turned on.");
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700143 return 0;
144}
145
146int V4L2Wrapper::StreamOff() {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700147 if (!format_) {
Ari Hausman-Cohenad6fe2b2016-11-16 10:48:07 -0800148 // Can't have turned on the stream without format being set,
Ari Hausman-Cohen71cb8742016-09-22 11:12:00 -0700149 // so nothing to turn off here.
150 return 0;
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700151 }
152
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700153 int32_t type = format_->type();
154 int res = IoctlLocked(VIDIOC_STREAMOFF, &type);
155 // Calling STREAMOFF releases all queued buffers back to the user.
156 int gralloc_res = gralloc_->unlockAllBuffers();
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800157 // No buffers in flight.
158 for (size_t i = 0; i < buffers_.size(); ++i) {
159 buffers_[i] = false;
160 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700161 if (res < 0) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700162 HAL_LOGE("STREAMOFF fails: %s", strerror(errno));
163 return -ENODEV;
164 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700165 if (gralloc_res < 0) {
166 HAL_LOGE("Failed to unlock all buffers after turning stream off.");
167 return gralloc_res;
168 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700169
Ari Hausman-Cohenad6fe2b2016-11-16 10:48:07 -0800170 HAL_LOGV("Stream turned off.");
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700171 return 0;
172}
173
174int V4L2Wrapper::QueryControl(uint32_t control_id,
175 v4l2_query_ext_ctrl* result) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700176 int res;
177
178 memset(result, 0, sizeof(*result));
179
180 if (extended_query_supported_) {
181 result->id = control_id;
182 res = IoctlLocked(VIDIOC_QUERY_EXT_CTRL, result);
183 // Assuming the operation was supported (not ENOTTY), no more to do.
184 if (errno != ENOTTY) {
185 if (res) {
186 HAL_LOGE("QUERY_EXT_CTRL fails: %s", strerror(errno));
187 return -ENODEV;
188 }
189 return 0;
190 }
191 }
192
193 // Extended control querying not supported, fall back to basic control query.
194 v4l2_queryctrl query;
195 query.id = control_id;
196 if (IoctlLocked(VIDIOC_QUERYCTRL, &query)) {
197 HAL_LOGE("QUERYCTRL fails: %s", strerror(errno));
198 return -ENODEV;
199 }
200
201 // Convert the basic result to the extended result.
202 result->id = query.id;
203 result->type = query.type;
204 memcpy(result->name, query.name, sizeof(query.name));
205 result->minimum = query.minimum;
206 if (query.type == V4L2_CTRL_TYPE_BITMASK) {
207 // According to the V4L2 documentation, when type is BITMASK,
208 // max and default should be interpreted as __u32. Practically,
209 // this means the conversion from 32 bit to 64 will pad with 0s not 1s.
210 result->maximum = static_cast<uint32_t>(query.maximum);
211 result->default_value = static_cast<uint32_t>(query.default_value);
212 } else {
213 result->maximum = query.maximum;
214 result->default_value = query.default_value;
215 }
216 result->step = static_cast<uint32_t>(query.step);
217 result->flags = query.flags;
218 result->elems = 1;
219 switch (result->type) {
220 case V4L2_CTRL_TYPE_INTEGER64:
221 result->elem_size = sizeof(int64_t);
222 break;
223 case V4L2_CTRL_TYPE_STRING:
224 result->elem_size = result->maximum + 1;
225 break;
226 default:
227 result->elem_size = sizeof(int32_t);
228 break;
229 }
230
231 return 0;
232}
233
234int V4L2Wrapper::GetControl(uint32_t control_id, int32_t* value) {
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700235 // For extended controls (any control class other than "user"),
236 // G_EXT_CTRL must be used instead of G_CTRL.
237 if (V4L2_CTRL_ID2CLASS(control_id) != V4L2_CTRL_CLASS_USER) {
238 v4l2_ext_control control;
239 v4l2_ext_controls controls;
240 memset(&control, 0, sizeof(control));
241 memset(&controls, 0, sizeof(controls));
242
243 control.id = control_id;
244 controls.ctrl_class = V4L2_CTRL_ID2CLASS(control_id);
245 controls.count = 1;
246 controls.controls = &control;
247
248 if (IoctlLocked(VIDIOC_G_EXT_CTRLS, &controls) < 0) {
249 HAL_LOGE("G_EXT_CTRLS fails: %s", strerror(errno));
250 return -ENODEV;
251 }
252 *value = control.value;
253 } else {
254 v4l2_control control{control_id, 0};
255 if (IoctlLocked(VIDIOC_G_CTRL, &control) < 0) {
256 HAL_LOGE("G_CTRL fails: %s", strerror(errno));
257 return -ENODEV;
258 }
259 *value = control.value;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700260 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700261 return 0;
262}
263
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700264int V4L2Wrapper::SetControl(uint32_t control_id,
265 int32_t desired,
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700266 int32_t* result) {
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700267 int32_t result_value = 0;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700268
Ari Hausman-Cohen99f3ea02016-08-02 10:47:07 -0700269 // TODO(b/29334616): When async, this may need to check if the stream
270 // is on, and if so, lock it off while setting format. Need to look
271 // into if V4L2 supports adjusting controls while the stream is on.
272
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700273 // For extended controls (any control class other than "user"),
274 // S_EXT_CTRL must be used instead of S_CTRL.
275 if (V4L2_CTRL_ID2CLASS(control_id) != V4L2_CTRL_CLASS_USER) {
276 v4l2_ext_control control;
277 v4l2_ext_controls controls;
278 memset(&control, 0, sizeof(control));
279 memset(&controls, 0, sizeof(controls));
280
281 control.id = control_id;
282 control.value = desired;
283 controls.ctrl_class = V4L2_CTRL_ID2CLASS(control_id);
284 controls.count = 1;
285 controls.controls = &control;
286
287 if (IoctlLocked(VIDIOC_S_EXT_CTRLS, &controls) < 0) {
288 HAL_LOGE("S_EXT_CTRLS fails: %s", strerror(errno));
289 return -ENODEV;
290 }
291 result_value = control.value;
292 } else {
293 v4l2_control control{control_id, desired};
294 if (IoctlLocked(VIDIOC_S_CTRL, &control) < 0) {
295 HAL_LOGE("S_CTRL fails: %s", strerror(errno));
296 return -ENODEV;
297 }
298 result_value = control.value;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700299 }
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700300
Ari Hausman-Cohen99f3ea02016-08-02 10:47:07 -0700301 // If the caller wants to know the result, pass it back.
302 if (result != nullptr) {
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700303 *result = result_value;
Ari Hausman-Cohen99f3ea02016-08-02 10:47:07 -0700304 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700305 return 0;
306}
307
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700308int V4L2Wrapper::GetFormats(std::set<uint32_t>* v4l2_formats) {
309 HAL_LOG_ENTER();
310
311 v4l2_fmtdesc format_query;
312 memset(&format_query, 0, sizeof(format_query));
313 // TODO(b/30000211): multiplanar support.
314 format_query.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
315 while (IoctlLocked(VIDIOC_ENUM_FMT, &format_query) >= 0) {
316 v4l2_formats->insert(format_query.pixelformat);
317 ++format_query.index;
318 }
319
320 if (errno != EINVAL) {
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700321 HAL_LOGE(
322 "ENUM_FMT fails at index %d: %s", format_query.index, strerror(errno));
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700323 return -ENODEV;
324 }
325 return 0;
326}
327
328int V4L2Wrapper::GetFormatFrameSizes(uint32_t v4l2_format,
329 std::set<std::array<int32_t, 2>>* sizes) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700330 v4l2_frmsizeenum size_query;
331 memset(&size_query, 0, sizeof(size_query));
332 size_query.pixel_format = v4l2_format;
333 if (IoctlLocked(VIDIOC_ENUM_FRAMESIZES, &size_query) < 0) {
334 HAL_LOGE("ENUM_FRAMESIZES failed: %s", strerror(errno));
335 return -ENODEV;
336 }
337 if (size_query.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
338 // Discrete: enumerate all sizes using VIDIOC_ENUM_FRAMESIZES.
339 // Assuming that a driver with discrete frame sizes has a reasonable number
340 // of them.
341 do {
342 sizes->insert({{{static_cast<int32_t>(size_query.discrete.width),
343 static_cast<int32_t>(size_query.discrete.height)}}});
344 ++size_query.index;
345 } while (IoctlLocked(VIDIOC_ENUM_FRAMESIZES, &size_query) >= 0);
346 if (errno != EINVAL) {
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700347 HAL_LOGE("ENUM_FRAMESIZES fails at index %d: %s",
348 size_query.index,
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700349 strerror(errno));
350 return -ENODEV;
351 }
352 } else {
353 // Continuous/Step-wise: based on the stepwise struct returned by the query.
354 // Fully listing all possible sizes, with large enough range/small enough
355 // step size, may produce far too many potential sizes. Instead, find the
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800356 // closest to a set of standard sizes.
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -0700357 for (const auto size : kStandardSizes) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700358 // Find the closest size, rounding up.
359 uint32_t desired_width = size[0];
360 uint32_t desired_height = size[1];
361 if (desired_width < size_query.stepwise.min_width ||
362 desired_height < size_query.stepwise.min_height) {
363 HAL_LOGV("Standard size %u x %u is too small for format %d",
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700364 desired_width,
365 desired_height,
366 v4l2_format);
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700367 continue;
368 } else if (desired_width > size_query.stepwise.max_width &&
369 desired_height > size_query.stepwise.max_height) {
370 HAL_LOGV("Standard size %u x %u is too big for format %d",
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700371 desired_width,
372 desired_height,
373 v4l2_format);
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700374 continue;
375 }
376
377 // Round up.
378 uint32_t width_steps = (desired_width - size_query.stepwise.min_width +
379 size_query.stepwise.step_width - 1) /
380 size_query.stepwise.step_width;
381 uint32_t height_steps = (desired_height - size_query.stepwise.min_height +
382 size_query.stepwise.step_height - 1) /
383 size_query.stepwise.step_height;
384 sizes->insert(
385 {{{static_cast<int32_t>(size_query.stepwise.min_width +
386 width_steps * size_query.stepwise.step_width),
387 static_cast<int32_t>(size_query.stepwise.min_height +
388 height_steps *
389 size_query.stepwise.step_height)}}});
390 }
391 }
392 return 0;
393}
394
395// Converts a v4l2_fract with units of seconds to an int64_t with units of ns.
396inline int64_t FractToNs(const v4l2_fract& fract) {
397 return (1000000000LL * fract.numerator) / fract.denominator;
398}
399
400int V4L2Wrapper::GetFormatFrameDurationRange(
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700401 uint32_t v4l2_format,
402 const std::array<int32_t, 2>& size,
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700403 std::array<int64_t, 2>* duration_range) {
404 // Potentially called so many times logging entry is a bad idea.
405
406 v4l2_frmivalenum duration_query;
407 memset(&duration_query, 0, sizeof(duration_query));
408 duration_query.pixel_format = v4l2_format;
409 duration_query.width = size[0];
410 duration_query.height = size[1];
411 if (IoctlLocked(VIDIOC_ENUM_FRAMEINTERVALS, &duration_query) < 0) {
412 HAL_LOGE("ENUM_FRAMEINTERVALS failed: %s", strerror(errno));
413 return -ENODEV;
414 }
415
416 int64_t min = std::numeric_limits<int64_t>::max();
417 int64_t max = std::numeric_limits<int64_t>::min();
418 if (duration_query.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
419 // Discrete: enumerate all durations using VIDIOC_ENUM_FRAMEINTERVALS.
420 do {
421 min = std::min(min, FractToNs(duration_query.discrete));
422 max = std::max(max, FractToNs(duration_query.discrete));
423 ++duration_query.index;
424 } while (IoctlLocked(VIDIOC_ENUM_FRAMEINTERVALS, &duration_query) >= 0);
425 if (errno != EINVAL) {
426 HAL_LOGE("ENUM_FRAMEINTERVALS fails at index %d: %s",
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700427 duration_query.index,
428 strerror(errno));
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700429 return -ENODEV;
430 }
431 } else {
432 // Continuous/Step-wise: simply convert the given min and max.
433 min = FractToNs(duration_query.stepwise.min);
434 max = FractToNs(duration_query.stepwise.max);
435 }
436 (*duration_range)[0] = min;
437 (*duration_range)[1] = max;
438 return 0;
439}
440
Ari Hausman-Cohenef523102016-11-21 17:02:01 -0800441int V4L2Wrapper::SetFormat(const StreamFormat& desired_format,
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700442 uint32_t* result_max_buffers) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700443 HAL_LOG_ENTER();
444
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700445 if (format_ && desired_format == *format_) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700446 HAL_LOGV("Already in correct format, skipping format setting.");
Ari Hausman-Cohena5c9bfd2016-11-18 14:57:07 -0800447 *result_max_buffers = buffers_.size();
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700448 return 0;
449 }
450
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800451 // Not in the correct format, set the new one.
452
453 if (format_) {
454 // If we had an old format, first request 0 buffers to inform the device
455 // we're no longer using any previously "allocated" buffers from the old
456 // format. This seems like it shouldn't be necessary for USERPTR memory,
457 // and/or should happen from turning the stream off, but the driver
458 // complained. May be a driver issue, or may be intended behavior.
459 int res = RequestBuffers(0);
460 if (res) {
461 return res;
462 }
463 }
464
465 // Set the camera to the new format.
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700466 v4l2_format new_format;
467 desired_format.FillFormatRequest(&new_format);
468 // TODO(b/29334616): When async, this will need to check if the stream
469 // is on, and if so, lock it off while setting format.
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800470
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700471 if (IoctlLocked(VIDIOC_S_FMT, &new_format) < 0) {
472 HAL_LOGE("S_FMT failed: %s", strerror(errno));
473 return -ENODEV;
474 }
475
476 // Check that the driver actually set to the requested values.
477 if (desired_format != new_format) {
478 HAL_LOGE("Device doesn't support desired stream configuration.");
479 return -EINVAL;
480 }
481
482 // Keep track of our new format.
483 format_.reset(new StreamFormat(new_format));
484
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800485 // Format changed, request new buffers.
486 int res = RequestBuffers(1);
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700487 if (res) {
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800488 HAL_LOGE("Requesting buffers for new format failed.");
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700489 return res;
490 }
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700491 *result_max_buffers = buffers_.size();
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700492 return 0;
493}
494
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800495int V4L2Wrapper::RequestBuffers(uint32_t num_requested) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700496 v4l2_requestbuffers req_buffers;
497 memset(&req_buffers, 0, sizeof(req_buffers));
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700498 req_buffers.type = format_->type();
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700499 req_buffers.memory = V4L2_MEMORY_USERPTR;
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800500 req_buffers.count = num_requested;
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700501
502 int res = IoctlLocked(VIDIOC_REQBUFS, &req_buffers);
503 // Calling REQBUFS releases all queued buffers back to the user.
504 int gralloc_res = gralloc_->unlockAllBuffers();
505 if (res < 0) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700506 HAL_LOGE("REQBUFS failed: %s", strerror(errno));
507 return -ENODEV;
508 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700509 if (gralloc_res < 0) {
510 HAL_LOGE("Failed to unlock all buffers when setting up new buffers.");
511 return gralloc_res;
512 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700513
514 // V4L2 will set req_buffers.count to a number of buffers it can handle.
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800515 if (num_requested > 0 && req_buffers.count < 1) {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700516 HAL_LOGE("REQBUFS claims it can't handle any buffers.");
517 return -ENODEV;
518 }
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700519 buffers_.resize(req_buffers.count, false);
520
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700521 return 0;
522}
523
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800524int V4L2Wrapper::EnqueueBuffer(const camera3_stream_buffer_t* camera_buffer,
525 uint32_t* enqueued_index) {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700526 if (!format_) {
527 HAL_LOGE("Stream format must be set before enqueuing buffers.");
528 return -ENODEV;
529 }
530
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700531 // Find a free buffer index. Could use some sort of persistent hinting
532 // here to improve expected efficiency, but buffers_.size() is expected
533 // to be low enough (<10 experimentally) that it's not worth it.
534 int index = -1;
535 {
536 std::lock_guard<std::mutex> guard(buffer_queue_lock_);
537 for (int i = 0; i < buffers_.size(); ++i) {
538 if (!buffers_[i]) {
539 index = i;
540 break;
541 }
542 }
543 }
544 if (index < 0) {
545 // Note: The HAL should be tracking the number of buffers in flight
546 // for each stream, and should never overflow the device.
547 HAL_LOGE("Cannot enqueue buffer: stream is already full.");
548 return -ENODEV;
549 }
550
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700551 // Set up a v4l2 buffer struct.
552 v4l2_buffer device_buffer;
553 memset(&device_buffer, 0, sizeof(device_buffer));
554 device_buffer.type = format_->type();
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700555 device_buffer.index = index;
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700556
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700557 // Use QUERYBUF to ensure our buffer/device is in good shape,
558 // and fill out remaining fields.
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700559 if (IoctlLocked(VIDIOC_QUERYBUF, &device_buffer) < 0) {
560 HAL_LOGE("QUERYBUF fails: %s", strerror(errno));
561 return -ENODEV;
562 }
563
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700564 // Lock the buffer for writing (fills in the user pointer field).
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700565 int res =
566 gralloc_->lock(camera_buffer, format_->bytes_per_line(), &device_buffer);
567 if (res) {
568 HAL_LOGE("Gralloc failed to lock buffer.");
569 return res;
570 }
571 if (IoctlLocked(VIDIOC_QBUF, &device_buffer) < 0) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700572 HAL_LOGE("QBUF fails: %s", strerror(errno));
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700573 gralloc_->unlock(&device_buffer);
574 return -ENODEV;
575 }
576
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700577 // Mark the buffer as in flight.
578 std::lock_guard<std::mutex> guard(buffer_queue_lock_);
579 buffers_[index] = true;
580
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800581 if (enqueued_index) {
582 *enqueued_index = index;
583 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700584 return 0;
585}
586
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800587int V4L2Wrapper::DequeueBuffer(uint32_t* dequeued_index) {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700588 if (!format_) {
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800589 HAL_LOGV(
590 "Format not set, so stream can't be on, "
591 "so no buffers available for dequeueing");
592 return -EAGAIN;
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700593 }
594
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800595 v4l2_buffer buffer;
596 memset(&buffer, 0, sizeof(buffer));
597 buffer.type = format_->type();
598 buffer.memory = V4L2_MEMORY_USERPTR;
599 int res = IoctlLocked(VIDIOC_DQBUF, &buffer);
600 if (res) {
601 if (errno == EAGAIN) {
602 // Expected failure.
603 return -EAGAIN;
604 } else {
605 // Unexpected failure.
606 HAL_LOGE("DQBUF fails: %s", strerror(errno));
607 return -ENODEV;
608 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700609 }
610
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700611 // Mark the buffer as no longer in flight.
612 {
613 std::lock_guard<std::mutex> guard(buffer_queue_lock_);
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800614 buffers_[buffer.index] = false;
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700615 }
616
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700617 // Now that we're done painting the buffer, we can unlock it.
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800618 res = gralloc_->unlock(&buffer);
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700619 if (res) {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700620 HAL_LOGE("Gralloc failed to unlock buffer after dequeueing.");
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700621 return res;
622 }
623
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800624 if (dequeued_index) {
625 *dequeued_index = buffer.index;
626 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700627 return 0;
628}
629
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700630} // namespace v4l2_camera_hal