1 /*
2 * v4l2_device.cpp - v4l2 device
3 *
4 * Copyright (c) 2014-2015 Intel Corporation
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * Author: Wind Yuan <feng.yuan@intel.com>
19 * Author: John Ye <john.ye@intel.com>
20 */
21
22 #include "v4l2_device.h"
23 #include <sys/ioctl.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <poll.h>
28 #include <errno.h>
29 #include <sys/mman.h>
30
31 #include "v4l2_buffer_proxy.h"
32
33 namespace XCam {
34
35 #define XCAM_V4L2_DEFAULT_BUFFER_COUNT 4
36
V4l2Device(const char * name)37 V4l2Device::V4l2Device (const char *name)
38 : _name (NULL)
39 , _fd (-1)
40 , _sensor_id (0)
41 , _capture_mode (0)
42 , _buf_type (V4L2_BUF_TYPE_VIDEO_CAPTURE)
43 , _buf_sync (false)
44 , _memory_type (V4L2_MEMORY_MMAP)
45 , _planes (NULL)
46 , _fps_n (0)
47 , _fps_d (0)
48 , _active (false)
49 , _buf_count (XCAM_V4L2_DEFAULT_BUFFER_COUNT)
50 , _queued_bufcnt(0)
51 ,_mplanes_count(FMT_NUM_PLANES)
52 {
53 if (name)
54 _name = strndup (name, XCAM_MAX_STR_SIZE);
55 xcam_mem_clear (_format);
56 }
57
~V4l2Device()58 V4l2Device::~V4l2Device ()
59 {
60 close();
61 if (_name)
62 xcam_free (_name);
63 if (_planes)
64 xcam_free (_planes);
65 }
66
67 bool
set_device_name(const char * name)68 V4l2Device::set_device_name (const char *name)
69 {
70 XCAM_ASSERT (name);
71
72 if (is_opened()) {
73 XCAM_LOG_WARNING ("can't set device name since device opened");
74 return false;
75 }
76 if (_name)
77 xcam_free (_name);
78 _name = strndup (name, XCAM_MAX_STR_SIZE);
79 return true;
80 }
81
82 bool
set_sensor_id(int id)83 V4l2Device::set_sensor_id (int id)
84 {
85 if (is_opened()) {
86 XCAM_LOG_WARNING ("can't set sensor id since device opened");
87 return false;
88 }
89 _sensor_id = id;
90 return true;
91 }
92
93 bool
set_capture_mode(uint32_t capture_mode)94 V4l2Device::set_capture_mode (uint32_t capture_mode)
95 {
96 if (is_opened()) {
97 XCAM_LOG_WARNING ("can't set sensor id since device opened");
98 return false;
99 }
100 _capture_mode = capture_mode;
101 return true;
102 }
103
104 bool
set_mplanes_count(uint32_t planes_count)105 V4l2Device::set_mplanes_count (uint32_t planes_count)
106 {
107 if (is_activated ()) {
108 XCAM_LOG_WARNING ("device(%s) set mplanes count failed", XCAM_STR (_name));
109 return false;
110 }
111 _mplanes_count = planes_count;
112 return true;
113 }
114
115 bool
set_framerate(uint32_t n,uint32_t d)116 V4l2Device::set_framerate (uint32_t n, uint32_t d)
117 {
118 if (_format.fmt.pix.pixelformat) {
119 XCAM_LOG_WARNING ("device(%s) set framerate failed since formatted was already set.", XCAM_STR(_name));
120 return false;
121 }
122
123 _fps_n = n;
124 _fps_d = d;
125
126 return true;
127 }
128
129 void
get_framerate(uint32_t & n,uint32_t & d)130 V4l2Device::get_framerate (uint32_t &n, uint32_t &d)
131 {
132 n = _fps_n;
133 d = _fps_d;
134 }
135
136 bool
set_mem_type(enum v4l2_memory type)137 V4l2Device::set_mem_type (enum v4l2_memory type) {
138 if (is_activated ()) {
139 XCAM_LOG_WARNING ("device(%s) set mem type failed", XCAM_STR (_name));
140 return false;
141 }
142 _memory_type = type;
143 return true;
144 }
145
146 bool
set_buf_type(enum v4l2_buf_type type)147 V4l2Device::set_buf_type (enum v4l2_buf_type type) {
148 if (is_activated ()) {
149 XCAM_LOG_WARNING ("device(%s) set buf type failed", XCAM_STR (_name));
150 return false;
151 }
152 _buf_type = type;
153 return true;
154 }
155
156 bool
set_buf_sync(bool sync)157 V4l2Device::set_buf_sync (bool sync) {
158 if (is_activated ()) {
159 XCAM_LOG_WARNING ("device(%s) set buf sync failed", XCAM_STR (_name));
160 return false;
161 }
162 _buf_sync = sync;
163 return true;
164 }
165
166 bool
set_buffer_count(uint32_t buf_count)167 V4l2Device::set_buffer_count (uint32_t buf_count)
168 {
169 if (is_activated ()) {
170 XCAM_LOG_WARNING ("device(%s) set buffer count failed", XCAM_STR (_name));
171 return false;
172 }
173
174 _buf_count = buf_count;
175
176 return true;
177 }
178
179
180 XCamReturn
open(bool nonblock)181 V4l2Device::open (bool nonblock)
182 {
183 struct v4l2_streamparm param;
184
185 if (is_opened()) {
186 XCAM_LOG_DEBUG ("device(%s) was already opened", XCAM_STR(_name));
187 return XCAM_RETURN_NO_ERROR;
188 }
189
190 if (!_name) {
191 XCAM_LOG_DEBUG ("v4l2 device open failed, there's no device name");
192 return XCAM_RETURN_ERROR_PARAM;
193 }
194 if (nonblock)
195 _fd = ::open (_name, O_RDWR | O_CLOEXEC | O_NONBLOCK);
196 else
197 _fd = ::open (_name, O_RDWR | O_CLOEXEC);
198 if (_fd == -1) {
199 XCAM_LOG_ERROR ("open device(%s) failed", _name);
200 return XCAM_RETURN_ERROR_IOCTL;
201 } else {
202 XCAM_LOG_DEBUG ("open device(%s) successed, fd: %d", _name, _fd);
203 }
204 #if 0
205 // set sensor id
206 if (io_control (VIDIOC_S_INPUT, &_sensor_id) < 0) {
207 XCAM_LOG_WARNING ("set sensor id(%d) failed but continue", _sensor_id);
208 }
209
210 // set capture mode
211 xcam_mem_clear (param);
212 param.type = _buf_type;
213 param.parm.capture.capturemode = _capture_mode;
214 if (io_control (VIDIOC_S_PARM, ¶m) < 0) {
215 XCAM_LOG_WARNING ("set capture mode(0x%08x) failed but continue", _capture_mode);
216 }
217 #endif
218 struct v4l2_capability cap;
219 // only video node cay query cap
220 if (_name && strstr(_name, "video")) {
221 query_cap(cap);
222 // get default foramt
223 get_format (_format);
224 }
225
226 if (_buf_type == V4L2_BUF_TYPE_META_CAPTURE)
227 _buf_sync = true;
228
229 return XCAM_RETURN_NO_ERROR;
230 }
231
232 XCamReturn
close()233 V4l2Device::close ()
234 {
235 if (!is_opened())
236 return XCAM_RETURN_NO_ERROR;
237 ::close (_fd);
238 _fd = -1;
239
240 XCAM_LOG_INFO ("device(%s) closed", XCAM_STR (_name));
241 return XCAM_RETURN_NO_ERROR;
242 }
243
244 int
io_control(unsigned long cmd,void * arg)245 V4l2Device::io_control (unsigned long cmd, void *arg)
246
247 {
248 if (_fd <= 0)
249 return -1;
250
251 return xcam_device_ioctl (_fd, cmd, arg);
252 }
253
254 int
poll_event(int timeout_msec,int stop_fd)255 V4l2Device::poll_event (int timeout_msec, int stop_fd)
256 {
257 int num_fds = stop_fd == -1 ? 1 : 2;
258 struct pollfd poll_fds[num_fds];
259 int ret = 0;
260
261 XCAM_ASSERT (_fd > 0);
262
263 memset(poll_fds, 0, sizeof(poll_fds));
264 poll_fds[0].fd = _fd;
265 poll_fds[0].events = (POLLPRI | POLLIN | POLLOUT | POLLERR | POLLNVAL | POLLHUP);
266
267 if (stop_fd != -1) {
268 poll_fds[1].fd = stop_fd;
269 poll_fds[1].events = POLLPRI | POLLIN | POLLOUT;
270 poll_fds[1].revents = 0;
271 }
272
273 ret = poll (poll_fds, num_fds, timeout_msec);
274 if (stop_fd != -1) {
275 if ((poll_fds[1].revents & POLLIN) || (poll_fds[1].revents & POLLPRI)) {
276 XCAM_LOG_DEBUG ("%s: Poll returning from flush", __FUNCTION__);
277 return POLL_STOP_RET;
278 }
279 }
280
281 if (ret > 0 && (poll_fds[0].revents & (POLLERR | POLLNVAL | POLLHUP))) {
282 XCAM_LOG_DEBUG ("v4l2 subdev(%s) polled error", XCAM_STR(_name));
283 return -1;
284 }
285
286 return ret;
287
288 }
289
290 XCamReturn
query_cap(struct v4l2_capability & cap)291 V4l2Device::query_cap (struct v4l2_capability &cap)
292 {
293 int ret = 0;
294
295 XCAM_FAIL_RETURN (ERROR, is_opened (), XCAM_RETURN_ERROR_FILE,
296 "Cannot query cap from v4l2 device while it is closed.");
297
298 ret = io_control(VIDIOC_QUERYCAP, &cap);
299
300 if (ret < 0) {
301 XCAM_LOG_ERROR("VIDIOC_QUERYCAP returned: %d (%s)", ret, strerror(errno));
302 return XCAM_RETURN_ERROR_UNKNOWN;
303 }
304
305 if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)
306 _buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
307 else if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE)
308 _buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
309 else if (cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)
310 _buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
311 else if (cap.capabilities & V4L2_CAP_VIDEO_OUTPUT_MPLANE)
312 _buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
313 else if (cap.capabilities & V4L2_CAP_META_CAPTURE)
314 _buf_type = V4L2_BUF_TYPE_META_CAPTURE;
315 else if (cap.capabilities & V4L2_CAP_META_OUTPUT)
316 _buf_type = V4L2_BUF_TYPE_META_OUTPUT;
317 else {
318 XCAM_LOG_ERROR("@%s: unsupported buffer type.", __FUNCTION__);
319 return XCAM_RETURN_ERROR_UNKNOWN;
320 }
321
322 XCAM_LOG_INFO("------------------------------");
323 XCAM_LOG_INFO("driver: '%s'", cap.driver);
324 XCAM_LOG_INFO("card: '%s'", cap.card);
325 XCAM_LOG_INFO("bus_info: '%s'", cap.bus_info);
326 XCAM_LOG_INFO("version: %x", cap.version);
327 XCAM_LOG_INFO("capabilities: %x", cap.capabilities);
328 XCAM_LOG_INFO("device caps: %x", cap.device_caps);
329 XCAM_LOG_INFO("buffer type %d", _buf_type);
330 XCAM_LOG_INFO("------------------------------");
331
332 return XCAM_RETURN_NO_ERROR;
333 }
334
335 XCamReturn
set_format(struct v4l2_format & format)336 V4l2Device::set_format (struct v4l2_format &format)
337 {
338 XCamReturn ret = XCAM_RETURN_NO_ERROR;
339
340 XCAM_FAIL_RETURN (ERROR, !is_activated (), XCAM_RETURN_ERROR_PARAM,
341 "Cannot set format to v4l2 device while it is active.");
342
343 XCAM_FAIL_RETURN (ERROR, is_opened (), XCAM_RETURN_ERROR_FILE,
344 "Cannot set format to v4l2 device while it is closed.");
345
346 struct v4l2_format tmp_format = format;
347
348 ret = pre_set_format (format);
349 if (ret != XCAM_RETURN_NO_ERROR) {
350 XCAM_LOG_WARNING ("device(%s) pre_set_format failed", XCAM_STR (_name));
351 //RKTODO::rkisp no need to do set format op for subdev.
352 //return ret;
353 }
354
355 if (io_control (VIDIOC_S_FMT, &format) < 0) {
356 if (errno == EBUSY) {
357 // TODO log device name
358 XCAM_LOG_ERROR("Video device is busy, fail to set format.");
359 } else {
360 // TODO log format details and errno
361 XCAM_LOG_ERROR("Fail to set format: %s", strerror(errno));
362 }
363
364 return XCAM_RETURN_ERROR_IOCTL;
365 }
366
367 if (tmp_format.fmt.pix.width != format.fmt.pix.width || tmp_format.fmt.pix.height != format.fmt.pix.height) {
368 XCAM_LOG_ERROR (
369 "device(%s) set v4l2 format failed, supported format: width:%d, height:%d",
370 XCAM_STR (_name),
371 format.fmt.pix.width,
372 format.fmt.pix.height);
373
374 return XCAM_RETURN_ERROR_PARAM;
375 }
376
377 while (_fps_n && _fps_d) {
378 struct v4l2_streamparm param;
379 xcam_mem_clear (param);
380 param.type = _buf_type;
381 if (io_control (VIDIOC_G_PARM, ¶m) < 0) {
382 XCAM_LOG_WARNING ("device(%s) set framerate failed on VIDIOC_G_PARM but continue", XCAM_STR (_name));
383 break;
384 }
385
386 if (!(param.parm.capture.capability & V4L2_CAP_TIMEPERFRAME))
387 break;
388
389 param.parm.capture.timeperframe.numerator = _fps_d;
390 param.parm.capture.timeperframe.denominator = _fps_n;
391
392 if (io_control (VIDIOC_S_PARM, ¶m) < 0) {
393 XCAM_LOG_WARNING ("device(%s) set framerate failed on VIDIOC_S_PARM but continue", XCAM_STR (_name));
394 break;
395 }
396 _fps_n = param.parm.capture.timeperframe.denominator;
397 _fps_d = param.parm.capture.timeperframe.numerator;
398 XCAM_LOG_INFO ("device(%s) set framerate(%d/%d)", XCAM_STR (_name), _fps_n, _fps_d);
399
400 // exit here, otherwise it is an infinite loop
401 break;
402 }
403
404 ret = post_set_format (format);
405 if (ret != XCAM_RETURN_NO_ERROR) {
406 XCAM_LOG_WARNING ("device(%s) post_set_format failed", XCAM_STR (_name));
407 return ret;
408 }
409
410 _format = format;
411 XCAM_LOG_INFO (
412 "device(%s) set format(w:%d, h:%d, pixelformat:%s, bytesperline:%d,image_size:%d)",
413 XCAM_STR (_name),
414 format.fmt.pix.width, format.fmt.pix.height,
415 xcam_fourcc_to_string (format.fmt.pix.pixelformat),
416 format.fmt.pix.bytesperline,
417 format.fmt.pix.sizeimage);
418
419 return XCAM_RETURN_NO_ERROR;
420 }
421
422 /*! \brief v4l2 set format
423 *
424 * \param[in] width format width
425 * \param[in] height format height
426 * \param[in] pixelformat fourcc
427 * \param[in] field V4L2_FIELD_INTERLACED or V4L2_FIELD_NONE
428 */
429 XCamReturn
set_format(uint32_t width,uint32_t height,uint32_t pixelformat,enum v4l2_field field,uint32_t bytes_perline)430 V4l2Device::set_format (
431 uint32_t width, uint32_t height,
432 uint32_t pixelformat, enum v4l2_field field, uint32_t bytes_perline)
433 {
434 XCAM_LOG_INFO (
435 "device(%s) set format(w:%d, h:%d, pixelformat:%s, bytesperline:%d)",
436 XCAM_STR (_name),
437 width, height,
438 xcam_fourcc_to_string (pixelformat),
439 bytes_perline);
440
441 struct v4l2_format format;
442 xcam_mem_clear (format);
443
444 format.type = _buf_type;
445 format.fmt.pix.width = width;
446 format.fmt.pix.height = height;
447 format.fmt.pix.pixelformat = pixelformat;
448 format.fmt.pix.field = field;
449
450 if (bytes_perline != 0)
451 format.fmt.pix.bytesperline = bytes_perline;
452 return set_format (format);
453 }
454
455 XCamReturn
pre_set_format(struct v4l2_format & format)456 V4l2Device::pre_set_format (struct v4l2_format &format)
457 {
458 XCAM_UNUSED (format);
459 return XCAM_RETURN_NO_ERROR;
460 }
461
462 XCamReturn
post_set_format(struct v4l2_format & format)463 V4l2Device::post_set_format (struct v4l2_format &format)
464 {
465 XCAM_UNUSED (format);
466 return XCAM_RETURN_NO_ERROR;
467 }
468
469 std::list<struct v4l2_fmtdesc>
enum_formats()470 V4l2Device::enum_formats ()
471 {
472 std::list<struct v4l2_fmtdesc> formats;
473 struct v4l2_fmtdesc format;
474 uint32_t i = 0;
475
476 while (1) {
477 xcam_mem_clear (format);
478 format.index = i++;
479 format.type = _buf_type;
480 if (this->io_control (VIDIOC_ENUM_FMT, &format) < 0) {
481 if (errno == EINVAL)
482 break;
483 else { // error
484 XCAM_LOG_DEBUG ("enum formats failed");
485 return formats;
486 }
487 }
488 formats.push_back (format);
489 }
490
491 return formats;
492 }
493
494 XCamReturn
get_format(struct v4l2_format & format)495 V4l2Device::get_format (struct v4l2_format &format)
496 {
497 if (is_activated ()) {
498 format = _format;
499 return XCAM_RETURN_NO_ERROR;
500 }
501
502 if (!is_opened ())
503 return XCAM_RETURN_ERROR_IOCTL;
504
505 xcam_mem_clear (format);
506 format.type = _buf_type;
507
508 if (this->io_control (VIDIOC_G_FMT, &format) < 0) {
509 // FIXME: also log the device name?
510 XCAM_LOG_ERROR("Fail to get format via ioctl VIDVIO_G_FMT.");
511 return XCAM_RETURN_ERROR_IOCTL;
512 }
513
514 return XCAM_RETURN_NO_ERROR;
515 }
516
517 XCamReturn
prepare()518 V4l2Device::prepare ()
519 {
520 XCamReturn ret = XCAM_RETURN_NO_ERROR;
521 // request buffer first
522 ret = request_buffer ();
523 XCAM_FAIL_RETURN (
524 ERROR, ret == XCAM_RETURN_NO_ERROR, ret,
525 "device(%s) start failed", XCAM_STR (_name));
526 _queued_bufcnt = 0;
527 //alloc buffers
528 ret = init_buffer_pool ();
529 XCAM_FAIL_RETURN (
530 ERROR, ret == XCAM_RETURN_NO_ERROR, ret,
531 "device(%s) start failed", XCAM_STR (_name));
532 #ifndef USE_RAWSTREAM_LIB
533 if (!V4L2_TYPE_IS_OUTPUT(_buf_type) &&
534 (_buf_type != V4L2_BUF_TYPE_META_OUTPUT)) {
535 #else
536 if (!V4L2_TYPE_IS_OUTPUT(_buf_type) && (_memory_type != V4L2_MEMORY_DMABUF) &&
537 (_buf_type != V4L2_BUF_TYPE_META_OUTPUT)) {
538 #endif
539 //queue all buffers
540 for (uint32_t i = 0; i < _buf_count; ++i) {
541 SmartPtr<V4l2Buffer> &buf = _buf_pool [i];
542 XCAM_ASSERT (buf.ptr());
543 XCAM_ASSERT (buf->get_buf().index == i);
544 ret = queue_buffer (buf);
545 if (ret != XCAM_RETURN_NO_ERROR) {
546 XCAM_LOG_ERROR (
547 "device(%s) start failed on queue index:%d",
548 XCAM_STR (_name), i);
549 stop ();
550 return ret;
551 }
552 }
553 }
554 return ret;
555 }
556
557 XCamReturn
558 V4l2Device::get_crop (struct v4l2_crop &crop)
559 {
560 int ret = 0;
561 XCAM_ASSERT (is_opened());
562 ret = this->io_control (VIDIOC_G_CROP, &crop);
563 if (ret < 0) {
564 XCAM_LOG_ERROR("subdev(%s) VIDIOC_G_CROP failed", XCAM_STR(_name));
565 return XCAM_RETURN_ERROR_IOCTL;
566 }
567 return XCAM_RETURN_NO_ERROR;
568 }
569
570 XCamReturn
571 V4l2Device::set_selection (struct v4l2_selection &select)
572 {
573 int ret = 0;
574 XCAM_ASSERT (is_opened());
575 ret = this->io_control (VIDIOC_S_SELECTION, &select);
576 if (ret < 0) {
577 XCAM_LOG_ERROR("videodev (%s) VIDIOC_S_SELECTION failed", XCAM_STR(_name));
578 return XCAM_RETURN_ERROR_IOCTL;
579 }
580 return XCAM_RETURN_NO_ERROR;
581 }
582
583 XCamReturn
584 V4l2Device::set_crop (struct v4l2_crop &crop)
585 {
586 int ret = 0;
587 XCAM_ASSERT (is_opened());
588 ret = this->io_control (VIDIOC_S_CROP, &crop);
589 if (ret < 0) {
590 XCAM_LOG_ERROR("subdev(%s) VIDIOC_S_CROP failed", XCAM_STR(_name));
591 return XCAM_RETURN_ERROR_IOCTL;
592 }
593 return XCAM_RETURN_NO_ERROR;
594 }
595
596 XCamReturn
597 V4l2SubDevice::set_selection (struct v4l2_subdev_selection &aSelection)
598 {
599 int ret = 0;
600 XCAM_ASSERT (is_opened());
601
602 XCAM_LOG_DEBUG ("VIDIOC_SUBDEV_S_SELECTION: which: %d, pad: %d, target: 0x%x, "
603 "flags: 0x%x, rect left: %d, rect top: %d, width: %d, height: %d",
604 aSelection.which,
605 aSelection.pad,
606 aSelection.target,
607 aSelection.flags,
608 aSelection.r.left,
609 aSelection.r.top,
610 aSelection.r.width,
611 aSelection.r.height);
612
613 ret = this->io_control (VIDIOC_SUBDEV_S_SELECTION, &aSelection);
614 if (ret < 0) {
615 XCAM_LOG_ERROR("subdev(%s) VIDIOC_SUBDEV_S_SELECTION failed", XCAM_STR(_name));
616 return XCAM_RETURN_ERROR_IOCTL;
617 }
618
619 return XCAM_RETURN_NO_ERROR;
620 }
621
622 XCamReturn
623 V4l2SubDevice::getFormat(struct v4l2_subdev_format &aFormat)
624 {
625 int ret = 0;
626 XCAM_ASSERT (is_opened());
627
628 ret = this->io_control(VIDIOC_SUBDEV_G_FMT, &aFormat);
629 if (ret < 0) {
630 XCAM_LOG_ERROR("subdev(%s) VIDIOC_SUBDEV_G_FMT failed: %s", XCAM_STR(_name));
631 return XCAM_RETURN_ERROR_IOCTL;
632 }
633
634 XCAM_LOG_DEBUG ("VIDIOC_SUBDEV_G_FMT: pad: %d, which: %d, width: %d, "
635 "height: %d, format: 0x%x, field: %d, color space: %d",
636 aFormat.pad,
637 aFormat.which,
638 aFormat.format.width,
639 aFormat.format.height,
640 aFormat.format.code,
641 aFormat.format.field,
642 aFormat.format.colorspace);
643
644 return XCAM_RETURN_NO_ERROR;
645 }
646
647 XCamReturn
648 V4l2SubDevice::setFormat(struct v4l2_subdev_format &aFormat)
649 {
650 int ret = 0;
651 XCAM_ASSERT (is_opened());
652
653 XCAM_LOG_DEBUG ("VIDIOC_SUBDEV_S_FMT: pad: %d, which: %d, width: %d, "
654 "height: %d, format: 0x%x, field: %d, color space: %d",
655 aFormat.pad,
656 aFormat.which,
657 aFormat.format.width,
658 aFormat.format.height,
659 aFormat.format.code,
660 aFormat.format.field,
661 aFormat.format.colorspace);
662
663 ret = this->io_control(VIDIOC_SUBDEV_S_FMT, &aFormat);
664 if (ret < 0) {
665 XCAM_LOG_ERROR("subdev(%s) VIDIOC_SUBDEV_S_FMT failed: %s", XCAM_STR(_name));
666 return XCAM_RETURN_ERROR_IOCTL;
667 }
668
669 return XCAM_RETURN_NO_ERROR;
670 }
671
672 XCamReturn
673 V4l2Device::start (bool prepared)
674 {
675 XCamReturn ret = XCAM_RETURN_NO_ERROR;
676 if (!prepared) {
677 // request buffer first
678 ret = request_buffer ();
679 XCAM_FAIL_RETURN (
680 ERROR, ret == XCAM_RETURN_NO_ERROR, ret,
681 "device(%s) start failed", XCAM_STR (_name));
682 _queued_bufcnt = 0;
683 //alloc buffers
684 ret = init_buffer_pool ();
685 XCAM_FAIL_RETURN (
686 ERROR, ret == XCAM_RETURN_NO_ERROR, ret,
687 "device(%s) start failed", XCAM_STR (_name));
688 if (!V4L2_TYPE_IS_OUTPUT(_buf_type) &&
689 (_buf_type != V4L2_BUF_TYPE_META_OUTPUT)) {
690 //queue all buffers
691 for (uint32_t i = 0; i < _buf_count; ++i) {
692 SmartPtr<V4l2Buffer> &buf = _buf_pool [i];
693 XCAM_ASSERT (buf.ptr());
694 XCAM_ASSERT (buf->get_buf().index == i);
695 ret = queue_buffer (buf);
696 if (ret != XCAM_RETURN_NO_ERROR) {
697 XCAM_LOG_ERROR (
698 "device(%s) start failed on queue index:%d",
699 XCAM_STR (_name), i);
700 stop ();
701 return ret;
702 }
703 }
704 }
705 }
706 // stream on
707 if (io_control (VIDIOC_STREAMON, &_buf_type) < 0) {
708 XCAM_LOG_ERROR (
709 "device(%s) start failed on VIDIOC_STREAMON, fd=%d",
710 XCAM_STR (_name), _fd);
711 stop ();
712 return XCAM_RETURN_ERROR_IOCTL;
713 }
714 _active = true;
715 XCAM_LOG_INFO ("device(%s) started successfully", XCAM_STR (_name));
716 return XCAM_RETURN_NO_ERROR;
717 }
718
719 XCamReturn
720 V4l2Device::stop_streamoff ()
721 {
722 SmartLock auto_lock(_buf_mutex);
723 XCAM_LOG_INFO ("device(%s) stop stream off", XCAM_STR (_name));
724 // stream off
725 if (_active) {
726 if (io_control (VIDIOC_STREAMOFF, &_buf_type) < 0) {
727 XCAM_LOG_WARNING ("device(%s) steamoff failed", XCAM_STR (_name));
728 }
729 _active = false;
730 }
731 return XCAM_RETURN_NO_ERROR;
732 }
733
734 XCamReturn
735 V4l2Device::stop_freebuffer ()
736 {
737 SmartLock auto_lock(_buf_mutex);
738 XCAM_LOG_INFO ("device(%s) stop free buffer", XCAM_STR (_name));
739 if (_buf_pool.size() > 0)
740 fini_buffer_pool ();
741 return XCAM_RETURN_NO_ERROR;
742 }
743
744 XCamReturn
745 V4l2Device::stop ()
746 {
747 SmartLock auto_lock(_buf_mutex);
748 XCAM_LOG_INFO ("device(%s) stop, already start: %d", XCAM_STR (_name), _active);
749
750 // stream off
751 if (_active) {
752 if (io_control (VIDIOC_STREAMOFF, &_buf_type) < 0) {
753 XCAM_LOG_WARNING ("device(%s) steamoff failed", XCAM_STR (_name));
754 }
755 _active = false;
756 /* while (_queued_bufcnt > 0) { */
757 /* struct v4l2_buffer v4l2_buf; */
758 /* struct v4l2_plane planes[_mplanes_count]; */
759
760 /* xcam_mem_clear (v4l2_buf); */
761 /* v4l2_buf.type = _buf_type; */
762 /* v4l2_buf.memory = _memory_type; */
763
764 /* if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == _buf_type || */
765 /* V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == _buf_type) { */
766 /* memset(planes, 0, sizeof(struct v4l2_plane) * _mplanes_count); */
767 /* v4l2_buf.m.planes = planes; */
768 /* v4l2_buf.length = _mplanes_count; */
769 /* } */
770
771 /* if (this->io_control (VIDIOC_DQBUF, &v4l2_buf) < 0) { */
772 /* XCAM_LOG_WARNING ("device(%s) fail to dequeue buffer.", XCAM_STR (_name)); */
773 /* } */
774 /* _queued_bufcnt--; */
775 /* } */
776 /* fini_buffer_pool (); */
777 /* release the shared buf between mipi tx and rx */
778 #if 0 // moved to fini_buffer_pool, buffer may be requested at prepare stage
779 if (_memory_type == V4L2_MEMORY_DMABUF) {
780 struct v4l2_requestbuffers request_buf;
781 xcam_mem_clear (request_buf);
782 request_buf.type = _buf_type;
783 request_buf.count = 0;
784 request_buf.memory = _memory_type;
785 if (io_control (VIDIOC_REQBUFS, &request_buf) < 0) {
786 XCAM_LOG_ERROR ("device(%s) starts failed on VIDIOC_REQBUFS", XCAM_STR (_name));
787 //return XCAM_RETURN_ERROR_IOCTL;
788 }
789 }
790 #endif
791 }
792
793 if (_buf_pool.size() > 0)
794 fini_buffer_pool ();
795 return XCAM_RETURN_NO_ERROR;
796 }
797
798 XCamReturn
799 V4l2Device::request_buffer ()
800 {
801 struct v4l2_requestbuffers request_buf;
802
803 XCAM_ASSERT (!is_activated());
804
805 xcam_mem_clear (request_buf);
806 request_buf.type = _buf_type;
807 request_buf.count = _buf_count;
808 request_buf.memory = _memory_type;
809
810 XCAM_LOG_INFO ("request buffers in device(%s): type: %d, count: %d, mem_type: %d",
811 XCAM_STR (_name),
812 request_buf.type,
813 request_buf.count,
814 request_buf.memory);
815
816 if (io_control (VIDIOC_REQBUFS, &request_buf) < 0) {
817 XCAM_LOG_INFO ("device(%s) starts failed on VIDIOC_REQBUFS", XCAM_STR (_name));
818 return XCAM_RETURN_ERROR_IOCTL;
819 }
820
821 XCAM_LOG_INFO ("device(%s) request buffer count: %d",
822 XCAM_STR (_name), request_buf.count);
823
824 if (request_buf.count != _buf_count) {
825 XCAM_LOG_INFO (
826 "device(%s) request buffer count doesn't match user settings, reset buffer count to %d",
827 XCAM_STR (_name), request_buf.count);
828 _buf_count = request_buf.count;
829 }
830
831 if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == _buf_type ||
832 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == _buf_type)
833 _planes = (struct v4l2_plane *)xcam_malloc0
834 (_buf_count * _mplanes_count * sizeof(struct v4l2_plane));
835
836 return XCAM_RETURN_NO_ERROR;
837 }
838
839 XCamReturn
840 V4l2Device::allocate_buffer (
841 SmartPtr<V4l2Buffer> &buf,
842 const struct v4l2_format &format,
843 const uint32_t index)
844 {
845 struct v4l2_buffer v4l2_buf;
846 int expbuf_fd = -1;
847 uintptr_t expbuf_ptr = 0;
848
849 xcam_mem_clear (v4l2_buf);
850 v4l2_buf.index = index;
851 v4l2_buf.type = _buf_type;
852 v4l2_buf.memory = _memory_type;
853 if (_buf_sync) {
854 v4l2_buf.flags = V4L2_BUF_FLAG_NO_CACHE_INVALIDATE |
855 V4L2_BUF_FLAG_NO_CACHE_CLEAN;
856 }
857
858 if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == _buf_type ||
859 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == _buf_type) {
860 v4l2_buf.m.planes = &_planes[index * _mplanes_count];
861 v4l2_buf.length = _mplanes_count;
862 }
863
864 switch (_memory_type) {
865 case V4L2_MEMORY_DMABUF:
866 {
867 v4l2_buf.length = format.fmt.pix.sizeimage;
868 if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == _buf_type ||
869 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == _buf_type) {
870 v4l2_buf.length = _mplanes_count;
871 for (int i=0; i<_mplanes_count; i++) {
872 v4l2_buf.m.planes[i].length = format.fmt.pix.sizeimage;
873 v4l2_buf.m.planes[i].bytesused = format.fmt.pix.sizeimage;
874 }
875 }
876 }
877 break;
878 case V4L2_MEMORY_MMAP:
879 {
880 void *pointer = MAP_FAILED;
881 int map_flags = MAP_SHARED;
882 #ifdef NEED_MAP_32BIT
883 map_flags |= MAP_32BIT;
884 #endif
885 if (io_control (VIDIOC_QUERYBUF, &v4l2_buf) < 0) {
886 XCAM_LOG_ERROR("device(%s) query MMAP buf(%d) failed", XCAM_STR(_name), index);
887 return XCAM_RETURN_ERROR_MEM;
888 }
889
890 if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == _buf_type ||
891 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == _buf_type) {
892 for (int i=0; i<_mplanes_count; i++) {
893 XCAM_LOG_DEBUG ("device(%s) get planar(%d) of buf(%d) length: %d", XCAM_STR (_name), i, index, v4l2_buf.m.planes[i].length);
894 pointer = mmap (0, v4l2_buf.m.planes[i].length, PROT_READ | PROT_WRITE, map_flags, _fd, v4l2_buf.m.planes[i].m.mem_offset);
895 v4l2_buf.m.planes[i].m.userptr = (uintptr_t) pointer;
896 if (pointer == MAP_FAILED) {
897 XCAM_LOG_ERROR("device(%s) mmap planar(%d) of buf(%d) failed", XCAM_STR(_name), i, index);
898 return XCAM_RETURN_ERROR_MEM;
899 }
900 }
901 expbuf_ptr = v4l2_buf.m.planes[0].m.userptr;
902 } else {
903 XCAM_LOG_DEBUG ("device(%s) get buf(%d) length: %d", XCAM_STR (_name), index, v4l2_buf.length);
904 pointer = mmap (0, v4l2_buf.length, PROT_READ | PROT_WRITE, map_flags, _fd, v4l2_buf.m.offset);
905 if (pointer == MAP_FAILED) {
906 XCAM_LOG_ERROR("device(%s) mmap buf(%d) failed", XCAM_STR(_name), index);
907 return XCAM_RETURN_ERROR_MEM;
908 }
909 expbuf_ptr = v4l2_buf.m.userptr = (uintptr_t) pointer;
910 }
911
912 // export buf dma fd
913 struct v4l2_exportbuffer expbuf;
914 xcam_mem_clear (expbuf);
915 expbuf.type = _buf_type;
916 expbuf.index = index;
917 expbuf.flags = O_CLOEXEC;
918 if (io_control (VIDIOC_EXPBUF, &expbuf) < 0) {
919 XCAM_LOG_ERROR ("device(%s) get dma buf(%d) failed", XCAM_STR (_name), index);
920 return XCAM_RETURN_ERROR_MEM;
921 } else {
922 XCAM_LOG_INFO ("device(%s) get dma buf(%d)-fd: %d", XCAM_STR (_name), index, expbuf.fd);
923 }
924 expbuf_fd = expbuf.fd;
925 }
926 break;
927 case V4L2_MEMORY_USERPTR:
928 {
929 v4l2_buf.length = format.fmt.pix.sizeimage;
930 if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == _buf_type ||
931 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == _buf_type) {
932 v4l2_buf.length = _mplanes_count;
933 for (int i=0; i<_mplanes_count; i++) {
934 v4l2_buf.m.planes[i].length = format.fmt.pix.sizeimage;
935 v4l2_buf.m.planes[i].bytesused = format.fmt.pix.sizeimage;
936 }
937 }
938 }
939 break;
940 default:
941 XCAM_ASSERT (false);
942 XCAM_LOG_WARNING (
943 "device(%s) allocated buffer mem_type(%d) doesn't support",
944 XCAM_STR (_name), _memory_type);
945 return XCAM_RETURN_ERROR_MEM;
946 }
947
948 buf = new V4l2Buffer (v4l2_buf, _format);
949 if (expbuf_fd != -1)
950 buf->set_expbuf_fd (expbuf_fd);
951 if (expbuf_ptr != 0)
952 buf->set_expbuf_usrptr(expbuf_ptr);
953 return XCAM_RETURN_NO_ERROR;
954 }
955
956 XCamReturn
957 V4l2Device::release_buffer (SmartPtr<V4l2Buffer> &buf)
958 {
959 int ret = 0;
960 switch (_memory_type) {
961 case V4L2_MEMORY_DMABUF:
962 {
963 }
964 break;
965 case V4L2_MEMORY_MMAP:
966 {
967 if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == _buf_type ||
968 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == _buf_type) {
969 for (int i=0; i<_mplanes_count; i++) {
970 XCAM_LOG_DEBUG("release multi planar(%d) of buffer length: %d", i, buf->get_buf().m.planes[i].length);
971 ret = munmap((void*)buf->get_buf().m.planes[i].m.userptr, buf->get_buf().m.planes[i].length);
972 }
973 ::close(buf->get_expbuf_fd());
974 } else {
975 XCAM_LOG_DEBUG("release buffer length: %d", buf->get_buf().length);
976 ret = munmap((void*)buf->get_buf().m.userptr, buf->get_buf().length);
977 ::close(buf->get_expbuf_fd());
978 }
979 if (ret != 0) {
980 XCAM_LOG_ERROR (
981 "release buffer: munmap failed");
982 }
983 }
984 break;
985 case V4L2_MEMORY_USERPTR:
986 break;
987 default:
988 XCAM_ASSERT (false);
989 XCAM_LOG_WARNING (
990 "device(%s) allocated buffer mem_type(%d) doesn't support",
991 XCAM_STR (_name), _memory_type);
992 return XCAM_RETURN_ERROR_MEM;
993 }
994 return XCAM_RETURN_NO_ERROR;
995 }
996
997 XCamReturn
998 V4l2Device::init_buffer_pool ()
999 {
1000 XCamReturn ret = XCAM_RETURN_NO_ERROR;
1001 uint32_t i = 0;
1002
1003 _buf_pool.clear ();
1004 _buf_pool.reserve (_buf_count);
1005
1006 for (; i < _buf_count; i++) {
1007 SmartPtr<V4l2Buffer> new_buf;
1008 XCAM_LOG_DEBUG("allocate_buffer index: %d", i);
1009 ret = allocate_buffer (new_buf, _format, i);
1010 if (ret != XCAM_RETURN_NO_ERROR) {
1011 break;
1012 }
1013 _buf_pool.push_back (new_buf);
1014 }
1015
1016 for (i = 0; i < _buf_count; i++) {
1017 SmartPtr<V4l2Buffer> &buf = _buf_pool [i];
1018 struct v4l2_buffer v4l2_buf = buf->get_buf ();
1019 XCAM_LOG_DEBUG ("init_buffer_pool device(%s) index:%d, memory:%d, type:%d, length:%d, fd:%d, ptr:%p",
1020 XCAM_STR (_name), v4l2_buf.index, v4l2_buf.memory,
1021 v4l2_buf.type, v4l2_buf.length, buf->get_expbuf_fd(), buf->get_expbuf_usrptr());
1022 }
1023 if (_buf_pool.empty()) {
1024 XCAM_LOG_ERROR ("No bufer allocated in device(%s)", XCAM_STR (_name));
1025 return XCAM_RETURN_ERROR_MEM;
1026 }
1027
1028 if (i != _buf_count) {
1029 XCAM_LOG_WARNING (
1030 "device(%s) allocate buffer count:%d failback to %d",
1031 XCAM_STR (_name), _buf_count, i);
1032 _buf_count = i;
1033 }
1034
1035 return XCAM_RETURN_NO_ERROR;
1036 }
1037
1038 XCamReturn
1039 V4l2Device::fini_buffer_pool()
1040 {
1041 uint32_t i = 0;
1042 int32_t tried_time = 0;
1043
1044 for (; i < _buf_pool.size(); i++) {
1045 release_buffer(_buf_pool [i]);
1046 }
1047
1048 if (_memory_type == V4L2_MEMORY_MMAP) {
1049 struct v4l2_requestbuffers request_buf;
1050 xcam_mem_clear (request_buf);
1051 request_buf.type = _buf_type;
1052 request_buf.count = 0;
1053 request_buf.memory = _memory_type;
1054 do {
1055 if (io_control (VIDIOC_REQBUFS, &request_buf) < 0) {
1056 usleep (100);
1057 XCAM_LOG_ERROR ("device(%s) failed on VIDIOC_REQBUFS, retry %d < 50times", XCAM_STR (_name), tried_time);
1058 //return XCAM_RETURN_ERROR_IOCTL;
1059 } else {
1060 break;
1061 }
1062 } while(tried_time++ < 50);
1063 } else if (_memory_type == V4L2_MEMORY_DMABUF) {
1064 struct v4l2_requestbuffers request_buf;
1065 xcam_mem_clear (request_buf);
1066 request_buf.type = _buf_type;
1067 request_buf.count = 0;
1068 request_buf.memory = _memory_type;
1069 do {
1070 if (io_control (VIDIOC_REQBUFS, &request_buf) < 0) {
1071 usleep (100);
1072 XCAM_LOG_ERROR ("device(%s) failed on VIDIOC_REQBUFS, retry %d < 50times", XCAM_STR (_name), tried_time);
1073 //return XCAM_RETURN_ERROR_IOCTL;
1074 } else {
1075 break;
1076 }
1077 } while(tried_time++ < 50);
1078 }
1079
1080 _buf_pool.clear ();
1081 if (_planes) {
1082 xcam_free (_planes);
1083 _planes = NULL;
1084 }
1085
1086 return XCAM_RETURN_NO_ERROR;
1087 }
1088
1089 SmartPtr<V4l2Buffer>
1090 V4l2Device::get_buffer_by_index (int index) {
1091 SmartLock auto_lock(_buf_mutex);
1092 SmartPtr<V4l2Buffer> &buf = _buf_pool [index];
1093
1094 return buf;
1095 }
1096
1097 XCamReturn
1098 V4l2Device::dequeue_buffer(SmartPtr<V4l2Buffer> &buf)
1099 {
1100 struct v4l2_buffer v4l2_buf;
1101 struct v4l2_plane planes[_mplanes_count];
1102
1103 if (!is_activated()) {
1104 XCAM_LOG_DEBUG (
1105 "device(%s) dequeue buffer failed since not activated", XCAM_STR (_name));
1106 return XCAM_RETURN_ERROR_PARAM;
1107 }
1108
1109 xcam_mem_clear (v4l2_buf);
1110 v4l2_buf.type = _buf_type;
1111 v4l2_buf.memory = _memory_type;
1112
1113 if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == _buf_type ||
1114 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == _buf_type) {
1115 memset(planes, 0, sizeof(struct v4l2_plane) * _mplanes_count);
1116 v4l2_buf.m.planes = planes;
1117 v4l2_buf.length = _mplanes_count;
1118 }
1119
1120 if (_buf_sync)
1121 v4l2_buf.flags = V4L2_BUF_FLAG_NO_CACHE_INVALIDATE | V4L2_BUF_FLAG_NO_CACHE_CLEAN;
1122
1123 if (this->io_control (VIDIOC_DQBUF, &v4l2_buf) < 0) {
1124 XCAM_LOG_ERROR ("device(%s) fail to dequeue buffer.", XCAM_STR (_name));
1125 return XCAM_RETURN_ERROR_IOCTL;
1126 }
1127
1128 if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == _buf_type ||
1129 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == _buf_type) {
1130 XCAM_LOG_DEBUG ("device(%s) multi planar dequeue buffer index:%d, length: %dn",
1131 XCAM_STR (_name), v4l2_buf.index,
1132 v4l2_buf.m.planes[0].length);
1133 if (V4L2_MEMORY_DMABUF == _memory_type) {
1134 XCAM_LOG_DEBUG ("device(%s) multi planar index:%d, fd: %d",
1135 XCAM_STR (_name), v4l2_buf.index, v4l2_buf.m.planes[0].m.fd);
1136 }
1137 } else {
1138 XCAM_LOG_DEBUG ("device(%s) dequeue buffer index:%d, length: %d",
1139 XCAM_STR (_name), v4l2_buf.index, v4l2_buf.length);
1140 }
1141
1142 if (v4l2_buf.index > _buf_count) {
1143 XCAM_LOG_ERROR (
1144 "device(%s) dequeue wrong buffer index:%d",
1145 XCAM_STR (_name), v4l2_buf.index);
1146 return XCAM_RETURN_ERROR_ISP;
1147 }
1148
1149 SmartLock auto_lock(_buf_mutex);
1150
1151 buf = _buf_pool [v4l2_buf.index];
1152 buf->set_timestamp (v4l2_buf.timestamp);
1153 buf->set_timecode (v4l2_buf.timecode);
1154 buf->set_sequence (v4l2_buf.sequence);
1155 if (!V4L2_TYPE_IS_OUTPUT(_buf_type) &&
1156 (_buf_type != V4L2_BUF_TYPE_META_OUTPUT))
1157 buf->set_queued(false);
1158 if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == _buf_type ||
1159 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == _buf_type) {
1160 buf->set_length (v4l2_buf.m.planes[0].length);
1161 } else {
1162 buf->set_length (v4l2_buf.length);
1163 }
1164 _queued_bufcnt--;
1165
1166 return XCAM_RETURN_NO_ERROR;
1167 }
1168
1169 XCamReturn
1170 V4l2Device::get_buffer (SmartPtr<V4l2Buffer> &buf, int index) const
1171 {
1172 SmartLock auto_lock(_buf_mutex);
1173
1174 if (_buf_pool.size() <= 0)
1175 return XCAM_RETURN_ERROR_MEM;
1176
1177 if (index != -1 && !(_buf_pool[index]->get_queued())) {
1178 buf = _buf_pool[index];
1179 buf->set_queued(true);
1180 return XCAM_RETURN_NO_ERROR;
1181 }
1182
1183 uint32_t i;
1184
1185 for (i = 0; i < _buf_pool.size(); i++) {
1186 if (!(_buf_pool[i]->get_queued())) {
1187 buf = _buf_pool[i];
1188 buf->set_queued(true);
1189 break;
1190 }
1191 }
1192
1193 if (i == _buf_count)
1194 return XCAM_RETURN_ERROR_MEM;
1195 else
1196 return XCAM_RETURN_NO_ERROR;
1197 }
1198
1199 XCamReturn
1200 V4l2Device::return_buffer_to_pool (SmartPtr<V4l2Buffer> &buf)
1201 {
1202 SmartLock auto_lock(_buf_mutex);
1203
1204 XCAM_ASSERT (buf.ptr());
1205 buf->reset ();
1206 return XCAM_RETURN_NO_ERROR;
1207 }
1208
1209 XCamReturn
1210 V4l2Device::return_buffer (SmartPtr<V4l2Buffer> &buf)
1211 {
1212 SmartLock auto_lock(_buf_mutex);
1213
1214 if (V4L2_TYPE_IS_OUTPUT(buf->get_buf ().type) ||
1215 (buf->get_buf ().type == V4L2_BUF_TYPE_META_OUTPUT)) {
1216 XCAM_ASSERT (buf.ptr());
1217 buf->reset ();
1218 return XCAM_RETURN_NO_ERROR;
1219 } else {
1220 if (!_active)
1221 buf->reset();
1222 else
1223 return queue_buffer (buf, true);
1224 }
1225
1226 return XCAM_RETURN_NO_ERROR;
1227 }
1228
1229 XCamReturn
1230 V4l2Device::queue_buffer (SmartPtr<V4l2Buffer> &buf, bool locked)
1231 {
1232 if (!locked)
1233 _buf_mutex.lock();
1234
1235 XCAM_ASSERT (buf.ptr());
1236 buf->reset ();
1237
1238 struct v4l2_buffer v4l2_buf = buf->get_buf ();
1239 struct v4l2_plane planes[_mplanes_count];
1240
1241 XCAM_ASSERT (v4l2_buf.index < _buf_count);
1242
1243 if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == _buf_type ||
1244 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == _buf_type) {
1245 XCAM_LOG_DEBUG ("device(%s) queue buffer index:%d, memory:%d, type:%d, multiply planar:%d, length:%d, fd:%d, ptr:%p",
1246 XCAM_STR (_name), v4l2_buf.index, v4l2_buf.memory,
1247 v4l2_buf.type, v4l2_buf.length, v4l2_buf.m.planes[0].length, buf->get_expbuf_fd(), buf->get_expbuf_usrptr());
1248 memset(planes, 0, sizeof(struct v4l2_plane) * _mplanes_count);
1249 v4l2_buf.m.planes = planes;
1250 planes[0] = buf->get_buf ().m.planes[0];
1251 } else {
1252 XCAM_LOG_DEBUG ("device(%s) queue buffer index:%d, memory:%d, type:%d, length:%d, fd:%d",
1253 XCAM_STR (_name), v4l2_buf.index, v4l2_buf.memory,
1254 v4l2_buf.type, v4l2_buf.length, buf->get_expbuf_fd());
1255 }
1256
1257 if (v4l2_buf.type == V4L2_BUF_TYPE_META_OUTPUT)
1258 v4l2_buf.bytesused = v4l2_buf.length;
1259 if (v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
1260 v4l2_buf.m.planes[0].bytesused = v4l2_buf.m.planes[0].length;
1261 if (V4L2_MEMORY_DMABUF == _memory_type)
1262 v4l2_buf.m.planes[0].m.fd = buf->get_expbuf_fd();
1263 else if (V4L2_MEMORY_USERPTR == _memory_type)
1264 v4l2_buf.m.planes[0].m.userptr = buf->get_expbuf_usrptr();
1265 }
1266
1267 _queued_bufcnt++;
1268 buf->set_queued(true);
1269 if (!locked)
1270 _buf_mutex.unlock();
1271
1272 if (_buf_sync)
1273 v4l2_buf.flags = V4L2_BUF_FLAG_NO_CACHE_INVALIDATE | V4L2_BUF_FLAG_NO_CACHE_CLEAN;
1274
1275 if (io_control (VIDIOC_QBUF, &v4l2_buf) < 0) {
1276 XCAM_LOG_ERROR("%s fail to enqueue buffer index:%d.",
1277 XCAM_STR(_name), v4l2_buf.index);
1278 // restore buf status
1279 {
1280 if (!locked)
1281 _buf_mutex.lock();
1282 /* SmartLock auto_lock(_buf_mutex); */
1283 buf->set_queued(false);
1284 _queued_bufcnt--;
1285 if (!locked)
1286 _buf_mutex.unlock();
1287 }
1288
1289 return XCAM_RETURN_ERROR_IOCTL;
1290 }
1291
1292 return XCAM_RETURN_NO_ERROR;
1293 }
1294
1295 V4l2SubDevice::V4l2SubDevice (const char *name)
1296 : V4l2Device (name)
1297 {
1298 }
1299
1300 XCamReturn
1301 V4l2Device::subscribe_event (int event)
1302 {
1303 struct v4l2_event_subscription sub;
1304 int ret = 0;
1305
1306 XCAM_ASSERT (is_opened());
1307
1308 xcam_mem_clear (sub);
1309 sub.type = event;
1310
1311 ret = this->io_control (VIDIOC_SUBSCRIBE_EVENT, &sub);
1312 if (ret < 0) {
1313 XCAM_LOG_DEBUG ("subdev(%s) subscribe event(%d) failed", XCAM_STR(_name), event);
1314 return XCAM_RETURN_ERROR_IOCTL;
1315 }
1316 return XCAM_RETURN_NO_ERROR;
1317 }
1318
1319 XCamReturn
1320 V4l2Device::unsubscribe_event (int event)
1321 {
1322 struct v4l2_event_subscription sub;
1323 int ret = 0;
1324
1325 XCAM_ASSERT (is_opened());
1326
1327 xcam_mem_clear (sub);
1328 sub.type = event;
1329
1330 ret = this->io_control (VIDIOC_UNSUBSCRIBE_EVENT, &sub);
1331 if (ret < 0) {
1332 XCAM_LOG_DEBUG ("subdev(%s) unsubscribe event(%d) failed", XCAM_STR(_name), event);
1333 return XCAM_RETURN_ERROR_IOCTL;
1334 }
1335 return XCAM_RETURN_NO_ERROR;
1336 }
1337
1338 XCamReturn
1339 V4l2Device::dequeue_event (struct v4l2_event &event)
1340 {
1341 int ret = 0;
1342 XCAM_ASSERT (is_opened());
1343
1344 ret = this->io_control (VIDIOC_DQEVENT, &event);
1345 if (ret < 0) {
1346 XCAM_LOG_DEBUG ("subdev(%s) dequeue event failed", XCAM_STR(_name));
1347 return XCAM_RETURN_ERROR_IOCTL;
1348 }
1349
1350 return XCAM_RETURN_NO_ERROR;
1351 }
1352
1353 XCamReturn
1354 V4l2SubDevice::get_selection (int pad, uint32_t target, struct v4l2_subdev_selection &select)
1355 {
1356 int ret = 0;
1357 XCAM_ASSERT (is_opened());
1358
1359 select.pad = pad;
1360 select.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1361 select.target = target;
1362
1363 ret = this->io_control (VIDIOC_SUBDEV_G_SELECTION, &select);
1364 if (ret < 0) {
1365 XCAM_LOG_DEBUG ("subdev(%s) get selection failed", XCAM_STR(_name));
1366 return XCAM_RETURN_ERROR_IOCTL;
1367 }
1368
1369 return XCAM_RETURN_NO_ERROR;
1370 }
1371
1372 XCamReturn V4l2SubDevice::start (bool prepared)
1373 {
1374 if (!is_opened())
1375 return XCAM_RETURN_ERROR_PARAM;
1376
1377 _active = true;
1378 return XCAM_RETURN_NO_ERROR;
1379 }
1380
1381 XCamReturn V4l2SubDevice::stop ()
1382 {
1383 if (_active)
1384 _active = false;
1385
1386 return XCAM_RETURN_NO_ERROR;
1387 }
1388
1389 }
1390