blob: 3fafffd27cd1c7a192f8cd56732b6e2e28f9432d [file] [log] [blame]
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -07001/*
2 * Copyright 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Ari Hausman-Cohen3841a7f2016-07-19 17:27:52 -070017#include "v4l2_wrapper.h"
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070018
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070019#include <algorithm>
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -070020#include <array>
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070021#include <limits>
Ari Hausman-Cohen2d1ea3a2017-03-24 18:38:16 -070022#include <mutex>
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070023#include <vector>
24
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070025#include <fcntl.h>
26#include <linux/videodev2.h>
27#include <sys/stat.h>
28#include <sys/types.h>
29
Ari Hausman-Cohen2d1ea3a2017-03-24 18:38:16 -070030#include <android-base/unique_fd.h>
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070031
Ari Hausman-Cohen3841a7f2016-07-19 17:27:52 -070032#include "common.h"
Ari Hausman-Cohen3841a7f2016-07-19 17:27:52 -070033#include "stream_format.h"
34#include "v4l2_gralloc.h"
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070035
36namespace v4l2_camera_hal {
37
Ari Hausman-Cohenc9bfa592016-11-29 18:37:18 -080038const int32_t kStandardSizes[][2] = {{640, 480}, {320, 240}};
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070039
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -070040V4L2Wrapper* V4L2Wrapper::NewV4L2Wrapper(const std::string device_path) {
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -070041 std::unique_ptr<V4L2Gralloc> gralloc(V4L2Gralloc::NewV4L2Gralloc());
42 if (!gralloc) {
43 HAL_LOGE("Failed to initialize gralloc helper.");
44 return nullptr;
45 }
46
47 return new V4L2Wrapper(device_path, std::move(gralloc));
48}
49
50V4L2Wrapper::V4L2Wrapper(const std::string device_path,
51 std::unique_ptr<V4L2Gralloc> gralloc)
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -070052 : device_path_(std::move(device_path)),
53 gralloc_(std::move(gralloc)),
Ari Hausman-Cohenad6fe2b2016-11-16 10:48:07 -080054 connection_count_(0) {}
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070055
Ari Hausman-Cohenad6fe2b2016-11-16 10:48:07 -080056V4L2Wrapper::~V4L2Wrapper() {}
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070057
58int V4L2Wrapper::Connect() {
59 HAL_LOG_ENTER();
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070060 std::lock_guard<std::mutex> lock(connection_lock_);
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070061
62 if (connected()) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070063 HAL_LOGV("Camera device %s is already connected.", device_path_.c_str());
64 ++connection_count_;
65 return 0;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070066 }
67
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -080068 // Open in nonblocking mode (DQBUF may return EAGAIN).
69 int fd = TEMP_FAILURE_RETRY(open(device_path_.c_str(), O_RDWR | O_NONBLOCK));
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070070 if (fd < 0) {
71 HAL_LOGE("failed to open %s (%s)", device_path_.c_str(), strerror(errno));
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070072 return -ENODEV;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070073 }
74 device_fd_.reset(fd);
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070075 ++connection_count_;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070076
77 // Check if this connection has the extended control query capability.
78 v4l2_query_ext_ctrl query;
79 query.id = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND;
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070080 extended_query_supported_ = (IoctlLocked(VIDIOC_QUERY_EXT_CTRL, &query) == 0);
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -070081
82 // TODO(b/29185945): confirm this is a supported device.
83 // This is checked by the HAL, but the device at device_path_ may
84 // not be the same one that was there when the HAL was loaded.
85 // (Alternatively, better hotplugging support may make this unecessary
86 // by disabling cameras that get disconnected and checking newly connected
87 // cameras, so Connect() is never called on an unsupported camera)
88 return 0;
89}
90
91void V4L2Wrapper::Disconnect() {
92 HAL_LOG_ENTER();
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070093 std::lock_guard<std::mutex> lock(connection_lock_);
94
95 if (connection_count_ == 0) {
96 // Not connected.
97 HAL_LOGE("Camera device %s is not connected, cannot disconnect.",
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -070098 device_path_.c_str());
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070099 return;
100 }
101
102 --connection_count_;
103 if (connection_count_ > 0) {
104 HAL_LOGV("Disconnected from camera device %s. %d connections remain.",
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -0700105 device_path_.c_str());
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700106 return;
107 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700108
Ari Hausman-Cohen2d1ea3a2017-03-24 18:38:16 -0700109 device_fd_.reset(-1); // Includes close().
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700110 format_.reset();
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700111 buffers_.clear();
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700112 // Closing the device releases all queued buffers back to the user.
113 gralloc_->unlockAllBuffers();
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700114}
115
116// Helper function. Should be used instead of ioctl throughout this class.
117template <typename T>
118int V4L2Wrapper::IoctlLocked(int request, T data) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700119 // Potentially called so many times logging entry is a bad idea.
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700120 std::lock_guard<std::mutex> lock(device_lock_);
121
122 if (!connected()) {
123 HAL_LOGE("Device %s not connected.", device_path_.c_str());
124 return -ENODEV;
125 }
126 return TEMP_FAILURE_RETRY(ioctl(device_fd_.get(), request, data));
127}
128
129int V4L2Wrapper::StreamOn() {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700130 if (!format_) {
131 HAL_LOGE("Stream format must be set before turning on stream.");
132 return -EINVAL;
133 }
134
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700135 int32_t type = format_->type();
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700136 if (IoctlLocked(VIDIOC_STREAMON, &type) < 0) {
137 HAL_LOGE("STREAMON fails: %s", strerror(errno));
138 return -ENODEV;
139 }
140
Ari Hausman-Cohenad6fe2b2016-11-16 10:48:07 -0800141 HAL_LOGV("Stream turned on.");
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700142 return 0;
143}
144
145int V4L2Wrapper::StreamOff() {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700146 if (!format_) {
Ari Hausman-Cohenad6fe2b2016-11-16 10:48:07 -0800147 // Can't have turned on the stream without format being set,
Ari Hausman-Cohen71cb8742016-09-22 11:12:00 -0700148 // so nothing to turn off here.
149 return 0;
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700150 }
151
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700152 int32_t type = format_->type();
153 int res = IoctlLocked(VIDIOC_STREAMOFF, &type);
154 // Calling STREAMOFF releases all queued buffers back to the user.
155 int gralloc_res = gralloc_->unlockAllBuffers();
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800156 // No buffers in flight.
157 for (size_t i = 0; i < buffers_.size(); ++i) {
158 buffers_[i] = false;
159 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700160 if (res < 0) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700161 HAL_LOGE("STREAMOFF fails: %s", strerror(errno));
162 return -ENODEV;
163 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700164 if (gralloc_res < 0) {
165 HAL_LOGE("Failed to unlock all buffers after turning stream off.");
166 return gralloc_res;
167 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700168
Ari Hausman-Cohenad6fe2b2016-11-16 10:48:07 -0800169 HAL_LOGV("Stream turned off.");
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700170 return 0;
171}
172
173int V4L2Wrapper::QueryControl(uint32_t control_id,
174 v4l2_query_ext_ctrl* result) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700175 int res;
176
177 memset(result, 0, sizeof(*result));
178
179 if (extended_query_supported_) {
180 result->id = control_id;
181 res = IoctlLocked(VIDIOC_QUERY_EXT_CTRL, result);
182 // Assuming the operation was supported (not ENOTTY), no more to do.
183 if (errno != ENOTTY) {
184 if (res) {
185 HAL_LOGE("QUERY_EXT_CTRL fails: %s", strerror(errno));
186 return -ENODEV;
187 }
188 return 0;
189 }
190 }
191
192 // Extended control querying not supported, fall back to basic control query.
193 v4l2_queryctrl query;
194 query.id = control_id;
195 if (IoctlLocked(VIDIOC_QUERYCTRL, &query)) {
196 HAL_LOGE("QUERYCTRL fails: %s", strerror(errno));
197 return -ENODEV;
198 }
199
200 // Convert the basic result to the extended result.
201 result->id = query.id;
202 result->type = query.type;
203 memcpy(result->name, query.name, sizeof(query.name));
204 result->minimum = query.minimum;
205 if (query.type == V4L2_CTRL_TYPE_BITMASK) {
206 // According to the V4L2 documentation, when type is BITMASK,
207 // max and default should be interpreted as __u32. Practically,
208 // this means the conversion from 32 bit to 64 will pad with 0s not 1s.
209 result->maximum = static_cast<uint32_t>(query.maximum);
210 result->default_value = static_cast<uint32_t>(query.default_value);
211 } else {
212 result->maximum = query.maximum;
213 result->default_value = query.default_value;
214 }
215 result->step = static_cast<uint32_t>(query.step);
216 result->flags = query.flags;
217 result->elems = 1;
218 switch (result->type) {
219 case V4L2_CTRL_TYPE_INTEGER64:
220 result->elem_size = sizeof(int64_t);
221 break;
222 case V4L2_CTRL_TYPE_STRING:
223 result->elem_size = result->maximum + 1;
224 break;
225 default:
226 result->elem_size = sizeof(int32_t);
227 break;
228 }
229
230 return 0;
231}
232
233int V4L2Wrapper::GetControl(uint32_t control_id, int32_t* value) {
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700234 // For extended controls (any control class other than "user"),
235 // G_EXT_CTRL must be used instead of G_CTRL.
236 if (V4L2_CTRL_ID2CLASS(control_id) != V4L2_CTRL_CLASS_USER) {
237 v4l2_ext_control control;
238 v4l2_ext_controls controls;
239 memset(&control, 0, sizeof(control));
240 memset(&controls, 0, sizeof(controls));
241
242 control.id = control_id;
243 controls.ctrl_class = V4L2_CTRL_ID2CLASS(control_id);
244 controls.count = 1;
245 controls.controls = &control;
246
247 if (IoctlLocked(VIDIOC_G_EXT_CTRLS, &controls) < 0) {
248 HAL_LOGE("G_EXT_CTRLS fails: %s", strerror(errno));
249 return -ENODEV;
250 }
251 *value = control.value;
252 } else {
253 v4l2_control control{control_id, 0};
254 if (IoctlLocked(VIDIOC_G_CTRL, &control) < 0) {
255 HAL_LOGE("G_CTRL fails: %s", strerror(errno));
256 return -ENODEV;
257 }
258 *value = control.value;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700259 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700260 return 0;
261}
262
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700263int V4L2Wrapper::SetControl(uint32_t control_id,
264 int32_t desired,
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700265 int32_t* result) {
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700266 int32_t result_value = 0;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700267
Ari Hausman-Cohen99f3ea02016-08-02 10:47:07 -0700268 // TODO(b/29334616): When async, this may need to check if the stream
269 // is on, and if so, lock it off while setting format. Need to look
270 // into if V4L2 supports adjusting controls while the stream is on.
271
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700272 // For extended controls (any control class other than "user"),
273 // S_EXT_CTRL must be used instead of S_CTRL.
274 if (V4L2_CTRL_ID2CLASS(control_id) != V4L2_CTRL_CLASS_USER) {
275 v4l2_ext_control control;
276 v4l2_ext_controls controls;
277 memset(&control, 0, sizeof(control));
278 memset(&controls, 0, sizeof(controls));
279
280 control.id = control_id;
281 control.value = desired;
282 controls.ctrl_class = V4L2_CTRL_ID2CLASS(control_id);
283 controls.count = 1;
284 controls.controls = &control;
285
286 if (IoctlLocked(VIDIOC_S_EXT_CTRLS, &controls) < 0) {
287 HAL_LOGE("S_EXT_CTRLS fails: %s", strerror(errno));
288 return -ENODEV;
289 }
290 result_value = control.value;
291 } else {
292 v4l2_control control{control_id, desired};
293 if (IoctlLocked(VIDIOC_S_CTRL, &control) < 0) {
294 HAL_LOGE("S_CTRL fails: %s", strerror(errno));
295 return -ENODEV;
296 }
297 result_value = control.value;
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700298 }
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700299
Ari Hausman-Cohen99f3ea02016-08-02 10:47:07 -0700300 // If the caller wants to know the result, pass it back.
301 if (result != nullptr) {
Ari Hausman-Cohen7a1fba62016-08-10 11:31:04 -0700302 *result = result_value;
Ari Hausman-Cohen99f3ea02016-08-02 10:47:07 -0700303 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700304 return 0;
305}
306
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700307int V4L2Wrapper::GetFormats(std::set<uint32_t>* v4l2_formats) {
308 HAL_LOG_ENTER();
309
310 v4l2_fmtdesc format_query;
311 memset(&format_query, 0, sizeof(format_query));
312 // TODO(b/30000211): multiplanar support.
313 format_query.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
314 while (IoctlLocked(VIDIOC_ENUM_FMT, &format_query) >= 0) {
315 v4l2_formats->insert(format_query.pixelformat);
316 ++format_query.index;
317 }
318
319 if (errno != EINVAL) {
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700320 HAL_LOGE(
321 "ENUM_FMT fails at index %d: %s", format_query.index, strerror(errno));
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700322 return -ENODEV;
323 }
324 return 0;
325}
326
327int V4L2Wrapper::GetFormatFrameSizes(uint32_t v4l2_format,
328 std::set<std::array<int32_t, 2>>* sizes) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700329 v4l2_frmsizeenum size_query;
330 memset(&size_query, 0, sizeof(size_query));
331 size_query.pixel_format = v4l2_format;
332 if (IoctlLocked(VIDIOC_ENUM_FRAMESIZES, &size_query) < 0) {
333 HAL_LOGE("ENUM_FRAMESIZES failed: %s", strerror(errno));
334 return -ENODEV;
335 }
336 if (size_query.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
337 // Discrete: enumerate all sizes using VIDIOC_ENUM_FRAMESIZES.
338 // Assuming that a driver with discrete frame sizes has a reasonable number
339 // of them.
340 do {
341 sizes->insert({{{static_cast<int32_t>(size_query.discrete.width),
342 static_cast<int32_t>(size_query.discrete.height)}}});
343 ++size_query.index;
344 } while (IoctlLocked(VIDIOC_ENUM_FRAMESIZES, &size_query) >= 0);
345 if (errno != EINVAL) {
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700346 HAL_LOGE("ENUM_FRAMESIZES fails at index %d: %s",
347 size_query.index,
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700348 strerror(errno));
349 return -ENODEV;
350 }
351 } else {
352 // Continuous/Step-wise: based on the stepwise struct returned by the query.
353 // Fully listing all possible sizes, with large enough range/small enough
354 // step size, may produce far too many potential sizes. Instead, find the
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800355 // closest to a set of standard sizes.
Ari Hausman-Cohenabbf9cc2016-08-23 11:59:59 -0700356 for (const auto size : kStandardSizes) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700357 // Find the closest size, rounding up.
358 uint32_t desired_width = size[0];
359 uint32_t desired_height = size[1];
360 if (desired_width < size_query.stepwise.min_width ||
361 desired_height < size_query.stepwise.min_height) {
362 HAL_LOGV("Standard size %u x %u is too small for format %d",
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700363 desired_width,
364 desired_height,
365 v4l2_format);
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700366 continue;
367 } else if (desired_width > size_query.stepwise.max_width &&
368 desired_height > size_query.stepwise.max_height) {
369 HAL_LOGV("Standard size %u x %u is too big for format %d",
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700370 desired_width,
371 desired_height,
372 v4l2_format);
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700373 continue;
374 }
375
376 // Round up.
377 uint32_t width_steps = (desired_width - size_query.stepwise.min_width +
378 size_query.stepwise.step_width - 1) /
379 size_query.stepwise.step_width;
380 uint32_t height_steps = (desired_height - size_query.stepwise.min_height +
381 size_query.stepwise.step_height - 1) /
382 size_query.stepwise.step_height;
383 sizes->insert(
384 {{{static_cast<int32_t>(size_query.stepwise.min_width +
385 width_steps * size_query.stepwise.step_width),
386 static_cast<int32_t>(size_query.stepwise.min_height +
387 height_steps *
388 size_query.stepwise.step_height)}}});
389 }
390 }
391 return 0;
392}
393
394// Converts a v4l2_fract with units of seconds to an int64_t with units of ns.
395inline int64_t FractToNs(const v4l2_fract& fract) {
396 return (1000000000LL * fract.numerator) / fract.denominator;
397}
398
399int V4L2Wrapper::GetFormatFrameDurationRange(
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700400 uint32_t v4l2_format,
401 const std::array<int32_t, 2>& size,
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700402 std::array<int64_t, 2>* duration_range) {
403 // Potentially called so many times logging entry is a bad idea.
404
405 v4l2_frmivalenum duration_query;
406 memset(&duration_query, 0, sizeof(duration_query));
407 duration_query.pixel_format = v4l2_format;
408 duration_query.width = size[0];
409 duration_query.height = size[1];
410 if (IoctlLocked(VIDIOC_ENUM_FRAMEINTERVALS, &duration_query) < 0) {
411 HAL_LOGE("ENUM_FRAMEINTERVALS failed: %s", strerror(errno));
412 return -ENODEV;
413 }
414
415 int64_t min = std::numeric_limits<int64_t>::max();
416 int64_t max = std::numeric_limits<int64_t>::min();
417 if (duration_query.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
418 // Discrete: enumerate all durations using VIDIOC_ENUM_FRAMEINTERVALS.
419 do {
420 min = std::min(min, FractToNs(duration_query.discrete));
421 max = std::max(max, FractToNs(duration_query.discrete));
422 ++duration_query.index;
423 } while (IoctlLocked(VIDIOC_ENUM_FRAMEINTERVALS, &duration_query) >= 0);
424 if (errno != EINVAL) {
425 HAL_LOGE("ENUM_FRAMEINTERVALS fails at index %d: %s",
Ari Hausman-Cohen5d753232016-08-10 14:27:36 -0700426 duration_query.index,
427 strerror(errno));
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700428 return -ENODEV;
429 }
430 } else {
431 // Continuous/Step-wise: simply convert the given min and max.
432 min = FractToNs(duration_query.stepwise.min);
433 max = FractToNs(duration_query.stepwise.max);
434 }
435 (*duration_range)[0] = min;
436 (*duration_range)[1] = max;
437 return 0;
438}
439
Ari Hausman-Cohenef523102016-11-21 17:02:01 -0800440int V4L2Wrapper::SetFormat(const StreamFormat& desired_format,
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700441 uint32_t* result_max_buffers) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700442 HAL_LOG_ENTER();
443
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700444 if (format_ && desired_format == *format_) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700445 HAL_LOGV("Already in correct format, skipping format setting.");
Ari Hausman-Cohena5c9bfd2016-11-18 14:57:07 -0800446 *result_max_buffers = buffers_.size();
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700447 return 0;
448 }
449
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800450 // Not in the correct format, set the new one.
451
452 if (format_) {
453 // If we had an old format, first request 0 buffers to inform the device
454 // we're no longer using any previously "allocated" buffers from the old
455 // format. This seems like it shouldn't be necessary for USERPTR memory,
456 // and/or should happen from turning the stream off, but the driver
457 // complained. May be a driver issue, or may be intended behavior.
458 int res = RequestBuffers(0);
459 if (res) {
460 return res;
461 }
462 }
463
464 // Set the camera to the new format.
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700465 v4l2_format new_format;
466 desired_format.FillFormatRequest(&new_format);
467 // TODO(b/29334616): When async, this will need to check if the stream
468 // is on, and if so, lock it off while setting format.
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800469
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700470 if (IoctlLocked(VIDIOC_S_FMT, &new_format) < 0) {
471 HAL_LOGE("S_FMT failed: %s", strerror(errno));
472 return -ENODEV;
473 }
474
475 // Check that the driver actually set to the requested values.
476 if (desired_format != new_format) {
477 HAL_LOGE("Device doesn't support desired stream configuration.");
478 return -EINVAL;
479 }
480
481 // Keep track of our new format.
482 format_.reset(new StreamFormat(new_format));
483
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800484 // Format changed, request new buffers.
485 int res = RequestBuffers(1);
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700486 if (res) {
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800487 HAL_LOGE("Requesting buffers for new format failed.");
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700488 return res;
489 }
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700490 *result_max_buffers = buffers_.size();
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700491 return 0;
492}
493
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800494int V4L2Wrapper::RequestBuffers(uint32_t num_requested) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700495 v4l2_requestbuffers req_buffers;
496 memset(&req_buffers, 0, sizeof(req_buffers));
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700497 req_buffers.type = format_->type();
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700498 req_buffers.memory = V4L2_MEMORY_USERPTR;
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800499 req_buffers.count = num_requested;
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700500
501 int res = IoctlLocked(VIDIOC_REQBUFS, &req_buffers);
502 // Calling REQBUFS releases all queued buffers back to the user.
503 int gralloc_res = gralloc_->unlockAllBuffers();
504 if (res < 0) {
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700505 HAL_LOGE("REQBUFS failed: %s", strerror(errno));
506 return -ENODEV;
507 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700508 if (gralloc_res < 0) {
509 HAL_LOGE("Failed to unlock all buffers when setting up new buffers.");
510 return gralloc_res;
511 }
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700512
513 // V4L2 will set req_buffers.count to a number of buffers it can handle.
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800514 if (num_requested > 0 && req_buffers.count < 1) {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700515 HAL_LOGE("REQBUFS claims it can't handle any buffers.");
516 return -ENODEV;
517 }
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700518 buffers_.resize(req_buffers.count, false);
519
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700520 return 0;
521}
522
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800523int V4L2Wrapper::EnqueueBuffer(const camera3_stream_buffer_t* camera_buffer,
524 uint32_t* enqueued_index) {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700525 if (!format_) {
526 HAL_LOGE("Stream format must be set before enqueuing buffers.");
527 return -ENODEV;
528 }
529
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700530 // Find a free buffer index. Could use some sort of persistent hinting
531 // here to improve expected efficiency, but buffers_.size() is expected
532 // to be low enough (<10 experimentally) that it's not worth it.
533 int index = -1;
534 {
535 std::lock_guard<std::mutex> guard(buffer_queue_lock_);
536 for (int i = 0; i < buffers_.size(); ++i) {
537 if (!buffers_[i]) {
538 index = i;
539 break;
540 }
541 }
542 }
543 if (index < 0) {
544 // Note: The HAL should be tracking the number of buffers in flight
545 // for each stream, and should never overflow the device.
546 HAL_LOGE("Cannot enqueue buffer: stream is already full.");
547 return -ENODEV;
548 }
549
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700550 // Set up a v4l2 buffer struct.
551 v4l2_buffer device_buffer;
552 memset(&device_buffer, 0, sizeof(device_buffer));
553 device_buffer.type = format_->type();
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700554 device_buffer.index = index;
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700555
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700556 // Use QUERYBUF to ensure our buffer/device is in good shape,
557 // and fill out remaining fields.
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700558 if (IoctlLocked(VIDIOC_QUERYBUF, &device_buffer) < 0) {
559 HAL_LOGE("QUERYBUF fails: %s", strerror(errno));
560 return -ENODEV;
561 }
562
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700563 // Lock the buffer for writing (fills in the user pointer field).
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700564 int res =
565 gralloc_->lock(camera_buffer, format_->bytes_per_line(), &device_buffer);
566 if (res) {
567 HAL_LOGE("Gralloc failed to lock buffer.");
568 return res;
569 }
570 if (IoctlLocked(VIDIOC_QBUF, &device_buffer) < 0) {
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700571 HAL_LOGE("QBUF fails: %s", strerror(errno));
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700572 gralloc_->unlock(&device_buffer);
573 return -ENODEV;
574 }
575
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700576 // Mark the buffer as in flight.
577 std::lock_guard<std::mutex> guard(buffer_queue_lock_);
578 buffers_[index] = true;
579
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800580 if (enqueued_index) {
581 *enqueued_index = index;
582 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700583 return 0;
584}
585
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800586int V4L2Wrapper::DequeueBuffer(uint32_t* dequeued_index) {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700587 if (!format_) {
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800588 HAL_LOGV(
589 "Format not set, so stream can't be on, "
590 "so no buffers available for dequeueing");
591 return -EAGAIN;
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700592 }
593
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800594 v4l2_buffer buffer;
595 memset(&buffer, 0, sizeof(buffer));
596 buffer.type = format_->type();
597 buffer.memory = V4L2_MEMORY_USERPTR;
598 int res = IoctlLocked(VIDIOC_DQBUF, &buffer);
599 if (res) {
600 if (errno == EAGAIN) {
601 // Expected failure.
602 return -EAGAIN;
603 } else {
604 // Unexpected failure.
605 HAL_LOGE("DQBUF fails: %s", strerror(errno));
606 return -ENODEV;
607 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700608 }
609
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700610 // Mark the buffer as no longer in flight.
611 {
612 std::lock_guard<std::mutex> guard(buffer_queue_lock_);
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800613 buffers_[buffer.index] = false;
Ari Hausman-Cohen0fbcaf52016-09-28 13:21:31 -0700614 }
615
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700616 // Now that we're done painting the buffer, we can unlock it.
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800617 res = gralloc_->unlock(&buffer);
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700618 if (res) {
Ari Hausman-Cohen660f8b82016-07-19 17:27:52 -0700619 HAL_LOGE("Gralloc failed to unlock buffer after dequeueing.");
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700620 return res;
621 }
622
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800623 if (dequeued_index) {
624 *dequeued_index = buffer.index;
625 }
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700626 return 0;
627}
628
Ari Hausman-Cohenc17fd092016-07-18 10:13:26 -0700629} // namespace v4l2_camera_hal