MythTV  master
NuppelVideoRecorder.cpp
Go to the documentation of this file.
1 #include <cstdio>
2 #include <cstdlib>
3 #include <fcntl.h>
4 #include <unistd.h>
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include "mythconfig.h"
8 #if HAVE_SYS_SOUNDCARD_H
9  #include <sys/soundcard.h>
10 #elif HAVE_SOUNDCARD_H
11  #include <soundcard.h>
12 #endif
13 #include <sys/ioctl.h>
14 #include <sys/mman.h>
15 #include <cerrno>
16 #include <cmath>
17 
18 #include <QStringList>
19 
20 #include <iostream>
21 
22 #include "mythmiscutil.h"
23 #include "mythcontext.h"
24 #include "NuppelVideoRecorder.h"
25 #include "channelbase.h"
26 #include "recordingprofile.h"
27 #include "tv_rec.h"
28 #include "tv_play.h"
29 #include "audioinput.h"
30 #include "mythlogging.h"
31 #include "vbitext/cc.h"
32 #include "vbitext/vbi.h"
33 #include "mythavutil.h"
34 #include "fourcc.h"
35 
36 #if HAVE_BIGENDIAN
37 extern "C" {
38 #include "bswap.h"
39 }
40 #endif
41 
42 extern "C" {
43 #include "libswscale/swscale.h"
44 #include "libavutil/imgutils.h"
45 }
46 
47 #ifdef USING_V4L2
48 #include <linux/videodev2.h>
49 
50 #include "go7007_myth.h"
51 
52 #ifdef USING_V4L1
53 #include <linux/videodev.h>
54 #endif // USING_V4L1
55 
56 #ifndef MJPIOC_S_PARAMS
57 #include "videodev_mjpeg.h"
58 #endif
59 
60 #endif // USING_V4L2
61 
62 #include "io/mythmediabuffer.h"
63 #include "RTjpegN.h"
64 
65 #include "programinfo.h"
66 #include "mythsystemevent.h"
67 
68 #define LOC QString("NVR(%1): ").arg(m_videodevice)
69 
71 {
72  RunProlog();
74  RunEpilog();
75 }
76 
78 {
79  RunProlog();
81  RunEpilog();
82 }
83 
85  V4LRecorder(rec)
86 {
88  m_seekTable = new std::vector<struct seektable_entry>;
89  m_ccd = new CC608Decoder(this);
90 
92 
94 }
95 
97 {
99  {
100  delete m_ringBuffer;
101  m_ringBuffer = nullptr;
102  }
103  delete m_rtjc;
104  delete [] m_mp3Buf;
105  if (m_gf)
106  lame_close(m_gf);
107  delete [] m_strm;
108  if (m_audioDevice)
109  {
110  delete m_audioDevice;
111  m_audioDevice = nullptr;
112  }
113  if (m_fd >= 0)
114  close(m_fd);
115  if (m_seekTable)
116  {
117  m_seekTable->clear();
118  delete m_seekTable;
119  }
120 
121  while (!m_videoBuffer.empty())
122  {
123  struct vidbuffertype *vb = m_videoBuffer.back();
124  delete [] vb->buffer;
125  delete vb;
126  m_videoBuffer.pop_back();
127  }
128  while (!m_audioBuffer.empty())
129  {
130  struct audbuffertype *ab = m_audioBuffer.back();
131  delete [] ab->buffer;
132  delete ab;
133  m_audioBuffer.pop_back();
134  }
135  while (!m_textBuffer.empty())
136  {
137  struct txtbuffertype *tb = m_textBuffer.back();
138  delete [] tb->buffer;
139  delete tb;
140  m_textBuffer.pop_back();
141  }
142 
143  if (m_mpaVidCodec)
144  avcodec_free_context(&m_mpaVidCtx);
145 
146  delete m_ccd;
147 }
148 
149 void NuppelVideoRecorder::SetOption(const QString &opt, int value)
150 {
151  if (opt == "width")
152  m_wOut = m_width = value;
153  else if (opt == "height")
154  m_hOut = m_height = value;
155  else if (opt == "rtjpegchromafilter")
156  m_m1 = value;
157  else if (opt == "rtjpeglumafilter")
158  m_m2 = value;
159  else if (opt == "rtjpegquality")
160  m_q = value;
161  else if ((opt == "mpeg4bitrate") || (opt == "mpeg2bitrate"))
162  m_targetBitRate = value;
163  else if (opt == "scalebitrate")
164  m_scaleBitRate = value;
165  else if (opt == "mpeg4maxquality")
166  {
167  if (value > 0)
168  m_maxQuality = value;
169  else
170  m_maxQuality = 1;
171  }
172  else if (opt == "mpeg4minquality")
173  m_minQuality = value;
174  else if (opt == "mpeg4qualdiff")
175  m_qualDiff = value;
176  else if (opt == "encodingthreadcount")
177  m_encodingThreadCount = value;
178  else if (opt == "mpeg4optionvhq")
179  {
180  if (value)
181  m_mbDecision = FF_MB_DECISION_RD;
182  else
183  m_mbDecision = FF_MB_DECISION_SIMPLE;
184  }
185  else if (opt == "mpeg4option4mv")
186  {
187  if (value)
188  m_mp4Opts |= AV_CODEC_FLAG_4MV;
189  else
190  m_mp4Opts &= ~AV_CODEC_FLAG_4MV;
191  }
192  else if (opt == "mpeg4optionidct")
193  {
194  if (value)
195  m_mp4Opts |= AV_CODEC_FLAG_INTERLACED_DCT;
196  else
197  m_mp4Opts &= ~AV_CODEC_FLAG_INTERLACED_DCT;
198  }
199  else if (opt == "mpeg4optionime")
200  {
201  if (value)
202  m_mp4Opts |= AV_CODEC_FLAG_INTERLACED_ME;
203  else
204  m_mp4Opts &= ~AV_CODEC_FLAG_INTERLACED_ME;
205  }
206  else if (opt == "hardwaremjpegquality")
207  m_hmjpgQuality = value;
208  else if (opt == "hardwaremjpeghdecimation")
209  m_hmjpgHDecimation = value;
210  else if (opt == "hardwaremjpegvdecimation")
211  m_hmjpgVDecimation = value;
212  else if (opt == "audiocompression")
213  m_compressAudio = (value != 0);
214  else if (opt == "mp3quality")
215  m_mp3Quality = value;
216  else if (opt == "samplerate")
217  m_audioSampleRate = value;
218  else if (opt == "audioframesize")
219  m_audioBufferSize = value;
220  else if (opt == "pip_mode")
221  m_pipMode = value;
222  else if (opt == "inpixfmt")
223  m_inPixFmt = (VideoFrameType)value;
224  else if (opt == "skipbtaudio")
225  m_skipBtAudio = (value != 0);
226  else if (opt == "volume")
227  m_volume = value;
228  else
229  V4LRecorder::SetOption(opt, value);
230 }
231 
232 void NuppelVideoRecorder::SetOption(const QString &name, const QString &value)
233 {
234  V4LRecorder::SetOption(name, value);
235 }
236 
238  const QString &videodev,
239  const QString &audiodev,
240  const QString &vbidev)
241 {
242  SetOption("videodevice", videodev);
243  SetOption("vbidevice", vbidev);
244  SetOption("tvformat", gCoreContext->GetSetting("TVFormat"));
245  SetOption("vbiformat", gCoreContext->GetSetting("VbiFormat"));
246  SetOption("audiodevice", audiodev);
247 
248  QString setting;
249  const StandardSetting *tmp = profile->byName("videocodec");
250  if (tmp)
251  setting = tmp->getValue();
252 
253  if (setting == "MPEG-4")
254  {
255  SetOption("videocodec", "mpeg4");
256 
257  SetIntOption(profile, "mpeg4bitrate");
258  SetIntOption(profile, "scalebitrate");
259  SetIntOption(profile, "mpeg4maxquality");
260  SetIntOption(profile, "mpeg4minquality");
261  SetIntOption(profile, "mpeg4qualdiff");
262 #ifdef USING_FFMPEG_THREADS
263  SetIntOption(profile, "encodingthreadcount");
264 #endif
265  SetIntOption(profile, "mpeg4optionvhq");
266  SetIntOption(profile, "mpeg4option4mv");
267  SetIntOption(profile, "mpeg4optionidct");
268  SetIntOption(profile, "mpeg4optionime");
269  }
270  else if (setting == "MPEG-2")
271  {
272  SetOption("videocodec", "mpeg2video");
273 
274  SetIntOption(profile, "mpeg2bitrate");
275  SetIntOption(profile, "scalebitrate");
276 #ifdef USING_FFMPEG_THREADS
277  SetIntOption(profile, "encodingthreadcount");
278 #endif
279  }
280  else if (setting == "RTjpeg")
281  {
282  SetOption("videocodec", "rtjpeg");
283 
284  SetIntOption(profile, "rtjpegquality");
285  SetIntOption(profile, "rtjpegchromafilter");
286  SetIntOption(profile, "rtjpeglumafilter");
287  }
288  else if (setting == "Hardware MJPEG")
289  {
290  SetOption("videocodec", "hardware-mjpeg");
291 
292  SetIntOption(profile, "hardwaremjpegquality");
293  SetIntOption(profile, "hardwaremjpeghdecimation");
294  SetIntOption(profile, "hardwaremjpegvdecimation");
295  }
296  else
297  {
298  LOG(VB_GENERAL, LOG_ERR, LOC +
299  "Unknown video codec. "
300  "Please go into the TV Settings, Recording Profiles and "
301  "setup the four 'Software Encoders' profiles. "
302  "Assuming RTjpeg for now.");
303 
304  SetOption("videocodec", "rtjpeg");
305 
306  SetIntOption(profile, "rtjpegquality");
307  SetIntOption(profile, "rtjpegchromafilter");
308  SetIntOption(profile, "rtjpeglumafilter");
309  }
310 
311  setting.clear();
312  if ((tmp = profile->byName("audiocodec")))
313  setting = tmp->getValue();
314 
315  if (setting == "MP3")
316  {
317  SetOption("audiocompression", 1);
318  SetIntOption(profile, "mp3quality");
319  SetIntOption(profile, "samplerate");
320  }
321  else if (setting == "Uncompressed")
322  {
323  SetOption("audiocompression", 0);
324  SetIntOption(profile, "samplerate");
325  }
326  else
327  {
328  LOG(VB_GENERAL, LOG_ERR, LOC + "Unknown audio codec");
329  SetOption("audiocompression", 0);
330  }
331 
332  SetIntOption(profile, "volume");
333 
334  SetIntOption(profile, "width");
335  SetIntOption(profile, "height");
336 }
337 
339 {
340  QMutexLocker locker(&m_pauseLock);
343  m_requestPause = true;
344 
345  // The wakeAll is to make sure [write|audio|main]paused are
346  // set immediately, even if we were already paused previously.
347  m_unpauseWait.wakeAll();
348 }
349 
350 bool NuppelVideoRecorder::IsPaused(bool holding_lock) const
351 {
352  if (!holding_lock)
353  m_pauseLock.lock();
354  bool ret = m_audioPaused && m_mainPaused && m_writePaused;
355  if (!holding_lock)
356  m_pauseLock.unlock();
357  return ret;
358 }
359 
360 void NuppelVideoRecorder::SetVideoFilters(QString& /*filters*/)
361 {
362 }
363 
365 {
366  return m_recording;
367 }
368 
370 {
371  return m_framesWritten;
372 }
373 
375 {
376  return m_channelFd;
377 }
378 
380 {
381  if (!m_useAvCodec)
382  m_useAvCodec = true;
383 
384  if (m_mpaVidCodec)
385  avcodec_free_context(&m_mpaVidCtx);
386 
387  QByteArray vcodec = m_videocodec.toLatin1();
388  m_mpaVidCodec = avcodec_find_encoder_by_name(vcodec.constData());
389 
390  if (!m_mpaVidCodec)
391  {
392  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Video Codec not found: %1")
393  .arg(vcodec.constData()));
394  return false;
395  }
396 
397  m_mpaVidCtx = avcodec_alloc_context3(nullptr);
398 
399  switch (m_pictureFormat)
400  {
401  case AV_PIX_FMT_YUV420P:
402  case AV_PIX_FMT_YUV422P:
403  case AV_PIX_FMT_YUVJ420P:
404  m_mpaVidCtx->pix_fmt = m_pictureFormat;
405  break;
406  default:
407  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Unknown picture format: %1")
408  .arg(m_pictureFormat));
409  }
410 
411  m_mpaVidCtx->width = m_wOut;
412  m_mpaVidCtx->height = (int)(m_height * m_heightMultiplier);
413 
414  int usebitrate = m_targetBitRate * 1000;
415  if (m_scaleBitRate)
416  {
417  float diff = (m_wOut * m_hOut) / (640.0 * 480.0);
418  usebitrate = (int)(diff * usebitrate);
419  }
420 
421  if (m_targetBitRate == -1)
422  usebitrate = -1;
423 
424  m_mpaVidCtx->time_base.den = (int)ceil(m_videoFrameRate * 100 *
426  m_mpaVidCtx->time_base.num = 100;
427 
428  // avcodec needs specific settings for mpeg2 compression
429  switch (m_mpaVidCtx->time_base.den)
430  {
431  case 2397:
432  case 2398: m_mpaVidCtx->time_base.den = 24000;
433  m_mpaVidCtx->time_base.num = 1001;
434  break;
435  case 2997:
436  case 2998: m_mpaVidCtx->time_base.den = 30000;
437  m_mpaVidCtx->time_base.num = 1001;
438  break;
439  case 5994:
440  case 5995: m_mpaVidCtx->time_base.den = 60000;
441  m_mpaVidCtx->time_base.num = 1001;
442  break;
443  }
444 
445  AVDictionary *opts = nullptr;
446 
447  m_mpaVidCtx->bit_rate = usebitrate;
448  m_mpaVidCtx->bit_rate_tolerance = usebitrate * 100;
449  m_mpaVidCtx->qmin = m_maxQuality;
450  m_mpaVidCtx->qmax = m_minQuality;
451  m_mpaVidCtx->max_qdiff = m_qualDiff;
452  m_mpaVidCtx->flags = m_mp4Opts;
453  m_mpaVidCtx->mb_decision = m_mbDecision;
454 
455  m_mpaVidCtx->qblur = 0.5;
456  m_mpaVidCtx->max_b_frames = 0;
457  m_mpaVidCtx->b_quant_factor = 0;
458  av_dict_set(&opts, "rc_strategy", "2", 0);
459  av_dict_set(&opts, "b_strategy", "0", 0);
460  m_mpaVidCtx->gop_size = 30;
461  m_mpaVidCtx->rc_max_rate = 0;
462  m_mpaVidCtx->rc_min_rate = 0;
463  m_mpaVidCtx->rc_buffer_size = 0;
464  m_mpaVidCtx->rc_override_count = 0;
465  av_dict_set(&opts, "rc_init_cplx", "0", 0);
466  m_mpaVidCtx->dct_algo = FF_DCT_AUTO;
467  m_mpaVidCtx->idct_algo = FF_IDCT_AUTO;
468  av_dict_set_int(&opts, "pred", FF_PRED_LEFT, 0);
469  if (m_videocodec.toLower() == "huffyuv" || m_videocodec.toLower() == "mjpeg")
470  m_mpaVidCtx->strict_std_compliance = FF_COMPLIANCE_UNOFFICIAL;
471  m_mpaVidCtx->thread_count = m_encodingThreadCount;
472 
473  if (avcodec_open2(m_mpaVidCtx, m_mpaVidCodec, &opts) < 0)
474  {
475  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Unable to open FFMPEG/%1 codec")
476  .arg(m_videocodec));
477  return false;
478  }
479 
480 
481  return true;
482 }
483 
485 {
486  m_pictureFormat = AV_PIX_FMT_YUV420P;
487 
488  m_rtjc = new RTjpeg();
489  int setval = RTJ_YUV420;
490  m_rtjc->SetFormat(&setval);
491  setval = (int)(m_hOut * m_heightMultiplier);
492  m_rtjc->SetSize(&m_wOut, &setval);
493  m_rtjc->SetQuality(&m_q);
494  setval = 2;
495  m_rtjc->SetIntra(&setval, &m_m1, &m_m2);
496 }
497 
498 
500 {
501  int tot_height = (int)(m_height * m_heightMultiplier);
502  double aspectnum = m_wOut / (double)tot_height;
503  uint aspect = 0;
504 
505  if (aspectnum == 0.0)
506  aspect = 0;
507  else if (fabs(aspectnum - 1.3333333333333333) < 0.001)
508  aspect = 2;
509  else if (fabs(aspectnum - 1.7777777777777777) < 0.001)
510  aspect = 3;
511  else if (fabs(aspectnum - 2.21) < 0.001)
512  aspect = 4;
513  else
514  aspect = aspectnum * 1000000;
515 
516  if ((aspect > 0) && (aspect != m_videoAspect))
517  {
518  m_videoAspect = aspect;
519  AspectChange((AspectRatio)aspect, 0);
520  }
521 
522  if (m_wOut && tot_height &&
523  ((uint)tot_height != m_videoHeight ||
524  (uint)m_wOut != m_videoWidth))
525  {
526  m_videoHeight = tot_height;
528  ResolutionChange(m_wOut, tot_height, 0);
529  }
530 
531  int den = (int)ceil(m_videoFrameRate * 100 * m_frameRateMultiplier);
532  int num = 100;
533 
534  // avcodec needs specific settings for mpeg2 compression
535  switch (den)
536  {
537  case 2397:
538  case 2398: den = 24000;
539  num = 1001;
540  break;
541  case 2997:
542  case 2998: den = 30000;
543  num = 1001;
544  break;
545  case 5994:
546  case 5995: den = 60000;
547  num = 1001;
548  break;
549  }
550 
551  FrameRate frameRate(den, num);
552  if (frameRate.isNonzero() && frameRate != m_frameRate)
553  {
554  m_frameRate = frameRate;
555  LOG(VB_RECORD, LOG_INFO, LOC + QString("NVR: frame rate = %1")
556  .arg(frameRate.toDouble() * 1000));
557  FrameRateChange(frameRate.toDouble() * 1000, 0);
558  }
559 }
560 
562 {
563  if (AudioInit() != 0)
564  {
565  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to init audio input device");
566  }
567 
568  if (m_videocodec == "hardware-mjpeg")
569  {
570  m_videocodec = "mjpeg";
571  m_hardwareEncode = true;
572 
573  MJPEGInit();
574 
576 
577  if (m_ntsc)
578  {
579  switch (m_hmjpgVDecimation)
580  {
581  case 2: m_height = 240; break;
582  case 4: m_height = 120; break;
583  default: m_height = 480; break;
584  }
585  }
586  else
587  {
588  switch (m_hmjpgVDecimation)
589  {
590  case 2: m_height = 288; break;
591  case 4: m_height = 144; break;
592  default: m_height = 576; break;
593  }
594  }
595  }
596 
597  if (!m_ringBuffer)
598  {
599  LOG(VB_GENERAL, LOG_WARNING, LOC + "Warning, old RingBuffer creation");
600  m_ringBuffer = MythMediaBuffer::Create("output.nuv", true);
601  m_weMadeBuffer = true;
602  m_livetv = false;
603  if (!m_ringBuffer || !m_ringBuffer->IsOpen())
604  {
605  m_error = "Could not open RingBuffer";
606  LOG(VB_GENERAL, LOG_ERR, LOC + m_error);
607  return;
608  }
609  }
610  else
612 
613  m_audioBytes = 0;
614 
615  InitBuffers();
616 }
617 
618 int NuppelVideoRecorder::AudioInit(bool skipdevice)
619 {
620  if (!skipdevice)
621  {
622  int blocksize = 0;
624  if (!m_audioDevice)
625  {
626  LOG(VB_GENERAL, LOG_ERR, LOC +
627  QString("Failed to create audio device: %1") .arg(m_audioDeviceName));
628  return 1;
629  }
630 
632  {
633  LOG(VB_GENERAL, LOG_ERR, LOC +
634  QString("Failed to open audio device %1").arg(m_audioDeviceName));
635  return 1;
636  }
637 
638  if ((blocksize = m_audioDevice->GetBlockSize()) <= 0)
639  {
640  blocksize = 1024;
641  LOG(VB_GENERAL, LOG_ERR, LOC +
642  QString("Failed to determine audio block size on %1,"
643  "using default 1024 bytes").arg(m_audioDeviceName));
644  }
645 
646  m_audioDevice->Close();
647  m_audioBufferSize = blocksize;
648  }
649 
651  LOG(VB_AUDIO, LOG_INFO, LOC +
652  QString("Audio device %1 buffer size: %1 bytes")
654 
655  if (m_compressAudio)
656  {
657  int tmp = 0;
658  m_gf = lame_init();
659  lame_set_bWriteVbrTag(m_gf, 0);
660  lame_set_quality(m_gf, m_mp3Quality);
661  lame_set_compression_ratio(m_gf, 11);
662  lame_set_mode(m_gf, m_audioChannels == 2 ? STEREO : MONO);
663  lame_set_num_channels(m_gf, m_audioChannels);
664  lame_set_in_samplerate(m_gf, m_audioSampleRate);
665  if ((tmp = lame_init_params(m_gf)) != 0)
666  {
667  LOG(VB_GENERAL, LOG_ERR, LOC +
668  QString("AudioInit(): lame_init_params error %1").arg(tmp));
669  m_compressAudio = false;
670  }
671 
672  if (m_audioBits != 16)
673  {
674  LOG(VB_GENERAL, LOG_ERR, LOC +
675  "AudioInit(): lame support requires 16bit audio");
676  m_compressAudio = false;
677  }
678  }
679  m_mp3BufSize = (int)(1.25 * 16384 + 7200);
680  m_mp3Buf = new char[m_mp3BufSize];
681 
682  return 0;
683 }
684 
695 {
696 #ifdef USING_V4L1
697  bool we_opened_fd = false;
698  int init_fd = m_fd;
699  if (init_fd < 0)
700  {
701  QByteArray vdevice = m_videodevice.toLatin1();
702  init_fd = open(vdevice.constData(), O_RDWR);
703  we_opened_fd = true;
704 
705  if (init_fd < 0)
706  {
707  LOG(VB_GENERAL, LOG_ERR, LOC + "Can't open video device" + ENO);
708  return false;
709  }
710  }
711 
712  struct video_capability vc;
713  memset(&vc, 0, sizeof(vc));
714  int ret = ioctl(init_fd, VIDIOCGCAP, &vc);
715 
716  if (ret < 0)
717  LOG(VB_GENERAL, LOG_ERR, LOC + "Can't query V4L capabilities" + ENO);
718 
719  if (we_opened_fd)
720  close(init_fd);
721 
722  if (ret < 0)
723  return false;
724 
725  if (vc.maxwidth != 768 && vc.maxwidth != 640)
726  vc.maxwidth = 720;
727 
728  if (vc.type & VID_TYPE_MJPEG_ENCODER)
729  {
730  if (vc.maxwidth >= 768)
731  m_hmjpgMaxW = 768;
732  else if (vc.maxwidth >= 704)
733  m_hmjpgMaxW = 704;
734  else
735  m_hmjpgMaxW = 640;
736  return true;
737  }
738 #endif // USING_V4L1
739 
740  LOG(VB_GENERAL, LOG_ERR, LOC + "MJPEG not supported by device");
741  return false;
742 }
743 
745 {
746  int videomegs = 0;
747  // cppcheck-suppress variableScope
748  int audiomegs = 2;
749 
750  if (!m_videoBufferSize)
751  {
752  m_videoBufferSize = static_cast<long>(
754  m_wOut, m_hOut));
755  }
756 
757  if (m_width >= 480 || m_height > 288)
758  videomegs = 20;
759  else
760  videomegs = 12;
761 
762  m_videoBufferCount = (videomegs * 1000 * 1000) / m_videoBufferSize;
763 
764  if (m_audioBufferSize != 0)
765  m_audioBufferCount = (audiomegs * 1000 * 1000) / m_audioBufferSize;
766  else
767  m_audioBufferCount = 0;
768 
769  m_textBufferSize = 8 * (sizeof(teletextsubtitle) + VT_WIDTH);
771 
772  for (int i = 0; i < m_videoBufferCount; i++)
773  {
774  auto *vidbuf = new vidbuffertype;
775  vidbuf->buffer = new unsigned char[m_videoBufferSize];
776  vidbuf->sample = 0;
777  vidbuf->freeToEncode = 0;
778  vidbuf->freeToBuffer = 1;
779  vidbuf->bufferlen = 0;
780  vidbuf->forcekey = false;
781 
782  m_videoBuffer.push_back(vidbuf);
783  }
784 
785  for (int i = 0; i < m_audioBufferCount; i++)
786  {
787  auto *audbuf = new audbuffertype;
788  audbuf->buffer = new unsigned char[m_audioBufferSize];
789  audbuf->sample = 0;
790  audbuf->freeToEncode = 0;
791  audbuf->freeToBuffer = 1;
792 
793  m_audioBuffer.push_back(audbuf);
794  }
795 
796  for (int i = 0; i < m_textBufferCount; i++)
797  {
798  auto *txtbuf = new txtbuffertype;
799  txtbuf->buffer = new unsigned char[m_textBufferSize];
800  txtbuf->freeToEncode = 0;
801  txtbuf->freeToBuffer = 1;
802 
803  m_textBuffer.push_back(txtbuf);
804  }
805 }
806 
808 {
809  for (auto & vidbuf : m_videoBuffer)
810  {
811  delete [] (vidbuf->buffer);
812  vidbuf->buffer = new unsigned char[m_videoBufferSize];
813  }
814 }
815 
817 {
818  delete [] m_strm;
819  m_strm = new signed char[m_width * m_height * 2 + 10];
820 }
821 
823 {
824  if (m_channelFd>0)
825  return true;
826 
827  int retries = 0;
828  QByteArray vdevice = m_videodevice.toLatin1();
829  m_fd = open(vdevice.constData(), O_RDWR);
830  while (m_fd < 0)
831  {
832  usleep(30000);
833  m_fd = open(vdevice.constData(), O_RDWR);
834  if (retries++ > 5)
835  {
836  m_error = QString("Can't open video device: %1").arg(m_videodevice);
837  LOG(VB_GENERAL, LOG_ERR, LOC + m_error + ENO);
838  KillChildren();
839  return false;
840  }
841  }
842 
843  m_channelFd = m_fd;
844  return true;
845 }
846 
848 {
849 #ifdef USING_V4L2
850  m_usingV4l2 = true;
851 
852  struct v4l2_capability vcap {};
853 
854  if (ioctl(m_channelFd, VIDIOC_QUERYCAP, &vcap) < 0)
855  {
856  m_usingV4l2 = false;
857  }
858 
859  if (m_usingV4l2 && !(vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
860  {
861  LOG(VB_GENERAL, LOG_ERR, LOC +
862  "Not a v4l2 capture device, falling back to v4l");
863  m_usingV4l2 = false;
864  }
865 
866  if (m_usingV4l2 && !(vcap.capabilities & V4L2_CAP_STREAMING))
867  {
868  LOG(VB_GENERAL, LOG_ERR, LOC +
869  "Won't work with the streaming interface, falling back");
870  m_usingV4l2 = false;
871  }
872 
873  if (vcap.card[0] == 'B' && vcap.card[1] == 'T' &&
874  vcap.card[2] == '8' && vcap.card[4] == '8')
875  m_correctBttv = true;
876 
877  QString driver = (char *)vcap.driver;
878  if (driver == "go7007")
879  m_go7007 = true;
880 #endif // USING_V4L2
881 }
882 
884 {
885  if (lzo_init() != LZO_E_OK)
886  {
887  LOG(VB_GENERAL, LOG_ERR, LOC + "lzo_init() failed, exiting");
888  m_error = "lzo_init() failed, exiting";
889  LOG(VB_GENERAL, LOG_ERR, LOC + m_error);
890  return;
891  }
892 
893  if (!Open())
894  {
895  m_error = "Failed to open device";
896  LOG(VB_GENERAL, LOG_ERR, LOC + m_error);
897  return;
898  }
899 
900  ProbeV4L2();
901 
902  if (m_usingV4l2 && !SetFormatV4L2())
903  {
904  m_error = "Failed to set V4L2 format";
905  LOG(VB_GENERAL, LOG_ERR, LOC + m_error);
906  return;
907  }
908 
909  StreamAllocate();
910 
911  m_positionMapLock.lock();
912  m_positionMap.clear();
913  m_positionMapDelta.clear();
914  m_positionMapLock.unlock();
915 
916  m_useAvCodec = (m_videocodec.toLower() != "rtjpeg");
917  if (m_useAvCodec)
919 
920  if (!m_useAvCodec)
921  SetupRTjpeg();
922 
924 
925  if (CreateNuppelFile() != 0)
926  {
927  m_error = QString("Cannot open '%1' for writing")
928  .arg(m_ringBuffer->GetFilename());
929  LOG(VB_GENERAL, LOG_ERR, LOC + m_error);
930  return;
931  }
932 
933  if (IsHelperRequested())
934  {
935  LOG(VB_GENERAL, LOG_ERR, LOC + "Children are already alive");
936  m_error = "Children are already alive";
937  return;
938  }
939 
940  {
941  QMutexLocker locker(&m_pauseLock);
942  m_requestRecording = true;
943  m_requestHelper = true;
944  m_recording = true;
945  m_recordingWait.wakeAll();
946  }
947 
948  m_writeThread = new NVRWriteThread(this);
949  m_writeThread->start();
950 
951  m_audioThread = new NVRAudioThread(this);
952  m_audioThread->start();
953 
954  if ((m_vbiMode != VBIMode::None) && (OpenVBIDevice() >= 0))
955  m_vbiThread = new VBIThread(this);
956 
957  // save the start time
958  gettimeofday(&m_stm, &m_tzone);
959 
960  // try to get run at higher scheduling priority, ignore failure
961  myth_nice(-10);
962 
963  if (m_usingV4l2)
964  {
965  m_inPixFmt = FMT_NONE;;
966  DoV4L2();
967  }
968  else
969  DoV4L1();
970 
971  {
972  QMutexLocker locker(&m_pauseLock);
973  m_requestRecording = false;
974  m_requestHelper = false;
975  m_recording = false;
976  m_recordingWait.wakeAll();
977  }
978 }
979 
980 #ifdef USING_V4L1
982 {
983  struct video_capability vc;
984  struct video_mmap mm;
985  struct video_mbuf vm;
986  struct video_channel vchan;
987  struct video_audio va;
988  struct video_tuner vt;
989 
990  memset(&mm, 0, sizeof(mm));
991  memset(&vm, 0, sizeof(vm));
992  memset(&vchan, 0, sizeof(vchan));
993  memset(&va, 0, sizeof(va));
994  memset(&vt, 0, sizeof(vt));
995  memset(&vc, 0, sizeof(vc));
996 
997  if (ioctl(m_fd, VIDIOCGCAP, &vc) < 0)
998  {
999  QString tmp = "VIDIOCGCAP: " + ENO;
1000  KillChildren();
1001  LOG(VB_GENERAL, LOG_ERR, tmp);
1002  m_error = tmp;
1003  return;
1004  }
1005 
1006  int channelinput = 0;
1007 
1008  if (m_channelObj)
1009  channelinput = m_channelObj->GetCurrentInputNum();
1010 
1011  vchan.channel = channelinput;
1012 
1013  if (ioctl(m_fd, VIDIOCGCHAN, &vchan) < 0)
1014  LOG(VB_GENERAL, LOG_ERR, LOC + "VIDIOCGCHAN: " + ENO);
1015 
1016  // Set volume level for audio recording (unless feature is disabled).
1017  if (!m_skipBtAudio)
1018  {
1019  // v4l1 compat in Linux 2.6.18 does not set VIDEO_VC_AUDIO,
1020  // so we just use VIDIOCGAUDIO unconditionally.. then only
1021  // report a get failure as an error if VIDEO_VC_AUDIO is set.
1022  if (ioctl(m_fd, VIDIOCGAUDIO, &va) < 0)
1023  {
1024  bool reports_audio = vchan.flags & VIDEO_VC_AUDIO;
1025  uint err_level = reports_audio ? VB_GENERAL : VB_AUDIO;
1026  // print at VB_GENERAL if driver reports audio.
1027  LOG(err_level, LOG_ERR, LOC + "Failed to get audio" + ENO);
1028  }
1029  else
1030  {
1031  // if channel has a audio then activate it
1032  va.flags &= ~VIDEO_AUDIO_MUTE; // now this really has to work
1033  va.volume = m_volume * 65535 / 100;
1034  if (ioctl(m_fd, VIDIOCSAUDIO, &va) < 0)
1035  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to set audio" + ENO);
1036  }
1037  }
1038 
1039  if ((vc.type & VID_TYPE_MJPEG_ENCODER) && m_hardwareEncode)
1040  {
1041  DoMJPEG();
1042  m_error = "MJPEG requested but not available.";
1043  LOG(VB_GENERAL, LOG_ERR, LOC + m_error);
1044  return;
1045  }
1046 
1047  m_inPixFmt = FMT_NONE;
1048  InitFilters();
1049 
1050  if (ioctl(m_fd, VIDIOCGMBUF, &vm) < 0)
1051  {
1052  QString tmp = "VIDIOCGMBUF: " + ENO;
1053  KillChildren();
1054  LOG(VB_GENERAL, LOG_ERR, LOC + tmp);
1055  m_error = tmp;
1056  return;
1057  }
1058 
1059  if (vm.frames < 2)
1060  {
1061  QString tmp = "need a minimum of 2 capture buffers";
1062  KillChildren();
1063  LOG(VB_GENERAL, LOG_ERR, LOC + tmp);
1064  m_error = tmp;
1065  return;
1066  }
1067 
1068  int frame;
1069 
1070  unsigned char *buf = (unsigned char *)mmap(0, vm.size,
1071  PROT_READ|PROT_WRITE,
1072  MAP_SHARED,
1073  m_fd, 0);
1074  if (buf == MAP_FAILED)
1075  {
1076  QString tmp = "mmap: " + ENO;
1077  KillChildren();
1078  LOG(VB_GENERAL, LOG_ERR, LOC + tmp);
1079  m_error = tmp;
1080  return;
1081  }
1082 
1083  mm.height = m_height;
1084  mm.width = m_width;
1085  if (m_inPixFmt == FMT_YUV422P)
1086  mm.format = VIDEO_PALETTE_YUV422P;
1087  else
1088  mm.format = VIDEO_PALETTE_YUV420P;
1089 
1090  mm.frame = 0;
1091  if (ioctl(m_fd, VIDIOCMCAPTURE, &mm)<0)
1092  LOG(VB_GENERAL, LOG_ERR, LOC + "VIDIOCMCAPTUREi0: " + ENO);
1093  mm.frame = 1;
1094  if (ioctl(m_fd, VIDIOCMCAPTURE, &mm)<0)
1095  LOG(VB_GENERAL, LOG_ERR, LOC + "VIDIOCMCAPTUREi1: " + ENO);
1096 
1097  int syncerrors = 0;
1098 
1099  while (IsRecordingRequested() && !IsErrored())
1100  {
1101  {
1102  QMutexLocker locker(&m_pauseLock);
1103  if (m_request_pause)
1104  {
1105  if (!m_mainPaused)
1106  {
1107  m_mainPaused = true;
1108  m_pauseWait.wakeAll();
1109  if (IsPaused(true) && m_tvrec)
1111  }
1112  m_unpauseWait.wait(&m_pauseLock, 100);
1113  if (m_clearTimeOnPause)
1114  gettimeofday(&m_stm, &m_tzone);
1115  continue;
1116  }
1117 
1118  if (!m_request_pause && m_mainPaused)
1119  {
1120  m_mainPaused = false;
1121  m_unpauseWait.wakeAll();
1122  }
1123  }
1124 
1125  frame = 0;
1126  mm.frame = 0;
1127  if (ioctl(m_fd, VIDIOCSYNC, &frame)<0)
1128  {
1129  syncerrors++;
1130  if (syncerrors == 10)
1131  LOG(VB_GENERAL, LOG_ERR, LOC +
1132  "Multiple bttv errors, further messages supressed");
1133  else if (syncerrors < 10)
1134  LOG(VB_GENERAL, LOG_ERR, LOC + "VIDIOCSYNC: " + ENO);
1135  }
1136  else
1137  {
1138  BufferIt(buf+vm.offsets[0], m_videoBufferSize);
1139  //memset(buf+vm.offsets[0], 0, m_videoBufferSize);
1140  }
1141 
1142  if (ioctl(m_fd, VIDIOCMCAPTURE, &mm)<0)
1143  LOG(VB_GENERAL, LOG_ERR, LOC + "VIDIOCMCAPTURE0: " + ENO);
1144 
1145  frame = 1;
1146  mm.frame = 1;
1147  if (ioctl(m_fd, VIDIOCSYNC, &frame)<0)
1148  {
1149  syncerrors++;
1150  if (syncerrors == 10)
1151  LOG(VB_GENERAL, LOG_ERR, LOC +
1152  "Multiple bttv errors, further messages supressed");
1153  else if (syncerrors < 10)
1154  LOG(VB_GENERAL, LOG_ERR, LOC + "VIDIOCSYNC: " + ENO);
1155  }
1156  else
1157  {
1158  BufferIt(buf+vm.offsets[1], m_videoBufferSize);
1159  //memset(buf+vm.offsets[1], 0, m_videoBufferSize);
1160  }
1161  if (ioctl(m_fd, VIDIOCMCAPTURE, &mm)<0)
1162  LOG(VB_GENERAL, LOG_ERR, LOC + "VIDIOCMCAPTURE1: " + ENO);
1163  }
1164 
1165  munmap(buf, vm.size);
1166 
1167  KillChildren();
1168 
1169  FinishRecording();
1170 
1171  close(m_fd);
1172 }
1173 #else // if !USING_V4L1
1174 void NuppelVideoRecorder::DoV4L1(void) {}
1175 #endif // !USING_V4L1
1176 
1177 #ifdef USING_V4L2
1179 {
1180  struct v4l2_format vfmt {};
1181 
1182  vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1183 
1184  vfmt.fmt.pix.width = m_width;
1185  vfmt.fmt.pix.height = m_height;
1186  vfmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
1187 
1188  if (m_go7007)
1189  vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
1190  else if (m_inPixFmt == FMT_YUV422P)
1191  vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P;
1192  else
1193  vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
1194 
1195  if (ioctl(m_fd, VIDIOC_S_FMT, &vfmt) < 0)
1196  {
1197  // this is supported by the cx88 and various ati cards.
1198  vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
1199 
1200  if (ioctl(m_fd, VIDIOC_S_FMT, &vfmt) < 0)
1201  {
1202  // this is supported by the HVR-950q
1203  vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
1204  if (ioctl(m_fd, VIDIOC_S_FMT, &vfmt) < 0)
1205  {
1206  LOG(VB_GENERAL, LOG_ERR, LOC +
1207  "v4l2: Unable to set desired format");
1208  return false;
1209  }
1210 
1211  // we need to convert the buffer - we can't deal with uyvy
1212  // directly.
1213  if (m_inPixFmt == FMT_YUV422P)
1214  {
1215  LOG(VB_GENERAL, LOG_ERR, LOC +
1216  "v4l2: uyvy format supported, but yuv422 requested.");
1217  LOG(VB_GENERAL, LOG_ERR, LOC +
1218  "v4l2: unfortunately, this converter hasn't been "
1219  "written yet, exiting");
1220  return false;
1221  }
1222  LOG(VB_RECORD, LOG_INFO, LOC +
1223  "v4l2: format set, getting uyvy from v4l, converting");
1224  }
1225  else
1226  {
1227  // we need to convert the buffer - we can't deal with yuyv directly.
1228  if (m_inPixFmt == FMT_YUV422P)
1229  {
1230  LOG(VB_GENERAL, LOG_ERR, LOC +
1231  "v4l2: yuyv format supported, but yuv422 requested.");
1232  LOG(VB_GENERAL, LOG_ERR, LOC +
1233  "v4l2: unfortunately, this converter hasn't been written "
1234  "yet, exiting");
1235  return false;
1236  }
1237  LOG(VB_RECORD, LOG_INFO, LOC +
1238  "v4l2: format set, getting yuyv from v4l, converting");
1239  }
1240  }
1241  else // cool, we can do our preferred format, most likely running on bttv.
1242  LOG(VB_RECORD, LOG_INFO, LOC +
1243  "v4l2: format set, getting yuv420 from v4l");
1244 
1245  // VIDIOC_S_FMT might change the format, check it
1246  if (m_width != (int)vfmt.fmt.pix.width ||
1247  m_height != (int)vfmt.fmt.pix.height)
1248  {
1249  LOG(VB_RECORD, LOG_INFO, LOC +
1250  QString("v4l2: resolution changed. requested %1x%2, using "
1251  "%3x%4 now")
1252  .arg(m_width).arg(m_height)
1253  .arg(vfmt.fmt.pix.width) .arg(vfmt.fmt.pix.height));
1254  m_wOut = m_width = vfmt.fmt.pix.width;
1255  m_hOut = m_height = vfmt.fmt.pix.height;
1256  }
1257 
1258  m_v4l2PixelFormat = vfmt.fmt.pix.pixelformat;
1259 
1260  return true;
1261 }
1262 #else // if !USING_V4L2
1263 bool NuppelVideoRecorder::SetFormatV4L2(void) { return false; }
1264 #endif // !USING_V4L2
1265 
1266 #ifdef USING_V4L2
1267 #define MAX_VIDEO_BUFFERS 5
1269 {
1270  struct v4l2_buffer vbuf {};
1271  struct v4l2_requestbuffers vrbuf {};
1272  struct v4l2_control vc {};
1273 
1274  vc.id = V4L2_CID_AUDIO_MUTE;
1275  vc.value = 0;
1276 
1277  if (ioctl(m_fd, VIDIOC_S_CTRL, &vc) < 0)
1278  LOG(VB_GENERAL, LOG_ERR, LOC +
1279  "VIDIOC_S_CTRL:V4L2_CID_AUDIO_MUTE: " + ENO);
1280 
1281  if (m_go7007)
1282  {
1283  struct go7007_comp_params comp {};
1284  struct go7007_mpeg_params mpeg {};
1285 
1286  comp.gop_size = m_keyframeDist;
1287  comp.max_b_frames = 0;
1288 
1289  if (fabs(m_videoAspect - 1.33333F) < 0.01F)
1290  {
1291  if (m_ntsc)
1293  else
1295  }
1296  else if (fabs(m_videoAspect - 1.77777F) < 0.01F)
1297  {
1298  if (m_ntsc)
1300  else
1302  }
1303  else
1304  {
1306  }
1307 
1308  comp.flags |= GO7007_COMP_CLOSED_GOP;
1309  if (ioctl(m_fd, GO7007IOC_S_COMP_PARAMS, &comp) < 0)
1310  {
1311  m_error = "Unable to set compression params";
1312  LOG(VB_GENERAL, LOG_ERR, LOC + m_error);
1313  return;
1314  }
1315 
1316  if (m_videocodec == "mpeg2video")
1318  else
1320 
1321  if (ioctl(m_fd, GO7007IOC_S_MPEG_PARAMS, &mpeg) < 0)
1322  {
1323  m_error = "Unable to set MPEG params";
1324  LOG(VB_GENERAL, LOG_ERR, LOC + m_error);
1325  return;
1326  }
1327 
1328  int usebitrate = m_targetBitRate * 1000;
1329  if (m_scaleBitRate)
1330  {
1331  float diff = (m_width * m_height) / (640.0 * 480.0);
1332  usebitrate = (int)(diff * usebitrate);
1333  }
1334 
1335  if (ioctl(m_fd, GO7007IOC_S_BITRATE, &usebitrate) < 0)
1336  {
1337  m_error = "Unable to set bitrate";
1338  LOG(VB_GENERAL, LOG_ERR, LOC + m_error);
1339  return;
1340  }
1341 
1342  m_hardwareEncode = true;
1343  }
1344 
1345  uint numbuffers = MAX_VIDEO_BUFFERS;
1346 
1347  vrbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1348  vrbuf.memory = V4L2_MEMORY_MMAP;
1349  vrbuf.count = numbuffers;
1350 
1351  if (ioctl(m_fd, VIDIOC_REQBUFS, &vrbuf) < 0)
1352  {
1353  m_error = "Not able to get any capture buffers, exiting";
1354  LOG(VB_GENERAL, LOG_ERR, LOC + m_error);
1355  return;
1356  }
1357 
1358  if (vrbuf.count < numbuffers)
1359  {
1360  LOG(VB_GENERAL, LOG_INFO, LOC +
1361  QString("Requested %1 buffers, but only %2 are available. "
1362  "Proceeding anyway").arg(numbuffers).arg(vrbuf.count));
1363  }
1364 
1365  numbuffers = vrbuf.count;
1366 
1367  std::array<uint8_t*,MAX_VIDEO_BUFFERS> buffers {};
1368  std::array<int,MAX_VIDEO_BUFFERS> bufferlen {};
1369 
1370  for (uint i = 0; i < numbuffers; i++)
1371  {
1372  vbuf.type = vrbuf.type;
1373  vbuf.index = i;
1374 
1375  if (ioctl(m_fd, VIDIOC_QUERYBUF, &vbuf) < 0)
1376  {
1377  LOG(VB_GENERAL, LOG_ERR, LOC +
1378  QString("unable to query capture buffer %1").arg(i));
1379  m_error = "Unable to query capture buffer";
1380  return;
1381  }
1382 
1383  buffers[i] = (unsigned char *)mmap(nullptr, vbuf.length,
1384  PROT_READ|PROT_WRITE, MAP_SHARED,
1385  m_fd, vbuf.m.offset);
1386 
1387  if (buffers[i] == MAP_FAILED)
1388  {
1389  LOG(VB_GENERAL, LOG_ERR, LOC + "mmap: " + ENO);
1390  LOG(VB_GENERAL, LOG_ERR, LOC + "Memory map failed");
1391  m_error = "Memory map failed";
1392  return;
1393  }
1394  bufferlen[i] = vbuf.length;
1395  }
1396 
1397  for (uint i = 0; i < numbuffers; i++)
1398  {
1399  memset(buffers[i], 0, bufferlen[i]);
1400  vbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1401  vbuf.index = i;
1402  if (ioctl(m_fd, VIDIOC_QBUF, &vbuf) < 0)
1403  LOG(VB_GENERAL, LOG_ERR, LOC + "unable to enqueue capture buffer (VIDIOC_QBUF failed) " + ENO);
1404  }
1405 
1406  int turnon = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1407  if (ioctl(m_fd, VIDIOC_STREAMON, &turnon) < 0)
1408  LOG(VB_GENERAL, LOG_ERR, LOC + "unable to start capture (VIDIOC_STREAMON failed) " + ENO);
1409 
1410  struct timeval tv {};
1411  fd_set rdset {};
1412  int frame = 0;
1413  bool forcekey = false;
1414 
1415  m_resetCapture = false;
1416 
1417  // setup pixel format conversions for YUYV and UYVY
1418  uint8_t *output_buffer = nullptr;
1419  struct SwsContext *convert_ctx = nullptr;
1420  AVFrame img_out;
1421  if (m_v4l2PixelFormat == V4L2_PIX_FMT_YUYV ||
1422  m_v4l2PixelFormat == V4L2_PIX_FMT_UYVY)
1423  {
1424  AVPixelFormat in_pixfmt = m_v4l2PixelFormat == V4L2_PIX_FMT_YUYV ?
1425  AV_PIX_FMT_YUYV422 :
1426  AV_PIX_FMT_UYVY422;
1427 
1428  output_buffer = (uint8_t*)av_malloc(m_height * m_width * 3 / 2);
1429  if (!output_buffer)
1430  {
1431  m_error = "Cannot initialize image conversion buffer";
1432  LOG(VB_GENERAL, LOG_ERR, LOC + m_error);
1433  return;
1434  }
1435 
1436  convert_ctx = sws_getCachedContext(convert_ctx, m_width, m_height, in_pixfmt,
1437  m_width, m_height, AV_PIX_FMT_YUV420P,
1438  SWS_FAST_BILINEAR, nullptr, nullptr, nullptr);
1439  if (!convert_ctx)
1440  {
1441  m_error = "Cannot initialize image conversion context";
1442  av_free(output_buffer);
1443  LOG(VB_GENERAL, LOG_ERR, LOC + m_error);
1444  return;
1445  }
1446 
1447  av_image_fill_arrays(img_out.data, img_out.linesize,
1448  output_buffer, AV_PIX_FMT_YUV420P, m_width, m_height, IMAGE_ALIGN);
1449  }
1450 
1451  while (IsRecordingRequested() && !IsErrored())
1452  {
1453 again:
1454  {
1455  QMutexLocker locker(&m_pauseLock);
1456  if (m_requestPause)
1457  {
1458  if (!m_mainPaused)
1459  {
1460  m_mainPaused = true;
1461  m_pauseWait.wakeAll();
1462  if (IsPaused(true) && m_tvrec)
1464  }
1465  m_unpauseWait.wait(&m_pauseLock, 100);
1466  if (m_clearTimeOnPause)
1467  gettimeofday(&m_stm, &m_tzone);
1468  continue;
1469  }
1470 
1471  if (!m_requestPause && m_mainPaused)
1472  {
1473  m_mainPaused = false;
1474  m_unpauseWait.wakeAll();
1475  }
1476  }
1477 
1478  if (m_resetCapture)
1479  {
1480  LOG(VB_GENERAL, LOG_ERR, LOC + "Resetting and re-queueing");
1481  turnon = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1482  if (ioctl(m_fd, VIDIOC_STREAMOFF, &turnon) < 0)
1483  LOG(VB_GENERAL, LOG_ERR, LOC + "unable to stop capture (VIDIOC_STREAMOFF failed) " + ENO);
1484 
1485  for (uint i = 0; i < numbuffers; i++)
1486  {
1487  memset(buffers[i], 0, bufferlen[i]);
1488  vbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1489  vbuf.index = i;
1490  if (ioctl(m_fd, VIDIOC_QBUF, &vbuf) < 0)
1491  LOG(VB_GENERAL, LOG_ERR, LOC + "unable to enqueue capture buffer (VIDIOC_QBUF failed) " + ENO);
1492  }
1493 
1494  if (ioctl(m_fd, VIDIOC_STREAMON, &turnon) < 0)
1495  LOG(VB_GENERAL, LOG_ERR, LOC + "unable to start capture (VIDIOC_STREAMON failed) " + ENO);
1496  m_resetCapture = false;
1497  }
1498 
1499  tv.tv_sec = 5;
1500  tv.tv_usec = 0;
1501  FD_ZERO(&rdset); // NOLINT(readability-isolate-declaration)
1502  FD_SET(m_fd, &rdset);
1503 
1504  switch (select(m_fd+1, &rdset, nullptr, nullptr, &tv))
1505  {
1506  case -1:
1507  if (errno == EINTR)
1508  goto again;
1509  LOG(VB_GENERAL, LOG_ERR, LOC + "select: " + ENO);
1510  continue;
1511  case 0:
1512  LOG(VB_GENERAL, LOG_INFO, LOC + "select timeout");
1513  continue;
1514  default: break;
1515  }
1516 
1517  memset(&vbuf, 0, sizeof(vbuf));
1518  vbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1519  vbuf.memory = V4L2_MEMORY_MMAP;
1520  if (ioctl(m_fd, VIDIOC_DQBUF, &vbuf) < 0)
1521  {
1522  LOG(VB_GENERAL, LOG_ERR, LOC + "DQBUF ioctl failed." + ENO);
1523 
1524  // EIO failed DQBUF de-tunes post 2.6.15.3 for cx88
1525  // EIO or EINVAL on bttv means we need to reset the buffers..
1526  if (errno == EIO && m_channelObj)
1527  {
1528  m_channelObj->Retune();
1529  m_resetCapture = true;
1530  continue;
1531  }
1532 
1533  if (errno == EIO || errno == EINVAL)
1534  {
1535  m_resetCapture = true;
1536  continue;
1537  }
1538 
1539  if (errno == EAGAIN)
1540  continue;
1541  }
1542 
1543  frame = vbuf.index;
1544  if (m_go7007)
1545  forcekey = ((vbuf.flags & V4L2_BUF_FLAG_KEYFRAME) != 0U);
1546 
1547  if (!m_requestPause)
1548  {
1549  if ((m_v4l2PixelFormat == V4L2_PIX_FMT_YUYV) &&
1550  (output_buffer != nullptr))
1551  {
1552  AVFrame img_in;
1553  av_image_fill_arrays(img_in.data, img_in.linesize,
1554  buffers[frame], AV_PIX_FMT_YUYV422, m_width, m_height,
1555  IMAGE_ALIGN);
1556  sws_scale(convert_ctx, img_in.data, img_in.linesize,
1557  0, m_height, img_out.data, img_out.linesize);
1558  BufferIt(output_buffer, m_videoBufferSize);
1559  }
1560  else if ((m_v4l2PixelFormat == V4L2_PIX_FMT_UYVY) &&
1561  (output_buffer != nullptr))
1562  {
1563  AVFrame img_in;
1564  av_image_fill_arrays(img_in.data, img_in.linesize,
1565  buffers[frame], AV_PIX_FMT_UYVY422, m_width, m_height,
1566  IMAGE_ALIGN);
1567  sws_scale(convert_ctx, img_in.data, img_in.linesize,
1568  0, m_height, img_out.data, img_out.linesize);
1569  BufferIt(output_buffer, m_videoBufferSize);
1570  }
1571  else
1572  {
1573  // buffer the frame directly
1574  BufferIt(buffers[frame], vbuf.bytesused, forcekey);
1575  }
1576  }
1577 
1578  vbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1579  if (ioctl(m_fd, VIDIOC_QBUF, &vbuf) < 0)
1580  LOG(VB_GENERAL, LOG_ERR, LOC + "unable to enqueue capture buffer (VIDIOC_QBUF failed) " + ENO);
1581  }
1582 
1583  KillChildren();
1584 
1585  if (ioctl(m_fd, VIDIOC_STREAMOFF, &turnon) < 0)
1586  LOG(VB_GENERAL, LOG_ERR, LOC + "unable to stop capture (VIDIOC_STREAMOFF failed) " + ENO);
1587 
1588  for (uint i = 0; i < numbuffers; i++)
1589  {
1590  munmap(buffers[i], bufferlen[i]);
1591  }
1592 
1593  FinishRecording();
1594 
1595  av_free(output_buffer);
1596  sws_freeContext(convert_ctx);
1597 
1598  close(m_fd);
1599  close(m_channelFd);
1600 }
1601 #else // if !USING_V4L2
1602 void NuppelVideoRecorder::DoV4L2(void) {}
1603 #endif // !USING_V4L2
1604 
1605 #ifdef USING_V4L1
1607 {
1608  struct mjpeg_params bparm;
1609 
1610  if (ioctl(m_fd, MJPIOC_G_PARAMS, &bparm) < 0)
1611  {
1612  LOG(VB_GENERAL, LOG_ERR, LOC + "MJPIOC_G_PARAMS: " + ENO);
1613  return;
1614  }
1615 
1616  //bparm.input = 2;
1617  //bparm.norm = 1;
1618  bparm.quality = m_hmjpgQuality;
1619 
1621  {
1623  }
1624  else
1625  {
1626  bparm.decimation = 0;
1627  bparm.HorDcm = m_hmjpgHDecimation;
1628  bparm.VerDcm = (m_hmjpgVDecimation + 1) / 2;
1629 
1630  if (m_hmjpgVDecimation == 1)
1631  {
1632  bparm.TmpDcm = 1;
1633  bparm.field_per_buff = 2;
1634  }
1635  else
1636  {
1637  bparm.TmpDcm = 2;
1638  bparm.field_per_buff = 1;
1639  }
1640 
1641  bparm.img_width = m_hmjpgMaxW;
1642 
1643  if (m_ntsc)
1644  bparm.img_height = 240;
1645  else
1646  bparm.img_height = 288;
1647 
1648  bparm.img_x = 0;
1649  bparm.img_y = 0;
1650  }
1651 
1652  bparm.APPn = 0;
1653 
1654  if (m_hmjpgVDecimation == 1)
1655  bparm.APP_len = 14;
1656  else
1657  bparm.APP_len = 0;
1658 
1659  bparm.odd_even = !(m_hmjpgVDecimation > 1);
1660 
1661  for (int n = 0; n < bparm.APP_len; n++)
1662  bparm.APP_data[n] = 0;
1663 
1664  if (ioctl(m_fd, MJPIOC_S_PARAMS, &bparm) < 0)
1665  {
1666  LOG(VB_GENERAL, LOG_DEBUG, LOC + "MJPIOC_S_PARAMS: " + ENO);
1667  return;
1668  }
1669 
1670  struct mjpeg_requestbuffers breq;
1671 
1672  breq.count = 64;
1673  breq.size = 256 * 1024;
1674 
1675  if (ioctl(m_fd, MJPIOC_REQBUFS, &breq) < 0)
1676  {
1677  LOG(VB_GENERAL, LOG_DEBUG, LOC + "MJPIOC_REQBUFS: " + ENO);
1678  return;
1679  }
1680 
1681  uint8_t *MJPG_buff = (uint8_t *)mmap(0, breq.count * breq.size,
1682  PROT_READ|PROT_WRITE, MAP_SHARED, m_fd,
1683  0);
1684 
1685  if (MJPG_buff == MAP_FAILED)
1686  {
1687  LOG(VB_GENERAL, LOG_ERR, LOC + "mapping mjpeg buffers");
1688  return;
1689  }
1690 
1691  struct mjpeg_sync bsync;
1692 
1693  for (unsigned int count = 0; count < breq.count; count++)
1694  {
1695  if (ioctl(m_fd, MJPIOC_QBUF_CAPT, &count) < 0)
1696  LOG(VB_GENERAL, LOG_ERR, LOC + "MJPIOC_QBUF_CAPT: " + ENO);
1697  }
1698 
1699  while (IsRecordingRequested() && !IsErrored())
1700  {
1701  {
1702  QMutexLocker locker(&m_pauseLock);
1703  if (m_request_pause)
1704  {
1705  if (!m_mainPaused)
1706  {
1707  m_mainPaused = true;
1708  m_pauseWait.wakeAll();
1709  if (IsPaused(true) && m_tvrec)
1711  }
1712  m_unpauseWait.wait(&m_pauseLock, 100);
1713  if (m_clearTimeOnPause)
1714  gettimeofday(&m_stm, &m_tzone);
1715  continue;
1716  }
1717 
1718  if (!m_request_pause && m_mainPaused)
1719  {
1720  m_mainPaused = false;
1721  m_unpauseWait.wakeAll();
1722  }
1723  }
1724 
1725  if (ioctl(m_fd, MJPIOC_SYNC, &bsync) < 0)
1726  {
1727  m_error = "MJPEG sync error";
1728  LOG(VB_GENERAL, LOG_ERR, LOC + m_error + ENO);
1729  break;
1730  }
1731 
1732  BufferIt((unsigned char *)(MJPG_buff + bsync.frame * breq.size),
1733  bsync.length);
1734 
1735  if (ioctl(m_fd, MJPIOC_QBUF_CAPT, &(bsync.frame)) < 0)
1736  {
1737  m_error = "MJPEG Capture error";
1738  LOG(VB_GENERAL, LOG_ERR, LOC + m_error + ENO);
1739  }
1740  }
1741 
1742  munmap(MJPG_buff, breq.count * breq.size);
1743  KillChildren();
1744 
1745  FinishRecording();
1746 
1747  close(m_fd);
1748 }
1749 #else // if !USING_V4L1
1750 void NuppelVideoRecorder::DoMJPEG(void) {}
1751 #endif // !USING_V4L1
1752 
1754 {
1755  {
1756  QMutexLocker locker(&m_pauseLock);
1757  m_requestHelper = false;
1758  m_unpauseWait.wakeAll();
1759  }
1760 
1761  if (m_writeThread)
1762  {
1763  m_writeThread->wait();
1764  delete m_writeThread;
1765  m_writeThread = nullptr;
1766  }
1767 
1768  if (m_audioThread)
1769  {
1770  m_audioThread->wait();
1771  delete m_audioThread;
1772  m_audioThread = nullptr;
1773  }
1774 
1775  if (m_vbiThread)
1776  {
1777  m_vbiThread->wait();
1778  delete m_vbiThread;
1779  m_vbiThread = nullptr;
1780  CloseVBIDevice();
1781  }
1782 }
1783 
1784 void NuppelVideoRecorder::BufferIt(unsigned char *buf, int len, bool forcekey)
1785 {
1786  struct timeval now {};
1787 
1788  int act = m_actVideoBuffer;
1789 
1790  if (!m_videoBuffer[act]->freeToBuffer) {
1791  return;
1792  }
1793 
1794  gettimeofday(&now, &m_tzone);
1795 
1796  long tcres = (now.tv_sec-m_stm.tv_sec)*1000 + now.tv_usec/1000 - m_stm.tv_usec/1000;
1797 
1798  m_useBttv = 0;
1799  // here is the non preferable timecode - drop algorithm - fallback
1800  if (!m_useBttv)
1801  {
1802  if (m_tf==0)
1803  m_tf = 2;
1804  else
1805  {
1806  int fn = tcres - m_oldTc;
1807 
1808  // the difference should be less than 1,5*timeperframe or we have
1809  // missed at least one frame, this code might be inaccurate!
1810 
1811  if (m_ntscFrameRate)
1812  fn = (fn+16)/33;
1813  else
1814  fn = (fn+20)/40;
1815  if (fn<1)
1816  fn=1;
1817  m_tf += 2*fn; // two fields
1818  }
1819  }
1820 
1821  m_oldTc = tcres;
1822 
1823  if (!m_videoBuffer[act]->freeToBuffer)
1824  {
1825  LOG(VB_GENERAL, LOG_INFO, LOC +
1826  "DROPPED frame due to full buffer in the recorder.");
1827  return; // we can't buffer the current frame
1828  }
1829 
1830  m_videoBuffer[act]->sample = m_tf;
1831 
1832  // record the time at the start of this frame.
1833  // 'tcres' is at the end of the frame, so subtract the right # of ms
1834  m_videoBuffer[act]->timecode = (m_ntscFrameRate) ? (tcres - 33) : (tcres - 40);
1835 
1836  memcpy(m_videoBuffer[act]->buffer, buf, len);
1837  m_videoBuffer[act]->bufferlen = len;
1838  m_videoBuffer[act]->forcekey = forcekey;
1839 
1840  m_videoBuffer[act]->freeToBuffer = 0;
1841  m_actVideoBuffer++;
1843  m_actVideoBuffer = 0; // cycle to begin of buffer
1844  m_videoBuffer[act]->freeToEncode = 1; // set last to prevent race
1845 }
1846 
1848 {
1849 #if HAVE_BIGENDIAN
1850  fh->timecode = bswap_32(fh->timecode);
1851  fh->packetlength = bswap_32(fh->packetlength);
1852 #endif
1854 }
1855 
1857 {
1858  if (newaspect == static_cast<double>(m_videoAspect))
1859  return;
1860 
1861  m_videoAspect = newaspect;
1862 
1863  struct rtframeheader frameheader {};
1864 
1865  frameheader.frametype = 'S';
1866  frameheader.comptype = 'M';
1867  frameheader.packetlength = sizeof(struct rtfileheader);
1868 
1869  WriteFrameheader(&frameheader);
1870 
1871  WriteFileHeader();
1872 }
1873 
1875 {
1876  struct rtfileheader fileheader {};
1877  static const std::string kFinfo { "MythTVVideo" };
1878  static const std::string kVers { "0.07" };
1879 
1880  std::copy(kFinfo.cbegin(), kFinfo.cend(), fileheader.finfo);
1881  std::copy(kVers.cbegin(), kVers.cend(), fileheader.version);
1882  fileheader.width = m_wOut;
1883  fileheader.height = (int)(m_hOut * m_heightMultiplier);
1884  fileheader.desiredwidth = 0;
1885  fileheader.desiredheight = 0;
1886  fileheader.pimode = 'P';
1887  fileheader.aspect = m_videoAspect;
1888  fileheader.fps = m_videoFrameRate;
1889  fileheader.fps *= m_frameRateMultiplier;
1890  fileheader.videoblocks = -1;
1891  fileheader.audioblocks = -1;
1892  fileheader.textsblocks = -1; // TODO: make only -1 if VBI support active?
1893  fileheader.keyframedist = KEYFRAMEDIST;
1894 
1895 #if HAVE_BIGENDIAN
1896  fileheader.width = bswap_32(fileheader.width);
1897  fileheader.height = bswap_32(fileheader.height);
1898  fileheader.desiredwidth = bswap_32(fileheader.desiredwidth);
1899  fileheader.desiredheight = bswap_32(fileheader.desiredheight);
1900  fileheader.aspect = bswap_dbl(fileheader.aspect);
1901  fileheader.fps = bswap_dbl(fileheader.fps);
1902  fileheader.videoblocks = bswap_32(fileheader.videoblocks);
1903  fileheader.audioblocks = bswap_32(fileheader.audioblocks);
1904  fileheader.textsblocks = bswap_32(fileheader.textsblocks);
1905  fileheader.keyframedist = bswap_32(fileheader.keyframedist);
1906 #endif
1907  m_ringBuffer->Write(&fileheader, FILEHEADERSIZE);
1908 }
1909 
1911 {
1912  struct rtframeheader frameheader {};
1913 
1914  WriteFileHeader();
1915 
1916  frameheader.frametype = 'D'; // compressor data
1917 
1918  if (m_useAvCodec)
1919  {
1920  frameheader.comptype = 'F';
1921  frameheader.packetlength = m_mpaVidCtx->extradata_size;
1922 
1923  WriteFrameheader(&frameheader);
1924  m_ringBuffer->Write(m_mpaVidCtx->extradata, frameheader.packetlength);
1925  }
1926  else
1927  {
1928  static std::array<uint32_t,128> s_tbls {};
1929 
1930  frameheader.comptype = 'R'; // compressor data for RTjpeg
1931  frameheader.packetlength = s_tbls.size() * sizeof(uint32_t);
1932 
1933  // compression configuration header
1934  WriteFrameheader(&frameheader);
1935 
1936  m_ringBuffer->Write(s_tbls.data(), s_tbls.size() * sizeof(uint32_t));
1937  }
1938 
1939  memset(&frameheader, 0, sizeof(frameheader));
1940  frameheader.frametype = 'X'; // extended data
1941  frameheader.packetlength = sizeof(extendeddata);
1942 
1943  // extended data header
1944  WriteFrameheader(&frameheader);
1945 
1946  struct extendeddata moredata {};
1947 
1948  moredata.version = 1;
1949  if (m_useAvCodec)
1950  {
1951  int vidfcc = 0;
1952  switch(m_mpaVidCodec->id)
1953  {
1954  case AV_CODEC_ID_MPEG4: vidfcc = FOURCC_DIVX; break;
1955  case AV_CODEC_ID_WMV1: vidfcc = FOURCC_WMV1; break;
1956  case AV_CODEC_ID_MSMPEG4V3: vidfcc = FOURCC_DIV3; break;
1957  case AV_CODEC_ID_MSMPEG4V2: vidfcc = FOURCC_MP42; break;
1958  case AV_CODEC_ID_MSMPEG4V1: vidfcc = FOURCC_MPG4; break;
1959  case AV_CODEC_ID_MJPEG: vidfcc = FOURCC_MJPG; break;
1960  case AV_CODEC_ID_H263:
1961  case AV_CODEC_ID_H263P: vidfcc = FOURCC_H263; break;
1962  case AV_CODEC_ID_H263I: vidfcc = FOURCC_I263; break;
1963  case AV_CODEC_ID_MPEG1VIDEO: vidfcc = FOURCC_MPEG; break;
1964  case AV_CODEC_ID_MPEG2VIDEO: vidfcc = FOURCC_MPG2; break;
1965  case AV_CODEC_ID_HUFFYUV: vidfcc = FOURCC_HFYU; break;
1966  default: break;
1967  }
1968  moredata.video_fourcc = vidfcc;
1969  moredata.lavc_bitrate = m_mpaVidCtx->bit_rate;
1970  moredata.lavc_qmin = m_mpaVidCtx->qmin;
1971  moredata.lavc_qmax = m_mpaVidCtx->qmax;
1972  moredata.lavc_maxqdiff = m_mpaVidCtx->max_qdiff;
1973  }
1974  else
1975  {
1976  moredata.video_fourcc = FOURCC_RJPG;
1977  moredata.rtjpeg_quality = m_q;
1978  moredata.rtjpeg_luma_filter = m_m1;
1979  moredata.rtjpeg_chroma_filter = m_m2;
1980  }
1981 
1982  if (m_compressAudio)
1983  {
1984  moredata.audio_fourcc = FOURCC_LAME;
1985  moredata.audio_compression_ratio = 11;
1986  moredata.audio_quality = m_mp3Quality;
1987  }
1988  else
1989  {
1990  moredata.audio_fourcc = FOURCC_RAWA;
1991  }
1992 
1994  moredata.audio_channels = m_audioChannels;
1996 
1998 
1999 #if HAVE_BIGENDIAN
2000  moredata.version = bswap_32(moredata.version);
2001  moredata.video_fourcc = bswap_32(moredata.video_fourcc);
2002  moredata.audio_fourcc = bswap_32(moredata.audio_fourcc);
2003  moredata.audio_sample_rate = bswap_32(moredata.audio_sample_rate);
2004  moredata.audio_bits_per_sample = bswap_32(moredata.audio_bits_per_sample);
2005  moredata.audio_channels = bswap_32(moredata.audio_channels);
2006  moredata.audio_compression_ratio = bswap_32(moredata.audio_compression_ratio);
2007  moredata.audio_quality = bswap_32(moredata.audio_quality);
2008  moredata.rtjpeg_quality = bswap_32(moredata.rtjpeg_quality);
2009  moredata.rtjpeg_luma_filter = bswap_32(moredata.rtjpeg_luma_filter);
2010  moredata.rtjpeg_chroma_filter = bswap_32(moredata.rtjpeg_chroma_filter);
2011  moredata.lavc_bitrate = bswap_32(moredata.lavc_bitrate);
2012  moredata.lavc_qmin = bswap_32(moredata.lavc_qmin);
2013  moredata.lavc_qmax = bswap_32(moredata.lavc_qmax);
2014  moredata.lavc_maxqdiff = bswap_32(moredata.lavc_maxqdiff);
2015  moredata.seektable_offset = bswap_64(moredata.seektable_offset);
2016  moredata.keyframeadjust_offset = bswap_64(moredata.keyframeadjust_offset);
2017 #endif
2018  m_ringBuffer->Write(&moredata, sizeof(moredata));
2019 
2020  m_lastBlock = 0;
2021  m_lf = 0; // that resets framenumber so that seeking in the
2022  // continues parts works too
2023 }
2024 
2026 {
2027  int numentries = m_seekTable->size();
2028 
2029  struct rtframeheader frameheader {};
2030  frameheader.frametype = 'Q'; // SeekTable
2031  frameheader.packetlength = sizeof(struct seektable_entry) * numentries;
2032 
2033  long long currentpos = m_ringBuffer->GetWritePosition();
2034 
2035  m_ringBuffer->Write(&frameheader, sizeof(frameheader));
2036 
2037  char *seekbuf = new char[frameheader.packetlength];
2038  int offset = 0;
2039 
2040  for (auto & entry : *m_seekTable)
2041  {
2042  memcpy(seekbuf + offset, (const void *)&entry,
2043  sizeof(struct seektable_entry));
2044  offset += sizeof(struct seektable_entry);
2045  }
2046 
2047  m_ringBuffer->Write(seekbuf, frameheader.packetlength);
2048 
2050  offsetof(struct extendeddata, seektable_offset),
2051  SEEK_SET);
2052 
2053  m_ringBuffer->Write(&currentpos, sizeof(long long));
2054 
2055  m_ringBuffer->WriterSeek(0, SEEK_END);
2056 
2057  delete [] seekbuf;
2058 }
2059 
2061  const std::vector<struct kfatable_entry> &kfa_table)
2062 {
2063  int numentries = kfa_table.size();
2064 
2065  struct rtframeheader frameheader {};
2066  frameheader.frametype = 'K'; // KFA Table
2067  frameheader.packetlength = sizeof(struct kfatable_entry) * numentries;
2068 
2069  long long currentpos = m_ringBuffer->GetWritePosition();
2070 
2071  m_ringBuffer->Write(&frameheader, sizeof(frameheader));
2072 
2073  char *kfa_buf = new char[frameheader.packetlength];
2074  uint offset = 0;
2075 
2076  for (auto kfa : kfa_table)
2077  {
2078  memcpy(kfa_buf + offset, &kfa,
2079  sizeof(struct kfatable_entry));
2080  offset += sizeof(struct kfatable_entry);
2081  }
2082 
2083  m_ringBuffer->Write(kfa_buf, frameheader.packetlength);
2084 
2085 
2087  offsetof(struct extendeddata, keyframeadjust_offset),
2088  SEEK_SET);
2089 
2090  m_ringBuffer->Write(&currentpos, sizeof(long long));
2091 
2092  m_ringBuffer->WriterSeek(0, SEEK_END);
2093 
2094  delete [] kfa_buf;
2095 }
2096 
2097 void NuppelVideoRecorder::UpdateSeekTable(int frame_num, long offset)
2098 {
2099  long long position = m_ringBuffer->GetWritePosition() + offset;
2100  struct seektable_entry ste { position, frame_num};
2101  m_seekTable->push_back(ste);
2102 
2103  m_positionMapLock.lock();
2104  if (!m_positionMap.contains(ste.keyframe_number))
2105  {
2106  m_positionMapDelta[ste.keyframe_number] = position;
2107  m_positionMap[ste.keyframe_number] = position;
2108  m_lastPositionMapPos = position;
2109  }
2110  m_positionMapLock.unlock();
2111 }
2112 
2114 {
2115  m_framesWritten = 0;
2116 
2117  if (!m_ringBuffer)
2118  {
2119  LOG(VB_GENERAL, LOG_ERR, LOC +
2120  "No ringbuffer, recorder wasn't initialized.");
2121  return -1;
2122  }
2123 
2124  if (!m_ringBuffer->IsOpen())
2125  {
2126  LOG(VB_GENERAL, LOG_ERR, LOC + "Ringbuffer isn't open");
2127  return -1;
2128  }
2129 
2130  WriteHeader();
2131 
2132  return 0;
2133 }
2134 
2136 {
2137  ResetForNewFile();
2138 
2139  for (int i = 0; i < m_videoBufferCount; i++)
2140  {
2141  vidbuffertype *vidbuf = m_videoBuffer[i];
2142  vidbuf->sample = 0;
2143  vidbuf->timecode = 0;
2144  vidbuf->freeToEncode = 0;
2145  vidbuf->freeToBuffer = 1;
2146  vidbuf->forcekey = false;
2147  }
2148 
2149  for (int i = 0; i < m_audioBufferCount; i++)
2150  {
2151  audbuffertype *audbuf = m_audioBuffer[i];
2152  audbuf->sample = 0;
2153  audbuf->timecode = 0;
2154  audbuf->freeToEncode = 0;
2155  audbuf->freeToBuffer = 1;
2156  }
2157 
2158  for (int i = 0; i < m_textBufferCount; i++)
2159  {
2160  txtbuffertype *txtbuf = m_textBuffer[i];
2161  txtbuf->freeToEncode = 0;
2162  txtbuf->freeToBuffer = 1;
2163  }
2164 
2165  m_actVideoEncode = 0;
2166  m_actVideoBuffer = 0;
2167  m_actAudioEncode = 0;
2168  m_actAudioBuffer = 0;
2169  m_actAudioSample = 0;
2170  m_actTextEncode = 0;
2171  m_actTextBuffer = 0;
2172 
2173  m_audioBytes = 0;
2174  m_effectiveDsp = 0;
2175 
2176  if (m_useAvCodec)
2178 
2179  if (m_curRecording)
2181 }
2182 
2184 {
2185  if (!m_audioDevice)
2186  {
2187  LOG(VB_GENERAL, LOG_ERR, LOC +
2188  QString("Invalid audio device (%1), exiting").arg(m_audioDeviceName));
2189  return;
2190  }
2191 
2193  {
2194  LOG(VB_GENERAL, LOG_ERR, LOC +
2195  QString("Failed to open audio device %1").arg(m_audioDeviceName));
2196  return;
2197  }
2198 
2199  if (!m_audioDevice->Start())
2200  {
2201  LOG(VB_GENERAL, LOG_ERR, LOC +
2202  QString("Failed to start audio capture on %1").arg(m_audioDeviceName));
2203  return;
2204  }
2205 
2206  struct timeval anow {};
2207  auto *buffer = new unsigned char[m_audioBufferSize];
2209 
2210  while (IsHelperRequested() && !IsErrored())
2211  {
2212  {
2213  QMutexLocker locker(&m_pauseLock);
2214  if (m_requestPause)
2215  {
2216  if (!m_audioPaused)
2217  {
2218  m_audioPaused = true;
2219  m_pauseWait.wakeAll();
2220  if (IsPaused(true) && m_tvrec)
2222  }
2223  m_unpauseWait.wait(&m_pauseLock, 100);
2224  continue;
2225  }
2226 
2227  if (!m_requestPause && m_audioPaused)
2228  {
2229  m_audioPaused = false;
2230  m_unpauseWait.wakeAll();
2231  }
2232  }
2233 
2234  if (!IsHelperRequested() || IsErrored())
2235  break;
2236 
2237  int lastread = m_audioDevice->GetSamples(buffer, m_audioBufferSize);
2238  if (m_audioBufferSize != lastread)
2239  {
2240  LOG(VB_GENERAL, LOG_ERR, LOC +
2241  QString("Short read, %1 of %2 bytes from ")
2242  .arg(lastread).arg(m_audioBufferSize) + m_audioDeviceName);
2243  }
2244 
2245  /* record the current time */
2246  /* Don't assume that the sound device's record buffer is empty
2247  (like we used to.) Measure to see how much stuff is in there,
2248  and correct for it when calculating the timestamp */
2249  gettimeofday(&anow, &m_tzone);
2250  int bytes_read = std::max(m_audioDevice->GetNumReadyBytes(), 0);
2251 
2252  int act = m_actAudioBuffer;
2253 
2254  if (!m_audioBuffer[act]->freeToBuffer)
2255  {
2256  LOG(VB_GENERAL, LOG_ERR, LOC + "Ran out of free AUDIO buffers :-(");
2257  m_actAudioSample++;
2258  continue;
2259  }
2260 
2261  m_audioBuffer[act]->sample = m_actAudioSample;
2262 
2263  /* calculate timecode. First compute the difference
2264  between now and stm (start time) */
2265  m_audioBuffer[act]->timecode = (anow.tv_sec - m_stm.tv_sec) * 1000 +
2266  anow.tv_usec / 1000 - m_stm.tv_usec / 1000;
2267  /* We want the timestamp to point to the start of this
2268  audio chunk. So, subtract off the length of the chunk
2269  and the length of audio still in the capture buffer. */
2270  m_audioBuffer[act]->timecode -= (int)(
2271  (bytes_read + m_audioBufferSize)
2272  * 1000.0 / (m_audioSampleRate * m_audioBytesPerSample));
2273 
2274  memcpy(m_audioBuffer[act]->buffer, buffer, m_audioBufferSize);
2275 
2276  m_audioBuffer[act]->freeToBuffer = 0;
2277  m_actAudioBuffer++;
2279  m_actAudioBuffer = 0;
2280  m_audioBuffer[act]->freeToEncode = 1;
2281 
2282  m_actAudioSample++;
2283  }
2284 
2285  delete [] buffer;
2286 
2287  if (m_audioDevice->IsOpen())
2288  m_audioDevice->Close();
2289 }
2290 
2291 #ifdef USING_V4L2
2293 {
2294  struct timeval tnow {};
2295  gettimeofday(&tnow, &m_tzone);
2296 
2297  int act = m_actTextBuffer;
2298  if (!m_textBuffer[act]->freeToBuffer)
2299  {
2300  LOG(VB_GENERAL, LOG_ERR, LOC +
2301  QString("Teletext #%1: ran out of free TEXT buffers :-(").arg(act));
2302  return;
2303  }
2304 
2305  // calculate timecode:
2306  // compute the difference between now and stm (start time)
2307  m_textBuffer[act]->timecode = (tnow.tv_sec-m_stm.tv_sec) * 1000 +
2308  tnow.tv_usec/1000 - m_stm.tv_usec/1000;
2309  m_textBuffer[act]->pagenr = (vbidata->teletextpage.pgno << 16) +
2310  vbidata->teletextpage.subno;
2311 
2312  unsigned char *inpos = vbidata->teletextpage.data[0];
2313  unsigned char *outpos = m_textBuffer[act]->buffer;
2314  *outpos = 0;
2315  struct teletextsubtitle st {};
2316  std::vector<uint8_t> linebuf {};
2317  linebuf.reserve(VT_WIDTH + 1);
2318 
2319  for (int y = 0; y < VT_HEIGHT; y++)
2320  {
2321  char c = ' ';
2322  char last_c = ' ';
2323  int hid = 0;
2324  int gfx = 0;
2325  int dbl = 0;
2326  int box = 0;
2327  int sep = 0;
2328  int hold = 0;
2329  int visible = 0;
2330  int fg = 7;
2331  int bg = 0;
2332 
2333  for (int x = 0; x < VT_WIDTH; ++x)
2334  {
2335  c = *inpos++;
2336  switch (c)
2337  {
2338  case 0x00 ... 0x07: /* alpha + fg color */
2339  fg = c & 7;
2340  gfx = 0;
2341  sep = 0;
2342  hid = 0;
2343  goto ctrl;
2344  case 0x08: /* flash */
2345  case 0x09: /* steady */
2346  goto ctrl;
2347  case 0x0a: /* end box */
2348  box = 0;
2349  goto ctrl;
2350  case 0x0b: /* start box */
2351  box = 1;
2352  goto ctrl;
2353  case 0x0c: /* normal height */
2354  dbl = 0;
2355  goto ctrl;
2356  case 0x0d: /* double height */
2357  if (y < VT_HEIGHT-2) /* ignored on last 2 lines */
2358  {
2359  dbl = 1;
2360  }
2361  goto ctrl;
2362  case 0x10 ... 0x17: /* gfx + fg color */
2363  fg = c & 7;
2364  gfx = 1;
2365  hid = 0;
2366  goto ctrl;
2367  case 0x18: /* conceal */
2368  hid = 1;
2369  goto ctrl;
2370  case 0x19: /* contiguous gfx */
2371  hid = 0;
2372  sep = 0;
2373  goto ctrl;
2374  case 0x1a: /* separate gfx */
2375  sep = 1;
2376  goto ctrl;
2377  case 0x1c: /* black bf */
2378  bg = 0;
2379  goto ctrl;
2380  case 0x1d: /* new bg */
2381  bg = fg;
2382  goto ctrl;
2383  case 0x1e: /* hold gfx */
2384  hold = 1;
2385  goto ctrl;
2386  case 0x1f: /* release gfx */
2387  hold = 0;
2388  goto ctrl;
2389  case 0x0e: /* SO */
2390  case 0x0f: /* SI */
2391  case 0x1b: /* ESC */
2392  goto ctrl;
2393 
2394  ctrl:
2395  c = ' ';
2396  if (hold && gfx)
2397  c = last_c;
2398  break;
2399  }
2400  if (gfx)
2401  {
2402  if ((c & 0xa0) == 0x20)
2403  {
2404  last_c = c;
2405  c += (c & 0x40) ? 32 : -32;
2406  }
2407  }
2408  if (hid)
2409  c = ' ';
2410 
2411  if (visible || (c != ' '))
2412  {
2413  if (!visible)
2414  {
2415  st.row = y;
2416  st.col = x;
2417  st.dbl = dbl;
2418  st.fg = fg;
2419  st.bg = bg;
2420  linebuf.clear();
2421  }
2422  linebuf.push_back(c);
2423  visible = 1;
2424  }
2425 
2426  (void) box;
2427  (void) sep;
2428  }
2429  if (visible)
2430  {
2431  st.len = linebuf.size() + 1;
2432  int maxlen = 200;
2433  int bufsize = ((outpos - m_textBuffer[act]->buffer + 1) + st.len);
2434  if (bufsize > maxlen)
2435  break;
2436  memcpy(outpos, &st, sizeof(st));
2437  outpos += sizeof(st);
2438  int count = std::max(st.len, static_cast<uint8_t>(41));
2439  std::copy(linebuf.cbegin(), linebuf.cbegin() + count, outpos);
2440  outpos += count;
2441  *outpos = 0;
2442  }
2443  }
2444 
2445  m_textBuffer[act]->bufferlen = outpos - m_textBuffer[act]->buffer + 1;
2446  m_textBuffer[act]->freeToBuffer = 0;
2447  m_actTextBuffer++;
2449  m_actTextBuffer = 0;
2450  m_textBuffer[act]->freeToEncode = 1;
2451 }
2452 #else // USING_V4L2
2453 void NuppelVideoRecorder::FormatTT(struct VBIData*) {}
2454 #endif // USING_V4L2
2455 
2457 {
2458  struct timeval tnow {};
2459  gettimeofday (&tnow, &m_tzone);
2460 
2461  // calculate timecode:
2462  // compute the difference between now and stm (start time)
2463  int tc = (tnow.tv_sec - m_stm.tv_sec) * 1000 +
2464  tnow.tv_usec / 1000 - m_stm.tv_usec / 1000;
2465 
2466  m_ccd->FormatCC(tc, code1, code2);
2467 }
2468 
2469 void NuppelVideoRecorder::AddTextData(unsigned char *buf, int len,
2470  int64_t timecode, char /*type*/)
2471 {
2472  int act = m_actTextBuffer;
2473  if (!m_textBuffer[act]->freeToBuffer)
2474  {
2475  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Teletext#%1").arg(act) +
2476  " ran out of free TEXT buffers :-(");
2477  return;
2478  }
2479 
2480  m_textBuffer[act]->timecode = timecode;
2481  memcpy(m_textBuffer[act]->buffer, buf, len);
2482  m_textBuffer[act]->bufferlen = len + sizeof(ccsubtitle);
2483 
2484  m_textBuffer[act]->freeToBuffer = 0;
2485  m_actTextBuffer++;
2487  m_actTextBuffer = 0;
2488  m_textBuffer[act]->freeToEncode = 1;
2489 }
2490 
2492 {
2493  while (IsHelperRequested() && !IsErrored())
2494  {
2495  {
2496  QMutexLocker locker(&m_pauseLock);
2497  if (m_requestPause)
2498  {
2499  if (!m_writePaused)
2500  {
2501  m_writePaused = true;
2502  m_pauseWait.wakeAll();
2503  if (IsPaused(true) && m_tvrec)
2505  }
2506  m_unpauseWait.wait(&m_pauseLock, 100);
2507  continue;
2508  }
2509 
2510  if (!m_requestPause && m_writePaused)
2511  {
2512  m_writePaused = false;
2513  m_unpauseWait.wakeAll();
2514  }
2515  }
2516 
2517  if (!IsHelperRequested() || IsErrored())
2518  break;
2519 
2521 
2522  enum
2523  { ACTION_NONE,
2524  ACTION_VIDEO,
2525  ACTION_AUDIO,
2526  ACTION_TEXT
2527  } action = ACTION_NONE;
2528  int firsttimecode = -1;
2529 
2530  if (m_videoBuffer[m_actVideoEncode]->freeToEncode)
2531  {
2532  action = ACTION_VIDEO;
2533  firsttimecode = m_videoBuffer[m_actVideoEncode]->timecode;
2534  }
2535 
2536  if (m_audioBufferCount &&
2537  m_audioBuffer[m_actAudioEncode]->freeToEncode &&
2538  (action == ACTION_NONE ||
2539  (m_audioBuffer[m_actAudioEncode]->timecode < firsttimecode)))
2540  {
2541  action = ACTION_AUDIO;
2542  firsttimecode = m_audioBuffer[m_actAudioEncode]->timecode;
2543  }
2544 
2545  if (m_textBufferCount &&
2546  m_textBuffer[m_actTextEncode]->freeToEncode &&
2547  (action == ACTION_NONE ||
2548  (m_textBuffer[m_actTextEncode]->timecode < firsttimecode)))
2549  {
2550  action = ACTION_TEXT;
2551  }
2552 
2553  switch (action)
2554  {
2555  case ACTION_VIDEO:
2556  {
2558  m_videoBuffer[m_actVideoEncode]->bufferlen,
2559  m_width, m_height);
2560  frame.m_frameNumber = m_videoBuffer[m_actVideoEncode]->sample;
2561  frame.m_timecode = m_videoBuffer[m_actVideoEncode]->timecode;
2562  frame.m_forceKey = m_videoBuffer[m_actVideoEncode]->forcekey;
2563  WriteVideo(&frame);
2564  // Ensure buffer isn't deleted
2565  frame.m_buffer = nullptr;
2566 
2567  m_videoBuffer[m_actVideoEncode]->sample = 0;
2568  m_videoBuffer[m_actVideoEncode]->freeToEncode = 0;
2569  m_videoBuffer[m_actVideoEncode]->freeToBuffer = 1;
2570  m_videoBuffer[m_actVideoEncode]->forcekey = false;
2571  m_actVideoEncode++;
2573  m_actVideoEncode = 0;
2574  break;
2575  }
2576  case ACTION_AUDIO:
2577  {
2580  m_audioBuffer[m_actAudioEncode]->timecode);
2581  if (IsErrored()) {
2582  LOG(VB_GENERAL, LOG_ERR, LOC +
2583  "ACTION_AUDIO cannot be completed due to error.");
2584  StopRecording();
2585  break;
2586  }
2587  m_audioBuffer[m_actAudioEncode]->sample = 0;
2588  m_audioBuffer[m_actAudioEncode]->freeToEncode = 0;
2589  m_audioBuffer[m_actAudioEncode]->freeToBuffer = 1;
2590  m_actAudioEncode++;
2592  m_actAudioEncode = 0;
2593  break;
2594  }
2595  case ACTION_TEXT:
2596  {
2598  m_textBuffer[m_actTextEncode]->bufferlen,
2599  m_textBuffer[m_actTextEncode]->timecode,
2600  m_textBuffer[m_actTextEncode]->pagenr);
2601  m_textBuffer[m_actTextEncode]->freeToEncode = 0;
2602  m_textBuffer[m_actTextEncode]->freeToBuffer = 1;
2603  m_actTextEncode++;
2605  m_actTextEncode = 0;
2606  break;
2607  }
2608  default:
2609  {
2610  usleep(100);
2611  break;
2612  }
2613  }
2614  }
2615 }
2616 
2618 {
2619  m_framesWritten = 0;
2620  m_lf = 0;
2621  m_lastBlock = 0;
2622 
2623  m_seekTable->clear();
2624 
2625  ClearStatistics();
2626 
2627  m_positionMapLock.lock();
2628  m_positionMap.clear();
2629  m_positionMapDelta.clear();
2630  m_positionMapLock.unlock();
2631 
2632  if (m_go7007)
2633  m_resetCapture = true;
2634 }
2635 
2637 {
2638  CreateNuppelFile();
2639 }
2640 
2642 {
2644 
2645  WriteSeekTable();
2646 
2648 
2649  m_positionMapLock.lock();
2650  m_positionMap.clear();
2651  m_positionMapDelta.clear();
2652  m_positionMapLock.unlock();
2653 }
2654 
2656  bool forcekey)
2657 {
2658  int tmp = 0;
2659  lzo_uint out_len = OUT_LEN;
2660  struct rtframeheader frameheader {};
2661  int raw = 0;
2662  int compressthis = m_compression;
2663  // cppcheck-suppress variableScope
2664  std::array<uint8_t*,3> planes {
2665  frame->m_buffer + frame->m_offsets[0],
2666  frame->m_buffer + frame->m_offsets[1],
2667  frame->m_buffer + frame->m_offsets[2] };
2668  int fnum = frame->m_frameNumber;
2669  long long timecode = frame->m_timecode;
2670 
2671  if (m_lf == 0)
2672  { // this will be triggered every new file
2673  m_lf = fnum;
2674  m_startNum = fnum;
2675  m_lastTimecode = 0;
2676  m_frameOfGop = 0;
2677  forcekey = true;
2678  }
2679 
2680  // see if it's time for a seeker header, sync information and a keyframe
2681  frameheader.keyframe = m_frameOfGop; // no keyframe defaulted
2682 
2683  bool wantkeyframe = forcekey;
2684 
2685  bool writesync = false;
2686 
2687  if ((!m_go7007 && (((fnum-m_startNum)>>1) % m_keyframeDist == 0 && !skipsync)) ||
2688  (m_go7007 && frame->m_forceKey))
2689  writesync = true;
2690 
2691  if (writesync)
2692  {
2693  m_ringBuffer->Write("RTjjjjjjjjjjjjjjjjjjjjjjjj", FRAMEHEADERSIZE);
2694 
2695  UpdateSeekTable(((fnum - m_startNum) >> 1) / m_keyframeDist);
2696 
2697  frameheader.frametype = 'S'; // sync frame
2698  frameheader.comptype = 'V'; // video sync information
2699  frameheader.filters = 0; // no filters applied
2700  frameheader.packetlength = 0; // no data packet
2701  frameheader.timecode = (fnum-m_startNum)>>1;
2702  // write video sync info
2703  WriteFrameheader(&frameheader);
2704  frameheader.frametype = 'S'; // sync frame
2705  frameheader.comptype = 'A'; // video sync information
2706  frameheader.filters = 0; // no filters applied
2707  frameheader.packetlength = 0; // no data packet
2708  frameheader.timecode = m_effectiveDsp; // effective dsp frequency
2709  // write audio sync info
2710  WriteFrameheader(&frameheader);
2711 
2712  wantkeyframe = true;
2713  //m_ringBuffer->Sync();
2714  }
2715 
2716  if (wantkeyframe)
2717  {
2718  frameheader.keyframe=0;
2719  m_frameOfGop=0;
2720  }
2721 
2722  if (m_useAvCodec)
2723  {
2724  MythAVFrame mpa_picture;
2725  MythAVUtil::FillAVFrame(mpa_picture, frame);
2726 
2727  if (wantkeyframe)
2728  mpa_picture->pict_type = AV_PICTURE_TYPE_I;
2729  else
2730  mpa_picture->pict_type = AV_PICTURE_TYPE_NONE;
2731 
2732  if (!m_hardwareEncode)
2733  {
2734  AVPacket packet;
2735  av_init_packet(&packet);
2736  packet.data = (uint8_t *)m_strm;
2737  packet.size = frame->m_bufferSize;
2738 
2739  int got_packet = 0;
2740  tmp = avcodec_encode_video2(m_mpaVidCtx, &packet, mpa_picture, &got_packet);
2741 
2742  if (tmp < 0 || !got_packet)
2743  {
2744  LOG(VB_GENERAL, LOG_ERR, LOC +
2745  "WriteVideo : avcodec_encode_video() failed");
2746  return;
2747  }
2748 
2749  tmp = packet.size;
2750  }
2751  }
2752  else
2753  {
2754  int freecount = 0;
2755  freecount = m_actVideoBuffer > m_actVideoEncode ?
2758 
2759  if (freecount < (m_videoBufferCount / 3))
2760  compressthis = 0; // speed up the encode process
2761 
2762  if (freecount < 5)
2763  raw = 1; // speed up the encode process
2764 
2765  if (m_transcoding)
2766  {
2767  raw = 0;
2768  compressthis = 1;
2769  }
2770 
2771  if (!raw)
2772  {
2773  if (wantkeyframe)
2774  m_rtjc->SetNextKey();
2775  tmp = m_rtjc->Compress(m_strm, planes.data());
2776  }
2777  else
2778  tmp = frame->m_bufferSize;
2779 
2780  // here is lzo compression afterwards
2781  if (compressthis)
2782  {
2783  int r = 0;
2784  if (raw)
2785  {
2786  r = lzo1x_1_compress(frame->m_buffer, frame->m_bufferSize,
2787  m_out.data(), &out_len, wrkmem.data());
2788  }
2789  else
2790  {
2791  r = lzo1x_1_compress((unsigned char *)m_strm, tmp, m_out.data(),
2792  &out_len, wrkmem.data());
2793  }
2794  if (r != LZO_E_OK)
2795  {
2796  LOG(VB_GENERAL, LOG_ERR, LOC + "lzo compression failed");
2797  return;
2798  }
2799  }
2800  }
2801 
2802  frameheader.frametype = 'V'; // video frame
2803  frameheader.timecode = timecode;
2804  m_lastTimecode = frameheader.timecode;
2805  frameheader.filters = 0; // no filters applied
2806 
2807  // compr ends here
2808  if (m_useAvCodec)
2809  {
2810  if (m_mpaVidCodec->id == AV_CODEC_ID_RAWVIDEO)
2811  {
2812  frameheader.comptype = '0';
2813  frameheader.packetlength = frame->m_bufferSize;
2814  WriteFrameheader(&frameheader);
2815  m_ringBuffer->Write(frame->m_buffer, frame->m_bufferSize);
2816  }
2817  else if (m_hardwareEncode)
2818  {
2819  frameheader.comptype = '4';
2820  frameheader.packetlength = frame->m_bufferSize;
2821  WriteFrameheader(&frameheader);
2822  m_ringBuffer->Write(frame->m_buffer, frame->m_bufferSize);
2823  }
2824  else
2825  {
2826  frameheader.comptype = '4';
2827  frameheader.packetlength = tmp;
2828  WriteFrameheader(&frameheader);
2830  }
2831  }
2832  else if (compressthis == 0 || (tmp < (int)out_len))
2833  {
2834  if (!raw)
2835  {
2836  frameheader.comptype = '1'; // video compression: RTjpeg only
2837  frameheader.packetlength = tmp;
2838  WriteFrameheader(&frameheader);
2840  }
2841  else
2842  {
2843  frameheader.comptype = '0'; // raw YUV420
2844  frameheader.packetlength = frame->m_bufferSize;
2845  WriteFrameheader(&frameheader);
2846  m_ringBuffer->Write(frame->m_buffer, frame->m_bufferSize); // we write buf directly
2847  }
2848  }
2849  else
2850  {
2851  if (!raw)
2852  frameheader.comptype = '2'; // video compression: RTjpeg with lzo
2853  else
2854  frameheader.comptype = '3'; // raw YUV420 with lzo
2855  frameheader.packetlength = out_len;
2856  WriteFrameheader(&frameheader);
2857  m_ringBuffer->Write(m_out.data(), out_len);
2858  }
2859 
2860  if (m_framesWritten == 0)
2861  SendMythSystemRecEvent("REC_STARTED_WRITING", m_curRecording);
2862 
2863  m_frameOfGop++;
2864  m_framesWritten++;
2865 
2866  // now we reset the last frame number so that we can find out
2867  // how many frames we didn't get next time
2868  m_lf = fnum;
2869 }
2870 
2871 #if HAVE_BIGENDIAN
2872 static void bswap_16_buf(short int *buf, int buf_cnt, int audio_channels)
2873  __attribute__ ((unused)); /* <- suppress compiler warning */
2874 
2875 static void bswap_16_buf(short int *buf, int buf_cnt, int audio_channels)
2876 {
2877  for (int i = 0; i < audio_channels * buf_cnt; i++)
2878  buf[i] = bswap_16(buf[i]);
2879 }
2880 #endif
2881 
2882 void NuppelVideoRecorder::WriteAudio(unsigned char *buf, int fnum, int timecode)
2883 {
2884  struct rtframeheader frameheader {};
2885 
2886  if (m_lastBlock == 0)
2887  {
2888  m_firstTc = -1;
2889  }
2890 
2891  if (m_lastBlock != 0)
2892  {
2893  if (fnum != (m_lastBlock+1))
2894  {
2895  m_audioBehind = fnum - (m_lastBlock+1);
2896  LOG(VB_RECORD, LOG_INFO, LOC + QString("audio behind %1 %2").
2897  arg(m_lastBlock).arg(fnum));
2898  }
2899  }
2900 
2901  frameheader.frametype = 'A'; // audio frame
2902  frameheader.timecode = timecode;
2903 
2904  if (m_firstTc == -1)
2905  {
2906  m_firstTc = timecode;
2907 #if 0
2908  LOG(VB_GENERAL, LOG_DEBUG, LOC +
2909  QString("first timecode=%1").arg(m_firstTc));
2910 #endif
2911  }
2912  else
2913  {
2914  timecode -= m_firstTc; // this is to avoid the lack between the beginning
2915  // of recording and the first timestamp, maybe we
2916  // can calculate the audio-video +-lack at the
2917  // beginning too
2918  auto abytes = (double)m_audioBytes; // - (double)m_audioBufferSize;
2919  // wrong guess ;-)
2920  // need seconds instead of msec's
2921  auto mt = (double)timecode;
2922  if (mt > 0.0)
2923  {
2924  double eff = (abytes / mt) * (100000.0 / m_audioBytesPerSample);
2925  m_effectiveDsp = (int)eff;
2926  }
2927  }
2928 
2929  if (m_compressAudio)
2930  {
2931  std::array<uint8_t,7200> mp3gapless {};
2932  int compressedsize = 0;
2933  int gaplesssize = 0;
2934  int lameret = 0;
2935 
2936  int sample_cnt = m_audioBufferSize / m_audioBytesPerSample;
2937 
2938 #if HAVE_BIGENDIAN
2939  bswap_16_buf((short int*) buf, sample_cnt, m_audioChannels);
2940 #endif
2941 
2942  if (m_audioChannels == 2)
2943  {
2944  lameret = lame_encode_buffer_interleaved(
2945  m_gf, (short int*) buf, sample_cnt,
2946  (unsigned char*) m_mp3Buf, m_mp3BufSize);
2947  }
2948  else
2949  {
2950  lameret = lame_encode_buffer(
2951  m_gf, (short int*) buf, (short int*) buf, sample_cnt,
2952  (unsigned char*) m_mp3Buf, m_mp3BufSize);
2953  }
2954 
2955  if (lameret < 0)
2956  {
2957  LOG(VB_GENERAL, LOG_ERR, LOC +
2958  QString("lame error '%1'").arg(lameret));
2959  m_error = QString("Audio Encoding Error '%1'")
2960  .arg(lameret);
2961  return;
2962  }
2963  compressedsize = lameret;
2964 
2965  lameret = lame_encode_flush_nogap(m_gf, mp3gapless.data(), mp3gapless.size());
2966  if (lameret < 0)
2967  {
2968  LOG(VB_GENERAL, LOG_ERR, LOC +
2969  QString("lame error '%1'").arg(lameret));
2970  m_error = QString("Audio Encoding Error '%1'")
2971  .arg(lameret);
2972  return;
2973  }
2974  gaplesssize = lameret;
2975 
2976  frameheader.comptype = '3'; // audio is compressed
2977  frameheader.packetlength = compressedsize + gaplesssize;
2978 
2979  if (frameheader.packetlength > 0)
2980  {
2981  WriteFrameheader(&frameheader);
2982  m_ringBuffer->Write(m_mp3Buf, compressedsize);
2983  m_ringBuffer->Write(mp3gapless.data(), gaplesssize);
2984  }
2986  }
2987  else
2988  {
2989  frameheader.comptype = '0'; // uncompressed audio
2990  frameheader.packetlength = m_audioBufferSize;
2991 
2992  WriteFrameheader(&frameheader);
2994  m_audioBytes += m_audioBufferSize; // only audio no header!!
2995  }
2996 
2997  // this will probably never happen and if there would be a
2998  // 'uncountable' video frame drop -> material==worthless
2999  if (m_audioBehind > 0)
3000  {
3001  LOG(VB_RECORD, LOG_INFO, LOC + "audio behind");
3002  frameheader.frametype = 'A'; // audio frame
3003  frameheader.comptype = 'N'; // output a nullframe with
3004  frameheader.packetlength = 0;
3005  WriteFrameheader(&frameheader);
3007  m_audioBehind--;
3008  }
3009 
3010  m_lastBlock = fnum;
3011 }
3012 
3013 void NuppelVideoRecorder::WriteText(unsigned char *buf, int len, int timecode,
3014  int pagenr)
3015 {
3016  struct rtframeheader frameheader {};
3017 
3018  frameheader.frametype = 'T'; // text frame
3019  frameheader.timecode = timecode;
3020 
3021  if (VBIMode::PAL_TT == m_vbiMode)
3022  {
3023  frameheader.comptype = 'T'; // european teletext
3024  frameheader.packetlength = len + 4;
3025  WriteFrameheader(&frameheader);
3026  union page_t {
3027  int32_t m_val32;
3028  struct { int8_t m_a,m_b,m_c,m_d; } m_val8;
3029  } v {};
3030  v.m_val32 = pagenr;
3031  m_ringBuffer->Write(&v.m_val8.m_d, sizeof(int8_t));
3032  m_ringBuffer->Write(&v.m_val8.m_c, sizeof(int8_t));
3033  m_ringBuffer->Write(&v.m_val8.m_b, sizeof(int8_t));
3034  m_ringBuffer->Write(&v.m_val8.m_a, sizeof(int8_t));
3035  m_ringBuffer->Write(buf, len);
3036  }
3037  else if (VBIMode::NTSC_CC == m_vbiMode)
3038  {
3039  frameheader.comptype = 'C'; // NTSC CC
3040  frameheader.packetlength = len;
3041 
3042  WriteFrameheader(&frameheader);
3043  m_ringBuffer->Write(buf, len);
3044  }
3045 }
3046 
3047 /* vim: set expandtab tabstop=4 shiftwidth=4: */
rtframeheader
Definition: format.h:35
NuppelVideoRecorder::m_channelFd
int m_channelFd
Definition: NuppelVideoRecorder.h:283
CC608Decoder::FormatCC
void FormatCC(int tc, int code1, int code2)
Definition: cc608decoder.cpp:49
NuppelVideoRecorder::m_heightMultiplier
double m_heightMultiplier
Definition: NuppelVideoRecorder.h:241
NuppelVideoRecorder::m_q
int m_q
Definition: NuppelVideoRecorder.h:165
extendeddata::version
int version
Definition: format.h:98
NuppelVideoRecorder::m_actAudioBuffer
int m_actAudioBuffer
Definition: NuppelVideoRecorder.h:205
channel
QDomElement channel
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:501
RecorderBase::SetPositionMapType
void SetPositionMapType(MarkTypes type)
Set seektable type.
Definition: recorderbase.h:278
FOURCC_I263
#define FOURCC_I263
Definition: fourcc.h:96
MARK_KEYFRAME
@ MARK_KEYFRAME
Definition: programtypes.h:62
rtfileheader::fps
double fps
Definition: format.h:27
NuppelVideoRecorder::FormatCC
void FormatCC(uint code1, uint code2) override
Definition: NuppelVideoRecorder.cpp:2456
MThread::start
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:288
ENO
#define ENO
This can be appended to the LOG args with "+".
Definition: mythlogging.h:72
NuppelVideoRecorder::m_keyframeDist
int m_keyframeDist
Definition: NuppelVideoRecorder.h:227
FILEHEADERSIZE
#define FILEHEADERSIZE
Definition: format.h:140
vbi.h
NuppelVideoRecorder::m_audioChannels
int m_audioChannels
Definition: NuppelVideoRecorder.h:173
teletextsubtitle::row
unsigned char row
Definition: format.h:175
copy
long long copy(QFile &dst, QFile &src, uint block_size)
Copies src file to dst file.
Definition: mythmiscutil.cpp:305
NuppelVideoRecorder::m_audioBits
int m_audioBits
Definition: NuppelVideoRecorder.h:174
vidbuffertype::buffer
unsigned char * buffer
Definition: format.h:149
NuppelVideoRecorder::m_actVideoBuffer
int m_actVideoBuffer
Definition: NuppelVideoRecorder.h:202
mjpeg_params::VerDcm
int VerDcm
Definition: videodev_mjpeg.h:30
NuppelVideoRecorder::m_audioBytes
unsigned long long m_audioBytes
Definition: NuppelVideoRecorder.h:172
MAX_VIDEO_BUFFERS
#define MAX_VIDEO_BUFFERS
Definition: NuppelVideoRecorder.cpp:1267
NuppelVideoRecorder::StartNewFile
void StartNewFile(void) override
Definition: NuppelVideoRecorder.cpp:2636
NuppelVideoRecorder::StreamAllocate
void StreamAllocate(void)
Definition: NuppelVideoRecorder.cpp:816
mjpeg_params::img_x
int img_x
Definition: videodev_mjpeg.h:35
V4LRecorder::m_vbiThread
VBIThread * m_vbiThread
Definition: v4lrecorder.h:55
rtfileheader::height
int height
Definition: format.h:21
FrameRate::toDouble
double toDouble(void) const
Definition: recorderbase.h:40
NuppelVideoRecorder::m_encodingThreadCount
int m_encodingThreadCount
Number of threads to use for MPEG-2 and MPEG-4 encoding.
Definition: NuppelVideoRecorder.h:264
NuppelVideoRecorder::m_clearTimeOnPause
bool m_clearTimeOnPause
Definition: NuppelVideoRecorder.h:280
mjpeg_params::APP_len
int APP_len
Definition: videodev_mjpeg.h:56
vidbuffertype::freeToEncode
int freeToEncode
Definition: format.h:147
extendeddata::lavc_maxqdiff
int lavc_maxqdiff
Definition: format.h:117
NuppelVideoRecorder::run
void run(void) override
run() starts the recording process, and does not exit until the recording is complete.
Definition: NuppelVideoRecorder.cpp:883
NuppelVideoRecorder::m_videoBuffer
std::vector< struct vidbuffertype * > m_videoBuffer
Definition: NuppelVideoRecorder.h:195
mjpeg_params::field_per_buff
int field_per_buff
Definition: videodev_mjpeg.h:34
AudioInput::GetBlockSize
virtual int GetBlockSize(void)=0
NuppelVideoRecorder::m_hmjpgHDecimation
int m_hmjpgHDecimation
Definition: NuppelVideoRecorder.h:276
NuppelVideoRecorder::m_actTextEncode
int m_actTextEncode
Definition: NuppelVideoRecorder.h:208
NuppelVideoRecorder::m_videoBufferSize
long m_videoBufferSize
Definition: NuppelVideoRecorder.h:215
NuppelVideoRecorder::m_frameOfGop
int m_frameOfGop
Definition: NuppelVideoRecorder.h:247
V4LRecorder
Abstract base class for Video4Linux based recorders.
Definition: v4lrecorder.h:25
NuppelVideoRecorder::Open
bool Open(void)
Definition: NuppelVideoRecorder.cpp:822
GO7007IOC_S_COMP_PARAMS
#define GO7007IOC_S_COMP_PARAMS
Definition: go7007_myth.h:91
GO7007_ASPECT_RATIO_4_3_NTSC
@ GO7007_ASPECT_RATIO_4_3_NTSC
Definition: go7007_myth.h:29
NuppelVideoRecorder::SetVideoFilters
void SetVideoFilters(QString &filters) override
Tells recorder which filters to use.
Definition: NuppelVideoRecorder.cpp:360
mjpeg_params::TmpDcm
int TmpDcm
Definition: videodev_mjpeg.h:31
NuppelVideoRecorder::m_usingV4l2
bool m_usingV4l2
Definition: NuppelVideoRecorder.h:282
V4LRecorder::m_requestHelper
volatile bool m_requestHelper
Definition: v4lrecorder.h:58
NuppelVideoRecorder.h
MythMediaBuffer::Create
static MythMediaBuffer * Create(const QString &Filename, bool Write, bool UseReadAhead=true, int Timeout=kDefaultOpenTimeout, bool StreamOnly=false)
Creates a RingBuffer instance.
Definition: mythmediabuffer.cpp:100
NuppelVideoRecorder::m_extendedDataOffset
long long m_extendedDataOffset
Definition: NuppelVideoRecorder.h:231
NuppelVideoRecorder::m_textBuffer
std::vector< struct txtbuffertype * > m_textBuffer
Definition: NuppelVideoRecorder.h:199
MythMediaBuffer::GetWritePosition
long long GetWritePosition(void) const
Returns how far into a ThreadedFileWriter file we have written.
Definition: mythmediabuffer.cpp:1779
NuppelVideoRecorder::m_mpaVidCodec
AVCodec * m_mpaVidCodec
Definition: NuppelVideoRecorder.h:253
NuppelVideoRecorder::m_hmjpgQuality
int m_hmjpgQuality
Definition: NuppelVideoRecorder.h:275
vt_page::subno
int subno
Definition: vt.h:38
GO7007_COMP_CLOSED_GOP
#define GO7007_COMP_CLOSED_GOP
Definition: go7007_myth.h:45
NuppelVideoRecorder::m_framesWritten
long long m_framesWritten
Definition: NuppelVideoRecorder.h:233
NuppelVideoRecorder::m_seekTable
std::vector< struct seektable_entry > * m_seekTable
Definition: NuppelVideoRecorder.h:228
CC608Decoder
Definition: cc608decoder.h:47
OUT_LEN
#define OUT_LEN
Definition: NuppelVideoRecorder.h:191
V4LRecorder::OpenVBIDevice
int OpenVBIDevice(void)
Definition: v4lrecorder.cpp:97
MythAVFrame
MythAVFrame little utility class that act as a safe way to allocate an AVFrame which can then be allo...
Definition: mythaverror.h:53
go7007_myth.h
go7007_comp_params::max_b_frames
__u32 max_b_frames
Definition: go7007_myth.h:39
NuppelVideoRecorder::m_lastTimecode
int m_lastTimecode
Definition: NuppelVideoRecorder.h:248
rtfileheader::width
int width
Definition: format.h:20
arg
arg(title).arg(filename).arg(doDelete))
VBIData::teletextpage
vt_page teletextpage
Definition: v4lrecorder.h:19
NuppelVideoRecorder::AudioInit
int AudioInit(bool skipdevice=false)
Definition: NuppelVideoRecorder.cpp:618
extendeddata::audio_channels
int audio_channels
Definition: format.h:104
NuppelVideoRecorder::MJPEGInit
bool MJPEGInit(void)
Determines MJPEG capture resolution.
Definition: NuppelVideoRecorder.cpp:694
RecorderBase::m_tvrec
TVRec * m_tvrec
Definition: recorderbase.h:314
DTVRecorder::IsErrored
bool IsErrored(void) override
Tells us whether an unrecoverable error has been encountered.
Definition: dtvrecorder.h:45
FOURCC_HFYU
#define FOURCC_HFYU
Definition: fourcc.h:95
MythMediaBuffer::Write
int Write(const void *Buffer, uint Count)
Writes buffer to ThreadedFileWriter::Write(const void*,uint)
Definition: mythmediabuffer.cpp:1617
NuppelVideoRecorder::m_audioBytesPerSample
int m_audioBytesPerSample
Definition: NuppelVideoRecorder.h:175
rtfileheader::textsblocks
int textsblocks
Definition: format.h:30
rtfileheader::desiredheight
int desiredheight
Definition: format.h:23
NuppelVideoRecorder::SetupRTjpeg
void SetupRTjpeg(void)
Definition: NuppelVideoRecorder.cpp:484
rtframeheader::timecode
int timecode
Definition: format.h:85
NuppelVideoRecorder::m_writePaused
bool m_writePaused
Definition: NuppelVideoRecorder.h:236
RTjpeg::SetNextKey
void SetNextKey(void)
Definition: RTjpegN.cpp:3265
AudioInput::GetSamples
virtual int GetSamples(void *buf, uint nbytes)=0
seektable_entry
Definition: format.h:128
FMT_YUV422P
@ FMT_YUV422P
Definition: mythframe.h:32
RecorderBase::m_videoWidth
uint m_videoWidth
Definition: recorderbase.h:331
txtbuffertype::freeToEncode
int freeToEncode
Definition: format.h:167
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MThread::RunProlog
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:198
VBIMode::None
@ None
Definition: tv.h:11
channelbase.h
NuppelVideoRecorder::ResizeVideoBuffers
void ResizeVideoBuffers(void)
Definition: NuppelVideoRecorder.cpp:807
NuppelVideoRecorder::m_mp4Opts
int m_mp4Opts
Definition: NuppelVideoRecorder.h:261
NuppelVideoRecorder::m_scaleBitRate
int m_scaleBitRate
Definition: NuppelVideoRecorder.h:257
NuppelVideoRecorder::m_v4l2PixelFormat
uint32_t m_v4l2PixelFormat
Definition: NuppelVideoRecorder.h:269
NuppelVideoRecorder::m_audioThread
NVRAudioThread * m_audioThread
Definition: NuppelVideoRecorder.h:223
mythsystemevent.h
NuppelVideoRecorder::SetNewVideoParams
void SetNewVideoParams(double newaspect)
Definition: NuppelVideoRecorder.cpp:1856
V4LRecorder::VBIThread
friend class VBIThread
Definition: v4lrecorder.h:26
go7007_comp_params::gop_size
__u32 gop_size
Definition: go7007_myth.h:38
GO7007_MPEG_VIDEO_MPEG2
@ GO7007_MPEG_VIDEO_MPEG2
Definition: go7007_myth.h:51
MJPIOC_REQBUFS
#define MJPIOC_REQBUFS
Definition: videodev_mjpeg.h:114
NuppelVideoRecorder::m_videoBufferCount
int m_videoBufferCount
Definition: NuppelVideoRecorder.h:211
MythVideoFrame::m_offsets
FrameOffsets m_offsets
Y, U, & V offsets.
Definition: mythframe.h:124
MythVideoFrame::m_forceKey
bool m_forceKey
hardware encoded .nuv
Definition: mythframe.h:120
NVRWriteThread::run
void run(void) override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
Definition: NuppelVideoRecorder.cpp:70
MJPIOC_QBUF_CAPT
#define MJPIOC_QBUF_CAPT
Definition: videodev_mjpeg.h:115
kfatable_entry
Definition: format.h:134
DTVRecorder::FinishRecording
void FinishRecording(void) override
Flushes the ringbuffer, and if this is not a live LiveTV recording saves the position map and filesiz...
Definition: dtvrecorder.cpp:126
NuppelVideoRecorder::m_actAudioEncode
int m_actAudioEncode
Definition: NuppelVideoRecorder.h:204
NuppelVideoRecorder::m_targetBitRate
int m_targetBitRate
Definition: NuppelVideoRecorder.h:256
NuppelVideoRecorder::m_mp3Quality
int m_mp3Quality
Definition: NuppelVideoRecorder.h:184
NuppelVideoRecorder::m_mbDecision
int m_mbDecision
Definition: NuppelVideoRecorder.h:262
extendeddata::audio_fourcc
int audio_fourcc
Definition: format.h:100
rtfileheader::desiredwidth
int desiredwidth
Definition: format.h:22
NuppelVideoRecorder::m_textBufferCount
int m_textBufferCount
Definition: NuppelVideoRecorder.h:213
NuppelVideoRecorder::m_oldTc
long int m_oldTc
Definition: NuppelVideoRecorder.h:245
NuppelVideoRecorder::WriteAudio
void WriteAudio(unsigned char *buf, int fnum, int timecode)
Definition: NuppelVideoRecorder.cpp:2882
NuppelVideoRecorder::m_compression
int m_compression
Definition: NuppelVideoRecorder.h:169
VBIMode::PAL_TT
@ PAL_TT
Definition: tv.h:12
extendeddata::rtjpeg_chroma_filter
int rtjpeg_chroma_filter
Definition: format.h:112
FOURCC_MJPG
#define FOURCC_MJPG
Definition: fourcc.h:97
vidbuffertype::timecode
int timecode
Definition: format.h:146
audbuffertype
Definition: format.h:155
RecorderBase::m_pauseLock
QMutex m_pauseLock
Definition: recorderbase.h:337
close
#define close
Definition: compat.h:16
V4LRecorder::SetOption
void SetOption(const QString &name, const QString &value) override
Set an specific option.
Definition: v4lrecorder.cpp:59
tmp
static guint32 * tmp
Definition: goom_core.cpp:31
MythVideoFrame::m_timecode
long long m_timecode
Definition: mythframe.h:112
VT_WIDTH
#define VT_WIDTH
Definition: vt.h:4
NuppelVideoRecorder::m_audioBufferCount
int m_audioBufferCount
Definition: NuppelVideoRecorder.h:212
rtfileheader
Definition: format.h:17
AudioInput::IsOpen
virtual bool IsOpen(void)=0
FrameRate::isNonzero
bool isNonzero(void) const
Definition: recorderbase.h:41
RecorderBase::m_requestPause
bool m_requestPause
Definition: recorderbase.h:338
GO7007_ASPECT_RATIO_4_3_PAL
@ GO7007_ASPECT_RATIO_4_3_PAL
Definition: go7007_myth.h:30
FMT_NONE
@ FMT_NONE
Definition: mythframe.h:17
NuppelVideoRecorder::m_audioBuffer
std::vector< struct audbuffertype * > m_audioBuffer
Definition: NuppelVideoRecorder.h:198
NuppelVideoRecorder::m_pipMode
int m_pipMode
Definition: NuppelVideoRecorder.h:168
mjpeg_params::decimation
int decimation
Definition: videodev_mjpeg.h:20
AudioInput::Start
virtual bool Start(void)=0
RecorderBase::m_recordingWait
QWaitCondition m_recordingWait
Definition: recorderbase.h:346
RecorderBase::m_curRecording
RecordingInfo * m_curRecording
Definition: recorderbase.h:334
AudioInput::Open
virtual bool Open(uint sample_bits, uint sample_rate, uint channels)=0
mjpeg_params::odd_even
int odd_even
Definition: videodev_mjpeg.h:51
FRAMEHEADERSIZE
#define FRAMEHEADERSIZE
Definition: format.h:139
NuppelVideoRecorder::m_lastBlock
int m_lastBlock
Definition: NuppelVideoRecorder.h:243
TVRec::RecorderPaused
void RecorderPaused(void)
This is a callback, called by the "recorder" instance when it has actually paused.
Definition: tv_rec.cpp:2945
NuppelVideoRecorder::WriteText
void WriteText(unsigned char *buf, int len, int timecode, int pagenr)
Definition: NuppelVideoRecorder.cpp:3013
AVFrame
struct AVFrame AVFrame
Definition: BorderDetector.h:15
rtframeheader::keyframe
char keyframe
Definition: format.h:72
NuppelVideoRecorder::m_startNum
int m_startNum
Definition: NuppelVideoRecorder.h:246
MythMediaBuffer::GetFilename
QString GetFilename(void) const
Definition: mythmediabuffer.cpp:1732
VT_HEIGHT
#define VT_HEIGHT
Definition: vt.h:5
txtbuffertype::buffer
unsigned char * buffer
Definition: format.h:169
NuppelVideoRecorder::m_hmjpgMaxW
int m_hmjpgMaxW
Definition: NuppelVideoRecorder.h:278
go7007_comp_params
Definition: go7007_myth.h:37
if
if(query.exec() &&query.next())
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:461
programinfo.h
MythVideoFrame::GetBufferSize
static size_t GetBufferSize(VideoFrameType Type, int Width, int Height, int Aligned=MYTH_WIDTH_ALIGNMENT)
Definition: mythframe.cpp:397
NuppelVideoRecorder::m_recording
bool m_recording
Definition: NuppelVideoRecorder.h:225
V4LRecorder::CloseVBIDevice
void CloseVBIDevice(void)
Definition: v4lrecorder.cpp:227
mythlogging.h
NuppelVideoRecorder::m_lf
unsigned int m_lf
Definition: NuppelVideoRecorder.h:161
NuppelVideoRecorder::m_maxQuality
int m_maxQuality
Definition: NuppelVideoRecorder.h:258
NVRAudioThread::m_parent
NuppelVideoRecorder * m_parent
Definition: NuppelVideoRecorder.h:68
ChannelBase
Abstract class providing a generic interface to tuning hardware.
Definition: channelbase.h:32
NuppelVideoRecorder::m_actTextBuffer
int m_actTextBuffer
Definition: NuppelVideoRecorder.h:209
hardwareprofile.scan.profile
profile
Definition: scan.py:99
VBIMode::NTSC_CC
@ NTSC_CC
Definition: tv.h:13
NuppelVideoRecorder::m_minQuality
int m_minQuality
Definition: NuppelVideoRecorder.h:259
txtbuffertype
Definition: format.h:164
RecorderBase::AspectChange
void AspectChange(uint aspect, long long frame)
Note a change in aspect ratio in the recordedmark table.
Definition: recorderbase.cpp:731
MythMediaBuffer::WriterSeek
long long WriterSeek(long long Position, int Whence, bool HasLock=false)
Calls ThreadedFileWriter::Seek(long long,int).
Definition: mythmediabuffer.cpp:1664
FOURCC_LAME
#define FOURCC_LAME
Definition: fourcc.h:81
mjpeg_params::img_height
int img_height
Definition: videodev_mjpeg.h:39
NuppelVideoRecorder::m_gf
lame_global_flags * m_gf
Definition: NuppelVideoRecorder.h:187
FMT_YV12
@ FMT_YV12
Definition: mythframe.h:19
AudioInput::GetNumReadyBytes
virtual int GetNumReadyBytes(void)=0
videodev_mjpeg.h
NuppelVideoRecorder::m_mpaVidCtx
AVCodecContext * m_mpaVidCtx
Definition: NuppelVideoRecorder.h:254
NuppelVideoRecorder::DoMJPEG
void DoMJPEG(void)
Definition: NuppelVideoRecorder.cpp:1606
mjpeg_requestbuffers::size
unsigned long size
Definition: videodev_mjpeg.h:90
GO7007_MPEG_VIDEO_MPEG4
@ GO7007_MPEG_VIDEO_MPEG4
Definition: go7007_myth.h:52
NuppelVideoRecorder::m_mainPaused
bool m_mainPaused
Definition: NuppelVideoRecorder.h:238
NuppelVideoRecorder::m_go7007
bool m_go7007
Definition: NuppelVideoRecorder.h:297
rtfileheader::videoblocks
int videoblocks
Definition: format.h:28
extendeddata::audio_compression_ratio
int audio_compression_ratio
Definition: format.h:107
teletextsubtitle
Definition: format.h:174
V4LRecorder::StopRecording
void StopRecording(void) override
StopRecording() signals to the recorder that it should stop recording and exit cleanly.
Definition: v4lrecorder.cpp:46
rtframeheader::comptype
char comptype
Definition: format.h:43
RTJ_YUV420
#define RTJ_YUV420
Definition: RTjpegN.h:63
audbuffertype::timecode
int timecode
Definition: format.h:157
NuppelVideoRecorder::WriteVideo
void WriteVideo(MythVideoFrame *frame, bool skipsync=false, bool forcekey=false)
Definition: NuppelVideoRecorder.cpp:2655
RecorderBase::m_videoHeight
uint m_videoHeight
Definition: recorderbase.h:330
NuppelVideoRecorder::m_audioPaused
bool m_audioPaused
Definition: NuppelVideoRecorder.h:237
NuppelVideoRecorder::m_mp3Buf
char * m_mp3Buf
Definition: NuppelVideoRecorder.h:185
NVRWriteThread::m_parent
NuppelVideoRecorder * m_parent
Definition: NuppelVideoRecorder.h:57
NuppelVideoRecorder::IsPaused
bool IsPaused(bool holding_lock=false) const override
Returns true iff recorder is paused.
Definition: NuppelVideoRecorder.cpp:350
RecorderBase::ResolutionChange
void ResolutionChange(uint width, uint height, long long frame)
Note a change in video size in the recordedmark table.
Definition: recorderbase.cpp:782
rtfileheader::pimode
char pimode
Definition: format.h:24
MythVideoFrame::m_frameNumber
long long m_frameNumber
Definition: mythframe.h:110
FrameRate
Definition: recorderbase.h:37
NuppelVideoRecorder::Pause
void Pause(bool clear=true) override
Pause tells recorder to pause, it should not block.
Definition: NuppelVideoRecorder.cpp:338
GO7007_ASPECT_RATIO_16_9_PAL
@ GO7007_ASPECT_RATIO_16_9_PAL
Definition: go7007_myth.h:32
NuppelVideoRecorder::GetVideoFd
int GetVideoFd(void) override
Returns file descriptor of recorder device.
Definition: NuppelVideoRecorder.cpp:374
NuppelVideoRecorder::WriteFrameheader
void WriteFrameheader(rtframeheader *fh)
Definition: NuppelVideoRecorder.cpp:1847
RecorderBase::IsRecordingRequested
virtual bool IsRecordingRequested(void)
Tells us if StopRecording() has been called.
Definition: recorderbase.cpp:251
MythVideoFrame::m_bufferSize
size_t m_bufferSize
Definition: mythframe.h:105
clear
static void clear(SettingsMap &cache, SettingsMap &overrides, const QString &myKey)
Definition: mythdb.cpp:844
MThread::RunEpilog
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:211
RecorderBase::m_ntscFrameRate
bool m_ntscFrameRate
Definition: recorderbase.h:325
FOURCC_WMV1
#define FOURCC_WMV1
Definition: fourcc.h:103
RecorderBase::m_videoFrameRate
double m_videoFrameRate
Definition: recorderbase.h:326
go7007_comp_params::flags
__u32 flags
Definition: go7007_myth.h:41
NuppelVideoRecorder::m_ccd
CC608Decoder * m_ccd
Definition: NuppelVideoRecorder.h:295
NuppelVideoRecorder::GetFramesWritten
long long GetFramesWritten(void) override
Returns number of frames written to disk.
Definition: NuppelVideoRecorder.cpp:369
NuppelVideoRecorder::m_compressAudio
bool m_compressAudio
Definition: NuppelVideoRecorder.h:170
NuppelVideoRecorder::m_pictureFormat
AVPixelFormat m_pictureFormat
Definition: NuppelVideoRecorder.h:267
NuppelVideoRecorder::m_fd
int m_fd
Definition: NuppelVideoRecorder.h:159
AudioInput::Close
virtual void Close(void)=0
NVRAudioThread::run
void run(void) override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
Definition: NuppelVideoRecorder.cpp:77
NuppelVideoRecorder::ResetForNewFile
void ResetForNewFile(void) override
Definition: NuppelVideoRecorder.cpp:2617
NuppelVideoRecorder::m_m2
int m_m2
Definition: NuppelVideoRecorder.h:164
rtfileheader::finfo
char finfo[12]
Definition: format.h:18
MythMediaBuffer::LiveMode
bool LiveMode(void) const
Returns true if this RingBuffer has been assigned a LiveTVChain.
Definition: mythmediabuffer.cpp:1791
DTVRecorder::ClearStatistics
void ClearStatistics(void) override
Definition: dtvrecorder.cpp:179
NuppelVideoRecorder::NVRWriteThread
friend class NVRWriteThread
Definition: NuppelVideoRecorder.h:73
NuppelVideoRecorder::m_audioBehind
int m_audioBehind
Definition: NuppelVideoRecorder.h:249
uint
unsigned int uint
Definition: compat.h:140
RecorderBase::m_videocodec
QString m_videocodec
Definition: recorderbase.h:321
RecorderBase::m_positionMap
frm_pos_map_t m_positionMap
Definition: recorderbase.h:358
V4LRecorder::IsHelperRequested
virtual bool IsHelperRequested(void) const
Definition: v4lrecorder.cpp:53
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:56
RecorderBase::m_containerFormat
AVContainer m_containerFormat
Definition: recorderbase.h:318
NuppelVideoRecorder::m_mp3BufSize
int m_mp3BufSize
Definition: NuppelVideoRecorder.h:186
RecorderBase::m_weMadeBuffer
bool m_weMadeBuffer
Definition: recorderbase.h:316
extendeddata::video_fourcc
int video_fourcc
Definition: format.h:99
RecorderBase::FrameRateChange
void FrameRateChange(uint framerate, uint64_t frame)
Note a change in video frame rate in the recordedmark table.
Definition: recorderbase.cpp:798
rtfileheader::audioblocks
int audioblocks
Definition: format.h:29
mjpeg_sync::length
unsigned long length
Definition: videodev_mjpeg.h:96
FOURCC_RAWA
#define FOURCC_RAWA
Definition: fourcc.h:82
mythmediabuffer.h
RecorderBase::m_positionMapDelta
frm_pos_map_t m_positionMapDelta
Definition: recorderbase.h:359
RecorderBase::m_videodevice
QString m_videodevice
Definition: recorderbase.h:322
NuppelVideoRecorder::AddTextData
void AddTextData(unsigned char *buf, int len, int64_t timecode, char type) override
Definition: NuppelVideoRecorder.cpp:2469
FOURCC_MPG4
#define FOURCC_MPG4
Definition: fourcc.h:101
extendeddata::audio_bits_per_sample
int audio_bits_per_sample
Definition: format.h:103
mjpeg_sync::frame
unsigned long frame
Definition: videodev_mjpeg.h:95
NuppelVideoRecorder::m_useAvCodec
bool m_useAvCodec
Definition: NuppelVideoRecorder.h:251
extendeddata::lavc_bitrate
int lavc_bitrate
Definition: format.h:114
NuppelVideoRecorder::m_tf
int m_tf
Definition: NuppelVideoRecorder.h:162
NuppelVideoRecorder::m_hmjpgVDecimation
int m_hmjpgVDecimation
Definition: NuppelVideoRecorder.h:277
buffers
Definition: freesurround.cpp:50
NuppelVideoRecorder::DoV4L2
void DoV4L2(void)
Definition: NuppelVideoRecorder.cpp:1268
NuppelVideoRecorder::m_actVideoEncode
int m_actVideoEncode
Definition: NuppelVideoRecorder.h:201
NuppelVideoRecorder::SetFormatV4L2
bool SetFormatV4L2(void)
Definition: NuppelVideoRecorder.cpp:1178
vidbuffertype::freeToBuffer
int freeToBuffer
Definition: format.h:148
GO7007_ASPECT_RATIO_1_1
@ GO7007_ASPECT_RATIO_1_1
Definition: go7007_myth.h:28
teletextsubtitle::dbl
unsigned char dbl
Definition: format.h:177
RTjpeg
Definition: RTjpegN.h:68
extendeddata::lavc_qmin
int lavc_qmin
Definition: format.h:115
RecorderBase::m_pauseWait
QWaitCondition m_pauseWait
Definition: recorderbase.h:340
MythMediaBuffer::WriterFlush
void WriterFlush(void)
Calls ThreadedFileWriter::Flush(void)
Definition: mythmediabuffer.cpp:1690
RecorderBase::m_ringBuffer
MythMediaBuffer * m_ringBuffer
Definition: recorderbase.h:315
NuppelVideoRecorder::InitBuffers
void InitBuffers(void)
Definition: NuppelVideoRecorder.cpp:744
NuppelVideoRecorder::m_rtjc
RTjpeg * m_rtjc
Definition: NuppelVideoRecorder.h:189
go7007_comp_params::aspect_ratio
enum go7007_aspect_ratio aspect_ratio
Definition: go7007_myth.h:40
GO7007_ASPECT_RATIO_16_9_NTSC
@ GO7007_ASPECT_RATIO_16_9_NTSC
Definition: go7007_myth.h:31
RecorderBase::m_ntsc
bool m_ntsc
Definition: recorderbase.h:324
vidbuffertype::sample
int sample
Definition: format.h:145
GO7007IOC_S_MPEG_PARAMS
#define GO7007IOC_S_MPEG_PARAMS
Definition: go7007_myth.h:87
mjpeg_sync
Definition: videodev_mjpeg.h:94
mjpeg_params::quality
int quality
Definition: videodev_mjpeg.h:46
V4LRecorder::m_vbiMode
int m_vbiMode
Definition: v4lrecorder.h:48
mythmiscutil.h
NuppelVideoRecorder::m_hardwareEncode
bool m_hardwareEncode
Definition: NuppelVideoRecorder.h:274
RTjpeg::SetIntra
int SetIntra(int *key, int *lm, int *cm)
Definition: RTjpegN.cpp:2725
FOURCC_MPG2
#define FOURCC_MPG2
Definition: fourcc.h:100
NuppelVideoRecorder::WriteSeekTable
void WriteSeekTable(void)
Definition: NuppelVideoRecorder.cpp:2025
NuppelVideoRecorder::WriteFileHeader
void WriteFileHeader(void)
Definition: NuppelVideoRecorder.cpp:1874
extendeddata::keyframeadjust_offset
long long keyframeadjust_offset
Definition: format.h:121
teletextsubtitle::len
unsigned char len
Definition: format.h:180
NuppelVideoRecorder::WriteKeyFrameAdjustTable
void WriteKeyFrameAdjustTable(const std::vector< struct kfatable_entry > &kfa_table)
Definition: NuppelVideoRecorder.cpp:2060
bswap_dbl
#define bswap_dbl(x)
Definition: bswap.h:6
rtframeheader::filters
char filters
Definition: format.h:75
NuppelVideoRecorder::m_wOut
int m_wOut
Definition: NuppelVideoRecorder.h:271
KEYFRAMEDIST
#define KEYFRAMEDIST
Definition: NuppelVideoRecorder.h:40
NuppelVideoRecorder::IsRecording
bool IsRecording(void) override
Tells whether the StartRecorder() loop is running.
Definition: NuppelVideoRecorder.cpp:364
DTVRecorder::m_error
QString m_error
non-empty iff irrecoverable recording error detected
Definition: dtvrecorder.h:159
VBIData
Definition: v4lrecorder.h:17
RTjpeg::SetFormat
int SetFormat(const int *fmt)
Definition: RTjpegN.cpp:2684
ProgramInfo::ClearPositionMap
void ClearPositionMap(MarkTypes type) const
Definition: programinfo.cpp:3631
vidbuffertype::forcekey
bool forcekey
Definition: format.h:151
NuppelVideoRecorder::CreateNuppelFile
int CreateNuppelFile(void)
Definition: NuppelVideoRecorder.cpp:2113
cc.h
NuppelVideoRecorder::Initialize
void Initialize(void) override
This is called between SetOptionsFromProfile() and run() to initialize any devices,...
Definition: NuppelVideoRecorder.cpp:561
formatNUV
@ formatNUV
Definition: recordingfile.h:15
NuppelVideoRecorder::m_lastPositionMapPos
long long m_lastPositionMapPos
Definition: NuppelVideoRecorder.h:229
RecorderBase::m_positionMapLock
QMutex m_positionMapLock
Definition: recorderbase.h:357
audbuffertype::sample
int sample
Definition: format.h:156
NuppelVideoRecorder::doAudioThread
void doAudioThread(void)
Definition: NuppelVideoRecorder.cpp:2183
NuppelVideoRecorder::m_stm
Definition: NuppelVideoRecorder.h:219
audbuffertype::freeToBuffer
int freeToBuffer
Definition: format.h:159
NuppelVideoRecorder::m_actAudioSample
long long m_actAudioSample
Definition: NuppelVideoRecorder.h:206
NuppelVideoRecorder::m_audioBufferSize
long m_audioBufferSize
Definition: NuppelVideoRecorder.h:216
NuppelVideoRecorder::m_audioDevice
AudioInput * m_audioDevice
Definition: NuppelVideoRecorder.h:171
extendeddata::audio_sample_rate
int audio_sample_rate
Definition: format.h:102
RTjpeg::SetSize
int SetSize(const int *w, const int *h)
Definition: RTjpegN.cpp:2690
bswap.h
RecorderBase::AspectRatio
AspectRatio
Definition: recorderbase.h:243
mythavutil.h
TVRec
This is the coordinating class of the Recorder Subsystem.
Definition: tv_rec.h:143
NuppelVideoRecorder::m_inPixFmt
VideoFrameType m_inPixFmt
Definition: NuppelVideoRecorder.h:266
rtframeheader::packetlength
int packetlength
Definition: format.h:87
NuppelVideoRecorder::BufferIt
void BufferIt(unsigned char *buf, int len=-1, bool forcekey=false)
Definition: NuppelVideoRecorder.cpp:1784
teletextsubtitle::col
unsigned char col
Definition: format.h:176
rtfileheader::aspect
double aspect
Definition: format.h:26
MJPIOC_SYNC
#define MJPIOC_SYNC
Definition: videodev_mjpeg.h:117
extendeddata
Definition: format.h:97
mythcontext.h
FOURCC_MP42
#define FOURCC_MP42
Definition: fourcc.h:98
mjpeg_params::img_width
int img_width
Definition: videodev_mjpeg.h:37
extendeddata::rtjpeg_quality
int rtjpeg_quality
Definition: format.h:110
NuppelVideoRecorder::m_useBttv
int m_useBttv
Definition: NuppelVideoRecorder.h:179
extendeddata::audio_quality
int audio_quality
Definition: format.h:108
NuppelVideoRecorder::DoV4L1
void DoV4L1(void)
Definition: NuppelVideoRecorder.cpp:981
mjpeg_requestbuffers::count
unsigned long count
Definition: videodev_mjpeg.h:89
tv_rec.h
mjpeg_params
Definition: videodev_mjpeg.h:9
FOURCC_MPEG
#define FOURCC_MPEG
Definition: fourcc.h:99
NuppelVideoRecorder::m_effectiveDsp
int m_effectiveDsp
Definition: NuppelVideoRecorder.h:177
NuppelVideoRecorder::m_transcoding
bool m_transcoding
Definition: NuppelVideoRecorder.h:182
NuppelVideoRecorder::ProbeV4L2
void ProbeV4L2(void)
Definition: NuppelVideoRecorder.cpp:847
build_compdb.action
action
Definition: build_compdb.py:9
NuppelVideoRecorder::SetupAVCodecVideo
bool SetupAVCodecVideo(void)
Definition: NuppelVideoRecorder.cpp:379
NuppelVideoRecorder::m_correctBttv
bool m_correctBttv
Definition: NuppelVideoRecorder.h:290
mjpeg_params::APP_data
char APP_data[60]
Definition: videodev_mjpeg.h:57
NuppelVideoRecorder::m_writeThread
NVRWriteThread * m_writeThread
Definition: NuppelVideoRecorder.h:222
NuppelVideoRecorder::WriteHeader
void WriteHeader(void)
Definition: NuppelVideoRecorder.cpp:1910
NuppelVideoRecorder::UpdateResolutions
void UpdateResolutions(void)
Definition: NuppelVideoRecorder.cpp:499
NuppelVideoRecorder::KillChildren
void KillChildren(void)
Definition: NuppelVideoRecorder.cpp:1753
extendeddata::rtjpeg_luma_filter
int rtjpeg_luma_filter
Definition: format.h:111
rtfileheader::version
char version[5]
Definition: format.h:19
MJPIOC_S_PARAMS
#define MJPIOC_S_PARAMS
Definition: videodev_mjpeg.h:113
NuppelVideoRecorder::m_resetCapture
bool m_resetCapture
Definition: NuppelVideoRecorder.h:298
FOURCC_DIVX
#define FOURCC_DIVX
Definition: fourcc.h:91
FOURCC_H263
#define FOURCC_H263
Definition: fourcc.h:93
NuppelVideoRecorder::m_out
std::array< lzo_byte, OUT_LEN > m_out
Definition: NuppelVideoRecorder.h:192
go7007_mpeg_params::mpeg_video_standard
enum go7007_mpeg_video_standard mpeg_video_standard
Definition: go7007_myth.h:58
NuppelVideoRecorder::m_textBufferSize
long m_textBufferSize
Definition: NuppelVideoRecorder.h:217
StandardSetting
Definition: standardsettings.h:30
ChannelBase::Retune
virtual bool Retune(void)
Definition: channelbase.h:87
SendMythSystemRecEvent
void SendMythSystemRecEvent(const QString &msg, const RecordingInfo *pginfo)
Definition: mythsystemevent.cpp:332
recordingprofile.h
LOC
#define LOC
Definition: NuppelVideoRecorder.cpp:68
VideoFrameType
VideoFrameType
Definition: mythframe.h:16
NuppelVideoRecorder::doWriteThread
void doWriteThread(void)
Definition: NuppelVideoRecorder.cpp:2491
NuppelVideoRecorder::m_height
int m_height
Definition: NuppelVideoRecorder.h:167
NuppelVideoRecorder::FinishRecording
void FinishRecording(void) override
Flushes the ringbuffer, and if this is not a live LiveTV recording saves the position map and filesiz...
Definition: NuppelVideoRecorder.cpp:2641
NuppelVideoRecorder::m_volume
int m_volume
Definition: NuppelVideoRecorder.h:293
RTjpegN.h
audbuffertype::buffer
unsigned char * buffer
Definition: format.h:160
NuppelVideoRecorder::m_strm
signed char * m_strm
Definition: NuppelVideoRecorder.h:160
audioinput.h
myth_nice
bool myth_nice(int val)
Definition: mythmiscutil.cpp:698
NuppelVideoRecorder::m_frameRateMultiplier
double m_frameRateMultiplier
Definition: NuppelVideoRecorder.h:240
RecordingProfile
Definition: recordingprofile.h:40
RecorderBase::m_frameRate
FrameRate m_frameRate
Definition: recorderbase.h:332
MythVideoFrame
Definition: mythframe.h:83
seektable_entry::keyframe_number
int keyframe_number
Definition: format.h:130
go7007_mpeg_params
Definition: go7007_myth.h:57
extendeddata::lavc_qmax
int lavc_qmax
Definition: format.h:116
RTjpeg::SetQuality
int SetQuality(int *quality)
Definition: RTjpegN.cpp:2667
MThread::wait
bool wait(unsigned long time=ULONG_MAX)
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:305
V4LRecorder::m_audioDeviceName
QString m_audioDeviceName
Definition: v4lrecorder.h:46
NuppelVideoRecorder::m_videoAspect
float m_videoAspect
Definition: NuppelVideoRecorder.h:180
RecorderBase::m_unpauseWait
QWaitCondition m_unpauseWait
Definition: recorderbase.h:341
NuppelVideoRecorder::SetOption
void SetOption(const QString &opt, int value) override
handles the "wait_for_seqstart" option.
Definition: NuppelVideoRecorder.cpp:149
RecorderBase::CheckForRingBufferSwitch
virtual bool CheckForRingBufferSwitch(void)
If requested, switch to new RingBuffer/ProgramInfo objects.
Definition: recorderbase.cpp:352
NuppelVideoRecorder::UpdateSeekTable
void UpdateSeekTable(int frame_num, long offset=0)
Definition: NuppelVideoRecorder.cpp:2097
ccsubtitle
Definition: format.h:184
NuppelVideoRecorder::m_hOut
int m_hOut
Definition: NuppelVideoRecorder.h:272
RTjpeg::Compress
int Compress(int8_t *sp, uint8_t **planes)
Definition: RTjpegN.cpp:3270
NuppelVideoRecorder::m_tzone
Definition: NuppelVideoRecorder.h:220
NuppelVideoRecorder::FormatTT
void FormatTT(struct VBIData *vbidata) override
Definition: NuppelVideoRecorder.cpp:2292
vt_page::data
unsigned char data[VT_HEIGHT][VT_WIDTH]
Definition: vt.h:43
NuppelVideoRecorder::m_channelObj
ChannelBase * m_channelObj
Definition: NuppelVideoRecorder.h:285
MJPIOC_G_PARAMS
#define MJPIOC_G_PARAMS
Definition: videodev_mjpeg.h:112
NuppelVideoRecorder::NuppelVideoRecorder
NuppelVideoRecorder(TVRec *rec, ChannelBase *channel)
Definition: NuppelVideoRecorder.cpp:84
GO7007IOC_S_BITRATE
#define GO7007IOC_S_BITRATE
Definition: go7007_myth.h:23
AudioInput::CreateDevice
static AudioInput * CreateDevice(const QByteArray &device)
Definition: audioinput.cpp:29
vidbuffertype
Definition: format.h:144
NuppelVideoRecorder::SetOptionsFromProfile
void SetOptionsFromProfile(RecordingProfile *profile, const QString &videodev, const QString &audiodev, const QString &vbidev) override
Sets basic recorder options.
Definition: NuppelVideoRecorder.cpp:237
teletextsubtitle::bg
unsigned char bg
Definition: format.h:179
NuppelVideoRecorder::m_skipBtAudio
bool m_skipBtAudio
Definition: NuppelVideoRecorder.h:287
mjpeg_params::HorDcm
int HorDcm
Definition: videodev_mjpeg.h:29
NuppelVideoRecorder::~NuppelVideoRecorder
~NuppelVideoRecorder() override
Definition: NuppelVideoRecorder.cpp:96
NuppelVideoRecorder::m_firstTc
int m_firstTc
Definition: NuppelVideoRecorder.h:244
NuppelVideoRecorder::NVRAudioThread
friend class NVRAudioThread
Definition: NuppelVideoRecorder.h:74
MythAVUtil::FillAVFrame
static int FillAVFrame(AVFrame *Frame, const MythVideoFrame *From, AVPixelFormat Fmt=AV_PIX_FMT_NONE)
Initialise AVFrame with content from MythVideoFrame.
Definition: mythavutil.cpp:120
audbuffertype::freeToEncode
int freeToEncode
Definition: format.h:158
rtframeheader::frametype
char frametype
Definition: format.h:36
vt_page::pgno
int pgno
Definition: vt.h:38
rtfileheader::keyframedist
int keyframedist
Definition: format.h:31
NuppelVideoRecorder::Reset
void Reset(void) override
Reset the recorder to the startup state.
Definition: NuppelVideoRecorder.cpp:2135
FOURCC_RJPG
#define FOURCC_RJPG
Definition: fourcc.h:102
txtbuffertype::freeToBuffer
int freeToBuffer
Definition: format.h:168
FOURCC_DIV3
#define FOURCC_DIV3
Definition: fourcc.h:90
NuppelVideoRecorder::m_audioSampleRate
int m_audioSampleRate
Definition: NuppelVideoRecorder.h:176
mjpeg_requestbuffers
Definition: videodev_mjpeg.h:88
mjpeg_params::APPn
int APPn
Definition: videodev_mjpeg.h:55
extendeddata::seektable_offset
long long seektable_offset
Definition: format.h:119
MythMediaBuffer::IsOpen
virtual bool IsOpen(void) const =0
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:915
fourcc.h
NuppelVideoRecorder::m_qualDiff
int m_qualDiff
Definition: NuppelVideoRecorder.h:260
RecorderBase::m_requestRecording
bool m_requestRecording
True if API call has requested a recording be [re]started.
Definition: recorderbase.h:343
NuppelVideoRecorder::m_width
int m_width
Definition: NuppelVideoRecorder.h:166
MythVideoFrame::m_buffer
uint8_t * m_buffer
Definition: mythframe.h:101
mjpeg_params::img_y
int img_y
Definition: videodev_mjpeg.h:36
tv_play.h
NuppelVideoRecorder::m_livetv
bool m_livetv
Definition: NuppelVideoRecorder.h:235
teletextsubtitle::fg
unsigned char fg
Definition: format.h:178
NuppelVideoRecorder::m_m1
int m_m1
Definition: NuppelVideoRecorder.h:163
RecorderBase::SetIntOption
void SetIntOption(RecordingProfile *profile, const QString &name)
Convenience function used to set integer options from a profile.
Definition: recorderbase.cpp:200