28 "MPEG-2 PS",
"MPEG-2 TS",
"MPEG-1 VCD",
"PES AV",
29 "",
"PES V",
"",
"PES A",
31 "SVCD",
"DVD-Special 1",
"DVD-Special 2"
36 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448
41 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384
46 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320
49#define LOC QString("V4L2SH[%1](%2): ").arg(m_inputId).arg(m_device)
56 int audioinput,
int inputid)
60 const QString& devkey = devname;
62 QMap<QString,V4L2encStreamHandler*>::iterator it =
s_handlers.find(devkey);
71 LOG(VB_RECORD, LOG_INFO,
72 QString(
"V4L2SH[%1]: Creating new stream handler for %2")
73 .arg(inputid).arg(devname));
79 LOG(VB_RECORD, LOG_INFO,
80 QString(
"V4L2SH[%1]: Using existing stream handler for %2")
81 .arg(inputid).arg(devkey) + QString(
" (%1 in use)").arg(rcount));
97 LOG(VB_RECORD, LOG_INFO, QString(
"V4L2SH[%1]: Return '%2' in use %3")
98 .arg(inputid).arg(devname).arg(*rit));
107 QMap<QString, V4L2encStreamHandler*>::iterator it =
111 LOG(VB_RECORD, LOG_INFO, QString(
"V4L2SH[%1]: Closing handler for %2")
112 .arg(inputid).arg(devname));
118 LOG(VB_GENERAL, LOG_ERR,
119 QString(
"V4L2SH[%1]: Error: Couldn't find handler for %2")
120 .arg(inputid).arg(devname));
134 return !failed && !failing;
138 int audio_input,
int inputid)
140 , m_audioInput(audio_input)
146 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"-- Failed to open %1: ")
151 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"'%1' open").arg(
m_device));
164 LOG(VB_RECORD, LOG_INFO,
LOC +
"run() -- begin");
168 LOG(VB_GENERAL, LOG_WARNING,
LOC +
169 "Starting stream handler, but v4l2 is not open!");
172 LOG(VB_GENERAL, LOG_ERR,
LOC +
173 QString(
"run() -- Failed to open %1: ")
186 bool good_data =
false;
199 LOG(VB_RECORD, LOG_INFO,
LOC +
"Waiting for stream start.");
210 int len =
m_drb->
Read(
reinterpret_cast<unsigned char *
>(pkt_buf),
214 LOG(VB_GENERAL, LOG_ERR,
LOC +
"run() -- Device error detected");
234 LOG(VB_GENERAL, LOG_ERR,
LOC +
"run() -- Device EOF detected");
247 QMutexLocker locker(&statisticsLock);
250 for (Irec = m_rec_gaps.begin();
251 Irec != m_rec_caps.end(); ++Irec)
254 (gap_start, gap_end));
256 LOG(VB_RECORD, LOG_DEBUG,
257 LOC + QString(
"Inserted gap %1 dur %2")
258 .arg(recordingGaps.back().toString())
259 .arg(gap_start.secsTo(gap_end)));
276 LOG(VB_GENERAL, LOG_ERR,
LOC +
277 QString(
"run() -- error reading from: %1")
283 buffer.append(pkt_buf, len);
294 LOG(VB_GENERAL, LOG_ERR,
LOC +
295 QString(
"run() -- _stream_data_list is empty, %1 buffered")
296 .arg(buffer.size()));
304 remainder = sit.key()->ProcessData
305 (
reinterpret_cast<const uint8_t *
>
306 (buffer.constData()), len);
311 if (remainder > 0 && (len > remainder))
312 buffer.remove(0, len - remainder);
318 LOG(VB_GENERAL, LOG_WARNING,
LOC +
319 QString(
"_running_desired(%1) _error(%2)")
322 LOG(VB_RECORD, LOG_INFO,
LOC +
"run() -- finishing up");
330 LOG(VB_RECORD, LOG_INFO,
LOC +
"run() -- end");
336 LOG(VB_RECORD, LOG_INFO,
LOC +
"open() -- begin");
340 LOG(VB_RECORD, LOG_WARNING,
LOC +
"run() -- Already open.");
356 m_error =
"V4L version 2 required";
376 m_error =
"Failed to allocate DRB buffer";
385 m_error =
"Failed to setup DRB buffer";
391 LOG(VB_RECORD, LOG_INFO,
LOC +
"open() -- done");
399 LOG(VB_RECORD, LOG_INFO,
LOC +
"Configure() -- Already configured.");
403 LOG(VB_RECORD, LOG_INFO,
LOC +
"Configure() -- begin");
409 LOG(VB_RECORD, LOG_ERR,
LOC +
"Configure() -- failed");
422 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"Options for %1")
430 if (m_maxBitrate < 0 && m_highPeakBitrate > 0)
432 if (m_bitrate < 0 && m_highBitrate > 0)
447 LOG(VB_CHANNEL, LOG_WARNING,
"Audio input not set.");
458 LOG(VB_RECORD, LOG_INFO,
LOC +
"Configure() -- done");
466 if (m_vbi_thread !=
nullptr)
468 m_vbi_thread->wait();
470 m_vbi_thread =
nullptr;
489 LOG(VB_RECORD, LOG_INFO,
LOC +
"Closed.");
497 LOG(VB_RECORD, LOG_INFO,
LOC +
"StartEncoding() -- begin");
504 LOG(VB_GENERAL, LOG_ERR,
LOC +
"V4L2 recorder not initialized.");
513 LOG(VB_GENERAL, LOG_INFO,
LOC +
514 QString(
"Streaming mode %1. Not using it.")
519 for (
int idx = 0; idx < 10; ++idx)
536 for ( ; idx < 50; ++idx)
542 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"StartEncoding read %1 bytes").arg(len));
547 LOG(VB_GENERAL, LOG_ERR,
LOC +
548 "StartEncoding: read failing, re-opening device: " +
ENO);
550 std::this_thread::sleep_for(2ms);
554 LOG(VB_GENERAL, LOG_ERR,
LOC +
555 "StartEncoding: Can't open video device." +
ENO);
556 m_error =
"Failed to start recording";
562 LOG(VB_GENERAL, LOG_ERR,
LOC +
563 QString(
"StartEncoding: read failed, retry in %1 msec:")
564 .arg(100 * idx) +
ENO);
565 std::this_thread::sleep_for(idx * 100us);
570 LOG(VB_GENERAL, LOG_ERR,
LOC +
571 "StartEncoding: read from video device failed." +
ENO);
572 m_error =
"Failed to start recording";
579 LOG(VB_RECORD, LOG_WARNING,
LOC +
580 QString(
"%1 read attempts required to start encoding").arg(idx));
591 LOG(VB_RECORD, LOG_INFO,
LOC +
"Already encoding");
598 LOG(VB_RECORD, LOG_INFO,
LOC +
599 QString(
"StartEncoding() -- %1->%2 listeners")
602 LOG(VB_RECORD, LOG_INFO,
LOC +
"StartEncoding() -- end");
613 LOG(VB_RECORD, LOG_INFO,
LOC +
"StopEncoding: already stopped.");
621 LOG(VB_RECORD, LOG_INFO,
LOC +
622 QString(
"StopEncoding() -- delayed, still have %1 listeners")
629 LOG(VB_GENERAL, LOG_ERR,
LOC +
630 "StopEncoding() -- V4L2enc recorder not started.");
645 std::this_thread::sleep_for(20ms);
651 LOG(VB_RECORD, LOG_INFO,
LOC +
652 QString(
"StopEncoding() -- %1->%2 listeners")
660 LOG(VB_RECORD, LOG_INFO,
LOC +
"RestartEncoding()");
679 if (V4L2_TUNER_MODE_LANG1_LANG2 ==
m_langMode &&
682 LOG(VB_GENERAL, LOG_WARNING,
LOC +
683 "SetLanguageMode() -- Dual audio mode incompatible "
684 "with Layer I audio. Falling back to Main Language");
691static int find_index(
const std::array<const int,14> &audio_rate,
int value)
693 for (
size_t i = 0; i < audio_rate.size(); ++i)
695 if (audio_rate[i] == value)
709 else if (opt ==
"height")
711 else if (opt ==
"mpeg2bitratemode")
714 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR;
716 else if (opt ==
"mpeg2bitrate")
720 else if (opt ==
"mpeg2maxbitrate")
724 else if (opt ==
"samplerate")
739 else if (opt ==
"mpeg2audbitratel1")
746 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Audiorate(L1): " +
747 QString(
"%1 is invalid").arg(value));
751 else if (opt ==
"mpeg2audbitratel2")
758 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Audiorate(L2): " +
759 QString(
"%1 is invalid").arg(value));
763 else if (opt ==
"mpeg2audbitratel3")
770 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Audiorate(L2): " +
771 QString(
"%1 is invalid").arg(value));
775 else if (opt ==
"mpeg2audvolume")
779 else if (opt ==
"low_mpegbitratemode")
783 else if (opt ==
"medium_mpegbitratemode")
787 else if (opt ==
"high_mpegbitratemode")
791 else if (opt.endsWith(
"avgbitrate"))
793 if (opt.startsWith(
"low"))
795 else if (opt.startsWith(
"medium"))
797 else if (opt.startsWith(
"high"))
802 else if (opt.endsWith(
"peakbitrate"))
804 if (opt.startsWith(
"low"))
806 else if (opt.startsWith(
"medium"))
808 else if (opt.startsWith(
"high"))
818 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"SetOption('%1', %2) -- success")
819 .arg(opt).arg(value));
835 if (opt ==
"vbidevice")
837 else if (opt ==
"mpeg2streamtype")
847 LOG(VB_GENERAL, LOG_ERR,
LOC +
848 QString(
"MPEG2 stream type %1 is invalid ").arg(value));
851 else if (opt ==
"mpeg2language")
854 int lang_mode = value.toInt(&ok);
857 LOG(VB_GENERAL, LOG_ERR,
LOC +
"MPEG2 language (stereo) flag " +
858 QString(
"'%1' is invalid").arg(value));
875 else if (opt ==
"mpeg2aspectratio")
877 if (value ==
"Square")
879 else if (value ==
"4:3")
881 else if (value ==
"16:9")
883 else if (value ==
"2.21:1")
888 else if (opt ==
"mpeg2audtype")
890 if (value ==
"Layer I")
892 else if (value ==
"Layer II")
894 else if (value ==
"Layer III")
898 LOG(VB_GENERAL, LOG_ERR,
LOC +
"MPEG2 audio layer: " +
899 QString(
"%1 is invalid").arg(value));
902 else if (opt ==
"audiocodec")
904 if (value.startsWith(
"V4L2:"))
916 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"SetOption('%1', '%2') -- success")
933 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"GetSignalStrength() -- "
934 "returning cached value (%1)")
944 int bitratemode,
const QString & reason)
946 if (maxbitrate == bitrate)
948 LOG(VB_RECORD, LOG_INFO,
LOC +
949 QString(
"SetBitrate() -- %1 bitrate %2 kbps CBR")
950 .arg(reason).arg(bitrate));
954 LOG(VB_RECORD, LOG_INFO,
LOC +
955 QString(
"SetBitrate() -- %1 bitrate %2/%3 kbps VBR")
956 .arg(reason).arg(bitrate).arg(maxbitrate));
960 if (bitratemode >= 0)
979 for ( ; idx < 10; ++idx)
988 std::this_thread::sleep_for(100us);
995 int pix = width * height;
1024 if (old_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
1026 LOG(VB_RECORD, LOG_INFO,
LOC +
1027 QString(
"Old bitrate %1 CBR").arg(old_avg));
1031 LOG(VB_RECORD, LOG_INFO,
LOC +
1032 QString(
"Old bitrate %1/%2 VBR").arg(old_avg).arg(old_max));
1043 LOG(VB_GENERAL, LOG_INFO,
LOC +
"ConfigureVBI() -- begin");
1046 LOG(VB_RECORD, LOG_INFO,
LOC +
"ConfigureVBI() -- end");
Buffers reads from device files.
bool IsRunning(void) const
bool Setup(const QString &streamName, int streamfd, uint readQuanta=sizeof(TSPacket), uint deviceBufferSize=0, uint deviceBufferCount=1)
void SetRequestPause(bool request)
uint Read(unsigned char *buf, uint count)
Try to Read count bytes from into buffer.
bool IsErrored(void) const
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
void setObjectName(const QString &name)
StreamDataList m_streamDataList
void PriorityEvent(int fd) override
volatile bool m_runningDesired
void SetRunning(bool running, bool using_buffering, bool using_section_reader)
bool IsRunning(void) const
QWaitCondition m_runningStateChanged
QRecursiveMutex m_listenerLock
static constexpr unsigned int kSize
bool SetOption(const QString &opt, int value)
static QMap< QString, V4L2encStreamHandler * > s_handlers
static const std::array< const int, 14 > kAudioRateL1
V4L2encStreamHandler(const QString &device, int audio_input, int inputid)
bool Status(bool &failed, bool &failing)
int m_langMode
0 is Main Lang; 1 is SAP Lang; 2 is Dual
int GetSignalStrength(void)
static void Return(V4L2encStreamHandler *&ref, int inputid)
void run(void) override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
static const std::array< const int, 14 > kAudioRateL2
QAtomicInt m_streamingCnt
~V4L2encStreamHandler(void) override
static QMap< QString, uint > s_handlers_refcnt
static QMutex s_handlers_lock
bool m_pauseEncodingAllowed
void SetBitrate(int bitrate, int maxbitrate, int bitratemode, const QString &reason)
bool SetLanguageMode(void)
Set audio language mode.
static const std::array< const std::string, 15 > kStreamTypes
static const std::array< const int, 14 > kAudioRateL3
bool SetBitrateForResolution(void)
static V4L2encStreamHandler * Get(const QString &devname, int audioinput, int inputid)
void RestartEncoding(void)
bool HasTuner(void) const
bool ResumeEncoding(void)
bool Open(const QString &dev_name, const QString &vbi_dev_name="")
bool SetVideoBitrate(int value)
bool GetResolution(int &width, int &height) const
bool IsEncoder(void) const
bool SetLanguageMode(int mode)
bool SetAudioSamplingRate(int value)
int GetOptionValue(DriverOption::category_t cat, const QString &desc)
bool SetVideoAspect(int value)
bool UserAdjustableResolution(void) const
bool SetVolume(int volume)
bool HasAudioSupport(void) const
bool SetStreamType(int value)
bool HasStreaming(void) const
int GetStreamType(void) 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_)
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
def read(device=None, features=[])
static int find_index(const std::array< const int, 14 > &audio_rate, int value)