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