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)
341 msg += QString(
"\t\t%1: %2").arg(idx).arg((
char *)qmenu.name);
344 msg += QString(
"\t\t%1: %2 (0x%3)")
345 .arg(idx).arg(qmenu.value)
346 .arg(qmenu.value, 0, 16, QChar(
'0'));
351 LOG(VB_CHANNEL, LOG_INFO,
LOC + msg);
357 struct v4l2_control ctrl {};
358 struct v4l2_ext_control ext_ctrl {};
359 struct v4l2_ext_controls ctrls {};
361 if (qctrl.flags& V4L2_CTRL_FLAG_DISABLED)
363 msg += QString(
"'%1' Disabled").arg((
char *)qctrl.name);
367 if (qctrl.type == V4L2_CTRL_TYPE_CTRL_CLASS)
369 msg += QString(
"'%1' V4L2_CTRL_TYPE_CTRL_CLASS").arg((
char *)qctrl.name);
373 ext_ctrl.id = qctrl.id;
374 if ((qctrl.flags& V4L2_CTRL_FLAG_WRITE_ONLY) ||
375 qctrl.type == V4L2_CTRL_TYPE_BUTTON)
381 if (qctrl.type >= V4L2_CTRL_COMPOUND_TYPES)
387 ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(qctrl.id);
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))
395 if (qctrl.type == V4L2_CTRL_TYPE_STRING)
397 ext_ctrl.size = qctrl.maximum + 1;
399 ext_ctrl.string = (
char *)malloc(ext_ctrl.size);
400 ext_ctrl.string[0] = 0;
402 if (ioctl(
m_fd, VIDIOC_G_EXT_CTRLS, &ctrls))
404 LOG(VB_CHANNEL, LOG_WARNING,
LOC +
405 QString(
"Failed to get ext_ctr %1: ")
406 .arg((
char *)qctrl.name) +
ENO);
412 if (ioctl(
m_fd, VIDIOC_G_CTRL, &ctrl))
414 LOG(VB_CHANNEL, LOG_WARNING,
LOC +
415 QString(
"Failed to get ctrl %1: ")
416 .arg((
char *)qctrl.name) +
ENO);
419 ext_ctrl.value = ctrl.value;
423 if (qctrl.type == V4L2_CTRL_TYPE_STRING)
424 free(ext_ctrl.string);
435 drv_opt.
m_name =
"Video Encoding";
437 V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
448 drv_opt.
m_name =
"Audio Encoding";
450 V4L2_MPEG_AUDIO_ENCODING_LAYER_2;
455 drv_opt.
m_name =
"Audio Bitrate";
457 V4L2_MPEG_AUDIO_ENCODING_LAYER_2;
463 drv_opt.
m_name =
"MPEG Audio sampling frequency";
465 V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
471 drv_opt.
m_name =
"Tuner Audio Modes";
473 V4L2_TUNER_MODE_STEREO;
478 DriverOption::Options::iterator Iopt =
options.begin();
479 for ( ; Iopt !=
options.end(); ++Iopt)
482 if (!(*Iopt).m_menu.isEmpty())
484 int minimum = INT_MAX;
487 DriverOption::menu_t::iterator Imenu = (*Iopt).m_menu.begin();
488 for ( ; Imenu != (*Iopt).m_menu.end(); ++Imenu)
490 minimum = std::min(Imenu.key(), minimum);
491 maximum = std::max(Imenu.key(), maximum);
493 if ((*Iopt).m_minimum != minimum)
495 LOG(VB_CHANNEL, LOG_INFO,
LOC +
496 QString(
"%1 menu options overrides minimum from %2 to %3")
497 .arg((*Iopt).m_name).arg((*Iopt).m_minimum).arg(minimum));
498 (*Iopt).m_minimum = minimum;
500 if ((*Iopt).m_maximum != maximum)
502 LOG(VB_CHANNEL, LOG_INFO,
LOC +
503 QString(
"%1 menu options overrides maximum from %2 to %3")
504 .arg((*Iopt).m_name).arg((*Iopt).m_maximum).arg(maximum));
505 (*Iopt).m_maximum = maximum;
513 struct v4l2_fmtdesc vid_fmtdesc {};
514 const std::array<const QString,2> flags {
"uncompressed",
"compressed"};
516 vid_fmtdesc.index = 0;
517 vid_fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
518 while(ioctl(
m_fd, VIDIOC_ENUM_FMT, &vid_fmtdesc) == 0)
520 formats << QString(
"%1 (%2)").arg((
char *)vid_fmtdesc.description,
521 flags[vid_fmtdesc.flags]);
532 LOG(VB_CHANNEL, LOG_DEBUG,
LOC + QString(
"GetFormats: %1")
540 LOG(VB_CHANNEL, LOG_INFO,
LOC +
"Options");
548 struct v4l2_queryctrl qctrl {};
549 qctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL;
550 while (0 == ioctl (
m_fd, VIDIOC_QUERYCTRL, &qctrl))
558 qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
573 LOG(VB_CHANNEL, LOG_WARNING,
LOC +
574 QString(
"Driver does not support option."));
579 DriverOption::menu_t::iterator Imenu = drv_opt.
m_menu.begin();
580 for ( ; Imenu != drv_opt.
m_menu.end(); ++Imenu)
582 if ((*Imenu) == desc)
584 LOG(VB_CHANNEL, LOG_INFO,
LOC + QString(
"GetOptionValue '%1' = %2")
585 .arg(desc).arg(Imenu.key()));
590 LOG(VB_CHANNEL, LOG_WARNING,
LOC +
591 QString(
"'%1' not found in driver options menu.").arg(desc));
597 v4l2_std_id std_id = 0;
598 struct v4l2_standard standard {};
600 if (-1 == ioctl (
m_fd, VIDIOC_G_STD, &std_id))
605 LOG(VB_CHANNEL, LOG_WARNING,
LOC +
606 "GetVideoStandard: Failed to detect signal." +
ENO);
612 while (0 == ioctl (
m_fd, VIDIOC_ENUMSTD, &standard))
614 if (standard.id & std_id)
616 name = (
char *)standard.name;
625 if (errno == EINVAL || standard.index == 0)
627 LOG(VB_CHANNEL, LOG_WARNING,
LOC +
628 "GetVideoStandard: Failed to find signal." +
ENO);
638 struct v4l2_tuner tuner {};
640 if (ioctl(
m_fd, VIDIOC_G_TUNER, &tuner, 0) != 0)
642 LOG(VB_GENERAL, LOG_ERR,
"GetSignalStrength() : "
643 "Failed to probe signal (v4l2)" +
ENO);
647 tuner.signal /= 655.35;
649 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"GetSignalStrength() : "
657 struct v4l2_format vfmt {};
659 vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
660 if (ioctl(
m_fd, VIDIOC_G_FMT, &vfmt) != 0)
662 LOG(VB_CHANNEL, LOG_WARNING,
LOC +
663 "Failed to determine resolution: " +
ENO);
668 width = vfmt.fmt.pix.width;
669 height = vfmt.fmt.pix.height;
670 LOG(VB_CHANNEL, LOG_INFO,
LOC +
671 QString(
"Resolution: %1x%2").arg(width).arg(height));
702 struct v4l2_queryctrl qctrl {};
704 qctrl.id = V4L2_CTRL_CLASS_MPEG | V4L2_CTRL_FLAG_NEXT_CTRL;
705 return (0 == ioctl (
m_fd, VIDIOC_QUERYCTRL, &qctrl) &&
706 V4L2_CTRL_ID2CLASS (qctrl.id) == V4L2_CTRL_CLASS_MPEG);
719 struct v4l2_ext_control ctrl {};
720 struct v4l2_ext_controls ctrls {};
725 ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
726 ctrls.controls = &ctrl;
728 if (ioctl(
m_fd, VIDIOC_G_EXT_CTRLS, &ctrls) != 0)
730 LOG(VB_GENERAL, LOG_ERR,
LOC +
731 QString(
"Failed to retrieve current %1 value.")
732 .arg(ctrl_desc) +
ENO);
736 return ctrls.controls->value;
741 const QString& value_desc)
745 if (current_value < 0)
747 if (current_value == value)
749 LOG(VB_CHANNEL, LOG_INFO,
LOC +
750 QString(
"%1 value is already %2 (%3).")
751 .arg(ctrl_desc, value_desc, QString::number(value)));
755 struct v4l2_ext_control ctrl {};
756 struct v4l2_ext_controls ctrls {};
762 ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
763 ctrls.controls = &ctrl;
765 if (ioctl(
m_fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
767 LOG(VB_GENERAL, LOG_ERR,
LOC +
768 QString(
"Failed to set %1 value to %2 (%3).")
769 .arg(ctrl_desc, value_desc, QString::number(value)) +
ENO);
773 LOG(VB_CHANNEL, LOG_INFO,
LOC +
774 QString(
"%1 value set to %2 (%3).")
775 .arg(ctrl_desc, value_desc, QString::number(value)));
784 case V4L2_MPEG_STREAM_TYPE_MPEG2_PS:
785 return "MPEG-2 program stream";
786 case V4L2_MPEG_STREAM_TYPE_MPEG2_TS:
787 return "MPEG-2 transport stream";
788 case V4L2_MPEG_STREAM_TYPE_MPEG1_SS:
789 return "MPEG-1 system stream";
790 case V4L2_MPEG_STREAM_TYPE_MPEG2_DVD:
791 return "MPEG-2 DVD-compatible stream";
792 case V4L2_MPEG_STREAM_TYPE_MPEG1_VCD:
793 return "MPEG-1 VCD-compatible stream";
794 case V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD:
795 return "MPEG-2 SVCD-compatible stream";
802 int type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
807 type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
814 LOG(VB_CHANNEL, LOG_INFO,
LOC +
815 QString(
"MPEG Stream Type is currently set to %1 (%2)")
827 value = V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
840 case V4L2_MPEG_VIDEO_ASPECT_1x1:
843 case V4L2_MPEG_VIDEO_ASPECT_4x3:
846 case V4L2_MPEG_VIDEO_ASPECT_16x9:
849 case V4L2_MPEG_VIDEO_ASPECT_221x100:
857 "Video Aspect ratio", desc);
865 case V4L2_MPEG_VIDEO_BITRATE_MODE_VBR:
868 case V4L2_MPEG_VIDEO_BITRATE_MODE_CBR:
873 return SetExtControl(V4L2_CID_MPEG_VIDEO_BITRATE_MODE, value,
874 "Video Bitrate Mode", desc);
879 QString desc = QString(
"%1").arg(value);
881 "Video Average Bitrate", desc);
886 QString desc = QString(
"%1").arg(value);
887 return SetExtControl(V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, value,
888 "Video Peak Bitrate", desc);
893 struct v4l2_format vfmt {};
895 vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
897 if (ioctl(
m_fd, VIDIOC_G_FMT, &vfmt) < 0)
899 LOG(VB_GENERAL, LOG_ERR,
LOC +
900 "SetResolution() -- Error getting format" +
ENO);
904 if ((vfmt.fmt.pix.width == width) && (vfmt.fmt.pix.height == height))
906 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"Resolution is already %1x%2")
907 .arg(width).arg(height));
911 vfmt.fmt.pix.width = width;
912 vfmt.fmt.pix.height = height;
914 if (ioctl(
m_fd, VIDIOC_S_FMT, &vfmt) < 0)
916 LOG(VB_GENERAL, LOG_ERR,
LOC +
917 "SetResolution() -- Error setting format" +
ENO);
921 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"Resolution set to %1x%2")
922 .arg(width).arg(height));
929 struct v4l2_audio ain {};
932 if (ioctl(
m_fd, VIDIOC_ENUMAUDIO, &ain) < 0)
934 LOG(VB_GENERAL, LOG_WARNING,
LOC +
935 QString(
"Failed to retrieve audio input.") +
ENO);
940 if (ioctl(
m_fd, VIDIOC_S_AUDIO, &ain) < 0)
942 LOG(VB_GENERAL, LOG_WARNING,
943 LOC + QString(
"Failed to set audio input to %1.").arg(value) +
ENO);
947 LOG(VB_CHANNEL, LOG_INFO,
LOC + QString(
"Audio input set to %1.")
956 value = V4L2_MPEG_AUDIO_ENCODING_LAYER_2;
962 case V4L2_MPEG_AUDIO_ENCODING_LAYER_1:
965 case V4L2_MPEG_AUDIO_ENCODING_LAYER_2:
968 case V4L2_MPEG_AUDIO_ENCODING_LAYER_3:
971 case V4L2_MPEG_AUDIO_ENCODING_AAC:
974 case V4L2_MPEG_AUDIO_ENCODING_AC3:
985 LOG(VB_CHANNEL, LOG_INFO,
LOC +
986 QString(
"Overriding AudioCodec for %1 to %2")
992 "Audio Codec", desc);
999 struct v4l2_queryctrl qctrl {};
1000 qctrl.id = V4L2_CID_AUDIO_VOLUME;
1001 if ((ioctl(
m_fd, VIDIOC_QUERYCTRL, &qctrl) < 0) ||
1002 (qctrl.flags & V4L2_CTRL_FLAG_DISABLED))
1004 LOG(VB_CHANNEL, LOG_WARNING,
1005 LOC +
"SetRecordingVolume() -- Audio volume control not supported.");
1010 int range = qctrl.maximum - qctrl.minimum;
1011 int value = (int) ((range * volume * 0.01F) + qctrl.minimum);
1012 int ctrl_volume =
std::clamp(value, qctrl.minimum, qctrl.maximum);
1015 struct v4l2_control ctrl {};
1016 ctrl.id = V4L2_CID_AUDIO_VOLUME;
1017 ctrl.value = ctrl_volume;
1019 if (ioctl(
m_fd, VIDIOC_S_CTRL, &ctrl) < 0)
1021 LOG(VB_GENERAL, LOG_WARNING,
LOC +
1022 "SetRecordingVolume() -- Failed to set recording volume" +
ENO);
1027 LOG(VB_RECORD, LOG_INFO,
LOC +
"SetRecordingVolume() -- volume set.");
1033 struct v4l2_tuner vt {};
1035 if (ioctl(
m_fd, VIDIOC_G_TUNER, &vt) < 0)
1037 LOG(VB_CHANNEL, LOG_WARNING,
LOC +
1038 "SetLanguageMode() -- Failed to retrieve audio mode" +
ENO);
1044 if (ioctl(
m_fd, VIDIOC_S_TUNER, &vt) < 0)
1046 LOG(VB_CHANNEL, LOG_WARNING,
LOC +
1047 "SetLanguageMode -- Failed to set audio mode" +
ENO);
1054 case V4L2_TUNER_MODE_MONO:
1057 case V4L2_TUNER_MODE_STEREO:
1061 case V4L2_TUNER_MODE_LANG2:
1065 case V4L2_TUNER_MODE_SAP:
1068 case V4L2_TUNER_MODE_LANG1:
1071 case V4L2_TUNER_MODE_LANG1_LANG2:
1072 desc =
"LANG1&Lang2";
1079 LOG(VB_CHANNEL, LOG_INFO,
LOC + QString(
"Language Mode set to %1 (%2)")
1080 .arg(desc).arg(mode));
1090 value = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
1095 case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100:
1098 case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000:
1101 case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000:
1111 LOG(VB_CHANNEL, LOG_INFO,
LOC +
1112 QString(
"Overriding sampling frequence for %1 to %2")
1117 return SetExtControl(V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ, value,
1118 "Audio Sample Rate", desc);
1126 case V4L2_MPEG_AUDIO_L2_BITRATE_32K:
1129 case V4L2_MPEG_AUDIO_L2_BITRATE_48K:
1132 case V4L2_MPEG_AUDIO_L2_BITRATE_56K:
1135 case V4L2_MPEG_AUDIO_L2_BITRATE_64K:
1138 case V4L2_MPEG_AUDIO_L2_BITRATE_80K:
1141 case V4L2_MPEG_AUDIO_L2_BITRATE_96K:
1144 case V4L2_MPEG_AUDIO_L2_BITRATE_112K:
1147 case V4L2_MPEG_AUDIO_L2_BITRATE_128K:
1150 case V4L2_MPEG_AUDIO_L2_BITRATE_160K:
1153 case V4L2_MPEG_AUDIO_L2_BITRATE_192K:
1156 case V4L2_MPEG_AUDIO_L2_BITRATE_224K:
1159 case V4L2_MPEG_AUDIO_L2_BITRATE_256K:
1162 case V4L2_MPEG_AUDIO_L2_BITRATE_320K:
1165 case V4L2_MPEG_AUDIO_L2_BITRATE_384K:
1173 "Audio L2 Bitrate", desc);
1179 struct v4l2_encoder_cmd command {};
1182 if (ioctl(
m_fd, VIDIOC_ENCODER_CMD, &command) != 0 && errno != ENOTTY)
1187 LOG(VB_CHANNEL, LOG_WARNING,
LOC +
1188 QString(
"SetEncoderState(%1) -- failed").arg(desc) +
ENO);
1191 LOG(VB_CHANNEL, LOG_INFO,
LOC +
1192 QString(
"SetEncoderState(%1) -- success").arg(desc));
1223 struct v4l2_format vbifmt {};
1225 vbifmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
1227 V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
1231 if (ioctl(fd, VIDIOC_S_FMT, &vbifmt) < 0)
1233 LOG(VB_CHANNEL, LOG_WARNING,
LOC +
"ConfigureVBI() -- " +
1234 "Failed to enable VBI embedding (/dev/videoX)" +
ENO);
1238 if (ioctl(fd, VIDIOC_G_FMT, &vbifmt) >= 0)
1240 LOG(VB_RECORD, LOG_INFO,
1241 LOC + QString(
"VBI service: %1, io size: %2")
1242 .arg(vbifmt.fmt.sliced.service_set)
1243 .arg(vbifmt.fmt.sliced.io_size));
1248 V4L2_MPEG_STREAM_VBI_FMT_IVTV,
1249 "MPEG Stream VBI format",
1250 "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