MythTV  master
mpegrecorder.cpp
Go to the documentation of this file.
1 // -*- Mode: c++ -*-
2 
3 // C++ headers
4 #include <algorithm>
5 #include <chrono> // for milliseconds
6 #include <cinttypes>
7 #include <ctime>
8 #include <fcntl.h>
9 #include <thread> // for sleep_for
10 #include <unistd.h>
11 #include <vector>
12 
13 // System headers
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <sys/ioctl.h>
17 #include <sys/time.h>
18 #include <sys/poll.h>
19 
20 #include <linux/videodev2.h>
21 
22 #include "libmythbase/mythconfig.h"
23 
24 // MythTV headers
26 #include "libmythbase/mythdate.h"
28 
29 #include "cardutil.h"
30 #include "io/mythmediabuffer.h"
31 #include "mpegrecorder.h"
32 #include "recordingprofile.h"
33 #include "tv_rec.h"
34 
35 #define LOC QString("MPEGRec[%1](%2): ") \
36  .arg(m_tvrec ? m_tvrec->GetInputId() : -1).arg(m_videodevice)
37 
38 const std::array<const int,14> MpegRecorder::kAudRateL1
39 {
40  32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448
41 };
42 
43 const std::array<const int,14> MpegRecorder::kAudRateL2
44 {
45  32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384
46 };
47 
48 const std::array<const int,14> MpegRecorder::kAudRateL3
49 {
50  32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320
51 };
52 
53 const std::array<const std::string,15> MpegRecorder::kStreamType
54 {
55  "MPEG-2 PS", "MPEG-2 TS", "MPEG-1 VCD", "PES AV",
56  "", "PES V", "", "PES A",
57  "", "", "DVD", "VCD",
58  "SVCD", "DVD-Special 1", "DVD-Special 2"
59 };
60 
61 const std::array<const std::string,4> MpegRecorder::kAspectRatio
62 {
63  "Square", "4:3", "16:9", "2.21:1"
64 };
65 
67 {
68  StopRecording();
69 
70  if (m_chanfd >= 0)
71  {
72  close(m_chanfd);
73  m_chanfd = -1;
74  }
75  if (m_readfd >= 0)
76  {
77  close(m_readfd);
78  m_readfd = -1;
79  }
80 
82  {
85 
86  delete m_deviceReadBuffer;
87  m_deviceReadBuffer = nullptr;
88  }
89 
90 }
91 
92 static int find_index(const std::array<const int,14> &audio_rate, int value)
93 {
94  for (uint i = 0; i < audio_rate.size(); i++)
95  {
96  if (audio_rate[i] == value)
97  return i;
98  }
99 
100  return -1;
101 }
102 
103 void MpegRecorder::SetOption(const QString &opt, int value)
104 {
105  if (opt == "width")
106  m_width = value;
107  else if (opt == "height")
108  m_height = value;
109  else if (opt == "mpeg2bitrate")
110  m_bitrate = value;
111  else if (opt == "mpeg2maxbitrate")
112  m_maxBitrate = value;
113  else if (opt == "samplerate")
114  m_audSampleRate = value;
115  else if (opt == "mpeg2audbitratel1")
116  {
117  int index = find_index(kAudRateL1, value);
118  if (index >= 0)
119  m_audBitrateL1 = index + 1;
120  else
121  {
122  LOG(VB_GENERAL, LOG_ERR, LOC + "Audiorate(L1): " +
123  QString("%1 is invalid").arg(value));
124  }
125  }
126  else if (opt == "mpeg2audbitratel2")
127  {
128  int index = find_index(kAudRateL2, value);
129  if (index >= 0)
130  m_audBitrateL2 = index + 1;
131  else
132  {
133  LOG(VB_GENERAL, LOG_ERR, LOC + "Audiorate(L2): " +
134  QString("%1 is invalid").arg(value));
135  }
136  }
137  else if (opt == "mpeg2audbitratel3")
138  {
139  int index = find_index(kAudRateL3, value);
140  if (index >= 0)
141  m_audBitrateL3 = index + 1;
142  else
143  {
144  LOG(VB_GENERAL, LOG_ERR, LOC + "Audiorate(L2): " +
145  QString("%1 is invalid").arg(value));
146  }
147  }
148  else if (opt == "mpeg2audvolume")
149  m_audVolume = value;
150  else if (opt.endsWith("_mpeg4avgbitrate"))
151  {
152  if (opt.startsWith("low"))
153  m_lowMpeg4AvgBitrate = value;
154  else if (opt.startsWith("medium"))
155  m_mediumMpeg4AvgBitrate = value;
156  else if (opt.startsWith("high"))
157  m_highMpeg4AvgBitrate = value;
158  else
159  V4LRecorder::SetOption(opt, value);
160  }
161  else if (opt.endsWith("_mpeg4peakbitrate"))
162  {
163  if (opt.startsWith("low"))
164  m_lowMpeg4PeakBitrate = value;
165  else if (opt.startsWith("medium"))
166  m_mediumMpeg4PeakBitrate = value;
167  else if (opt.startsWith("high"))
168  m_highMpeg4PeakBitrate = value;
169  else
170  V4LRecorder::SetOption(opt, value);
171  }
172  else
173  V4LRecorder::SetOption(opt, value);
174 }
175 
176 void MpegRecorder::SetOption(const QString &opt, const QString &value)
177 {
178  std::string value_ss = value.toStdString();
179  if (opt == "mpeg2streamtype")
180  {
181  bool found = false;
182  for (size_t i = 0; i < kStreamType.size(); i++)
183  {
184  if (kStreamType[i] == value_ss)
185  {
186  if (kStreamType[i] == "MPEG-2 TS")
187  {
189  }
190  else if (kStreamType[i] == "MPEG-2 PS")
191  {
193  }
194  else
195  {
196  // TODO Expand AVContainer to include other types in
197  // streamType
199  }
200  m_streamType = i;
201  found = true;
202  break;
203  }
204  }
205 
206  if (!found)
207  {
208  LOG(VB_GENERAL, LOG_ERR, LOC + "MPEG2 stream type: " +
209  QString("%1 is invalid").arg(value));
210  }
211  }
212  else if (opt == "mpeg2language")
213  {
214  bool ok = false;
215  m_language = value.toInt(&ok); // on failure language will be 0
216  if (!ok)
217  {
218  LOG(VB_GENERAL, LOG_ERR, LOC + "MPEG2 language (stereo) flag " +
219  QString("'%1' is invalid").arg(value));
220  }
221  }
222  else if (opt == "mpeg2aspectratio")
223  {
224  bool found = false;
225  for (size_t i = 0; i < kAspectRatio.size(); i++)
226  {
227  if (kAspectRatio[i] == value_ss)
228  {
229  m_aspectRatio = i + 1;
230  found = true;
231  break;
232  }
233  }
234 
235  if (!found)
236  {
237  LOG(VB_GENERAL, LOG_ERR, LOC + "MPEG2 Aspect-ratio: " +
238  QString("%1 is invalid").arg(value));
239  }
240  }
241  else if (opt == "mpeg2audtype")
242  {
243  if (value == "Layer I")
244  m_audType = V4L2_MPEG_AUDIO_ENCODING_LAYER_1 + 1;
245  else if (value == "Layer II")
246  m_audType = V4L2_MPEG_AUDIO_ENCODING_LAYER_2 + 1;
247  else if (value == "Layer III")
248  m_audType = V4L2_MPEG_AUDIO_ENCODING_LAYER_3 + 1;
249  else
250  {
251  LOG(VB_GENERAL, LOG_ERR, LOC + "MPEG2 audio layer: " +
252  QString("%1 is invalid").arg(value));
253  }
254  }
255  else if (opt == "audiocodec")
256  {
257  if (value == "AAC Hardware Encoder")
258  m_audType = V4L2_MPEG_AUDIO_ENCODING_AAC + 1;
259  else if (value == "AC3 Hardware Encoder")
260  m_audType = V4L2_MPEG_AUDIO_ENCODING_AC3 + 1;
261  }
262  else
263  {
264  V4LRecorder::SetOption(opt, value);
265  }
266 }
267 
269  const QString &videodev,
270  [[maybe_unused]] const QString &audiodev,
271  [[maybe_unused]] const QString &vbidev)
272 {
273  if (videodev.startsWith("file:", Qt::CaseInsensitive))
274  {
275  m_deviceIsMpegFile = true;
276  m_bufferSize = 64000;
277  QString newVideoDev = videodev;
278  if (newVideoDev.startsWith("file:", Qt::CaseInsensitive))
279  newVideoDev = newVideoDev.remove(0,5);
280  SetOption("videodevice", newVideoDev);
281  }
282  else
283  {
284  SetOption("videodevice", videodev);
285  }
286  SetOption("vbidevice", vbidev);
287  SetOption("audiodevice", audiodev);
288 
289  SetOption("tvformat", gCoreContext->GetSetting("TVFormat"));
290  SetOption("vbiformat", gCoreContext->GetSetting("VbiFormat"));
291 
292  SetIntOption(profile, "mpeg2bitrate");
293  SetIntOption(profile, "mpeg2maxbitrate");
294  SetStrOption(profile, "mpeg2streamtype");
295  SetStrOption(profile, "mpeg2aspectratio");
296  SetStrOption(profile, "mpeg2language");
297 
298  SetIntOption(profile, "samplerate");
299  SetStrOption(profile, "mpeg2audtype");
300  SetIntOption(profile, "mpeg2audbitratel1");
301  SetIntOption(profile, "mpeg2audbitratel2");
302  SetIntOption(profile, "mpeg2audbitratel3");
303  SetIntOption(profile, "mpeg2audvolume");
304 
305  SetIntOption(profile, "width");
306  SetIntOption(profile, "height");
307 
308  SetIntOption(profile, "low_mpeg4avgbitrate");
309  SetIntOption(profile, "low_mpeg4peakbitrate");
310  SetIntOption(profile, "medium_mpeg4avgbitrate");
311  SetIntOption(profile, "medium_mpeg4peakbitrate");
312  SetIntOption(profile, "high_mpeg4avgbitrate");
313  SetIntOption(profile, "high_mpeg4peakbitrate");
314 
315  SetStrOption(profile, "audiocodec");
316 }
317 
318 // same as the base class, it just doesn't complain if an option is missing
320 {
321  const StandardSetting *setting = profile->byName(name);
322  if (setting)
323  SetOption(name, setting->getValue().toInt());
324 }
325 
326 // same as the base class, it just doesn't complain if an option is missing
328 {
329  const StandardSetting *setting = profile->byName(name);
330  if (setting)
331  SetOption(name, setting->getValue());
332 }
333 
335 {
336  QByteArray vdevice = m_videodevice.toLatin1();
337  m_chanfd = m_readfd = open(vdevice.constData(), O_RDONLY);
338 
339  if (m_readfd < 0)
340  {
341  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Can't open MPEG File '%1'")
342  .arg(m_videodevice) + ENO);
343  m_error = LOC + QString("Can't open MPEG File '%1'")
344  .arg(m_videodevice) + ENO;
345  return false;
346  }
347  return true;
348 }
349 
351 {
352  // open implicitly starts encoding, so we need the lock..
353  QMutexLocker locker(&m_startStopEncodingLock);
354 
355  QByteArray vdevice = m_videodevice.toLatin1();
356  m_chanfd = open(vdevice.constData(), O_RDWR);
357  if (m_chanfd < 0)
358  {
359  LOG(VB_GENERAL, LOG_ERR, LOC + "Can't open video device. " + ENO);
360  m_error = LOC + "Can't open video device. " + ENO;
361  return false;
362  }
363 
364  m_bufferSize = 4096;
365 
366  bool supports_tuner = false;
367  bool supports_audio = false;
368  uint32_t capabilities = 0;
369  if (CardUtil::GetV4LInfo(m_chanfd, m_card, m_driver, m_version, capabilities))
370  {
371  m_supportsSlicedVbi = ((capabilities & V4L2_CAP_SLICED_VBI_CAPTURE) != 0U);
372  supports_tuner = ((capabilities & V4L2_CAP_TUNER) != 0U);
373  supports_audio = ((capabilities & V4L2_CAP_AUDIO) != 0U);
375  if (m_driver == "hdpvr")
376  {
377  m_bufferSize = 1500 * TSPacket::kSize;
378  m_useIForKeyframe = false;
379  }
380  }
381 
382  if (!(capabilities & V4L2_CAP_VIDEO_CAPTURE))
383  {
384  LOG(VB_GENERAL, LOG_ERR, LOC + "V4L version 1, unsupported");
385  m_error = LOC + "V4L version 1, unsupported";
386  close(m_chanfd);
387  m_chanfd = -1;
388  return false;
389  }
390 
392  {
393  close(m_chanfd);
394  m_chanfd = -1;
395  return false;
396  }
397 
398  if (supports_tuner)
399  SetLanguageMode(m_chanfd); // we don't care if this fails...
400 
401  if (supports_audio)
402  SetRecordingVolume(m_chanfd); // we don't care if this fails...
403 
405  {
406  close(m_chanfd);
407  m_chanfd = -1;
408  return false;
409  }
410 
411  SetVBIOptions(m_chanfd); // we don't care if this fails...
412 
413  m_readfd = open(vdevice.constData(), O_RDWR | O_NONBLOCK);
414 
415  if (m_readfd < 0)
416  {
417  LOG(VB_GENERAL, LOG_ERR, LOC + "Can't open video device." + ENO);
418  m_error = LOC + "Can't open video device." + ENO;
419  close(m_chanfd);
420  m_chanfd = -1;
421  return false;
422  }
423 
424  if (m_deviceReadBuffer)
425  {
428 
429  delete m_deviceReadBuffer;
430  m_deviceReadBuffer = nullptr;
431  }
432 
434 
435  if (!m_deviceReadBuffer)
436  {
437  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to allocate DRB buffer");
438  m_error = "Failed to allocate DRB buffer";
439  close(m_chanfd);
440  m_chanfd = -1;
441  close(m_readfd);
442  m_readfd = -1;
443  return false;
444  }
445 
446  if (!m_deviceReadBuffer->Setup(vdevice.constData(), m_readfd))
447  {
448  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to setup DRB buffer");
449  m_error = "Failed to setup DRB buffer";
450  close(m_chanfd);
451  m_chanfd = -1;
452  close(m_readfd);
453  m_readfd = -1;
454  return false;
455  }
456 
457  LOG(VB_RECORD, LOG_INFO, LOC + "DRB ready");
458 
459  if (m_vbiFd >= 0)
460  m_vbiThread = new VBIThread(this);
461 
462  return true;
463 }
464 
465 
467 {
468  if (m_driver == "hdpvr")
469  return true;
470 
471  struct v4l2_format vfmt {};
472 
473  vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
474 
475  if (ioctl(chanfd, VIDIOC_G_FMT, &vfmt) < 0)
476  {
477  LOG(VB_GENERAL, LOG_ERR, LOC + "Error getting format" + ENO);
478  m_error = LOC + "Error getting format" + ENO;
479  return false;
480  }
481 
482  vfmt.fmt.pix.width = m_width;
483  vfmt.fmt.pix.height = m_height;
484 
485  if (ioctl(chanfd, VIDIOC_S_FMT, &vfmt) < 0)
486  {
487  LOG(VB_GENERAL, LOG_ERR, LOC + "Error setting format" + ENO);
488  m_error = LOC + "Error setting format" + ENO;
489  return false;
490  }
491 
492  return true;
493 }
494 
497 {
498  struct v4l2_tuner vt {};
499  if (ioctl(chanfd, VIDIOC_G_TUNER, &vt) < 0)
500  {
501  LOG(VB_GENERAL, LOG_WARNING, LOC + "Unable to get audio mode" + ENO);
502  return false;
503  }
504 
505  switch (m_language)
506  {
507  case 0:
508  vt.audmode = V4L2_TUNER_MODE_LANG1;
509  break;
510  case 1:
511  vt.audmode = V4L2_TUNER_MODE_LANG2;
512  break;
513  case 2:
514  vt.audmode = V4L2_TUNER_MODE_LANG1_LANG2;
515  break;
516  default:
517  vt.audmode = V4L2_TUNER_MODE_LANG1;
518  }
519 
520  int audio_layer = GetFilteredAudioLayer();
521  bool success = true;
522  if ((2 == m_language) && (1 == audio_layer))
523  {
524  LOG(VB_GENERAL, LOG_WARNING,
525  "Dual audio mode incompatible with Layer I audio."
526  "\n\t\t\tFalling back to Main Language");
527  vt.audmode = V4L2_TUNER_MODE_LANG1;
528  success = false;
529  }
530 
531  if (ioctl(chanfd, VIDIOC_S_TUNER, &vt) < 0)
532  {
533  LOG(VB_GENERAL, LOG_WARNING, LOC + "Unable to set audio mode" + ENO);
534  success = false;
535  }
536 
537  return success;
538 }
539 
541 {
542  // Get volume min/max values
543  struct v4l2_queryctrl qctrl {};
544  qctrl.id = V4L2_CID_AUDIO_VOLUME;
545  if ((ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl) < 0) ||
546  (qctrl.flags & V4L2_CTRL_FLAG_DISABLED))
547  {
548  LOG(VB_CHANNEL, LOG_WARNING,
549  LOC + "Audio volume control not supported.");
550  return false;
551  }
552 
553  // calculate volume in card units.
554  int range = qctrl.maximum - qctrl.minimum;
555  int value = (int) ((range * m_audVolume * 0.01F) + qctrl.minimum);
556  int ctrl_volume = std::min(qctrl.maximum, std::max(qctrl.minimum, value));
557 
558  // Set recording volume
559  struct v4l2_control ctrl {V4L2_CID_AUDIO_VOLUME, ctrl_volume};
560 
561  if (ioctl(chanfd, VIDIOC_S_CTRL, &ctrl) < 0)
562  {
563  LOG(VB_GENERAL, LOG_WARNING, LOC +
564  "Unable to set recording volume" + ENO + "\n\t\t\t" +
565  "If you are using an AverMedia M179 card this is normal.");
566  return false;
567  }
568 
569  return true;
570 }
571 
573 {
574  uint st = (uint) m_streamType;
575 
576  if (m_driver == "ivtv")
577  {
578  switch (st)
579  {
580  case 2: st = 2; break;
581  case 10:
582  case 13:
583  case 14: st = 10; break;
584  case 11: st = 11; break;
585  case 12: st = 12; break;
586  default: st = 0; break;
587  }
588  }
589 
590  if (st != (uint) m_streamType)
591  {
592  LOG(VB_GENERAL, LOG_WARNING, LOC +
593  QString("Stream type '%1'\n\t\t\t"
594  "is not supported by %2 driver, using '%3' instead.")
595  .arg(QString::fromStdString(kStreamType[m_streamType]),
596  m_driver,
597  QString::fromStdString(kStreamType[st])));
598  }
599 
600  return st;
601 }
602 
604 {
605  uint sr = (uint) m_audSampleRate;
606 
607  sr = (m_driver == "ivtv") ? 48000 : sr; // only 48kHz works properly.
608 
609  if (sr != (uint) m_audSampleRate)
610  {
611  LOG(VB_GENERAL, LOG_WARNING, LOC +
612  QString("Audio sample rate %1 Hz\n\t\t\t"
613  "is not supported by %2 driver, using %3 Hz instead.")
614  .arg(m_audSampleRate).arg(m_driver).arg(sr));
615  }
616 
617  switch (sr)
618  {
619  case 32000: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000;
620  case 44100: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100;
621  case 48000:
622  default: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
623  }
624 }
625 
627 {
628  uint layer = (uint) m_audType;
629 
630  layer = std::max(std::min(layer, 3U), 1U);
631 
632  layer = (m_driver == "ivtv") ? 2 : layer;
633 
634  if (layer != (uint) m_audType)
635  {
636  LOG(VB_GENERAL, LOG_WARNING, LOC +
637  QString("MPEG layer %1 does not work properly\n\t\t\t"
638  "with %2 driver. Using MPEG layer %3 audio instead.")
639  .arg(m_audType).arg(m_driver).arg(layer));
640  }
641 
642  return layer;
643 }
644 
646 {
647  return ((2 == audio_layer) ? std::max(m_audBitrateL2, 10) :
648  ((3 == audio_layer) ? m_audBitrateL3 : std::max(m_audBitrateL1, 6)));
649 }
650 
651 static int streamtype_ivtv_to_v4l2(int st)
652 {
653  switch (st)
654  {
655  case 0: return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
656  case 1: return V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
657  case 2: return V4L2_MPEG_STREAM_TYPE_MPEG1_VCD;
658  case 3: /* PES A/V */
659  case 5: /* PES V */
660  case 7: /* PES A */
661  return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
662  case 10: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD;
663  case 11: return V4L2_MPEG_STREAM_TYPE_MPEG1_VCD; /* VCD */
664  case 12: return V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD;
665  case 13: /* DVD-Special 1 */
666  case 14: /* DVD-Special 2 */
667  return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD;
668  default: return V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
669  }
670 }
671 
672 static void add_ext_ctrl(std::vector<struct v4l2_ext_control> &ctrl_list,
673  uint32_t id, int32_t value)
674 {
675  struct v4l2_ext_control tmp_ctrl {};
676  tmp_ctrl.id = id;
677  tmp_ctrl.value = value;
678  ctrl_list.push_back(tmp_ctrl);
679 }
680 
681 static void set_ctrls(int fd, std::vector<struct v4l2_ext_control> &ext_ctrls)
682 {
683  static QMutex s_controlDescriptionLock;
684  static QMap<uint32_t,QString> s_controlDescription;
685 
686  s_controlDescriptionLock.lock();
687  if (s_controlDescription.isEmpty())
688  {
689  s_controlDescription[V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ] =
690  "Audio Sampling Frequency";
691  s_controlDescription[V4L2_CID_MPEG_VIDEO_ASPECT] =
692  "Video Aspect ratio";
693  s_controlDescription[V4L2_CID_MPEG_AUDIO_ENCODING] =
694  "Audio Encoding";
695  s_controlDescription[V4L2_CID_MPEG_AUDIO_L2_BITRATE] =
696  "Audio L2 Bitrate";
697  s_controlDescription[V4L2_CID_MPEG_VIDEO_BITRATE_PEAK] =
698  "Video Peak Bitrate";
699  s_controlDescription[V4L2_CID_MPEG_VIDEO_BITRATE] =
700  "Video Average Bitrate";
701  s_controlDescription[V4L2_CID_MPEG_STREAM_TYPE] =
702  "MPEG Stream type";
703  s_controlDescription[V4L2_CID_MPEG_VIDEO_BITRATE_MODE] =
704  "MPEG Bitrate mode";
705  }
706  s_controlDescriptionLock.unlock();
707 
708  for (auto & ext_ctrl : ext_ctrls)
709  {
710  struct v4l2_ext_controls ctrls {};
711 
712  int value = ext_ctrl.value;
713 
714  ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
715  ctrls.count = 1;
716  ctrls.controls = &ext_ctrl;
717 
718  if (ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
719  {
720  QMutexLocker locker(&s_controlDescriptionLock);
721  LOG(VB_GENERAL, LOG_ERR, QString("mpegrecorder.cpp:set_ctrls(): ") +
722  QString("Could not set %1 to %2")
723  .arg(s_controlDescription[ext_ctrl.id]).arg(value) +
724  ENO);
725  }
726  }
727 }
728 
730 {
731  std::vector<struct v4l2_ext_control> ext_ctrls;
732 
733  // Set controls
734  if (m_driver != "hdpvr")
735  {
736  if (!m_driver.startsWith("saa7164"))
737  {
738  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
740 
741  uint audio_layer = GetFilteredAudioLayer();
742  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_ENCODING,
743  audio_layer - 1);
744 
745  uint audbitrate = GetFilteredAudioBitRate(audio_layer);
746  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_L2_BITRATE,
747  audbitrate - 1);
748  }
749 
750  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_ASPECT,
751  m_aspectRatio - 1);
752 
753  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_STREAM_TYPE,
755 
756  }
757  else
758  {
761  }
762  m_maxBitrate = std::max(m_maxBitrate, m_bitrate);
763 
764  if (m_driver == "hdpvr" || m_driver.startsWith("saa7164"))
765  {
766  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
767  (m_maxBitrate == m_bitrate) ?
768  V4L2_MPEG_VIDEO_BITRATE_MODE_CBR :
769  V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
770  }
771 
772  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE,
773  m_bitrate * 1000);
774 
775  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
776  m_maxBitrate * 1000);
777 
778  set_ctrls(chanfd, ext_ctrls);
779 
780  bool ok = false;
781  int audioinput = m_audioDeviceName.toUInt(&ok);
782  if (ok)
783  {
784  struct v4l2_audio ain {};
785  ain.index = audioinput;
786  if (ioctl(chanfd, VIDIOC_ENUMAUDIO, &ain) < 0)
787  {
788  LOG(VB_GENERAL, LOG_WARNING, LOC + "Unable to get audio input.");
789  }
790  else
791  {
792  ain.index = audioinput;
793  if (ioctl(chanfd, VIDIOC_S_AUDIO, &ain) < 0)
794  {
795  LOG(VB_GENERAL, LOG_WARNING,
796  LOC + "Unable to set audio input.");
797  }
798  }
799  }
800 
801  // query supported audio codecs if spdif is not used
802  if (m_driver == "hdpvr" && audioinput != 2)
803  {
804  struct v4l2_queryctrl qctrl {};
805  qctrl.id = V4L2_CID_MPEG_AUDIO_ENCODING;
806 
807  if (!ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl))
808  {
809  uint audio_enc = std::max(std::min(m_audType-1, qctrl.maximum), qctrl.minimum);
810  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_ENCODING, audio_enc);
811  }
812  else
813  {
814  LOG(VB_GENERAL, LOG_WARNING, LOC +
815  "Unable to get supported audio codecs." + ENO);
816  }
817  }
818 
819  return true;
820 }
821 
823 {
824  if (VBIMode::None == m_vbiMode)
825  return true;
826 
827  if (m_driver == "hdpvr")
828  return true;
829 
830 #ifdef V4L2_CAP_SLICED_VBI_CAPTURE
832  {
833  int fd = 0;
834 
835  if (OpenVBIDevice() >= 0)
836  fd = m_vbiFd;
837  else
838  fd = chanfd;
839 
840  struct v4l2_format vbifmt {};
841  vbifmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
842  vbifmt.fmt.sliced.service_set |= (VBIMode::PAL_TT == m_vbiMode) ?
843  V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
844 
845  if (ioctl(fd, VIDIOC_S_FMT, &vbifmt) < 0)
846  {
847  if (m_vbiFd >= 0)
848  {
849  fd = chanfd; // Retry with video device instead
850  if (ioctl(fd, VIDIOC_S_FMT, &vbifmt) < 0)
851  {
852  LOG(VB_GENERAL, LOG_WARNING, LOC +
853  "Unable to enable VBI embedding (/dev/vbiX)" + ENO);
854  return false;
855  }
856  }
857  else
858  {
859  LOG(VB_GENERAL, LOG_WARNING, LOC +
860  "Unable to enable VBI embedding (/dev/videoX)" + ENO);
861  return false;
862  }
863  }
864 
865  if (ioctl(fd, VIDIOC_G_FMT, &vbifmt) >= 0)
866  {
867  LOG(VB_RECORD, LOG_INFO,
868  LOC + QString("VBI service: %1, io size: %2")
869  .arg(vbifmt.fmt.sliced.service_set)
870  .arg(vbifmt.fmt.sliced.io_size));
871 
872  struct v4l2_ext_control vbi_ctrl {};
873  vbi_ctrl.id = V4L2_CID_MPEG_STREAM_VBI_FMT;
874  vbi_ctrl.value = V4L2_MPEG_STREAM_VBI_FMT_IVTV;
875 
876  struct v4l2_ext_controls ctrls {};
877  ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
878  ctrls.count = 1;
879  ctrls.controls = &vbi_ctrl;
880 
881  if (ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
882  {
883  LOG(VB_GENERAL, LOG_WARNING, LOC +
884  "Unable to set VBI embedding format" + ENO);
885  }
886  else
887  {
888  return true;
889  }
890  }
891  }
892 #endif // V4L2_CAP_SLICED_VBI_CAPTURE
893 
894  return OpenVBIDevice() >= 0;
895 }
896 
898 {
899  ResetForNewFile();
901 }
902 
904 {
905  if (!Open())
906  {
907  if (m_error.isEmpty())
908  m_error = "Failed to open V4L device";
909  return;
910  }
911 
912  bool has_select = true;
913 
914 #if defined(__FreeBSD__)
915  // HACK. FreeBSD PVR150/500 driver doesn't currently support select()
916  has_select = false;
917 #endif
918 
919  if (m_driver == "hdpvr")
920  {
921  int progNum = 1;
922  auto *sd = new MPEGStreamData(progNum,
923  m_tvrec ? m_tvrec->GetInputId() : -1,
924  true);
925  sd->SetRecordingType(m_recordingType);
926  SetStreamData(sd);
927 
930 
931  // Make sure the first things in the file are a PAT & PMT
935  }
936 
937  {
938  QMutexLocker locker(&m_pauseLock);
939  m_requestRecording = true;
940  m_requestHelper = true;
941  m_recording = true;
942  m_recordingWait.wakeAll();
943  }
944 
945  auto *buffer = new unsigned char[m_bufferSize + 1];
946  int len = 0;
947  int remainder = 0;
948 
949  bool good_data = false;
950  bool gap = false;
951  QDateTime gap_start;
952 
953  MythTimer elapsedTimer;
954  float elapsed = NAN;
955  long long bytesRead = 0;
956 
957  bool ok { false };
958  // Bytes per second, but env var is BITS PER SECOND
959  int dummyBPS = qEnvironmentVariableIntValue("DUMMYBPS", &ok) / 8;
960  if (ok)
961  {
962  LOG(VB_GENERAL, LOG_INFO,
963  LOC + QString("Throttling dummy recorder to %1 bits per second")
964  .arg(dummyBPS * 8));
965  }
966 
967  struct timeval tv {};
968  fd_set rdset;
969 
970  if (m_deviceIsMpegFile)
971  elapsedTimer.start();
972  else if (m_deviceReadBuffer)
973  {
974  LOG(VB_RECORD, LOG_INFO, LOC + "Initial startup of recorder");
975  StartEncoding();
976  }
977 
978  QByteArray vdevice = m_videodevice.toLatin1();
979  while (IsRecordingRequested() && !IsErrored())
980  {
981  if (PauseAndWait(100ms))
982  continue;
983 
984  if (m_deviceIsMpegFile)
985  {
986  if (dummyBPS && bytesRead)
987  {
988  elapsed = (elapsedTimer.elapsed().count() / 1000.0) + 1;
989  while ((bytesRead / elapsed) > dummyBPS)
990  {
991  std::this_thread::sleep_for(50ms);
992  elapsed = (elapsedTimer.elapsed().count() / 1000.0) + 1;
993  }
994  }
995  else if (GetFramesWritten())
996  {
997  elapsed = (elapsedTimer.elapsed().count() / 1000.0) + 1;
998  while ((GetFramesWritten() / elapsed) > 30)
999  {
1000  std::this_thread::sleep_for(50ms);
1001  elapsed = (elapsedTimer.elapsed().count() / 1000.0) + 1;
1002  }
1003  }
1004  }
1005 
1006  if (m_deviceReadBuffer)
1007  {
1008  len = m_deviceReadBuffer->Read
1009  (&(buffer[remainder]), m_bufferSize - remainder);
1010 
1011  // Check for DRB errors
1013  {
1014  LOG(VB_GENERAL, LOG_ERR, LOC + "Device error detected");
1015 
1016  if (good_data)
1017  {
1018  if (gap)
1019  {
1020  /* Already processing a gap, which means
1021  * restarting the encoding didn't work! */
1022  SetRecordingStatus(RecStatus::Failing, __FILE__, __LINE__);
1023  }
1024  else
1025  gap = true;
1026  }
1027 
1028  if (!RestartEncoding())
1029  SetRecordingStatus(RecStatus::Failing, __FILE__, __LINE__);
1030  }
1031  else if (m_deviceReadBuffer->IsEOF() &&
1033  {
1034  LOG(VB_GENERAL, LOG_ERR, LOC + "Device EOF detected");
1035  m_error = "Device EOF detected";
1036  }
1037  else
1038  {
1039  // If we have seen good data, but now have a gap, note it
1040  if (good_data)
1041  {
1042  if (gap)
1043  {
1044  QMutexLocker locker(&m_statisticsLock);
1045  QDateTime gap_end(MythDate::current());
1046 
1047  m_recordingGaps.push_back(RecordingGap
1048  (gap_start, gap_end));
1049  LOG(VB_RECORD, LOG_DEBUG,
1050  LOC + QString("Inserted gap %1 dur %2")
1051  .arg(m_recordingGaps.back().toString())
1052  .arg(gap_start.secsTo(gap_end)));
1053  gap = false;
1054  }
1055  else
1056  gap_start = MythDate::current();
1057  }
1058  else
1059  good_data = true;
1060  }
1061  }
1062  else if (m_readfd < 0)
1063  continue;
1064  else
1065  {
1066  if (has_select)
1067  {
1068  tv.tv_sec = 5;
1069  tv.tv_usec = 0;
1070  FD_ZERO(&rdset); // NOLINT(readability-isolate-declaration)
1071  FD_SET(m_readfd, &rdset);
1072 
1073  switch (select(m_readfd + 1, &rdset, nullptr, nullptr, &tv))
1074  {
1075  case -1:
1076  if (errno == EINTR)
1077  continue;
1078 
1079  LOG(VB_GENERAL, LOG_ERR, LOC + "Select error" + ENO);
1080  continue;
1081 
1082  case 0:
1083  LOG(VB_GENERAL, LOG_ERR, LOC + "select timeout - "
1084  "driver has stopped responding");
1085 
1086  if (close(m_readfd) != 0)
1087  {
1088  LOG(VB_GENERAL, LOG_ERR, LOC + "Close error" + ENO);
1089  }
1090 
1091  // Force card to be reopened on next iteration..
1092  m_readfd = -1;
1093  continue;
1094 
1095  default:
1096  break;
1097  }
1098  }
1099 
1100  len = read(m_readfd, &(buffer[remainder]), m_bufferSize - remainder);
1101 
1102  if (len < 0 && !has_select)
1103  {
1104  QMutexLocker locker(&m_pauseLock);
1106  m_unpauseWait.wait(&m_pauseLock, 25);
1107  continue;
1108  }
1109 
1110  if ((len == 0) && (m_deviceIsMpegFile))
1111  {
1112  close(m_readfd);
1113  m_readfd = open(vdevice.constData(), O_RDONLY);
1114 
1115  if (m_readfd >= 0)
1116  {
1117  len = read(m_readfd,
1118  &(buffer[remainder]), m_bufferSize - remainder);
1119  }
1120 
1121  if (len <= 0)
1122  {
1123  m_error = "Failed to read from video file";
1124  continue;
1125  }
1126  }
1127  else if (len < 0 && errno != EAGAIN)
1128  {
1129  LOG(VB_GENERAL, LOG_ERR, LOC + QString("error reading from: %1")
1130  .arg(m_videodevice) + ENO);
1131  continue;
1132  }
1133  }
1134 
1135  if (len > 0)
1136  {
1137  bytesRead += len;
1138  len += remainder;
1139 
1140  if (m_driver == "hdpvr")
1141  {
1142  remainder = m_streamData->ProcessData(buffer, len);
1143  int start_remain = len - remainder;
1144  if (remainder && (start_remain >= remainder))
1145  memcpy(buffer, buffer+start_remain, remainder);
1146  else if (remainder)
1147  memmove(buffer, buffer+start_remain, remainder);
1148  }
1149  else
1150  {
1151  FindPSKeyFrames(buffer, len);
1152  }
1153  }
1154  }
1155 
1156  LOG(VB_RECORD, LOG_INFO, LOC + "run finishing up");
1157 
1158  StopEncoding();
1159 
1160  {
1161  QMutexLocker locker(&m_pauseLock);
1162  m_requestHelper = false;
1163  }
1164 
1165  if (m_vbiThread)
1166  {
1167  m_vbiThread->wait();
1168  delete m_vbiThread;
1169  m_vbiThread = nullptr;
1170  CloseVBIDevice();
1171  }
1172 
1173  FinishRecording();
1174 
1175  delete[] buffer;
1176 
1177  if (m_driver == "hdpvr")
1178  {
1181  SetStreamData(nullptr);
1182  }
1183 
1184  QMutexLocker locker(&m_pauseLock);
1185  m_requestRecording = false;
1186  m_recording = false;
1187  m_recordingWait.wakeAll();
1188 }
1189 
1190 bool MpegRecorder::ProcessTSPacket(const TSPacket &tspacket_real)
1191 {
1192  const uint pid = tspacket_real.PID();
1193 
1194  TSPacket *tspacket_fake = nullptr;
1195  if ((m_driver == "hdpvr") && (pid == 0x1001)) // PCRPID for HD-PVR
1196  {
1197  tspacket_fake = tspacket_real.CreateClone();
1198  uint cc = (m_continuityCounter[pid] == 0xFF) ?
1199  0 : (m_continuityCounter[pid] + 1) & 0xf;
1200  tspacket_fake->SetContinuityCounter(cc);
1201  }
1202 
1203  const TSPacket &tspacket = (tspacket_fake)
1204  ? *tspacket_fake : tspacket_real;
1205 
1206  bool ret = DTVRecorder::ProcessTSPacket(tspacket);
1207 
1208  delete tspacket_fake;
1209 
1210  return ret;
1211 }
1212 
1214 {
1215  LOG(VB_RECORD, LOG_INFO, LOC + "Reset(void)");
1216  ResetForNewFile();
1217 
1218  if (m_h2645Parser != nullptr)
1219  m_h2645Parser->Reset();
1220 
1221  m_startCode = 0xffffffff;
1222 
1223  if (m_curRecording)
1224  {
1226  }
1227  if (m_streamData)
1229 }
1230 
1232 {
1233  QMutexLocker locker(&m_pauseLock);
1235  m_paused = false;
1236  m_requestPause = true;
1237 }
1238 
1239 bool MpegRecorder::PauseAndWait(std::chrono::milliseconds timeout)
1240 {
1241  QMutexLocker locker(&m_pauseLock);
1242  if (m_requestPause)
1243  {
1244  if (!IsPaused(true))
1245  {
1246  LOG(VB_RECORD, LOG_INFO, LOC + "PauseAndWait pause");
1247 
1248  StopEncoding();
1249 
1250  m_paused = true;
1251  m_pauseWait.wakeAll();
1252 
1253  if (m_tvrec)
1255  }
1256 
1257  m_unpauseWait.wait(&m_pauseLock, timeout.count());
1258  }
1259 
1260  if (!m_requestPause && IsPaused(true))
1261  {
1262  LOG(VB_RECORD, LOG_INFO, LOC + "PauseAndWait unpause");
1263 
1264  if (m_driver == "hdpvr")
1265  {
1266  // HD-PVR will sometimes reset to defaults
1268  }
1269 
1270  StartEncoding();
1271 
1272  if (m_streamData)
1274 
1275  m_paused = false;
1276  }
1277 
1278  return IsPaused(true);
1279 }
1280 
1282 {
1283  LOG(VB_RECORD, LOG_INFO, LOC + "RestartEncoding");
1284 
1285  QMutexLocker locker(&m_startStopEncodingLock);
1286 
1287  StopEncoding();
1288 
1289  // Make sure the next things in the file are a PAT & PMT
1290  if (m_streamData &&
1293  {
1294  m_payloadBuffer.clear(); // No reason to keep part of a frame
1297  }
1298 
1299  if (m_driver == "hdpvr") // HD-PVR will sometimes reset to defaults
1301 
1302  return StartEncoding();
1303 }
1304 
1306 {
1307  QMutexLocker locker(&m_startStopEncodingLock);
1308 
1309  LOG(VB_RECORD, LOG_INFO, LOC + "StartEncoding");
1310 
1311  if (m_readfd < 0)
1312  {
1313  m_readfd = open(m_videodevice.toLatin1().constData(), O_RDWR | O_NONBLOCK);
1314  if (m_readfd < 0)
1315  {
1316  LOG(VB_GENERAL, LOG_ERR, LOC +
1317  "StartEncoding: Can't open video device." + ENO);
1318  m_error = "Failed to start recording";
1319  return false;
1320  }
1321  }
1322 
1323  if (m_h2645Parser != nullptr)
1324  m_h2645Parser->Reset();
1325 
1326  bool good_res = true;
1327  if (m_driver == "hdpvr")
1328  {
1329  m_waitForKeyframeOption = true;
1330  m_seenSps = false;
1331  good_res = HandleResolutionChanges();
1332  }
1333 
1334  // (at least) with the 3.10 kernel, the V4L2_ENC_CMD_START does
1335  // not reliably start the data flow from a HD-PVR. A read() seems
1336  // to work, though.
1337 
1338  int idx = 1;
1339  for ( ; idx < 50; ++idx)
1340  {
1341  uint8_t dummy = 0;
1342  int len = read(m_readfd, &dummy, 0);
1343  if (len == 0)
1344  break;
1345  if (idx == 20)
1346  {
1347  LOG(VB_GENERAL, LOG_ERR, LOC +
1348  "StartEncoding: read failing, re-opening device: " + ENO);
1349  close(m_readfd);
1350  std::this_thread::sleep_for(2ms);
1351  m_readfd = open(m_videodevice.toLatin1().constData(),
1352  O_RDWR | O_NONBLOCK);
1353  if (m_readfd < 0)
1354  {
1355  LOG(VB_GENERAL, LOG_ERR, LOC +
1356  "StartEncoding: Can't open video device." + ENO);
1357  m_error = "Failed to start recording";
1358  return false;
1359  }
1360  }
1361  else
1362  {
1363  LOG(VB_GENERAL, LOG_ERR, LOC +
1364  QString("StartEncoding: read failed, retry in %1 msec:")
1365  .arg(100 * idx) + ENO);
1366  std::this_thread::sleep_for(idx * 100us);
1367  }
1368  }
1369  if (idx == 50)
1370  {
1371  LOG(VB_GENERAL, LOG_ERR, LOC +
1372  "StartEncoding: read from video device failed." + ENO);
1373  m_error = "Failed to start recording";
1374  close(m_readfd);
1375  m_readfd = -1;
1376  return false;
1377  }
1378  if (idx > 0)
1379  {
1380  LOG(VB_RECORD, LOG_WARNING, LOC +
1381  QString("%1 read attempts required to start encoding").arg(idx));
1382  }
1383 
1384  if (!good_res) // Try again
1386 
1387  if (m_deviceReadBuffer)
1388  {
1389  m_deviceReadBuffer->Reset(m_videodevice.toLatin1().constData(), m_readfd);
1392  }
1393 
1394  return true;
1395 }
1396 
1398 {
1399  QMutexLocker locker(&m_startStopEncodingLock);
1400 
1401  LOG(VB_RECORD, LOG_INFO, LOC + "StopEncoding");
1402 
1403  if (m_readfd < 0)
1404  return;
1405 
1406  struct v4l2_encoder_cmd command {};
1407  command.cmd = V4L2_ENC_CMD_STOP;
1408  command.flags = V4L2_ENC_CMD_STOP_AT_GOP_END;
1409 
1410  if (m_deviceReadBuffer)
1412 
1413  bool stopped = 0 == ioctl(m_readfd, VIDIOC_ENCODER_CMD, &command);
1414  if (stopped)
1415  {
1416  LOG(VB_RECORD, LOG_INFO, LOC + "Encoding stopped");
1417  }
1418  else if (errno != ENOTTY && errno != EINVAL)
1419  {
1420  // Some drivers do not support this ioctl at all. It is marked as
1421  // "experimental" in the V4L2 API spec. These drivers return EINVAL
1422  // in older kernels and ENOTTY in 3.1+
1423 
1424  LOG(VB_GENERAL, LOG_WARNING, LOC + "StopEncoding failed" + ENO);
1425  }
1426 
1428  {
1429  // allow last bits of data through..
1430  std::this_thread::sleep_for(20ms);
1432  }
1433 
1434  // close the fd so streamoff/streamon work in V4LChannel
1435  close(m_readfd);
1436  m_readfd = -1;
1437 }
1438 
1440 {
1443 }
1444 
1445 void MpegRecorder::SetBitrate(int bitrate, int maxbitrate,
1446  const QString & reason)
1447 {
1448  if (maxbitrate == bitrate)
1449  {
1450  LOG(VB_RECORD, LOG_INFO, LOC + QString("%1 bitrate %2 kbps CBR")
1451  .arg(reason).arg(bitrate));
1452  }
1453  else
1454  {
1455  LOG(VB_RECORD, LOG_INFO, LOC + QString("%1 bitrate %2/%3 kbps VBR")
1456  .arg(reason).arg(bitrate).arg(maxbitrate));
1457  }
1458 
1459  std::vector<struct v4l2_ext_control> ext_ctrls;
1460  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
1461  (maxbitrate == bitrate) ?
1462  V4L2_MPEG_VIDEO_BITRATE_MODE_CBR :
1463  V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
1464 
1465  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE,
1466  bitrate * 1000);
1467 
1468  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
1469  maxbitrate * 1000);
1470 
1471  set_ctrls(m_readfd, ext_ctrls);
1472 }
1473 
1475 {
1476  LOG(VB_RECORD, LOG_INFO, LOC + "Checking Resolution");
1477  uint pix = 0;
1478  struct v4l2_format vfmt {};
1479  vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1480 
1481  if (0 == ioctl(m_chanfd, VIDIOC_G_FMT, &vfmt))
1482  {
1483  LOG(VB_RECORD, LOG_INFO, LOC + QString("Got Resolution %1x%2")
1484  .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height));
1485  pix = vfmt.fmt.pix.width * vfmt.fmt.pix.height;
1486  }
1487 
1488  if (!pix)
1489  {
1490  LOG(VB_RECORD, LOG_INFO, LOC + "Giving up detecting resolution: " + ENO);
1491  return false; // nothing to do, we don't have a resolution yet
1492  }
1493 
1494  int old_max = m_maxBitrate;
1495  int old_avg = m_bitrate;
1496  if (pix <= 768*568)
1497  {
1500  }
1501  else if (pix >= 1920*1080)
1502  {
1505  }
1506  else
1507  {
1510  }
1511  m_maxBitrate = std::max(m_maxBitrate, m_bitrate);
1512 
1513  if ((old_max != m_maxBitrate) || (old_avg != m_bitrate))
1514  {
1515  if (old_max == old_avg)
1516  {
1517  LOG(VB_RECORD, LOG_INFO, LOC +
1518  QString("Old bitrate %1 CBR").arg(old_avg));
1519  }
1520  else
1521  {
1522  LOG(VB_RECORD, LOG_INFO,LOC +
1523  QString("Old bitrate %1/%2 VBR") .arg(old_avg).arg(old_max));
1524  }
1525 
1527  }
1528 
1529  return true;
1530 }
1531 
1533 {
1534  LOG(VB_VBI, LOG_INFO, LOC + QString("FormatCC(0x%1,0x%2)")
1535  .arg(code1,0,16).arg(code2,0,16));
1536  // TODO add to CC data vector
1537 
1538  // TODO find video frames in output and insert cc_data
1539  // as CEA-708 user_data packets containing CEA-608 captions
1541 }
MpegRecorder::Pause
void Pause(bool clear=true) override
Pause tells recorder to pause, it should not block.
Definition: mpegrecorder.cpp:1231
MpegRecorder::m_clearTimeOnPause
bool m_clearTimeOnPause
Definition: mpegrecorder.h:93
DTVRecorder::FindPSKeyFrames
void FindPSKeyFrames(const uint8_t *buffer, uint len) override
Definition: dtvrecorder.cpp:1118
DTVRecorder::HandleSingleProgramPMT
void HandleSingleProgramPMT(ProgramMapTable *pmt, bool insert) override
Definition: dtvrecorder.cpp:1405
MythTimer::elapsed
std::chrono::milliseconds elapsed(void)
Returns milliseconds elapsed since last start() or restart()
Definition: mythtimer.cpp:91
O_NONBLOCK
#define O_NONBLOCK
Definition: compat.h:341
MpegRecorder::m_version
uint32_t m_version
Definition: mpegrecorder.h:86
ENO
#define ENO
This can be appended to the LOG args with "+".
Definition: mythlogging.h:73
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:102
DeviceReadBuffer::Start
void Start(void)
Definition: DeviceReadBuffer.cpp:106
LOC
#define LOC
Definition: mpegrecorder.cpp:35
formatUnknown
@ formatUnknown
Definition: recordingfile.h:14
MpegRecorder::SetLanguageMode
bool SetLanguageMode(int chanfd)
Set audio language mode.
Definition: mpegrecorder.cpp:496
DeviceReadBuffer::Setup
bool Setup(const QString &streamName, int streamfd, uint readQuanta=sizeof(TSPacket), uint deviceBufferSize=0, uint deviceBufferCount=1)
Definition: DeviceReadBuffer.cpp:49
V4LRecorder::m_vbiThread
VBIThread * m_vbiThread
Definition: v4lrecorder.h:56
MpegRecorder::Reset
void Reset(void) override
Reset the recorder to the startup state.
Definition: mpegrecorder.cpp:1213
MPEGStreamData::SetDesiredProgram
void SetDesiredProgram(int p)
Definition: mpegstreamdata.cpp:65
DTVRecorder::m_payloadBuffer
std::vector< unsigned char > m_payloadBuffer
Definition: dtvrecorder.h:166
MPEGStreamData::AddMPEGSPListener
void AddMPEGSPListener(MPEGSingleProgramStreamListener *val)
Definition: mpegstreamdata.cpp:1716
MythTimer
A QElapsedTimer based timer to replace use of QTime as a timer.
Definition: mythtimer.h:13
RecorderBase::m_statisticsLock
QMutex m_statisticsLock
Definition: recorderbase.h:375
MpegRecorder::m_deviceIsMpegFile
bool m_deviceIsMpegFile
Definition: mpegrecorder.h:80
set_ctrls
static void set_ctrls(int fd, std::vector< struct v4l2_ext_control > &ext_ctrls)
Definition: mpegrecorder.cpp:681
DTVRecorder::ResetForNewFile
void ResetForNewFile(void) override
Definition: dtvrecorder.cpp:140
MThread::wait
bool wait(std::chrono::milliseconds time=std::chrono::milliseconds::max())
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:300
discid.disc.read
def read(device=None, features=[])
Definition: disc.py:35
MpegRecorder::StartEncoding
bool StartEncoding(void)
Definition: mpegrecorder.cpp:1305
MpegRecorder::kAspectRatio
static const std::array< const std::string, 4 > kAspectRatio
Definition: mpegrecorder.h:125
V4LRecorder::m_requestHelper
volatile bool m_requestHelper
Definition: v4lrecorder.h:59
DTVRecorder::m_startCode
uint32_t m_startCode
Definition: dtvrecorder.h:135
V4LRecorder::OpenVBIDevice
int OpenVBIDevice(void)
Definition: v4lrecorder.cpp:94
MpegRecorder::SetIntOption
void SetIntOption(RecordingProfile *profile, const QString &name)
Definition: mpegrecorder.cpp:319
TSHeader::PID
unsigned int PID(void) const
Definition: tspacket.h:91
MpegRecorder::m_supportsSlicedVbi
bool m_supportsSlicedVbi
Definition: mpegrecorder.h:87
MpegRecorder::m_lowMpeg4PeakBitrate
unsigned int m_lowMpeg4PeakBitrate
Definition: mpegrecorder.h:111
cc
Definition: cc.h:9
MpegRecorder::PauseAndWait
bool PauseAndWait(std::chrono::milliseconds timeout=100ms) override
If m_requestPause is true, sets pause and blocks up to timeout milliseconds or until unpaused,...
Definition: mpegrecorder.cpp:1239
H2645Parser::Reset
virtual void Reset(void)
Definition: H2645Parser.cpp:93
MpegRecorder::GetFilteredAudioLayer
uint GetFilteredAudioLayer(void) const
Definition: mpegrecorder.cpp:626
DTVRecorder::SetStreamData
virtual void SetStreamData(MPEGStreamData *data)
Definition: dtvrecorder.cpp:218
MpegRecorder::m_deviceReadBuffer
DeviceReadBuffer * m_deviceReadBuffer
Definition: mpegrecorder.h:129
RecorderBase::m_tvrec
TVRec * m_tvrec
Definition: recorderbase.h:315
DTVRecorder::IsErrored
bool IsErrored(void) override
Tells us whether an unrecoverable error has been encountered.
Definition: dtvrecorder.h:45
DeviceReadBuffer::Read
uint Read(unsigned char *buf, uint count)
Try to Read count bytes from into buffer.
Definition: DeviceReadBuffer.cpp:616
MpegRecorder::SetOption
void SetOption(const QString &opt, int value) override
handles the "wait_for_seqstart" option.
Definition: mpegrecorder.cpp:103
TSPacket::CreateClone
TSPacket * CreateClone(void) const
Definition: tspacket.h:222
MythTimer::start
void start(void)
starts measuring elapsed time.
Definition: mythtimer.cpp:47
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
VBIMode::None
@ None
Definition: tv.h:11
V4LRecorder::VBIThread
friend class VBIThread
Definition: v4lrecorder.h:27
MpegRecorder::OpenMpegFileAsInput
bool OpenMpegFileAsInput(void)
Definition: mpegrecorder.cpp:334
MpegRecorder::m_driver
QString m_driver
Definition: mpegrecorder.h:85
DeviceReadBuffer
Buffers reads from device files.
Definition: DeviceReadBuffer.h:35
DTVRecorder::FinishRecording
void FinishRecording(void) override
Flushes the ringbuffer, and if this is not a live LiveTV recording saves the position map and filesiz...
Definition: dtvrecorder.cpp:126
MpegRecorder::m_highMpeg4PeakBitrate
unsigned int m_highMpeg4PeakBitrate
Definition: mpegrecorder.h:115
DTVRecorder::m_recordingType
QString m_recordingType
Definition: dtvrecorder.h:130
MPEGStreamData::PMTSingleProgram
const ProgramMapTable * PMTSingleProgram(void) const
Definition: mpegstreamdata.h:266
MpegRecorder::m_highMpeg4AvgBitrate
unsigned int m_highMpeg4AvgBitrate
Definition: mpegrecorder.h:114
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:14
VBIMode::PAL_TT
@ PAL_TT
Definition: tv.h:12
MpegRecorder::OpenV4L2DeviceAsInput
bool OpenV4L2DeviceAsInput(void)
Definition: mpegrecorder.cpp:350
MpegRecorder::run
void run(void) override
run() starts the recording process, and does not exit until the recording is complete.
Definition: mpegrecorder.cpp:903
RecorderBase::m_pauseLock
QMutex m_pauseLock
Definition: recorderbase.h:338
close
#define close
Definition: compat.h:43
V4LRecorder::SetOption
void SetOption(const QString &name, const QString &value) override
Set an specific option.
Definition: v4lrecorder.cpp:56
MpegRecorder::m_height
int m_height
Definition: mpegrecorder.h:97
DTVRecorder::m_continuityCounter
std::array< uint8_t, 0x1fff+1 > m_continuityCounter
Definition: dtvrecorder.h:182
TSHeader::SetContinuityCounter
void SetContinuityCounter(unsigned int cc)
Definition: tspacket.h:168
RecorderBase::m_requestPause
bool m_requestPause
Definition: recorderbase.h:339
RecorderBase::m_recordingWait
QWaitCondition m_recordingWait
Definition: recorderbase.h:347
RecorderBase::m_curRecording
RecordingInfo * m_curRecording
Definition: recorderbase.h:335
find_index
static int find_index(const std::array< const int, 14 > &audio_rate, int value)
Definition: mpegrecorder.cpp:92
TVRec::RecorderPaused
void RecorderPaused(void)
This is a callback, called by the "recorder" instance when it has actually paused.
Definition: tv_rec.cpp:2984
TVRec::GetInputId
uint GetInputId(void) const
Returns the inputid.
Definition: tv_rec.h:234
mythdate.h
MpegRecorder::SetV4L2DeviceOptions
bool SetV4L2DeviceOptions(int chanfd)
Definition: mpegrecorder.cpp:729
RecorderBase::m_paused
bool m_paused
Definition: recorderbase.h:340
MPEGStreamData::PATSingleProgram
const ProgramAssociationTable * PATSingleProgram(void) const
Definition: mpegstreamdata.h:264
DTVRecorder::HandleSingleProgramPAT
void HandleSingleProgramPAT(ProgramAssociationTable *pat, bool insert) override
Definition: dtvrecorder.cpp:1385
programinfo.h
V4LRecorder::CloseVBIDevice
void CloseVBIDevice(void)
Definition: v4lrecorder.cpp:202
hardwareprofile.scan.profile
profile
Definition: scan.py:97
CardUtil::GetV4LInfo
static bool GetV4LInfo(int videofd, QString &input, QString &driver, uint32_t &version, uint32_t &capabilities)
Definition: cardutil.cpp:2351
RecorderBase::m_recordingGaps
RecordingGaps m_recordingGaps
Definition: recorderbase.h:382
MpegRecorder::HandleResolutionChanges
bool HandleResolutionChanges(void)
Definition: mpegrecorder.cpp:1474
TSPacket
Used to access the data of a Transport Stream packet.
Definition: tspacket.h:205
MPEGStreamData::ProcessData
virtual int ProcessData(const unsigned char *buffer, int len)
Definition: mpegstreamdata.cpp:951
V4LRecorder::StopRecording
void StopRecording(void) override
StopRecording() signals to the recorder that it should stop recording and exit cleanly.
Definition: v4lrecorder.cpp:43
MpegRecorder::kStreamType
static const std::array< const std::string, 15 > kStreamType
Definition: mpegrecorder.h:124
RecStatus::Failing
@ Failing
Definition: recordingstatus.h:17
MpegRecorder::Open
bool Open(void)
Definition: mpegrecorder.cpp:897
DeviceReadBuffer::IsRunning
bool IsRunning(void) const
Definition: DeviceReadBuffer.cpp:254
MPEGStreamData
Encapsulates data about MPEG stream and emits events for each table.
Definition: mpegstreamdata.h:85
MpegRecorder::m_lowMpeg4AvgBitrate
unsigned int m_lowMpeg4AvgBitrate
Definition: mpegrecorder.h:110
MPEGStreamData::RemoveWritingListener
void RemoveWritingListener(TSPacketListener *val)
Definition: mpegstreamdata.cpp:1660
DTVRecorder::GetFramesWritten
long long GetFramesWritten(void) override
Returns number of frames written to disk.
Definition: dtvrecorder.h:48
MpegRecorder::m_bufferSize
int m_bufferSize
Definition: mpegrecorder.h:81
MpegRecorder::SetRecordingVolume
bool SetRecordingVolume(int chanfd)
Definition: mpegrecorder.cpp:540
RecorderBase::IsRecordingRequested
virtual bool IsRecordingRequested(void)
Tells us if StopRecording() has been called.
Definition: recorderbase.cpp:250
DTVRecorder::m_h2645Parser
H2645Parser * m_h2645Parser
Definition: dtvrecorder.h:151
clear
static void clear(SettingsMap &cache, SettingsMap &overrides, const QString &myKey)
Definition: mythdb.cpp:897
DTVRecorder::m_seenSps
bool m_seenSps
Definition: dtvrecorder.h:150
MpegRecorder::m_aspectRatio
int m_aspectRatio
Definition: mpegrecorder.h:101
MpegRecorder::m_language
unsigned int m_language
0 is Main Lang; 1 is SAP Lang; 2 is Dual
Definition: mpegrecorder.h:109
MpegRecorder::TeardownAll
void TeardownAll(void)
Definition: mpegrecorder.cpp:66
DeviceReadBuffer::Stop
void Stop(void)
Definition: DeviceReadBuffer.cpp:149
StandardSetting::getValue
virtual QString getValue(void) const
Definition: standardsettings.h:52
MpegRecorder::m_audBitrateL3
int m_audBitrateL3
Definition: mpegrecorder.h:106
DTVRecorder::ProcessTSPacket
bool ProcessTSPacket(const TSPacket &tspacket) override
Definition: dtvrecorder.cpp:1543
MpegRecorder::m_audVolume
int m_audVolume
Definition: mpegrecorder.h:107
uint
unsigned int uint
Definition: compat.h:81
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
RecorderBase::m_containerFormat
AVContainer m_containerFormat
Definition: recorderbase.h:319
MpegRecorder::SetVideoCaptureFormat
bool SetVideoCaptureFormat(int chanfd)
Definition: mpegrecorder.cpp:466
MpegRecorder::kAudRateL3
static const std::array< const int, 14 > kAudRateL3
Definition: mpegrecorder.h:123
MpegRecorder::GetFilteredStreamType
uint GetFilteredStreamType(void) const
Definition: mpegrecorder.cpp:572
MpegRecorder::GetFilteredAudioSampleRate
uint GetFilteredAudioSampleRate(void) const
Definition: mpegrecorder.cpp:603
mythmediabuffer.h
RecorderBase::m_videodevice
QString m_videodevice
Definition: recorderbase.h:323
MpegRecorder::m_card
QString m_card
Definition: mpegrecorder.h:84
MpegRecorder::m_audBitrateL2
int m_audBitrateL2
Definition: mpegrecorder.h:105
MpegRecorder::SetOptionsFromProfile
void SetOptionsFromProfile(RecordingProfile *profile, const QString &videodev, const QString &audiodev, const QString &vbidev) override
Sets basic recorder options.
Definition: mpegrecorder.cpp:268
MpegRecorder::FormatCC
void FormatCC(uint code1, uint code2) override
Definition: mpegrecorder.cpp:1532
RecorderBase::m_pauseWait
QWaitCondition m_pauseWait
Definition: recorderbase.h:341
MPEGStreamData::AddAVListener
void AddAVListener(TSPacketListenerAV *val)
Definition: mpegstreamdata.cpp:1674
MpegRecorder::InitStreamData
void InitStreamData(void) override
Definition: mpegrecorder.cpp:1439
MpegRecorder::m_mediumMpeg4AvgBitrate
unsigned int m_mediumMpeg4AvgBitrate
Definition: mpegrecorder.h:112
MpegRecorder::m_width
int m_width
Definition: mpegrecorder.h:96
DTVRecorder::m_waitForKeyframeOption
bool m_waitForKeyframeOption
Wait for the a GOP/SEQ-start before sending data.
Definition: dtvrecorder.h:154
MpegRecorder::StopEncoding
void StopEncoding(void)
Definition: mpegrecorder.cpp:1397
V4LRecorder::m_vbiMode
int m_vbiMode
Definition: v4lrecorder.h:49
MpegRecorder::m_maxBitrate
int m_maxBitrate
Definition: mpegrecorder.h:99
MpegRecorder::SetBitrate
void SetBitrate(int bitrate, int maxbitrate, const QString &reason)
Definition: mpegrecorder.cpp:1445
RecordingGap
Definition: recordingquality.h:14
MpegRecorder::GetFilteredAudioBitRate
uint GetFilteredAudioBitRate(uint audio_layer) const
Definition: mpegrecorder.cpp:645
RecorderBase::SetRecordingStatus
virtual void SetRecordingStatus(RecStatus::Type status, const QString &file, int line)
Definition: recorderbase.cpp:395
DTVRecorder::m_streamData
MPEGStreamData * m_streamData
Definition: dtvrecorder.h:162
mythcorecontext.h
MPEGStreamData::AddWritingListener
void AddWritingListener(TSPacketListener *val)
Definition: mpegstreamdata.cpp:1649
MPEGStreamData::DesiredProgram
int DesiredProgram(void) const
Definition: mpegstreamdata.h:260
cardutil.h
MARK_GOP_BYFRAME
@ MARK_GOP_BYFRAME
Definition: programtypes.h:64
DTVRecorder::m_error
QString m_error
non-empty iff irrecoverable recording error detected
Definition: dtvrecorder.h:160
DTVRecorder::m_useIForKeyframe
bool m_useIForKeyframe
Definition: dtvrecorder.h:208
ProgramInfo::ClearPositionMap
void ClearPositionMap(MarkTypes type) const
Definition: programinfo.cpp:3808
MpegRecorder::m_audType
int m_audType
Definition: mpegrecorder.h:102
MpegRecorder::m_startStopEncodingLock
QRecursiveMutex m_startStopEncodingLock
Definition: mpegrecorder.h:90
mpegrecorder.h
MpegRecorder::kAudRateL2
static const std::array< const int, 14 > kAudRateL2
Definition: mpegrecorder.h:122
MpegRecorder::m_audSampleRate
int m_audSampleRate
Definition: mpegrecorder.h:103
MpegRecorder::SetVBIOptions
bool SetVBIOptions(int chanfd)
Definition: mpegrecorder.cpp:822
RecorderBase::m_recording
bool m_recording
True while recording is actually being performed.
Definition: recorderbase.h:346
MPEGStreamData::Reset
virtual void Reset(void)
Definition: mpegstreamdata.h:94
MpegRecorder::kAudRateL1
static const std::array< const int, 14 > kAudRateL1
Definition: mpegrecorder.h:121
tv_rec.h
DeviceReadBuffer::IsErrored
bool IsErrored(void) const
Definition: DeviceReadBuffer.cpp:242
MpegRecorder::SetStrOption
void SetStrOption(RecordingProfile *profile, const QString &name)
Definition: mpegrecorder.cpp:327
MpegRecorder::m_readfd
int m_readfd
Definition: mpegrecorder.h:119
StandardSetting
Definition: standardsettings.h:29
DeviceReadBuffer::IsEOF
bool IsEOF(void) const
Definition: DeviceReadBuffer.cpp:248
recordingprofile.h
DeviceReadBuffer::SetRequestPause
void SetRequestPause(bool request)
Definition: DeviceReadBuffer.cpp:163
add_ext_ctrl
static void add_ext_ctrl(std::vector< struct v4l2_ext_control > &ctrl_list, uint32_t id, int32_t value)
Definition: mpegrecorder.cpp:672
RecordingProfile
Definition: recordingprofile.h:41
MpegRecorder::m_audBitrateL1
int m_audBitrateL1
Definition: mpegrecorder.h:104
streamtype_ivtv_to_v4l2
static int streamtype_ivtv_to_v4l2(int st)
Definition: mpegrecorder.cpp:651
V4LRecorder::m_audioDeviceName
QString m_audioDeviceName
Definition: v4lrecorder.h:47
MpegRecorder::m_mediumMpeg4PeakBitrate
unsigned int m_mediumMpeg4PeakBitrate
Definition: mpegrecorder.h:113
RecorderBase::m_unpauseWait
QWaitCondition m_unpauseWait
Definition: recorderbase.h:342
MpegRecorder::RestartEncoding
bool RestartEncoding(void)
Definition: mpegrecorder.cpp:1281
MpegRecorder::m_streamType
int m_streamType
Definition: mpegrecorder.h:100
MPEGStreamData::RemoveAVListener
void RemoveAVListener(TSPacketListenerAV *val)
Definition: mpegstreamdata.cpp:1695
MpegRecorder::m_chanfd
int m_chanfd
Definition: mpegrecorder.h:118
MpegRecorder::m_bitrate
int m_bitrate
Definition: mpegrecorder.h:98
RecorderBase::IsPaused
virtual bool IsPaused(bool holding_lock=false) const
Returns true iff recorder is paused.
Definition: recorderbase.cpp:281
DeviceReadBuffer::Reset
void Reset(const QString &streamName, int streamfd)
Definition: DeviceReadBuffer.cpp:134
formatMPEG2_PS
@ formatMPEG2_PS
Definition: recordingfile.h:17
formatMPEG2_TS
@ formatMPEG2_TS
Definition: recordingfile.h:16
V4LRecorder::m_vbiFd
int m_vbiFd
Definition: v4lrecorder.h:58
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:898
RecorderBase::m_requestRecording
bool m_requestRecording
True if API call has requested a recording be [re]started.
Definition: recorderbase.h:344
TSPacket::kSize
static constexpr unsigned int kSize
Definition: tspacket.h:259
MpegRecorder::ProcessTSPacket
bool ProcessTSPacket(const TSPacket &tspacket) override
Definition: mpegrecorder.cpp:1190