MythTV  master
nuppeldecoder.cpp
Go to the documentation of this file.
1 // C++ headers
2 #include <algorithm>
3 #include <cassert>
4 #include <cerrno>
5 #include <cstdio> // for SEEK_SET, SEEK_CUR
6 #include <cstring>
7 #include <sys/types.h>
8 #include <vector> // for vector
9 using namespace std;
10 
11 // Qt headers
12 #include <QMutex>
13 #include <QMap> // for QMap<>::iterator, QMap
14 
15 // MythTV headers
16 #include "mythconfig.h"
17 #include "nuppeldecoder.h"
18 #include "mythplayer.h"
19 #include "mythlogging.h"
20 #include "programinfo.h"
21 #include "mythavutil.h"
22 #include "fourcc.h"
23 #include "RTjpegN.h"
24 #include "audiooutput.h" // for RTjpeg, RTJ_YUV420
25 #include "audiooutputsettings.h" // for ::FORMAT_NONE, ::FORMAT_S16, etc
26 #include "audioplayer.h" // for AudioPlayer
27 #include "cc608reader.h" // for CC608Reader
28 
29 #include "lzo/lzo1x.h"
30 
31 extern "C" {
32 #if HAVE_BIGENDIAN
33 #include "bswap.h"
34 #endif
35 #include "libavutil/opt.h"
36 }
37 
38 #define LOC QString("NVD: ")
39 
41  const ProgramInfo &pginfo)
42  : DecoderBase(parent, pginfo)
43 {
44  // initialize structures
45  memset(&m_fileHeader, 0, sizeof(rtfileheader));
46  memset(&m_frameHeader, 0, sizeof(rtframeheader));
47  memset(&m_extraData, 0, sizeof(extendeddata));
48  m_planes[0] = m_planes[1] = m_planes[2] = nullptr;
49  m_audioSamples = (uint8_t *)av_mallocz(AudioOutput::kMaxSizeBuffer);
50 
51  // set parent class variables
53  m_lastKey = 0;
54  m_framesPlayed = 0;
55  m_getRawFrames = false;
56  m_getRawVideo = false;
57 
58  m_rtjd = new RTjpeg();
59  int format = RTJ_YUV420;
60  m_rtjd->SetFormat(&format);
61 
62  if (lzo_init() != LZO_E_OK)
63  {
64  LOG(VB_GENERAL, LOG_ERR, "NuppelDecoder: lzo_init() failed, aborting");
65  m_errored = true;
66  return;
67  }
68 }
69 
71 {
72  delete m_rtjd;
73  delete [] m_ffmpegExtraData;
74  if (m_buf)
75  av_freep(&m_buf);
76  if (m_buf2)
77  av_freep(&m_buf2);
78  if (m_strm)
79  av_freep(&m_strm);
80 
81  av_freep(&m_audioSamples);
82 
83  while (!m_storedData.empty())
84  {
85  delete m_storedData.front();
86  m_storedData.pop_front();
87  }
90 }
91 
93  int /*testbufsize*/)
94 {
95  return strncmp(testbuf, "NuppelVideo", 11) == 0 ||
96  strncmp(testbuf, "MythTVVideo", 11) == 0;
97 }
98 
100 {
101  MythCodecID value = kCodec_NONE;
102  if (m_mpaVidCodec)
103  {
104  if (QString(m_mpaVidCodec->name) == "mpeg4")
105  value = kCodec_NUV_MPEG4;
106  }
107  else if (m_usingExtraData && m_extraData.video_fourcc == FOURCC_DIVX)
108  value = kCodec_NUV_MPEG4;
109  else
110  value = kCodec_NUV_RTjpeg;
111  return (value);
112 }
113 
115 {
116  if (m_mpaVidCtx)
117  return ff_codec_id_string(m_mpaVidCtx->codec_id);
118  return QString();
119 }
120 
122 {
124  return false; // NOLINT(readability-simplify-boolean-expr)
125 
126 #if HAVE_BIGENDIAN
127  fh->width = bswap_32(fh->width);
128  fh->height = bswap_32(fh->height);
129  fh->desiredwidth = bswap_32(fh->desiredwidth);
130  fh->desiredheight = bswap_32(fh->desiredheight);
131  fh->aspect = bswap_dbl(fh->aspect);
132  fh->fps = bswap_dbl(fh->fps);
133  fh->videoblocks = bswap_32(fh->videoblocks);
134  fh->audioblocks = bswap_32(fh->audioblocks);
135  fh->textsblocks = bswap_32(fh->textsblocks);
136  fh->keyframedist = bswap_32(fh->keyframedist);
137 #endif
138 
139  return true;
140 }
141 
143 {
145  return false; // NOLINT(readability-simplify-boolean-expr)
146 
147 #if HAVE_BIGENDIAN
148  fh->timecode = bswap_32(fh->timecode);
149  fh->packetlength = bswap_32(fh->packetlength);
150 #endif
151 
152  return true;
153 }
154 
155 int NuppelDecoder::OpenFile(RingBuffer *rbuffer, bool novideo,
156  char testbuf[kDecoderProbeBufferSize],
157  int /*testbufsize*/)
158 {
159  (void)testbuf;
160 
161  m_ringBuffer = rbuffer;
162  m_disableVideo = novideo;
163  m_tracks[kTrackTypeVideo].clear();
164  StreamInfo si(0, 0, 0, 0, 0);
165  m_tracks[kTrackTypeVideo].push_back(si);
167 
168  struct rtframeheader frameheader {};
169  long long startpos = 0;
170  int foundit = 0;
171 
173  {
174  LOG(VB_GENERAL, LOG_ERR,
175  QString("Error reading file: %1").arg(m_ringBuffer->GetFilename()));
176  return -1;
177  }
178 
179  while ((QString(m_fileHeader.finfo) != "NuppelVideo") &&
180  (QString(m_fileHeader.finfo) != "MythTVVideo"))
181  {
182  m_ringBuffer->Seek(startpos, SEEK_SET);
183  char dummychar = 0;
184  m_ringBuffer->Read(&dummychar, 1);
185 
186  startpos = m_ringBuffer->GetReadPosition();
187 
189  {
190  LOG(VB_GENERAL, LOG_ERR, QString("Error reading file: %1")
191  .arg(m_ringBuffer->GetFilename()));
192  return -1;
193  }
194 
195  if (startpos > 20000)
196  {
197  LOG(VB_GENERAL, LOG_ERR, QString("Bad file: '%1'")
198  .arg(m_ringBuffer->GetFilename()));
199  return -1;
200  }
201  }
202 
203  if (m_fileHeader.aspect > .999 && m_fileHeader.aspect < 1.001)
204  m_fileHeader.aspect = 4.0 / 3;
205  m_currentAspect = m_fileHeader.aspect;
206 
207  GetPlayer()->SetKeyframeDistance(m_fileHeader.keyframedist);
209  m_fileHeader.fps, m_currentAspect, false, 16);
210 
211  m_videoWidth = m_fileHeader.width;
212  m_videoHeight = m_fileHeader.height;
214  m_keyframeDist = m_fileHeader.keyframedist;
216 
217  if (!ReadFrameheader(&frameheader))
218  {
219  LOG(VB_GENERAL, LOG_ERR, "File not big enough for a header");
220  return -1;
221  }
222  if (frameheader.frametype != 'D')
223  {
224  LOG(VB_GENERAL, LOG_ERR, "Illegal file format");
225  return -1;
226  }
227 
228  char *space = new char[m_videoSize];
229 
230  if (frameheader.comptype == 'F')
231  {
232  m_ffmpegExtraDataSize = frameheader.packetlength;
233  if (m_ffmpegExtraDataSize > 0)
234  {
236  if (frameheader.packetlength != m_ringBuffer->Read(m_ffmpegExtraData,
237  frameheader.packetlength))
238  {
239  LOG(VB_GENERAL, LOG_ERR,
240  "File not big enough for first frame data");
241  delete [] m_ffmpegExtraData;
242  m_ffmpegExtraData = nullptr;
243  delete [] space;
244  return -1;
245  }
246  }
247  }
248  else
249  {
250  if (frameheader.packetlength != m_ringBuffer->Read(space,
251  frameheader.packetlength))
252  {
253  LOG(VB_GENERAL, LOG_ERR,
254  "File not big enough for first frame data");
255  delete [] space;
256  return -1;
257  }
258  }
259 
260  if ((m_videoHeight & 1) == 1)
261  {
262  m_videoHeight--;
263  LOG(VB_GENERAL, LOG_ERR,
264  QString("Incompatible video height, reducing to %1")
265  .arg( m_videoHeight));
266  }
267 
268  startpos = m_ringBuffer->GetReadPosition();
269 
270  ReadFrameheader(&frameheader);
271 
272  if (frameheader.frametype == 'X')
273  {
274  if (frameheader.packetlength != EXTENDEDSIZE)
275  {
276  LOG(VB_GENERAL, LOG_ERR, "Corrupt file. Bad extended frame.");
277  }
278  else
279  {
280  m_ringBuffer->Read(&m_extraData, frameheader.packetlength);
281 #if HAVE_BIGENDIAN
282  struct extendeddata *ed = &m_extraData;
283  ed->version = bswap_32(ed->version);
284  ed->video_fourcc = bswap_32(ed->video_fourcc);
285  ed->audio_fourcc = bswap_32(ed->audio_fourcc);
286  ed->audio_sample_rate = bswap_32(ed->audio_sample_rate);
287  ed->audio_bits_per_sample = bswap_32(ed->audio_bits_per_sample);
288  ed->audio_channels = bswap_32(ed->audio_channels);
290  ed->audio_quality = bswap_32(ed->audio_quality);
291  ed->rtjpeg_quality = bswap_32(ed->rtjpeg_quality);
292  ed->rtjpeg_luma_filter = bswap_32(ed->rtjpeg_luma_filter);
293  ed->rtjpeg_chroma_filter = bswap_32(ed->rtjpeg_chroma_filter);
294  ed->lavc_bitrate = bswap_32(ed->lavc_bitrate);
295  ed->lavc_qmin = bswap_32(ed->lavc_qmin);
296  ed->lavc_qmax = bswap_32(ed->lavc_qmax);
297  ed->lavc_maxqdiff = bswap_32(ed->lavc_maxqdiff);
298  ed->seektable_offset = bswap_64(ed->seektable_offset);
299  ed->keyframeadjust_offset = bswap_64(ed->keyframeadjust_offset);
300 #endif
301  m_usingExtraData = true;
302  ReadFrameheader(&frameheader);
303  }
304  }
305 
306  if (m_usingExtraData && m_extraData.seektable_offset > 0)
307  {
308  long long currentpos = m_ringBuffer->GetReadPosition();
309  struct rtframeheader seek_frameheader {};
310 
311  int seekret = m_ringBuffer->Seek(m_extraData.seektable_offset, SEEK_SET);
312  if (seekret == -1)
313  {
314  LOG(VB_GENERAL, LOG_ERR,
315  QString("NuppelDecoder::OpenFile(): seek error (%1)")
316  .arg(strerror(errno)));
317  }
318 
319  ReadFrameheader(&seek_frameheader);
320 
321  if (seek_frameheader.frametype != 'Q')
322  {
323  LOG(VB_GENERAL, LOG_ERR,
324  QString("Invalid seektable (frametype %1)")
325  .arg((int)seek_frameheader.frametype));
326  }
327  else
328  {
329  if (seek_frameheader.packetlength > 0)
330  {
331  char *seekbuf = new char[seek_frameheader.packetlength];
332  m_ringBuffer->Read(seekbuf, seek_frameheader.packetlength);
333 
334  int numentries = seek_frameheader.packetlength /
335  sizeof(struct seektable_entry);
336  struct seektable_entry ste {0, 0};
337  int offset = 0;
338 
339  m_positionMapLock.lock();
340 
341  m_positionMap.clear();
342  m_positionMap.reserve(numentries);
343 
344  for (int z = 0; z < numentries; z++)
345  {
346  memcpy(&ste, seekbuf + offset,
347  sizeof(struct seektable_entry));
348 #if HAVE_BIGENDIAN
349  ste.file_offset = bswap_64(ste.file_offset);
350  ste.keyframe_number = bswap_32(ste.keyframe_number);
351 #endif
352  offset += sizeof(struct seektable_entry);
353 
354  PosMapEntry e = {ste.keyframe_number,
356  ste.file_offset};
357  m_positionMap.push_back(e);
358  uint64_t frame_num = ste.keyframe_number * m_keyframeDist;
359  m_frameToDurMap[frame_num] =
360  frame_num * 1000 / m_videoFrameRate;
361  m_durToFrameMap[m_frameToDurMap[frame_num]] = frame_num;
362  }
363  m_hasFullPositionMap = true;
364  m_totalLength = (int)((ste.keyframe_number * m_keyframeDist * 1.0) /
367 
368  m_positionMapLock.unlock();
369 
371 
372  delete [] seekbuf;
373  }
374  else
375  LOG(VB_GENERAL, LOG_ERR, "0 length seek table");
376  }
377 
378  m_ringBuffer->Seek(currentpos, SEEK_SET);
379  }
380 
381  if (m_usingExtraData && m_extraData.keyframeadjust_offset > 0 &&
383  {
384  long long currentpos = m_ringBuffer->GetReadPosition();
385  struct rtframeheader kfa_frameheader {};
386 
387  int kfa_ret = m_ringBuffer->Seek(m_extraData.keyframeadjust_offset,
388  SEEK_SET);
389  if (kfa_ret == -1)
390  {
391  LOG(VB_GENERAL, LOG_ERR,
392  QString("NuppelDecoder::OpenFile(): keyframeadjust (%1)")
393  .arg(strerror(errno)));
394  }
395 
396  m_ringBuffer->Read(&kfa_frameheader, FRAMEHEADERSIZE);
397 
398  if (kfa_frameheader.frametype != 'K')
399  {
400  LOG(VB_GENERAL, LOG_ERR,
401  QString("Invalid key frame adjust table (frametype %1)")
402  .arg((int)kfa_frameheader.frametype));
403  }
404  else
405  {
406  if (kfa_frameheader.packetlength > 0)
407  {
408  char *kfa_buf = new char[kfa_frameheader.packetlength];
409  m_ringBuffer->Read(kfa_buf, kfa_frameheader.packetlength);
410 
411  int numentries = kfa_frameheader.packetlength /
412  sizeof(struct kfatable_entry);
413  struct kfatable_entry kfate {};
414  int offset = 0;
415  int adjust = 0;
416  QMap<long long, int> keyFrameAdjustMap;
417 
418  for (int z = 0; z < numentries; z++)
419  {
420  memcpy(&kfate, kfa_buf + offset,
421  sizeof(struct kfatable_entry));
422 #if HAVE_BIGENDIAN
423  kfate.adjust = bswap_32(kfate.adjust);
424  kfate.keyframe_number = bswap_32(kfate.keyframe_number);
425 #endif
426  offset += sizeof(struct kfatable_entry);
427 
428  keyFrameAdjustMap[kfate.keyframe_number] = kfate.adjust;
429  adjust += kfate.adjust;
430  }
432 
436 
437  adjust = 0;
438 
439  {
440  QMutexLocker locker(&m_positionMapLock);
441  for (auto & entry : m_positionMap)
442  {
443  long long adj = entry.adjFrame;
444 
445  if (keyFrameAdjustMap.contains(adj))
446  adjust += keyFrameAdjustMap[adj];
447 
448  entry.adjFrame -= adjust;
449  }
450  }
451 
452  delete [] kfa_buf;
453  }
454  else
455  LOG(VB_GENERAL, LOG_ERR, "0 length key frame adjust table");
456  }
457 
458  m_ringBuffer->Seek(currentpos, SEEK_SET);
459  }
460 
461  while (frameheader.frametype != 'A' && frameheader.frametype != 'V' &&
462  frameheader.frametype != 'S' && frameheader.frametype != 'T' &&
463  frameheader.frametype != 'R')
464  {
465  m_ringBuffer->Seek(startpos, SEEK_SET);
466 
467  char dummychar = 0;
468  m_ringBuffer->Read(&dummychar, 1);
469 
470  startpos = m_ringBuffer->GetReadPosition();
471 
472  if (!ReadFrameheader(&frameheader))
473  {
474  delete [] space;
475  return -1;
476  }
477 
478  if (startpos > 20000)
479  {
480  delete [] space;
481  return -1;
482  }
483  }
484 
485  foundit = 0;
486 
487  m_effDsp = m_audioSamplerate * 100;
489 
490  if (m_usingExtraData)
491  {
492  m_effDsp = m_extraData.audio_sample_rate * 100;
494  m_audioSamplerate = m_extraData.audio_sample_rate;
495 #if HAVE_BIGENDIAN
496  // Why only if using extradata?
497  m_audioBitsPerSample = m_extraData.audio_bits_per_sample;
498 #endif
499  AudioFormat format = FORMAT_NONE;
500  switch (m_extraData.audio_bits_per_sample)
501  {
502  case 8: format = FORMAT_U8; break;
503  case 16: format = FORMAT_S16; break;
504  case 24: format = FORMAT_S24; break;
505  case 32: format = FORMAT_S32; break;
506  }
507 
508  m_audio->SetAudioParams(format, m_extraData.audio_channels,
509  m_extraData.audio_channels,
510  AV_CODEC_ID_NONE, m_extraData.audio_sample_rate,
511  false /* AC3/DTS pass through */);
512  m_audio->ReinitAudio();
513  foundit = 1;
514  }
515 
516  while (!foundit)
517  {
518  if (frameheader.frametype == 'S')
519  {
520  if (frameheader.comptype == 'A')
521  {
522  m_effDsp = frameheader.timecode;
523  if (m_effDsp > 0)
524  {
526  foundit = 1;
527  continue;
528  }
529  }
530  }
531  if (frameheader.frametype != 'R' && frameheader.packetlength != 0)
532  {
533  if (frameheader.packetlength != m_ringBuffer->Read(space,
534  frameheader.packetlength))
535  {
536  foundit = 1;
537  continue;
538  }
539  }
540 
541  long long startpos2 = m_ringBuffer->GetReadPosition();
542 
543  foundit = !ReadFrameheader(&frameheader);
544 
545  bool framesearch = false;
546 
547  while (frameheader.frametype != 'A' && frameheader.frametype != 'V' &&
548  frameheader.frametype != 'S' && frameheader.frametype != 'T' &&
549  frameheader.frametype != 'R' && frameheader.frametype != 'X')
550  {
551  if (!framesearch)
552  LOG(VB_GENERAL, LOG_INFO, "Searching for frame header.");
553 
554  framesearch = true;
555 
556  m_ringBuffer->Seek(startpos2, SEEK_SET);
557 
558  char dummychar = 0;
559  m_ringBuffer->Read(&dummychar, 1);
560 
561  startpos2 = m_ringBuffer->GetReadPosition();
562 
563  foundit = !ReadFrameheader(&frameheader);
564  if (foundit)
565  break;
566  }
567  }
568 
569  delete [] space;
570 
571  m_setReadAhead = false;
572 
573  // mpeg4 encodes are small enough that this shouldn't matter
574  if (m_usingExtraData && m_extraData.video_fourcc == FOURCC_DIVX)
575  m_setReadAhead = true;
576 
577  m_bitrate = 0;
578  unsigned min_bitrate = 1000;
579  if (m_usingExtraData && m_extraData.video_fourcc == FOURCC_DIVX)
580  {
581  // Use video bitrate, ignore negligible audio bitrate
582  m_bitrate = m_extraData.lavc_bitrate / 1000;
583  }
584  m_bitrate = max(m_bitrate, min_bitrate); // set minimum 1 Mb/s to be safe
585  LOG(VB_PLAYBACK, LOG_INFO,
586  QString("Setting bitrate to %1 Kb/s").arg(m_bitrate));
587 
589 
590  m_videoSizeTotal = 0;
591  m_videoFramesRead = 0;
592 
593  m_ringBuffer->Seek(startpos, SEEK_SET);
594 
595  m_buf = (unsigned char*)av_malloc(m_videoSize);
596  m_strm = (unsigned char*)av_malloc(m_videoSize * 2);
597 
599  return 1;
600 
601  if (SyncPositionMap())
602  return 1;
603 
604  return 0;
605 }
606 
607 void release_nuppel_buffer(void *opaque, uint8_t *data)
608 {
609  auto *frame = (VideoFrame*)data;
610  auto *nd = (NuppelDecoder*)opaque;
611  if (nd && nd->GetPlayer())
612  nd->GetPlayer()->DeLimboFrame(frame);
613 }
614 
615 int get_nuppel_buffer(struct AVCodecContext *c, AVFrame *pic, int /*flags*/)
616 {
617  auto *nd = (NuppelDecoder *)(c->opaque);
618 
619  for (int i = 0; i < 3; i++)
620  {
621  pic->data[i] = nd->m_directFrame->buf + nd->m_directFrame->offsets[i];
622  pic->linesize[i] = nd->m_directFrame->pitches[i];
623  }
624 
625  pic->opaque = nd->m_directFrame;
626 
627  // Set release method
628  AVBufferRef *buffer =
629  av_buffer_create((uint8_t*)nd->m_directFrame, 0, release_nuppel_buffer, nd, 0);
630  pic->buf[0] = buffer;
631 
632  return 0;
633 }
634 
636 {
637  if (m_mpaVidCodec)
639 
640  if (m_usingExtraData)
641  {
642  switch(m_extraData.video_fourcc)
643  {
644  case FOURCC_DIVX: codec = AV_CODEC_ID_MPEG4; break;
645  case FOURCC_WMV1: codec = AV_CODEC_ID_WMV1; break;
646  case FOURCC_DIV3: codec = AV_CODEC_ID_MSMPEG4V3; break;
647  case FOURCC_MP42: codec = AV_CODEC_ID_MSMPEG4V2; break;
648  case FOURCC_MPG4: codec = AV_CODEC_ID_MSMPEG4V1; break;
649  case FOURCC_MJPG: codec = AV_CODEC_ID_MJPEG; break;
650  case FOURCC_H263: codec = AV_CODEC_ID_H263; break;
651  case FOURCC_H264: codec = AV_CODEC_ID_H264; break;
652  case FOURCC_I263: codec = AV_CODEC_ID_H263I; break;
653  case FOURCC_MPEG: codec = AV_CODEC_ID_MPEG1VIDEO; break;
654  case FOURCC_MPG2: codec = AV_CODEC_ID_MPEG2VIDEO; break;
655  case FOURCC_HFYU: codec = AV_CODEC_ID_HUFFYUV; break;
656  default: codec = -1;
657  }
658  }
659  m_mpaVidCodec = avcodec_find_decoder((enum AVCodecID)codec);
660 
661  if (!m_mpaVidCodec)
662  {
663  if (m_usingExtraData)
664  {
665  LOG(VB_GENERAL, LOG_ERR,
666  QString("couldn't find video codec (%1)")
667  .arg(m_extraData.video_fourcc));
668  }
669  else
670  {
671  LOG(VB_GENERAL, LOG_ERR, "couldn't find video codec");
672  }
673  return false;
674  }
675 
676  if (m_mpaVidCodec->capabilities & AV_CODEC_CAP_DR1 && codec != AV_CODEC_ID_MJPEG)
677  m_directRendering = true;
678 
679  if (m_mpaVidCtx)
680  avcodec_free_context(&m_mpaVidCtx);
681 
682  m_mpaVidCtx = avcodec_alloc_context3(nullptr);
683 
684  m_mpaVidCtx->codec_id = (enum AVCodecID)codec;
685  m_mpaVidCtx->codec_type = AVMEDIA_TYPE_VIDEO;
686  m_mpaVidCtx->width = m_videoWidth;
687  m_mpaVidCtx->height = m_videoHeight;
688  m_mpaVidCtx->err_recognition = AV_EF_CRCCHECK | AV_EF_BITSTREAM |
689  AV_EF_BUFFER;
690  m_mpaVidCtx->bits_per_coded_sample = 12;
691 
692  if (m_directRendering)
693  {
694  // m_mpaVidCtx->flags |= CODEC_FLAG_EMU_EDGE;
695  m_mpaVidCtx->draw_horiz_band = nullptr;
696  m_mpaVidCtx->get_buffer2 = get_nuppel_buffer;
697  m_mpaVidCtx->opaque = (void *)this;
698  }
699  if (m_ffmpegExtraDataSize > 0)
700  {
701  av_opt_set_int(m_mpaVidCtx, "extern_huff", 1, 0);
702  m_mpaVidCtx->extradata = m_ffmpegExtraData;
703  m_mpaVidCtx->extradata_size = m_ffmpegExtraDataSize;
704  }
705 
706  QMutexLocker locker(avcodeclock);
707  if (avcodec_open2(m_mpaVidCtx, m_mpaVidCodec, nullptr) < 0)
708  {
709  LOG(VB_GENERAL, LOG_ERR, LOC + "Couldn't find lavc video codec");
710  return false;
711  }
712 
713  return true;
714 }
715 
717 {
718  QMutexLocker locker(avcodeclock);
719 
720  if (m_mpaVidCodec && m_mpaVidCtx)
721  avcodec_free_context(&m_mpaVidCtx);
722 }
723 
725 {
726  if (m_mpaAudCodec)
728 
729  if (m_usingExtraData)
730  {
731  switch(m_extraData.audio_fourcc)
732  {
733  case FOURCC_LAME: codec = AV_CODEC_ID_MP3; break;
734  case FOURCC_AC3 : codec = AV_CODEC_ID_AC3; break;
735  default: codec = -1;
736  }
737  }
738  m_mpaAudCodec = avcodec_find_decoder((enum AVCodecID)codec);
739 
740  if (!m_mpaAudCodec)
741  {
742  if (m_usingExtraData)
743  {
744  LOG(VB_GENERAL, LOG_ERR, QString("couldn't find audio codec (%1)")
745  .arg(m_extraData.audio_fourcc));
746  }
747  else
748  {
749  LOG(VB_GENERAL, LOG_ERR, "couldn't find audio codec");
750  }
751  return false;
752  }
753 
754  if (m_mpaAudCtx)
755  avcodec_free_context(&m_mpaAudCtx);
756 
757  m_mpaAudCtx = avcodec_alloc_context3(nullptr);
758 
759  m_mpaAudCtx->codec_id = (enum AVCodecID)codec;
760  m_mpaAudCtx->codec_type = AVMEDIA_TYPE_AUDIO;
761 
762  QMutexLocker locker(avcodeclock);
763  if (avcodec_open2(m_mpaAudCtx, m_mpaAudCodec, nullptr) < 0)
764  {
765  LOG(VB_GENERAL, LOG_ERR, LOC + "Couldn't find lavc audio codec");
766  return false;
767  }
768 
769  return true;
770 }
771 
773 {
774  QMutexLocker locker(avcodeclock);
775 
776  if (m_mpaAudCodec && m_mpaAudCtx)
777  avcodec_free_context(&m_mpaAudCtx);
778 }
779 
780 static void CopyToVideo(unsigned char *buf, int video_width,
781  int video_height, VideoFrame *frame)
782 {
783  (void)video_width;
784  (void)video_height;
785  copybuffer(frame, buf, frame->width);
786 }
787 
788 bool NuppelDecoder::DecodeFrame(struct rtframeheader *frameheader,
789  unsigned char *lstrm, VideoFrame *frame)
790 {
791  lzo_uint out_len = 0;
792  int compoff = 0;
793 
794  m_directFrame = frame;
795 
796  if (!m_buf2)
797  {
798  m_buf2 = (unsigned char*)av_malloc(m_videoSize + 64);
799  m_planes[0] = m_buf;
801  m_planes[2] = m_planes[1] + (m_videoWidth * m_videoHeight) / 4;
802  }
803 
804  if (frameheader->comptype == 'N')
805  {
806  memset(frame->buf, 0, frame->pitches[0] * m_videoHeight);
807  memset(frame->buf + frame->offsets[1], 127,
808  frame->pitches[1] * frame->height / 2);
809  memset(frame->buf + frame->offsets[2], 127,
810  frame->pitches[2] * frame->height / 2);
811  return true;
812  }
813 
814  if (frameheader->comptype == 'L')
815  {
816  switch(m_lastCt)
817  {
818  case '0': case '3':
820  break;
821  case '1': case '2':
822  default:
824  break;
825  }
826  return true;
827  }
828 
829  compoff = 1;
830  if (frameheader->comptype == '2' || frameheader->comptype == '3')
831  compoff=0;
832 
833  m_lastCt = frameheader->comptype;
834 
835  if (!compoff)
836  {
837  int r = lzo1x_decompress(lstrm, frameheader->packetlength, m_buf2, &out_len,
838  nullptr);
839  if (r != LZO_E_OK)
840  {
841  LOG(VB_GENERAL, LOG_ERR, "minilzo: can't decompress illegal data");
842  }
843  }
844 
845  if (frameheader->comptype == '0')
846  {
847  CopyToVideo(lstrm, m_videoWidth, m_videoHeight, frame);
848  return true;
849  }
850 
851  if (frameheader->comptype == '3')
852  {
854  return true;
855  }
856 
857  if (frameheader->comptype == '2' || frameheader->comptype == '1')
858  {
859  if (compoff)
860  m_rtjd->Decompress((int8_t*)lstrm, m_planes);
861  else
862  m_rtjd->Decompress((int8_t*)m_buf2, m_planes);
863 
865  }
866  else
867  {
868  if (!m_mpaVidCodec)
869  InitAVCodecVideo(frameheader->comptype - '3');
870 
871  if (!m_mpaVidCtx)
872  {
873  LOG(VB_PLAYBACK, LOG_ERR, LOC + "NULL mpa_vidctx");
874  return false;
875  }
876 
877  MythAVFrame mpa_pic;
878  if (!mpa_pic)
879  return false;
880  AVPacket pkt;
881  av_init_packet(&pkt);
882  pkt.data = lstrm;
883  pkt.size = frameheader->packetlength;
884 
885  {
886  QMutexLocker locker(avcodeclock);
887  // if directrendering, writes into buf
888  bool gotpicture = false;
889  // SUGGESTION
890  // Now that avcodec_decode_video2 is deprecated and replaced
891  // by 2 calls (receive frame and send packet), this could be optimized
892  // into separate routines or separate threads.
893  // Also now that it always consumes a whole buffer some code
894  // in the caller may be able to be optimized.
895  int ret = avcodec_receive_frame(m_mpaVidCtx, mpa_pic);
896  if (ret == 0)
897  gotpicture = true;
898  if (ret == AVERROR(EAGAIN))
899  ret = 0;
900  if (ret == 0)
901  ret = avcodec_send_packet(m_mpaVidCtx, &pkt);
902  m_directFrame = nullptr;
903  // The code assumes that there is always space to add a new
904  // packet. This seems risky but has always worked.
905  // It should actually check if (ret == AVERROR(EAGAIN)) and then keep
906  // the packet around and try it again after processing the frame
907  // received here.
908  if (ret < 0)
909  {
910  char error[AV_ERROR_MAX_STRING_SIZE];
911  LOG(VB_GENERAL, LOG_ERR, LOC +
912  QString("video decode error: %1 (%2)")
913  .arg(av_make_error_string(error, sizeof(error), ret))
914  .arg(gotpicture));
915  }
916  if (!gotpicture)
917  {
918  return false;
919  }
920  }
921 
922 /* XXX: Broken
923  if (mpa_pic->qscale_table != nullptr && mpa_pic->qstride > 0)
924  {
925  int tablesize = mpa_pic->qstride * ((m_videoHeight + 15) / 16);
926 
927  if (frame->qstride != mpa_pic->qstride ||
928  frame->qscale_table == nullptr)
929  {
930  frame->qstride = mpa_pic->qstride;
931 
932  if (frame->qscale_table)
933  delete [] frame->qscale_table;
934 
935  frame->qscale_table = new unsigned char[tablesize];
936  }
937 
938  memcpy(frame->qscale_table, mpa_pic->qscale_table, tablesize);
939  }
940 */
941 
942  if (m_directRendering)
943  return true;
944 
945  AVFrame *tmp = mpa_pic;
946  m_copyFrame.Copy(frame, tmp, m_mpaVidCtx->pix_fmt);
947  }
948 
949  return true;
950 }
951 
953 {
954  switch (type)
955  {
956  case 'A': case 'V': case 'S': case 'T': case 'R': case 'X':
957  case 'M': case 'D': case 'Q': case 'K':
958  return true;
959  default:
960  return false;
961  }
962 
963  return false;
964 }
965 
966 void NuppelDecoder::StoreRawData(unsigned char *newstrm)
967 {
968  unsigned char *strmcpy = nullptr;
969  if (newstrm)
970  {
971  strmcpy = new unsigned char[m_frameHeader.packetlength];
972  memcpy(strmcpy, newstrm, m_frameHeader.packetlength);
973  }
974 
975  m_storedData.push_back(new RawDataList(m_frameHeader, strmcpy));
976 }
977 
978 // The return value is the number of bytes in storedData before the 'SV' frame
980 {
981  long sync_offset = 0;
982 
983  for (auto *data : m_storedData)
984  {
985  if (data->frameheader.frametype == 'S' &&
986  data->frameheader.comptype == 'V')
987  {
988  data->frameheader.timecode = framenum;
989  return sync_offset;
990  }
991  sync_offset += FRAMEHEADERSIZE;
992  if (data->packet)
993  sync_offset += data->frameheader.packetlength;
994  }
995  return 0;
996 }
997 
999  long timecodeOffset)
1000 {
1001  while (!m_storedData.empty())
1002  {
1003  RawDataList *data = m_storedData.front();
1004 
1005  if (data->frameheader.frametype != 'S')
1006  data->frameheader.timecode -= timecodeOffset;
1007 
1008  if (storevid || data->frameheader.frametype != 'V')
1009  {
1010  rb->Write(&(data->frameheader), FRAMEHEADERSIZE);
1011  if (data->packet)
1012  rb->Write(data->packet, data->frameheader.packetlength);
1013  }
1014  m_storedData.pop_front();
1015  delete data;
1016  }
1017 }
1018 
1020 {
1021  while (!m_storedData.empty())
1022  {
1023  RawDataList *data = m_storedData.front();
1024  m_storedData.pop_front();
1025  delete data;
1026  }
1027 }
1028 
1029 bool NuppelDecoder::GetFrame(DecodeType decodetype, bool& /*Retry*/)
1030 {
1031  bool gotvideo = false;
1032  int seeklen = 0;
1033  AVPacket pkt;
1034 
1035  m_decodedVideoFrame = nullptr;
1036 
1037  while (!gotvideo)
1038  {
1039  long long currentposition = m_ringBuffer->GetReadPosition();
1040  if (m_waitingForChange && currentposition + 4 >= m_readAdjust)
1041  {
1042  FileChanged();
1043  currentposition = m_ringBuffer->GetReadPosition();
1044  }
1045 
1047  {
1048  SetEof(true);
1049  return false;
1050  }
1051 
1052 
1053  if (!m_ringBuffer->LiveMode() &&
1054  ((m_frameHeader.frametype == 'Q') || (m_frameHeader.frametype == 'K')))
1055  {
1056  SetEof(true);
1057  return false;
1058  }
1059 
1060  bool framesearch = false;
1061 
1062  while (!isValidFrametype(m_frameHeader.frametype))
1063  {
1064  if (!framesearch)
1065  LOG(VB_GENERAL, LOG_INFO, "Searching for frame header.");
1066 
1067  framesearch = true;
1068 
1069  m_ringBuffer->Seek((long long)seeklen-FRAMEHEADERSIZE, SEEK_CUR);
1070 
1072  {
1073  SetEof(true);
1074  return false;
1075  }
1076  seeklen = 1;
1077  }
1078 
1079  if (m_frameHeader.frametype == 'M')
1080  {
1081  int sizetoskip = sizeof(rtfileheader) - sizeof(rtframeheader);
1082  char *dummy = new char[sizetoskip + 1];
1083 
1084  if (m_ringBuffer->Read(dummy, sizetoskip) != sizetoskip)
1085  {
1086  delete [] dummy;
1087  SetEof(true);
1088  return false;
1089  }
1090 
1091  delete [] dummy;
1092  continue;
1093  }
1094 
1095  if (m_frameHeader.frametype == 'R')
1096  {
1097  if (m_getRawFrames)
1098  StoreRawData(nullptr);
1099  continue; // the R-frame has no data packet
1100  }
1101 
1102  if (m_frameHeader.frametype == 'S')
1103  {
1104  if (m_frameHeader.comptype == 'A')
1105  {
1106  if (m_frameHeader.timecode > 2000000 &&
1107  m_frameHeader.timecode < 5500000)
1108  {
1109  m_effDsp = m_frameHeader.timecode;
1111  }
1112  }
1113  else if (m_frameHeader.comptype == 'V')
1114  {
1115  m_lastKey = m_frameHeader.timecode;
1116  m_framesPlayed = (m_frameHeader.timecode > 0 ?
1117  m_frameHeader.timecode - 1 : 0);
1118 
1119  if (!m_hasFullPositionMap)
1120  {
1121  long long last_index = 0;
1122  long long this_index = m_lastKey / m_keyframeDist;
1123 
1124  QMutexLocker locker(&m_positionMapLock);
1125  if (!m_positionMap.empty())
1126  last_index = m_positionMap.back().index;
1127 
1128  if (this_index > last_index)
1129  {
1130  PosMapEntry e = {this_index, m_lastKey, currentposition};
1131  m_positionMap.push_back(e);
1133  m_lastKey * 1000 / m_videoFrameRate;
1135  }
1136  }
1137  }
1138  if (m_getRawFrames)
1139  StoreRawData(nullptr);
1140  }
1141 
1142  if (m_frameHeader.packetlength > 0)
1143  {
1144  if (m_frameHeader.packetlength > 10485760) // arbitrary 10MB limit
1145  {
1146  LOG(VB_GENERAL, LOG_ERR, QString("Broken packet: %1 %2")
1147  .arg(m_frameHeader.frametype)
1148  .arg(m_frameHeader.packetlength));
1149  SetEof(true);
1150  return false;
1151  }
1152  if (m_ringBuffer->Read(m_strm, m_frameHeader.packetlength) !=
1153  m_frameHeader.packetlength)
1154  {
1155  SetEof(true);
1156  return false;
1157  }
1158  }
1159  else
1160  continue;
1161 
1162  if (m_frameHeader.frametype == 'V')
1163  {
1164  if (!(kDecodeVideo & decodetype))
1165  {
1166  m_framesPlayed++;
1167  gotvideo = true;
1168  continue;
1169  }
1170 
1172  if (!buf)
1173  continue;
1174 
1175  bool ret = DecodeFrame(&m_frameHeader, m_strm, buf);
1176  if (!ret)
1177  {
1178  GetPlayer()->DiscardVideoFrame(buf);
1179  continue;
1180  }
1181 
1182  buf->aspect = m_currentAspect;
1183  buf->frameNumber = m_framesPlayed;
1184  buf->frameCounter = m_frameCounter++;
1185  buf->dummy = 0;
1186  GetPlayer()->ReleaseNextVideoFrame(buf, m_frameHeader.timecode);
1187 
1188  // We need to make the frame available ourselves
1189  // if we are not using ffmpeg/avlib.
1190  if (m_directFrame)
1191  GetPlayer()->DeLimboFrame(buf);
1192 
1193  m_decodedVideoFrame = buf;
1194  gotvideo = true;
1197  m_framesPlayed++;
1198 
1199  if (!m_setReadAhead)
1200  {
1201  m_videoSizeTotal += m_frameHeader.packetlength;
1203 
1204  if (m_videoFramesRead > 15)
1205  {
1207 
1208  float bps = (m_videoSizeTotal * 8.0F / 1024.0F *
1209  static_cast<float>(m_videoFrameRate));
1210  m_bitrate = (uint) (bps * 1.5F);
1211 
1213  m_setReadAhead = true;
1214  }
1215  }
1216  continue;
1217  }
1218 
1219  if (m_frameHeader.frametype=='A' && (kDecodeAudio & decodetype))
1220  {
1221  if ((m_frameHeader.comptype == '3') || (m_frameHeader.comptype == 'A'))
1222  {
1223  if (m_getRawFrames)
1225 
1226  if (!m_mpaAudCodec)
1227  {
1228  if (m_frameHeader.comptype == '3')
1229  InitAVCodecAudio(AV_CODEC_ID_MP3);
1230  else if (m_frameHeader.comptype == 'A')
1231  InitAVCodecAudio(AV_CODEC_ID_AC3);
1232  else
1233  {
1234  LOG(VB_GENERAL, LOG_ERR, LOC + QString("GetFrame: "
1235  "Unknown audio comptype of '%1', skipping")
1236  .arg(m_frameHeader.comptype));
1237  return false;
1238  }
1239  }
1240 
1241  av_init_packet(&pkt);
1242  pkt.data = m_strm;
1243  pkt.size = m_frameHeader.packetlength;
1244 
1245  QMutexLocker locker(avcodeclock);
1246 
1247  while (pkt.size > 0 && m_audio->HasAudioOut())
1248  {
1249  int data_size = 0;
1250 
1252  data_size, &pkt);
1253  if (ret < 0)
1254  {
1255  LOG(VB_GENERAL, LOG_ERR, LOC + "Unknown audio decoding error");
1256  return false;
1257  }
1258 
1259  pkt.size -= ret;
1260  pkt.data += ret;
1261  if (data_size <= 0)
1262  continue;
1263 
1264  m_audio->AddAudioData((char *)m_audioSamples, data_size,
1265  m_frameHeader.timecode, 0);
1266  }
1267  }
1268  else
1269  {
1270  m_getRawFrames = false;
1271 #if HAVE_BIGENDIAN
1272  // Why endian correct the audio buffer here?
1273  // Don't big-endian clients have to do it in audiooutBlah.cpp?
1274  if (m_audioBitsPerSample == 16) {
1275  // swap bytes
1276  for (int i = 0; i < (m_frameHeader.packetlength & ~1); i+=2) {
1277  char tmp;
1278  tmp = m_strm[i+1];
1279  m_strm[i+1] = m_strm[i];
1280  m_strm[i] = tmp;
1281  }
1282  }
1283 #endif
1284  LOG(VB_PLAYBACK, LOG_DEBUG, QString("A audio timecode %1")
1285  .arg(m_frameHeader.timecode));
1286  m_audio->AddAudioData((char *)m_strm, m_frameHeader.packetlength,
1287  m_frameHeader.timecode, 0);
1288  }
1289  }
1290 
1291  if (m_frameHeader.frametype == 'T' && (kDecodeVideo & decodetype))
1292  {
1293  if (m_getRawFrames)
1295 
1297  m_frameHeader.timecode, m_frameHeader.comptype);
1298  }
1299 
1300  if (m_frameHeader.frametype == 'S' && m_frameHeader.comptype == 'M')
1301  {
1302  unsigned char *eop = m_strm + m_frameHeader.packetlength;
1303  unsigned char *cur = m_strm;
1304 
1305  struct rtfileheader tmphead {};
1306  struct rtfileheader *fh = &tmphead;
1307 
1308  memcpy(fh, cur, min((int)sizeof(*fh), m_frameHeader.packetlength));
1309 
1310  while (QString(fh->finfo) != "MythTVVideo" &&
1311  cur + m_frameHeader.packetlength <= eop)
1312  {
1313  cur++;
1314  memcpy(fh, cur, min((int)sizeof(*fh), m_frameHeader.packetlength));
1315  }
1316 
1317  if (QString(fh->finfo) == "MythTVVideo")
1318  {
1319 #if HAVE_BIGENDIAN
1320  fh->width = bswap_32(fh->width);
1321  fh->height = bswap_32(fh->height);
1322  fh->desiredwidth = bswap_32(fh->desiredwidth);
1323  fh->desiredheight = bswap_32(fh->desiredheight);
1324  fh->aspect = bswap_dbl(fh->aspect);
1325  fh->fps = bswap_dbl(fh->fps);
1326  fh->videoblocks = bswap_32(fh->videoblocks);
1327  fh->audioblocks = bswap_32(fh->audioblocks);
1328  fh->textsblocks = bswap_32(fh->textsblocks);
1329  fh->keyframedist = bswap_32(fh->keyframedist);
1330 #endif
1331 
1332  m_fileHeader = *fh;
1333 
1334  if (m_fileHeader.aspect > .999 && m_fileHeader.aspect < 1.001)
1335  m_fileHeader.aspect = 4.0 / 3;
1336  m_currentAspect = m_fileHeader.aspect;
1337 
1338  GetPlayer()->SetKeyframeDistance(m_fileHeader.keyframedist);
1340  m_fileHeader.fps, m_currentAspect, false, 2);
1341  }
1342  }
1343  }
1344 
1346 
1347  return true;
1348 }
1349 
1350 void NuppelDecoder::SeekReset(long long newKey, uint skipFrames,
1351  bool doFlush, bool discardFrames)
1352 {
1353  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1354  QString("SeekReset(%1, %2, %3 flush, %4 discard)")
1355  .arg(newKey).arg(skipFrames)
1356  .arg((doFlush) ? "do" : "don't")
1357  .arg((discardFrames) ? "do" : "don't"));
1358 
1359  QMutexLocker locker(avcodeclock);
1360 
1361  DecoderBase::SeekReset(newKey, skipFrames, doFlush, discardFrames);
1362 
1363  if (m_mpaVidCodec && doFlush)
1364  avcodec_flush_buffers(m_mpaVidCtx);
1365 
1366  if (discardFrames)
1367  GetPlayer()->DiscardVideoFrames(doFlush, false);
1368 
1369  for (;(skipFrames > 0) && !m_atEof; skipFrames--)
1370  {
1371  bool retry = false;
1372  GetFrame(kDecodeAV, retry);
1373  if (m_decodedVideoFrame)
1375  }
1376 }
1377 
1378 /* vim: set expandtab tabstop=4 shiftwidth=4: */
uint m_bitrate
Definition: decoderbase.h:304
void DeLimboFrame(VideoFrame *frame)
Definition: mythplayer.cpp:981
int lavc_qmax
Definition: format.h:112
void SetKeyframeDistance(int keyframedistance)
Definition: mythplayer.cpp:520
#define FOURCC_I263
Definition: fourcc.h:97
MythPlayer * GetPlayer()
Definition: decoderbase.h:154
int pitches[3]
Y, U, & V pitches.
Definition: mythframe.h:159
int audio_bits_per_sample
Definition: format.h:99
AVCodecContext * m_mpaAudCtx
static const int kMaxSizeBuffer
kMaxSizeBuffer is the maximum size of a buffer to be used with DecodeAudio
Definition: audiooutput.h:194
unsigned char * m_strm
int textsblocks
Definition: format.h:26
#define LOC
static void copybuffer(VideoFrame *dst, uint8_t *buffer, int pitch, VideoFrameType type=FMT_YV12)
Definition: mythframe.h:698
void DiscardVideoFrames(bool KeyFrame, bool Flushed)
Places frames in the available frames queue.
Definition: mythplayer.cpp:944
VideoFrame * m_decodedVideoFrame
int lavc_qmin
Definition: format.h:111
long long m_readAdjust
Definition: decoderbase.h:348
virtual void SeekReset(long long newkey, uint skipFrames, bool doFlush, bool discardFrames)
Definition: decoderbase.cpp:70
static void CopyToVideo(unsigned char *buf, int video_width, int video_height, VideoFrame *frame)
unsigned char * buf
Definition: mythframe.h:139
int Copy(VideoFrame *dst, const VideoFrame *src)
Definition: mythavutil.cpp:330
#define EXTENDEDSIZE
Definition: format.h:137
bool LiveMode(void) const
Returns true if this RingBuffer has been assigned a LiveTVChain.
unsigned long long m_frameCounter
Definition: decoderbase.h:308
VideoFrame * GetNextVideoFrame(void)
Removes a frame from the available queue for decoding onto.
Definition: mythplayer.cpp:895
MythCodecID
Definition: mythcodecid.h:10
RTjpeg * m_rtjd
Definition: nuppeldecoder.h:89
static void error(const char *str,...)
Definition: vbi.c:42
int lavc_maxqdiff
Definition: format.h:113
bool m_hasFullPositionMap
Definition: decoderbase.h:324
bool DecodeFrame(struct rtframeheader *frameheader, unsigned char *lstrm, VideoFrame *frame)
long long file_offset
Definition: format.h:125
#define FOURCC_H263
Definition: fourcc.h:94
void release_nuppel_buffer(void *opaque, uint8_t *data)
void SetAudioParams(AudioFormat format, int orig_channels, int channels, AVCodecID codec, int samplerate, bool passthru, int codec_profile=-1)
Set audio output parameters.
bool m_hasKeyFrameAdjustTable
Definition: decoderbase.h:340
int get_nuppel_buffer(struct AVCodecContext *c, AVFrame *pic, int)
MarkTypes m_positionMapType
Definition: decoderbase.h:327
struct AVFrame AVFrame
QString GetFilename(void) const
Returns name of file used by this RingBuffer.
char finfo[12]
Definition: format.h:14
char frametype
Definition: format.h:32
int lavc_bitrate
Definition: format.h:110
#define FOURCC_HFYU
Definition: fourcc.h:96
bool m_getRawFrames
Definition: decoderbase.h:342
int keyframe_number
Definition: format.h:132
Definition: space.py:1
QString ReinitAudio(void)
void StoreRawData(unsigned char *strm)
Definition: format.h:123
long UpdateStoredFrameNum(long framenumber) override
int timecode
Definition: format.h:81
MythCodecID GetVideoCodecID(void) const override
#define FOURCC_AC3
Definition: fourcc.h:84
static guint32 * tmp
Definition: goom_core.c:35
AudioPlayer * m_audio
Definition: decoderbase.h:295
uint8_t * m_audioSamples
void WriteStoredData(RingBuffer *rb, bool storevid, long timecodeOffset) override
bool m_directRendering
float aspect
Definition: mythframe.h:143
char comptype
Definition: format.h:39
virtual void SetEof(bool eof)
Definition: decoderbase.h:134
#define FOURCC_MJPG
Definition: fourcc.h:98
bool m_getRawVideo
Definition: decoderbase.h:343
void SetFileLength(int total, int frames)
Definition: mythplayer.cpp:672
int audio_quality
Definition: format.h:104
Holds information on recordings and videos.
Definition: programinfo.h:67
long long seektable_offset
Definition: format.h:115
bool GetFrame(DecodeType, bool &) override
Demux, preprocess and possibly decode a frame of video/audio.
int videoblocks
Definition: format.h:24
#define RTJ_YUV420
Definition: RTjpegN.h:60
void CloseAVCodecVideo(void)
void SetVideoParams(int w, int h, double fps, float aspect, bool ForceUpdate, int ReferenceFrames, FrameScanType scan=kScan_Ignore, const QString &codecName=QString())
Definition: mythplayer.cpp:603
uint GetRawBitrate(void) const
Returns the estimated bitrate if the video were played at normal speed.
Definition: decoderbase.h:201
const int kDecoderProbeBufferSize
Definition: decoderbase.h:23
int version
Definition: format.h:94
unsigned char * m_planes[3]
frm_pos_map_t m_frameToDurMap
Definition: decoderbase.h:331
void SeekReset(long long newKey=0, uint skipFrames=0, bool doFlush=false, bool discardFrames=false) override
int desiredwidth
Definition: format.h:18
void CloseAVCodecAudio(void)
friend int get_nuppel_buffer(struct AVCodecContext *c, AVFrame *pic, int flags)
sinfo_vec_t m_tracks[kTrackTypeCount]
Definition: decoderbase.h:355
bool HasAudioOut(void) const
Definition: audioplayer.h:53
unsigned char * packet
Definition: nuppeldecoder.h:30
bool m_errored
Definition: decoderbase.h:345
bool ReadFrameheader(struct rtframeheader *fh)
unsigned char * m_buf
uint8_t * m_ffmpegExtraData
int SetFormat(const int *fmt)
Definition: RTjpegN.cpp:2683
unsigned char * m_buf2
QMutex m_positionMapLock
Definition: decoderbase.h:329
double aspect
Definition: format.h:22
int m_keyframeDist
Definition: decoderbase.h:311
long long m_framesPlayed
Definition: decoderbase.h:306
int DecodeAudio(AVCodecContext *ctx, uint8_t *buffer, int &data_size, const AVPacket *pkt)
DecodeAudio Utility routine.
unsigned int uint
Definition: compat.h:140
int rtjpeg_quality
Definition: format.h:106
#define FOURCC_LAME
Definition: fourcc.h:82
#define FOURCC_WMV1
Definition: fourcc.h:104
long long keyframeadjust_offset
Definition: format.h:117
void AddTextData(unsigned char *buf, int len, int64_t timecode, char type) override
QString GetRawEncodingType(void) override
bool InitAVCodecVideo(int codec)
bool InitAVCodecAudio(int codec)
virtual long long GetReadPosition(void) const =0
Returns how far into the file we have read.
#define FOURCC_H264
Definition: fourcc.h:95
int audio_compression_ratio
Definition: format.h:103
#define FOURCC_DIVX
Definition: fourcc.h:92
void * av_malloc(unsigned int size)
int audio_channels
Definition: format.h:100
#define FRAMEHEADERSIZE
Definition: format.h:135
static bool isValidFrametype(char type)
static bool CanHandle(char testbuf[kDecoderProbeBufferSize], int testbufsize=kDecoderProbeBufferSize)
long long frameNumber
Definition: mythframe.h:147
bool m_waitingForChange
Definition: decoderbase.h:347
Definition: RTjpegN.h:64
float m_currentAspect
Definition: decoderbase.h:300
struct rtframeheader frameheader
Definition: nuppeldecoder.h:29
virtual bool SyncPositionMap(void)
Updates the position map used for skipping frames.
int rtjpeg_luma_filter
Definition: format.h:107
long long m_lastKey
Definition: decoderbase.h:310
virtual void ReleaseNextVideoFrame(VideoFrame *buffer, int64_t timecode, bool wrap=true)
Places frame on the queue of frames ready for display.
Definition: mythplayer.cpp:905
#define FOURCC_MPG2
Definition: fourcc.h:101
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
RingBuffer * m_ringBuffer
Definition: decoderbase.h:296
frm_pos_map_t m_durToFrameMap
Definition: decoderbase.h:332
bool ReadFileheader(struct rtfileheader *fh)
AVCodec * m_mpaVidCodec
vector< PosMapEntry > m_positionMap
Definition: decoderbase.h:330
long long frameCounter
raw frame counter/ticker for discontinuity checks
Definition: mythframe.h:148
QMutex * avcodeclock
This global variable is used to makes certain calls to avlib threadsafe.
int keyframedist
Definition: format.h:27
int offsets[3]
Y, U, & V offsets.
Definition: mythframe.h:160
int video_fourcc
Definition: format.h:95
MythAVCopy m_copyFrame
Definition: decoderbase.h:313
DecodeType
Definition: decoderbase.h:47
void DiscardVideoFrame(VideoFrame *buffer)
Places frame in the available frames queue.
Definition: mythplayer.cpp:925
void ClearStoredData(void) override
void FileChanged(void)
VideoFrame * m_directFrame
int height
Definition: mythframe.h:142
#define FOURCC_MP42
Definition: fourcc.h:99
~NuppelDecoder() override
StreamInfo m_selectedTrack[(uint) kTrackTypeCount]
Definition: decoderbase.h:357
long long m_totalFrames
double fps
Definition: format.h:23
void SetEffDsp(int dsprate)
int Read(void *buf, int count)
This is the public method for reading from a file, it calls the appropriate read method if the file i...
int audio_sample_rate
Definition: format.h:98
NuppelDecoder(MythPlayer *parent, const ProgramInfo &pginfo)
AVCodecContext * m_mpaVidCtx
#define FOURCC_DIV3
Definition: fourcc.h:91
int adjust
Definition: format.h:131
int Write(const void *buf, uint count)
Writes buffer to ThreadedFileWriter::Write(const void*,uint)
list< RawDataList * > m_storedData
MythAVFrame little utility class that act as a safe way to allocate an AVFrame which can then be allo...
Definition: mythavutil.h:42
int audioblocks
Definition: format.h:25
int keyframe_number
Definition: format.h:126
#define FOURCC_MPG4
Definition: fourcc.h:102
Implements a file/stream reader/writer.
virtual CC608Reader * GetCC608Reader(uint=0)
Definition: mythplayer.h:325
void AddAudioData(char *buffer, int len, int64_t timecode, int frames)
int m_ffmpegExtraDataSize
void UpdateRawBitrate(uint raw_bitrate)
Set the raw bit rate, to allow RingBuffer adjust effective bitrate.
Definition: ringbuffer.cpp:307
long long Seek(long long pos, int whence, bool has_lock=false)
Seeks to a particular position in the file.
Definition: ringbuffer.cpp:510
AVCodec * m_mpaAudCodec
int rtjpeg_chroma_filter
Definition: format.h:108
long long m_framesRead
Definition: decoderbase.h:307
double m_videoFrameRate
Definition: nuppeldecoder.h:94
int height
Definition: format.h:17
#define FILEHEADERSIZE
Definition: format.h:136
Definition: format.h:129
int width
Definition: format.h:16
void Decompress(int8_t *sp, uint8_t **planes)
Definition: RTjpegN.cpp:3306
#define FOURCC_MPEG
Definition: fourcc.h:100
int audio_fourcc
Definition: format.h:96
int desiredheight
Definition: format.h:19
int packetlength
Definition: format.h:83
int OpenFile(RingBuffer *rbuffer, bool novideo, char testbuf[kDecoderProbeBufferSize], int testbufsize=kDecoderProbeBufferSize) override
EofState m_atEof
Definition: decoderbase.h:320