14 #include <sys/types.h>
16 #include <sys/ioctl.h>
20 #include <linux/videodev2.h>
22 #include "libmythbase/mythconfig.h"
35 #define LOC QString("MPEGRec[%1](%2): ") \
36 .arg(m_tvrec ? m_tvrec->GetInputId() : -1).arg(m_videodevice)
40 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448
45 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384
50 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320
55 "MPEG-2 PS",
"MPEG-2 TS",
"MPEG-1 VCD",
"PES AV",
56 "",
"PES V",
"",
"PES A",
58 "SVCD",
"DVD-Special 1",
"DVD-Special 2"
63 "Square",
"4:3",
"16:9",
"2.21:1"
92 static int find_index(
const std::array<const int,14> &audio_rate,
int value)
94 for (
uint i = 0; i < audio_rate.size(); i++)
96 if (audio_rate[i] == value)
107 else if (opt ==
"height")
109 else if (opt ==
"mpeg2bitrate")
111 else if (opt ==
"mpeg2maxbitrate")
113 else if (opt ==
"samplerate")
115 else if (opt ==
"mpeg2audbitratel1")
122 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Audiorate(L1): " +
123 QString(
"%1 is invalid").arg(value));
126 else if (opt ==
"mpeg2audbitratel2")
133 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Audiorate(L2): " +
134 QString(
"%1 is invalid").arg(value));
137 else if (opt ==
"mpeg2audbitratel3")
144 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Audiorate(L2): " +
145 QString(
"%1 is invalid").arg(value));
148 else if (opt ==
"mpeg2audvolume")
152 else if (opt.endsWith(
"_mpeg4avgbitrate"))
154 if (opt.startsWith(
"low"))
156 else if (opt.startsWith(
"medium"))
158 else if (opt.startsWith(
"high"))
163 else if (opt.endsWith(
"_mpeg4peakbitrate"))
165 if (opt.startsWith(
"low"))
167 else if (opt.startsWith(
"medium"))
169 else if (opt.startsWith(
"high"))
182 std::string value_ss = value.toStdString();
183 if (opt ==
"mpeg2streamtype")
212 LOG(VB_GENERAL, LOG_ERR,
LOC +
"MPEG2 stream type: " +
213 QString(
"%1 is invalid").arg(value));
216 else if (opt ==
"mpeg2language")
222 LOG(VB_GENERAL, LOG_ERR,
LOC +
"MPEG2 language (stereo) flag " +
223 QString(
"'%1' is invalid").arg(value));
226 else if (opt ==
"mpeg2aspectratio")
241 LOG(VB_GENERAL, LOG_ERR,
LOC +
"MPEG2 Aspect-ratio: " +
242 QString(
"%1 is invalid").arg(value));
245 else if (opt ==
"mpeg2audtype")
247 if (value ==
"Layer I")
248 m_audType = V4L2_MPEG_AUDIO_ENCODING_LAYER_1 + 1;
249 else if (value ==
"Layer II")
250 m_audType = V4L2_MPEG_AUDIO_ENCODING_LAYER_2 + 1;
251 else if (value ==
"Layer III")
252 m_audType = V4L2_MPEG_AUDIO_ENCODING_LAYER_3 + 1;
255 LOG(VB_GENERAL, LOG_ERR,
LOC +
"MPEG2 audio layer: " +
256 QString(
"%1 is invalid").arg(value));
259 else if (opt ==
"audiocodec")
261 if (value ==
"AAC Hardware Encoder")
262 m_audType = V4L2_MPEG_AUDIO_ENCODING_AAC + 1;
263 else if (value ==
"AC3 Hardware Encoder")
264 m_audType = V4L2_MPEG_AUDIO_ENCODING_AC3 + 1;
273 const QString &videodev,
274 [[maybe_unused]]
const QString &audiodev,
275 [[maybe_unused]]
const QString &vbidev)
277 if (videodev.startsWith(
"file:", Qt::CaseInsensitive))
281 QString newVideoDev = videodev;
282 if (newVideoDev.startsWith(
"file:", Qt::CaseInsensitive))
283 newVideoDev = newVideoDev.remove(0,5);
345 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Can't open MPEG File '%1'")
347 m_error =
LOC + QString(
"Can't open MPEG File '%1'")
360 m_chanfd = open(vdevice.constData(), O_RDWR);
363 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Can't open video device. " +
ENO);
370 bool supports_tuner =
false;
371 bool supports_audio =
false;
372 uint32_t capabilities = 0;
376 supports_tuner = ((capabilities & V4L2_CAP_TUNER) != 0U);
377 supports_audio = ((capabilities & V4L2_CAP_AUDIO) != 0U);
386 if (!(capabilities & V4L2_CAP_VIDEO_CAPTURE))
388 LOG(VB_GENERAL, LOG_ERR,
LOC +
"V4L version 1, unsupported");
421 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Can't open video device." +
ENO);
441 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to allocate DRB buffer");
442 m_error =
"Failed to allocate DRB buffer";
452 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to setup DRB buffer");
453 m_error =
"Failed to setup DRB buffer";
461 LOG(VB_RECORD, LOG_INFO,
LOC +
"DRB ready");
475 struct v4l2_format vfmt {};
477 vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
479 if (ioctl(chanfd, VIDIOC_G_FMT, &vfmt) < 0)
481 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Error getting format" +
ENO);
489 if (ioctl(chanfd, VIDIOC_S_FMT, &vfmt) < 0)
491 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Error setting format" +
ENO);
502 struct v4l2_tuner vt {};
503 if (ioctl(chanfd, VIDIOC_G_TUNER, &vt) < 0)
505 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Unable to get audio mode" +
ENO);
512 vt.audmode = V4L2_TUNER_MODE_LANG1;
515 vt.audmode = V4L2_TUNER_MODE_LANG2;
518 vt.audmode = V4L2_TUNER_MODE_LANG1_LANG2;
521 vt.audmode = V4L2_TUNER_MODE_LANG1;
528 LOG(VB_GENERAL, LOG_WARNING,
529 "Dual audio mode incompatible with Layer I audio."
530 "\n\t\t\tFalling back to Main Language");
531 vt.audmode = V4L2_TUNER_MODE_LANG1;
535 if (ioctl(chanfd, VIDIOC_S_TUNER, &vt) < 0)
537 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Unable to set audio mode" +
ENO);
547 struct v4l2_queryctrl qctrl {};
548 qctrl.id = V4L2_CID_AUDIO_VOLUME;
549 if ((ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl) < 0) ||
550 (qctrl.flags & V4L2_CTRL_FLAG_DISABLED))
552 LOG(VB_CHANNEL, LOG_WARNING,
553 LOC +
"Audio volume control not supported.");
558 int range = qctrl.maximum - qctrl.minimum;
559 int value = (int) ((range *
m_audVolume * 0.01F) + qctrl.minimum);
560 int ctrl_volume =
std::clamp(value, qctrl.minimum, qctrl.maximum);
563 struct v4l2_control ctrl {V4L2_CID_AUDIO_VOLUME, ctrl_volume};
565 if (ioctl(chanfd, VIDIOC_S_CTRL, &ctrl) < 0)
567 LOG(VB_GENERAL, LOG_WARNING,
LOC +
568 "Unable to set recording volume" +
ENO +
"\n\t\t\t" +
569 "If you are using an AverMedia M179 card this is normal.");
584 case 2: st = 2;
break;
587 case 14: st = 10;
break;
588 case 11: st = 11;
break;
589 case 12: st = 12;
break;
590 default: st = 0;
break;
596 LOG(VB_GENERAL, LOG_WARNING,
LOC +
597 QString(
"Stream type '%1'\n\t\t\t"
598 "is not supported by %2 driver, using '%3' instead.")
611 sr = (
m_driver ==
"ivtv") ? 48000 : sr;
615 LOG(VB_GENERAL, LOG_WARNING,
LOC +
616 QString(
"Audio sample rate %1 Hz\n\t\t\t"
617 "is not supported by %2 driver, using %3 Hz instead.")
623 case 32000:
return V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000;
624 case 44100:
return V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100;
626 default:
return V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
636 layer = (
m_driver ==
"ivtv") ? 2 : layer;
640 LOG(VB_GENERAL, LOG_WARNING,
LOC +
641 QString(
"MPEG layer %1 does not work properly\n\t\t\t"
642 "with %2 driver. Using MPEG layer %3 audio instead.")
651 if (2 == audio_layer)
653 if (3 == audio_layer)
662 case 0:
return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
663 case 1:
return V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
664 case 2:
return V4L2_MPEG_STREAM_TYPE_MPEG1_VCD;
668 return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
669 case 10:
return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD;
670 case 11:
return V4L2_MPEG_STREAM_TYPE_MPEG1_VCD;
671 case 12:
return V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD;
674 return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD;
675 default:
return V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
679 static void add_ext_ctrl(std::vector<struct v4l2_ext_control> &ctrl_list,
680 uint32_t
id, int32_t value)
682 struct v4l2_ext_control tmp_ctrl {};
684 tmp_ctrl.value = value;
685 ctrl_list.push_back(tmp_ctrl);
688 static void set_ctrls(
int fd, std::vector<struct v4l2_ext_control> &ext_ctrls)
690 static QMutex s_controlDescriptionLock;
691 static QMap<uint32_t,QString> s_controlDescription;
693 s_controlDescriptionLock.lock();
694 if (s_controlDescription.isEmpty())
696 s_controlDescription[V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ] =
697 "Audio Sampling Frequency";
698 s_controlDescription[V4L2_CID_MPEG_VIDEO_ASPECT] =
699 "Video Aspect ratio";
700 s_controlDescription[V4L2_CID_MPEG_AUDIO_ENCODING] =
702 s_controlDescription[V4L2_CID_MPEG_AUDIO_L2_BITRATE] =
704 s_controlDescription[V4L2_CID_MPEG_VIDEO_BITRATE_PEAK] =
705 "Video Peak Bitrate";
706 s_controlDescription[V4L2_CID_MPEG_VIDEO_BITRATE] =
707 "Video Average Bitrate";
708 s_controlDescription[V4L2_CID_MPEG_STREAM_TYPE] =
710 s_controlDescription[V4L2_CID_MPEG_VIDEO_BITRATE_MODE] =
713 s_controlDescriptionLock.unlock();
715 for (
auto & ext_ctrl : ext_ctrls)
717 struct v4l2_ext_controls ctrls {};
719 int value = ext_ctrl.value;
721 ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
723 ctrls.controls = &ext_ctrl;
725 if (ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
727 QMutexLocker locker(&s_controlDescriptionLock);
728 LOG(VB_GENERAL, LOG_ERR, QString(
"mpegrecorder.cpp:set_ctrls(): ") +
729 QString(
"Could not set %1 to %2")
730 .arg(s_controlDescription[ext_ctrl.id]).arg(value) +
738 std::vector<struct v4l2_ext_control> ext_ctrls;
743 if (!
m_driver.startsWith(
"saa7164"))
745 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
773 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
775 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR :
776 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
782 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
791 struct v4l2_audio ain {};
792 ain.index = audioinput;
793 if (ioctl(chanfd, VIDIOC_ENUMAUDIO, &ain) < 0)
795 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Unable to get audio input.");
799 ain.index = audioinput;
800 if (ioctl(chanfd, VIDIOC_S_AUDIO, &ain) < 0)
802 LOG(VB_GENERAL, LOG_WARNING,
803 LOC +
"Unable to set audio input.");
809 if (
m_driver ==
"hdpvr" && audioinput != 2)
811 struct v4l2_queryctrl qctrl {};
812 qctrl.id = V4L2_CID_MPEG_AUDIO_ENCODING;
814 if (!ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl))
817 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_ENCODING, audio_enc);
821 LOG(VB_GENERAL, LOG_WARNING,
LOC +
822 "Unable to get supported audio codecs." +
ENO);
837 #ifdef V4L2_CAP_SLICED_VBI_CAPTURE
847 struct v4l2_format vbifmt {};
848 vbifmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
850 V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
852 if (ioctl(fd, VIDIOC_S_FMT, &vbifmt) < 0)
857 if (ioctl(fd, VIDIOC_S_FMT, &vbifmt) < 0)
859 LOG(VB_GENERAL, LOG_WARNING,
LOC +
860 "Unable to enable VBI embedding (/dev/vbiX)" +
ENO);
866 LOG(VB_GENERAL, LOG_WARNING,
LOC +
867 "Unable to enable VBI embedding (/dev/videoX)" +
ENO);
872 if (ioctl(fd, VIDIOC_G_FMT, &vbifmt) >= 0)
874 LOG(VB_RECORD, LOG_INFO,
875 LOC + QString(
"VBI service: %1, io size: %2")
876 .arg(vbifmt.fmt.sliced.service_set)
877 .arg(vbifmt.fmt.sliced.io_size));
879 struct v4l2_ext_control vbi_ctrl {};
880 vbi_ctrl.id = V4L2_CID_MPEG_STREAM_VBI_FMT;
881 vbi_ctrl.value = V4L2_MPEG_STREAM_VBI_FMT_IVTV;
883 struct v4l2_ext_controls ctrls {};
884 ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
886 ctrls.controls = &vbi_ctrl;
888 if (ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
890 LOG(VB_GENERAL, LOG_WARNING,
LOC +
891 "Unable to set VBI embedding format" +
ENO);
899 #endif // V4L2_CAP_SLICED_VBI_CAPTURE
915 m_error =
"Failed to open V4L device";
919 bool has_select =
true;
921 #if defined(__FreeBSD__)
956 bool good_data =
false;
962 long long bytesRead = 0;
966 int dummyBPS = qEnvironmentVariableIntValue(
"DUMMYBPS", &ok) / 8;
969 LOG(VB_GENERAL, LOG_INFO,
970 LOC + QString(
"Throttling dummy recorder to %1 bits per second")
974 struct timeval tv {};
978 elapsedTimer.
start();
981 LOG(VB_RECORD, LOG_INFO,
LOC +
"Initial startup of recorder");
993 if (dummyBPS && bytesRead)
995 elapsed = (elapsedTimer.
elapsed().count() / 1000.0) + 1;
996 while ((bytesRead / elapsed) > dummyBPS)
998 std::this_thread::sleep_for(50ms);
999 elapsed = (elapsedTimer.
elapsed().count() / 1000.0) + 1;
1004 elapsed = (elapsedTimer.
elapsed().count() / 1000.0) + 1;
1007 std::this_thread::sleep_for(50ms);
1008 elapsed = (elapsedTimer.
elapsed().count() / 1000.0) + 1;
1021 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Device error detected");
1043 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Device EOF detected");
1044 m_error =
"Device EOF detected";
1057 (gap_start, gap_end));
1058 LOG(VB_RECORD, LOG_DEBUG,
1059 LOC + QString(
"Inserted gap %1 dur %2")
1061 .arg(gap_start.secsTo(gap_end)));
1088 switch (select(
m_readfd + 1, &rdset,
nullptr,
nullptr, &tv))
1094 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Select error" +
ENO);
1098 LOG(VB_GENERAL, LOG_ERR,
LOC +
"select timeout - "
1099 "driver has stopped responding");
1103 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Close error" +
ENO);
1117 if (len < 0 && !has_select)
1128 m_readfd = open(vdevice.constData(), O_RDONLY);
1138 m_error =
"Failed to read from video file";
1142 else if (len < 0 && errno != EAGAIN)
1144 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"error reading from: %1")
1158 int start_remain = len - remainder;
1159 if (remainder && (start_remain >= remainder))
1160 memcpy(buffer, buffer+start_remain, remainder);
1162 memmove(buffer, buffer+start_remain, remainder);
1171 LOG(VB_RECORD, LOG_INFO,
LOC +
"run finishing up");
1207 const uint pid = tspacket_real.
PID();
1210 if ((
m_driver ==
"hdpvr") && (pid == 0x1001))
1218 const TSPacket &tspacket = (tspacket_fake)
1219 ? *tspacket_fake : tspacket_real;
1223 delete tspacket_fake;
1230 LOG(VB_RECORD, LOG_INFO,
LOC +
"Reset(void)");
1261 LOG(VB_RECORD, LOG_INFO,
LOC +
"PauseAndWait pause");
1277 LOG(VB_RECORD, LOG_INFO,
LOC +
"PauseAndWait unpause");
1298 LOG(VB_RECORD, LOG_INFO,
LOC +
"RestartEncoding");
1324 LOG(VB_RECORD, LOG_INFO,
LOC +
"StartEncoding");
1331 LOG(VB_GENERAL, LOG_ERR,
LOC +
1332 "StartEncoding: Can't open video device." +
ENO);
1333 m_error =
"Failed to start recording";
1341 bool good_res =
true;
1354 for ( ; idx < 50; ++idx)
1362 LOG(VB_GENERAL, LOG_ERR,
LOC +
1363 "StartEncoding: read failing, re-opening device: " +
ENO);
1365 std::this_thread::sleep_for(2ms);
1370 LOG(VB_GENERAL, LOG_ERR,
LOC +
1371 "StartEncoding: Can't open video device." +
ENO);
1372 m_error =
"Failed to start recording";
1378 LOG(VB_GENERAL, LOG_ERR,
LOC +
1379 QString(
"StartEncoding: read failed, retry in %1 msec:")
1380 .arg(100 * idx) +
ENO);
1381 std::this_thread::sleep_for(idx * 100us);
1386 LOG(VB_GENERAL, LOG_ERR,
LOC +
1387 "StartEncoding: read from video device failed." +
ENO);
1388 m_error =
"Failed to start recording";
1395 LOG(VB_RECORD, LOG_WARNING,
LOC +
1396 QString(
"%1 read attempts required to start encoding").arg(idx));
1416 LOG(VB_RECORD, LOG_INFO,
LOC +
"StopEncoding");
1421 struct v4l2_encoder_cmd command {};
1422 command.cmd = V4L2_ENC_CMD_STOP;
1423 command.flags = V4L2_ENC_CMD_STOP_AT_GOP_END;
1428 bool stopped = 0 == ioctl(
m_readfd, VIDIOC_ENCODER_CMD, &command);
1431 LOG(VB_RECORD, LOG_INFO,
LOC +
"Encoding stopped");
1433 else if (errno != ENOTTY && errno != EINVAL)
1439 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"StopEncoding failed" +
ENO);
1445 std::this_thread::sleep_for(20ms);
1461 const QString & reason)
1463 if (maxbitrate == bitrate)
1465 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"%1 bitrate %2 kbps CBR")
1466 .arg(reason).arg(bitrate));
1470 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"%1 bitrate %2/%3 kbps VBR")
1471 .arg(reason).arg(bitrate).arg(maxbitrate));
1474 std::vector<struct v4l2_ext_control> ext_ctrls;
1475 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
1476 (maxbitrate == bitrate) ?
1477 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR :
1478 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
1483 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
1491 LOG(VB_RECORD, LOG_INFO,
LOC +
"Checking Resolution");
1493 struct v4l2_format vfmt {};
1494 vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1496 if (0 == ioctl(
m_chanfd, VIDIOC_G_FMT, &vfmt))
1498 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"Got Resolution %1x%2")
1499 .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height));
1500 pix = vfmt.fmt.pix.width * vfmt.fmt.pix.height;
1505 LOG(VB_RECORD, LOG_INFO,
LOC +
"Giving up detecting resolution: " +
ENO);
1516 else if (pix >= 1920*1080)
1530 if (old_max == old_avg)
1532 LOG(VB_RECORD, LOG_INFO,
LOC +
1533 QString(
"Old bitrate %1 CBR").arg(old_avg));
1537 LOG(VB_RECORD, LOG_INFO,
LOC +
1538 QString(
"Old bitrate %1/%2 VBR") .arg(old_avg).arg(old_max));
1549 LOG(VB_VBI, LOG_INFO,
LOC + QString(
"FormatCC(0x%1,0x%2)")
1550 .arg(code1,0,16).arg(code2,0,16));