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