blob: b24535c4bafda38515f42361c3a25bb7329b3fa9 [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-Cohenabbf9cc2016-08-23 11:59:59 -070039const int32_t kStandardSizes[][2] = {
40 {1920, 1080}, {1280, 720}, {640, 480}, {320, 240}};
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070041
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -070042V4L2Wrapper* V4L2Wrapper::NewV4L2Wrapper(const std::string device_path) {
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -070043 std::unique_ptr<V4L2Gralloc> gralloc(V4L2Gralloc::NewV4L2Gralloc());
44 if (!gralloc) {
45 HAL_LOGE("Failed to initialize gralloc helper.");
46 return nullptr;
47 }
48
49 return new V4L2Wrapper(device_path, std::move(gralloc));
50}
51
52V4L2Wrapper::V4L2Wrapper(const std::string device_path,
53 std::unique_ptr<V4L2Gralloc> gralloc)
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -070054 : device_path_(std::move(device_path)),
55 gralloc_(std::move(gralloc)),
Ari Hausman-Cohenad6fe2b2016-11-16 10:48:07 -080056 connection_count_(0) {}
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070057
Ari Hausman-Cohenad6fe2b2016-11-16 10:48:07 -080058V4L2Wrapper::~V4L2Wrapper() {}
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070059
60int V4L2Wrapper::Connect() {
61 HAL_LOG_ENTER();
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070062 std::lock_guard<std::mutex> lock(connection_lock_);
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070063
64 if (connected()) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070065 HAL_LOGV("Camera device %s is already connected.", device_path_.c_str());
66 ++connection_count_;
67 return 0;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070068 }
69
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -080070 // Open in nonblocking mode (DQBUF may return EAGAIN).
71 int fd = TEMP_FAILURE_RETRY(open(device_path_.c_str(), O_RDWR | O_NONBLOCK));
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070072 if (fd < 0) {
73 HAL_LOGE("failed to open %s (%s)", device_path_.c_str(), strerror(errno));
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070074 return -ENODEV;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070075 }
76 device_fd_.reset(fd);
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070077 ++connection_count_;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070078
79 // Check if this connection has the extended control query capability.
80 v4l2_query_ext_ctrl query;
81 query.id = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND;
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070082 extended_query_supported_ = (IoctlLocked(VIDIOC_QUERY_EXT_CTRL, &query) == 0);
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070083
84 // TODO(b/29185945): confirm this is a supported device.
85 // This is checked by the HAL, but the device at device_path_ may
86 // not be the same one that was there when the HAL was loaded.
87 // (Alternatively, better hotplugging support may make this unecessary
88 // by disabling cameras that get disconnected and checking newly connected
89 // cameras, so Connect() is never called on an unsupported camera)
90 return 0;
91}
92
93void V4L2Wrapper::Disconnect() {
94 HAL_LOG_ENTER();
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070095 std::lock_guard<std::mutex> lock(connection_lock_);
96
97 if (connection_count_ == 0) {
98 // Not connected.
99 HAL_LOGE("Camera device %s is not connected, cannot disconnect.",
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -0700100 device_path_.c_str());
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700101 return;
102 }
103
104 --connection_count_;
105 if (connection_count_ > 0) {
106 HAL_LOGV("Disconnected from camera device %s. %d connections remain.",
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -0700107 device_path_.c_str());
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700108 return;
109 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700110
111 device_fd_.reset(); // Includes close().
112 format_.reset();
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700113 buffers_.clear();
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700114 // Closing the device releases all queued buffers back to the user.
115 gralloc_->unlockAllBuffers();
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700116}
117
118// Helper function. Should be used instead of ioctl throughout this class.
119template <typename T>
120int V4L2Wrapper::IoctlLocked(int request, T data) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700121 // Potentially called so many times logging entry is a bad idea.
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700122 std::lock_guard<std::mutex> lock(device_lock_);
123
124 if (!connected()) {
125 HAL_LOGE("Device %s not connected.", device_path_.c_str());
126 return -ENODEV;
127 }
128 return TEMP_FAILURE_RETRY(ioctl(device_fd_.get(), request, data));
129}
130
131int V4L2Wrapper::StreamOn() {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700132 if (!format_) {
133 HAL_LOGE("Stream format must be set before turning on stream.");
134 return -EINVAL;
135 }
136
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700137 int32_t type = format_->type();
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700138 if (IoctlLocked(VIDIOC_STREAMON, &type) < 0) {
139 HAL_LOGE("STREAMON fails: %s", strerror(errno));
140 return -ENODEV;
141 }
142
Ari Hausman-Cohenad6fe2b2016-11-16 10:48:07 -0800143 HAL_LOGV("Stream turned on.");
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700144 return 0;
145}
146
147int V4L2Wrapper::StreamOff() {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700148 if (!format_) {
Ari Hausman-Cohenad6fe2b2016-11-16 10:48:07 -0800149 // Can't have turned on the stream without format being set,
Ari Hausman-Cohen71cb8742016-09-22 11:12:00 -0700150 // so nothing to turn off here.
151 return 0;
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700152 }
153
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700154 int32_t type = format_->type();
155 int res = IoctlLocked(VIDIOC_STREAMOFF, &type);
156 // Calling STREAMOFF releases all queued buffers back to the user.
157 int gralloc_res = gralloc_->unlockAllBuffers();
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800158 // No buffers in flight.
159 for (size_t i = 0; i < buffers_.size(); ++i) {
160 buffers_[i] = false;
161 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700162 if (res < 0) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700163 HAL_LOGE("STREAMOFF fails: %s", strerror(errno));
164 return -ENODEV;
165 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700166 if (gralloc_res < 0) {
167 HAL_LOGE("Failed to unlock all buffers after turning stream off.");
168 return gralloc_res;
169 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700170
Ari Hausman-Cohenad6fe2b2016-11-16 10:48:07 -0800171 HAL_LOGV("Stream turned off.");
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700172 return 0;
173}
174
175int V4L2Wrapper::QueryControl(uint32_t control_id,
176 v4l2_query_ext_ctrl* result) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700177 int res;
178
179 memset(result, 0, sizeof(*result));
180
181 if (extended_query_supported_) {
182 result->id = control_id;
183 res = IoctlLocked(VIDIOC_QUERY_EXT_CTRL, result);
184 // Assuming the operation was supported (not ENOTTY), no more to do.
185 if (errno != ENOTTY) {
186 if (res) {
187 HAL_LOGE("QUERY_EXT_CTRL fails: %s", strerror(errno));
188 return -ENODEV;
189 }
190 return 0;
191 }
192 }
193
194 // Extended control querying not supported, fall back to basic control query.
195 v4l2_queryctrl query;
196 query.id = control_id;
197 if (IoctlLocked(VIDIOC_QUERYCTRL, &query)) {
198 HAL_LOGE("QUERYCTRL fails: %s", strerror(errno));
199 return -ENODEV;
200 }
201
202 // Convert the basic result to the extended result.
203 result->id = query.id;
204 result->type = query.type;
205 memcpy(result->name, query.name, sizeof(query.name));
206 result->minimum = query.minimum;
207 if (query.type == V4L2_CTRL_TYPE_BITMASK) {
208 // According to the V4L2 documentation, when type is BITMASK,
209 // max and default should be interpreted as __u32. Practically,
210 // this means the conversion from 32 bit to 64 will pad with 0s not 1s.
211 result->maximum = static_cast<uint32_t>(query.maximum);
212 result->default_value = static_cast<uint32_t>(query.default_value);
213 } else {
214 result->maximum = query.maximum;
215 result->default_value = query.default_value;
216 }
217 result->step = static_cast<uint32_t>(query.step);
218 result->flags = query.flags;
219 result->elems = 1;
220 switch (result->type) {
221 case V4L2_CTRL_TYPE_INTEGER64:
222 result->elem_size = sizeof(int64_t);
223 break;
224 case V4L2_CTRL_TYPE_STRING:
225 result->elem_size = result->maximum + 1;
226 break;
227 default:
228 result->elem_size = sizeof(int32_t);
229 break;
230 }
231
232 return 0;
233}
234
235int V4L2Wrapper::GetControl(uint32_t control_id, int32_t* value) {
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700236 // For extended controls (any control class other than "user"),
237 // G_EXT_CTRL must be used instead of G_CTRL.
238 if (V4L2_CTRL_ID2CLASS(control_id) != V4L2_CTRL_CLASS_USER) {
239 v4l2_ext_control control;
240 v4l2_ext_controls controls;
241 memset(&control, 0, sizeof(control));
242 memset(&controls, 0, sizeof(controls));
243
244 control.id = control_id;
245 controls.ctrl_class = V4L2_CTRL_ID2CLASS(control_id);
246 controls.count = 1;
247 controls.controls = &control;
248
249 if (IoctlLocked(VIDIOC_G_EXT_CTRLS, &controls) < 0) {
250 HAL_LOGE("G_EXT_CTRLS fails: %s", strerror(errno));
251 return -ENODEV;
252 }
253 *value = control.value;
254 } else {
255 v4l2_control control{control_id, 0};
256 if (IoctlLocked(VIDIOC_G_CTRL, &control) < 0) {
257 HAL_LOGE("G_CTRL fails: %s", strerror(errno));
258 return -ENODEV;
259 }
260 *value = control.value;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700261 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700262 return 0;
263}
264
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700265int V4L2Wrapper::SetControl(uint32_t control_id,
266 int32_t desired,
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700267 int32_t* result) {
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700268 int32_t result_value = 0;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700269
Ari Hausman-Cohen99f3ea02016-08-02 10:47:07 -0700270 // TODO(b/29334616): When async, this may need to check if the stream
271 // is on, and if so, lock it off while setting format. Need to look
272 // into if V4L2 supports adjusting controls while the stream is on.
273
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700274 // For extended controls (any control class other than "user"),
275 // S_EXT_CTRL must be used instead of S_CTRL.
276 if (V4L2_CTRL_ID2CLASS(control_id) != V4L2_CTRL_CLASS_USER) {
277 v4l2_ext_control control;
278 v4l2_ext_controls controls;
279 memset(&control, 0, sizeof(control));
280 memset(&controls, 0, sizeof(controls));
281
282 control.id = control_id;
283 control.value = desired;
284 controls.ctrl_class = V4L2_CTRL_ID2CLASS(control_id);
285 controls.count = 1;
286 controls.controls = &control;
287
288 if (IoctlLocked(VIDIOC_S_EXT_CTRLS, &controls) < 0) {
289 HAL_LOGE("S_EXT_CTRLS fails: %s", strerror(errno));
290 return -ENODEV;
291 }
292 result_value = control.value;
293 } else {
294 v4l2_control control{control_id, desired};
295 if (IoctlLocked(VIDIOC_S_CTRL, &control) < 0) {
296 HAL_LOGE("S_CTRL fails: %s", strerror(errno));
297 return -ENODEV;
298 }
299 result_value = control.value;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700300 }
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700301
Ari Hausman-Cohen99f3ea02016-08-02 10:47:07 -0700302 // If the caller wants to know the result, pass it back.
303 if (result != nullptr) {
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700304 *result = result_value;
Ari Hausman-Cohen99f3ea02016-08-02 10:47:07 -0700305 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700306 return 0;
307}
308
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700309int V4L2Wrapper::GetFormats(std::set<uint32_t>* v4l2_formats) {
310 HAL_LOG_ENTER();
311
312 v4l2_fmtdesc format_query;
313 memset(&format_query, 0, sizeof(format_query));
314 // TODO(b/30000211): multiplanar support.
315 format_query.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
316 while (IoctlLocked(VIDIOC_ENUM_FMT, &format_query) >= 0) {
317 v4l2_formats->insert(format_query.pixelformat);
318 ++format_query.index;
319 }
320
321 if (errno != EINVAL) {
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700322 HAL_LOGE(
323 "ENUM_FMT fails at index %d: %s", format_query.index, strerror(errno));
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700324 return -ENODEV;
325 }
326 return 0;
327}
328
329int V4L2Wrapper::GetFormatFrameSizes(uint32_t v4l2_format,
330 std::set<std::array<int32_t, 2>>* sizes) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700331 v4l2_frmsizeenum size_query;
332 memset(&size_query, 0, sizeof(size_query));
333 size_query.pixel_format = v4l2_format;
334 if (IoctlLocked(VIDIOC_ENUM_FRAMESIZES, &size_query) < 0) {
335 HAL_LOGE("ENUM_FRAMESIZES failed: %s", strerror(errno));
336 return -ENODEV;
337 }
338 if (size_query.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
339 // Discrete: enumerate all sizes using VIDIOC_ENUM_FRAMESIZES.
340 // Assuming that a driver with discrete frame sizes has a reasonable number
341 // of them.
342 do {
343 sizes->insert({{{static_cast<int32_t>(size_query.discrete.width),
344 static_cast<int32_t>(size_query.discrete.height)}}});
345 ++size_query.index;
346 } while (IoctlLocked(VIDIOC_ENUM_FRAMESIZES, &size_query) >= 0);
347 if (errno != EINVAL) {
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700348 HAL_LOGE("ENUM_FRAMESIZES fails at index %d: %s",
349 size_query.index,
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700350 strerror(errno));
351 return -ENODEV;
352 }
353 } else {
354 // Continuous/Step-wise: based on the stepwise struct returned by the query.
355 // Fully listing all possible sizes, with large enough range/small enough
356 // step size, may produce far too many potential sizes. Instead, find the
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800357 // closest to a set of standard sizes.
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -0700358 for (const auto size : kStandardSizes) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700359 // Find the closest size, rounding up.
360 uint32_t desired_width = size[0];
361 uint32_t desired_height = size[1];
362 if (desired_width < size_query.stepwise.min_width ||
363 desired_height < size_query.stepwise.min_height) {
364 HAL_LOGV("Standard size %u x %u is too small for format %d",
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700365 desired_width,
366 desired_height,
367 v4l2_format);
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700368 continue;
369 } else if (desired_width > size_query.stepwise.max_width &&
370 desired_height > size_query.stepwise.max_height) {
371 HAL_LOGV("Standard size %u x %u is too big for format %d",
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700372 desired_width,
373 desired_height,
374 v4l2_format);
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700375 continue;
376 }
377
378 // Round up.
379 uint32_t width_steps = (desired_width - size_query.stepwise.min_width +
380 size_query.stepwise.step_width - 1) /
381 size_query.stepwise.step_width;
382 uint32_t height_steps = (desired_height - size_query.stepwise.min_height +
383 size_query.stepwise.step_height - 1) /
384 size_query.stepwise.step_height;
385 sizes->insert(
386 {{{static_cast<int32_t>(size_query.stepwise.min_width +
387 width_steps * size_query.stepwise.step_width),
388 static_cast<int32_t>(size_query.stepwise.min_height +
389 height_steps *
390 size_query.stepwise.step_height)}}});
391 }
392 }
393 return 0;
394}
395
396// Converts a v4l2_fract with units of seconds to an int64_t with units of ns.
397inline int64_t FractToNs(const v4l2_fract& fract) {
398 return (1000000000LL * fract.numerator) / fract.denominator;
399}
400
401int V4L2Wrapper::GetFormatFrameDurationRange(
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700402 uint32_t v4l2_format,
403 const std::array<int32_t, 2>& size,
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700404 std::array<int64_t, 2>* duration_range) {
405 // Potentially called so many times logging entry is a bad idea.
406
407 v4l2_frmivalenum duration_query;
408 memset(&duration_query, 0, sizeof(duration_query));
409 duration_query.pixel_format = v4l2_format;
410 duration_query.width = size[0];
411 duration_query.height = size[1];
412 if (IoctlLocked(VIDIOC_ENUM_FRAMEINTERVALS, &duration_query) < 0) {
413 HAL_LOGE("ENUM_FRAMEINTERVALS failed: %s", strerror(errno));
414 return -ENODEV;
415 }
416
417 int64_t min = std::numeric_limits<int64_t>::max();
418 int64_t max = std::numeric_limits<int64_t>::min();
419 if (duration_query.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
420 // Discrete: enumerate all durations using VIDIOC_ENUM_FRAMEINTERVALS.
421 do {
422 min = std::min(min, FractToNs(duration_query.discrete));
423 max = std::max(max, FractToNs(duration_query.discrete));
424 ++duration_query.index;
425 } while (IoctlLocked(VIDIOC_ENUM_FRAMEINTERVALS, &duration_query) >= 0);
426 if (errno != EINVAL) {
427 HAL_LOGE("ENUM_FRAMEINTERVALS fails at index %d: %s",
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700428 duration_query.index,
429 strerror(errno));
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700430 return -ENODEV;
431 }
432 } else {
433 // Continuous/Step-wise: simply convert the given min and max.
434 min = FractToNs(duration_query.stepwise.min);
435 max = FractToNs(duration_query.stepwise.max);
436 }
437 (*duration_range)[0] = min;
438 (*duration_range)[1] = max;
439 return 0;
440}
441
Ari Hausman-Cohenef523102016-11-21 17:02:01 -0800442int V4L2Wrapper::SetFormat(const StreamFormat& desired_format,
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700443 uint32_t* result_max_buffers) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700444 HAL_LOG_ENTER();
445
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700446 if (format_ && desired_format == *format_) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700447 HAL_LOGV("Already in correct format, skipping format setting.");
Ari Hausman-Cohena5c9bfd2016-11-18 14:57:07 -0800448 *result_max_buffers = buffers_.size();
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700449 return 0;
450 }
451
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800452 // Not in the correct format, set the new one.
453
454 if (format_) {
455 // If we had an old format, first request 0 buffers to inform the device
456 // we're no longer using any previously "allocated" buffers from the old
457 // format. This seems like it shouldn't be necessary for USERPTR memory,
458 // and/or should happen from turning the stream off, but the driver
459 // complained. May be a driver issue, or may be intended behavior.
460 int res = RequestBuffers(0);
461 if (res) {
462 return res;
463 }
464 }
465
466 // Set the camera to the new format.
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700467 v4l2_format new_format;
468 desired_format.FillFormatRequest(&new_format);
469 // TODO(b/29334616): When async, this will need to check if the stream
470 // is on, and if so, lock it off while setting format.
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800471
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700472 if (IoctlLocked(VIDIOC_S_FMT, &new_format) < 0) {
473 HAL_LOGE("S_FMT failed: %s", strerror(errno));
474 return -ENODEV;
475 }
476
477 // Check that the driver actually set to the requested values.
478 if (desired_format != new_format) {
479 HAL_LOGE("Device doesn't support desired stream configuration.");
480 return -EINVAL;
481 }
482
483 // Keep track of our new format.
484 format_.reset(new StreamFormat(new_format));
485
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800486 // Format changed, request new buffers.
487 int res = RequestBuffers(1);
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700488 if (res) {
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800489 HAL_LOGE("Requesting buffers for new format failed.");
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700490 return res;
491 }
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700492 *result_max_buffers = buffers_.size();
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700493 return 0;
494}
495
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800496int V4L2Wrapper::RequestBuffers(uint32_t num_requested) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700497 v4l2_requestbuffers req_buffers;
498 memset(&req_buffers, 0, sizeof(req_buffers));
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700499 req_buffers.type = format_->type();
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700500 req_buffers.memory = V4L2_MEMORY_USERPTR;
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800501 req_buffers.count = num_requested;
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700502
503 int res = IoctlLocked(VIDIOC_REQBUFS, &req_buffers);
504 // Calling REQBUFS releases all queued buffers back to the user.
505 int gralloc_res = gralloc_->unlockAllBuffers();
506 if (res < 0) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700507 HAL_LOGE("REQBUFS failed: %s", strerror(errno));
508 return -ENODEV;
509 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700510 if (gralloc_res < 0) {
511 HAL_LOGE("Failed to unlock all buffers when setting up new buffers.");
512 return gralloc_res;
513 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700514
515 // V4L2 will set req_buffers.count to a number of buffers it can handle.
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800516 if (num_requested > 0 && req_buffers.count < 1) {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700517 HAL_LOGE("REQBUFS claims it can't handle any buffers.");
518 return -ENODEV;
519 }
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700520 buffers_.resize(req_buffers.count, false);
521
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700522 return 0;
523}
524
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800525int V4L2Wrapper::EnqueueBuffer(const camera3_stream_buffer_t* camera_buffer,
526 uint32_t* enqueued_index) {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700527 if (!format_) {
528 HAL_LOGE("Stream format must be set before enqueuing buffers.");
529 return -ENODEV;
530 }
531
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700532 // Find a free buffer index. Could use some sort of persistent hinting
533 // here to improve expected efficiency, but buffers_.size() is expected
534 // to be low enough (<10 experimentally) that it's not worth it.
535 int index = -1;
536 {
537 std::lock_guard<std::mutex> guard(buffer_queue_lock_);
538 for (int i = 0; i < buffers_.size(); ++i) {
539 if (!buffers_[i]) {
540 index = i;
541 break;
542 }
543 }
544 }
545 if (index < 0) {
546 // Note: The HAL should be tracking the number of buffers in flight
547 // for each stream, and should never overflow the device.
548 HAL_LOGE("Cannot enqueue buffer: stream is already full.");
549 return -ENODEV;
550 }
551
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700552 // Set up a v4l2 buffer struct.
553 v4l2_buffer device_buffer;
554 memset(&device_buffer, 0, sizeof(device_buffer));
555 device_buffer.type = format_->type();
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700556 device_buffer.index = index;
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700557
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700558 // Use QUERYBUF to ensure our buffer/device is in good shape,
559 // and fill out remaining fields.
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700560 if (IoctlLocked(VIDIOC_QUERYBUF, &device_buffer) < 0) {
561 HAL_LOGE("QUERYBUF fails: %s", strerror(errno));
562 return -ENODEV;
563 }
564
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700565 // Lock the buffer for writing (fills in the user pointer field).
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700566 int res =
567 gralloc_->lock(camera_buffer, format_->bytes_per_line(), &device_buffer);
568 if (res) {
569 HAL_LOGE("Gralloc failed to lock buffer.");
570 return res;
571 }
572 if (IoctlLocked(VIDIOC_QBUF, &device_buffer) < 0) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700573 HAL_LOGE("QBUF fails: %s", strerror(errno));
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700574 gralloc_->unlock(&device_buffer);
575 return -ENODEV;
576 }
577
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700578 // Mark the buffer as in flight.
579 std::lock_guard<std::mutex> guard(buffer_queue_lock_);
580 buffers_[index] = true;
581
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800582 if (enqueued_index) {
583 *enqueued_index = index;
584 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700585 return 0;
586}
587
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800588int V4L2Wrapper::DequeueBuffer(uint32_t* dequeued_index) {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700589 if (!format_) {
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800590 HAL_LOGV(
591 "Format not set, so stream can't be on, "
592 "so no buffers available for dequeueing");
593 return -EAGAIN;
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700594 }
595
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800596 v4l2_buffer buffer;
597 memset(&buffer, 0, sizeof(buffer));
598 buffer.type = format_->type();
599 buffer.memory = V4L2_MEMORY_USERPTR;
600 int res = IoctlLocked(VIDIOC_DQBUF, &buffer);
601 if (res) {
602 if (errno == EAGAIN) {
603 // Expected failure.
604 return -EAGAIN;
605 } else {
606 // Unexpected failure.
607 HAL_LOGE("DQBUF fails: %s", strerror(errno));
608 return -ENODEV;
609 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700610 }
611
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700612 // Mark the buffer as no longer in flight.
613 {
614 std::lock_guard<std::mutex> guard(buffer_queue_lock_);
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800615 buffers_[buffer.index] = false;
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700616 }
617
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700618 // Now that we're done painting the buffer, we can unlock it.
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800619 res = gralloc_->unlock(&buffer);
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700620 if (res) {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700621 HAL_LOGE("Gralloc failed to unlock buffer after dequeueing.");
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700622 return res;
623 }
624
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800625 if (dequeued_index) {
626 *dequeued_index = buffer.index;
627 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700628 return 0;
629}
630
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700631} // namespace v4l2_camera_hal