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 using namespace std;
13 
14 // System headers
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <sys/ioctl.h>
18 #include <sys/time.h>
19 #include <sys/poll.h>
20 
21 #include <linux/videodev2.h>
22 
23 #include "mythconfig.h"
24 
25 // MythTV headers
26 #include "mpegrecorder.h"
27 #include "io/mythmediabuffer.h"
28 #include "mythcorecontext.h"
29 #include "programinfo.h"
30 #include "recordingprofile.h"
31 #include "tv_rec.h"
32 #include "mythdate.h"
33 #include "cardutil.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 
81  if (m_deviceReadBuffer)
82  {
83  if (m_deviceReadBuffer->IsRunning())
84  m_deviceReadBuffer->Stop();
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  {
188  m_containerFormat = formatMPEG2_TS;
189  }
190  else if (kStreamType[i] == "MPEG-2 PS")
191  {
192  m_containerFormat = formatMPEG2_PS;
193  }
194  else
195  {
196  // TODO Expand AVContainer to include other types in
197  // streamType
198  m_containerFormat = formatUnknown;
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.toLower().startsWith("file:"))
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 
394  if (!SetVideoCaptureFormat(m_chanfd))
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 
407  if (!SetV4L2DeviceOptions(m_chanfd))
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  {
429  if (m_deviceReadBuffer->IsRunning())
430  m_deviceReadBuffer->Stop();
431 
432  delete m_deviceReadBuffer;
433  m_deviceReadBuffer = nullptr;
434  }
435 
436  m_deviceReadBuffer = new DeviceReadBuffer(this);
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 = min(qctrl.maximum, 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  .arg(m_driver)
600  .arg(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 = max(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) ? max(m_audBitrateL2, 10) :
651  ((3 == audio_layer) ? m_audBitrateL3 : 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(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, 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  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,
742  GetFilteredAudioSampleRate());
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,
757  streamtype_ivtv_to_v4l2(GetFilteredStreamType()));
758 
759  }
760  else
761  {
762  m_maxBitrate = m_highMpeg4PeakBitrate;
763  m_bitrate = m_highMpeg4AvgBitrate;
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 = max(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
834  if (m_supportsSlicedVbi)
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();
903  return (m_deviceIsMpegFile) ? OpenMpegFileAsInput() : OpenV4L2DeviceAsInput();
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 
931  m_streamData->AddAVListener(this);
932  m_streamData->AddWritingListener(this);
933 
934  // Make sure the first things in the file are a PAT & PMT
935  HandleSingleProgramPAT(m_streamData->PATSingleProgram(), true);
936  HandleSingleProgramPMT(m_streamData->PMTSingleProgram(), true);
937  m_waitForKeyframeOption = true;
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  int dummyBPS = 0; // Bytes per second, but env var is BITS PER SECOND
960 
961  if (getenv("DUMMYBPS"))
962  {
963  dummyBPS = atoi(getenv("DUMMYBPS")) / 8;
964  LOG(VB_GENERAL, LOG_INFO,
965  LOC + QString("Throttling dummy recorder to %1 bits per second")
966  .arg(dummyBPS * 8));
967  }
968 
969  struct timeval tv {};
970  fd_set rdset;
971 
972  if (m_deviceIsMpegFile)
973  elapsedTimer.start();
974  else if (m_deviceReadBuffer)
975  {
976  LOG(VB_RECORD, LOG_INFO, LOC + "Initial startup of recorder");
977  StartEncoding();
978  }
979 
980  QByteArray vdevice = m_videodevice.toLatin1();
981  while (IsRecordingRequested() && !IsErrored())
982  {
983  if (PauseAndWait(100))
984  continue;
985 
986  if (m_deviceIsMpegFile)
987  {
988  if (dummyBPS && bytesRead)
989  {
990  elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
991  while ((bytesRead / elapsed) > dummyBPS)
992  {
993  std::this_thread::sleep_for(std::chrono::milliseconds(50));
994  elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
995  }
996  }
997  else if (GetFramesWritten())
998  {
999  elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
1000  while ((GetFramesWritten() / elapsed) > 30)
1001  {
1002  std::this_thread::sleep_for(std::chrono::milliseconds(50));
1003  elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
1004  }
1005  }
1006  }
1007 
1008  if (m_deviceReadBuffer)
1009  {
1010  len = m_deviceReadBuffer->Read
1011  (&(buffer[remainder]), m_bufferSize - remainder);
1012 
1013  // Check for DRB errors
1014  if (m_deviceReadBuffer->IsErrored())
1015  {
1016  LOG(VB_GENERAL, LOG_ERR, LOC + "Device error detected");
1017 
1018  if (good_data)
1019  {
1020  if (gap)
1021  {
1022  /* Already processing a gap, which means
1023  * restarting the encoding didn't work! */
1024  SetRecordingStatus(RecStatus::Failing, __FILE__, __LINE__);
1025  }
1026  else
1027  gap = true;
1028  }
1029 
1030  if (!RestartEncoding())
1031  SetRecordingStatus(RecStatus::Failing, __FILE__, __LINE__);
1032  }
1033  else if (m_deviceReadBuffer->IsEOF() &&
1034  IsRecordingRequested())
1035  {
1036  LOG(VB_GENERAL, LOG_ERR, LOC + "Device EOF detected");
1037  m_error = "Device EOF detected";
1038  }
1039  else
1040  {
1041  // If we have seen good data, but now have a gap, note it
1042  if (good_data)
1043  {
1044  if (gap)
1045  {
1046  QMutexLocker locker(&m_statisticsLock);
1047  QDateTime gap_end(MythDate::current());
1048 
1049  m_recordingGaps.push_back(RecordingGap
1050  (gap_start, gap_end));
1051  LOG(VB_RECORD, LOG_DEBUG,
1052  LOC + QString("Inserted gap %1 dur %2")
1053  .arg(m_recordingGaps.back().toString())
1054  .arg(gap_start.secsTo(gap_end)));
1055  gap = false;
1056  }
1057  else
1058  gap_start = MythDate::current();
1059  }
1060  else
1061  good_data = true;
1062  }
1063  }
1064  else if (m_readfd < 0)
1065  continue;
1066  else
1067  {
1068  if (has_select)
1069  {
1070  tv.tv_sec = 5;
1071  tv.tv_usec = 0;
1072  FD_ZERO(&rdset); // NOLINT(readability-isolate-declaration)
1073  FD_SET(m_readfd, &rdset);
1074 
1075  switch (select(m_readfd + 1, &rdset, nullptr, nullptr, &tv))
1076  {
1077  case -1:
1078  if (errno == EINTR)
1079  continue;
1080 
1081  LOG(VB_GENERAL, LOG_ERR, LOC + "Select error" + ENO);
1082  continue;
1083 
1084  case 0:
1085  LOG(VB_GENERAL, LOG_ERR, LOC + "select timeout - "
1086  "driver has stopped responding");
1087 
1088  if (close(m_readfd) != 0)
1089  {
1090  LOG(VB_GENERAL, LOG_ERR, LOC + "Close error" + ENO);
1091  }
1092 
1093  // Force card to be reopened on next iteration..
1094  m_readfd = -1;
1095  continue;
1096 
1097  default:
1098  break;
1099  }
1100  }
1101 
1102  len = read(m_readfd, &(buffer[remainder]), m_bufferSize - remainder);
1103 
1104  if (len < 0 && !has_select)
1105  {
1106  QMutexLocker locker(&m_pauseLock);
1107  if (m_requestRecording && !m_requestPause)
1108  m_unpauseWait.wait(&m_pauseLock, 25);
1109  continue;
1110  }
1111 
1112  if ((len == 0) && (m_deviceIsMpegFile))
1113  {
1114  close(m_readfd);
1115  m_readfd = open(vdevice.constData(), O_RDONLY);
1116 
1117  if (m_readfd >= 0)
1118  {
1119  len = read(m_readfd,
1120  &(buffer[remainder]), m_bufferSize - remainder);
1121  }
1122 
1123  if (len <= 0)
1124  {
1125  m_error = "Failed to read from video file";
1126  continue;
1127  }
1128  }
1129  else if (len < 0 && errno != EAGAIN)
1130  {
1131  LOG(VB_GENERAL, LOG_ERR, LOC + QString("error reading from: %1")
1132  .arg(m_videodevice) + ENO);
1133  continue;
1134  }
1135  }
1136 
1137  if (len > 0)
1138  {
1139  bytesRead += len;
1140  len += remainder;
1141 
1142  if (m_driver == "hdpvr")
1143  {
1144  remainder = m_streamData->ProcessData(buffer, len);
1145  int start_remain = len - remainder;
1146  if (remainder && (start_remain >= remainder))
1147  memcpy(buffer, buffer+start_remain, remainder);
1148  else if (remainder)
1149  memmove(buffer, buffer+start_remain, remainder);
1150  }
1151  else
1152  {
1153  FindPSKeyFrames(buffer, len);
1154  }
1155  }
1156  }
1157 
1158  LOG(VB_RECORD, LOG_INFO, LOC + "run finishing up");
1159 
1160  StopEncoding();
1161 
1162  {
1163  QMutexLocker locker(&m_pauseLock);
1164  m_requestHelper = false;
1165  }
1166 
1167  if (m_vbiThread)
1168  {
1169  m_vbiThread->wait();
1170  delete m_vbiThread;
1171  m_vbiThread = nullptr;
1172  CloseVBIDevice();
1173  }
1174 
1175  FinishRecording();
1176 
1177  delete[] buffer;
1178 
1179  if (m_driver == "hdpvr")
1180  {
1181  m_streamData->RemoveWritingListener(this);
1182  m_streamData->RemoveAVListener(this);
1183  SetStreamData(nullptr);
1184  }
1185 
1186  QMutexLocker locker(&m_pauseLock);
1187  m_requestRecording = false;
1188  m_recording = false;
1189  m_recordingWait.wakeAll();
1190 }
1191 
1192 bool MpegRecorder::ProcessTSPacket(const TSPacket &tspacket_real)
1193 {
1194  const uint pid = tspacket_real.PID();
1195 
1196  TSPacket *tspacket_fake = nullptr;
1197  if ((m_driver == "hdpvr") && (pid == 0x1001)) // PCRPID for HD-PVR
1198  {
1199  tspacket_fake = tspacket_real.CreateClone();
1200  uint cc = (m_continuityCounter[pid] == 0xFF) ?
1201  0 : (m_continuityCounter[pid] + 1) & 0xf;
1202  tspacket_fake->SetContinuityCounter(cc);
1203  }
1204 
1205  const TSPacket &tspacket = (tspacket_fake)
1206  ? *tspacket_fake : tspacket_real;
1207 
1208  bool ret = DTVRecorder::ProcessTSPacket(tspacket);
1209 
1210  delete tspacket_fake;
1211 
1212  return ret;
1213 }
1214 
1216 {
1217  LOG(VB_RECORD, LOG_INFO, LOC + "Reset(void)");
1218  ResetForNewFile();
1219 
1220  if (m_h2645Parser != nullptr)
1221  m_h2645Parser->Reset();
1222 
1223  m_startCode = 0xffffffff;
1224 
1225  if (m_curRecording)
1226  {
1227  m_curRecording->ClearPositionMap(MARK_GOP_BYFRAME);
1228  }
1229  if (m_streamData)
1230  m_streamData->Reset(m_streamData->DesiredProgram());
1231 }
1232 
1234 {
1235  QMutexLocker locker(&m_pauseLock);
1236  m_clearTimeOnPause = clear;
1237  m_paused = false;
1238  m_requestPause = true;
1239 }
1240 
1242 {
1243  QMutexLocker locker(&m_pauseLock);
1244  if (m_requestPause)
1245  {
1246  if (!IsPaused(true))
1247  {
1248  LOG(VB_RECORD, LOG_INFO, LOC + "PauseAndWait pause");
1249 
1250  StopEncoding();
1251 
1252  m_paused = true;
1253  m_pauseWait.wakeAll();
1254 
1255  if (m_tvrec)
1256  m_tvrec->RecorderPaused();
1257  }
1258 
1259  m_unpauseWait.wait(&m_pauseLock, timeout);
1260  }
1261 
1262  if (!m_requestPause && IsPaused(true))
1263  {
1264  LOG(VB_RECORD, LOG_INFO, LOC + "PauseAndWait unpause");
1265 
1266  if (m_driver == "hdpvr")
1267  {
1268  // HD-PVR will sometimes reset to defaults
1269  SetV4L2DeviceOptions(m_chanfd);
1270  }
1271 
1272  StartEncoding();
1273 
1274  if (m_streamData)
1275  m_streamData->Reset(m_streamData->DesiredProgram());
1276 
1277  m_paused = false;
1278  }
1279 
1280  return IsPaused(true);
1281 }
1282 
1284 {
1285  LOG(VB_RECORD, LOG_INFO, LOC + "RestartEncoding");
1286 
1287  QMutexLocker locker(&m_startStopEncodingLock);
1288 
1289  StopEncoding();
1290 
1291  // Make sure the next things in the file are a PAT & PMT
1292  if (m_streamData &&
1293  m_streamData->PATSingleProgram() &&
1294  m_streamData->PMTSingleProgram())
1295  {
1296  m_payloadBuffer.clear(); // No reason to keep part of a frame
1297  HandleSingleProgramPAT(m_streamData->PATSingleProgram(), true);
1298  HandleSingleProgramPMT(m_streamData->PMTSingleProgram(), true);
1299  }
1300 
1301  if (m_driver == "hdpvr") // HD-PVR will sometimes reset to defaults
1302  SetV4L2DeviceOptions(m_chanfd);
1303 
1304  return StartEncoding();
1305 }
1306 
1308 {
1309  QMutexLocker locker(&m_startStopEncodingLock);
1310 
1311  LOG(VB_RECORD, LOG_INFO, LOC + "StartEncoding");
1312 
1313  if (m_readfd < 0)
1314  {
1315  m_readfd = open(m_videodevice.toLatin1().constData(), O_RDWR | O_NONBLOCK);
1316  if (m_readfd < 0)
1317  {
1318  LOG(VB_GENERAL, LOG_ERR, LOC +
1319  "StartEncoding: Can't open video device." + ENO);
1320  m_error = "Failed to start recording";
1321  return false;
1322  }
1323  }
1324 
1325  if (m_h2645Parser != nullptr)
1326  m_h2645Parser->Reset();
1327 
1328  bool good_res = true;
1329  if (m_driver == "hdpvr")
1330  {
1331  m_waitForKeyframeOption = true;
1332  m_seenSps = false;
1333  good_res = HandleResolutionChanges();
1334  }
1335 
1336  // (at least) with the 3.10 kernel, the V4L2_ENC_CMD_START does
1337  // not reliably start the data flow from a HD-PVR. A read() seems
1338  // to work, though.
1339 
1340  int idx = 1;
1341  for ( ; idx < 50; ++idx)
1342  {
1343  uint8_t dummy = 0;
1344  int len = read(m_readfd, &dummy, 0);
1345  if (len == 0)
1346  break;
1347  if (idx == 20)
1348  {
1349  LOG(VB_GENERAL, LOG_ERR, LOC +
1350  "StartEncoding: read failing, re-opening device: " + ENO);
1351  close(m_readfd);
1352  std::this_thread::sleep_for(std::chrono::milliseconds(2));
1353  m_readfd = open(m_videodevice.toLatin1().constData(),
1354  O_RDWR | O_NONBLOCK);
1355  if (m_readfd < 0)
1356  {
1357  LOG(VB_GENERAL, LOG_ERR, LOC +
1358  "StartEncoding: Can't open video device." + ENO);
1359  m_error = "Failed to start recording";
1360  return false;
1361  }
1362  }
1363  else
1364  {
1365  LOG(VB_GENERAL, LOG_ERR, LOC +
1366  QString("StartEncoding: read failed, retry in %1 msec:")
1367  .arg(100 * idx) + ENO);
1368  std::this_thread::sleep_for(std::chrono::microseconds(idx * 100));
1369  }
1370  }
1371  if (idx == 50)
1372  {
1373  LOG(VB_GENERAL, LOG_ERR, LOC +
1374  "StartEncoding: read from video device failed." + ENO);
1375  m_error = "Failed to start recording";
1376  close(m_readfd);
1377  m_readfd = -1;
1378  return false;
1379  }
1380  if (idx > 0)
1381  {
1382  LOG(VB_RECORD, LOG_WARNING, LOC +
1383  QString("%1 read attempts required to start encoding").arg(idx));
1384  }
1385 
1386  if (!good_res) // Try again
1387  HandleResolutionChanges();
1388 
1389  if (m_deviceReadBuffer)
1390  {
1391  m_deviceReadBuffer->Reset(m_videodevice.toLatin1().constData(), m_readfd);
1392  m_deviceReadBuffer->SetRequestPause(false);
1393  m_deviceReadBuffer->Start();
1394  }
1395 
1396  return true;
1397 }
1398 
1400 {
1401  QMutexLocker locker(&m_startStopEncodingLock);
1402 
1403  LOG(VB_RECORD, LOG_INFO, LOC + "StopEncoding");
1404 
1405  if (m_readfd < 0)
1406  return;
1407 
1408  struct v4l2_encoder_cmd command {};
1409  command.cmd = V4L2_ENC_CMD_STOP;
1410  command.flags = V4L2_ENC_CMD_STOP_AT_GOP_END;
1411 
1412  if (m_deviceReadBuffer)
1413  m_deviceReadBuffer->SetRequestPause(true);
1414 
1415  bool stopped = 0 == ioctl(m_readfd, VIDIOC_ENCODER_CMD, &command);
1416  if (stopped)
1417  {
1418  LOG(VB_RECORD, LOG_INFO, LOC + "Encoding stopped");
1419  }
1420  else if (errno != ENOTTY && errno != EINVAL)
1421  {
1422  // Some drivers do not support this ioctl at all. It is marked as
1423  // "experimental" in the V4L2 API spec. These drivers return EINVAL
1424  // in older kernels and ENOTTY in 3.1+
1425 
1426  LOG(VB_GENERAL, LOG_WARNING, LOC + "StopEncoding failed" + ENO);
1427  }
1428 
1429  if (m_deviceReadBuffer && m_deviceReadBuffer->IsRunning())
1430  {
1431  // allow last bits of data through..
1432  std::this_thread::sleep_for(std::chrono::milliseconds(20));
1433  m_deviceReadBuffer->Stop();
1434  }
1435 
1436  // close the fd so streamoff/streamon work in V4LChannel
1437  close(m_readfd);
1438  m_readfd = -1;
1439 }
1440 
1442 {
1443  m_streamData->AddMPEGSPListener(this);
1444  m_streamData->SetDesiredProgram(1);
1445 }
1446 
1447 void MpegRecorder::SetBitrate(int bitrate, int maxbitrate,
1448  const QString & reason)
1449 {
1450  if (maxbitrate == bitrate)
1451  {
1452  LOG(VB_RECORD, LOG_INFO, LOC + QString("%1 bitrate %2 kbps CBR")
1453  .arg(reason).arg(bitrate));
1454  }
1455  else
1456  {
1457  LOG(VB_RECORD, LOG_INFO, LOC + QString("%1 bitrate %2/%3 kbps VBR")
1458  .arg(reason).arg(bitrate).arg(maxbitrate));
1459  }
1460 
1461  vector<struct v4l2_ext_control> ext_ctrls;
1462  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
1463  (maxbitrate == bitrate) ?
1464  V4L2_MPEG_VIDEO_BITRATE_MODE_CBR :
1465  V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
1466 
1467  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE,
1468  bitrate * 1000);
1469 
1470  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
1471  maxbitrate * 1000);
1472 
1473  set_ctrls(m_readfd, ext_ctrls);
1474 }
1475 
1477 {
1478  LOG(VB_RECORD, LOG_INFO, LOC + "Checking Resolution");
1479  uint pix = 0;
1480  struct v4l2_format vfmt {};
1481  vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1482 
1483  if (0 == ioctl(m_chanfd, VIDIOC_G_FMT, &vfmt))
1484  {
1485  LOG(VB_RECORD, LOG_INFO, LOC + QString("Got Resolution %1x%2")
1486  .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height));
1487  pix = vfmt.fmt.pix.width * vfmt.fmt.pix.height;
1488  }
1489 
1490  if (!pix)
1491  {
1492  LOG(VB_RECORD, LOG_INFO, LOC + "Giving up detecting resolution: " + ENO);
1493  return false; // nothing to do, we don't have a resolution yet
1494  }
1495 
1496  int old_max = m_maxBitrate;
1497  int old_avg = m_bitrate;
1498  if (pix <= 768*568)
1499  {
1500  m_maxBitrate = m_lowMpeg4PeakBitrate;
1501  m_bitrate = m_lowMpeg4AvgBitrate;
1502  }
1503  else if (pix >= 1920*1080)
1504  {
1505  m_maxBitrate = m_highMpeg4PeakBitrate;
1506  m_bitrate = m_highMpeg4AvgBitrate;
1507  }
1508  else
1509  {
1510  m_maxBitrate = m_mediumMpeg4PeakBitrate;
1511  m_bitrate = m_mediumMpeg4AvgBitrate;
1512  }
1513  m_maxBitrate = std::max(m_maxBitrate, m_bitrate);
1514 
1515  if ((old_max != m_maxBitrate) || (old_avg != m_bitrate))
1516  {
1517  if (old_max == old_avg)
1518  {
1519  LOG(VB_RECORD, LOG_INFO, LOC +
1520  QString("Old bitrate %1 CBR").arg(old_avg));
1521  }
1522  else
1523  {
1524  LOG(VB_RECORD, LOG_INFO,LOC +
1525  QString("Old bitrate %1/%2 VBR") .arg(old_avg).arg(old_max));
1526  }
1527 
1528  SetBitrate(m_bitrate, m_maxBitrate, "New");
1529  }
1530 
1531  return true;
1532 }
1533 
1535 {
1536  LOG(VB_VBI, LOG_INFO, LOC + QString("FormatCC(0x%1,0x%2)")
1537  .arg(code1,0,16).arg(code2,0,16));
1538  // TODO add to CC data vector
1539 
1540  // TODO find video frames in output and insert cc_data
1541  // as CEA-708 user_data packets containing CEA-608 captions
1543 }
MpegRecorder::Pause
void Pause(bool clear=true) override
Pause tells recorder to pause, it should not block.
Definition: mpegrecorder.cpp:1233
VBIThread
Definition: v4lrecorder.h:61
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
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
set_ctrls
static void set_ctrls(int fd, vector< struct v4l2_ext_control > &ext_ctrls)
Definition: mpegrecorder.cpp:684
MpegRecorder::Reset
void Reset(void) override
Reset the recorder to the startup state.
Definition: mpegrecorder.cpp:1215
MythTimer
A QElapsedTimer based timer to replace use of QTime as a timer.
Definition: mythtimer.h:13
discid.disc.read
def read(device=None, features=[])
Definition: disc.py:35
MpegRecorder::StartEncoding
bool StartEncoding(void)
Definition: mpegrecorder.cpp:1307
MpegRecorder::kAspectRatio
static const std::array< const std::string, 4 > kAspectRatio
Definition: mpegrecorder.h:125
MpegRecorder::SetIntOption
void SetIntOption(RecordingProfile *profile, const QString &name)
Definition: mpegrecorder.cpp:322
TSHeader::PID
unsigned int PID(void) const
Definition: tspacket.h:71
cc
Definition: cc.h:9
arg
arg(title).arg(filename).arg(doDelete))
MpegRecorder::GetFilteredAudioLayer
uint GetFilteredAudioLayer(void) const
Definition: mpegrecorder.cpp:629
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:183
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
MpegRecorder::OpenMpegFileAsInput
bool OpenMpegFileAsInput(void)
Definition: mpegrecorder.cpp:337
DeviceReadBuffer
Buffers reads from device files.
Definition: DeviceReadBuffer.h:33
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: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
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
TSHeader::SetContinuityCounter
void SetContinuityCounter(unsigned int cc)
Definition: tspacket.h:148
find_index
static int find_index(const std::array< const int, 14 > &audio_rate, int value)
Definition: mpegrecorder.cpp:92
mythdate.h
MpegRecorder::SetV4L2DeviceOptions
bool SetV4L2DeviceOptions(int chanfd)
Definition: mpegrecorder.cpp:732
programinfo.h
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:2159
MpegRecorder::HandleResolutionChanges
bool HandleResolutionChanges(void)
Definition: mpegrecorder.cpp:1476
TSPacket
Used to access the data of a Transport Stream packet.
Definition: tspacket.h:166
O_NONBLOCK
#define O_NONBLOCK
Definition: mythmedia.cpp:25
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:900
MPEGStreamData
Encapsulates data about MPEG stream and emits events for each table.
Definition: mpegstreamdata.h:85
MpegRecorder::SetRecordingVolume
bool SetRecordingVolume(int chanfd)
Definition: mpegrecorder.cpp:543
clear
static void clear(SettingsMap &cache, SettingsMap &overrides, const QString &myKey)
Definition: mythdb.cpp:846
MpegRecorder::TeardownAll
void TeardownAll(void)
Definition: mpegrecorder.cpp:66
StandardSetting::getValue
virtual QString getValue(void) const
Definition: standardsettings.h:51
DTVRecorder::ProcessTSPacket
bool ProcessTSPacket(const TSPacket &tspacket) override
Definition: dtvrecorder.cpp:1469
uint
unsigned int uint
Definition: compat.h:140
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:57
MpegRecorder::SetVideoCaptureFormat
bool SetVideoCaptureFormat(int chanfd)
Definition: mpegrecorder.cpp:469
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:1241
MpegRecorder::kAudRateL3
static const std::array< const int, 14 > kAudRateL3
Definition: mpegrecorder.h:123
MpegRecorder::GetFilteredStreamType
uint GetFilteredStreamType(void) const
Definition: mpegrecorder.cpp:575
MpegRecorder::GetFilteredAudioSampleRate
uint GetFilteredAudioSampleRate(void) const
Definition: mpegrecorder.cpp:606
mythmediabuffer.h
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:1534
MythTimer::elapsed
int elapsed(void)
Returns milliseconds elapsed since last start() or restart()
Definition: mythtimer.cpp:90
MpegRecorder::InitStreamData
void InitStreamData(void) override
Definition: mpegrecorder.cpp:1441
MpegRecorder::StopEncoding
void StopEncoding(void)
Definition: mpegrecorder.cpp:1399
MpegRecorder::SetBitrate
void SetBitrate(int bitrate, int maxbitrate, const QString &reason)
Definition: mpegrecorder.cpp:1447
RecordingGap
Definition: recordingquality.h:14
MpegRecorder::GetFilteredAudioBitRate
uint GetFilteredAudioBitRate(uint audio_layer) const
Definition: mpegrecorder.cpp:648
add_ext_ctrl
static void add_ext_ctrl(vector< struct v4l2_ext_control > &ctrl_list, uint32_t id, int32_t value)
Definition: mpegrecorder.cpp:675
mythcorecontext.h
cardutil.h
MARK_GOP_BYFRAME
@ MARK_GOP_BYFRAME
Definition: programtypes.h:64
mpegrecorder.h
MpegRecorder::kAudRateL2
static const std::array< const int, 14 > kAudRateL2
Definition: mpegrecorder.h:122
MpegRecorder::SetVBIOptions
bool SetVBIOptions(int chanfd)
Definition: mpegrecorder.cpp:825
MpegRecorder::kAudRateL1
static const std::array< const int, 14 > kAudRateL1
Definition: mpegrecorder.h:121
tv_rec.h
MpegRecorder::SetStrOption
void SetStrOption(RecordingProfile *profile, const QString &name)
Definition: mpegrecorder.cpp:330
StandardSetting
Definition: standardsettings.h:29
recordingprofile.h
RecordingProfile
Definition: recordingprofile.h:39
streamtype_ivtv_to_v4l2
static int streamtype_ivtv_to_v4l2(int st)
Definition: mpegrecorder.cpp:654
MpegRecorder::RestartEncoding
bool RestartEncoding(void)
Definition: mpegrecorder.cpp:1283
formatMPEG2_PS
@ formatMPEG2_PS
Definition: recordingfile.h:17
formatMPEG2_TS
@ formatMPEG2_TS
Definition: recordingfile.h:16
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:916
TSPacket::kSize
static constexpr unsigned int kSize
Definition: tspacket.h:220
MpegRecorder::ProcessTSPacket
bool ProcessTSPacket(const TSPacket &tspacket) override
Definition: mpegrecorder.cpp:1192