19#include <linux/videodev2.h>
21#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"
92static 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;
679static 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);
688static 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);
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.0F) + 1;
996 while ((bytesRead / elapsed) > dummyBPS)
998 std::this_thread::sleep_for(50ms);
999 elapsed = (elapsedTimer.
elapsed().count() / 1000.0F) + 1;
1004 elapsed = (elapsedTimer.
elapsed().count() / 1000.0F) + 1;
1007 std::this_thread::sleep_for(50ms);
1008 elapsed = (elapsedTimer.
elapsed().count() / 1000.0F) + 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));
static bool GetV4LInfo(int videofd, QString &input, QString &driver, uint32_t &version, uint32_t &capabilities)
QString m_error
non-empty iff irrecoverable recording error detected
void FinishRecording(void) override
Flushes the ringbuffer, and if this is not a live LiveTV recording saves the position map and filesiz...
std::array< uint8_t, 0x1fff+1 > m_continuityCounter
std::vector< unsigned char > m_payloadBuffer
bool IsErrored(void) override
Tells us whether an unrecoverable error has been encountered.
void ResetForNewFile(void) override
bool ProcessTSPacket(const TSPacket &tspacket) override
H2645Parser * m_h2645Parser
void HandleSingleProgramPAT(ProgramAssociationTable *pat, bool insert) override
long long GetFramesWritten(void) override
Returns number of frames written to disk.
bool m_waitForKeyframeOption
Wait for the a GOP/SEQ-start before sending data.
MPEGStreamData * m_streamData
void FindPSKeyFrames(const uint8_t *buffer, uint len) override
virtual void SetStreamData(MPEGStreamData *data)
void HandleSingleProgramPMT(ProgramMapTable *pmt, bool insert) override
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 Reset(const QString &streamName, int streamfd)
Encapsulates data about MPEG stream and emits events for each table.
void SetDesiredProgram(int p)
const ProgramMapTable * PMTSingleProgram(void) const
void AddWritingListener(TSPacketListener *val)
void AddMPEGSPListener(MPEGSingleProgramStreamListener *val)
int DesiredProgram(void) const
void RemoveWritingListener(TSPacketListener *val)
const ProgramAssociationTable * PATSingleProgram(void) const
virtual int ProcessData(const unsigned char *buffer, int len)
void RemoveAVListener(TSPacketListenerAV *val)
void AddAVListener(TSPacketListenerAV *val)
bool wait(std::chrono::milliseconds time=std::chrono::milliseconds::max())
Wait for the MThread to exit, with a maximum timeout.
QRecursiveMutex m_startStopEncodingLock
void InitStreamData(void) override
unsigned int m_mediumMpeg4PeakBitrate
static const std::array< const int, 14 > kAudRateL1
void SetOption(const QString &opt, int value) override
handles the "wait_for_seqstart" option.
void run(void) override
run() starts the recording process, and does not exit until the recording is complete.
unsigned int m_mediumMpeg4AvgBitrate
bool PauseAndWait(std::chrono::milliseconds timeout=100ms) override
If m_requestPause is true, sets pause and blocks up to timeout milliseconds or until unpaused,...
bool SetV4L2DeviceOptions(int chanfd)
static const std::array< const int, 14 > kAudRateL2
void Reset(void) override
Reset the recorder to the startup state.
void SetOptionsFromProfile(RecordingProfile *profile, const QString &videodev, const QString &audiodev, const QString &vbidev) override
Sets basic recorder options.
static const std::array< const std::string, 15 > kStreamType
bool ProcessTSPacket(const TSPacket &tspacket) override
void SetBitrate(int bitrate, int maxbitrate, const QString &reason)
void SetStrOption(RecordingProfile *profile, const QString &name)
bool SetRecordingVolume(int chanfd)
DeviceReadBuffer * m_deviceReadBuffer
void SetIntOption(RecordingProfile *profile, const QString &name)
uint GetFilteredAudioSampleRate(void) const
static const std::array< const std::string, 4 > kAspectRatio
bool RestartEncoding(void)
bool OpenMpegFileAsInput(void)
unsigned int m_lowMpeg4PeakBitrate
bool OpenV4L2DeviceAsInput(void)
bool SetLanguageMode(int chanfd)
Set audio language mode.
uint GetFilteredAudioLayer(void) const
static const std::array< const int, 14 > kAudRateL3
unsigned int m_highMpeg4PeakBitrate
bool HandleResolutionChanges(void)
unsigned int m_language
0 is Main Lang; 1 is SAP Lang; 2 is Dual
void Pause(bool clear=true) override
Pause tells recorder to pause, it should not block.
unsigned int m_lowMpeg4AvgBitrate
uint GetFilteredAudioBitRate(uint audio_layer) const
bool SetVideoCaptureFormat(int chanfd)
void FormatCC(uint code1, uint code2) override
bool SetVBIOptions(int chanfd)
uint GetFilteredStreamType(void) const
unsigned int m_highMpeg4AvgBitrate
QString GetSetting(const QString &key, const QString &defaultval="")
A QElapsedTimer based timer to replace use of QTime as a timer.
std::chrono::milliseconds elapsed(void)
Returns milliseconds elapsed since last start() or restart()
void start(void)
starts measuring elapsed time.
void ClearPositionMap(MarkTypes type) const
AVContainer m_containerFormat
virtual bool IsRecordingRequested(void)
Tells us if StopRecording() has been called.
bool m_recording
True while recording is actually being performed.
virtual void SetRecordingStatus(RecStatus::Type status, const QString &file, int line)
QWaitCondition m_pauseWait
RecordingGaps m_recordingGaps
virtual bool IsPaused(bool holding_lock=false) const
Returns true iff recorder is paused.
bool m_requestRecording
True if API call has requested a recording be [re]started.
RecordingInfo * m_curRecording
QWaitCondition m_unpauseWait
QWaitCondition m_recordingWait
virtual QString getValue(void) const
Used to access the data of a Transport Stream packet.
TSPacket * CreateClone(void) const
static constexpr unsigned int kSize
void RecorderPaused(void)
This is a callback, called by the "recorder" instance when it has actually paused.
uint GetInputId(void) const
Returns the inputid.
void CloseVBIDevice(void)
void StopRecording(void) override
StopRecording() signals to the recorder that it should stop recording and exit cleanly.
void SetOption(const QString &name, const QString &value) override
Set an specific option.
volatile bool m_requestHelper
QString m_audioDeviceName
static void add_ext_ctrl(std::vector< struct v4l2_ext_control > &ctrl_list, uint32_t id, int32_t value)
static int find_index(const std::array< const int, 14 > &audio_rate, int value)
static int streamtype_ivtv_to_v4l2(int st)
static void set_ctrls(int fd, std::vector< struct v4l2_ext_control > &ext_ctrls)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
static void clear(SettingsMap &cache, SettingsMap &overrides, const QString &myKey)
#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 eu8 clamp(eu8 value, eu8 low, eu8 high)