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