blob: b88faafef8d9af1a7db388f0847945048048163d [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>
20#include <limits>
21#include <vector>
22
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070023#include <fcntl.h>
24#include <linux/videodev2.h>
25#include <sys/stat.h>
26#include <sys/types.h>
27
28#include <mutex>
29
30#include <nativehelper/ScopedFd.h>
31
Ari Hausman-Cohen3841a7f2016-07-19 17:27:52 -070032#include "common.h"
33#include "stream.h"
34#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-Cohen9e6fd982016-08-02 16:29:53 -070039const std::vector<std::array<int32_t, 2>> kStandardSizes(
40 {{{1920, 1080}}, {{1280, 720}}, {{640, 480}}, {{320, 240}}});
41
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -070042V4L2Wrapper* V4L2Wrapper::NewV4L2Wrapper(const std::string device_path) {
43 HAL_LOG_ENTER();
44
45 std::unique_ptr<V4L2Gralloc> gralloc(V4L2Gralloc::NewV4L2Gralloc());
46 if (!gralloc) {
47 HAL_LOGE("Failed to initialize gralloc helper.");
48 return nullptr;
49 }
50
51 return new V4L2Wrapper(device_path, std::move(gralloc));
52}
53
54V4L2Wrapper::V4L2Wrapper(const std::string device_path,
55 std::unique_ptr<V4L2Gralloc> gralloc)
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -070056 : device_path_(std::move(device_path)),
57 gralloc_(std::move(gralloc)),
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070058 max_buffers_(0),
59 connection_count_(0) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070060 HAL_LOG_ENTER();
61}
62
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -070063V4L2Wrapper::~V4L2Wrapper() {
64 HAL_LOG_ENTER();
65}
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070066
67int V4L2Wrapper::Connect() {
68 HAL_LOG_ENTER();
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070069 std::lock_guard<std::mutex> lock(connection_lock_);
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070070
71 if (connected()) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070072 HAL_LOGV("Camera device %s is already connected.", device_path_.c_str());
73 ++connection_count_;
74 return 0;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070075 }
76
77 int fd = TEMP_FAILURE_RETRY(open(device_path_.c_str(), O_RDWR));
78 if (fd < 0) {
79 HAL_LOGE("failed to open %s (%s)", device_path_.c_str(), strerror(errno));
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070080 return -ENODEV;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070081 }
82 device_fd_.reset(fd);
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070083 ++connection_count_;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070084
85 // Check if this connection has the extended control query capability.
86 v4l2_query_ext_ctrl query;
87 query.id = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND;
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070088 extended_query_supported_ = (IoctlLocked(VIDIOC_QUERY_EXT_CTRL, &query) == 0);
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070089
90 // TODO(b/29185945): confirm this is a supported device.
91 // This is checked by the HAL, but the device at device_path_ may
92 // not be the same one that was there when the HAL was loaded.
93 // (Alternatively, better hotplugging support may make this unecessary
94 // by disabling cameras that get disconnected and checking newly connected
95 // cameras, so Connect() is never called on an unsupported camera)
96 return 0;
97}
98
99void V4L2Wrapper::Disconnect() {
100 HAL_LOG_ENTER();
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700101 std::lock_guard<std::mutex> lock(connection_lock_);
102
103 if (connection_count_ == 0) {
104 // Not connected.
105 HAL_LOGE("Camera device %s is not connected, cannot disconnect.",
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700106 device_path_.c_str(),
107 connection_count_);
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700108 return;
109 }
110
111 --connection_count_;
112 if (connection_count_ > 0) {
113 HAL_LOGV("Disconnected from camera device %s. %d connections remain.",
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700114 device_path_.c_str(),
115 connection_count_);
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700116 return;
117 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700118
119 device_fd_.reset(); // Includes close().
120 format_.reset();
121 max_buffers_ = 0;
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700122 // Closing the device releases all queued buffers back to the user.
123 gralloc_->unlockAllBuffers();
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700124}
125
126// Helper function. Should be used instead of ioctl throughout this class.
127template <typename T>
128int V4L2Wrapper::IoctlLocked(int request, T data) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700129 // Potentially called so many times logging entry is a bad idea.
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700130 std::lock_guard<std::mutex> lock(device_lock_);
131
132 if (!connected()) {
133 HAL_LOGE("Device %s not connected.", device_path_.c_str());
134 return -ENODEV;
135 }
136 return TEMP_FAILURE_RETRY(ioctl(device_fd_.get(), request, data));
137}
138
139int V4L2Wrapper::StreamOn() {
140 HAL_LOG_ENTER();
141
142 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
153 return 0;
154}
155
156int V4L2Wrapper::StreamOff() {
157 HAL_LOG_ENTER();
158
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700159 if (!format_) {
160 HAL_LOGE("Stream format must be set to turn off stream.");
161 return -ENODEV;
162 }
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();
168 if (res < 0) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700169 HAL_LOGE("STREAMOFF fails: %s", strerror(errno));
170 return -ENODEV;
171 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700172 if (gralloc_res < 0) {
173 HAL_LOGE("Failed to unlock all buffers after turning stream off.");
174 return gralloc_res;
175 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700176
177 return 0;
178}
179
180int V4L2Wrapper::QueryControl(uint32_t control_id,
181 v4l2_query_ext_ctrl* result) {
182 HAL_LOG_ENTER();
183 int res;
184
185 memset(result, 0, sizeof(*result));
186
187 if (extended_query_supported_) {
188 result->id = control_id;
189 res = IoctlLocked(VIDIOC_QUERY_EXT_CTRL, result);
190 // Assuming the operation was supported (not ENOTTY), no more to do.
191 if (errno != ENOTTY) {
192 if (res) {
193 HAL_LOGE("QUERY_EXT_CTRL fails: %s", strerror(errno));
194 return -ENODEV;
195 }
196 return 0;
197 }
198 }
199
200 // Extended control querying not supported, fall back to basic control query.
201 v4l2_queryctrl query;
202 query.id = control_id;
203 if (IoctlLocked(VIDIOC_QUERYCTRL, &query)) {
204 HAL_LOGE("QUERYCTRL fails: %s", strerror(errno));
205 return -ENODEV;
206 }
207
208 // Convert the basic result to the extended result.
209 result->id = query.id;
210 result->type = query.type;
211 memcpy(result->name, query.name, sizeof(query.name));
212 result->minimum = query.minimum;
213 if (query.type == V4L2_CTRL_TYPE_BITMASK) {
214 // According to the V4L2 documentation, when type is BITMASK,
215 // max and default should be interpreted as __u32. Practically,
216 // this means the conversion from 32 bit to 64 will pad with 0s not 1s.
217 result->maximum = static_cast<uint32_t>(query.maximum);
218 result->default_value = static_cast<uint32_t>(query.default_value);
219 } else {
220 result->maximum = query.maximum;
221 result->default_value = query.default_value;
222 }
223 result->step = static_cast<uint32_t>(query.step);
224 result->flags = query.flags;
225 result->elems = 1;
226 switch (result->type) {
227 case V4L2_CTRL_TYPE_INTEGER64:
228 result->elem_size = sizeof(int64_t);
229 break;
230 case V4L2_CTRL_TYPE_STRING:
231 result->elem_size = result->maximum + 1;
232 break;
233 default:
234 result->elem_size = sizeof(int32_t);
235 break;
236 }
237
238 return 0;
239}
240
241int V4L2Wrapper::GetControl(uint32_t control_id, int32_t* value) {
242 HAL_LOG_ENTER();
243
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700244 // For extended controls (any control class other than "user"),
245 // G_EXT_CTRL must be used instead of G_CTRL.
246 if (V4L2_CTRL_ID2CLASS(control_id) != V4L2_CTRL_CLASS_USER) {
247 v4l2_ext_control control;
248 v4l2_ext_controls controls;
249 memset(&control, 0, sizeof(control));
250 memset(&controls, 0, sizeof(controls));
251
252 control.id = control_id;
253 controls.ctrl_class = V4L2_CTRL_ID2CLASS(control_id);
254 controls.count = 1;
255 controls.controls = &control;
256
257 if (IoctlLocked(VIDIOC_G_EXT_CTRLS, &controls) < 0) {
258 HAL_LOGE("G_EXT_CTRLS fails: %s", strerror(errno));
259 return -ENODEV;
260 }
261 *value = control.value;
262 } else {
263 v4l2_control control{control_id, 0};
264 if (IoctlLocked(VIDIOC_G_CTRL, &control) < 0) {
265 HAL_LOGE("G_CTRL fails: %s", strerror(errno));
266 return -ENODEV;
267 }
268 *value = control.value;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700269 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700270 return 0;
271}
272
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700273int V4L2Wrapper::SetControl(uint32_t control_id,
274 int32_t desired,
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700275 int32_t* result) {
276 HAL_LOG_ENTER();
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700277 int32_t result_value = 0;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700278
Ari Hausman-Cohen99f3ea02016-08-02 10:47:07 -0700279 // TODO(b/29334616): When async, this may need to check if the stream
280 // is on, and if so, lock it off while setting format. Need to look
281 // into if V4L2 supports adjusting controls while the stream is on.
282
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700283 // For extended controls (any control class other than "user"),
284 // S_EXT_CTRL must be used instead of S_CTRL.
285 if (V4L2_CTRL_ID2CLASS(control_id) != V4L2_CTRL_CLASS_USER) {
286 v4l2_ext_control control;
287 v4l2_ext_controls controls;
288 memset(&control, 0, sizeof(control));
289 memset(&controls, 0, sizeof(controls));
290
291 control.id = control_id;
292 control.value = desired;
293 controls.ctrl_class = V4L2_CTRL_ID2CLASS(control_id);
294 controls.count = 1;
295 controls.controls = &control;
296
297 if (IoctlLocked(VIDIOC_S_EXT_CTRLS, &controls) < 0) {
298 HAL_LOGE("S_EXT_CTRLS fails: %s", strerror(errno));
299 return -ENODEV;
300 }
301 result_value = control.value;
302 } else {
303 v4l2_control control{control_id, desired};
304 if (IoctlLocked(VIDIOC_S_CTRL, &control) < 0) {
305 HAL_LOGE("S_CTRL fails: %s", strerror(errno));
306 return -ENODEV;
307 }
308 result_value = control.value;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700309 }
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700310
Ari Hausman-Cohen99f3ea02016-08-02 10:47:07 -0700311 // If the caller wants to know the result, pass it back.
312 if (result != nullptr) {
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700313 *result = result_value;
Ari Hausman-Cohen99f3ea02016-08-02 10:47:07 -0700314 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700315 return 0;
316}
317
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700318int V4L2Wrapper::GetFormats(std::set<uint32_t>* v4l2_formats) {
319 HAL_LOG_ENTER();
320
321 v4l2_fmtdesc format_query;
322 memset(&format_query, 0, sizeof(format_query));
323 // TODO(b/30000211): multiplanar support.
324 format_query.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
325 while (IoctlLocked(VIDIOC_ENUM_FMT, &format_query) >= 0) {
326 v4l2_formats->insert(format_query.pixelformat);
327 ++format_query.index;
328 }
329
330 if (errno != EINVAL) {
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700331 HAL_LOGE(
332 "ENUM_FMT fails at index %d: %s", format_query.index, strerror(errno));
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700333 return -ENODEV;
334 }
335 return 0;
336}
337
338int V4L2Wrapper::GetFormatFrameSizes(uint32_t v4l2_format,
339 std::set<std::array<int32_t, 2>>* sizes) {
340 HAL_LOG_ENTER();
341
342 v4l2_frmsizeenum size_query;
343 memset(&size_query, 0, sizeof(size_query));
344 size_query.pixel_format = v4l2_format;
345 if (IoctlLocked(VIDIOC_ENUM_FRAMESIZES, &size_query) < 0) {
346 HAL_LOGE("ENUM_FRAMESIZES failed: %s", strerror(errno));
347 return -ENODEV;
348 }
349 if (size_query.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
350 // Discrete: enumerate all sizes using VIDIOC_ENUM_FRAMESIZES.
351 // Assuming that a driver with discrete frame sizes has a reasonable number
352 // of them.
353 do {
354 sizes->insert({{{static_cast<int32_t>(size_query.discrete.width),
355 static_cast<int32_t>(size_query.discrete.height)}}});
356 ++size_query.index;
357 } while (IoctlLocked(VIDIOC_ENUM_FRAMESIZES, &size_query) >= 0);
358 if (errno != EINVAL) {
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700359 HAL_LOGE("ENUM_FRAMESIZES fails at index %d: %s",
360 size_query.index,
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700361 strerror(errno));
362 return -ENODEV;
363 }
364 } else {
365 // Continuous/Step-wise: based on the stepwise struct returned by the query.
366 // Fully listing all possible sizes, with large enough range/small enough
367 // step size, may produce far too many potential sizes. Instead, find the
368 // closest to a set of standard sizes plus largest possible.
369 sizes->insert({{{static_cast<int32_t>(size_query.stepwise.max_width),
370 static_cast<int32_t>(size_query.stepwise.max_height)}}});
371 for (const auto& size : kStandardSizes) {
372 // Find the closest size, rounding up.
373 uint32_t desired_width = size[0];
374 uint32_t desired_height = size[1];
375 if (desired_width < size_query.stepwise.min_width ||
376 desired_height < size_query.stepwise.min_height) {
377 HAL_LOGV("Standard size %u x %u is too small for format %d",
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700378 desired_width,
379 desired_height,
380 v4l2_format);
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700381 continue;
382 } else if (desired_width > size_query.stepwise.max_width &&
383 desired_height > size_query.stepwise.max_height) {
384 HAL_LOGV("Standard size %u x %u is too big for format %d",
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700385 desired_width,
386 desired_height,
387 v4l2_format);
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700388 continue;
389 }
390
391 // Round up.
392 uint32_t width_steps = (desired_width - size_query.stepwise.min_width +
393 size_query.stepwise.step_width - 1) /
394 size_query.stepwise.step_width;
395 uint32_t height_steps = (desired_height - size_query.stepwise.min_height +
396 size_query.stepwise.step_height - 1) /
397 size_query.stepwise.step_height;
398 sizes->insert(
399 {{{static_cast<int32_t>(size_query.stepwise.min_width +
400 width_steps * size_query.stepwise.step_width),
401 static_cast<int32_t>(size_query.stepwise.min_height +
402 height_steps *
403 size_query.stepwise.step_height)}}});
404 }
405 }
406 return 0;
407}
408
409// Converts a v4l2_fract with units of seconds to an int64_t with units of ns.
410inline int64_t FractToNs(const v4l2_fract& fract) {
411 return (1000000000LL * fract.numerator) / fract.denominator;
412}
413
414int V4L2Wrapper::GetFormatFrameDurationRange(
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700415 uint32_t v4l2_format,
416 const std::array<int32_t, 2>& size,
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700417 std::array<int64_t, 2>* duration_range) {
418 // Potentially called so many times logging entry is a bad idea.
419
420 v4l2_frmivalenum duration_query;
421 memset(&duration_query, 0, sizeof(duration_query));
422 duration_query.pixel_format = v4l2_format;
423 duration_query.width = size[0];
424 duration_query.height = size[1];
425 if (IoctlLocked(VIDIOC_ENUM_FRAMEINTERVALS, &duration_query) < 0) {
426 HAL_LOGE("ENUM_FRAMEINTERVALS failed: %s", strerror(errno));
427 return -ENODEV;
428 }
429
430 int64_t min = std::numeric_limits<int64_t>::max();
431 int64_t max = std::numeric_limits<int64_t>::min();
432 if (duration_query.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
433 // Discrete: enumerate all durations using VIDIOC_ENUM_FRAMEINTERVALS.
434 do {
435 min = std::min(min, FractToNs(duration_query.discrete));
436 max = std::max(max, FractToNs(duration_query.discrete));
437 ++duration_query.index;
438 } while (IoctlLocked(VIDIOC_ENUM_FRAMEINTERVALS, &duration_query) >= 0);
439 if (errno != EINVAL) {
440 HAL_LOGE("ENUM_FRAMEINTERVALS fails at index %d: %s",
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700441 duration_query.index,
442 strerror(errno));
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700443 return -ENODEV;
444 }
445 } else {
446 // Continuous/Step-wise: simply convert the given min and max.
447 min = FractToNs(duration_query.stepwise.min);
448 max = FractToNs(duration_query.stepwise.max);
449 }
450 (*duration_range)[0] = min;
451 (*duration_range)[1] = max;
452 return 0;
453}
454
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700455int V4L2Wrapper::SetFormat(const default_camera_hal::Stream& stream,
456 uint32_t* result_max_buffers) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700457 HAL_LOG_ENTER();
458
459 // Should be checked earlier; sanity check.
460 if (stream.isInputType()) {
461 HAL_LOGE("Input streams not supported.");
462 return -EINVAL;
463 }
464
465 StreamFormat desired_format(stream);
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700466 if (format_ && desired_format == *format_) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700467 HAL_LOGV("Already in correct format, skipping format setting.");
468 return 0;
469 }
470
471 // Not in the correct format, set our format.
472 v4l2_format new_format;
473 desired_format.FillFormatRequest(&new_format);
474 // TODO(b/29334616): When async, this will need to check if the stream
475 // is on, and if so, lock it off while setting format.
476 if (IoctlLocked(VIDIOC_S_FMT, &new_format) < 0) {
477 HAL_LOGE("S_FMT failed: %s", strerror(errno));
478 return -ENODEV;
479 }
480
481 // Check that the driver actually set to the requested values.
482 if (desired_format != new_format) {
483 HAL_LOGE("Device doesn't support desired stream configuration.");
484 return -EINVAL;
485 }
486
487 // Keep track of our new format.
488 format_.reset(new StreamFormat(new_format));
489
490 // Format changed, setup new buffers.
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700491 int res = SetupBuffers();
492 if (res) {
493 HAL_LOGE("Failed to set up buffers for new format.");
494 return res;
495 }
496 *result_max_buffers = max_buffers_;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700497 return 0;
498}
499
500int V4L2Wrapper::SetupBuffers() {
501 HAL_LOG_ENTER();
502
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700503 if (!format_) {
504 HAL_LOGE("Stream format must be set before setting up buffers.");
505 return -ENODEV;
506 }
507
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700508 // "Request" a buffer (since we're using a userspace buffer, this just
509 // tells V4L2 to switch into userspace buffer mode).
510 v4l2_requestbuffers req_buffers;
511 memset(&req_buffers, 0, sizeof(req_buffers));
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700512 req_buffers.type = format_->type();
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700513 req_buffers.memory = V4L2_MEMORY_USERPTR;
514 req_buffers.count = 1;
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700515
516 int res = IoctlLocked(VIDIOC_REQBUFS, &req_buffers);
517 // Calling REQBUFS releases all queued buffers back to the user.
518 int gralloc_res = gralloc_->unlockAllBuffers();
519 if (res < 0) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700520 HAL_LOGE("REQBUFS failed: %s", strerror(errno));
521 return -ENODEV;
522 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700523 if (gralloc_res < 0) {
524 HAL_LOGE("Failed to unlock all buffers when setting up new buffers.");
525 return gralloc_res;
526 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700527
528 // V4L2 will set req_buffers.count to a number of buffers it can handle.
529 max_buffers_ = req_buffers.count;
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700530 // Sanity check.
531 if (max_buffers_ < 1) {
532 HAL_LOGE("REQBUFS claims it can't handle any buffers.");
533 return -ENODEV;
534 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700535 return 0;
536}
537
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700538int V4L2Wrapper::EnqueueBuffer(const camera3_stream_buffer_t* camera_buffer) {
539 HAL_LOG_ENTER();
540
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700541 if (!format_) {
542 HAL_LOGE("Stream format must be set before enqueuing buffers.");
543 return -ENODEV;
544 }
545
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700546 // Set up a v4l2 buffer struct.
547 v4l2_buffer device_buffer;
548 memset(&device_buffer, 0, sizeof(device_buffer));
549 device_buffer.type = format_->type();
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700550 // TODO(b/29334616): when this is async, actually limit the number
551 // of buffers used to the known max, and set this according to the
552 // queue length.
553 device_buffer.index = 0;
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700554
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700555 // Use QUERYBUF to ensure our buffer/device is in good shape,
556 // and fill out remaining fields.
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700557 if (IoctlLocked(VIDIOC_QUERYBUF, &device_buffer) < 0) {
558 HAL_LOGE("QUERYBUF fails: %s", strerror(errno));
559 return -ENODEV;
560 }
561
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700562 // Lock the buffer for writing (fills in the user pointer field).
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700563 int res =
564 gralloc_->lock(camera_buffer, format_->bytes_per_line(), &device_buffer);
565 if (res) {
566 HAL_LOGE("Gralloc failed to lock buffer.");
567 return res;
568 }
569 if (IoctlLocked(VIDIOC_QBUF, &device_buffer) < 0) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700570 HAL_LOGE("QBUF fails: %s", strerror(errno));
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700571 gralloc_->unlock(&device_buffer);
572 return -ENODEV;
573 }
574
575 return 0;
576}
577
578int V4L2Wrapper::DequeueBuffer(v4l2_buffer* buffer) {
579 HAL_LOG_ENTER();
580
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700581 if (!format_) {
582 HAL_LOGE("Stream format must be set before dequeueing buffers.");
583 return -ENODEV;
584 }
585
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700586 memset(buffer, 0, sizeof(*buffer));
587 buffer->type = format_->type();
588 buffer->memory = V4L2_MEMORY_USERPTR;
589 if (IoctlLocked(VIDIOC_DQBUF, buffer) < 0) {
590 HAL_LOGE("DQBUF fails: %s", strerror(errno));
591 return -ENODEV;
592 }
593
594 // Now that we're done painting the buffer, we can unlock it.
595 int res = gralloc_->unlock(buffer);
596 if (res) {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700597 HAL_LOGE("Gralloc failed to unlock buffer after dequeueing.");
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700598 return res;
599 }
600
601 return 0;
602}
603
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700604} // namespace v4l2_camera_hal