11 #include <sys/ioctl.h>
29 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
30 #define loadRelaxed load
35 "MPEG-2 PS",
"MPEG-2 TS",
"MPEG-1 VCD",
"PES AV",
36 "",
"PES V",
"",
"PES A",
38 "SVCD",
"DVD-Special 1",
"DVD-Special 2"
43 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448
48 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384
53 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320
56 #define LOC QString("V4L2SH[%1](%2): ").arg(m_inputId).arg(m_device)
63 int audioinput,
int inputid)
67 const QString& devkey = devname;
69 QMap<QString,V4L2encStreamHandler*>::iterator it =
s_handlers.find(devkey);
78 LOG(VB_RECORD, LOG_INFO,
79 QString(
"V4L2SH[%1]: Creating new stream handler for %2")
80 .arg(inputid).arg(devname));
86 LOG(VB_RECORD, LOG_INFO,
87 QString(
"V4L2SH[%1]: Using existing stream handler for %2")
88 .arg(inputid).arg(devkey) + QString(
" (%1 in use)").arg(rcount));
104 LOG(VB_RECORD, LOG_INFO, QString(
"V4L2SH[%1]: Return '%2' in use %3")
105 .arg(inputid).arg(devname).arg(*rit));
114 QMap<QString, V4L2encStreamHandler*>::iterator it =
118 LOG(VB_RECORD, LOG_INFO, QString(
"V4L2SH[%1]: Closing handler for %2")
119 .arg(inputid).arg(devname));
125 LOG(VB_GENERAL, LOG_ERR,
126 QString(
"V4L2SH[%1]: Error: Couldn't find handler for %2")
127 .arg(inputid).arg(devname));
141 return !failed && !failing;
145 int audio_input,
int inputid)
147 , m_audioInput(audio_input)
153 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"-- Failed to open %1: ")
158 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"'%1' open").arg(
m_device));
171 LOG(VB_RECORD, LOG_INFO,
LOC +
"run() -- begin");
175 LOG(VB_GENERAL, LOG_WARNING,
LOC +
176 "Starting stream handler, but v4l2 is not open!");
179 LOG(VB_GENERAL, LOG_ERR,
LOC +
180 QString(
"run() -- Failed to open %1: ")
193 bool good_data =
false;
206 LOG(VB_RECORD, LOG_INFO,
LOC +
"Waiting for stream start.");
217 int len =
m_drb->
Read(
reinterpret_cast<unsigned char *
>(pkt_buf),
221 LOG(VB_GENERAL, LOG_ERR,
LOC +
"run() -- Device error detected");
239 LOG(VB_GENERAL, LOG_ERR,
LOC +
"run() -- Device EOF detected");
244 #if 0 // For this to work, the data needs to be propagated back up to
252 QMutexLocker locker(&statisticsLock);
255 for (Irec = m_rec_gaps.begin();
256 Irec != m_rec_caps.end(); ++Irec)
259 (gap_start, gap_end));
261 LOG(VB_RECORD, LOG_DEBUG,
262 LOC + QString(
"Inserted gap %1 dur %2")
263 .arg(recordingGaps.back().toString())
264 .arg(gap_start.secsTo(gap_end)));
281 LOG(VB_GENERAL, LOG_ERR,
LOC +
282 QString(
"run() -- error reading from: %1")
288 buffer.append(pkt_buf, len);
299 LOG(VB_GENERAL, LOG_ERR,
LOC +
300 QString(
"run() -- _stream_data_list is empty, %1 buffered")
301 .arg(buffer.size()));
309 remainder = sit.key()->ProcessData
310 (
reinterpret_cast<const uint8_t *
>
311 (buffer.constData()), len);
316 if (remainder > 0 && (len > remainder))
317 buffer.remove(0, len - remainder);
323 LOG(VB_GENERAL, LOG_WARNING,
LOC +
324 QString(
"_running_desired(%1) _error(%2)")
327 LOG(VB_RECORD, LOG_INFO,
LOC +
"run() -- finishing up");
335 LOG(VB_RECORD, LOG_INFO,
LOC +
"run() -- end");
341 LOG(VB_RECORD, LOG_INFO,
LOC +
"open() -- begin");
345 LOG(VB_RECORD, LOG_WARNING,
LOC +
"run() -- Already open.");
361 m_error =
"V4L version 2 required";
381 m_error =
"Failed to allocate DRB buffer";
390 m_error =
"Failed to setup DRB buffer";
396 LOG(VB_RECORD, LOG_INFO,
LOC +
"open() -- done");
404 LOG(VB_RECORD, LOG_INFO,
LOC +
"Configure() -- Already configured.");
408 LOG(VB_RECORD, LOG_INFO,
LOC +
"Configure() -- begin");
414 LOG(VB_RECORD, LOG_ERR,
LOC +
"Configure() -- failed");
427 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"Options for %1")
435 if (m_maxBitrate < 0 && m_highPeakBitrate > 0)
437 if (m_bitrate < 0 && m_highBitrate > 0)
452 LOG(VB_CHANNEL, LOG_WARNING,
"Audio input not set.");
463 LOG(VB_RECORD, LOG_INFO,
LOC +
"Configure() -- done");
471 if (m_vbi_thread !=
nullptr)
473 m_vbi_thread->wait();
475 m_vbi_thread =
nullptr;
494 LOG(VB_RECORD, LOG_INFO,
LOC +
"Closed.");
502 LOG(VB_RECORD, LOG_INFO,
LOC +
"StartEncoding() -- begin");
509 LOG(VB_GENERAL, LOG_ERR,
LOC +
"V4L2 recorder not initialized.");
517 LOG(VB_GENERAL, LOG_INFO,
LOC +
518 QString(
"Streaming mode %1. Not using it.")
523 for (
int idx = 0; idx < 10; ++idx)
540 for ( ; idx < 50; ++idx)
546 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"StartEncoding read %1 bytes").arg(len));
551 LOG(VB_GENERAL, LOG_ERR,
LOC +
552 "StartEncoding: read failing, re-opening device: " +
ENO);
554 std::this_thread::sleep_for(2ms);
558 LOG(VB_GENERAL, LOG_ERR,
LOC +
559 "StartEncoding: Can't open video device." +
ENO);
560 m_error =
"Failed to start recording";
566 LOG(VB_GENERAL, LOG_ERR,
LOC +
567 QString(
"StartEncoding: read failed, retry in %1 msec:")
568 .arg(100 * idx) +
ENO);
569 std::this_thread::sleep_for(idx * 100us);
574 LOG(VB_GENERAL, LOG_ERR,
LOC +
575 "StartEncoding: read from video device failed." +
ENO);
576 m_error =
"Failed to start recording";
583 LOG(VB_RECORD, LOG_WARNING,
LOC +
584 QString(
"%1 read attempts required to start encoding").arg(idx));
594 LOG(VB_RECORD, LOG_INFO,
LOC +
"Already encoding");
600 LOG(VB_RECORD, LOG_INFO,
LOC +
601 QString(
"StartEncoding() -- %1->%2 listeners")
604 LOG(VB_RECORD, LOG_INFO,
LOC +
"StartEncoding() -- end");
615 LOG(VB_RECORD, LOG_INFO,
LOC +
"StopEncoding: already stopped.");
623 LOG(VB_RECORD, LOG_INFO,
LOC +
624 QString(
"StopEncoding() -- delayed, still have %1 listeners")
631 LOG(VB_GENERAL, LOG_ERR,
LOC +
632 "StopEncoding() -- V4L2enc recorder not started.");
647 std::this_thread::sleep_for(20ms);
653 LOG(VB_RECORD, LOG_INFO,
LOC +
654 QString(
"StopEncoding() -- %1->%2 listeners")
662 LOG(VB_RECORD, LOG_INFO,
LOC +
"RestartEncoding()");
681 if (V4L2_TUNER_MODE_LANG1_LANG2 ==
m_langMode &&
684 LOG(VB_GENERAL, LOG_WARNING,
LOC +
685 "SetLanguageMode() -- Dual audio mode incompatible "
686 "with Layer I audio. Falling back to Main Language");
693 static int find_index(
const std::array<const int,14> &audio_rate,
int value)
695 for (
size_t i = 0; i < audio_rate.size(); ++i)
697 if (audio_rate[i] == value)
711 else if (opt ==
"height")
713 else if (opt ==
"mpeg2bitratemode")
716 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR;
718 else if (opt ==
"mpeg2bitrate")
722 else if (opt ==
"mpeg2maxbitrate")
726 else if (opt ==
"samplerate")
741 else if (opt ==
"mpeg2audbitratel1")
748 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Audiorate(L1): " +
749 QString(
"%1 is invalid").arg(value));
753 else if (opt ==
"mpeg2audbitratel2")
760 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Audiorate(L2): " +
761 QString(
"%1 is invalid").arg(value));
765 else if (opt ==
"mpeg2audbitratel3")
772 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Audiorate(L2): " +
773 QString(
"%1 is invalid").arg(value));
777 else if (opt ==
"mpeg2audvolume")
779 else if (opt ==
"low_mpegbitratemode")
781 else if (opt ==
"medium_mpegbitratemode")
783 else if (opt ==
"high_mpegbitratemode")
785 else if (opt.endsWith(
"avgbitrate"))
787 if (opt.startsWith(
"low"))
789 else if (opt.startsWith(
"medium"))
791 else if (opt.startsWith(
"high"))
796 else if (opt.endsWith(
"peakbitrate"))
798 if (opt.startsWith(
"low"))
800 else if (opt.startsWith(
"medium"))
802 else if (opt.startsWith(
"high"))
810 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"SetOption('%1', %2) -- success")
811 .arg(opt).arg(value));
827 if (opt ==
"vbidevice")
829 else if (opt ==
"mpeg2streamtype")
839 LOG(VB_GENERAL, LOG_ERR,
LOC +
840 QString(
"MPEG2 stream type %1 is invalid ").arg(value));
843 else if (opt ==
"mpeg2language")
846 int lang_mode = value.toInt(&ok);
849 LOG(VB_GENERAL, LOG_ERR,
LOC +
"MPEG2 language (stereo) flag " +
850 QString(
"'%1' is invalid").arg(value));
867 else if (opt ==
"mpeg2aspectratio")
869 if (value ==
"Square")
871 else if (value ==
"4:3")
873 else if (value ==
"16:9")
875 else if (value ==
"2.21:1")
880 else if (opt ==
"mpeg2audtype")
882 if (value ==
"Layer I")
884 else if (value ==
"Layer II")
886 else if (value ==
"Layer III")
890 LOG(VB_GENERAL, LOG_ERR,
LOC +
"MPEG2 audio layer: " +
891 QString(
"%1 is invalid").arg(value));
894 else if (opt ==
"audiocodec")
896 if (value.startsWith(
"V4L2:"))
906 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"SetOption('%1', '%2') -- success")
907 .arg(opt).arg(value));
923 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"GetSignalStrength() -- "
924 "returning cached value (%1)")
934 int bitratemode,
const QString & reason)
936 if (maxbitrate == bitrate)
938 LOG(VB_RECORD, LOG_INFO,
LOC +
939 QString(
"SetBitrate() -- %1 bitrate %2 kbps CBR")
940 .arg(reason).arg(bitrate));
944 LOG(VB_RECORD, LOG_INFO,
LOC +
945 QString(
"SetBitrate() -- %1 bitrate %2/%3 kbps VBR")
946 .arg(reason).arg(bitrate).arg(maxbitrate));
950 if (bitratemode >= 0)
969 for ( ; idx < 10; ++idx)
978 std::this_thread::sleep_for(100us);
985 int pix = width * height;
1014 if (old_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
1016 LOG(VB_RECORD, LOG_INFO,
LOC +
1017 QString(
"Old bitrate %1 CBR").arg(old_avg));
1021 LOG(VB_RECORD, LOG_INFO,
LOC +
1022 QString(
"Old bitrate %1/%2 VBR").arg(old_avg).arg(old_max));
1033 LOG(VB_GENERAL, LOG_INFO,
LOC +
"ConfigureVBI() -- begin");
1036 LOG(VB_RECORD, LOG_INFO,
LOC +
"ConfigureVBI() -- end");