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