MythTV  master
v4l2util.cpp
Go to the documentation of this file.
1 #include "v4l2util.h"
3 
4 #include <sys/ioctl.h>
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <algorithm>
8 #include <climits>
9 #include <fcntl.h>
10 #include <unistd.h>
11 
12 #include <array>
13 
14 #include <QRegularExpression>
15 
16 #define LOC QString("V4L2(%1): ").arg(m_deviceName)
17 
18 V4L2util::V4L2util(const QString& dev_name)
19 {
20  Open(dev_name);
21 }
22 
23 V4L2util::V4L2util(const QString& dev_name, const QString& vbi_dev_name)
24  : m_fd(0)
25 {
26  Open(dev_name, vbi_dev_name);
27 }
28 
30 {
31  Close();
32 }
33 
34 bool V4L2util::Open(const QString& dev_name, const QString& vbi_dev_name)
35 {
36  if (m_fd >= 0 && dev_name == m_deviceName)
37  return true;
38 
39  Close();
40 
41  m_fd = open(dev_name.toLatin1().constData(), O_RDWR);
42  if (m_fd < 0)
43  {
44  LOG(VB_CHANNEL, LOG_INFO, LOC +
45  QString("Could not open '%1': ").arg(dev_name) + ENO);
46  return false;
47  }
48  m_deviceName = dev_name;
49 
50  struct v4l2_query_ext_ctrl qc {};
51  qc.id = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND;
52  m_haveQueryExtCtrl = (ioctl(m_fd, VIDIOC_QUERY_EXT_CTRL, &qc) == 0);
53 
54  m_cardName.clear();
55  m_driverName.clear();
56  m_version = 0;
57  m_capabilities = 0;
58 
59  struct v4l2_capability capability {};
60  if (ioctl(m_fd, VIDIOC_QUERYCAP, &capability) >= 0)
61  {
62  m_cardName = QString::fromLatin1((const char*)capability.card);
63  m_driverName = QString::fromLatin1((const char*)capability.driver);
64  m_version = capability.version;
65  m_capabilities = capability.capabilities;
66  }
67  else
68  {
69  Close();
70  return false;
71  }
72 
73  static const QRegularExpression kDigitsRE { R"(\[[0-9]\]$)" };
74  if (!m_driverName.isEmpty())
75  m_driverName.remove( kDigitsRE );
76 
77  OpenVBI(vbi_dev_name);
78 
79  LOG(VB_CHANNEL, LOG_INFO, LOC + "Opened");
80  return true;
81 }
82 
84 {
85  if (m_fd >= 0)
86  {
87  close(m_fd);
88  LOG(VB_CHANNEL, LOG_INFO, LOC + "Closed");
89  }
90  m_fd = -1;
91  m_options.clear();
92 }
93 
94 bool V4L2util::HasStreaming(void) const
95 {
96  if (m_capabilities ^ V4L2_CAP_STREAMING)
97  return false;
98 
99  struct v4l2_requestbuffers reqbuf {};
100 
101  if (-1 == ioctl (m_fd, VIDIOC_REQBUFS, &reqbuf))
102  {
103  if (errno == EINVAL)
104  {
105  LOG(VB_CHANNEL, LOG_INFO, LOC +
106  "Video capturing or mmap-streaming is not supported");
107  }
108  else
109  {
110  LOG(VB_CHANNEL, LOG_WARNING, LOC + "VIDIOC_REQBUFS" + ENO);
111  }
112  return false;
113  }
114 
115  return true;
116 }
117 
118 bool V4L2util::HasSlicedVBI(void) const
119 {
120  return (m_capabilities & V4L2_CAP_SLICED_VBI_CAPTURE) != 0U;
121 }
122 
123 void V4L2util::bitmask_toString(QString& result, uint32_t flags,
124  uint32_t mask, const QString& desc)
125 {
126  if (flags& mask)
127  {
128  if (!result.isEmpty())
129  result += '|';
130  result += desc;
131  }
132 }
133 
134 QString V4L2util::ctrlflags_toString(uint32_t flags)
135 {
136  QString result;
137 
138  bitmask_toString(result, flags, V4L2_CTRL_FLAG_DISABLED,
139  "disabled");
140  bitmask_toString(result, flags, V4L2_CTRL_FLAG_GRABBED,
141  "grabbed");
142  bitmask_toString(result, flags, V4L2_CTRL_FLAG_READ_ONLY,
143  "read-only");
144  bitmask_toString(result, flags, V4L2_CTRL_FLAG_UPDATE,
145  "update");
146  bitmask_toString(result, flags, V4L2_CTRL_FLAG_INACTIVE,
147  "inactive");
148  bitmask_toString(result, flags, V4L2_CTRL_FLAG_SLIDER,
149  "slider");
150  bitmask_toString(result, flags, V4L2_CTRL_FLAG_WRITE_ONLY,
151  "write-only");
152  bitmask_toString(result, flags, V4L2_CTRL_FLAG_VOLATILE,
153  "volatile");
154  bitmask_toString(result, flags, V4L2_CTRL_FLAG_HAS_PAYLOAD,
155  "has-payload");
156  bitmask_toString(result, flags, V4L2_CTRL_FLAG_EXECUTE_ON_WRITE,
157  "execute-on-write");
158 
159  return result;
160 }
161 
163 {
164  switch (type)
165  {
166  case V4L2_CTRL_TYPE_INTEGER:
167  return "int";
168  case V4L2_CTRL_TYPE_INTEGER64:
169  return "int64";
170  case V4L2_CTRL_TYPE_STRING:
171  return "str";
172  case V4L2_CTRL_TYPE_BOOLEAN:
173  return "bool";
174  case V4L2_CTRL_TYPE_MENU:
175  return "menu";
176  case V4L2_CTRL_TYPE_INTEGER_MENU:
177  return "intmenu";
178  case V4L2_CTRL_TYPE_BUTTON:
179  return "button";
180  case V4L2_CTRL_TYPE_BITMASK:
181  return "bitmask";
182  case V4L2_CTRL_TYPE_U8:
183  return "u8";
184  case V4L2_CTRL_TYPE_U16:
185  return "u16";
186  case V4L2_CTRL_TYPE_U32:
187  return "u32";
188  default:
189  return "unknown";
190  }
191 }
192 
193 void V4L2util::log_qctrl(struct v4l2_queryctrl& queryctrl,
194  DriverOption& drv_opt, QString& msg)
195 {
196  struct v4l2_querymenu qmenu {};
197  QString nameStr((char *)queryctrl.name);
198 
199  qmenu.id = queryctrl.id;
200 
201  // Replace non-printable with _
202  static const QRegularExpression kNonPrintableRE { "[^a-zA-Z\\d\\s]" };
203  nameStr.replace(kNonPrintableRE, "_");
204 
205  drv_opt.m_name = nameStr;
206  drv_opt.m_minimum = queryctrl.minimum;
207  drv_opt.m_maximum = queryctrl.maximum;
208  drv_opt.m_step = queryctrl.step;
209  drv_opt.m_defaultValue = queryctrl.default_value;;
210 
211  if (nameStr == "Stream Type")
213  else if (nameStr == "Video Encoding")
215  else if (nameStr == "Video Aspect")
217  else if (nameStr == "Video B Frames")
219  else if (nameStr == "Video GOP Size")
221  else if (nameStr == "Video Bitrate Mode")
223  else if (nameStr == "Video Bitrate")
225  else if (nameStr == "Video Peak Bitrate")
227  else if (nameStr == "Audio Encoding")
229  else if (nameStr == "Audio Bitrate Mode")
231  else if (nameStr == "Audio Bitrate")
233  else if (nameStr == "Brightness")
235  else if (nameStr == "Contrast")
237  else if (nameStr == "Saturation")
239  else if (nameStr == "Hue")
240  drv_opt.m_category = DriverOption::HUE;
241  else if (nameStr == "Sharpness")
243  else if (nameStr == "Volume")
245  else
247 
248  switch (queryctrl.type)
249  {
250  case V4L2_CTRL_TYPE_INTEGER:
251  case V4L2_CTRL_TYPE_INTEGER64:
252  case V4L2_CTRL_TYPE_U8:
253  case V4L2_CTRL_TYPE_U16:
254  case V4L2_CTRL_TYPE_U32:
255  msg = QString("%1 : min=%2 max=%3 step=%4 default=%5")
256  .arg(QString("%1 (%2)").arg(nameStr, queryctrl_toString(queryctrl.type)), 31, QChar(' '))
257  .arg(queryctrl.minimum)
258  .arg(queryctrl.maximum)
259  .arg(queryctrl.step)
260  .arg(queryctrl.default_value);
261  drv_opt.m_type = DriverOption::INTEGER;
262  break;
263  case V4L2_CTRL_TYPE_STRING:
264  msg = QString("%1 : min=%2 max=%3 step=%4")
265  .arg(QString("%1 (%2)").arg(nameStr, queryctrl_toString(queryctrl.type)), 31, QChar(' '))
266  .arg(queryctrl.minimum)
267  .arg(queryctrl.maximum)
268  .arg(queryctrl.step);
269  drv_opt.m_type = DriverOption::STRING;
270  break;
271  case V4L2_CTRL_TYPE_BOOLEAN:
272  msg = QString("%1 : default=%2")
273  .arg(QString("%1 (%2)").arg(nameStr, queryctrl_toString(queryctrl.type)), 31, QChar(' '))
274  .arg(queryctrl.default_value);
275  drv_opt.m_type = DriverOption::BOOLEAN;
276  break;
277  case V4L2_CTRL_TYPE_MENU:
278  case V4L2_CTRL_TYPE_INTEGER_MENU:
279  {
280  msg = QString("%1 : min=%3 max=%4 default=%5")
281  .arg(QString("%1 (%2)").arg(nameStr, queryctrl_toString(queryctrl.type)), 31, QChar(' '))
282  .arg(queryctrl.minimum)
283  .arg(queryctrl.maximum)
284  .arg(queryctrl.default_value);
285 #if 0
286  struct v4l2_querymenu querymenu = { 0, };
287  memset (&querymenu, 0, sizeof (querymenu));
288  querymenu.id = queryctrl.id;
289 
290  for (querymenu.index = queryctrl.minimum;
291  static_cast<int>(querymenu.index) <= queryctrl.maximum;
292  ++querymenu.index)
293  {
294  drv_opt.menu.clear();
295  if (0 == ioctl(m_fd, VIDIOC_QUERYMENU, &querymenu))
296  {
297  msg += QString(" menu>%1").arg((char *)querymenu.name);
298  drv_opt.menu[querymenu.index] =
299  QString((char *)querymenu.name);
300  }
301  }
302 #endif
303  drv_opt.m_type = DriverOption::MENU;
304  break;
305  }
306  case V4L2_CTRL_TYPE_BUTTON:
307  msg = QString("%1 :")
308  .arg(QString("%1 (%2)").arg(nameStr, queryctrl_toString(queryctrl.type)), 31, QChar(' '));
309  drv_opt.m_type = DriverOption::BUTTON;
310  break;
311  case V4L2_CTRL_TYPE_BITMASK:
312  msg = QString("%1 : max=0x%2 default=0x%3")
313  .arg(QString("%1 (%2)").arg(nameStr, queryctrl_toString(queryctrl.type)), 31, QChar(' '))
314  .arg(queryctrl.maximum, 8, 16, QChar(' '))
315  .arg(queryctrl.default_value, 8, 16, QChar(' '));
316  drv_opt.m_type = DriverOption::BITMASK;
317  break;
318 
319  default:
320  msg = QString("%1 : type=%2")
321  .arg(QString("%1 (%2)").arg(nameStr, queryctrl_toString(queryctrl.type)), 31, QChar(' '))
322  .arg(queryctrl.type);
324  break;
325  }
326 
327  if (queryctrl.flags)
328  msg += QString(" flags=%1").arg(ctrlflags_toString(queryctrl.flags));
329 
330  if (queryctrl.type == V4L2_CTRL_TYPE_MENU ||
331  queryctrl.type == V4L2_CTRL_TYPE_INTEGER_MENU)
332  {
333  for (int idx = queryctrl.minimum; idx <= queryctrl.maximum; ++idx)
334  {
335  qmenu.index = idx;
336  if (ioctl(m_fd, VIDIOC_QUERYMENU, &qmenu))
337  continue;
338 
339  drv_opt.m_menu[idx] = QString((char *)qmenu.name);
340  if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
341  msg += QString("\t\t%1: %2").arg(idx).arg((char *)qmenu.name);
342  else
343  {
344  msg += QString("\t\t%1: %2 (0x%3)")
345  .arg(idx).arg(qmenu.value)
346  .arg(qmenu.value, 0, 16, QChar('0'));
347  }
348  }
349  }
350 
351  LOG(VB_CHANNEL, LOG_INFO, LOC + msg);
352 }
353 
354 bool V4L2util::log_control(struct v4l2_queryctrl& qctrl, DriverOption& drv_opt,
355  QString& msg)
356 {
357  struct v4l2_control ctrl {};
358  struct v4l2_ext_control ext_ctrl {};
359  struct v4l2_ext_controls ctrls {};
360 
361  if (qctrl.flags& V4L2_CTRL_FLAG_DISABLED)
362  {
363  msg += QString("'%1' Disabled").arg((char *)qctrl.name);
364  return true;
365  }
366 
367  if (qctrl.type == V4L2_CTRL_TYPE_CTRL_CLASS)
368  {
369  msg += QString("'%1' V4L2_CTRL_TYPE_CTRL_CLASS").arg((char *)qctrl.name);
370  return true;
371  }
372 
373  ext_ctrl.id = qctrl.id;
374  if ((qctrl.flags& V4L2_CTRL_FLAG_WRITE_ONLY) ||
375  qctrl.type == V4L2_CTRL_TYPE_BUTTON)
376  {
377  log_qctrl(qctrl, drv_opt, msg);
378  return true;
379  }
380 
381  if (qctrl.type >= V4L2_CTRL_COMPOUND_TYPES)
382  {
383  log_qctrl(qctrl, drv_opt, msg);
384  return true;
385  }
386 
387  ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(qctrl.id);
388  ctrls.count = 1;
389  ctrls.controls = &ext_ctrl;
390  if (qctrl.type == V4L2_CTRL_TYPE_INTEGER64 ||
391  qctrl.type == V4L2_CTRL_TYPE_STRING ||
392  (V4L2_CTRL_ID2CLASS(qctrl.id) != V4L2_CTRL_CLASS_USER &&
393  qctrl.id < V4L2_CID_PRIVATE_BASE))
394  {
395  if (qctrl.type == V4L2_CTRL_TYPE_STRING)
396  {
397  ext_ctrl.size = qctrl.maximum + 1;
398  ext_ctrl.string = (char *)malloc(ext_ctrl.size);
399  ext_ctrl.string[0] = 0;
400  }
401  if (ioctl(m_fd, VIDIOC_G_EXT_CTRLS, &ctrls))
402  {
403  LOG(VB_CHANNEL, LOG_WARNING, LOC +
404  QString("Failed to get ext_ctr %1: ")
405  .arg((char *)qctrl.name) + ENO);
406  return false;
407  }
408  }
409  else {
410  ctrl.id = qctrl.id;
411  if (ioctl(m_fd, VIDIOC_G_CTRL, &ctrl))
412  {
413  LOG(VB_CHANNEL, LOG_WARNING, LOC +
414  QString("Failed to get ctrl %1: ")
415  .arg((char *)qctrl.name) + ENO);
416  return false;
417  }
418  ext_ctrl.value = ctrl.value;
419  }
420  log_qctrl(qctrl, drv_opt, msg);
421 
422  if (qctrl.type == V4L2_CTRL_TYPE_STRING)
423  free(ext_ctrl.string);
424  return true;
425 }
426 
427 // Some drivers don't set 'default' options, so make some assumptions
429 {
430  if (!options.contains(DriverOption::VIDEO_ENCODING))
431  {
432  DriverOption drv_opt;
434  drv_opt.m_name = "Video Encoding";
435  drv_opt.m_minimum = drv_opt.m_maximum = drv_opt.m_defaultValue =
436  V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
437  drv_opt.m_menu[drv_opt.m_defaultValue] = "MPEG-2 Video";
438  options[drv_opt.m_category] = drv_opt;
439  }
440 
441  if (!options.contains(DriverOption::AUDIO_ENCODING))
442  {
443  DriverOption drv_opt;
444 
445  // V4L2_CID_MPEG_AUDIO_ENCODING
447  drv_opt.m_name = "Audio Encoding";
448  drv_opt.m_minimum = drv_opt.m_maximum = drv_opt.m_defaultValue =
449  V4L2_MPEG_AUDIO_ENCODING_LAYER_2;
450  drv_opt.m_menu[drv_opt.m_defaultValue] = "MPEG-1/2 Layer II encoding";
451  options[drv_opt.m_category] = drv_opt;
452 
454  drv_opt.m_name = "Audio Bitrate";
455  drv_opt.m_minimum = drv_opt.m_maximum = drv_opt.m_defaultValue =
456  V4L2_MPEG_AUDIO_ENCODING_LAYER_2;
457  drv_opt.m_menu[drv_opt.m_defaultValue] = "MPEG-1/2 Layer II encoding";
458  options[drv_opt.m_category] = drv_opt;
459 
460  // V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ
462  drv_opt.m_name = "MPEG Audio sampling frequency";
463  drv_opt.m_minimum = drv_opt.m_maximum = drv_opt.m_defaultValue =
464  V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
465  drv_opt.m_menu[drv_opt.m_defaultValue] = "48 kHz";
466  options[drv_opt.m_category] = drv_opt;
467 
468  // VIDIOC_S_TUNER
470  drv_opt.m_name = "Tuner Audio Modes";
471  drv_opt.m_minimum = drv_opt.m_maximum = drv_opt.m_defaultValue =
472  V4L2_TUNER_MODE_STEREO;
473  drv_opt.m_menu[drv_opt.m_defaultValue] = "Play stereo audio";
474  options[drv_opt.m_category] = drv_opt;
475  }
476 
477  DriverOption::Options::iterator Iopt = options.begin();
478  for ( ; Iopt != options.end(); ++Iopt)
479  {
480  // If the driver provides a menu of options, use it to set limits
481  if (!(*Iopt).m_menu.isEmpty())
482  {
483  int minimum = INT_MAX;
484  int maximum = -1;
485 
486  DriverOption::menu_t::iterator Imenu = (*Iopt).m_menu.begin();
487  for ( ; Imenu != (*Iopt).m_menu.end(); ++Imenu)
488  {
489  minimum = std::min(Imenu.key(), minimum);
490  maximum = std::max(Imenu.key(), maximum);
491  }
492  if ((*Iopt).m_minimum != minimum)
493  {
494  LOG(VB_CHANNEL, LOG_INFO, LOC +
495  QString("%1 menu options overrides minimum from %2 to %3")
496  .arg((*Iopt).m_name).arg((*Iopt).m_minimum).arg(minimum));
497  (*Iopt).m_minimum = minimum;
498  }
499  if ((*Iopt).m_maximum != maximum)
500  {
501  LOG(VB_CHANNEL, LOG_INFO, LOC +
502  QString("%1 menu options overrides maximum from %2 to %3")
503  .arg((*Iopt).m_name).arg((*Iopt).m_maximum).arg(maximum));
504  (*Iopt).m_maximum = maximum;
505  }
506  }
507  }
508 }
509 
510 bool V4L2util::GetFormats(QStringList& formats)
511 {
512  struct v4l2_fmtdesc vid_fmtdesc {};
513  const std::array<const QString,2> flags {"uncompressed", "compressed"};
514 
515  vid_fmtdesc.index = 0;
516  vid_fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
517  while(ioctl(m_fd, VIDIOC_ENUM_FMT, &vid_fmtdesc) == 0)
518  {
519  formats << QString("%1 (%2)").arg((char *)vid_fmtdesc.description,
520  flags[vid_fmtdesc.flags]);
521 
522  /* Convert the pixelformat attributes from FourCC into 'human readab
523  fprintf(stdout, " pixelformat :%c%c%c%c\\n",
524  vid_fmtdesc.pixelformat& 0xFF, (vid_fmtdesc.pixelformat >>
525  (vid_fmtdesc.pixelformat >> 16)& 0xFF, (vid_fmtdesc.pixelfo
526  */
527 
528  vid_fmtdesc.index++;
529  }
530 
531  LOG(VB_CHANNEL, LOG_DEBUG, LOC + QString("GetFormats: %1")
532  .arg(formats.join(",")));
533 
534  return true;
535 }
536 
538 {
539  LOG(VB_CHANNEL, LOG_INFO, LOC + "Options");
540 
541  if (!m_options.isEmpty())
542  {
543  options = m_options;
544  return true;
545  }
546 
547  struct v4l2_queryctrl qctrl {};
548  qctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL;
549  while (0 == ioctl (m_fd, VIDIOC_QUERYCTRL, &qctrl))
550  {
551  QString msg;
552  DriverOption drv_opt;
553 
554  log_control(qctrl, drv_opt, msg);
555  m_options[drv_opt.m_category] = drv_opt;
556 
557  qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
558  }
559 
561  options = m_options;
562  return true;
563 }
564 
566 {
567  if (m_options.isEmpty())
569 
570  if (!m_options.contains(cat))
571  {
572  LOG(VB_CHANNEL, LOG_WARNING, LOC +
573  QString("Driver does not support option."));
574  return -1;
575  }
576 
577  DriverOption drv_opt = m_options.value(cat);
578  DriverOption::menu_t::iterator Imenu = drv_opt.m_menu.begin();
579  for ( ; Imenu != drv_opt.m_menu.end(); ++Imenu)
580  {
581  if ((*Imenu) == desc)
582  {
583  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("GetOptionValue '%1' = %2")
584  .arg(desc).arg(Imenu.key()));
585  return Imenu.key();
586  }
587  }
588 
589  LOG(VB_CHANNEL, LOG_WARNING, LOC +
590  QString("'%1' not found in driver options menu.").arg(desc));
591  return -1;
592 }
593 
594 bool V4L2util::GetVideoStandard(QString& name) const
595 {
596  v4l2_std_id std_id = 0;
597  struct v4l2_standard standard {};
598 
599  if (-1 == ioctl (m_fd, VIDIOC_G_STD, &std_id))
600  {
601  /* Note when VIDIOC_ENUMSTD always returns EINVAL this
602  is no video device or it falls under the USB exception,
603  and VIDIOC_G_STD returning EINVAL is no error. */
604  LOG(VB_CHANNEL, LOG_WARNING, LOC +
605  "GetVideoStandard: Failed to detect signal." + ENO);
606  return false;
607  }
608 
609  standard.index = 0;
610 
611  while (0 == ioctl (m_fd, VIDIOC_ENUMSTD, &standard))
612  {
613  if (standard.id & std_id)
614  {
615  name = (char *)standard.name;
616  return true;
617  }
618 
619  ++standard.index;
620  }
621 
622  /* EINVAL indicates the end of the enumeration, which cannot be
623  empty unless this device falls under the USB exception. */
624  if (errno == EINVAL || standard.index == 0)
625  {
626  LOG(VB_CHANNEL, LOG_WARNING, LOC +
627  "GetVideoStandard: Failed to find signal." + ENO);
628  }
629 
630  return false;
631 }
632 
634 {
635  return -1; // Does not work
636 
637  struct v4l2_tuner tuner {};
638 
639  if (ioctl(m_fd, VIDIOC_G_TUNER, &tuner, 0) != 0)
640  {
641  LOG(VB_GENERAL, LOG_ERR, "GetSignalStrength() : "
642  "Failed to probe signal (v4l2)" + ENO);
643  return -1;
644  }
645 
646  tuner.signal /= 655.35; // Set to 0-100 range
647 
648  LOG(VB_RECORD, LOG_INFO, LOC + QString("GetSignalStrength() : "
649  "(%1\%)")
650  .arg(tuner.signal));
651  return tuner.signal;
652 }
653 
654 bool V4L2util::GetResolution(int& width, int& height) const
655 {
656  struct v4l2_format vfmt {};
657 
658  vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
659  if (ioctl(m_fd, VIDIOC_G_FMT, &vfmt) != 0)
660  {
661  LOG(VB_CHANNEL, LOG_WARNING, LOC +
662  "Failed to determine resolution: " + ENO);
663  width = height = -1;
664  return false;
665  }
666 
667  width = vfmt.fmt.pix.width;
668  height = vfmt.fmt.pix.height;
669  LOG(VB_CHANNEL, LOG_INFO, LOC +
670  QString("Resolution: %1x%2").arg(width).arg(height));
671  return true;
672 }
673 
674 uint32_t V4L2util::GetCapabilities(void) const
675 {
676  return m_capabilities;
677 }
678 
679 QString V4L2util::GetDeviceName(void) const
680 {
681  return m_deviceName;
682 }
683 
684 QString V4L2util::GetDriverName(void) const
685 {
686  return m_driverName;
687 }
688 
689 bool V4L2util::HasTuner(void) const
690 {
691  return (m_capabilities & V4L2_CAP_TUNER) != 0U;
692 }
693 
695 {
696  return (m_capabilities & V4L2_CAP_AUDIO) != 0U;
697 }
698 
699 bool V4L2util::IsEncoder(void) const
700 {
701  struct v4l2_queryctrl qctrl {};
702 
703  qctrl.id = V4L2_CTRL_CLASS_MPEG | V4L2_CTRL_FLAG_NEXT_CTRL;
704  return (0 == ioctl (m_fd, VIDIOC_QUERYCTRL, &qctrl) &&
705  V4L2_CTRL_ID2CLASS (qctrl.id) == V4L2_CTRL_CLASS_MPEG);
706 }
707 
709 {
710  // I have not been able to come up with a way of querying the
711  // driver to answer this question.
712 
713  return m_driverName != "hdpvr";
714 }
715 
716 int V4L2util::GetExtControl(int request, const QString& ctrl_desc) const
717 {
718  struct v4l2_ext_control ctrl {};
719  struct v4l2_ext_controls ctrls {};
720 
721  ctrl.id = request;
722 
723  ctrls.count = 1;
724  ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
725  ctrls.controls = &ctrl;
726 
727  if (ioctl(m_fd, VIDIOC_G_EXT_CTRLS, &ctrls) != 0)
728  {
729  LOG(VB_GENERAL, LOG_ERR, LOC +
730  QString("Failed to retrieve current %1 value.")
731  .arg(ctrl_desc) + ENO);
732  return -1;
733  }
734 
735  return ctrls.controls->value;
736 }
737 
738 
739 bool V4L2util::SetExtControl(int request, int value, const QString& ctrl_desc,
740  const QString& value_desc)
741 {
742  int current_value = GetExtControl(request, ctrl_desc);
743 
744  if (current_value < 0)
745  return false;
746  if (current_value == value)
747  {
748  LOG(VB_CHANNEL, LOG_INFO, LOC +
749  QString("%1 value is already %2 (%3).")
750  .arg(ctrl_desc, value_desc, QString::number(value)));
751  return true;
752  }
753 
754  struct v4l2_ext_control ctrl {};
755  struct v4l2_ext_controls ctrls {};
756 
757  ctrl.id = request;
758  ctrl.value = value;
759 
760  ctrls.count = 1;
761  ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
762  ctrls.controls = &ctrl;
763 
764  if (ioctl(m_fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
765  {
766  LOG(VB_GENERAL, LOG_ERR, LOC +
767  QString("Failed to set %1 value to %2 (%3).")
768  .arg(ctrl_desc, value_desc, QString::number(value)) + ENO);
769  return false;
770  }
771 
772  LOG(VB_CHANNEL, LOG_INFO, LOC +
773  QString("%1 value set to %2 (%3).")
774  .arg(ctrl_desc, value_desc, QString::number(value)));
775 
776  return true;
777 }
778 
779 QString V4L2util::StreamTypeDesc(int value)
780 {
781  switch (value)
782  {
783  case V4L2_MPEG_STREAM_TYPE_MPEG2_PS:
784  return "MPEG-2 program stream";
785  case V4L2_MPEG_STREAM_TYPE_MPEG2_TS:
786  return "MPEG-2 transport stream";
787  case V4L2_MPEG_STREAM_TYPE_MPEG1_SS:
788  return "MPEG-1 system stream";
789  case V4L2_MPEG_STREAM_TYPE_MPEG2_DVD:
790  return "MPEG-2 DVD-compatible stream";
791  case V4L2_MPEG_STREAM_TYPE_MPEG1_VCD:
792  return "MPEG-1 VCD-compatible stream";
793  case V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD:
794  return "MPEG-2 SVCD-compatible stream";
795  }
796  return "Unknown";
797 }
798 
799 int V4L2util::GetStreamType(void) const
800 {
801  int type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
802 
803  if (DriverName().startsWith("saa7164"))
804  {
805  // The saa7164 driver reports that it can do TS, but it doesn't work!
806  type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
807  }
808  else
809  {
810  type = GetExtControl(V4L2_CID_MPEG_STREAM_TYPE, "Stream Type");
811  }
812 
813  LOG(VB_CHANNEL, LOG_INFO, LOC +
814  QString("MPEG Stream Type is currently set to %1 (%2)")
815  .arg(StreamTypeDesc(type)).arg(type));
816 
817  return type;
818 }
819 
820 bool V4L2util::SetStreamType(int value)
821 {
822  if (DriverName().startsWith("saa7164") ||
823  DriverName().startsWith("ivtv"))
824  {
825  // The saa7164 driver reports that it can do TS, but it doesn't work!
826  value = V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
827  }
828 
829  return SetExtControl(V4L2_CID_MPEG_STREAM_TYPE, value,
830  "MPEG Stream type", StreamTypeDesc(value));
831 }
832 
833 // Video controls
835 {
836  QString desc;
837  switch (value)
838  {
839  case V4L2_MPEG_VIDEO_ASPECT_1x1:
840  desc = "Square";
841  break;
842  case V4L2_MPEG_VIDEO_ASPECT_4x3:
843  desc = "4x3";
844  break;
845  case V4L2_MPEG_VIDEO_ASPECT_16x9:
846  desc = "16x9";
847  break;
848  case V4L2_MPEG_VIDEO_ASPECT_221x100:
849  desc = "221x100";
850  break;
851  default:
852  desc = "Unknown";
853  }
854 
855  return SetExtControl(V4L2_CID_MPEG_VIDEO_ASPECT, value,
856  "Video Aspect ratio", desc);
857 }
858 
860 {
861  QString desc;
862  switch (value)
863  {
864  case V4L2_MPEG_VIDEO_BITRATE_MODE_VBR:
865  desc = "VBR";
866  break;
867  case V4L2_MPEG_VIDEO_BITRATE_MODE_CBR:
868  desc = "CBR";
869  break;
870  }
871 
872  return SetExtControl(V4L2_CID_MPEG_VIDEO_BITRATE_MODE, value,
873  "Video Bitrate Mode", desc);
874 }
875 
877 {
878  QString desc = QString("%1").arg(value);
879  return SetExtControl(V4L2_CID_MPEG_VIDEO_BITRATE, value,
880  "Video Average Bitrate", desc);
881 }
882 
884 {
885  QString desc = QString("%1").arg(value);
886  return SetExtControl(V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, value,
887  "Video Peak Bitrate", desc);
888 }
889 
890 bool V4L2util::SetResolution(uint32_t width, uint32_t height)
891 {
892  struct v4l2_format vfmt {};
893 
894  vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
895 
896  if (ioctl(m_fd, VIDIOC_G_FMT, &vfmt) < 0)
897  {
898  LOG(VB_GENERAL, LOG_ERR, LOC +
899  "SetResolution() -- Error getting format" + ENO);
900  return false;
901  }
902 
903  if ((vfmt.fmt.pix.width == width) && (vfmt.fmt.pix.height == height))
904  {
905  LOG(VB_RECORD, LOG_INFO, LOC + QString("Resolution is already %1x%2")
906  .arg(width).arg(height));
907  return true;
908  }
909 
910  vfmt.fmt.pix.width = width;
911  vfmt.fmt.pix.height = height;
912 
913  if (ioctl(m_fd, VIDIOC_S_FMT, &vfmt) < 0)
914  {
915  LOG(VB_GENERAL, LOG_ERR, LOC +
916  "SetResolution() -- Error setting format" + ENO);
917  return false;
918  }
919 
920  LOG(VB_RECORD, LOG_INFO, LOC + QString("Resolution set to %1x%2")
921  .arg(width).arg(height));
922  return true;
923 }
924 
925 // Audio controls
926 bool V4L2util::SetAudioInput(int value)
927 {
928  struct v4l2_audio ain {};
929 
930  ain.index = value;
931  if (ioctl(m_fd, VIDIOC_ENUMAUDIO, &ain) < 0)
932  {
933  LOG(VB_GENERAL, LOG_WARNING, LOC +
934  QString("Failed to retrieve audio input.") + ENO);
935  return false;
936  }
937 
938  ain.index = value;
939  if (ioctl(m_fd, VIDIOC_S_AUDIO, &ain) < 0)
940  {
941  LOG(VB_GENERAL, LOG_WARNING,
942  LOC + QString("Failed to set audio input to %1.").arg(value) + ENO);
943  return false;
944  }
945 
946  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Audio input set to %1.")
947  .arg(value));
948  return true;
949 }
950 
951 bool V4L2util::SetAudioCodec(int value)
952 {
953 #if 0
954  if (DriverName().startsWith("ivtv"))
955  value = V4L2_MPEG_AUDIO_ENCODING_LAYER_2;
956 #endif
957 
958  QString desc;
959  switch (value)
960  {
961  case V4L2_MPEG_AUDIO_ENCODING_LAYER_1:
962  desc = "Layer I";
963  break;
964  case V4L2_MPEG_AUDIO_ENCODING_LAYER_2:
965  desc = "Layer II";
966  break;
967  case V4L2_MPEG_AUDIO_ENCODING_LAYER_3:
968  desc = "Layer III";
969  break;
970  case V4L2_MPEG_AUDIO_ENCODING_AAC:
971  desc = "AAC";
972  break;
973  case V4L2_MPEG_AUDIO_ENCODING_AC3:
974  desc = "AC3";
975  break;
976  default:
977  desc = "Unknown";
978  break;
979  }
980 
981 #if 0
982  if (DriverName().startsWith("ivtv"))
983  {
984  LOG(VB_CHANNEL, LOG_INFO, LOC +
985  QString("Overriding AudioCodec for %1 to %2")
986  .arg(DriverName()).arg(desc));
987  }
988 #endif
989 
990  return SetExtControl(V4L2_CID_MPEG_AUDIO_ENCODING, value,
991  "Audio Codec", desc);
992 }
993 
994 
995 bool V4L2util::SetVolume(int volume)
996 {
997  // Get volume min/max values
998  struct v4l2_queryctrl qctrl {};
999  qctrl.id = V4L2_CID_AUDIO_VOLUME;
1000  if ((ioctl(m_fd, VIDIOC_QUERYCTRL, &qctrl) < 0) ||
1001  (qctrl.flags & V4L2_CTRL_FLAG_DISABLED))
1002  {
1003  LOG(VB_CHANNEL, LOG_WARNING,
1004  LOC + "SetRecordingVolume() -- Audio volume control not supported.");
1005  return false;
1006  }
1007 
1008  // calculate volume in card units.
1009  int range = qctrl.maximum - qctrl.minimum;
1010  int value = (int) ((range * volume * 0.01F) + qctrl.minimum);
1011  int ctrl_volume = std::clamp(value, qctrl.minimum, qctrl.maximum);
1012 
1013  // Set recording volume
1014  struct v4l2_control ctrl {};
1015  ctrl.id = V4L2_CID_AUDIO_VOLUME;
1016  ctrl.value = ctrl_volume;
1017 
1018  if (ioctl(m_fd, VIDIOC_S_CTRL, &ctrl) < 0)
1019  {
1020  LOG(VB_GENERAL, LOG_WARNING, LOC +
1021  "SetRecordingVolume() -- Failed to set recording volume" + ENO);
1022 // "If you are using an AverMedia M179 card this is normal."
1023  return false;
1024  }
1025 
1026  LOG(VB_RECORD, LOG_INFO, LOC + "SetRecordingVolume() -- volume set.");
1027  return true;
1028 }
1029 
1031 {
1032  struct v4l2_tuner vt {};
1033 
1034  if (ioctl(m_fd, VIDIOC_G_TUNER, &vt) < 0)
1035  {
1036  LOG(VB_CHANNEL, LOG_WARNING, LOC +
1037  "SetLanguageMode() -- Failed to retrieve audio mode" + ENO);
1038  return false;
1039  }
1040 
1041  vt.audmode = mode;
1042 
1043  if (ioctl(m_fd, VIDIOC_S_TUNER, &vt) < 0)
1044  {
1045  LOG(VB_CHANNEL, LOG_WARNING, LOC +
1046  "SetLanguageMode -- Failed to set audio mode" + ENO);
1047  return false;
1048  }
1049 
1050  QString desc;
1051  switch (mode)
1052  {
1053  case V4L2_TUNER_MODE_MONO:
1054  desc = "Mono";
1055  break;
1056  case V4L2_TUNER_MODE_STEREO:
1057  desc = "Stereo";
1058  break;
1059 #if 0
1060  case V4L2_TUNER_MODE_LANG2:
1061  desc = "Lang2";
1062  break;
1063 #endif
1064  case V4L2_TUNER_MODE_SAP:
1065  desc = "SAP";
1066  break;
1067  case V4L2_TUNER_MODE_LANG1:
1068  desc = "LANG1";
1069  break;
1070  case V4L2_TUNER_MODE_LANG1_LANG2:
1071  desc = "LANG1&Lang2";
1072  break;
1073  default:
1074  desc = "Unknown";
1075  break;
1076  }
1077 
1078  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Language Mode set to %1 (%2)")
1079  .arg(desc).arg(mode));
1080  return true;
1081 }
1082 
1084 {
1085  QString desc;
1086 
1087 #if 0
1088  if (DriverName().startsWith("ivtv"))
1089  value = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
1090 #endif
1091 
1092  switch (value)
1093  {
1094  case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100:
1095  desc = "44.1kHz";
1096  break;
1097  case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000:
1098  desc = "48kHz";
1099  break;
1100  case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000:
1101  desc = "32kHz";
1102  break;
1103  default:
1104  desc = "Unknown";
1105  }
1106 
1107 #if 0
1108  if (DriverName().startsWith("ivtv"))
1109  {
1110  LOG(VB_CHANNEL, LOG_INFO, LOC +
1111  QString("Overriding sampling frequence for %1 to %2")
1112  .arg(DriverName()).arg(desc));
1113  }
1114 #endif
1115 
1116  return SetExtControl(V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ, value,
1117  "Audio Sample Rate", desc);
1118 }
1119 
1121 {
1122  QString desc;
1123  switch (value)
1124  {
1125  case V4L2_MPEG_AUDIO_L2_BITRATE_32K:
1126  desc = "32K";
1127  break;
1128  case V4L2_MPEG_AUDIO_L2_BITRATE_48K:
1129  desc = "48K";
1130  break;
1131  case V4L2_MPEG_AUDIO_L2_BITRATE_56K:
1132  desc = "56K";
1133  break;
1134  case V4L2_MPEG_AUDIO_L2_BITRATE_64K:
1135  desc = "64K";
1136  break;
1137  case V4L2_MPEG_AUDIO_L2_BITRATE_80K:
1138  desc = "80K";
1139  break;
1140  case V4L2_MPEG_AUDIO_L2_BITRATE_96K:
1141  desc = "96K";
1142  break;
1143  case V4L2_MPEG_AUDIO_L2_BITRATE_112K:
1144  desc = "112K";
1145  break;
1146  case V4L2_MPEG_AUDIO_L2_BITRATE_128K:
1147  desc = "128K";
1148  break;
1149  case V4L2_MPEG_AUDIO_L2_BITRATE_160K:
1150  desc = "160K";
1151  break;
1152  case V4L2_MPEG_AUDIO_L2_BITRATE_192K:
1153  desc = "192K";
1154  break;
1155  case V4L2_MPEG_AUDIO_L2_BITRATE_224K:
1156  desc = "224K";
1157  break;
1158  case V4L2_MPEG_AUDIO_L2_BITRATE_256K:
1159  desc = "256K";
1160  break;
1161  case V4L2_MPEG_AUDIO_L2_BITRATE_320K:
1162  desc = "320K";
1163  break;
1164  case V4L2_MPEG_AUDIO_L2_BITRATE_384K:
1165  desc = "384K";
1166  break;
1167  default:
1168  desc = "Unknown";
1169  }
1170 
1171  return SetExtControl(V4L2_CID_MPEG_AUDIO_L2_BITRATE, value,
1172  "Audio L2 Bitrate", desc);
1173 }
1174 
1175 // Actions
1176 bool V4L2util::SetEncoderState(int mode, const QString& desc)
1177 {
1178  struct v4l2_encoder_cmd command {};
1179 
1180  command.cmd = mode;
1181  if (ioctl(m_fd, VIDIOC_ENCODER_CMD, &command) != 0 && errno != ENOTTY)
1182  {
1183  // Some drivers do not support this ioctl at all. It is marked as
1184  // "experimental" in the V4L2 API spec. These drivers return EINVAL
1185  // in older kernels and ENOTTY in 3.1+
1186  LOG(VB_CHANNEL, LOG_WARNING, LOC +
1187  QString("SetEncoderState(%1) -- failed").arg(desc) + ENO);
1188  return false;
1189  }
1190  LOG(VB_CHANNEL, LOG_INFO, LOC +
1191  QString("SetEncoderState(%1) -- success").arg(desc));
1192  return true;
1193 }
1194 
1196 {
1197  return SetEncoderState(V4L2_ENC_CMD_START, "Start");
1198 }
1199 
1201 {
1202  return SetEncoderState(V4L2_ENC_CMD_STOP, "Stop");
1203 }
1204 
1206 {
1207  return SetEncoderState(V4L2_ENC_CMD_PAUSE, "Pause");
1208 }
1209 
1211 {
1212  return SetEncoderState(V4L2_ENC_CMD_RESUME, "Resume");
1213 }
1214 
1215 bool V4L2util::OpenVBI(const QString& /*vbi_dev_name*/)
1216 {
1217  return false;
1218 }
1219 
1221 {
1222  struct v4l2_format vbifmt {};
1223 
1224  vbifmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
1225  vbifmt.fmt.sliced.service_set |= (VBIMode::PAL_TT == vbimode) ?
1226  V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
1227 
1228  int fd = m_vbiFd < 0 ? m_fd : m_vbiFd;
1229 
1230  if (ioctl(fd, VIDIOC_S_FMT, &vbifmt) < 0)
1231  {
1232  LOG(VB_CHANNEL, LOG_WARNING, LOC + "ConfigureVBI() -- " +
1233  "Failed to enable VBI embedding (/dev/videoX)" + ENO);
1234  return false;
1235  }
1236 
1237  if (ioctl(fd, VIDIOC_G_FMT, &vbifmt) >= 0)
1238  {
1239  LOG(VB_RECORD, LOG_INFO,
1240  LOC + QString("VBI service: %1, io size: %2")
1241  .arg(vbifmt.fmt.sliced.service_set)
1242  .arg(vbifmt.fmt.sliced.io_size));
1243 
1244  // V4L2_MPEG_STREAM_VBI_FMT_NONE = 0, /* No VBI in the MPEG stream */
1245  // V4L2_MPEG_STREAM_VBI_FMT_IVTV = 1, /* VBI in private packets, IVTV form
1246  return SetExtControl(V4L2_CID_MPEG_STREAM_VBI_FMT,
1247  V4L2_MPEG_STREAM_VBI_FMT_IVTV,
1248  "MPEG Stream VBI format",
1249  "VBI in private packets, IVTV form");
1250 
1251  }
1252 
1253  return false;
1254 }
DriverOption::m_step
uint32_t m_step
Definition: driveroption.h:33
V4L2util::SetAudioBitrateL2
bool SetAudioBitrateL2(int value)
Definition: v4l2util.cpp:1120
V4L2util::StartEncoding
bool StartEncoding(void)
Definition: v4l2util.cpp:1195
V4L2util::m_capabilities
uint32_t m_capabilities
Definition: v4l2util.h:106
ENO
#define ENO
This can be appended to the LOG args with "+".
Definition: mythlogging.h:73
V4L2util::GetResolution
bool GetResolution(int &width, int &height) const
Definition: v4l2util.cpp:654
DriverOption::Options
QMap< category_t, DriverOption > Options
Definition: driveroption.h:22
V4L2util::SetAudioInput
bool SetAudioInput(int value)
Definition: v4l2util.cpp:926
DriverOption::VIDEO_ASPECT
@ VIDEO_ASPECT
Definition: driveroption.h:10
DriverOption::m_defaultValue
int32_t m_defaultValue
Definition: driveroption.h:31
DriverOption::BUTTON
@ BUTTON
Definition: driveroption.h:19
V4L2util::SetEncoderState
bool SetEncoderState(int mode, const QString &desc)
Definition: v4l2util.cpp:1176
V4L2util::SetVideoBitrate
bool SetVideoBitrate(int value)
Definition: v4l2util.cpp:876
V4L2util::DriverName
QString DriverName(void) const
Definition: v4l2util.h:48
V4L2util::SetExtControl
bool SetExtControl(int request, int value, const QString &ctrl_desc, const QString &value_desc)
Definition: v4l2util.cpp:739
DriverOption::SATURATION
@ SATURATION
Definition: driveroption.h:15
V4L2util::SetLanguageMode
bool SetLanguageMode(int mode)
Definition: v4l2util.cpp:1030
hardwareprofile.devicelist.cat
def cat(file_name)
Definition: devicelist.py:95
V4L2util::queryctrl_toString
static QString queryctrl_toString(int type)
Definition: v4l2util.cpp:162
V4L2util::m_options
DriverOption::Options m_options
Definition: v4l2util.h:101
V4L2util::GetFormats
bool GetFormats(QStringList &formats)
Definition: v4l2util.cpp:510
V4L2util::SetVideoAspect
bool SetVideoAspect(int value)
Definition: v4l2util.cpp:834
V4L2util::HasTuner
bool HasTuner(void) const
Definition: v4l2util.cpp:689
V4L2util::StopEncoding
bool StopEncoding(void)
Definition: v4l2util.cpp:1200
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
DriverOption::AUDIO_BITRATE
@ AUDIO_BITRATE
Definition: driveroption.h:14
DriverOption::VIDEO_BITRATE_PEAK
@ VIDEO_BITRATE_PEAK
Definition: driveroption.h:12
DriverOption::VIDEO_BITRATE
@ VIDEO_BITRATE
Definition: driveroption.h:12
VBIMode::PAL_TT
@ PAL_TT
Definition: tv.h:13
close
#define close
Definition: compat.h:43
V4L2util::SetSlicedVBI
bool SetSlicedVBI(VBIMode::vbimode_t vbimode)
Definition: v4l2util.cpp:1220
DriverOption::category_t
category_t
Definition: driveroption.h:9
LOC
#define LOC
Definition: v4l2util.cpp:16
V4L2util::SetResolution
bool SetResolution(uint32_t width, uint32_t height)
Definition: v4l2util.cpp:890
mythlogging.h
DriverOption::VIDEO_BITRATE_MODE
@ VIDEO_BITRATE_MODE
Definition: driveroption.h:12
DriverOption::m_minimum
int32_t m_minimum
Definition: driveroption.h:29
V4L2util::SetVideoBitratePeak
bool SetVideoBitratePeak(int value)
Definition: v4l2util.cpp:883
DriverOption::AUDIO_BITRATE_MODE
@ AUDIO_BITRATE_MODE
Definition: driveroption.h:13
V4L2util::log_control
bool log_control(struct v4l2_queryctrl &qctrl, DriverOption &drv_opt, QString &msg)
Definition: v4l2util.cpp:354
V4L2util::UserAdjustableResolution
bool UserAdjustableResolution(void) const
Definition: v4l2util.cpp:708
V4L2util::SetAudioCodec
bool SetAudioCodec(int value)
Definition: v4l2util.cpp:951
V4L2util::SetVolume
bool SetVolume(int volume)
Definition: v4l2util.cpp:995
v4l2util.h
DriverOption::UNKNOWN_CAT
@ UNKNOWN_CAT
Definition: driveroption.h:10
V4L2util::HasSlicedVBI
bool HasSlicedVBI(void) const
Definition: v4l2util.cpp:118
V4L2util::StreamTypeDesc
static QString StreamTypeDesc(int value)
Definition: v4l2util.cpp:779
V4L2util::PauseEncoding
bool PauseEncoding(void)
Definition: v4l2util.cpp:1205
DriverOption::SHARPNESS
@ SHARPNESS
Definition: driveroption.h:15
V4L2util::ctrlflags_toString
static QString ctrlflags_toString(uint32_t flags)
Definition: v4l2util.cpp:134
V4L2util::SetDefaultOptions
void SetDefaultOptions(DriverOption::Options &options)
Definition: v4l2util.cpp:428
VBIMode::vbimode_t
vbimode_t
Definition: tv.h:10
V4L2util::GetExtControl
int GetExtControl(int request, const QString &ctrl_desc="") const
Definition: v4l2util.cpp:716
V4L2util::Open
bool Open(const QString &dev_name, const QString &vbi_dev_name="")
Definition: v4l2util.cpp:34
formats
const std::array< const std::string, 8 > formats
Definition: vbilut.cpp:189
V4L2util::m_vbiFd
int m_vbiFd
Definition: v4l2util.h:100
V4L2util::log_qctrl
void log_qctrl(struct v4l2_queryctrl &queryctrl, DriverOption &drv_opt, QString &msg)
Definition: v4l2util.cpp:193
DriverOption
Definition: driveroption.h:6
DriverOption::m_name
QString m_name
Definition: driveroption.h:27
DriverOption::VIDEO_ENCODING
@ VIDEO_ENCODING
Definition: driveroption.h:10
DriverOption::MENU
@ MENU
Definition: driveroption.h:18
V4L2util::m_version
int m_version
Definition: v4l2util.h:105
DriverOption::BRIGHTNESS
@ BRIGHTNESS
Definition: driveroption.h:15
DriverOption::BOOLEAN
@ BOOLEAN
Definition: driveroption.h:18
DriverOption::UNKNOWN_TYPE
@ UNKNOWN_TYPE
Definition: driveroption.h:18
V4L2util::HasStreaming
bool HasStreaming(void) const
Definition: v4l2util.cpp:94
V4L2util::GetVideoStandard
bool GetVideoStandard(QString &name) const
Definition: v4l2util.cpp:594
V4L2util::m_driverName
QString m_driverName
Definition: v4l2util.h:103
clamp
static eu8 clamp(eu8 value, eu8 low, eu8 high)
Definition: pxsup2dast.c:204
V4L2util::GetDeviceName
QString GetDeviceName(void) const
Definition: v4l2util.cpp:679
DriverOption::STREAM_TYPE
@ STREAM_TYPE
Definition: driveroption.h:10
DriverOption::AUDIO_LANGUAGE
@ AUDIO_LANGUAGE
Definition: driveroption.h:14
V4L2util::SetStreamType
bool SetStreamType(int value)
Definition: v4l2util.cpp:820
DriverOption::m_category
category_t m_category
Definition: driveroption.h:28
DriverOption::AUDIO_SAMPLERATE
@ AUDIO_SAMPLERATE
Definition: driveroption.h:13
vbimode
vbimode
Definition: vbilut.h:21
V4L2util::HasAudioSupport
bool HasAudioSupport(void) const
Definition: v4l2util.cpp:694
V4L2util::m_deviceName
QString m_deviceName
Definition: v4l2util.h:102
DriverOption::m_type
type_t m_type
Definition: driveroption.h:36
V4L2util::GetDriverName
QString GetDriverName(void) const
Definition: v4l2util.cpp:684
DriverOption::m_menu
menu_t m_menu
Definition: driveroption.h:35
V4L2util::m_fd
int m_fd
Definition: v4l2util.h:99
DriverOption::m_maximum
int32_t m_maximum
Definition: driveroption.h:30
DriverOption::HUE
@ HUE
Definition: driveroption.h:15
V4L2util::m_haveQueryExtCtrl
bool m_haveQueryExtCtrl
Definition: v4l2util.h:107
V4L2util::GetOptionValue
int GetOptionValue(DriverOption::category_t cat, const QString &desc)
Definition: v4l2util.cpp:565
V4L2util::m_cardName
QString m_cardName
Definition: v4l2util.h:104
V4L2util::~V4L2util
~V4L2util(void)
Definition: v4l2util.cpp:29
V4L2util::SetVideoBitrateMode
bool SetVideoBitrateMode(int value)
Definition: v4l2util.cpp:859
V4L2util::SetAudioSamplingRate
bool SetAudioSamplingRate(int value)
Definition: v4l2util.cpp:1083
V4L2util::GetOptions
bool GetOptions(DriverOption::Options &options)
Definition: v4l2util.cpp:537
V4L2util::bitmask_toString
static void bitmask_toString(QString &result, uint32_t flags, uint32_t mask, const QString &desc)
Definition: v4l2util.cpp:123
V4L2util::V4L2util
V4L2util(void)=default
DriverOption::BITMASK
@ BITMASK
Definition: driveroption.h:19
DriverOption::VOLUME
@ VOLUME
Definition: driveroption.h:14
DriverOption::STRING
@ STRING
Definition: driveroption.h:18
DriverOption::VIDEO_GOP_SIZE
@ VIDEO_GOP_SIZE
Definition: driveroption.h:11
V4L2util::ResumeEncoding
bool ResumeEncoding(void)
Definition: v4l2util.cpp:1210
V4L2util::IsEncoder
bool IsEncoder(void) const
Definition: v4l2util.cpp:699
V4L2util::GetCapabilities
uint32_t GetCapabilities(void) const
Definition: v4l2util.cpp:674
V4L2util::GetStreamType
int GetStreamType(void) const
Definition: v4l2util.cpp:799
DriverOption::INTEGER
@ INTEGER
Definition: driveroption.h:18
V4L2util::OpenVBI
static bool OpenVBI(const QString &vbi_dev_name)
Definition: v4l2util.cpp:1215
V4L2util::Close
void Close(void)
Definition: v4l2util.cpp:83
build_compdb.options
options
Definition: build_compdb.py:11
DriverOption::VIDEO_B_FRAMES
@ VIDEO_B_FRAMES
Definition: driveroption.h:11
DriverOption::AUDIO_ENCODING
@ AUDIO_ENCODING
Definition: driveroption.h:13
DriverOption::CONTRAST
@ CONTRAST
Definition: driveroption.h:15
V4L2util::GetSignalStrength
int GetSignalStrength(void) const
Definition: v4l2util.cpp:633