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