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)
711 else if (opt ==
"height")
715 else if (opt ==
"mpeg2bitratemode")
718 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR;
720 else if (opt ==
"mpeg2bitrate")
724 else if (opt ==
"mpeg2maxbitrate")
728 else if (opt ==
"samplerate")
743 else if (opt ==
"mpeg2audbitratel1")
752 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Audiorate(L1): " +
753 QString(
"%1 is invalid").arg(value));
757 else if (opt ==
"mpeg2audbitratel2")
766 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Audiorate(L2): " +
767 QString(
"%1 is invalid").arg(value));
771 else if (opt ==
"mpeg2audbitratel3")
780 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Audiorate(L2): " +
781 QString(
"%1 is invalid").arg(value));
785 else if (opt ==
"mpeg2audvolume")
789 else if (opt ==
"low_mpegbitratemode")
793 else if (opt ==
"medium_mpegbitratemode")
797 else if (opt ==
"high_mpegbitratemode")
801 else if (opt.endsWith(
"avgbitrate"))
803 if (opt.startsWith(
"low"))
805 else if (opt.startsWith(
"medium"))
807 else if (opt.startsWith(
"high"))
812 else if (opt.endsWith(
"peakbitrate"))
814 if (opt.startsWith(
"low"))
816 else if (opt.startsWith(
"medium"))
818 else if (opt.startsWith(
"high"))
828 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"SetOption('%1', %2) -- success")
829 .arg(opt).arg(value));
845 if (opt ==
"vbidevice")
849 else if (opt ==
"mpeg2streamtype")
859 LOG(VB_GENERAL, LOG_ERR,
LOC +
860 QString(
"MPEG2 stream type %1 is invalid ").arg(value));
863 else if (opt ==
"mpeg2language")
866 int lang_mode = value.toInt(&ok);
869 LOG(VB_GENERAL, LOG_ERR,
LOC +
"MPEG2 language (stereo) flag " +
870 QString(
"'%1' is invalid").arg(value));
887 else if (opt ==
"mpeg2aspectratio")
889 if (value ==
"Square")
891 else if (value ==
"4:3")
893 else if (value ==
"16:9")
895 else if (value ==
"2.21:1")
900 else if (opt ==
"mpeg2audtype")
902 if (value ==
"Layer I")
906 else if (value ==
"Layer II")
910 else if (value ==
"Layer III")
916 LOG(VB_GENERAL, LOG_ERR,
LOC +
"MPEG2 audio layer: " +
917 QString(
"%1 is invalid").arg(value));
920 else if (opt ==
"audiocodec")
922 if (value.startsWith(
"V4L2:"))
934 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"SetOption('%1', '%2') -- success")
951 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"GetSignalStrength() -- "
952 "returning cached value (%1)")
962 int bitratemode,
const QString & reason)
964 if (maxbitrate == bitrate)
966 LOG(VB_RECORD, LOG_INFO,
LOC +
967 QString(
"SetBitrate() -- %1 bitrate %2 kbps CBR")
968 .arg(reason).arg(bitrate));
972 LOG(VB_RECORD, LOG_INFO,
LOC +
973 QString(
"SetBitrate() -- %1 bitrate %2/%3 kbps VBR")
974 .arg(reason).arg(bitrate).arg(maxbitrate));
978 if (bitratemode >= 0)
997 for ( ; idx < 10; ++idx)
1006 std::this_thread::sleep_for(100us);
1013 int pix = width * height;
1042 if (old_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
1044 LOG(VB_RECORD, LOG_INFO,
LOC +
1045 QString(
"Old bitrate %1 CBR").arg(old_avg));
1049 LOG(VB_RECORD, LOG_INFO,
LOC +
1050 QString(
"Old bitrate %1/%2 VBR").arg(old_avg).arg(old_max));
1061 LOG(VB_GENERAL, LOG_INFO,
LOC +
"ConfigureVBI() -- begin");
1064 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)