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