14#include <QRegularExpression>
16#define LOC QString("V4L2(%1): ").arg(m_deviceName)
26 Open(dev_name, vbi_dev_name);
41 m_fd = open(dev_name.toLatin1().constData(), O_RDWR);
44 LOG(VB_CHANNEL, LOG_INFO,
LOC +
45 QString(
"Could not open '%1': ").arg(dev_name) +
ENO);
50 struct v4l2_query_ext_ctrl qc {};
51 qc.id = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND;
59 struct v4l2_capability capability {};
60 if (ioctl(
m_fd, VIDIOC_QUERYCAP, &capability) >= 0)
62 m_cardName = QString::fromLatin1((
const char*)capability.card);
63 m_driverName = QString::fromLatin1((
const char*)capability.driver);
73 static const QRegularExpression kDigitsRE { R
"(\[[0-9]\]$)" };
79 LOG(VB_CHANNEL, LOG_INFO,
LOC +
"Opened");
88 LOG(VB_CHANNEL, LOG_INFO,
LOC +
"Closed");
99 struct v4l2_requestbuffers reqbuf {};
101 if (-1 == ioctl (
m_fd, VIDIOC_REQBUFS, &reqbuf))
105 LOG(VB_CHANNEL, LOG_INFO,
LOC +
106 "Video capturing or mmap-streaming is not supported");
110 LOG(VB_CHANNEL, LOG_WARNING,
LOC +
"VIDIOC_REQBUFS" +
ENO);
124 uint32_t mask,
const QString& desc)
128 if (!result.isEmpty())
166 case V4L2_CTRL_TYPE_INTEGER:
168 case V4L2_CTRL_TYPE_INTEGER64:
170 case V4L2_CTRL_TYPE_STRING:
172 case V4L2_CTRL_TYPE_BOOLEAN:
174 case V4L2_CTRL_TYPE_MENU:
176 case V4L2_CTRL_TYPE_INTEGER_MENU:
178 case V4L2_CTRL_TYPE_BUTTON:
180 case V4L2_CTRL_TYPE_BITMASK:
182 case V4L2_CTRL_TYPE_U8:
184 case V4L2_CTRL_TYPE_U16:
186 case V4L2_CTRL_TYPE_U32:
196 struct v4l2_querymenu qmenu {};
197 QString nameStr((
char *)queryctrl.name);
199 qmenu.id = queryctrl.id;
202 static const QRegularExpression kNonPrintableRE {
"[^a-zA-Z\\d\\s]" };
203 nameStr.replace(kNonPrintableRE,
"_");
208 drv_opt.
m_step = queryctrl.step;
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")
241 else if (nameStr ==
"Sharpness")
243 else if (nameStr ==
"Volume")
248 switch (queryctrl.type)
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)
260 .arg(queryctrl.default_value);
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);
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);
277 case V4L2_CTRL_TYPE_MENU:
278 case V4L2_CTRL_TYPE_INTEGER_MENU:
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);
286 struct v4l2_querymenu querymenu = { 0, };
287 memset (&querymenu, 0,
sizeof (querymenu));
288 querymenu.id = queryctrl.id;
290 for (querymenu.index = queryctrl.minimum;
291 static_cast<int>(querymenu.index) <= queryctrl.maximum;
294 drv_opt.menu.clear();
295 if (0 == ioctl(
m_fd, VIDIOC_QUERYMENU, &querymenu))
297 msg += QString(
" menu>%1").arg((
char *)querymenu.name);
298 drv_opt.menu[querymenu.index] =
299 QString((
char *)querymenu.name);
306 case V4L2_CTRL_TYPE_BUTTON:
307 msg = QString(
"%1 :")
308 .arg(QString(
"%1 (%2)").arg(nameStr,
queryctrl_toString(queryctrl.type)), 31, QChar(
' '));
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(
' '));
320 msg = QString(
"%1 : type=%2")
321 .arg(QString(
"%1 (%2)").arg(nameStr,
queryctrl_toString(queryctrl.type)), 31, QChar(
' '))
322 .arg(queryctrl.type);
330 if (queryctrl.type == V4L2_CTRL_TYPE_MENU ||
331 queryctrl.type == V4L2_CTRL_TYPE_INTEGER_MENU)
333 for (
int idx = queryctrl.minimum; idx <= queryctrl.maximum; ++idx)
336 if (ioctl(
m_fd, VIDIOC_QUERYMENU, &qmenu))
339 drv_opt.
m_menu[idx] = QString((
char *)qmenu.name);
340 if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
342 msg += QString(
"\t\t%1: %2").arg(idx).arg((
char *)qmenu.name);
346 msg += QString(
"\t\t%1: %2 (0x%3)")
347 .arg(idx).arg(qmenu.value)
348 .arg(qmenu.value, 0, 16, QChar(
'0'));
353 LOG(VB_CHANNEL, LOG_INFO,
LOC + msg);
359 struct v4l2_control ctrl {};
360 struct v4l2_ext_control ext_ctrl {};
361 struct v4l2_ext_controls ctrls {};
363 if (qctrl.flags& V4L2_CTRL_FLAG_DISABLED)
365 msg += QString(
"'%1' Disabled").arg((
char *)qctrl.name);
369 if (qctrl.type == V4L2_CTRL_TYPE_CTRL_CLASS)
371 msg += QString(
"'%1' V4L2_CTRL_TYPE_CTRL_CLASS").arg((
char *)qctrl.name);
375 ext_ctrl.id = qctrl.id;
376 if ((qctrl.flags& V4L2_CTRL_FLAG_WRITE_ONLY) ||
377 qctrl.type == V4L2_CTRL_TYPE_BUTTON)
383 if (qctrl.type >= V4L2_CTRL_COMPOUND_TYPES)
389 ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(qctrl.id);
391 ctrls.controls = &ext_ctrl;
392 if (qctrl.type == V4L2_CTRL_TYPE_INTEGER64 ||
393 qctrl.type == V4L2_CTRL_TYPE_STRING ||
394 (V4L2_CTRL_ID2CLASS(qctrl.id) != V4L2_CTRL_CLASS_USER &&
395 qctrl.id < V4L2_CID_PRIVATE_BASE))
397 if (qctrl.type == V4L2_CTRL_TYPE_STRING)
399 ext_ctrl.size = qctrl.maximum + 1;
401 ext_ctrl.string = (
char *)malloc(ext_ctrl.size);
402 ext_ctrl.string[0] = 0;
404 if (ioctl(
m_fd, VIDIOC_G_EXT_CTRLS, &ctrls))
406 LOG(VB_CHANNEL, LOG_WARNING,
LOC +
407 QString(
"Failed to get ext_ctr %1: ")
408 .arg((
char *)qctrl.name) +
ENO);
414 if (ioctl(
m_fd, VIDIOC_G_CTRL, &ctrl))
416 LOG(VB_CHANNEL, LOG_WARNING,
LOC +
417 QString(
"Failed to get ctrl %1: ")
418 .arg((
char *)qctrl.name) +
ENO);
421 ext_ctrl.value = ctrl.value;
425 if (qctrl.type == V4L2_CTRL_TYPE_STRING)
426 free(ext_ctrl.string);
437 drv_opt.
m_name =
"Video Encoding";
439 V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
450 drv_opt.
m_name =
"Audio Encoding";
452 V4L2_MPEG_AUDIO_ENCODING_LAYER_2;
457 drv_opt.
m_name =
"Audio Bitrate";
459 V4L2_MPEG_AUDIO_ENCODING_LAYER_2;
465 drv_opt.
m_name =
"MPEG Audio sampling frequency";
467 V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
473 drv_opt.
m_name =
"Tuner Audio Modes";
475 V4L2_TUNER_MODE_STEREO;
480 DriverOption::Options::iterator Iopt =
options.begin();
481 for ( ; Iopt !=
options.end(); ++Iopt)
484 if (!(*Iopt).m_menu.isEmpty())
486 int minimum = INT_MAX;
489 DriverOption::menu_t::iterator Imenu = (*Iopt).m_menu.begin();
490 for ( ; Imenu != (*Iopt).m_menu.end(); ++Imenu)
492 minimum = std::min(Imenu.key(), minimum);
493 maximum = std::max(Imenu.key(), maximum);
495 if ((*Iopt).m_minimum != minimum)
497 LOG(VB_CHANNEL, LOG_INFO,
LOC +
498 QString(
"%1 menu options overrides minimum from %2 to %3")
499 .arg((*Iopt).m_name).arg((*Iopt).m_minimum).arg(minimum));
500 (*Iopt).m_minimum = minimum;
502 if ((*Iopt).m_maximum != maximum)
504 LOG(VB_CHANNEL, LOG_INFO,
LOC +
505 QString(
"%1 menu options overrides maximum from %2 to %3")
506 .arg((*Iopt).m_name).arg((*Iopt).m_maximum).arg(maximum));
507 (*Iopt).m_maximum = maximum;
515 struct v4l2_fmtdesc vid_fmtdesc {};
516 const std::array<const QString,2> flags {
"uncompressed",
"compressed"};
518 vid_fmtdesc.index = 0;
519 vid_fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
520 while(ioctl(
m_fd, VIDIOC_ENUM_FMT, &vid_fmtdesc) == 0)
522 formats << QString(
"%1 (%2)").arg((
char *)vid_fmtdesc.description,
523 flags[vid_fmtdesc.flags]);
534 LOG(VB_CHANNEL, LOG_DEBUG,
LOC + QString(
"GetFormats: %1")
542 LOG(VB_CHANNEL, LOG_INFO,
LOC +
"Options");
550 struct v4l2_queryctrl qctrl {};
551 qctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL;
552 while (0 == ioctl (
m_fd, VIDIOC_QUERYCTRL, &qctrl))
560 qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
575 LOG(VB_CHANNEL, LOG_WARNING,
LOC +
576 QString(
"Driver does not support option."));
581 DriverOption::menu_t::iterator Imenu = drv_opt.
m_menu.begin();
582 for ( ; Imenu != drv_opt.
m_menu.end(); ++Imenu)
584 if ((*Imenu) == desc)
586 LOG(VB_CHANNEL, LOG_INFO,
LOC + QString(
"GetOptionValue '%1' = %2")
587 .arg(desc).arg(Imenu.key()));
592 LOG(VB_CHANNEL, LOG_WARNING,
LOC +
593 QString(
"'%1' not found in driver options menu.").arg(desc));
599 v4l2_std_id std_id = 0;
600 struct v4l2_standard standard {};
602 if (-1 == ioctl (
m_fd, VIDIOC_G_STD, &std_id))
607 LOG(VB_CHANNEL, LOG_WARNING,
LOC +
608 "GetVideoStandard: Failed to detect signal." +
ENO);
614 while (0 == ioctl (
m_fd, VIDIOC_ENUMSTD, &standard))
616 if (standard.id & std_id)
618 name = (
char *)standard.name;
627 if (errno == EINVAL || standard.index == 0)
629 LOG(VB_CHANNEL, LOG_WARNING,
LOC +
630 "GetVideoStandard: Failed to find signal." +
ENO);
640 struct v4l2_tuner tuner {};
642 if (ioctl(
m_fd, VIDIOC_G_TUNER, &tuner, 0) != 0)
644 LOG(VB_GENERAL, LOG_ERR,
"GetSignalStrength() : "
645 "Failed to probe signal (v4l2)" +
ENO);
649 tuner.signal /= 655.35;
651 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"GetSignalStrength() : "
659 struct v4l2_format vfmt {};
661 vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
662 if (ioctl(
m_fd, VIDIOC_G_FMT, &vfmt) != 0)
664 LOG(VB_CHANNEL, LOG_WARNING,
LOC +
665 "Failed to determine resolution: " +
ENO);
670 width = vfmt.fmt.pix.width;
671 height = vfmt.fmt.pix.height;
672 LOG(VB_CHANNEL, LOG_INFO,
LOC +
673 QString(
"Resolution: %1x%2").arg(width).arg(height));
704 struct v4l2_queryctrl qctrl {};
706 qctrl.id = V4L2_CTRL_CLASS_MPEG | V4L2_CTRL_FLAG_NEXT_CTRL;
707 return (0 == ioctl (
m_fd, VIDIOC_QUERYCTRL, &qctrl) &&
708 V4L2_CTRL_ID2CLASS (qctrl.id) == V4L2_CTRL_CLASS_MPEG);
721 struct v4l2_ext_control ctrl {};
722 struct v4l2_ext_controls ctrls {};
727 ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
728 ctrls.controls = &ctrl;
730 if (ioctl(
m_fd, VIDIOC_G_EXT_CTRLS, &ctrls) != 0)
732 LOG(VB_GENERAL, LOG_ERR,
LOC +
733 QString(
"Failed to retrieve current %1 value.")
734 .arg(ctrl_desc) +
ENO);
738 return ctrls.controls->value;
743 const QString& value_desc)
747 if (current_value < 0)
749 if (current_value == value)
751 LOG(VB_CHANNEL, LOG_INFO,
LOC +
752 QString(
"%1 value is already %2 (%3).")
753 .arg(ctrl_desc, value_desc, QString::number(value)));
757 struct v4l2_ext_control ctrl {};
758 struct v4l2_ext_controls ctrls {};
764 ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
765 ctrls.controls = &ctrl;
767 if (ioctl(
m_fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
769 LOG(VB_GENERAL, LOG_ERR,
LOC +
770 QString(
"Failed to set %1 value to %2 (%3).")
771 .arg(ctrl_desc, value_desc, QString::number(value)) +
ENO);
775 LOG(VB_CHANNEL, LOG_INFO,
LOC +
776 QString(
"%1 value set to %2 (%3).")
777 .arg(ctrl_desc, value_desc, QString::number(value)));
786 case V4L2_MPEG_STREAM_TYPE_MPEG2_PS:
787 return "MPEG-2 program stream";
788 case V4L2_MPEG_STREAM_TYPE_MPEG2_TS:
789 return "MPEG-2 transport stream";
790 case V4L2_MPEG_STREAM_TYPE_MPEG1_SS:
791 return "MPEG-1 system stream";
792 case V4L2_MPEG_STREAM_TYPE_MPEG2_DVD:
793 return "MPEG-2 DVD-compatible stream";
794 case V4L2_MPEG_STREAM_TYPE_MPEG1_VCD:
795 return "MPEG-1 VCD-compatible stream";
796 case V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD:
797 return "MPEG-2 SVCD-compatible stream";
804 int type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
809 type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
816 LOG(VB_CHANNEL, LOG_INFO,
LOC +
817 QString(
"MPEG Stream Type is currently set to %1 (%2)")
829 value = V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
842 case V4L2_MPEG_VIDEO_ASPECT_1x1:
845 case V4L2_MPEG_VIDEO_ASPECT_4x3:
848 case V4L2_MPEG_VIDEO_ASPECT_16x9:
851 case V4L2_MPEG_VIDEO_ASPECT_221x100:
859 "Video Aspect ratio", desc);
867 case V4L2_MPEG_VIDEO_BITRATE_MODE_VBR:
870 case V4L2_MPEG_VIDEO_BITRATE_MODE_CBR:
875 return SetExtControl(V4L2_CID_MPEG_VIDEO_BITRATE_MODE, value,
876 "Video Bitrate Mode", desc);
881 QString desc = QString(
"%1").arg(value);
883 "Video Average Bitrate", desc);
888 QString desc = QString(
"%1").arg(value);
889 return SetExtControl(V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, value,
890 "Video Peak Bitrate", desc);
895 struct v4l2_format vfmt {};
897 vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
899 if (ioctl(
m_fd, VIDIOC_G_FMT, &vfmt) < 0)
901 LOG(VB_GENERAL, LOG_ERR,
LOC +
902 "SetResolution() -- Error getting format" +
ENO);
906 if ((vfmt.fmt.pix.width == width) && (vfmt.fmt.pix.height == height))
908 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"Resolution is already %1x%2")
909 .arg(width).arg(height));
913 vfmt.fmt.pix.width = width;
914 vfmt.fmt.pix.height = height;
916 if (ioctl(
m_fd, VIDIOC_S_FMT, &vfmt) < 0)
918 LOG(VB_GENERAL, LOG_ERR,
LOC +
919 "SetResolution() -- Error setting format" +
ENO);
923 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"Resolution set to %1x%2")
924 .arg(width).arg(height));
931 struct v4l2_audio ain {};
934 if (ioctl(
m_fd, VIDIOC_ENUMAUDIO, &ain) < 0)
936 LOG(VB_GENERAL, LOG_WARNING,
LOC +
937 QString(
"Failed to retrieve audio input.") +
ENO);
942 if (ioctl(
m_fd, VIDIOC_S_AUDIO, &ain) < 0)
944 LOG(VB_GENERAL, LOG_WARNING,
945 LOC + QString(
"Failed to set audio input to %1.").arg(value) +
ENO);
949 LOG(VB_CHANNEL, LOG_INFO,
LOC + QString(
"Audio input set to %1.")
958 value = V4L2_MPEG_AUDIO_ENCODING_LAYER_2;
964 case V4L2_MPEG_AUDIO_ENCODING_LAYER_1:
967 case V4L2_MPEG_AUDIO_ENCODING_LAYER_2:
970 case V4L2_MPEG_AUDIO_ENCODING_LAYER_3:
973 case V4L2_MPEG_AUDIO_ENCODING_AAC:
976 case V4L2_MPEG_AUDIO_ENCODING_AC3:
987 LOG(VB_CHANNEL, LOG_INFO,
LOC +
988 QString(
"Overriding AudioCodec for %1 to %2")
994 "Audio Codec", desc);
1001 struct v4l2_queryctrl qctrl {};
1002 qctrl.id = V4L2_CID_AUDIO_VOLUME;
1003 if ((ioctl(
m_fd, VIDIOC_QUERYCTRL, &qctrl) < 0) ||
1004 (qctrl.flags & V4L2_CTRL_FLAG_DISABLED))
1006 LOG(VB_CHANNEL, LOG_WARNING,
1007 LOC +
"SetRecordingVolume() -- Audio volume control not supported.");
1012 int range = qctrl.maximum - qctrl.minimum;
1013 int value = (int) ((range * volume * 0.01F) + qctrl.minimum);
1014 int ctrl_volume =
std::clamp(value, qctrl.minimum, qctrl.maximum);
1017 struct v4l2_control ctrl {};
1018 ctrl.id = V4L2_CID_AUDIO_VOLUME;
1019 ctrl.value = ctrl_volume;
1021 if (ioctl(
m_fd, VIDIOC_S_CTRL, &ctrl) < 0)
1023 LOG(VB_GENERAL, LOG_WARNING,
LOC +
1024 "SetRecordingVolume() -- Failed to set recording volume" +
ENO);
1029 LOG(VB_RECORD, LOG_INFO,
LOC +
"SetRecordingVolume() -- volume set.");
1035 struct v4l2_tuner vt {};
1037 if (ioctl(
m_fd, VIDIOC_G_TUNER, &vt) < 0)
1039 LOG(VB_CHANNEL, LOG_WARNING,
LOC +
1040 "SetLanguageMode() -- Failed to retrieve audio mode" +
ENO);
1046 if (ioctl(
m_fd, VIDIOC_S_TUNER, &vt) < 0)
1048 LOG(VB_CHANNEL, LOG_WARNING,
LOC +
1049 "SetLanguageMode -- Failed to set audio mode" +
ENO);
1056 case V4L2_TUNER_MODE_MONO:
1059 case V4L2_TUNER_MODE_STEREO:
1063 case V4L2_TUNER_MODE_LANG2:
1067 case V4L2_TUNER_MODE_SAP:
1070 case V4L2_TUNER_MODE_LANG1:
1073 case V4L2_TUNER_MODE_LANG1_LANG2:
1074 desc =
"LANG1&Lang2";
1081 LOG(VB_CHANNEL, LOG_INFO,
LOC + QString(
"Language Mode set to %1 (%2)")
1082 .arg(desc).arg(mode));
1092 value = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
1097 case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100:
1100 case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000:
1103 case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000:
1113 LOG(VB_CHANNEL, LOG_INFO,
LOC +
1114 QString(
"Overriding sampling frequence for %1 to %2")
1119 return SetExtControl(V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ, value,
1120 "Audio Sample Rate", desc);
1128 case V4L2_MPEG_AUDIO_L2_BITRATE_32K:
1131 case V4L2_MPEG_AUDIO_L2_BITRATE_48K:
1134 case V4L2_MPEG_AUDIO_L2_BITRATE_56K:
1137 case V4L2_MPEG_AUDIO_L2_BITRATE_64K:
1140 case V4L2_MPEG_AUDIO_L2_BITRATE_80K:
1143 case V4L2_MPEG_AUDIO_L2_BITRATE_96K:
1146 case V4L2_MPEG_AUDIO_L2_BITRATE_112K:
1149 case V4L2_MPEG_AUDIO_L2_BITRATE_128K:
1152 case V4L2_MPEG_AUDIO_L2_BITRATE_160K:
1155 case V4L2_MPEG_AUDIO_L2_BITRATE_192K:
1158 case V4L2_MPEG_AUDIO_L2_BITRATE_224K:
1161 case V4L2_MPEG_AUDIO_L2_BITRATE_256K:
1164 case V4L2_MPEG_AUDIO_L2_BITRATE_320K:
1167 case V4L2_MPEG_AUDIO_L2_BITRATE_384K:
1175 "Audio L2 Bitrate", desc);
1181 struct v4l2_encoder_cmd command {};
1184 if (ioctl(
m_fd, VIDIOC_ENCODER_CMD, &command) != 0 && errno != ENOTTY)
1189 LOG(VB_CHANNEL, LOG_WARNING,
LOC +
1190 QString(
"SetEncoderState(%1) -- failed").arg(desc) +
ENO);
1193 LOG(VB_CHANNEL, LOG_INFO,
LOC +
1194 QString(
"SetEncoderState(%1) -- success").arg(desc));
1225 struct v4l2_format vbifmt {};
1227 vbifmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
1229 V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
1233 if (ioctl(fd, VIDIOC_S_FMT, &vbifmt) < 0)
1235 LOG(VB_CHANNEL, LOG_WARNING,
LOC +
"ConfigureVBI() -- " +
1236 "Failed to enable VBI embedding (/dev/videoX)" +
ENO);
1240 if (ioctl(fd, VIDIOC_G_FMT, &vbifmt) >= 0)
1242 LOG(VB_RECORD, LOG_INFO,
1243 LOC + QString(
"VBI service: %1, io size: %2")
1244 .arg(vbifmt.fmt.sliced.service_set)
1245 .arg(vbifmt.fmt.sliced.io_size));
1250 V4L2_MPEG_STREAM_VBI_FMT_IVTV,
1251 "MPEG Stream VBI format",
1252 "VBI in private packets, IVTV form");
static const std::array< const std::string, 8 > formats
bool GetFormats(QStringList &formats)
bool GetVideoStandard(QString &name) const
bool HasTuner(void) const
bool ResumeEncoding(void)
static bool OpenVBI(const QString &vbi_dev_name)
bool Open(const QString &dev_name, const QString &vbi_dev_name="")
bool SetVideoBitrate(int value)
DriverOption::Options m_options
QString GetDriverName(void) const
bool GetResolution(int &width, int &height) const
bool log_control(struct v4l2_queryctrl &qctrl, DriverOption &drv_opt, QString &msg)
bool IsEncoder(void) const
void log_qctrl(struct v4l2_queryctrl &queryctrl, DriverOption &drv_opt, QString &msg)
bool SetLanguageMode(int mode)
bool SetAudioSamplingRate(int value)
int GetOptionValue(DriverOption::category_t cat, const QString &desc)
bool SetExtControl(int request, int value, const QString &ctrl_desc, const QString &value_desc)
static QString ctrlflags_toString(uint32_t flags)
bool SetSlicedVBI(VBIMode::vbimode_t vbimode)
bool SetEncoderState(int mode, const QString &desc)
bool SetVideoAspect(int value)
bool UserAdjustableResolution(void) const
QString DriverName(void) const
QString GetDeviceName(void) const
static QString queryctrl_toString(int type)
bool HasSlicedVBI(void) const
bool SetVolume(int volume)
bool HasAudioSupport(void) const
bool SetStreamType(int value)
bool HasStreaming(void) const
static void bitmask_toString(QString &result, uint32_t flags, uint32_t mask, const QString &desc)
void SetDefaultOptions(DriverOption::Options &options)
int GetStreamType(void) const
bool GetOptions(DriverOption::Options &options)
uint32_t GetCapabilities(void) const
int GetExtControl(int request, const QString &ctrl_desc="") const
bool SetAudioInput(int value)
bool SetResolution(uint32_t width, uint32_t height)
static QString StreamTypeDesc(int value)
bool SetVideoBitrateMode(int value)
bool SetVideoBitratePeak(int value)
bool SetAudioBitrateL2(int value)
int GetSignalStrength(void) const
bool SetAudioCodec(int value)
#define ENO
This can be appended to the LOG args with "+".
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
static eu8 clamp(eu8 value, eu8 low, eu8 high)
QMap< category_t, DriverOption > Options