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