PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
vtkPlusV4L2VideoSource.cxx
Go to the documentation of this file.
1 /*=Plus=header=begin======================================================
2  Program: Plus
3  Copyright (c) Laboratory for Percutaneous Surgery. All rights reserved.
4  See License.txt for details.
5  =========================================================Plus=header=end*/
6 
7 // Local includes
8 #include "PlusConfigure.h"
10 #include "vtkPlusChannel.h"
11 #include "vtkPlusDataSource.h"
12 
13 // VTK includes
14 #include <vtkImageData.h>
15 #include <vtkObjectFactory.h>
16 
17 // OS includes
18 #include <fcntl.h>
19 #include <sys/stat.h>
20 #include <errno.h>
21 #include <sys/ioctl.h>
22 #include <sys/mman.h>
23 
24 //----------------------------------------------------------------------------
25 
27 
28 //----------------------------------------------------------------------------
29 
30 namespace
31 {
32  int xioctl(int fh, unsigned long int request, void* arg)
33  {
34  int r;
35 
36  do
37  {
38  r = ioctl(fh, request, arg);
39  }
40  while (-1 == r && EINTR == errno);
41 
42  return r;
43  }
44 }
45 
46 #define CLEAR(x) memset(&(x), 0, sizeof(x))
47 
48 //----------------------------------------------------------------------------
50  : DeviceName("")
51  , IOMethod(IO_METHOD_READ)
52  , FileDescriptor(-1)
53  , FrameBuffers(nullptr)
54  , BufferCount(0)
55  , DeviceFormat(std::make_shared<v4l2_format>())
56  , FormatWidth(nullptr)
57  , FormatHeight(nullptr)
58  , PixelFormat(nullptr)
59  , FieldOrder(nullptr)
60  , DataSource(nullptr)
61 {
62  memset(this->DeviceFormat.get(), 0, sizeof(struct v4l2_format));
63 
64  this->StartThreadForInternalUpdates = true;
65 }
66 
67 //----------------------------------------------------------------------------
69 {
70 }
71 
72 //----------------------------------------------------------------------------
73 void vtkPlusV4L2VideoSource::PrintSelf(ostream& os, vtkIndent indent)
74 {
75  this->Superclass::PrintSelf(os, indent);
76 
77  os << indent << "DeviceName: " << this->DeviceName << std::endl;
78  os << indent << "IOMethod: " << this->IOMethodToString(this->IOMethod) << std::endl;
79  os << indent << "BufferCount: " << this->BufferCount << std::endl;
80 
81  if (this->FileDescriptor != -1)
82  {
83  os << indent << "Available formats: " << std::endl;
84 
85  struct v4l2_fmtdesc fmtdesc;
86  CLEAR(fmtdesc);
87  fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
88  while (ioctl(this->FileDescriptor, VIDIOC_ENUM_FMT, &fmtdesc) == 0)
89  {
90  os << indent << fmtdesc.description << std::endl;
91  fmtdesc.index++;
92  }
93  }
94  else
95  {
96  os << indent << "Cannot enumerate known formats. Camera not connected." << std::endl;
97  }
98 }
99 
100 //-----------------------------------------------------------------------------
101 PlusStatus vtkPlusV4L2VideoSource::ReadConfiguration(vtkXMLDataElement* rootConfigElement)
102 {
103  XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_READING(deviceConfig, rootConfigElement);
104 
105  XML_READ_STRING_ATTRIBUTE_REQUIRED(DeviceName, deviceConfig);
106  std::string ioMethod;
107  XML_READ_STRING_ATTRIBUTE_NONMEMBER_OPTIONAL(IOMethod, ioMethod, deviceConfig);
108  if (vtkPlusV4L2VideoSource::StringToIOMethod(ioMethod) != IO_METHOD_UNKNOWN)
109  {
111  }
112  else
113  {
114  LOG_WARNING("Unknown method: " << ioMethod << ". Defaulting to " << vtkPlusV4L2VideoSource::IOMethodToString(this->IOMethod));
115  }
116 
117  int frameSize[2];
118  XML_READ_VECTOR_ATTRIBUTE_NONMEMBER_OPTIONAL(int, 2, FrameSize, frameSize, deviceConfig);
119  if (deviceConfig->GetAttribute("FrameSize") != nullptr)
120  {
121  if (frameSize[0] < 0 || frameSize[1] < 0)
122  {
123  LOG_WARNING("Invalid frame size in configuration file. Not setting parameters to device.");
124  }
125  else
126  {
127  this->FormatHeight = std::make_shared<unsigned int>(static_cast<unsigned int>(frameSize[0]));
128  this->FormatWidth = std::make_shared<unsigned int>(static_cast<unsigned int>(frameSize[1]));
129  }
130  }
131 
132  std::string pixelFormat;
133  XML_READ_STRING_ATTRIBUTE_NONMEMBER_OPTIONAL(PixelFormat, pixelFormat, deviceConfig);
134  if (deviceConfig->GetAttribute("PixelFormat") != nullptr)
135  {
136  this->PixelFormat = std::make_shared<unsigned int>(vtkPlusV4L2VideoSource::StringToPixelFormat(pixelFormat));
137  }
138 
139  std::string fieldOrder;
140  XML_READ_STRING_ATTRIBUTE_NONMEMBER_OPTIONAL(FieldOrder, fieldOrder, deviceConfig);
141  if (deviceConfig->GetAttribute("FieldOrder") != nullptr)
142  {
143  this->FieldOrder = std::make_shared<v4l2_field>(vtkPlusV4L2VideoSource::StringToFieldOrder(fieldOrder));
144  }
145 
146  return PLUS_SUCCESS;
147 }
148 
149 //-----------------------------------------------------------------------------
150 PlusStatus vtkPlusV4L2VideoSource::WriteConfiguration(vtkXMLDataElement* rootConfigElement)
151 {
152  XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(deviceConfig, rootConfigElement);
153 
154  XML_WRITE_STRING_ATTRIBUTE_IF_NOT_EMPTY(DeviceName, deviceConfig);
155 
156  deviceConfig->SetAttribute("IOMethod", vtkPlusV4L2VideoSource::IOMethodToString(this->IOMethod).c_str());
157 
158  int frameSize[2] = { static_cast<int>(this->DeviceFormat->fmt.pix.width), static_cast<int>(this->DeviceFormat->fmt.pix.height) };
159  deviceConfig->SetVectorAttribute("FrameSize", 2, frameSize);
160 
161  deviceConfig->SetAttribute("PixelFormat", vtkPlusV4L2VideoSource::PixelFormatToString(this->DeviceFormat->fmt.pix.pixelformat).c_str());
162 
163  deviceConfig->SetAttribute("FieldOrder", vtkPlusV4L2VideoSource::FieldOrderToString(static_cast<v4l2_field>(this->DeviceFormat->fmt.pix.field)).c_str());
164 
165  return PLUS_SUCCESS;
166 }
167 
168 //-----------------------------------------------------------------------------
170 {
171  this->FrameBuffers = (FrameBuffer*) calloc(1, sizeof(FrameBuffer));
172 
173  if (!this->FrameBuffers)
174  {
175  LOG_ERROR("Unable to allocate " << sizeof(FrameBuffer) << " bytes for capture frame.");
176  return PLUS_FAIL;
177  }
178 
179  this->FrameBuffers[0].length = bufferSize;
180  this->FrameBuffers[0].start = malloc(bufferSize);
181 
182  if (!this->FrameBuffers[0].start)
183  {
184  LOG_ERROR("Unable to allocate " << bufferSize << " bytes for capture frame.");
185  return PLUS_FAIL;
186  }
187 
188  this->BufferCount = 1;
189 
190  return PLUS_SUCCESS;
191 }
192 
193 //-----------------------------------------------------------------------------
195 {
196  struct v4l2_requestbuffers req;
197 
198  CLEAR(req);
199 
200  req.count = 4;
201  req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
202  req.memory = V4L2_MEMORY_MMAP;
203 
204  if (-1 == xioctl(this->FileDescriptor, VIDIOC_REQBUFS, &req))
205  {
206  if (EINVAL == errno)
207  {
208  LOG_ERROR(this->DeviceName << " does not support memory mapping");
209  }
210  else
211  {
212  LOG_ERROR("VIDIOC_REQBUFS" << ": " << strerror(errno));
213  }
214  return PLUS_FAIL;
215  }
216 
217  if (req.count < 2)
218  {
219  LOG_ERROR("Insufficient buffer memory on " << this->DeviceName);
220  return PLUS_FAIL;
221  }
222 
223  this->FrameBuffers = (FrameBuffer*) calloc(req.count, sizeof(FrameBuffer));
224 
225  if (!this->FrameBuffers)
226  {
227  LOG_ERROR("Out of memory");
228  return PLUS_FAIL;
229  }
230 
231  for (this->BufferCount = 0; this->BufferCount < req.count; ++this->BufferCount)
232  {
233  v4l2_buffer buf;
234  CLEAR(buf);
235 
236  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
237  buf.memory = V4L2_MEMORY_MMAP;
238  buf.index = this->BufferCount;
239 
240  if (-1 == xioctl(this->FileDescriptor, VIDIOC_QUERYBUF, &buf))
241  {
242  LOG_ERROR("VIDIOC_QUERYBUF" << ": " << strerror(errno));
243  return PLUS_FAIL;
244  }
245 
246  this->FrameBuffers[this->BufferCount].length = buf.length;
247  this->FrameBuffers[this->BufferCount].start = mmap(NULL /* start anywhere */, buf.length, PROT_READ | PROT_WRITE /* required */, MAP_SHARED /* recommended */, this->FileDescriptor, buf.m.offset);
248 
249  if (MAP_FAILED == this->FrameBuffers[this->BufferCount].start)
250  {
251  LOG_ERROR("mmap" << ": " << strerror(errno));
252  }
253  }
254 
255  return PLUS_SUCCESS;
256 }
257 
258 //----------------------------------------------------------------------------
260 {
261  struct v4l2_requestbuffers req;
262 
263  CLEAR(req);
264 
265  req.count = 4;
266  req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
267  req.memory = V4L2_MEMORY_USERPTR;
268 
269  if (-1 == xioctl(this->FileDescriptor, VIDIOC_REQBUFS, &req))
270  {
271  if (EINVAL == errno)
272  {
273  LOG_ERROR(this->DeviceName << " does not support user pointer i/o");
274  }
275  else
276  {
277  LOG_ERROR("VIDIOC_REQBUFS" << ": " << strerror(errno));
278  }
279  return PLUS_FAIL;
280  }
281 
282  this->FrameBuffers = (FrameBuffer*) calloc(4, sizeof(FrameBuffer));
283 
284  if (!this->FrameBuffers)
285  {
286  LOG_ERROR("Out of memory");
287  return PLUS_FAIL;
288  }
289 
290  for (this->BufferCount = 0; this->BufferCount < 4; ++this->BufferCount)
291  {
292  this->FrameBuffers[this->BufferCount].length = bufferSize;
293  this->FrameBuffers[this->BufferCount].start = malloc(bufferSize);
294 
295  if (!this->FrameBuffers[this->BufferCount].start)
296  {
297  LOG_ERROR("Out of memory");
298  return PLUS_FAIL;
299  }
300  }
301 
302  return PLUS_SUCCESS;
303 }
304 
305 //----------------------------------------------------------------------------
307 {
308  // Ensure we can detect the device in the OS
309  struct stat st;
310  if (-1 == stat(this->DeviceName.c_str(), &st))
311  {
312  LOG_ERROR("Cannot identify " << this->DeviceName << ": " << strerror(errno));
313  return PLUS_FAIL;
314  }
315  if (!S_ISCHR(st.st_mode))
316  {
317  LOG_ERROR(this->DeviceName << " is not a valid device.");
318  return PLUS_FAIL;
319  }
320 
321  // Open the device
322  this->FileDescriptor = open(this->DeviceName.c_str(), O_RDWR | O_NONBLOCK, 0);
323  if (-1 == this->FileDescriptor)
324  {
325  LOG_ERROR("Cannot open " << this->DeviceName << ": " << strerror(errno));
326  return PLUS_FAIL;
327  }
328 
329  // Confirm requested device is capable
330  v4l2_capability cap;
331  if (-1 == xioctl(this->FileDescriptor, VIDIOC_QUERYCAP, &cap))
332  {
333  if (EINVAL == errno)
334  {
335  LOG_ERROR(this->DeviceName << " is not a V4L2 device");
336  }
337  else
338  {
339  LOG_ERROR("VIDIOC_QUERYCAP" << ": " << strerror(errno));
340  }
341  return PLUS_FAIL;
342  }
343 
344  if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
345  {
346  LOG_ERROR(this->DeviceName << " is not a video capture device");
347  return PLUS_FAIL;
348  }
349 
350  switch (this->IOMethod)
351  {
352  case IO_METHOD_READ:
353  {
354  if (!(cap.capabilities & V4L2_CAP_READWRITE))
355  {
356  LOG_ERROR(this->DeviceName << " does not support read i/o");
357  return PLUS_FAIL;
358  }
359  break;
360  }
361  case IO_METHOD_MMAP:
362  case IO_METHOD_USERPTR:
363  {
364  if (!(cap.capabilities & V4L2_CAP_STREAMING))
365  {
366  LOG_ERROR(this->DeviceName << " does not support streaming i/o");
367  return PLUS_FAIL;
368  }
369  break;
370  }
371  default:
372  {
373  LOG_ERROR("Unknown IO method.");
374  return PLUS_FAIL;
375  }
376  }
377 
378  // Select video input, video standard and tune here
379  struct v4l2_cropcap cropcap;
380  CLEAR(cropcap);
381  cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
382  if (0 == xioctl(this->FileDescriptor, VIDIOC_CROPCAP, &cropcap))
383  {
384  struct v4l2_crop crop;
385  CLEAR(crop);
386  crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
387  crop.c = cropcap.defrect;
388 
389  // TODO : get clip information from data source and set to device
390  if (-1 == xioctl(this->FileDescriptor, VIDIOC_S_CROP, &crop))
391  {
392  switch (errno)
393  {
394  case EINVAL:
395  // Cropping not supported
396  break;
397  }
398  }
399  }
400 
401  // Retrieve current v4l2 format settings
402  this->DeviceFormat->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
403  if (-1 == xioctl(this->FileDescriptor, VIDIOC_G_FMT, this->DeviceFormat.get()))
404  {
405  LOG_ERROR("VIDIOC_G_FMT" << ": " << strerror(errno));
406  return PLUS_FAIL;
407  }
408 
409  if (this->FormatWidth != nullptr)
410  {
411  this->DeviceFormat->fmt.pix.width = *this->FormatWidth;
412  }
413  if (this->FormatHeight != nullptr)
414  {
415  this->DeviceFormat->fmt.pix.height = *this->FormatHeight;
416  }
417  if (this->PixelFormat != nullptr)
418  {
419  this->DeviceFormat->fmt.pix.pixelformat = *this->PixelFormat;
420  }
421  if (this->FieldOrder != nullptr)
422  {
423  this->DeviceFormat->fmt.pix.field = *this->FieldOrder;
424  }
425 
426  if (-1 == xioctl(this->FileDescriptor, VIDIOC_S_FMT, this->DeviceFormat.get()))
427  {
428  LOG_WARNING("Unable to set requested video format. Continuing with existing format: " << strerror(errno));
429  if (-1 == xioctl(this->FileDescriptor, VIDIOC_G_FMT, this->DeviceFormat.get()))
430  {
431  LOG_ERROR("VIDIOC_G_FMT" << ": " << strerror(errno));
432  return PLUS_FAIL;
433  }
434  }
435 
436  assert(this->DataSource != nullptr);
437 
438  this->DataSource->SetInputFrameSize(this->DeviceFormat->fmt.pix.width, this->DeviceFormat->fmt.pix.height, 1);
439  this->ImageSize[0] = this->DeviceFormat->fmt.pix.width;
440  this->ImageSize[1] = this->DeviceFormat->fmt.pix.height;
441  this->ImageSize[2] = 1;
442  this->DataSource->SetPixelType(VTK_UNSIGNED_CHAR);
443  this->NumberOfScalarComponents = this->DeviceFormat->fmt.pix.sizeimage / this->DeviceFormat->fmt.pix.width / this->DeviceFormat->fmt.pix.height;
445 
446  this->FrameFields["pixelformat"].second = vtkPlusV4L2VideoSource::PixelFormatToString(this->DeviceFormat->fmt.pix.pixelformat);
447 
448  // Use this->DeviceFormat to initialize data source
449  switch (this->IOMethod)
450  {
451  case IO_METHOD_READ:
452  {
453  return this->InitRead(this->DeviceFormat->fmt.pix.sizeimage);
454  }
455  case IO_METHOD_MMAP:
456  {
457  return this->InitMmap();
458  }
459  case IO_METHOD_USERPTR:
460  {
461  return this->InitUserp(this->DeviceFormat->fmt.pix.sizeimage);
462  }
463  default:
464  {
465  return PLUS_FAIL;
466  }
467  }
468 }
469 
470 //----------------------------------------------------------------------------
472 {
473  switch (this->IOMethod)
474  {
475  case IO_METHOD_READ:
476  {
477  free(this->FrameBuffers[0].start);
478  break;
479  }
480  case IO_METHOD_MMAP:
481  {
482  for (unsigned int i = 0; i < this->BufferCount; ++i)
483  {
484  if (-1 == munmap(this->FrameBuffers[i].start, this->FrameBuffers[i].length))
485  {
486  LOG_ERROR("munmap" << ": " << strerror(errno));
487  return PLUS_FAIL;
488  }
489  }
490  break;
491  }
492  case IO_METHOD_USERPTR:
493  {
494  for (unsigned int i = 0; i < this->BufferCount; ++i)
495  {
496  free(this->FrameBuffers[i].start);
497  }
498  break;
499  }
500  }
501 
502  free(this->FrameBuffers);
503 
504  if (-1 == close(this->FileDescriptor))
505  {
506  LOG_ERROR("Close" << ": " << strerror(errno));
507  return PLUS_FAIL;
508  }
509 
510  this->BufferCount = 0;
511  this->FileDescriptor = -1;
512 
513  return PLUS_SUCCESS;
514 }
515 
516 //----------------------------------------------------------------------------
518 {
519  fd_set fds;
520  timeval tv;
521  int r;
522 
523  FD_ZERO(&fds);
524  FD_SET(this->FileDescriptor, &fds);
525 
526  // Timeout
527  tv.tv_sec = 2;
528  tv.tv_usec = 0;
529 
530  r = select(this->FileDescriptor + 1, &fds, NULL, NULL, &tv);
531 
532  if (-1 == r)
533  {
534  LOG_ERROR("Unable to select video device" << ": " << strerror(errno));
535  return PLUS_FAIL;
536  }
537 
538  if (0 == r)
539  {
540  LOG_ERROR("Select timeout.");
541  return PLUS_FAIL;
542  }
543 
544  unsigned int currentBufferIndex;
545  unsigned int bytesUsed;
546  if (this->ReadFrame(currentBufferIndex, bytesUsed) != PLUS_SUCCESS)
547  {
548  return PLUS_FAIL;
549  }
550 
551  if (this->DataSource->AddItem(this->FrameBuffers[currentBufferIndex].start, this->ImageSize, bytesUsed, US_IMG_BRIGHTNESS, this->FrameNumber, UNDEFINED_TIMESTAMP, UNDEFINED_TIMESTAMP, &this->FrameFields) != PLUS_SUCCESS)
552  {
553  LOG_ERROR("vtkPlusV4L2VideoSource::Unable to add item to the buffer.");
554  return PLUS_FAIL;
555  }
556 
557  this->FrameNumber++;
558  return PLUS_SUCCESS;
559 }
560 
561 //----------------------------------------------------------------------------
562 PlusStatus vtkPlusV4L2VideoSource::ReadFrame(unsigned int& currentBufferIndex, unsigned int& bytesUsed)
563 {
564  switch (this->IOMethod)
565  {
566  case IO_METHOD_READ:
567  {
568  return ReadFrameFileDescriptor(currentBufferIndex, bytesUsed);
569  }
570  case IO_METHOD_MMAP:
571  {
572  return ReadFrameMemoryMap(currentBufferIndex, bytesUsed);
573  }
574  case IO_METHOD_USERPTR:
575  {
576  return ReadFrameUserPtr(currentBufferIndex, bytesUsed);
577  }
578  }
579 
580  return PLUS_FAIL;
581 }
582 
583 //----------------------------------------------------------------------------
584 PlusStatus vtkPlusV4L2VideoSource::ReadFrameFileDescriptor(unsigned int& currentBufferIndex, unsigned int& bytesUsed)
585 {
586  if (-1 == read(this->FileDescriptor, this->FrameBuffers[0].start, this->FrameBuffers[0].length))
587  {
588  switch (errno)
589  {
590  case EAGAIN:
591  {
592  return PLUS_FAIL;
593  }
594  case EIO:
595  {
596  // Could ignore EIO, see spec
597  }
598  default:
599  {
600  LOG_ERROR("Read" << ": " << strerror(errno));
601  return PLUS_FAIL;
602  }
603  }
604  }
605 
606  currentBufferIndex = 0;
607  bytesUsed = this->FrameBuffers[0].length;
608 
609  return PLUS_SUCCESS;
610 }
611 
612 //----------------------------------------------------------------------------
613 PlusStatus vtkPlusV4L2VideoSource::ReadFrameMemoryMap(unsigned int& currentBufferIndex, unsigned int& bytesUsed)
614 {
615  struct v4l2_buffer buf;
616  CLEAR(buf);
617 
618  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
619  buf.memory = V4L2_MEMORY_MMAP;
620 
621  if (-1 == xioctl(this->FileDescriptor, VIDIOC_DQBUF, &buf))
622  {
623  switch (errno)
624  {
625  case EAGAIN:
626  {
627  return PLUS_FAIL;
628  }
629  case EIO:
630  {
631  // Could ignore EIO, see spec
632  }
633  default:
634  {
635  LOG_ERROR("VIDIOC_DQBUF" << ": " << strerror(errno));
636  return PLUS_FAIL;
637  }
638  }
639  }
640 
641  if (-1 == xioctl(this->FileDescriptor, VIDIOC_QBUF, &buf))
642  {
643  LOG_ERROR("VIDIOC_QBUF" << ": " << strerror(errno));
644  return PLUS_FAIL;
645  }
646 
647  currentBufferIndex = buf.index;
648  bytesUsed = buf.length;
649 
650  return PLUS_SUCCESS;
651 }
652 
653 //----------------------------------------------------------------------------
654 PlusStatus vtkPlusV4L2VideoSource::ReadFrameUserPtr(unsigned int& currentBufferIndex, unsigned int& bytesUsed)
655 {
656  v4l2_buffer buf;
657  CLEAR(buf);
658 
659  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
660  buf.memory = V4L2_MEMORY_USERPTR;
661 
662  if (-1 == xioctl(this->FileDescriptor, VIDIOC_DQBUF, &buf))
663  {
664  switch (errno)
665  {
666  case EAGAIN:
667  {
668  return PLUS_FAIL;
669  }
670  case EIO:
671  {
672  // Could ignore EIO, see spec
673  }
674  default:
675  {
676  LOG_ERROR("VIDIOC_DQBUF" << ": " << strerror(errno));
677  return PLUS_FAIL;
678  }
679  }
680  }
681 
682  for (currentBufferIndex = 0; currentBufferIndex < this->BufferCount; ++currentBufferIndex)
683  {
684  if (buf.m.userptr == (unsigned long) this->FrameBuffers[currentBufferIndex].start && buf.length == this->FrameBuffers[currentBufferIndex].length)
685  {
686  break;
687  }
688  }
689 
690  if (-1 == xioctl(this->FileDescriptor, VIDIOC_QBUF, &buf))
691  {
692  LOG_ERROR("VIDIOC_QBUF" << ": " << strerror(errno));
693  return PLUS_FAIL;
694  }
695 
696  bytesUsed = buf.bytesused;
697 
698  return PLUS_SUCCESS;
699 }
700 
701 //----------------------------------------------------------------------------
703 {
704  if (this->OutputChannels.empty())
705  {
706  LOG_ERROR("No output channels defined for vtkPlusV4L2VideoSource. Cannot proceed.");
707  this->CorrectlyConfigured = false;
708  return PLUS_FAIL;
709  }
710 
712  {
713  LOG_ERROR("Cannot retrieve first output video source. Unable to start device.");
714  return PLUS_FAIL;
715  }
716 
717  return PLUS_SUCCESS;
718 }
719 
720 //----------------------------------------------------------------------------
722 {
723  v4l2_buf_type type;
724 
725  switch (this->IOMethod)
726  {
727  case IO_METHOD_READ:
728  {
729  // Nothing to do
730  break;
731  }
732  case IO_METHOD_MMAP:
733  case IO_METHOD_USERPTR:
734  {
735  type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
736  if (-1 == xioctl(this->FileDescriptor, VIDIOC_STREAMOFF, &type))
737  {
738  LOG_ERROR("VIDIOC_STREAMOFF" << ": " << strerror(errno));
739  break;
740  }
741  }
742  }
743 
744  return PLUS_SUCCESS;
745 }
746 
747 //----------------------------------------------------------------------------
749 {
750  enum v4l2_buf_type type;
751 
752  switch (this->IOMethod)
753  {
754  case IO_METHOD_MMAP:
755  {
756  for (unsigned int i = 0; i < this->BufferCount; ++i)
757  {
758  struct v4l2_buffer buf;
759  CLEAR(buf);
760  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
761  buf.memory = V4L2_MEMORY_MMAP;
762  buf.index = i;
763 
764  if (-1 == xioctl(this->FileDescriptor, VIDIOC_QBUF, &buf))
765  {
766  LOG_ERROR("VIDIOC_QBUF" << ": " << strerror(errno));
767  return PLUS_FAIL;
768  }
769  }
770  type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
771  if (-1 == xioctl(this->FileDescriptor, VIDIOC_STREAMON, &type))
772  {
773  LOG_ERROR("VIDIOC_STREAMON" << ": " << strerror(errno));
774  return PLUS_FAIL;
775  }
776  break;
777  }
778  case IO_METHOD_USERPTR:
779  {
780  for (unsigned int i = 0; i < this->BufferCount; ++i)
781  {
782  struct v4l2_buffer buf;
783  CLEAR(buf);
784  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
785  buf.memory = V4L2_MEMORY_USERPTR;
786  buf.index = i;
787  buf.m.userptr = (unsigned long) this->FrameBuffers[i].start;
788  buf.length = this->FrameBuffers[i].length;
789 
790  if (-1 == xioctl(this->FileDescriptor, VIDIOC_QBUF, &buf))
791  {
792  LOG_ERROR("VIDIOC_QBUF" << ": " << strerror(errno));
793  return PLUS_FAIL;
794  }
795  }
796  type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
797  if (-1 == xioctl(this->FileDescriptor, VIDIOC_STREAMON, &type))
798  {
799  LOG_ERROR("VIDIOC_STREAMON" << ": " << strerror(errno));
800  return PLUS_FAIL;
801  }
802  break;
803  }
804  default:
805  {}
806  }
807 
808  return PLUS_SUCCESS;
809 }
810 
811 //----------------------------------------------------------------------------
812 std::string vtkPlusV4L2VideoSource::IOMethodToString(V4L2_IO_METHOD ioMethod)
813 {
814  switch (ioMethod)
815  {
816  case IO_METHOD_READ:
817  return "IO_METHOD_READ";
818  case IO_METHOD_MMAP:
819  return "IO_METHOD_MMAP";
820  case IO_METHOD_USERPTR:
821  return "IO_METHOD_USERPTR";
822  default:
823  return "IO_METHOD_UNKNOWN";
824  }
825 }
826 
827 //----------------------------------------------------------------------------
828 vtkPlusV4L2VideoSource::V4L2_IO_METHOD vtkPlusV4L2VideoSource::StringToIOMethod(const std::string& method)
829 {
830  if (igsioCommon::IsEqualInsensitive(method, "IO_METHOD_READ"))
831  {
832  return IO_METHOD_READ;
833  }
834  else if (igsioCommon::IsEqualInsensitive(method, "IO_METHOD_MMAP"))
835  {
836  return IO_METHOD_MMAP;
837  }
838  else if (igsioCommon::IsEqualInsensitive(method, "IO_METHOD_USERPTR"))
839  {
840  return IO_METHOD_USERPTR;
841  }
842  else
843  {
844  return IO_METHOD_UNKNOWN;
845  }
846 }
847 
848 //----------------------------------------------------------------------------
849 #define PIXEL_FORMAT_CASE(format) case format: return #format
850 std::string vtkPlusV4L2VideoSource::PixelFormatToString(unsigned int pixelFormat)
851 {
852  switch (pixelFormat)
853  {
854  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_RGB332);
855  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_RGB444);
856  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_ARGB444);
857  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_XRGB444);
858  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_RGB555);
859  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_ARGB555);
860  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_XRGB555);
861  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_RGB565);
862  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_RGB555X);
863  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_ARGB555X);
864  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_XRGB555X);
865  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_RGB565X);
866  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_BGR666);
867  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_BGR24);
868  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_RGB24);
869  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_BGR32);
870  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_ABGR32);
871  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_XBGR32);
872  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_RGB32);
873  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_ARGB32);
874  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_XRGB32);
875  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_GREY);
876  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_Y4);
877  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_Y6);
878  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_Y10);
879  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_Y12);
880  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_Y16);
881  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_Y16_BE);
882  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_Y10BPACK);
883  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_PAL8);
884  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_UV8);
885  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_YUYV);
886  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_YYUV);
887  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_YVYU);
888  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_UYVY);
889  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_VYUY);
890  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_Y41P);
891  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_YUV444);
892  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_YUV555);
893  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_YUV565);
894  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_YUV32);
895  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_HI240);
896  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_HM12);
897  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_M420);
898  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_NV12);
899  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_NV21);
900  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_NV16);
901  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_NV61);
902  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_NV24);
903  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_NV42);
904  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_NV12M);
905  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_NV21M);
906  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_NV16M);
907  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_NV61M);
908  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_NV12MT);
909  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_NV12MT_16X16);
910  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_YUV410);
911  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_YVU410);
912  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_YUV411P);
913  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_YUV420);
914  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_YVU420);
915  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_YUV422P);
916  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_YUV420M);
917  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_YVU420M);
918  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_MJPEG);
919  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_JPEG);
920  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_DV);
921  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_MPEG);
922  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_H264);
923  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_H264_NO_SC);
924  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_H264_MVC);
925  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_H263);
926  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_MPEG1);
927  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_MPEG2);
928  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_MPEG4);
929  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_XVID);
930  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_VC1_ANNEX_G);
931  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_VC1_ANNEX_L);
932  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_VP8);
933  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_CPIA1);
934  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_WNVA);
935  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_SN9C10X);
936  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_SN9C20X_I420);
937  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_PWC1);
938  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_PWC2);
939  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_ET61X251);
940  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_SPCA501);
941  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_SPCA505);
942  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_SPCA508);
943  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_SPCA561);
944  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_PAC207);
945  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_MR97310A);
946  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_JL2005BCD);
947  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_SN9C2028);
948  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_SQ905C);
949  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_PJPG);
950  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_OV511);
951  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_OV518);
952  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_STV0680);
953  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_TM6000);
954  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_CIT_YYVYUY);
955  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_KONICA420);
956  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_JPGL);
957  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_SE401);
958  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_S5C_UYVY_JPG);
959  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_Y8I);
960  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_Y12I);
961  PIXEL_FORMAT_CASE(V4L2_PIX_FMT_Z16);
962  default:
963  {return "V4L2_PIX_FMT_XXXX";}
964  }
965 }
966 #undef PIXEL_FORMAT_CASE
967 
968 //----------------------------------------------------------------------------
969 #define PIXEL_FORMAT_STRING_COMPARE(format, formatStr) else if (igsioCommon::IsEqualInsensitive(#format, formatStr)) return format
970 unsigned int vtkPlusV4L2VideoSource::StringToPixelFormat(const std::string& format)
971 {
972  if (igsioCommon::IsEqualInsensitive("V4L2_PIX_FMT_RGB332", format)) {return V4L2_PIX_FMT_RGB332;}
973  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_RGB444, format);
974  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_ARGB444, format);
975  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_XRGB444, format);
976  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_RGB555, format);
977  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_ARGB555, format);
978  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_XRGB555, format);
979  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_RGB565, format);
980  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_RGB555X, format);
981  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_ARGB555X, format);
982  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_XRGB555X, format);
983  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_RGB565X, format);
984  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_BGR666, format);
985  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_BGR24, format);
986  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_RGB24, format);
987  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_BGR32, format);
988  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_ABGR32, format);
989  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_XBGR32, format);
990  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_RGB32, format);
991  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_ARGB32, format);
992  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_XRGB32, format);
993  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_GREY, format);
994  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_Y4, format);
995  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_Y6, format);
996  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_Y10, format);
997  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_Y12, format);
998  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_Y16, format);
999  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_Y16_BE, format);
1000  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_Y10BPACK, format);
1001  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_PAL8, format);
1002  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_UV8, format);
1003  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_YUYV, format);
1004  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_YYUV, format);
1005  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_YVYU, format);
1006  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_UYVY, format);
1007  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_VYUY, format);
1008  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_Y41P, format);
1009  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_YUV444, format);
1010  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_YUV555, format);
1011  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_YUV565, format);
1012  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_YUV32, format);
1013  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_HI240, format);
1014  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_HM12, format);
1015  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_M420, format);
1016  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_NV12, format);
1017  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_NV21, format);
1018  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_NV16, format);
1019  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_NV61, format);
1020  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_NV24, format);
1021  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_NV42, format);
1022  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_NV12M, format);
1023  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_NV21M, format);
1024  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_NV16M, format);
1025  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_NV61M, format);
1026  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_NV12MT, format);
1027  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_NV12MT_16X16, format);
1028  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_YUV410, format);
1029  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_YVU410, format);
1030  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_YUV411P, format);
1031  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_YUV420, format);
1032  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_YVU420, format);
1033  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_YUV422P, format);
1034  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_YUV420M, format);
1035  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_YVU420M, format);
1036  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_MJPEG, format);
1037  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_JPEG, format);
1038  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_DV, format);
1039  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_MPEG, format);
1040  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_H264, format);
1041  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_H264_NO_SC, format);
1042  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_H264_MVC, format);
1043  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_H263, format);
1044  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_MPEG1, format);
1045  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_MPEG2, format);
1046  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_MPEG4, format);
1047  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_XVID, format);
1048  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_VC1_ANNEX_G, format);
1049  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_VC1_ANNEX_L, format);
1050  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_VP8, format);
1051  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_CPIA1, format);
1052  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_WNVA, format);
1053  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_SN9C10X, format);
1054  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_SN9C20X_I420, format);
1055  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_PWC1, format);
1056  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_PWC2, format);
1057  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_ET61X251, format);
1058  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_SPCA501, format);
1059  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_SPCA505, format);
1060  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_SPCA508, format);
1061  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_SPCA561, format);
1062  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_PAC207, format);
1063  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_MR97310A, format);
1064  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_JL2005BCD, format);
1065  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_SN9C2028, format);
1066  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_SQ905C, format);
1067  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_PJPG, format);
1068  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_OV511, format);
1069  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_OV518, format);
1070  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_STV0680, format);
1071  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_TM6000, format);
1072  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_CIT_YYVYUY, format);
1073  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_KONICA420, format);
1074  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_JPGL, format);
1075  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_SE401, format);
1076  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_S5C_UYVY_JPG, format);
1077  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_Y8I, format);
1078  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_Y12I, format);
1079  PIXEL_FORMAT_STRING_COMPARE(V4L2_PIX_FMT_Z16, format);
1080  else {return v4l2_fourcc('x', 'x', 'x', 'x');}
1081 }
1082 #undef PIXEL_FORMAT_STRING_COMPARE
1083 
1084 //----------------------------------------------------------------------------
1085 #define FIELD_ORDER_CASE(field) case field: return #field
1086 std::string vtkPlusV4L2VideoSource::FieldOrderToString(v4l2_field field)
1087 {
1088  switch (field)
1089  {
1090  FIELD_ORDER_CASE(V4L2_FIELD_ANY);
1091  FIELD_ORDER_CASE(V4L2_FIELD_NONE);
1092  FIELD_ORDER_CASE(V4L2_FIELD_TOP);
1093  FIELD_ORDER_CASE(V4L2_FIELD_BOTTOM);
1094  FIELD_ORDER_CASE(V4L2_FIELD_INTERLACED);
1095  FIELD_ORDER_CASE(V4L2_FIELD_SEQ_TB);
1096  FIELD_ORDER_CASE(V4L2_FIELD_SEQ_BT);
1097  FIELD_ORDER_CASE(V4L2_FIELD_ALTERNATE);
1098  FIELD_ORDER_CASE(V4L2_FIELD_INTERLACED_TB);
1099  FIELD_ORDER_CASE(V4L2_FIELD_INTERLACED_BT);
1100  default:
1101  {return "V4L2_FIELD_ANY";}
1102  }
1103 }
1104 #undef FIELD_ORDER_CASE
1105 
1106 //----------------------------------------------------------------------------
1107 v4l2_field vtkPlusV4L2VideoSource::StringToFieldOrder(const std::string& field)
1108 {
1109  if (igsioCommon::IsEqualInsensitive("V4L2_FIELD_ANY", field)) {return V4L2_FIELD_ANY;}
1110  else if (igsioCommon::IsEqualInsensitive("V4L2_FIELD_TOP", field)){return V4L2_FIELD_TOP;}
1111  else if (igsioCommon::IsEqualInsensitive("V4L2_FIELD_BOTTOM", field)){return V4L2_FIELD_BOTTOM;}
1112  else if (igsioCommon::IsEqualInsensitive("V4L2_FIELD_INTERLACED", field)){return V4L2_FIELD_INTERLACED;}
1113  else if (igsioCommon::IsEqualInsensitive("V4L2_FIELD_SEQ_TB", field)){return V4L2_FIELD_SEQ_TB;}
1114  else if (igsioCommon::IsEqualInsensitive("V4L2_FIELD_SEQ_BT", field)){return V4L2_FIELD_SEQ_BT;}
1115  else if (igsioCommon::IsEqualInsensitive("V4L2_FIELD_ALTERNATE", field)){return V4L2_FIELD_ALTERNATE;}
1116  else if (igsioCommon::IsEqualInsensitive("V4L2_FIELD_INTERLACED_TB", field)){return V4L2_FIELD_INTERLACED_TB;}
1117  else if (igsioCommon::IsEqualInsensitive("V4L2_FIELD_INTERLACED_BT", field)){return V4L2_FIELD_INTERLACED_BT;}
1118  else {return V4L2_FIELD_ANY;}
1119 }
std::shared_ptr< unsigned int > FormatWidth
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
static unsigned int StringToPixelFormat(const std::string &format)
virtual PlusStatus InternalStartRecording() VTK_OVERRIDE
#define CLEAR(x)
PlusStatus InitRead(unsigned int bufferSize)
std::shared_ptr< unsigned int > PixelFormat
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(deviceConfig, rootConfigElement)
PlusStatus ReadConfiguration(vtkXMLDataElement *config)
static std::string IOMethodToString(V4L2_IO_METHOD ioMethod)
igsioStatus PlusStatus
Definition: PlusCommon.h:40
PlusStatus SetInputFrameSize(unsigned int x, unsigned int y, unsigned int z)
virtual PlusStatus AddItem(vtkImageData *frame, US_IMAGE_ORIENTATION usImageOrientation, US_IMAGE_TYPE imageType, long frameNumber, double unfilteredTimestamp=UNDEFINED_TIMESTAMP, double filteredTimestamp=UNDEFINED_TIMESTAMP, const igsioFieldMapType *customFields=NULL)
PlusStatus WriteConfiguration(vtkXMLDataElement *config)
PlusStatus ReadFrame(unsigned int &currentBufferIndex, unsigned int &bytesUsed)
for i
PlusStatus ReadFrameFileDescriptor(unsigned int &currentBufferIndex, unsigned int &bytesUsed)
#define PLUS_FAIL
Definition: PlusCommon.h:43
PlusStatus SetPixelType(igsioCommon::VTKScalarPixelType pixelType)
virtual PlusStatus NotifyConfigured()
PlusStatus GetFirstActiveOutputVideoSource(vtkPlusDataSource *&aVideoSource)
Class for interfacing an V4L2 device and recording frames into a Plus buffer.
unsigned long FrameNumber
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
static v4l2_field StringToFieldOrder(const std::string &field)
#define PIXEL_FORMAT_CASE(format)
PlusStatus InitUserp(unsigned int bufferSize)
vtkPlusDataSource * DataSource
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_READING(deviceConfig, rootConfigElement)
static V4L2_IO_METHOD StringToIOMethod(const std::string &method)
const char * start
Definition: phidget22.h:5116
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
vtkStandardNewMacro(vtkPlusV4L2VideoSource)
static std::string PixelFormatToString(unsigned int format)
static std::string FieldOrderToString(v4l2_field field)
std::shared_ptr< v4l2_field > FieldOrder
bool StartThreadForInternalUpdates
ChannelContainer OutputChannels
virtual PlusStatus InternalDisconnect() VTK_OVERRIDE
PlusStatus SetNumberOfScalarComponents(unsigned int numberOfScalarComponents)
#define PIXEL_FORMAT_STRING_COMPARE(format, formatStr)
std::shared_ptr< unsigned int > FormatHeight
std::shared_ptr< struct v4l2_format > DeviceFormat
virtual PlusStatus InternalStopRecording() VTK_OVERRIDE
PlusStatus ReadFrameMemoryMap(unsigned int &currentBufferIndex, unsigned int &bytesUsed)
#define FIELD_ORDER_CASE(field)
virtual PlusStatus InternalConnect() VTK_OVERRIDE
PlusStatus ReadFrameUserPtr(unsigned int &currentBufferIndex, unsigned int &bytesUsed)
bool CorrectlyConfigured