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::s_audRateL1[] =
46 {
47  32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0
48 };
49 
50 const int MpegRecorder::s_audRateL2[] =
51 {
52  32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0
53 };
54 
55 const int MpegRecorder::s_audRateL3[] =
56 {
57  32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0
58 };
59 
60 const char* MpegRecorder::s_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::s_aspectRatio[] =
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_device_read_buffer)
89  {
90  if (m_device_read_buffer->IsRunning())
91  m_device_read_buffer->Stop();
92 
93  delete m_device_read_buffer;
94  m_device_read_buffer = 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(s_audRateL1, 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(s_audRateL2, 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(s_audRateL3, 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_low_mpeg4avgbitrate = value;
161  else if (opt.startsWith("medium"))
162  m_medium_mpeg4avgbitrate = value;
163  else if (opt.startsWith("high"))
164  m_high_mpeg4avgbitrate = value;
165  else
166  V4LRecorder::SetOption(opt, value);
167  }
168  else if (opt.endsWith("_mpeg4peakbitrate"))
169  {
170  if (opt.startsWith("low"))
171  m_low_mpeg4peakbitrate = value;
172  else if (opt.startsWith("medium"))
173  m_medium_mpeg4peakbitrate = value;
174  else if (opt.startsWith("high"))
175  m_high_mpeg4peakbitrate = 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(s_streamType) / sizeof(char*); i++)
189  {
190  if (QString(s_streamType[i]) == value)
191  {
192  if (QString(s_streamType[i]) == "MPEG-2 TS")
193  {
194  m_containerFormat = formatMPEG2_TS;
195  }
196  else if (QString(s_streamType[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; s_aspectRatio[i] != nullptr; i++)
232  {
233  if (QString(s_aspectRatio[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_start_stop_encoding_lock);
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, supports_audio = false;
376  uint32_t capabilities = 0;
377  if (CardUtil::GetV4LInfo(m_chanfd, m_card, m_driver, m_version, capabilities))
378  {
379  m_supports_sliced_vbi = ((capabilities & V4L2_CAP_SLICED_VBI_CAPTURE) != 0U);
380  supports_tuner = ((capabilities & V4L2_CAP_TUNER) != 0U);
381  supports_audio = ((capabilities & V4L2_CAP_AUDIO) != 0U);
383  if (m_driver == "hdpvr")
384  {
385  m_bufferSize = 1500 * TSPacket::kSize;
386  m_h264_parser.use_I_forKeyframes(false);
387  }
388  }
389 
390  if (!(capabilities & V4L2_CAP_VIDEO_CAPTURE))
391  {
392  LOG(VB_GENERAL, LOG_ERR, LOC + "V4L version 1, unsupported");
393  m_error = LOC + "V4L version 1, unsupported";
394  close(m_chanfd);
395  m_chanfd = -1;
396  return false;
397  }
398 
399  if (!SetVideoCaptureFormat(m_chanfd))
400  {
401  close(m_chanfd);
402  m_chanfd = -1;
403  return false;
404  }
405 
406  if (supports_tuner)
407  SetLanguageMode(m_chanfd); // we don't care if this fails...
408 
409  if (supports_audio)
410  SetRecordingVolume(m_chanfd); // we don't care if this fails...
411 
412  if (!SetV4L2DeviceOptions(m_chanfd))
413  {
414  close(m_chanfd);
415  m_chanfd = -1;
416  return false;
417  }
418 
419  SetVBIOptions(m_chanfd); // we don't care if this fails...
420 
421  m_readfd = open(vdevice.constData(), O_RDWR | O_NONBLOCK);
422 
423  if (m_readfd < 0)
424  {
425  LOG(VB_GENERAL, LOG_ERR, LOC + "Can't open video device." + ENO);
426  m_error = LOC + "Can't open video device." + ENO;
427  close(m_chanfd);
428  m_chanfd = -1;
429  return false;
430  }
431 
432  if (m_device_read_buffer)
433  {
434  if (m_device_read_buffer->IsRunning())
435  m_device_read_buffer->Stop();
436 
437  delete m_device_read_buffer;
438  m_device_read_buffer = nullptr;
439  }
440 
441  m_device_read_buffer = new DeviceReadBuffer(this);
442 
443  if (!m_device_read_buffer)
444  {
445  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to allocate DRB buffer");
446  m_error = "Failed to allocate DRB buffer";
447  close(m_chanfd);
448  m_chanfd = -1;
449  close(m_readfd);
450  m_readfd = -1;
451  return false;
452  }
453 
454  if (!m_device_read_buffer->Setup(vdevice.constData(), m_readfd))
455  {
456  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to setup DRB buffer");
457  m_error = "Failed to setup DRB buffer";
458  close(m_chanfd);
459  m_chanfd = -1;
460  close(m_readfd);
461  m_readfd = -1;
462  return false;
463  }
464 
465  LOG(VB_RECORD, LOG_INFO, LOC + "DRB ready");
466 
467  if (m_vbi_fd >= 0)
468  m_vbi_thread = new VBIThread(this);
469 
470  return true;
471 }
472 
473 
475 {
476  if (m_driver == "hdpvr")
477  return true;
478 
479  struct v4l2_format vfmt {};
480 
481  vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
482 
483  if (ioctl(chanfd, VIDIOC_G_FMT, &vfmt) < 0)
484  {
485  LOG(VB_GENERAL, LOG_ERR, LOC + "Error getting format" + ENO);
486  m_error = LOC + "Error getting format" + ENO;
487  return false;
488  }
489 
490  vfmt.fmt.pix.width = m_width;
491  vfmt.fmt.pix.height = m_height;
492 
493  if (ioctl(chanfd, VIDIOC_S_FMT, &vfmt) < 0)
494  {
495  LOG(VB_GENERAL, LOG_ERR, LOC + "Error setting format" + ENO);
496  m_error = LOC + "Error setting format" + ENO;
497  return false;
498  }
499 
500  return true;
501 }
502 
505 {
506  struct v4l2_tuner vt {};
507  if (ioctl(chanfd, VIDIOC_G_TUNER, &vt) < 0)
508  {
509  LOG(VB_GENERAL, LOG_WARNING, LOC + "Unable to get audio mode" + ENO);
510  return false;
511  }
512 
513  switch (m_language)
514  {
515  case 0:
516  vt.audmode = V4L2_TUNER_MODE_LANG1;
517  break;
518  case 1:
519  vt.audmode = V4L2_TUNER_MODE_LANG2;
520  break;
521  case 2:
522  vt.audmode = V4L2_TUNER_MODE_LANG1_LANG2;
523  break;
524  default:
525  vt.audmode = V4L2_TUNER_MODE_LANG1;
526  }
527 
528  int audio_layer = GetFilteredAudioLayer();
529  bool success = true;
530  if ((2 == m_language) && (1 == audio_layer))
531  {
532  LOG(VB_GENERAL, LOG_WARNING,
533  "Dual audio mode incompatible with Layer I audio."
534  "\n\t\t\tFalling back to Main Language");
535  vt.audmode = V4L2_TUNER_MODE_LANG1;
536  success = false;
537  }
538 
539  if (ioctl(chanfd, VIDIOC_S_TUNER, &vt) < 0)
540  {
541  LOG(VB_GENERAL, LOG_WARNING, LOC + "Unable to set audio mode" + ENO);
542  success = false;
543  }
544 
545  return success;
546 }
547 
549 {
550  // Get volume min/max values
551  struct v4l2_queryctrl qctrl {};
552  qctrl.id = V4L2_CID_AUDIO_VOLUME;
553  if ((ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl) < 0) ||
554  (qctrl.flags & V4L2_CTRL_FLAG_DISABLED))
555  {
556  LOG(VB_CHANNEL, LOG_WARNING,
557  LOC + "Audio volume control not supported.");
558  return false;
559  }
560 
561  // calculate volume in card units.
562  int range = qctrl.maximum - qctrl.minimum;
563  int value = (int) ((range * m_audvolume * 0.01F) + qctrl.minimum);
564  int ctrl_volume = min(qctrl.maximum, max(qctrl.minimum, value));
565 
566  // Set recording volume
567  struct v4l2_control ctrl {V4L2_CID_AUDIO_VOLUME, ctrl_volume};
568 
569  if (ioctl(chanfd, VIDIOC_S_CTRL, &ctrl) < 0)
570  {
571  LOG(VB_GENERAL, LOG_WARNING, LOC +
572  "Unable to set recording volume" + ENO + "\n\t\t\t" +
573  "If you are using an AverMedia M179 card this is normal.");
574  return false;
575  }
576 
577  return true;
578 }
579 
581 {
582  uint st = (uint) m_streamtype;
583 
584  if (m_driver == "ivtv")
585  {
586  switch (st)
587  {
588  case 2: st = 2; break;
589  case 10:
590  case 13:
591  case 14: st = 10; break;
592  case 11: st = 11; break;
593  case 12: st = 12; break;
594  default: st = 0; break;
595  }
596  }
597 
598  if (st != (uint) m_streamtype)
599  {
600  LOG(VB_GENERAL, LOG_WARNING, LOC +
601  QString("Stream type '%1'\n\t\t\t"
602  "is not supported by %2 driver, using '%3' instead.")
603  .arg(s_streamType[m_streamtype]).arg(m_driver).arg(s_streamType[st]));
604  }
605 
606  return st;
607 }
608 
610 {
611  uint sr = (uint) m_audsamplerate;
612 
613  sr = (m_driver == "ivtv") ? 48000 : sr; // only 48kHz works properly.
614 
615  if (sr != (uint) m_audsamplerate)
616  {
617  LOG(VB_GENERAL, LOG_WARNING, LOC +
618  QString("Audio sample rate %1 Hz\n\t\t\t"
619  "is not supported by %2 driver, using %3 Hz instead.")
620  .arg(m_audsamplerate).arg(m_driver).arg(sr));
621  }
622 
623  switch (sr)
624  {
625  case 32000: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000;
626  case 44100: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100;
627  case 48000: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
628  default: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
629  }
630 }
631 
633 {
634  uint layer = (uint) m_audtype;
635 
636  layer = max(min(layer, 3U), 1U);
637 
638  layer = (m_driver == "ivtv") ? 2 : layer;
639 
640  if (layer != (uint) m_audtype)
641  {
642  LOG(VB_GENERAL, LOG_WARNING, LOC +
643  QString("MPEG layer %1 does not work properly\n\t\t\t"
644  "with %2 driver. Using MPEG layer %3 audio instead.")
645  .arg(m_audtype).arg(m_driver).arg(layer));
646  }
647 
648  return layer;
649 }
650 
652 {
653  return ((2 == audio_layer) ? max(m_audbitratel2, 10) :
654  ((3 == audio_layer) ? m_audbitratel3 : max(m_audbitratel1, 6)));
655 }
656 
657 static int streamtype_ivtv_to_v4l2(int st)
658 {
659  switch (st)
660  {
661  case 0: return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
662  case 1: return V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
663  case 2: return V4L2_MPEG_STREAM_TYPE_MPEG1_VCD;
664  case 3: return V4L2_MPEG_STREAM_TYPE_MPEG2_PS; /* PES A/V */
665  case 5: return V4L2_MPEG_STREAM_TYPE_MPEG2_PS; /* PES V */
666  case 7: return V4L2_MPEG_STREAM_TYPE_MPEG2_PS; /* PES A */
667  case 10: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD;
668  case 11: return V4L2_MPEG_STREAM_TYPE_MPEG1_VCD; /* VCD */
669  case 12: return V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD;
670  case 13: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD; /* DVD-Special 1 */
671  case 14: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD; /* DVD-Special 2 */
672  default: return V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
673  }
674 }
675 
676 static void add_ext_ctrl(vector<struct v4l2_ext_control> &ctrl_list,
677  uint32_t id, int32_t value)
678 {
679  struct v4l2_ext_control tmp_ctrl {};
680  tmp_ctrl.id = id;
681  tmp_ctrl.value = value;
682  ctrl_list.push_back(tmp_ctrl);
683 }
684 
685 static void set_ctrls(int fd, vector<struct v4l2_ext_control> &ext_ctrls)
686 {
687  static QMutex control_description_lock;
688  static QMap<uint32_t,QString> control_description;
689 
690  control_description_lock.lock();
691  if (control_description.isEmpty())
692  {
693  control_description[V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ] =
694  "Audio Sampling Frequency";
695  control_description[V4L2_CID_MPEG_VIDEO_ASPECT] =
696  "Video Aspect ratio";
697  control_description[V4L2_CID_MPEG_AUDIO_ENCODING] =
698  "Audio Encoding";
699  control_description[V4L2_CID_MPEG_AUDIO_L2_BITRATE] =
700  "Audio L2 Bitrate";
701  control_description[V4L2_CID_MPEG_VIDEO_BITRATE_PEAK] =
702  "Video Peak Bitrate";
703  control_description[V4L2_CID_MPEG_VIDEO_BITRATE] =
704  "Video Average Bitrate";
705  control_description[V4L2_CID_MPEG_STREAM_TYPE] =
706  "MPEG Stream type";
707  control_description[V4L2_CID_MPEG_VIDEO_BITRATE_MODE] =
708  "MPEG Bitrate mode";
709  }
710  control_description_lock.unlock();
711 
712  for (size_t i = 0; i < ext_ctrls.size(); i++)
713  {
714  struct v4l2_ext_controls ctrls {};
715 
716  int value = ext_ctrls[i].value;
717 
718  ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
719  ctrls.count = 1;
720  ctrls.controls = &ext_ctrls[i];
721 
722  if (ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
723  {
724  QMutexLocker locker(&control_description_lock);
725  LOG(VB_GENERAL, LOG_ERR, QString("mpegrecorder.cpp:set_ctrls(): ") +
726  QString("Could not set %1 to %2")
727  .arg(control_description[ext_ctrls[i].id]).arg(value) +
728  ENO);
729  }
730  }
731 }
732 
734 {
735  vector<struct v4l2_ext_control> ext_ctrls;
736 
737  // Set controls
738  if (m_driver != "hdpvr")
739  {
740  if (!m_driver.startsWith("saa7164"))
741  {
742  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
743  GetFilteredAudioSampleRate());
744 
745  uint audio_layer = GetFilteredAudioLayer();
746  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_ENCODING,
747  audio_layer - 1);
748 
749  uint audbitrate = GetFilteredAudioBitRate(audio_layer);
750  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_L2_BITRATE,
751  audbitrate - 1);
752  }
753 
754  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_ASPECT,
755  m_aspectratio - 1);
756 
757  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_STREAM_TYPE,
758  streamtype_ivtv_to_v4l2(GetFilteredStreamType()));
759 
760  }
761  else
762  {
763  m_maxbitrate = m_high_mpeg4peakbitrate;
764  m_bitrate = m_high_mpeg4avgbitrate;
765  }
766  m_maxbitrate = std::max(m_maxbitrate, m_bitrate);
767 
768  if (m_driver == "hdpvr" || m_driver.startsWith("saa7164"))
769  {
770  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
771  (m_maxbitrate == m_bitrate) ?
772  V4L2_MPEG_VIDEO_BITRATE_MODE_CBR :
773  V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
774  }
775 
776  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE,
777  m_bitrate * 1000);
778 
779  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
780  m_maxbitrate * 1000);
781 
782  set_ctrls(chanfd, ext_ctrls);
783 
784  bool ok;
785  int audioinput = m_audiodevice.toUInt(&ok);
786  if (ok)
787  {
788  struct v4l2_audio ain {};
789  ain.index = audioinput;
790  if (ioctl(chanfd, VIDIOC_ENUMAUDIO, &ain) < 0)
791  {
792  LOG(VB_GENERAL, LOG_WARNING, LOC + "Unable to get audio input.");
793  }
794  else
795  {
796  ain.index = audioinput;
797  if (ioctl(chanfd, VIDIOC_S_AUDIO, &ain) < 0)
798  {
799  LOG(VB_GENERAL, LOG_WARNING,
800  LOC + "Unable to set audio input.");
801  }
802  }
803  }
804 
805  // query supported audio codecs if spdif is not used
806  if (m_driver == "hdpvr" && audioinput != 2)
807  {
808  struct v4l2_queryctrl qctrl {};
809  qctrl.id = V4L2_CID_MPEG_AUDIO_ENCODING;
810 
811  if (!ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl))
812  {
813  uint audio_enc = max(min(m_audtype-1, qctrl.maximum), qctrl.minimum);
814  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_ENCODING, audio_enc);
815  }
816  else
817  {
818  LOG(VB_GENERAL, LOG_WARNING, LOC +
819  "Unable to get supported audio codecs." + ENO);
820  }
821  }
822 
823  return true;
824 }
825 
827 {
828  if (VBIMode::None == m_vbimode)
829  return true;
830 
831  if (m_driver == "hdpvr")
832  return true;
833 
834 #ifdef V4L2_CAP_SLICED_VBI_CAPTURE
835  if (m_supports_sliced_vbi)
836  {
837  int fd;
838 
839  if (OpenVBIDevice() >= 0)
840  fd = m_vbi_fd;
841  else
842  fd = chanfd;
843 
844  struct v4l2_format vbifmt {};
845  vbifmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
846  vbifmt.fmt.sliced.service_set |= (VBIMode::PAL_TT == m_vbimode) ?
847  V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
848 
849  if (ioctl(fd, VIDIOC_S_FMT, &vbifmt) < 0)
850  {
851  if (m_vbi_fd >= 0)
852  {
853  fd = chanfd; // Retry with video device instead
854  if (ioctl(fd, VIDIOC_S_FMT, &vbifmt) < 0)
855  {
856  LOG(VB_GENERAL, LOG_WARNING, LOC +
857  "Unable to enable VBI embedding (/dev/vbiX)" + ENO);
858  return false;
859  }
860  }
861  else
862  {
863  LOG(VB_GENERAL, LOG_WARNING, LOC +
864  "Unable to enable VBI embedding (/dev/videoX)" + ENO);
865  return false;
866  }
867  }
868 
869  if (ioctl(fd, VIDIOC_G_FMT, &vbifmt) >= 0)
870  {
871  LOG(VB_RECORD, LOG_INFO,
872  LOC + QString("VBI service: %1, io size: %2")
873  .arg(vbifmt.fmt.sliced.service_set)
874  .arg(vbifmt.fmt.sliced.io_size));
875 
876  struct v4l2_ext_control vbi_ctrl {};
877  vbi_ctrl.id = V4L2_CID_MPEG_STREAM_VBI_FMT;
878  vbi_ctrl.value = V4L2_MPEG_STREAM_VBI_FMT_IVTV;
879 
880  struct v4l2_ext_controls ctrls {};
881  ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
882  ctrls.count = 1;
883  ctrls.controls = &vbi_ctrl;
884 
885  if (ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
886  {
887  LOG(VB_GENERAL, LOG_WARNING, LOC +
888  "Unable to set VBI embedding format" + ENO);
889  }
890  else
891  {
892  return true;
893  }
894  }
895  }
896 #endif // V4L2_CAP_SLICED_VBI_CAPTURE
897 
898  return OpenVBIDevice() >= 0;
899 }
900 
902 {
903  ResetForNewFile();
904  return (m_deviceIsMpegFile) ? OpenMpegFileAsInput() : OpenV4L2DeviceAsInput();
905 }
906 
908 {
909  if (!Open())
910  {
911  if (m_error.isEmpty())
912  m_error = "Failed to open V4L device";
913  return;
914  }
915 
916  bool has_select = true;
917 
918 #if defined(__FreeBSD__)
919  // HACK. FreeBSD PVR150/500 driver doesn't currently support select()
920  has_select = false;
921 #endif
922 
923  if (m_driver == "hdpvr")
924  {
925  int progNum = 1;
927  (progNum, m_tvrec ? m_tvrec->GetInputId() : -1,
928  true);
929  sd->SetRecordingType(m_recording_type);
930  SetStreamData(sd);
931 
932  m_stream_data->AddAVListener(this);
933  m_stream_data->AddWritingListener(this);
934 
935  // Make sure the first things in the file are a PAT & PMT
936  HandleSingleProgramPAT(m_stream_data->PATSingleProgram(), true);
937  HandleSingleProgramPMT(m_stream_data->PMTSingleProgram(), true);
938  m_wait_for_keyframe_option = true;
939  }
940 
941  {
942  QMutexLocker locker(&m_pauseLock);
943  m_request_recording = true;
944  m_request_helper = true;
945  m_recording = true;
946  m_recordingWait.wakeAll();
947  }
948 
949  unsigned char *buffer = new unsigned char[m_bufferSize + 1];
950  int len;
951  int remainder = 0;
952 
953  bool good_data = false;
954  bool gap = false;
955  QDateTime gap_start;
956 
957  MythTimer elapsedTimer;
958  float elapsed;
959  long long bytesRead = 0;
960  int dummyBPS = 0; // Bytes per second, but env var is BITS PER SECOND
961 
962  if (getenv("DUMMYBPS"))
963  {
964  dummyBPS = atoi(getenv("DUMMYBPS")) / 8;
965  LOG(VB_GENERAL, LOG_INFO,
966  LOC + QString("Throttling dummy recorder to %1 bits per second")
967  .arg(dummyBPS * 8));
968  }
969 
970  struct timeval tv {};
971  fd_set rdset;
972 
973  if (m_deviceIsMpegFile)
974  elapsedTimer.start();
975  else if (m_device_read_buffer)
976  {
977  LOG(VB_RECORD, LOG_INFO, LOC + "Initial startup of recorder");
978  StartEncoding();
979  }
980 
981  QByteArray vdevice = m_videodevice.toLatin1();
982  while (IsRecordingRequested() && !IsErrored())
983  {
984  if (PauseAndWait(100))
985  continue;
986 
987  if (m_deviceIsMpegFile)
988  {
989  if (dummyBPS && bytesRead)
990  {
991  elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
992  while ((bytesRead / elapsed) > dummyBPS)
993  {
994  std::this_thread::sleep_for(std::chrono::milliseconds(50));
995  elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
996  }
997  }
998  else if (GetFramesWritten())
999  {
1000  elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
1001  while ((GetFramesWritten() / elapsed) > 30)
1002  {
1003  std::this_thread::sleep_for(std::chrono::milliseconds(50));
1004  elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
1005  }
1006  }
1007  }
1008 
1009  if (m_device_read_buffer)
1010  {
1011  len = m_device_read_buffer->Read
1012  (&(buffer[remainder]), m_bufferSize - remainder);
1013 
1014  // Check for DRB errors
1015  if (m_device_read_buffer->IsErrored())
1016  {
1017  LOG(VB_GENERAL, LOG_ERR, LOC + "Device error detected");
1018 
1019  if (good_data)
1020  {
1021  if (gap)
1022  {
1023  /* Already processing a gap, which means
1024  * restarting the encoding didn't work! */
1025  SetRecordingStatus(RecStatus::Failing, __FILE__, __LINE__);
1026  }
1027  else
1028  gap = true;
1029  }
1030 
1031  if (!RestartEncoding())
1032  SetRecordingStatus(RecStatus::Failing, __FILE__, __LINE__);
1033  }
1034  else if (m_device_read_buffer->IsEOF() &&
1035  IsRecordingRequested())
1036  {
1037  LOG(VB_GENERAL, LOG_ERR, LOC + "Device EOF detected");
1038  m_error = "Device EOF detected";
1039  }
1040  else
1041  {
1042  // If we have seen good data, but now have a gap, note it
1043  if (good_data)
1044  {
1045  if (gap)
1046  {
1047  QMutexLocker locker(&m_statisticsLock);
1048  QDateTime gap_end(MythDate::current());
1049 
1050  m_recordingGaps.push_back(RecordingGap
1051  (gap_start, gap_end));
1052  LOG(VB_RECORD, LOG_DEBUG,
1053  LOC + QString("Inserted gap %1 dur %2")
1054  .arg(m_recordingGaps.back().toString())
1055  .arg(gap_start.secsTo(gap_end)));
1056  gap = false;
1057  }
1058  else
1059  gap_start = MythDate::current();
1060  }
1061  else
1062  good_data = true;
1063  }
1064  }
1065  else if (m_readfd < 0)
1066  continue;
1067  else
1068  {
1069  if (has_select)
1070  {
1071  tv.tv_sec = 5;
1072  tv.tv_usec = 0;
1073  FD_ZERO(&rdset);
1074  FD_SET(m_readfd, &rdset);
1075 
1076  switch (select(m_readfd + 1, &rdset, nullptr, nullptr, &tv))
1077  {
1078  case -1:
1079  if (errno == EINTR)
1080  continue;
1081 
1082  LOG(VB_GENERAL, LOG_ERR, LOC + "Select error" + ENO);
1083  continue;
1084 
1085  case 0:
1086  LOG(VB_GENERAL, LOG_ERR, LOC + "select timeout - "
1087  "driver has stopped responding");
1088 
1089  if (close(m_readfd) != 0)
1090  {
1091  LOG(VB_GENERAL, LOG_ERR, LOC + "Close error" + ENO);
1092  }
1093 
1094  // Force card to be reopened on next iteration..
1095  m_readfd = -1;
1096  continue;
1097 
1098  default:
1099  break;
1100  }
1101  }
1102 
1103  len = read(m_readfd, &(buffer[remainder]), m_bufferSize - remainder);
1104 
1105  if (len < 0 && !has_select)
1106  {
1107  QMutexLocker locker(&m_pauseLock);
1108  if (m_request_recording && !m_request_pause)
1109  m_unpauseWait.wait(&m_pauseLock, 25);
1110  continue;
1111  }
1112 
1113  if ((len == 0) && (m_deviceIsMpegFile))
1114  {
1115  close(m_readfd);
1116  m_readfd = open(vdevice.constData(), O_RDONLY);
1117 
1118  if (m_readfd >= 0)
1119  {
1120  len = read(m_readfd,
1121  &(buffer[remainder]), m_bufferSize - remainder);
1122  }
1123 
1124  if (len <= 0)
1125  {
1126  m_error = "Failed to read from video file";
1127  continue;
1128  }
1129  }
1130  else if (len < 0 && errno != EAGAIN)
1131  {
1132  LOG(VB_GENERAL, LOG_ERR, LOC + QString("error reading from: %1")
1133  .arg(m_videodevice) + ENO);
1134  continue;
1135  }
1136  }
1137 
1138  if (len > 0)
1139  {
1140  bytesRead += len;
1141  len += remainder;
1142 
1143  if (m_driver == "hdpvr")
1144  {
1145  remainder = m_stream_data->ProcessData(buffer, len);
1146  int start_remain = len - remainder;
1147  if (remainder && (start_remain >= remainder))
1148  memcpy(buffer, buffer+start_remain, remainder);
1149  else if (remainder)
1150  memmove(buffer, buffer+start_remain, remainder);
1151  }
1152  else
1153  {
1154  FindPSKeyFrames(buffer, len);
1155  }
1156  }
1157  }
1158 
1159  LOG(VB_RECORD, LOG_INFO, LOC + "run finishing up");
1160 
1161  StopEncoding();
1162 
1163  {
1164  QMutexLocker locker(&m_pauseLock);
1165  m_request_helper = false;
1166  }
1167 
1168  if (m_vbi_thread)
1169  {
1170  m_vbi_thread->wait();
1171  delete m_vbi_thread;
1172  m_vbi_thread = nullptr;
1173  CloseVBIDevice();
1174  }
1175 
1176  FinishRecording();
1177 
1178  delete[] buffer;
1179 
1180  if (m_driver == "hdpvr")
1181  {
1182  m_stream_data->RemoveWritingListener(this);
1183  m_stream_data->RemoveAVListener(this);
1184  SetStreamData(nullptr);
1185  }
1186 
1187  QMutexLocker locker(&m_pauseLock);
1188  m_request_recording = false;
1189  m_recording = false;
1190  m_recordingWait.wakeAll();
1191 }
1192 
1193 bool MpegRecorder::ProcessTSPacket(const TSPacket &tspacket_real)
1194 {
1195  const uint pid = tspacket_real.PID();
1196 
1197  TSPacket *tspacket_fake = nullptr;
1198  if ((m_driver == "hdpvr") && (pid == 0x1001)) // PCRPID for HD-PVR
1199  {
1200  tspacket_fake = tspacket_real.CreateClone();
1201  uint cc = (m_continuity_counter[pid] == 0xFF) ?
1202  0 : (m_continuity_counter[pid] + 1) & 0xf;
1203  tspacket_fake->SetContinuityCounter(cc);
1204  }
1205 
1206  const TSPacket &tspacket = (tspacket_fake)
1207  ? *tspacket_fake : tspacket_real;
1208 
1209  bool ret = DTVRecorder::ProcessTSPacket(tspacket);
1210 
1211  delete tspacket_fake;
1212 
1213  return ret;
1214 }
1215 
1217 {
1218  LOG(VB_RECORD, LOG_INFO, LOC + "Reset(void)");
1219  ResetForNewFile();
1220 
1221  m_start_code = 0xffffffff;
1222 
1223  if (m_curRecording)
1224  {
1225  m_curRecording->ClearPositionMap(MARK_GOP_BYFRAME);
1226  }
1227  if (m_stream_data)
1228  m_stream_data->Reset(m_stream_data->DesiredProgram());
1229 }
1230 
1232 {
1233  QMutexLocker locker(&m_pauseLock);
1234  m_cleartimeonpause = clear;
1235  m_paused = false;
1236  m_request_pause = true;
1237 }
1238 
1240 {
1241  QMutexLocker locker(&m_pauseLock);
1242  if (m_request_pause)
1243  {
1244  if (!IsPaused(true))
1245  {
1246  LOG(VB_RECORD, LOG_INFO, LOC + "PauseAndWait pause");
1247 
1248  StopEncoding();
1249 
1250  m_paused = true;
1251  m_pauseWait.wakeAll();
1252 
1253  if (m_tvrec)
1254  m_tvrec->RecorderPaused();
1255  }
1256 
1257  m_unpauseWait.wait(&m_pauseLock, timeout);
1258  }
1259 
1260  if (!m_request_pause && IsPaused(true))
1261  {
1262  LOG(VB_RECORD, LOG_INFO, LOC + "PauseAndWait unpause");
1263 
1264  if (m_driver == "hdpvr")
1265  {
1266  m_h264_parser.Reset();
1267  m_wait_for_keyframe_option = true;
1268  m_seen_sps = false;
1269  // HD-PVR will sometimes reset to defaults
1270  SetV4L2DeviceOptions(m_chanfd);
1271  }
1272 
1273  StartEncoding();
1274 
1275  if (m_stream_data)
1276  m_stream_data->Reset(m_stream_data->DesiredProgram());
1277 
1278  m_paused = false;
1279  }
1280 
1281  return IsPaused(true);
1282 }
1283 
1285 {
1286  LOG(VB_RECORD, LOG_INFO, LOC + "RestartEncoding");
1287 
1288  QMutexLocker locker(&m_start_stop_encoding_lock);
1289 
1290  StopEncoding();
1291 
1292  // Make sure the next things in the file are a PAT & PMT
1293  if (m_stream_data &&
1294  m_stream_data->PATSingleProgram() &&
1295  m_stream_data->PMTSingleProgram())
1296  {
1297  m_payload_buffer.clear(); // No reason to keep part of a frame
1298  HandleSingleProgramPAT(m_stream_data->PATSingleProgram(), true);
1299  HandleSingleProgramPMT(m_stream_data->PMTSingleProgram(), true);
1300  }
1301 
1302  if (m_driver == "hdpvr") // HD-PVR will sometimes reset to defaults
1303  SetV4L2DeviceOptions(m_chanfd);
1304 
1305  return StartEncoding();
1306 }
1307 
1309 {
1310  QMutexLocker locker(&m_start_stop_encoding_lock);
1311 
1312  LOG(VB_RECORD, LOG_INFO, LOC + "StartEncoding");
1313 
1314  if (m_readfd < 0)
1315  {
1316  m_readfd = open(m_videodevice.toLatin1().constData(), O_RDWR | O_NONBLOCK);
1317  if (m_readfd < 0)
1318  {
1319  LOG(VB_GENERAL, LOG_ERR, LOC +
1320  "StartEncoding: Can't open video device." + ENO);
1321  m_error = "Failed to start recording";
1322  return false;
1323  }
1324  }
1325 
1326  bool good_res = true;
1327  if (m_driver == "hdpvr")
1328  {
1329  m_h264_parser.Reset();
1330  m_wait_for_keyframe_option = true;
1331  m_seen_sps = false;
1332  good_res = HandleResolutionChanges();
1333  }
1334 
1335  // (at least) with the 3.10 kernel, the V4L2_ENC_CMD_START does
1336  // not reliably start the data flow from a HD-PVR. A read() seems
1337  // to work, though.
1338 
1339  int idx = 1;
1340  for ( ; idx < 50; ++idx)
1341  {
1342  uint8_t dummy;
1343  int len = read(m_readfd, &dummy, 0);
1344  if (len == 0)
1345  break;
1346  if (idx == 20)
1347  {
1348  LOG(VB_GENERAL, LOG_ERR, LOC +
1349  "StartEncoding: read failing, re-opening device: " + ENO);
1350  close(m_readfd);
1351  std::this_thread::sleep_for(std::chrono::milliseconds(2));
1352  m_readfd = open(m_videodevice.toLatin1().constData(),
1353  O_RDWR | O_NONBLOCK);
1354  if (m_readfd < 0)
1355  {
1356  LOG(VB_GENERAL, LOG_ERR, LOC +
1357  "StartEncoding: Can't open video device." + ENO);
1358  m_error = "Failed to start recording";
1359  return false;
1360  }
1361  }
1362  else
1363  {
1364  LOG(VB_GENERAL, LOG_ERR, LOC +
1365  QString("StartEncoding: read failed, retry in %1 msec:")
1366  .arg(100 * idx) + ENO);
1367  std::this_thread::sleep_for(std::chrono::microseconds(idx * 100));
1368  }
1369  }
1370  if (idx == 50)
1371  {
1372  LOG(VB_GENERAL, LOG_ERR, LOC +
1373  "StartEncoding: read from video device failed." + ENO);
1374  m_error = "Failed to start recording";
1375  close(m_readfd);
1376  m_readfd = -1;
1377  return false;
1378  }
1379  if (idx > 0)
1380  {
1381  LOG(VB_RECORD, LOG_WARNING, LOC +
1382  QString("%1 read attempts required to start encoding").arg(idx));
1383  }
1384 
1385  if (!good_res) // Try again
1386  HandleResolutionChanges();
1387 
1388  if (m_device_read_buffer)
1389  {
1390  m_device_read_buffer->Reset(m_videodevice.toLatin1().constData(), m_readfd);
1391  m_device_read_buffer->SetRequestPause(false);
1392  m_device_read_buffer->Start();
1393  }
1394 
1395  return true;
1396 }
1397 
1399 {
1400  QMutexLocker locker(&m_start_stop_encoding_lock);
1401 
1402  LOG(VB_RECORD, LOG_INFO, LOC + "StopEncoding");
1403 
1404  if (m_readfd < 0)
1405  return;
1406 
1407  struct v4l2_encoder_cmd command {};
1408  command.cmd = V4L2_ENC_CMD_STOP;
1409  command.flags = V4L2_ENC_CMD_STOP_AT_GOP_END;
1410 
1411  if (m_device_read_buffer)
1412  m_device_read_buffer->SetRequestPause(true);
1413 
1414  bool stopped = 0 == ioctl(m_readfd, VIDIOC_ENCODER_CMD, &command);
1415  if (stopped)
1416  {
1417  LOG(VB_RECORD, LOG_INFO, LOC + "Encoding stopped");
1418  }
1419  else if (errno != ENOTTY && errno != EINVAL)
1420  {
1421  // Some drivers do not support this ioctl at all. It is marked as
1422  // "experimental" in the V4L2 API spec. These drivers return EINVAL
1423  // in older kernels and ENOTTY in 3.1+
1424 
1425  LOG(VB_GENERAL, LOG_WARNING, LOC + "StopEncoding failed" + ENO);
1426  }
1427 
1428  if (m_device_read_buffer && m_device_read_buffer->IsRunning())
1429  {
1430  // allow last bits of data through..
1431  std::this_thread::sleep_for(std::chrono::milliseconds(20));
1432  m_device_read_buffer->Stop();
1433  }
1434 
1435  // close the fd so streamoff/streamon work in V4LChannel
1436  close(m_readfd);
1437  m_readfd = -1;
1438 }
1439 
1441 {
1442  m_stream_data->AddMPEGSPListener(this);
1443  m_stream_data->SetDesiredProgram(1);
1444 }
1445 
1446 void MpegRecorder::SetBitrate(int bitrate, int maxbitrate,
1447  const QString & reason)
1448 {
1449  if (maxbitrate == bitrate)
1450  {
1451  LOG(VB_RECORD, LOG_INFO, LOC + QString("%1 bitrate %2 kbps CBR")
1452  .arg(reason).arg(bitrate));
1453  }
1454  else
1455  {
1456  LOG(VB_RECORD, LOG_INFO, LOC + QString("%1 bitrate %2/%3 kbps VBR")
1457  .arg(reason).arg(bitrate).arg(maxbitrate));
1458  }
1459 
1460  vector<struct v4l2_ext_control> ext_ctrls;
1461  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
1462  (maxbitrate == bitrate) ?
1463  V4L2_MPEG_VIDEO_BITRATE_MODE_CBR :
1464  V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
1465 
1466  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE,
1467  bitrate * 1000);
1468 
1469  add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
1470  maxbitrate * 1000);
1471 
1472  set_ctrls(m_readfd, ext_ctrls);
1473 }
1474 
1476 {
1477  LOG(VB_RECORD, LOG_INFO, LOC + "Checking Resolution");
1478  uint pix = 0;
1479  struct v4l2_format vfmt {};
1480  vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1481 
1482  if (0 == ioctl(m_chanfd, VIDIOC_G_FMT, &vfmt))
1483  {
1484  LOG(VB_RECORD, LOG_INFO, LOC + QString("Got Resolution %1x%2")
1485  .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height));
1486  pix = vfmt.fmt.pix.width * vfmt.fmt.pix.height;
1487  }
1488 
1489  if (!pix)
1490  {
1491  LOG(VB_RECORD, LOG_INFO, LOC + "Giving up detecting resolution: " + ENO);
1492  return false; // nothing to do, we don't have a resolution yet
1493  }
1494 
1495  int old_max = m_maxbitrate, old_avg = m_bitrate;
1496  if (pix <= 768*568)
1497  {
1498  m_maxbitrate = m_low_mpeg4peakbitrate;
1499  m_bitrate = m_low_mpeg4avgbitrate;
1500  }
1501  else if (pix >= 1920*1080)
1502  {
1503  m_maxbitrate = m_high_mpeg4peakbitrate;
1504  m_bitrate = m_high_mpeg4avgbitrate;
1505  }
1506  else
1507  {
1508  m_maxbitrate = m_medium_mpeg4peakbitrate;
1509  m_bitrate = m_medium_mpeg4avgbitrate;
1510  }
1511  m_maxbitrate = std::max(m_maxbitrate, m_bitrate);
1512 
1513  if ((old_max != m_maxbitrate) || (old_avg != m_bitrate))
1514  {
1515  if (old_max == old_avg)
1516  {
1517  LOG(VB_RECORD, LOG_INFO, LOC +
1518  QString("Old bitrate %1 CBR").arg(old_avg));
1519  }
1520  else
1521  {
1522  LOG(VB_RECORD, LOG_INFO,LOC +
1523  QString("Old bitrate %1/%2 VBR") .arg(old_avg).arg(old_max));
1524  }
1525 
1526  SetBitrate(m_bitrate, m_maxbitrate, "New");
1527  }
1528 
1529  return true;
1530 }
1531 
1533 {
1534  LOG(VB_VBI, LOG_INFO, LOC + QString("FormatCC(0x%1,0x%2)")
1535  .arg(code1,0,16).arg(code2,0,16));
1536  // TODO add to CC data vector
1537 
1538  // TODO find video frames in output and insert cc_data
1539  // as CEA-708 user_data packets containing CEA-608 captions
1541 }
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
static const int s_audRateL2[]
Definition: mpegrecorder.h:122
#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)
unsigned int uint
Definition: compat.h:140
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
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_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:2166
def read(device=None, features=[])
Definition: disc.py:35
virtual QString getValue(void) const
#define close
Definition: compat.h:16
static void clear(SettingsMap &cache, SettingsMap &overrides, const QString &myKey)
Definition: mythdb.cpp:830
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 * s_streamType[]
Definition: mpegrecorder.h:124
const char * name
Definition: ParseText.cpp:328
#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
int elapsed(void) const
Returns milliseconds elapsed since last start() or restart()
Definition: mythtimer.cpp:90
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
bool RestartEncoding(void)
#define LOC
static const char * s_aspectRatio[]
Definition: mpegrecorder.h:125
Buffers reads from device files.
TSPacket * CreateClone(void) const
Definition: tspacket.h:183
bool SetRecordingVolume(int chanfd)
static const int s_audRateL3[]
Definition: mpegrecorder.h:123
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
static const int s_audRateL1[]
Definition: mpegrecorder.h:121
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.