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  const QString &audiodev,
271  const QString &vbidev)
272 {
273  (void)audiodev;
274  (void)vbidev;
275 
276  if (videodev.startsWith("file:", Qt::CaseInsensitive))
277  {
278  m_deviceIsMpegFile = true;
279  m_bufferSize = 64000;
280  QString newVideoDev = videodev;
281  if (newVideoDev.startsWith("file:", Qt::CaseInsensitive))
282  newVideoDev = newVideoDev.remove(0,5);
283  SetOption("videodevice", newVideoDev);
284  }
285  else
286  {
287  SetOption("videodevice", videodev);
288  }
289  SetOption("vbidevice", vbidev);
290  SetOption("audiodevice", audiodev);
291 
292  SetOption("tvformat", gCoreContext->GetSetting("TVFormat"));
293  SetOption("vbiformat", gCoreContext->GetSetting("VbiFormat"));
294 
295  SetIntOption(profile, "mpeg2bitrate");
296  SetIntOption(profile, "mpeg2maxbitrate");
297  SetStrOption(profile, "mpeg2streamtype");
298  SetStrOption(profile, "mpeg2aspectratio");
299  SetStrOption(profile, "mpeg2language");
300 
301  SetIntOption(profile, "samplerate");
302  SetStrOption(profile, "mpeg2audtype");
303  SetIntOption(profile, "mpeg2audbitratel1");
304  SetIntOption(profile, "mpeg2audbitratel2");
305  SetIntOption(profile, "mpeg2audbitratel3");
306  SetIntOption(profile, "mpeg2audvolume");
307 
308  SetIntOption(profile, "width");
309  SetIntOption(profile, "height");
310 
311  SetIntOption(profile, "low_mpeg4avgbitrate");
312  SetIntOption(profile, "low_mpeg4peakbitrate");
313  SetIntOption(profile, "medium_mpeg4avgbitrate");
314  SetIntOption(profile, "medium_mpeg4peakbitrate");
315  SetIntOption(profile, "high_mpeg4avgbitrate");
316  SetIntOption(profile, "high_mpeg4peakbitrate");
317 
318  SetStrOption(profile, "audiocodec");
319 }
320 
321 // same as the base class, it just doesn't complain if an option is missing
323 {
324  const StandardSetting *setting = profile->byName(name);
325  if (setting)
326  SetOption(name, setting->getValue().toInt());
327 }
328 
329 // same as the base class, it just doesn't complain if an option is missing
331 {
332  const StandardSetting *setting = profile->byName(name);
333  if (setting)
334  SetOption(name, setting->getValue());
335 }
336 
338 {
339  QByteArray vdevice = m_videodevice.toLatin1();
340  m_chanfd = m_readfd = open(vdevice.constData(), O_RDONLY);
341 
342  if (m_readfd < 0)
343  {
344  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Can't open MPEG File '%1'")
345  .arg(m_videodevice) + ENO);
346  m_error = LOC + QString("Can't open MPEG File '%1'")
347  .arg(m_videodevice) + ENO;
348  return false;
349  }
350  return true;
351 }
352 
354 {
355  // open implicitly starts encoding, so we need the lock..
356  QMutexLocker locker(&m_startStopEncodingLock);
357 
358  QByteArray vdevice = m_videodevice.toLatin1();
359  m_chanfd = open(vdevice.constData(), O_RDWR);
360  if (m_chanfd < 0)
361  {
362  LOG(VB_GENERAL, LOG_ERR, LOC + "Can't open video device. " + ENO);
363  m_error = LOC + "Can't open video device. " + ENO;
364  return false;
365  }
366 
367  m_bufferSize = 4096;
368 
369  bool supports_tuner = false;
370  bool supports_audio = false;
371  uint32_t capabilities = 0;
372  if (CardUtil::GetV4LInfo(m_chanfd, m_card, m_driver, m_version, capabilities))
373  {
374  m_supportsSlicedVbi = ((capabilities & V4L2_CAP_SLICED_VBI_CAPTURE) != 0U);
375  supports_tuner = ((capabilities & V4L2_CAP_TUNER) != 0U);
376  supports_audio = ((capabilities & V4L2_CAP_AUDIO) != 0U);
378  if (m_driver == "hdpvr")
379  {
380  m_bufferSize = 1500 * TSPacket::kSize;
381  m_useIForKeyframe = false;
382  }
383  }
384 
385  if (!(capabilities & V4L2_CAP_VIDEO_CAPTURE))
386  {
387  LOG(VB_GENERAL, LOG_ERR, LOC + "V4L version 1, unsupported");
388  m_error = LOC + "V4L version 1, unsupported";
389  close(m_chanfd);
390  m_chanfd = -1;
391  return false;
392  }
393 
395  {
396  close(m_chanfd);
397  m_chanfd = -1;
398  return false;
399  }
400 
401  if (supports_tuner)
402  SetLanguageMode(m_chanfd); // we don't care if this fails...
403 
404  if (supports_audio)
405  SetRecordingVolume(m_chanfd); // we don't care if this fails...
406 
408  {
409  close(m_chanfd);
410  m_chanfd = -1;
411  return false;
412  }
413 
414  SetVBIOptions(m_chanfd); // we don't care if this fails...
415 
416  m_readfd = open(vdevice.constData(), O_RDWR | O_NONBLOCK);
417 
418  if (m_readfd < 0)
419  {
420  LOG(VB_GENERAL, LOG_ERR, LOC + "Can't open video device." + ENO);
421  m_error = LOC + "Can't open video device." + ENO;
422  close(m_chanfd);
423  m_chanfd = -1;
424  return false;
425  }
426 
427  if (m_deviceReadBuffer)
428  {
431 
432  delete m_deviceReadBuffer;
433  m_deviceReadBuffer = nullptr;
434  }
435 
437 
438  if (!m_deviceReadBuffer)
439  {
440  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to allocate DRB buffer");
441  m_error = "Failed to allocate DRB buffer";
442  close(m_chanfd);
443  m_chanfd = -1;
444  close(m_readfd);
445  m_readfd = -1;
446  return false;
447  }
448 
449  if (!m_deviceReadBuffer->Setup(vdevice.constData(), m_readfd))
450  {
451  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to setup DRB buffer");
452  m_error = "Failed to setup DRB buffer";
453  close(m_chanfd);
454  m_chanfd = -1;
455  close(m_readfd);
456  m_readfd = -1;
457  return false;
458  }
459 
460  LOG(VB_RECORD, LOG_INFO, LOC + "DRB ready");
461 
462  if (m_vbiFd >= 0)
463  m_vbiThread = new VBIThread(this);
464 
465  return true;
466 }
467 
468 
470 {
471  if (m_driver == "hdpvr")
472  return true;
473 
474  struct v4l2_format vfmt {};
475 
476  vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
477 
478  if (ioctl(chanfd, VIDIOC_G_FMT, &vfmt) < 0)
479  {
480  LOG(VB_GENERAL, LOG_ERR, LOC + "Error getting format" + ENO);
481  m_error = LOC + "Error getting format" + ENO;
482  return false;
483  }
484 
485  vfmt.fmt.pix.width = m_width;
486  vfmt.fmt.pix.height = m_height;
487 
488  if (ioctl(chanfd, VIDIOC_S_FMT, &vfmt) < 0)
489  {
490  LOG(VB_GENERAL, LOG_ERR, LOC + "Error setting format" + ENO);
491  m_error = LOC + "Error setting format" + ENO;
492  return false;
493  }
494 
495  return true;
496 }
497 
500 {
501  struct v4l2_tuner vt {};
502  if (ioctl(chanfd, VIDIOC_G_TUNER, &vt) < 0)
503  {
504  LOG(VB_GENERAL, LOG_WARNING, LOC + "Unable to get audio mode" + ENO);
505  return false;
506  }
507 
508  switch (m_language)
509  {
510  case 0:
511  vt.audmode = V4L2_TUNER_MODE_LANG1;
512  break;
513  case 1:
514  vt.audmode = V4L2_TUNER_MODE_LANG2;
515  break;
516  case 2:
517  vt.audmode = V4L2_TUNER_MODE_LANG1_LANG2;
518  break;
519  default:
520  vt.audmode = V4L2_TUNER_MODE_LANG1;
521  }
522 
523  int audio_layer = GetFilteredAudioLayer();
524  bool success = true;
525  if ((2 == m_language) && (1 == audio_layer))
526  {
527  LOG(VB_GENERAL, LOG_WARNING,
528  "Dual audio mode incompatible with Layer I audio."
529  "\n\t\t\tFalling back to Main Language");
530  vt.audmode = V4L2_TUNER_MODE_LANG1;
531  success = false;
532  }
533 
534  if (ioctl(chanfd, VIDIOC_S_TUNER, &vt) < 0)
535  {
536  LOG(VB_GENERAL, LOG_WARNING, LOC + "Unable to set audio mode" + ENO);
537  success = false;
538  }
539 
540  return success;
541 }
542 
544 {
545  // Get volume min/max values
546  struct v4l2_queryctrl qctrl {};
547  qctrl.id = V4L2_CID_AUDIO_VOLUME;
548  if ((ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl) < 0) ||
549  (qctrl.flags & V4L2_CTRL_FLAG_DISABLED))
550  {
551  LOG(VB_CHANNEL, LOG_WARNING,
552  LOC + "Audio volume control not supported.");
553  return false;
554  }
555 
556  // calculate volume in card units.
557  int range = qctrl.maximum - qctrl.minimum;
558  int value = (int) ((range * m_audVolume * 0.01F) + qctrl.minimum);
559  int ctrl_volume = std::min(qctrl.maximum, std::max(qctrl.minimum, value));
560 
561  // Set recording volume
562  struct v4l2_control ctrl {V4L2_CID_AUDIO_VOLUME, ctrl_volume};
563 
564  if (ioctl(chanfd, VIDIOC_S_CTRL, &ctrl) < 0)
565  {
566  LOG(VB_GENERAL, LOG_WARNING, LOC +
567  "Unable to set recording volume" + ENO + "\n\t\t\t" +
568  "If you are using an AverMedia M179 card this is normal.");
569  return false;
570  }
571 
572  return true;
573 }
574 
576 {
577  uint st = (uint) m_streamType;
578 
579  if (m_driver == "ivtv")
580  {
581  switch (st)
582  {
583  case 2: st = 2; break;
584  case 10:
585  case 13:
586  case 14: st = 10; break;
587  case 11: st = 11; break;
588  case 12: st = 12; break;
589  default: st = 0; break;
590  }
591  }
592 
593  if (st != (uint) m_streamType)
594  {
595  LOG(VB_GENERAL, LOG_WARNING, LOC +
596  QString("Stream type '%1'\n\t\t\t"
597  "is not supported by %2 driver, using '%3' instead.")
598  .arg(QString::fromStdString(kStreamType[m_streamType]),
599  m_driver,
600  QString::fromStdString(kStreamType[st])));
601  }
602 
603  return st;
604 }
605 
607 {
608  uint sr = (uint) m_audSampleRate;
609 
610  sr = (m_driver == "ivtv") ? 48000 : sr; // only 48kHz works properly.
611 
612  if (sr != (uint) m_audSampleRate)
613  {
614  LOG(VB_GENERAL, LOG_WARNING, LOC +
615  QString("Audio sample rate %1 Hz\n\t\t\t"
616  "is not supported by %2 driver, using %3 Hz instead.")
617  .arg(m_audSampleRate).arg(m_driver).arg(sr));
618  }
619 
620  switch (sr)
621  {
622  case 32000: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000;
623  case 44100: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100;
624  case 48000:
625  default: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
626  }
627 }
628 
630 {
631  uint layer = (uint) m_audType;
632 
633  layer = std::max(std::min(layer, 3U), 1U);
634 
635  layer = (m_driver == "ivtv") ? 2 : layer;
636 
637  if (layer != (uint) m_audType)
638  {
639  LOG(VB_GENERAL, LOG_WARNING, LOC +
640  QString("MPEG layer %1 does not work properly\n\t\t\t"
641  "with %2 driver. Using MPEG layer %3 audio instead.")
642  .arg(m_audType).arg(m_driver).arg(layer));
643  }
644 
645  return layer;
646 }
647 
649 {
650  return ((2 == audio_layer) ? std::max(m_audBitrateL2, 10) :
651  ((3 == audio_layer) ? m_audBitrateL3 : std::max(m_audBitrateL1, 6)));
652 }
653 
654 static int streamtype_ivtv_to_v4l2(int st)
655 {
656  switch (st)
657  {
658  case 0: return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
659  case 1: return V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
660  case 2: return V4L2_MPEG_STREAM_TYPE_MPEG1_VCD;
661  case 3: /* PES A/V */
662  case 5: /* PES V */
663  case 7: /* PES A */
664  return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
665  case 10: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD;
666  case 11: return V4L2_MPEG_STREAM_TYPE_MPEG1_VCD; /* VCD */
667  case 12: return V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD;
668  case 13: /* DVD-Special 1 */
669  case 14: /* DVD-Special 2 */
670  return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD;
671  default: return V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
672  }
673 }
674 
675 static void add_ext_ctrl(std::vector<struct v4l2_ext_control> &ctrl_list,
676  uint32_t id, int32_t value)
677 {
678  struct v4l2_ext_control tmp_ctrl {};
679  tmp_ctrl.id = id;
680  tmp_ctrl.value = value;
681  ctrl_list.push_back(tmp_ctrl);
682 }
683 
684 static void set_ctrls(int fd, std::vector<struct v4l2_ext_control> &ext_ctrls)
685 {
686  static QMutex s_controlDescriptionLock;
687  static QMap<uint32_t,QString> s_controlDescription;
688 
689  s_controlDescriptionLock.lock();
690  if (s_controlDescription.isEmpty())
691  {
692  s_controlDescription[V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ] =
693  "Audio Sampling Frequency";
694  s_controlDescription[V4L2_CID_MPEG_VIDEO_ASPECT] =
695  "Video Aspect ratio";
696  s_controlDescription[V4L2_CID_MPEG_AUDIO_ENCODING] =
697  "Audio Encoding";
698  s_controlDescription[V4L2_CID_MPEG_AUDIO_L2_BITRATE] =
699  "Audio L2 Bitrate";
700  s_controlDescription[V4L2_CID_MPEG_VIDEO_BITRATE_PEAK] =
701  "Video Peak Bitrate";
702  s_controlDescription[V4L2_CID_MPEG_VIDEO_BITRATE] =
703  "Video Average Bitrate";
704  s_controlDescription[V4L2_CID_MPEG_STREAM_TYPE] =
705  "MPEG Stream type";
706  s_controlDescription[V4L2_CID_MPEG_VIDEO_BITRATE_MODE] =
707  "MPEG Bitrate mode";
708  }
709  s_controlDescriptionLock.unlock();
710 
711  for (auto & ext_ctrl : ext_ctrls)
712  {
713  struct v4l2_ext_controls ctrls {};
714 
715  int value = ext_ctrl.value;
716 
717  ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
718  ctrls.count = 1;
719  ctrls.controls = &ext_ctrl;
720 
721  if (ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
722  {
723  QMutexLocker locker(&s_controlDescriptionLock);
724  LOG(VB_GENERAL, LOG_ERR, QString("mpegrecorder.cpp:set_ctrls(): ") +
725  QString("Could not set %1 to %2")
726  .arg(s_controlDescription[ext_ctrl.id]).arg(value) +
727  ENO);
728  }
729  }
730 }
731 
733 {
734  std::vector<struct v4l2_ext_control> ext_ctrls;
735 
736  // Set controls
737  if (m_driver != "hdpvr")
738  {
739  if (!m_driver.startsWith("saa7164"))
740  {
741  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
743 
744  uint audio_layer = GetFilteredAudioLayer();
745  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_ENCODING,
746  audio_layer - 1);
747 
748  uint audbitrate = GetFilteredAudioBitRate(audio_layer);
749  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_L2_BITRATE,
750  audbitrate - 1);
751  }
752 
753  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_ASPECT,
754  m_aspectRatio - 1);
755 
756  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_STREAM_TYPE,
758 
759  }
760  else
761  {
764  }
765  m_maxBitrate = std::max(m_maxBitrate, m_bitrate);
766 
767  if (m_driver == "hdpvr" || m_driver.startsWith("saa7164"))
768  {
769  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
770  (m_maxBitrate == m_bitrate) ?
771  V4L2_MPEG_VIDEO_BITRATE_MODE_CBR :
772  V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
773  }
774 
775  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE,
776  m_bitrate * 1000);
777 
778  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
779  m_maxBitrate * 1000);
780 
781  set_ctrls(chanfd, ext_ctrls);
782 
783  bool ok = false;
784  int audioinput = m_audioDeviceName.toUInt(&ok);
785  if (ok)
786  {
787  struct v4l2_audio ain {};
788  ain.index = audioinput;
789  if (ioctl(chanfd, VIDIOC_ENUMAUDIO, &ain) < 0)
790  {
791  LOG(VB_GENERAL, LOG_WARNING, LOC + "Unable to get audio input.");
792  }
793  else
794  {
795  ain.index = audioinput;
796  if (ioctl(chanfd, VIDIOC_S_AUDIO, &ain) < 0)
797  {
798  LOG(VB_GENERAL, LOG_WARNING,
799  LOC + "Unable to set audio input.");
800  }
801  }
802  }
803 
804  // query supported audio codecs if spdif is not used
805  if (m_driver == "hdpvr" && audioinput != 2)
806  {
807  struct v4l2_queryctrl qctrl {};
808  qctrl.id = V4L2_CID_MPEG_AUDIO_ENCODING;
809 
810  if (!ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl))
811  {
812  uint audio_enc = std::max(std::min(m_audType-1, qctrl.maximum), qctrl.minimum);
813  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_ENCODING, audio_enc);
814  }
815  else
816  {
817  LOG(VB_GENERAL, LOG_WARNING, LOC +
818  "Unable to get supported audio codecs." + ENO);
819  }
820  }
821 
822  return true;
823 }
824 
826 {
827  if (VBIMode::None == m_vbiMode)
828  return true;
829 
830  if (m_driver == "hdpvr")
831  return true;
832 
833 #ifdef V4L2_CAP_SLICED_VBI_CAPTURE
835  {
836  int fd = 0;
837 
838  if (OpenVBIDevice() >= 0)
839  fd = m_vbiFd;
840  else
841  fd = chanfd;
842 
843  struct v4l2_format vbifmt {};
844  vbifmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
845  vbifmt.fmt.sliced.service_set |= (VBIMode::PAL_TT == m_vbiMode) ?
846  V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
847 
848  if (ioctl(fd, VIDIOC_S_FMT, &vbifmt) < 0)
849  {
850  if (m_vbiFd >= 0)
851  {
852  fd = chanfd; // Retry with video device instead
853  if (ioctl(fd, VIDIOC_S_FMT, &vbifmt) < 0)
854  {
855  LOG(VB_GENERAL, LOG_WARNING, LOC +
856  "Unable to enable VBI embedding (/dev/vbiX)" + ENO);
857  return false;
858  }
859  }
860  else
861  {
862  LOG(VB_GENERAL, LOG_WARNING, LOC +
863  "Unable to enable VBI embedding (/dev/videoX)" + ENO);
864  return false;
865  }
866  }
867 
868  if (ioctl(fd, VIDIOC_G_FMT, &vbifmt) >= 0)
869  {
870  LOG(VB_RECORD, LOG_INFO,
871  LOC + QString("VBI service: %1, io size: %2")
872  .arg(vbifmt.fmt.sliced.service_set)
873  .arg(vbifmt.fmt.sliced.io_size));
874 
875  struct v4l2_ext_control vbi_ctrl {};
876  vbi_ctrl.id = V4L2_CID_MPEG_STREAM_VBI_FMT;
877  vbi_ctrl.value = V4L2_MPEG_STREAM_VBI_FMT_IVTV;
878 
879  struct v4l2_ext_controls ctrls {};
880  ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
881  ctrls.count = 1;
882  ctrls.controls = &vbi_ctrl;
883 
884  if (ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
885  {
886  LOG(VB_GENERAL, LOG_WARNING, LOC +
887  "Unable to set VBI embedding format" + ENO);
888  }
889  else
890  {
891  return true;
892  }
893  }
894  }
895 #endif // V4L2_CAP_SLICED_VBI_CAPTURE
896 
897  return OpenVBIDevice() >= 0;
898 }
899 
901 {
902  ResetForNewFile();
904 }
905 
907 {
908  if (!Open())
909  {
910  if (m_error.isEmpty())
911  m_error = "Failed to open V4L device";
912  return;
913  }
914 
915  bool has_select = true;
916 
917 #if defined(__FreeBSD__)
918  // HACK. FreeBSD PVR150/500 driver doesn't currently support select()
919  has_select = false;
920 #endif
921 
922  if (m_driver == "hdpvr")
923  {
924  int progNum = 1;
925  auto *sd = new MPEGStreamData(progNum,
926  m_tvrec ? m_tvrec->GetInputId() : -1,
927  true);
928  sd->SetRecordingType(m_recordingType);
929  SetStreamData(sd);
930 
933 
934  // Make sure the first things in the file are a PAT & PMT
938  }
939 
940  {
941  QMutexLocker locker(&m_pauseLock);
942  m_requestRecording = true;
943  m_requestHelper = true;
944  m_recording = true;
945  m_recordingWait.wakeAll();
946  }
947 
948  auto *buffer = new unsigned char[m_bufferSize + 1];
949  int len = 0;
950  int remainder = 0;
951 
952  bool good_data = false;
953  bool gap = false;
954  QDateTime gap_start;
955 
956  MythTimer elapsedTimer;
957  float elapsed = NAN;
958  long long bytesRead = 0;
959 
960  bool ok { false };
961  // Bytes per second, but env var is BITS PER SECOND
962  int dummyBPS = qEnvironmentVariableIntValue("DUMMYBPS", &ok) / 8;
963  if (ok)
964  {
965  LOG(VB_GENERAL, LOG_INFO,
966  LOC + QString("Throttling dummy recorder to %1 bits per second")
967  .arg(dummyBPS * 8));
968  }
969 
970  struct timeval tv {};
971  fd_set rdset;
972 
973  if (m_deviceIsMpegFile)
974  elapsedTimer.start();
975  else if (m_deviceReadBuffer)
976  {
977  LOG(VB_RECORD, LOG_INFO, LOC + "Initial startup of recorder");
978  StartEncoding();
979  }
980 
981  QByteArray vdevice = m_videodevice.toLatin1();
982  while (IsRecordingRequested() && !IsErrored())
983  {
984  if (PauseAndWait(100ms))
985  continue;
986 
987  if (m_deviceIsMpegFile)
988  {
989  if (dummyBPS && bytesRead)
990  {
991  elapsed = (elapsedTimer.elapsed().count() / 1000.0) + 1;
992  while ((bytesRead / elapsed) > dummyBPS)
993  {
994  std::this_thread::sleep_for(50ms);
995  elapsed = (elapsedTimer.elapsed().count() / 1000.0) + 1;
996  }
997  }
998  else if (GetFramesWritten())
999  {
1000  elapsed = (elapsedTimer.elapsed().count() / 1000.0) + 1;
1001  while ((GetFramesWritten() / elapsed) > 30)
1002  {
1003  std::this_thread::sleep_for(50ms);
1004  elapsed = (elapsedTimer.elapsed().count() / 1000.0) + 1;
1005  }
1006  }
1007  }
1008 
1009  if (m_deviceReadBuffer)
1010  {
1011  len = m_deviceReadBuffer->Read
1012  (&(buffer[remainder]), m_bufferSize - remainder);
1013 
1014  // Check for DRB errors
1016  {
1017  LOG(VB_GENERAL, LOG_ERR, LOC + "Device error detected");
1018 
1019  if (good_data)
1020  {
1021  if (gap)
1022  {
1023  /* Already processing a gap, which means
1024  * restarting the encoding didn't work! */
1025  SetRecordingStatus(RecStatus::Failing, __FILE__, __LINE__);
1026  }
1027  else
1028  gap = true;
1029  }
1030 
1031  if (!RestartEncoding())
1032  SetRecordingStatus(RecStatus::Failing, __FILE__, __LINE__);
1033  }
1034  else if (m_deviceReadBuffer->IsEOF() &&
1036  {
1037  LOG(VB_GENERAL, LOG_ERR, LOC + "Device EOF detected");
1038  m_error = "Device EOF detected";
1039  }
1040  else
1041  {
1042  // If we have seen good data, but now have a gap, note it
1043  if (good_data)
1044  {
1045  if (gap)
1046  {
1047  QMutexLocker locker(&m_statisticsLock);
1048  QDateTime gap_end(MythDate::current());
1049 
1050  m_recordingGaps.push_back(RecordingGap
1051  (gap_start, gap_end));
1052  LOG(VB_RECORD, LOG_DEBUG,
1053  LOC + QString("Inserted gap %1 dur %2")
1054  .arg(m_recordingGaps.back().toString())
1055  .arg(gap_start.secsTo(gap_end)));
1056  gap = false;
1057  }
1058  else
1059  gap_start = MythDate::current();
1060  }
1061  else
1062  good_data = true;
1063  }
1064  }
1065  else if (m_readfd < 0)
1066  continue;
1067  else
1068  {
1069  if (has_select)
1070  {
1071  tv.tv_sec = 5;
1072  tv.tv_usec = 0;
1073  FD_ZERO(&rdset); // NOLINT(readability-isolate-declaration)
1074  FD_SET(m_readfd, &rdset);
1075 
1076  switch (select(m_readfd + 1, &rdset, nullptr, nullptr, &tv))
1077  {
1078  case -1:
1079  if (errno == EINTR)
1080  continue;
1081 
1082  LOG(VB_GENERAL, LOG_ERR, LOC + "Select error" + ENO);
1083  continue;
1084 
1085  case 0:
1086  LOG(VB_GENERAL, LOG_ERR, LOC + "select timeout - "
1087  "driver has stopped responding");
1088 
1089  if (close(m_readfd) != 0)
1090  {
1091  LOG(VB_GENERAL, LOG_ERR, LOC + "Close error" + ENO);
1092  }
1093 
1094  // Force card to be reopened on next iteration..
1095  m_readfd = -1;
1096  continue;
1097 
1098  default:
1099  break;
1100  }
1101  }
1102 
1103  len = read(m_readfd, &(buffer[remainder]), m_bufferSize - remainder);
1104 
1105  if (len < 0 && !has_select)
1106  {
1107  QMutexLocker locker(&m_pauseLock);
1109  m_unpauseWait.wait(&m_pauseLock, 25);
1110  continue;
1111  }
1112 
1113  if ((len == 0) && (m_deviceIsMpegFile))
1114  {
1115  close(m_readfd);
1116  m_readfd = open(vdevice.constData(), O_RDONLY);
1117 
1118  if (m_readfd >= 0)
1119  {
1120  len = read(m_readfd,
1121  &(buffer[remainder]), m_bufferSize - remainder);
1122  }
1123 
1124  if (len <= 0)
1125  {
1126  m_error = "Failed to read from video file";
1127  continue;
1128  }
1129  }
1130  else if (len < 0 && errno != EAGAIN)
1131  {
1132  LOG(VB_GENERAL, LOG_ERR, LOC + QString("error reading from: %1")
1133  .arg(m_videodevice) + ENO);
1134  continue;
1135  }
1136  }
1137 
1138  if (len > 0)
1139  {
1140  bytesRead += len;
1141  len += remainder;
1142 
1143  if (m_driver == "hdpvr")
1144  {
1145  remainder = m_streamData->ProcessData(buffer, len);
1146  int start_remain = len - remainder;
1147  if (remainder && (start_remain >= remainder))
1148  memcpy(buffer, buffer+start_remain, remainder);
1149  else if (remainder)
1150  memmove(buffer, buffer+start_remain, remainder);
1151  }
1152  else
1153  {
1154  FindPSKeyFrames(buffer, len);
1155  }
1156  }
1157  }
1158 
1159  LOG(VB_RECORD, LOG_INFO, LOC + "run finishing up");
1160 
1161  StopEncoding();
1162 
1163  {
1164  QMutexLocker locker(&m_pauseLock);
1165  m_requestHelper = false;
1166  }
1167 
1168  if (m_vbiThread)
1169  {
1170  m_vbiThread->wait();
1171  delete m_vbiThread;
1172  m_vbiThread = nullptr;
1173  CloseVBIDevice();
1174  }
1175 
1176  FinishRecording();
1177 
1178  delete[] buffer;
1179 
1180  if (m_driver == "hdpvr")
1181  {
1184  SetStreamData(nullptr);
1185  }
1186 
1187  QMutexLocker locker(&m_pauseLock);
1188  m_requestRecording = false;
1189  m_recording = false;
1190  m_recordingWait.wakeAll();
1191 }
1192 
1193 bool MpegRecorder::ProcessTSPacket(const TSPacket &tspacket_real)
1194 {
1195  const uint pid = tspacket_real.PID();
1196 
1197  TSPacket *tspacket_fake = nullptr;
1198  if ((m_driver == "hdpvr") && (pid == 0x1001)) // PCRPID for HD-PVR
1199  {
1200  tspacket_fake = tspacket_real.CreateClone();
1201  uint cc = (m_continuityCounter[pid] == 0xFF) ?
1202  0 : (m_continuityCounter[pid] + 1) & 0xf;
1203  tspacket_fake->SetContinuityCounter(cc);
1204  }
1205 
1206  const TSPacket &tspacket = (tspacket_fake)
1207  ? *tspacket_fake : tspacket_real;
1208 
1209  bool ret = DTVRecorder::ProcessTSPacket(tspacket);
1210 
1211  delete tspacket_fake;
1212 
1213  return ret;
1214 }
1215 
1217 {
1218  LOG(VB_RECORD, LOG_INFO, LOC + "Reset(void)");
1219  ResetForNewFile();
1220 
1221  if (m_h2645Parser != nullptr)
1222  m_h2645Parser->Reset();
1223 
1224  m_startCode = 0xffffffff;
1225 
1226  if (m_curRecording)
1227  {
1229  }
1230  if (m_streamData)
1232 }
1233 
1235 {
1236  QMutexLocker locker(&m_pauseLock);
1238  m_paused = false;
1239  m_requestPause = true;
1240 }
1241 
1242 bool MpegRecorder::PauseAndWait(std::chrono::milliseconds timeout)
1243 {
1244  QMutexLocker locker(&m_pauseLock);
1245  if (m_requestPause)
1246  {
1247  if (!IsPaused(true))
1248  {
1249  LOG(VB_RECORD, LOG_INFO, LOC + "PauseAndWait pause");
1250 
1251  StopEncoding();
1252 
1253  m_paused = true;
1254  m_pauseWait.wakeAll();
1255 
1256  if (m_tvrec)
1258  }
1259 
1260  m_unpauseWait.wait(&m_pauseLock, timeout.count());
1261  }
1262 
1263  if (!m_requestPause && IsPaused(true))
1264  {
1265  LOG(VB_RECORD, LOG_INFO, LOC + "PauseAndWait unpause");
1266 
1267  if (m_driver == "hdpvr")
1268  {
1269  // HD-PVR will sometimes reset to defaults
1271  }
1272 
1273  StartEncoding();
1274 
1275  if (m_streamData)
1277 
1278  m_paused = false;
1279  }
1280 
1281  return IsPaused(true);
1282 }
1283 
1285 {
1286  LOG(VB_RECORD, LOG_INFO, LOC + "RestartEncoding");
1287 
1288  QMutexLocker locker(&m_startStopEncodingLock);
1289 
1290  StopEncoding();
1291 
1292  // Make sure the next things in the file are a PAT & PMT
1293  if (m_streamData &&
1296  {
1297  m_payloadBuffer.clear(); // No reason to keep part of a frame
1300  }
1301 
1302  if (m_driver == "hdpvr") // HD-PVR will sometimes reset to defaults
1304 
1305  return StartEncoding();
1306 }
1307 
1309 {
1310  QMutexLocker locker(&m_startStopEncodingLock);
1311 
1312  LOG(VB_RECORD, LOG_INFO, LOC + "StartEncoding");
1313 
1314  if (m_readfd < 0)
1315  {
1316  m_readfd = open(m_videodevice.toLatin1().constData(), O_RDWR | O_NONBLOCK);
1317  if (m_readfd < 0)
1318  {
1319  LOG(VB_GENERAL, LOG_ERR, LOC +
1320  "StartEncoding: Can't open video device." + ENO);
1321  m_error = "Failed to start recording";
1322  return false;
1323  }
1324  }
1325 
1326  if (m_h2645Parser != nullptr)
1327  m_h2645Parser->Reset();
1328 
1329  bool good_res = true;
1330  if (m_driver == "hdpvr")
1331  {
1332  m_waitForKeyframeOption = true;
1333  m_seenSps = false;
1334  good_res = HandleResolutionChanges();
1335  }
1336 
1337  // (at least) with the 3.10 kernel, the V4L2_ENC_CMD_START does
1338  // not reliably start the data flow from a HD-PVR. A read() seems
1339  // to work, though.
1340 
1341  int idx = 1;
1342  for ( ; idx < 50; ++idx)
1343  {
1344  uint8_t dummy = 0;
1345  int len = read(m_readfd, &dummy, 0);
1346  if (len == 0)
1347  break;
1348  if (idx == 20)
1349  {
1350  LOG(VB_GENERAL, LOG_ERR, LOC +
1351  "StartEncoding: read failing, re-opening device: " + ENO);
1352  close(m_readfd);
1353  std::this_thread::sleep_for(2ms);
1354  m_readfd = open(m_videodevice.toLatin1().constData(),
1355  O_RDWR | O_NONBLOCK);
1356  if (m_readfd < 0)
1357  {
1358  LOG(VB_GENERAL, LOG_ERR, LOC +
1359  "StartEncoding: Can't open video device." + ENO);
1360  m_error = "Failed to start recording";
1361  return false;
1362  }
1363  }
1364  else
1365  {
1366  LOG(VB_GENERAL, LOG_ERR, LOC +
1367  QString("StartEncoding: read failed, retry in %1 msec:")
1368  .arg(100 * idx) + ENO);
1369  std::this_thread::sleep_for(idx * 100us);
1370  }
1371  }
1372  if (idx == 50)
1373  {
1374  LOG(VB_GENERAL, LOG_ERR, LOC +
1375  "StartEncoding: read from video device failed." + ENO);
1376  m_error = "Failed to start recording";
1377  close(m_readfd);
1378  m_readfd = -1;
1379  return false;
1380  }
1381  if (idx > 0)
1382  {
1383  LOG(VB_RECORD, LOG_WARNING, LOC +
1384  QString("%1 read attempts required to start encoding").arg(idx));
1385  }
1386 
1387  if (!good_res) // Try again
1389 
1390  if (m_deviceReadBuffer)
1391  {
1392  m_deviceReadBuffer->Reset(m_videodevice.toLatin1().constData(), m_readfd);
1395  }
1396 
1397  return true;
1398 }
1399 
1401 {
1402  QMutexLocker locker(&m_startStopEncodingLock);
1403 
1404  LOG(VB_RECORD, LOG_INFO, LOC + "StopEncoding");
1405 
1406  if (m_readfd < 0)
1407  return;
1408 
1409  struct v4l2_encoder_cmd command {};
1410  command.cmd = V4L2_ENC_CMD_STOP;
1411  command.flags = V4L2_ENC_CMD_STOP_AT_GOP_END;
1412 
1413  if (m_deviceReadBuffer)
1415 
1416  bool stopped = 0 == ioctl(m_readfd, VIDIOC_ENCODER_CMD, &command);
1417  if (stopped)
1418  {
1419  LOG(VB_RECORD, LOG_INFO, LOC + "Encoding stopped");
1420  }
1421  else if (errno != ENOTTY && errno != EINVAL)
1422  {
1423  // Some drivers do not support this ioctl at all. It is marked as
1424  // "experimental" in the V4L2 API spec. These drivers return EINVAL
1425  // in older kernels and ENOTTY in 3.1+
1426 
1427  LOG(VB_GENERAL, LOG_WARNING, LOC + "StopEncoding failed" + ENO);
1428  }
1429 
1431  {
1432  // allow last bits of data through..
1433  std::this_thread::sleep_for(20ms);
1435  }
1436 
1437  // close the fd so streamoff/streamon work in V4LChannel
1438  close(m_readfd);
1439  m_readfd = -1;
1440 }
1441 
1443 {
1446 }
1447 
1448 void MpegRecorder::SetBitrate(int bitrate, int maxbitrate,
1449  const QString & reason)
1450 {
1451  if (maxbitrate == bitrate)
1452  {
1453  LOG(VB_RECORD, LOG_INFO, LOC + QString("%1 bitrate %2 kbps CBR")
1454  .arg(reason).arg(bitrate));
1455  }
1456  else
1457  {
1458  LOG(VB_RECORD, LOG_INFO, LOC + QString("%1 bitrate %2/%3 kbps VBR")
1459  .arg(reason).arg(bitrate).arg(maxbitrate));
1460  }
1461 
1462  std::vector<struct v4l2_ext_control> ext_ctrls;
1463  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
1464  (maxbitrate == bitrate) ?
1465  V4L2_MPEG_VIDEO_BITRATE_MODE_CBR :
1466  V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
1467 
1468  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE,
1469  bitrate * 1000);
1470 
1471  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
1472  maxbitrate * 1000);
1473 
1474  set_ctrls(m_readfd, ext_ctrls);
1475 }
1476 
1478 {
1479  LOG(VB_RECORD, LOG_INFO, LOC + "Checking Resolution");
1480  uint pix = 0;
1481  struct v4l2_format vfmt {};
1482  vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1483 
1484  if (0 == ioctl(m_chanfd, VIDIOC_G_FMT, &vfmt))
1485  {
1486  LOG(VB_RECORD, LOG_INFO, LOC + QString("Got Resolution %1x%2")
1487  .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height));
1488  pix = vfmt.fmt.pix.width * vfmt.fmt.pix.height;
1489  }
1490 
1491  if (!pix)
1492  {
1493  LOG(VB_RECORD, LOG_INFO, LOC + "Giving up detecting resolution: " + ENO);
1494  return false; // nothing to do, we don't have a resolution yet
1495  }
1496 
1497  int old_max = m_maxBitrate;
1498  int old_avg = m_bitrate;
1499  if (pix <= 768*568)
1500  {
1503  }
1504  else if (pix >= 1920*1080)
1505  {
1508  }
1509  else
1510  {
1513  }
1514  m_maxBitrate = std::max(m_maxBitrate, m_bitrate);
1515 
1516  if ((old_max != m_maxBitrate) || (old_avg != m_bitrate))
1517  {
1518  if (old_max == old_avg)
1519  {
1520  LOG(VB_RECORD, LOG_INFO, LOC +
1521  QString("Old bitrate %1 CBR").arg(old_avg));
1522  }
1523  else
1524  {
1525  LOG(VB_RECORD, LOG_INFO,LOC +
1526  QString("Old bitrate %1/%2 VBR") .arg(old_avg).arg(old_max));
1527  }
1528 
1530  }
1531 
1532  return true;
1533 }
1534 
1536 {
1537  LOG(VB_VBI, LOG_INFO, LOC + QString("FormatCC(0x%1,0x%2)")
1538  .arg(code1,0,16).arg(code2,0,16));
1539  // TODO add to CC data vector
1540 
1541  // TODO find video frames in output and insert cc_data
1542  // as CEA-708 user_data packets containing CEA-608 captions
1544 }
MpegRecorder::Pause
void Pause(bool clear=true) override
Pause tells recorder to pause, it should not block.
Definition: mpegrecorder.cpp:1234
MpegRecorder::m_clearTimeOnPause
bool m_clearTimeOnPause
Definition: mpegrecorder.h:97
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:103
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:499
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:1216
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:684
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:1308
MpegRecorder::kAspectRatio
static const std::array< const std::string, 4 > kAspectRatio
Definition: mpegrecorder.h:129
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:322
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:115
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:1242
H2645Parser::Reset
virtual void Reset(void)
Definition: H2645Parser.cpp:93
MpegRecorder::GetFilteredAudioLayer
uint GetFilteredAudioLayer(void) const
Definition: mpegrecorder.cpp:629
DTVRecorder::SetStreamData
virtual void SetStreamData(MPEGStreamData *data)
Definition: dtvrecorder.cpp:218
MpegRecorder::m_deviceReadBuffer
DeviceReadBuffer * m_deviceReadBuffer
Definition: mpegrecorder.h:133
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:337
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:119
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:118
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:353
MpegRecorder::run
void run(void) override
run() starts the recording process, and does not exit until the recording is complete.
Definition: mpegrecorder.cpp:906
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:101
DTVRecorder::m_continuityCounter
std::array< uint8_t, 0x1fff+1 > m_continuityCounter
Definition: dtvrecorder.h:186
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:2897
TVRec::GetInputId
uint GetInputId(void) const
Returns the inputid.
Definition: tv_rec.h:236
mythdate.h
MpegRecorder::SetV4L2DeviceOptions
bool SetV4L2DeviceOptions(int chanfd)
Definition: mpegrecorder.cpp:732
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:99
CardUtil::GetV4LInfo
static bool GetV4LInfo(int videofd, QString &input, QString &driver, uint32_t &version, uint32_t &capabilities)
Definition: cardutil.cpp:2374
RecorderBase::m_recordingGaps
RecordingGaps m_recordingGaps
Definition: recorderbase.h:382
MpegRecorder::HandleResolutionChanges
bool HandleResolutionChanges(void)
Definition: mpegrecorder.cpp:1477
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:128
RecStatus::Failing
@ Failing
Definition: recordingstatus.h:18
MpegRecorder::Open
bool Open(void)
Definition: mpegrecorder.cpp:900
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:114
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:543
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:898
DTVRecorder::m_seenSps
bool m_seenSps
Definition: dtvrecorder.h:150
MpegRecorder::m_aspectRatio
int m_aspectRatio
Definition: mpegrecorder.h:105
MpegRecorder::m_language
unsigned int m_language
0 is Main Lang; 1 is SAP Lang; 2 is Dual
Definition: mpegrecorder.h:113
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:110
DTVRecorder::ProcessTSPacket
bool ProcessTSPacket(const TSPacket &tspacket) override
Definition: dtvrecorder.cpp:1543
MpegRecorder::m_audVolume
int m_audVolume
Definition: mpegrecorder.h:111
uint
unsigned int uint
Definition: compat.h:81
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:54
RecorderBase::m_containerFormat
AVContainer m_containerFormat
Definition: recorderbase.h:319
MpegRecorder::SetVideoCaptureFormat
bool SetVideoCaptureFormat(int chanfd)
Definition: mpegrecorder.cpp:469
MpegRecorder::kAudRateL3
static const std::array< const int, 14 > kAudRateL3
Definition: mpegrecorder.h:127
MpegRecorder::GetFilteredStreamType
uint GetFilteredStreamType(void) const
Definition: mpegrecorder.cpp:575
MpegRecorder::GetFilteredAudioSampleRate
uint GetFilteredAudioSampleRate(void) const
Definition: mpegrecorder.cpp:606
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:109
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:1535
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:1442
MpegRecorder::m_mediumMpeg4AvgBitrate
unsigned int m_mediumMpeg4AvgBitrate
Definition: mpegrecorder.h:116
MpegRecorder::m_width
int m_width
Definition: mpegrecorder.h:100
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:1400
V4LRecorder::m_vbiMode
int m_vbiMode
Definition: v4lrecorder.h:49
MpegRecorder::m_maxBitrate
int m_maxBitrate
Definition: mpegrecorder.h:103
MpegRecorder::SetBitrate
void SetBitrate(int bitrate, int maxbitrate, const QString &reason)
Definition: mpegrecorder.cpp:1448
RecordingGap
Definition: recordingquality.h:14
MpegRecorder::GetFilteredAudioBitRate
uint GetFilteredAudioBitRate(uint audio_layer) const
Definition: mpegrecorder.cpp:648
RecorderBase::SetRecordingStatus
virtual void SetRecordingStatus(RecStatus::Type status, const QString &file, int line)
Definition: recorderbase.cpp:396
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:65
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:212
ProgramInfo::ClearPositionMap
void ClearPositionMap(MarkTypes type) const
Definition: programinfo.cpp:3809
MpegRecorder::m_audType
int m_audType
Definition: mpegrecorder.h:106
MpegRecorder::m_startStopEncodingLock
QRecursiveMutex m_startStopEncodingLock
Definition: mpegrecorder.h:93
mpegrecorder.h
MpegRecorder::kAudRateL2
static const std::array< const int, 14 > kAudRateL2
Definition: mpegrecorder.h:126
MpegRecorder::m_audSampleRate
int m_audSampleRate
Definition: mpegrecorder.h:107
MpegRecorder::SetVBIOptions
bool SetVBIOptions(int chanfd)
Definition: mpegrecorder.cpp:825
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:125
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:330
MpegRecorder::m_readfd
int m_readfd
Definition: mpegrecorder.h:123
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:675
RecordingProfile
Definition: recordingprofile.h:41
MpegRecorder::m_audBitrateL1
int m_audBitrateL1
Definition: mpegrecorder.h:108
streamtype_ivtv_to_v4l2
static int streamtype_ivtv_to_v4l2(int st)
Definition: mpegrecorder.cpp:654
V4LRecorder::m_audioDeviceName
QString m_audioDeviceName
Definition: v4lrecorder.h:47
MpegRecorder::m_mediumMpeg4PeakBitrate
unsigned int m_mediumMpeg4PeakBitrate
Definition: mpegrecorder.h:117
RecorderBase::m_unpauseWait
QWaitCondition m_unpauseWait
Definition: recorderbase.h:342
MpegRecorder::RestartEncoding
bool RestartEncoding(void)
Definition: mpegrecorder.cpp:1284
MpegRecorder::m_streamType
int m_streamType
Definition: mpegrecorder.h:104
MPEGStreamData::RemoveAVListener
void RemoveAVListener(TSPacketListenerAV *val)
Definition: mpegstreamdata.cpp:1695
MpegRecorder::m_chanfd
int m_chanfd
Definition: mpegrecorder.h:122
MpegRecorder::m_bitrate
int m_bitrate
Definition: mpegrecorder.h:102
RecorderBase::IsPaused
virtual bool IsPaused(bool holding_lock=false) const
Returns true iff recorder is paused.
Definition: recorderbase.cpp:282
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:896
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:1193