14 #include <sys/types.h>
16 #include <sys/ioctl.h>
20 #include <linux/videodev2.h>
22 #include "libmythbase/mythconfig.h"
36 #define LOC QString("MPEGRec[%1](%2): ") \
37 .arg(m_tvrec ? m_tvrec->GetInputId() : -1).arg(m_videodevice)
41 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448
46 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384
51 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320
56 "MPEG-2 PS",
"MPEG-2 TS",
"MPEG-1 VCD",
"PES AV",
57 "",
"PES V",
"",
"PES A",
59 "SVCD",
"DVD-Special 1",
"DVD-Special 2"
64 "Square",
"4:3",
"16:9",
"2.21:1"
93 static int find_index(
const std::array<const int,14> &audio_rate,
int value)
95 for (
uint i = 0; i < audio_rate.size(); i++)
97 if (audio_rate[i] == value)
108 else if (opt ==
"height")
110 else if (opt ==
"mpeg2bitrate")
112 else if (opt ==
"mpeg2maxbitrate")
114 else if (opt ==
"samplerate")
116 else if (opt ==
"mpeg2audbitratel1")
123 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Audiorate(L1): " +
124 QString(
"%1 is invalid").arg(value));
127 else if (opt ==
"mpeg2audbitratel2")
134 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Audiorate(L2): " +
135 QString(
"%1 is invalid").arg(value));
138 else if (opt ==
"mpeg2audbitratel3")
145 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Audiorate(L2): " +
146 QString(
"%1 is invalid").arg(value));
149 else if (opt ==
"mpeg2audvolume")
153 else if (opt.endsWith(
"_mpeg4avgbitrate"))
155 if (opt.startsWith(
"low"))
157 else if (opt.startsWith(
"medium"))
159 else if (opt.startsWith(
"high"))
164 else if (opt.endsWith(
"_mpeg4peakbitrate"))
166 if (opt.startsWith(
"low"))
168 else if (opt.startsWith(
"medium"))
170 else if (opt.startsWith(
"high"))
183 std::string value_ss = value.toStdString();
184 if (opt ==
"mpeg2streamtype")
213 LOG(VB_GENERAL, LOG_ERR,
LOC +
"MPEG2 stream type: " +
214 QString(
"%1 is invalid").arg(value));
217 else if (opt ==
"mpeg2language")
223 LOG(VB_GENERAL, LOG_ERR,
LOC +
"MPEG2 language (stereo) flag " +
224 QString(
"'%1' is invalid").arg(value));
227 else if (opt ==
"mpeg2aspectratio")
242 LOG(VB_GENERAL, LOG_ERR,
LOC +
"MPEG2 Aspect-ratio: " +
243 QString(
"%1 is invalid").arg(value));
246 else if (opt ==
"mpeg2audtype")
248 if (value ==
"Layer I")
249 m_audType = V4L2_MPEG_AUDIO_ENCODING_LAYER_1 + 1;
250 else if (value ==
"Layer II")
251 m_audType = V4L2_MPEG_AUDIO_ENCODING_LAYER_2 + 1;
252 else if (value ==
"Layer III")
253 m_audType = V4L2_MPEG_AUDIO_ENCODING_LAYER_3 + 1;
256 LOG(VB_GENERAL, LOG_ERR,
LOC +
"MPEG2 audio layer: " +
257 QString(
"%1 is invalid").arg(value));
260 else if (opt ==
"audiocodec")
262 if (value ==
"AAC Hardware Encoder")
263 m_audType = V4L2_MPEG_AUDIO_ENCODING_AAC + 1;
264 else if (value ==
"AC3 Hardware Encoder")
265 m_audType = V4L2_MPEG_AUDIO_ENCODING_AC3 + 1;
274 const QString &videodev,
275 [[maybe_unused]]
const QString &audiodev,
276 [[maybe_unused]]
const QString &vbidev)
278 if (videodev.startsWith(
"file:", Qt::CaseInsensitive))
282 QString newVideoDev = videodev;
283 if (newVideoDev.startsWith(
"file:", Qt::CaseInsensitive))
284 newVideoDev = newVideoDev.remove(0,5);
346 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Can't open MPEG File '%1'")
348 m_error =
LOC + QString(
"Can't open MPEG File '%1'")
361 m_chanfd = open(vdevice.constData(), O_RDWR);
364 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Can't open video device. " +
ENO);
371 bool supports_tuner =
false;
372 bool supports_audio =
false;
373 uint32_t capabilities = 0;
377 supports_tuner = ((capabilities & V4L2_CAP_TUNER) != 0U);
378 supports_audio = ((capabilities & V4L2_CAP_AUDIO) != 0U);
387 if (!(capabilities & V4L2_CAP_VIDEO_CAPTURE))
389 LOG(VB_GENERAL, LOG_ERR,
LOC +
"V4L version 1, unsupported");
422 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Can't open video device." +
ENO);
442 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to allocate DRB buffer");
443 m_error =
"Failed to allocate DRB buffer";
453 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to setup DRB buffer");
454 m_error =
"Failed to setup DRB buffer";
462 LOG(VB_RECORD, LOG_INFO,
LOC +
"DRB ready");
476 struct v4l2_format vfmt {};
478 vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
480 if (ioctl(chanfd, VIDIOC_G_FMT, &vfmt) < 0)
482 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Error getting format" +
ENO);
490 if (ioctl(chanfd, VIDIOC_S_FMT, &vfmt) < 0)
492 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Error setting format" +
ENO);
503 struct v4l2_tuner vt {};
504 if (ioctl(chanfd, VIDIOC_G_TUNER, &vt) < 0)
506 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Unable to get audio mode" +
ENO);
513 vt.audmode = V4L2_TUNER_MODE_LANG1;
516 vt.audmode = V4L2_TUNER_MODE_LANG2;
519 vt.audmode = V4L2_TUNER_MODE_LANG1_LANG2;
522 vt.audmode = V4L2_TUNER_MODE_LANG1;
529 LOG(VB_GENERAL, LOG_WARNING,
530 "Dual audio mode incompatible with Layer I audio."
531 "\n\t\t\tFalling back to Main Language");
532 vt.audmode = V4L2_TUNER_MODE_LANG1;
536 if (ioctl(chanfd, VIDIOC_S_TUNER, &vt) < 0)
538 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Unable to set audio mode" +
ENO);
548 struct v4l2_queryctrl qctrl {};
549 qctrl.id = V4L2_CID_AUDIO_VOLUME;
550 if ((ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl) < 0) ||
551 (qctrl.flags & V4L2_CTRL_FLAG_DISABLED))
553 LOG(VB_CHANNEL, LOG_WARNING,
554 LOC +
"Audio volume control not supported.");
559 int range = qctrl.maximum - qctrl.minimum;
560 int value = (int) ((range *
m_audVolume * 0.01F) + qctrl.minimum);
561 int ctrl_volume =
std::clamp(value, qctrl.minimum, qctrl.maximum);
564 struct v4l2_control ctrl {V4L2_CID_AUDIO_VOLUME, ctrl_volume};
566 if (ioctl(chanfd, VIDIOC_S_CTRL, &ctrl) < 0)
568 LOG(VB_GENERAL, LOG_WARNING,
LOC +
569 "Unable to set recording volume" +
ENO +
"\n\t\t\t" +
570 "If you are using an AverMedia M179 card this is normal.");
585 case 2: st = 2;
break;
588 case 14: st = 10;
break;
589 case 11: st = 11;
break;
590 case 12: st = 12;
break;
591 default: st = 0;
break;
597 LOG(VB_GENERAL, LOG_WARNING,
LOC +
598 QString(
"Stream type '%1'\n\t\t\t"
599 "is not supported by %2 driver, using '%3' instead.")
612 sr = (
m_driver ==
"ivtv") ? 48000 : sr;
616 LOG(VB_GENERAL, LOG_WARNING,
LOC +
617 QString(
"Audio sample rate %1 Hz\n\t\t\t"
618 "is not supported by %2 driver, using %3 Hz instead.")
624 case 32000:
return V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000;
625 case 44100:
return V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100;
627 default:
return V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
637 layer = (
m_driver ==
"ivtv") ? 2 : layer;
641 LOG(VB_GENERAL, LOG_WARNING,
LOC +
642 QString(
"MPEG layer %1 does not work properly\n\t\t\t"
643 "with %2 driver. Using MPEG layer %3 audio instead.")
652 if (2 == audio_layer)
654 if (3 == audio_layer)
663 case 0:
return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
664 case 1:
return V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
665 case 2:
return V4L2_MPEG_STREAM_TYPE_MPEG1_VCD;
669 return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
670 case 10:
return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD;
671 case 11:
return V4L2_MPEG_STREAM_TYPE_MPEG1_VCD;
672 case 12:
return V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD;
675 return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD;
676 default:
return V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
680 static void add_ext_ctrl(std::vector<struct v4l2_ext_control> &ctrl_list,
681 uint32_t
id, int32_t value)
683 struct v4l2_ext_control tmp_ctrl {};
685 tmp_ctrl.value = value;
686 ctrl_list.push_back(tmp_ctrl);
689 static void set_ctrls(
int fd, std::vector<struct v4l2_ext_control> &ext_ctrls)
691 static QMutex s_controlDescriptionLock;
692 static QMap<uint32_t,QString> s_controlDescription;
694 s_controlDescriptionLock.lock();
695 if (s_controlDescription.isEmpty())
697 s_controlDescription[V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ] =
698 "Audio Sampling Frequency";
699 s_controlDescription[V4L2_CID_MPEG_VIDEO_ASPECT] =
700 "Video Aspect ratio";
701 s_controlDescription[V4L2_CID_MPEG_AUDIO_ENCODING] =
703 s_controlDescription[V4L2_CID_MPEG_AUDIO_L2_BITRATE] =
705 s_controlDescription[V4L2_CID_MPEG_VIDEO_BITRATE_PEAK] =
706 "Video Peak Bitrate";
707 s_controlDescription[V4L2_CID_MPEG_VIDEO_BITRATE] =
708 "Video Average Bitrate";
709 s_controlDescription[V4L2_CID_MPEG_STREAM_TYPE] =
711 s_controlDescription[V4L2_CID_MPEG_VIDEO_BITRATE_MODE] =
714 s_controlDescriptionLock.unlock();
716 for (
auto & ext_ctrl : ext_ctrls)
718 struct v4l2_ext_controls ctrls {};
720 int value = ext_ctrl.value;
722 ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
724 ctrls.controls = &ext_ctrl;
726 if (ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
728 QMutexLocker locker(&s_controlDescriptionLock);
729 LOG(VB_GENERAL, LOG_ERR, QString(
"mpegrecorder.cpp:set_ctrls(): ") +
730 QString(
"Could not set %1 to %2")
731 .arg(s_controlDescription[ext_ctrl.id]).arg(value) +
739 std::vector<struct v4l2_ext_control> ext_ctrls;
744 if (!
m_driver.startsWith(
"saa7164"))
746 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
774 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
776 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR :
777 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
783 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
792 struct v4l2_audio ain {};
793 ain.index = audioinput;
794 if (ioctl(chanfd, VIDIOC_ENUMAUDIO, &ain) < 0)
796 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Unable to get audio input.");
800 ain.index = audioinput;
801 if (ioctl(chanfd, VIDIOC_S_AUDIO, &ain) < 0)
803 LOG(VB_GENERAL, LOG_WARNING,
804 LOC +
"Unable to set audio input.");
810 if (
m_driver ==
"hdpvr" && audioinput != 2)
812 struct v4l2_queryctrl qctrl {};
813 qctrl.id = V4L2_CID_MPEG_AUDIO_ENCODING;
815 if (!ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl))
818 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_ENCODING, audio_enc);
822 LOG(VB_GENERAL, LOG_WARNING,
LOC +
823 "Unable to get supported audio codecs." +
ENO);
838 #ifdef V4L2_CAP_SLICED_VBI_CAPTURE
848 struct v4l2_format vbifmt {};
849 vbifmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
851 V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
853 if (ioctl(fd, VIDIOC_S_FMT, &vbifmt) < 0)
858 if (ioctl(fd, VIDIOC_S_FMT, &vbifmt) < 0)
860 LOG(VB_GENERAL, LOG_WARNING,
LOC +
861 "Unable to enable VBI embedding (/dev/vbiX)" +
ENO);
867 LOG(VB_GENERAL, LOG_WARNING,
LOC +
868 "Unable to enable VBI embedding (/dev/videoX)" +
ENO);
873 if (ioctl(fd, VIDIOC_G_FMT, &vbifmt) >= 0)
875 LOG(VB_RECORD, LOG_INFO,
876 LOC + QString(
"VBI service: %1, io size: %2")
877 .arg(vbifmt.fmt.sliced.service_set)
878 .arg(vbifmt.fmt.sliced.io_size));
880 struct v4l2_ext_control vbi_ctrl {};
881 vbi_ctrl.id = V4L2_CID_MPEG_STREAM_VBI_FMT;
882 vbi_ctrl.value = V4L2_MPEG_STREAM_VBI_FMT_IVTV;
884 struct v4l2_ext_controls ctrls {};
885 ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
887 ctrls.controls = &vbi_ctrl;
889 if (ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
891 LOG(VB_GENERAL, LOG_WARNING,
LOC +
892 "Unable to set VBI embedding format" +
ENO);
900 #endif // V4L2_CAP_SLICED_VBI_CAPTURE
916 m_error =
"Failed to open V4L device";
920 bool has_select =
true;
922 #if defined(__FreeBSD__)
957 bool good_data =
false;
963 long long bytesRead = 0;
967 int dummyBPS = qEnvironmentVariableIntValue(
"DUMMYBPS", &ok) / 8;
970 LOG(VB_GENERAL, LOG_INFO,
971 LOC + QString(
"Throttling dummy recorder to %1 bits per second")
975 struct timeval tv {};
979 elapsedTimer.
start();
982 LOG(VB_RECORD, LOG_INFO,
LOC +
"Initial startup of recorder");
994 if (dummyBPS && bytesRead)
996 elapsed = (elapsedTimer.
elapsed().count() / 1000.0) + 1;
997 while ((bytesRead / elapsed) > dummyBPS)
999 std::this_thread::sleep_for(50ms);
1000 elapsed = (elapsedTimer.
elapsed().count() / 1000.0) + 1;
1005 elapsed = (elapsedTimer.
elapsed().count() / 1000.0) + 1;
1008 std::this_thread::sleep_for(50ms);
1009 elapsed = (elapsedTimer.
elapsed().count() / 1000.0) + 1;
1022 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Device error detected");
1044 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Device EOF detected");
1045 m_error =
"Device EOF detected";
1058 (gap_start, gap_end));
1059 LOG(VB_RECORD, LOG_DEBUG,
1060 LOC + QString(
"Inserted gap %1 dur %2")
1062 .arg(gap_start.secsTo(gap_end)));
1089 switch (select(
m_readfd + 1, &rdset,
nullptr,
nullptr, &tv))
1095 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Select error" +
ENO);
1099 LOG(VB_GENERAL, LOG_ERR,
LOC +
"select timeout - "
1100 "driver has stopped responding");
1104 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Close error" +
ENO);
1118 if (len < 0 && !has_select)
1129 m_readfd = open(vdevice.constData(), O_RDONLY);
1139 m_error =
"Failed to read from video file";
1143 else if (len < 0 && errno != EAGAIN)
1145 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"error reading from: %1")
1159 int start_remain = len - remainder;
1160 if (remainder && (start_remain >= remainder))
1161 memcpy(buffer, buffer+start_remain, remainder);
1163 memmove(buffer, buffer+start_remain, remainder);
1172 LOG(VB_RECORD, LOG_INFO,
LOC +
"run finishing up");
1208 const uint pid = tspacket_real.
PID();
1211 if ((
m_driver ==
"hdpvr") && (pid == 0x1001))
1219 const TSPacket &tspacket = (tspacket_fake)
1220 ? *tspacket_fake : tspacket_real;
1224 delete tspacket_fake;
1231 LOG(VB_RECORD, LOG_INFO,
LOC +
"Reset(void)");
1262 LOG(VB_RECORD, LOG_INFO,
LOC +
"PauseAndWait pause");
1278 LOG(VB_RECORD, LOG_INFO,
LOC +
"PauseAndWait unpause");
1299 LOG(VB_RECORD, LOG_INFO,
LOC +
"RestartEncoding");
1325 LOG(VB_RECORD, LOG_INFO,
LOC +
"StartEncoding");
1332 LOG(VB_GENERAL, LOG_ERR,
LOC +
1333 "StartEncoding: Can't open video device." +
ENO);
1334 m_error =
"Failed to start recording";
1342 bool good_res =
true;
1355 for ( ; idx < 50; ++idx)
1363 LOG(VB_GENERAL, LOG_ERR,
LOC +
1364 "StartEncoding: read failing, re-opening device: " +
ENO);
1366 std::this_thread::sleep_for(2ms);
1371 LOG(VB_GENERAL, LOG_ERR,
LOC +
1372 "StartEncoding: Can't open video device." +
ENO);
1373 m_error =
"Failed to start recording";
1379 LOG(VB_GENERAL, LOG_ERR,
LOC +
1380 QString(
"StartEncoding: read failed, retry in %1 msec:")
1381 .arg(100 * idx) +
ENO);
1382 std::this_thread::sleep_for(idx * 100us);
1387 LOG(VB_GENERAL, LOG_ERR,
LOC +
1388 "StartEncoding: read from video device failed." +
ENO);
1389 m_error =
"Failed to start recording";
1396 LOG(VB_RECORD, LOG_WARNING,
LOC +
1397 QString(
"%1 read attempts required to start encoding").arg(idx));
1417 LOG(VB_RECORD, LOG_INFO,
LOC +
"StopEncoding");
1422 struct v4l2_encoder_cmd command {};
1423 command.cmd = V4L2_ENC_CMD_STOP;
1424 command.flags = V4L2_ENC_CMD_STOP_AT_GOP_END;
1429 bool stopped = 0 == ioctl(
m_readfd, VIDIOC_ENCODER_CMD, &command);
1432 LOG(VB_RECORD, LOG_INFO,
LOC +
"Encoding stopped");
1434 else if (errno != ENOTTY && errno != EINVAL)
1440 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"StopEncoding failed" +
ENO);
1446 std::this_thread::sleep_for(20ms);
1462 const QString & reason)
1464 if (maxbitrate == bitrate)
1466 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"%1 bitrate %2 kbps CBR")
1467 .arg(reason).arg(bitrate));
1471 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"%1 bitrate %2/%3 kbps VBR")
1472 .arg(reason).arg(bitrate).arg(maxbitrate));
1475 std::vector<struct v4l2_ext_control> ext_ctrls;
1476 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
1477 (maxbitrate == bitrate) ?
1478 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR :
1479 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
1484 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
1492 LOG(VB_RECORD, LOG_INFO,
LOC +
"Checking Resolution");
1494 struct v4l2_format vfmt {};
1495 vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1497 if (0 == ioctl(
m_chanfd, VIDIOC_G_FMT, &vfmt))
1499 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"Got Resolution %1x%2")
1500 .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height));
1501 pix = vfmt.fmt.pix.width * vfmt.fmt.pix.height;
1506 LOG(VB_RECORD, LOG_INFO,
LOC +
"Giving up detecting resolution: " +
ENO);
1517 else if (pix >= 1920*1080)
1531 if (old_max == old_avg)
1533 LOG(VB_RECORD, LOG_INFO,
LOC +
1534 QString(
"Old bitrate %1 CBR").arg(old_avg));
1538 LOG(VB_RECORD, LOG_INFO,
LOC +
1539 QString(
"Old bitrate %1/%2 VBR") .arg(old_avg).arg(old_max));
1550 LOG(VB_VBI, LOG_INFO,
LOC + QString(
"FormatCC(0x%1,0x%2)")
1551 .arg(code1,0,16).arg(code2,0,16));