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;
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;
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;
338  int offset = 0;
339 
340  ste.file_offset = 0;
341  ste.keyframe_number = 0;
342 
343  m_positionMapLock.lock();
344 
345  m_positionMap.clear();
346  m_positionMap.reserve(numentries);
347 
348  for (int z = 0; z < numentries; z++)
349  {
350  memcpy(&ste, seekbuf + offset,
351  sizeof(struct seektable_entry));
352 #if HAVE_BIGENDIAN
353  ste.file_offset = bswap_64(ste.file_offset);
354  ste.keyframe_number = bswap_32(ste.keyframe_number);
355 #endif
356  offset += sizeof(struct seektable_entry);
357 
358  PosMapEntry e = {ste.keyframe_number,
360  ste.file_offset};
361  m_positionMap.push_back(e);
362  uint64_t frame_num = ste.keyframe_number * m_keyframedist;
363  m_frameToDurMap[frame_num] =
364  frame_num * 1000 / m_video_frame_rate;
365  m_durToFrameMap[m_frameToDurMap[frame_num]] = frame_num;
366  }
367  m_hasFullPositionMap = true;
368  m_totalLength = (int)((ste.keyframe_number * m_keyframedist * 1.0) /
370  m_totalFrames = (long long)ste.keyframe_number * m_keyframedist;
371 
372  m_positionMapLock.unlock();
373 
375 
376  delete [] seekbuf;
377  }
378  else
379  LOG(VB_GENERAL, LOG_ERR, "0 length seek table");
380  }
381 
382  ringBuffer->Seek(currentpos, SEEK_SET);
383  }
384 
387  {
388  long long currentpos = ringBuffer->GetReadPosition();
389  struct rtframeheader kfa_frameheader;
390 
392  SEEK_SET);
393  if (kfa_ret == -1)
394  {
395  LOG(VB_GENERAL, LOG_ERR,
396  QString("NuppelDecoder::OpenFile(): keyframeadjust (%1)")
397  .arg(strerror(errno)));
398  }
399 
400  ringBuffer->Read(&kfa_frameheader, FRAMEHEADERSIZE);
401 
402  if (kfa_frameheader.frametype != 'K')
403  {
404  LOG(VB_GENERAL, LOG_ERR,
405  QString("Invalid key frame adjust table (frametype %1)")
406  .arg((int)kfa_frameheader.frametype));
407  }
408  else
409  {
410  if (kfa_frameheader.packetlength > 0)
411  {
412  char *kfa_buf = new char[kfa_frameheader.packetlength];
413  ringBuffer->Read(kfa_buf, kfa_frameheader.packetlength);
414 
415  int numentries = kfa_frameheader.packetlength /
416  sizeof(struct kfatable_entry);
417  struct kfatable_entry kfate;
418  int offset = 0;
419  int adjust = 0;
420  QMap<long long, int> keyFrameAdjustMap;
421 
422  for (int z = 0; z < numentries; z++)
423  {
424  memcpy(&kfate, kfa_buf + offset,
425  sizeof(struct kfatable_entry));
426 #if HAVE_BIGENDIAN
427  kfate.adjust = bswap_32(kfate.adjust);
428  kfate.keyframe_number = bswap_32(kfate.keyframe_number);
429 #endif
430  offset += sizeof(struct kfatable_entry);
431 
432  keyFrameAdjustMap[kfate.keyframe_number] = kfate.adjust;
433  adjust += kfate.adjust;
434  }
436 
440 
441  adjust = 0;
442 
443  {
444  QMutexLocker locker(&m_positionMapLock);
445  for (size_t i = 0; i < m_positionMap.size(); i++)
446  {
447  long long adj = m_positionMap[i].adjFrame;
448 
449  if (keyFrameAdjustMap.contains(adj))
450  adjust += keyFrameAdjustMap[adj];
451 
452  m_positionMap[i].adjFrame -= adjust;
453  }
454  }
455 
456  delete [] kfa_buf;
457  }
458  else
459  LOG(VB_GENERAL, LOG_ERR, "0 length key frame adjust table");
460  }
461 
462  ringBuffer->Seek(currentpos, SEEK_SET);
463  }
464 
465  while (frameheader.frametype != 'A' && frameheader.frametype != 'V' &&
466  frameheader.frametype != 'S' && frameheader.frametype != 'T' &&
467  frameheader.frametype != 'R')
468  {
469  ringBuffer->Seek(startpos, SEEK_SET);
470 
471  char dummychar;
472  ringBuffer->Read(&dummychar, 1);
473 
474  startpos = ringBuffer->GetReadPosition();
475 
476  if (!ReadFrameheader(&frameheader))
477  {
478  delete [] space;
479  return -1;
480  }
481 
482  if (startpos > 20000)
483  {
484  delete [] space;
485  return -1;
486  }
487  }
488 
489  foundit = 0;
490 
493 
494  if (m_usingextradata)
495  {
499 #if HAVE_BIGENDIAN
500  // Why only if using extradata?
501  m_audio_bits_per_sample = m_extradata.audio_bits_per_sample;
502 #endif
503  AudioFormat format = FORMAT_NONE;
505  {
506  case 8: format = FORMAT_U8; break;
507  case 16: format = FORMAT_S16; break;
508  case 24: format = FORMAT_S24; break;
509  case 32: format = FORMAT_S32; break;
510  }
511 
514  AV_CODEC_ID_NONE, m_extradata.audio_sample_rate,
515  false /* AC3/DTS pass through */);
516  m_audio->ReinitAudio();
517  foundit = 1;
518  }
519 
520  while (!foundit)
521  {
522  if (frameheader.frametype == 'S')
523  {
524  if (frameheader.comptype == 'A')
525  {
526  m_effdsp = frameheader.timecode;
527  if (m_effdsp > 0)
528  {
530  foundit = 1;
531  continue;
532  }
533  }
534  }
535  if (frameheader.frametype != 'R' && frameheader.packetlength != 0)
536  {
537  if (frameheader.packetlength != ringBuffer->Read(space,
538  frameheader.packetlength))
539  {
540  foundit = 1;
541  continue;
542  }
543  }
544 
545  long long startpos2 = ringBuffer->GetReadPosition();
546 
547  foundit = !ReadFrameheader(&frameheader);
548 
549  bool framesearch = false;
550 
551  while (frameheader.frametype != 'A' && frameheader.frametype != 'V' &&
552  frameheader.frametype != 'S' && frameheader.frametype != 'T' &&
553  frameheader.frametype != 'R' && frameheader.frametype != 'X')
554  {
555  if (!framesearch)
556  LOG(VB_GENERAL, LOG_INFO, "Searching for frame header.");
557 
558  framesearch = true;
559 
560  ringBuffer->Seek(startpos2, SEEK_SET);
561 
562  char dummychar;
563  ringBuffer->Read(&dummychar, 1);
564 
565  startpos2 = ringBuffer->GetReadPosition();
566 
567  foundit = !ReadFrameheader(&frameheader);
568  if (foundit)
569  break;
570  }
571  }
572 
573  delete [] space;
574 
575  m_setreadahead = false;
576 
577  // mpeg4 encodes are small enough that this shouldn't matter
579  m_setreadahead = true;
580 
581  m_bitrate = 0;
582  unsigned min_bitrate = 1000;
584  {
585  // Use video bitrate, ignore negligible audio bitrate
587  }
588  m_bitrate = max(m_bitrate, min_bitrate); // set minimum 1 Mb/s to be safe
589  LOG(VB_PLAYBACK, LOG_INFO,
590  QString("Setting bitrate to %1 Kb/s").arg(m_bitrate));
591 
593 
594  m_videosizetotal = 0;
595  m_videoframesread = 0;
596 
597  ringBuffer->Seek(startpos, SEEK_SET);
598 
599  m_buf = (unsigned char*)av_malloc(m_video_size);
600  m_strm = (unsigned char*)av_malloc(m_video_size * 2);
601 
603  return 1;
604 
605  if (SyncPositionMap())
606  return 1;
607 
608  return 0;
609 }
610 
611 void release_nuppel_buffer(void *opaque, uint8_t *data)
612 {
613  VideoFrame *frame = (VideoFrame*)data;
614  NuppelDecoder *nd = (NuppelDecoder*)opaque;
615  if (nd && nd->GetPlayer())
616  nd->GetPlayer()->DeLimboFrame(frame);
617 }
618 
619 int get_nuppel_buffer(struct AVCodecContext *c, AVFrame *pic, int /*flags*/)
620 {
621  NuppelDecoder *nd = (NuppelDecoder *)(c->opaque);
622 
623  int i;
624 
625  for (i = 0; i < 3; i++)
626  {
627  pic->data[i] = nd->m_directframe->buf + nd->m_directframe->offsets[i];
628  pic->linesize[i] = nd->m_directframe->pitches[i];
629  }
630 
631  pic->opaque = nd->m_directframe;
632 
633  // Set release method
634  AVBufferRef *buffer =
635  av_buffer_create((uint8_t*)nd->m_directframe, 0, release_nuppel_buffer, nd, 0);
636  pic->buf[0] = buffer;
637 
638  return 0;
639 }
640 
642 {
643  if (m_mpa_vidcodec)
645 
646  if (m_usingextradata)
647  {
648  switch(m_extradata.video_fourcc)
649  {
650  case FOURCC_DIVX: codec = AV_CODEC_ID_MPEG4; break;
651  case FOURCC_WMV1: codec = AV_CODEC_ID_WMV1; break;
652  case FOURCC_DIV3: codec = AV_CODEC_ID_MSMPEG4V3; break;
653  case FOURCC_MP42: codec = AV_CODEC_ID_MSMPEG4V2; break;
654  case FOURCC_MPG4: codec = AV_CODEC_ID_MSMPEG4V1; break;
655  case FOURCC_MJPG: codec = AV_CODEC_ID_MJPEG; break;
656  case FOURCC_H263: codec = AV_CODEC_ID_H263; break;
657  case FOURCC_H264: codec = AV_CODEC_ID_H264; break;
658  case FOURCC_I263: codec = AV_CODEC_ID_H263I; break;
659  case FOURCC_MPEG: codec = AV_CODEC_ID_MPEG1VIDEO; break;
660  case FOURCC_MPG2: codec = AV_CODEC_ID_MPEG2VIDEO; break;
661  case FOURCC_HFYU: codec = AV_CODEC_ID_HUFFYUV; break;
662  default: codec = -1;
663  }
664  }
665  m_mpa_vidcodec = avcodec_find_decoder((enum AVCodecID)codec);
666 
667  if (!m_mpa_vidcodec)
668  {
669  if (m_usingextradata)
670  LOG(VB_GENERAL, LOG_ERR,
671  QString("couldn't find video codec (%1)")
672  .arg(m_extradata.video_fourcc));
673  else
674  LOG(VB_GENERAL, LOG_ERR, "couldn't find video codec");
675  return false;
676  }
677 
678  if (m_mpa_vidcodec->capabilities & AV_CODEC_CAP_DR1 && codec != AV_CODEC_ID_MJPEG)
679  m_directrendering = true;
680 
681  if (m_mpa_vidctx)
682  avcodec_free_context(&m_mpa_vidctx);
683 
684  m_mpa_vidctx = avcodec_alloc_context3(nullptr);
685 
686  m_mpa_vidctx->codec_id = (enum AVCodecID)codec;
687  m_mpa_vidctx->codec_type = AVMEDIA_TYPE_VIDEO;
688  m_mpa_vidctx->width = m_video_width;
689  m_mpa_vidctx->height = m_video_height;
690  m_mpa_vidctx->err_recognition = AV_EF_CRCCHECK | AV_EF_BITSTREAM |
691  AV_EF_BUFFER;
692  m_mpa_vidctx->bits_per_coded_sample = 12;
693 
694  if (m_directrendering)
695  {
696  // m_mpa_vidctx->flags |= CODEC_FLAG_EMU_EDGE;
697  m_mpa_vidctx->draw_horiz_band = nullptr;
698  m_mpa_vidctx->get_buffer2 = get_nuppel_buffer;
699  m_mpa_vidctx->opaque = (void *)this;
700  }
701  if (m_ffmpeg_extradatasize > 0)
702  {
703  av_opt_set_int(m_mpa_vidctx, "extern_huff", 1, 0);
704  m_mpa_vidctx->extradata = m_ffmpeg_extradata;
705  m_mpa_vidctx->extradata_size = m_ffmpeg_extradatasize;
706  }
707 
708  QMutexLocker locker(avcodeclock);
709  if (avcodec_open2(m_mpa_vidctx, m_mpa_vidcodec, nullptr) < 0)
710  {
711  LOG(VB_GENERAL, LOG_ERR, LOC + "Couldn't find lavc video codec");
712  return false;
713  }
714 
715  return true;
716 }
717 
719 {
720  QMutexLocker locker(avcodeclock);
721 
723  avcodec_free_context(&m_mpa_vidctx);
724 }
725 
727 {
728  if (m_mpa_audcodec)
730 
731  if (m_usingextradata)
732  {
733  switch(m_extradata.audio_fourcc)
734  {
735  case FOURCC_LAME: codec = AV_CODEC_ID_MP3; break;
736  case FOURCC_AC3 : codec = AV_CODEC_ID_AC3; break;
737  default: codec = -1;
738  }
739  }
740  m_mpa_audcodec = avcodec_find_decoder((enum AVCodecID)codec);
741 
742  if (!m_mpa_audcodec)
743  {
744  if (m_usingextradata)
745  LOG(VB_GENERAL, LOG_ERR, QString("couldn't find audio codec (%1)")
746  .arg(m_extradata.audio_fourcc));
747  else
748  LOG(VB_GENERAL, LOG_ERR, "couldn't find audio codec");
749  return false;
750  }
751 
752  if (m_mpa_audctx)
753  avcodec_free_context(&m_mpa_audctx);
754 
755  m_mpa_audctx = avcodec_alloc_context3(nullptr);
756 
757  m_mpa_audctx->codec_id = (enum AVCodecID)codec;
758  m_mpa_audctx->codec_type = AVMEDIA_TYPE_AUDIO;
759 
760  QMutexLocker locker(avcodeclock);
761  if (avcodec_open2(m_mpa_audctx, m_mpa_audcodec, nullptr) < 0)
762  {
763  LOG(VB_GENERAL, LOG_ERR, LOC + "Couldn't find lavc audio codec");
764  return false;
765  }
766 
767  return true;
768 }
769 
771 {
772  QMutexLocker locker(avcodeclock);
773 
775  avcodec_free_context(&m_mpa_audctx);
776 }
777 
778 static void CopyToVideo(unsigned char *buf, int video_width,
779  int video_height, VideoFrame *frame)
780 {
781  (void)video_width;
782  (void)video_height;
783  copybuffer(frame, buf, frame->width);
784 }
785 
786 bool NuppelDecoder::DecodeFrame(struct rtframeheader *frameheader,
787  unsigned char *lstrm, VideoFrame *frame)
788 {
789  lzo_uint out_len;
790  int compoff = 0;
791 
792  m_directframe = frame;
793 
794  if (!m_buf2)
795  {
796  m_buf2 = (unsigned char*)av_malloc(m_video_size + 64);
797  m_planes[0] = m_buf;
799  m_planes[2] = m_planes[1] + (m_video_width * m_video_height) / 4;
800  }
801 
802  if (frameheader->comptype == 'N')
803  {
804  memset(frame->buf, 0, frame->pitches[0] * m_video_height);
805  memset(frame->buf + frame->offsets[1], 127,
806  frame->pitches[1] * frame->height / 2);
807  memset(frame->buf + frame->offsets[2], 127,
808  frame->pitches[2] * frame->height / 2);
809  return true;
810  }
811 
812  if (frameheader->comptype == 'L')
813  {
814  switch(m_lastct)
815  {
816  case '0': case '3':
818  break;
819  case '1': case '2':
820  default:
822  break;
823  }
824  return true;
825  }
826 
827  compoff = 1;
828  if (frameheader->comptype == '2' || frameheader->comptype == '3')
829  compoff=0;
830 
831  m_lastct = frameheader->comptype;
832 
833  if (!compoff)
834  {
835  int r = lzo1x_decompress(lstrm, frameheader->packetlength, m_buf2, &out_len,
836  nullptr);
837  if (r != LZO_E_OK)
838  {
839  LOG(VB_GENERAL, LOG_ERR, "minilzo: can't decompress illegal data");
840  }
841  }
842 
843  if (frameheader->comptype == '0')
844  {
845  CopyToVideo(lstrm, m_video_width, m_video_height, frame);
846  return true;
847  }
848 
849  if (frameheader->comptype == '3')
850  {
852  return true;
853  }
854 
855  if (frameheader->comptype == '2' || frameheader->comptype == '1')
856  {
857  if (compoff)
858  m_rtjd->Decompress((int8_t*)lstrm, m_planes);
859  else
860  m_rtjd->Decompress((int8_t*)m_buf2, m_planes);
861 
863  }
864  else
865  {
866  if (!m_mpa_vidcodec)
867  InitAVCodecVideo(frameheader->comptype - '3');
868 
869  if (!m_mpa_vidctx)
870  {
871  LOG(VB_PLAYBACK, LOG_ERR, LOC + "NULL mpa_vidctx");
872  return false;
873  }
874 
875  MythAVFrame mpa_pic;
876  if (!mpa_pic)
877  return false;
878  AVPacket pkt;
879  av_init_packet(&pkt);
880  pkt.data = lstrm;
881  pkt.size = frameheader->packetlength;
882 
883  {
884  QMutexLocker locker(avcodeclock);
885  // if directrendering, writes into buf
886  bool gotpicture = false;
887  // SUGGESTION
888  // Now that avcodec_decode_video2 is deprecated and replaced
889  // by 2 calls (receive frame and send packet), this could be optimized
890  // into separate routines or separate threads.
891  // Also now that it always consumes a whole buffer some code
892  // in the caller may be able to be optimized.
893  int ret = avcodec_receive_frame(m_mpa_vidctx, mpa_pic);
894  if (ret == 0)
895  gotpicture = true;
896  if (ret == AVERROR(EAGAIN))
897  ret = 0;
898  if (ret == 0)
899  ret = avcodec_send_packet(m_mpa_vidctx, &pkt);
900  m_directframe = nullptr;
901  // The code assumes that there is always space to add a new
902  // packet. This seems risky but has always worked.
903  // It should actually check if (ret == AVERROR(EAGAIN)) and then keep
904  // the packet around and try it again after processing the frame
905  // received here.
906  if (ret < 0)
907  {
908  char error[AV_ERROR_MAX_STRING_SIZE];
909  LOG(VB_GENERAL, LOG_ERR, LOC +
910  QString("video decode error: %1 (%2)")
911  .arg(av_make_error_string(error, sizeof(error), ret))
912  .arg(gotpicture));
913  }
914  if (!gotpicture)
915  {
916  return false;
917  }
918  }
919 
920 /* XXX: Broken
921  if (mpa_pic->qscale_table != nullptr && mpa_pic->qstride > 0)
922  {
923  int tablesize = mpa_pic->qstride * ((m_video_height + 15) / 16);
924 
925  if (frame->qstride != mpa_pic->qstride ||
926  frame->qscale_table == nullptr)
927  {
928  frame->qstride = mpa_pic->qstride;
929 
930  if (frame->qscale_table)
931  delete [] frame->qscale_table;
932 
933  frame->qscale_table = new unsigned char[tablesize];
934  }
935 
936  memcpy(frame->qscale_table, mpa_pic->qscale_table, tablesize);
937  }
938 */
939 
940  if (m_directrendering)
941  return true;
942 
943  AVFrame *tmp = mpa_pic;
944  m_copyFrame.Copy(frame, tmp, m_mpa_vidctx->pix_fmt);
945  }
946 
947  return true;
948 }
949 
951 {
952  switch (type)
953  {
954  case 'A': case 'V': case 'S': case 'T': case 'R': case 'X':
955  case 'M': case 'D': case 'Q': case 'K':
956  return true;
957  default:
958  return false;
959  }
960 
961  return false;
962 }
963 
964 void NuppelDecoder::StoreRawData(unsigned char *newstrm)
965 {
966  unsigned char *strmcpy;
967  if (newstrm)
968  {
969  strmcpy = new unsigned char[m_frameheader.packetlength];
970  memcpy(strmcpy, newstrm, m_frameheader.packetlength);
971  }
972  else
973  strmcpy = nullptr;
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  list<RawDataList*>::iterator it = m_storedData.begin();
984  for ( ; it != m_storedData.end(); ++it)
985  {
986  RawDataList *data = *it;
987  if (data->frameheader.frametype == 'S' &&
988  data->frameheader.comptype == 'V')
989  {
990  data->frameheader.timecode = framenum;
991  return sync_offset;
992  }
993  sync_offset += FRAMEHEADERSIZE;
994  if (data->packet)
995  sync_offset += data->frameheader.packetlength;
996  }
997  return 0;
998 }
999 
1001  long timecodeOffset)
1002 {
1003  while (!m_storedData.empty())
1004  {
1005  RawDataList *data = m_storedData.front();
1006 
1007  if (data->frameheader.frametype != 'S')
1008  data->frameheader.timecode -= timecodeOffset;
1009 
1010  if (storevid || data->frameheader.frametype != 'V')
1011  {
1012  rb->Write(&(data->frameheader), FRAMEHEADERSIZE);
1013  if (data->packet)
1014  rb->Write(data->packet, data->frameheader.packetlength);
1015  }
1016  m_storedData.pop_front();
1017  delete data;
1018  }
1019 }
1020 
1022 {
1023  while (!m_storedData.empty())
1024  {
1025  RawDataList *data = m_storedData.front();
1026  m_storedData.pop_front();
1027  delete data;
1028  }
1029 }
1030 
1032 {
1033  bool gotvideo = false;
1034  int seeklen = 0;
1035  AVPacket pkt;
1036 
1037  m_decoded_video_frame = nullptr;
1038 
1039  while (!gotvideo)
1040  {
1041  long long currentposition = ringBuffer->GetReadPosition();
1042  if (m_waitingForChange && currentposition + 4 >= m_readAdjust)
1043  {
1044  FileChanged();
1045  currentposition = ringBuffer->GetReadPosition();
1046  }
1047 
1049  {
1050  SetEof(true);
1051  return false;
1052  }
1053 
1054 
1055  if (!ringBuffer->LiveMode() &&
1056  ((m_frameheader.frametype == 'Q') || (m_frameheader.frametype == 'K')))
1057  {
1058  SetEof(true);
1059  return false;
1060  }
1061 
1062  bool framesearch = false;
1063 
1065  {
1066  if (!framesearch)
1067  LOG(VB_GENERAL, LOG_INFO, "Searching for frame header.");
1068 
1069  framesearch = true;
1070 
1071  ringBuffer->Seek((long long)seeklen-FRAMEHEADERSIZE, SEEK_CUR);
1072 
1074  {
1075  SetEof(true);
1076  return false;
1077  }
1078  seeklen = 1;
1079  }
1080 
1081  if (m_frameheader.frametype == 'M')
1082  {
1083  int sizetoskip = sizeof(rtfileheader) - sizeof(rtframeheader);
1084  char *dummy = new char[sizetoskip + 1];
1085 
1086  if (ringBuffer->Read(dummy, sizetoskip) != sizetoskip)
1087  {
1088  delete [] dummy;
1089  SetEof(true);
1090  return false;
1091  }
1092 
1093  delete [] dummy;
1094  continue;
1095  }
1096 
1097  if (m_frameheader.frametype == 'R')
1098  {
1099  if (m_getrawframes)
1100  StoreRawData(nullptr);
1101  continue; // the R-frame has no data packet
1102  }
1103 
1104  if (m_frameheader.frametype == 'S')
1105  {
1106  if (m_frameheader.comptype == 'A')
1107  {
1108  if (m_frameheader.timecode > 2000000 &&
1109  m_frameheader.timecode < 5500000)
1110  {
1113  }
1114  }
1115  else if (m_frameheader.comptype == 'V')
1116  {
1119  m_frameheader.timecode - 1 : 0);
1120 
1121  if (!m_hasFullPositionMap)
1122  {
1123  long long last_index = 0;
1124  long long this_index = m_lastKey / m_keyframedist;
1125 
1126  QMutexLocker locker(&m_positionMapLock);
1127  if (!m_positionMap.empty())
1128  last_index = m_positionMap.back().index;
1129 
1130  if (this_index > last_index)
1131  {
1132  PosMapEntry e = {this_index, m_lastKey, currentposition};
1133  m_positionMap.push_back(e);
1135  m_lastKey * 1000 / m_video_frame_rate;
1137  }
1138  }
1139  }
1140  if (m_getrawframes)
1141  StoreRawData(nullptr);
1142  }
1143 
1144  if (m_frameheader.packetlength > 0)
1145  {
1146  if (m_frameheader.packetlength > 10485760) // arbitrary 10MB limit
1147  {
1148  LOG(VB_GENERAL, LOG_ERR, QString("Broken packet: %1 %2")
1149  .arg(m_frameheader.frametype)
1150  .arg(m_frameheader.packetlength));
1151  SetEof(true);
1152  return false;
1153  }
1156  {
1157  SetEof(true);
1158  return false;
1159  }
1160  }
1161  else
1162  continue;
1163 
1164  if (m_frameheader.frametype == 'V')
1165  {
1166  if (!(kDecodeVideo & decodetype))
1167  {
1168  m_framesPlayed++;
1169  gotvideo = true;
1170  continue;
1171  }
1172 
1174  if (!buf)
1175  continue;
1176 
1177  bool ret = DecodeFrame(&m_frameheader, m_strm, buf);
1178  if (!ret)
1179  {
1180  GetPlayer()->DiscardVideoFrame(buf);
1181  continue;
1182  }
1183 
1184  buf->aspect = m_current_aspect;
1185  buf->frameNumber = m_framesPlayed;
1186  buf->dummy = 0;
1188 
1189  // We need to make the frame available ourselves
1190  // if we are not using ffmpeg/avlib.
1191  if (m_directframe)
1192  GetPlayer()->DeLimboFrame(buf);
1193 
1194  m_decoded_video_frame = buf;
1195  gotvideo = true;
1198  m_framesPlayed++;
1199 
1200  if (!m_setreadahead)
1201  {
1204 
1205  if (m_videoframesread > 15)
1206  {
1208 
1209  float bps = (m_videosizetotal * 8.0F / 1024.0F *
1210  static_cast<float>(m_video_frame_rate));
1211  m_bitrate = (uint) (bps * 1.5F);
1212 
1214  m_setreadahead = true;
1215  }
1216  }
1217  continue;
1218  }
1219 
1220  if (m_frameheader.frametype=='A' && (kDecodeAudio & decodetype))
1221  {
1222  if ((m_frameheader.comptype == '3') || (m_frameheader.comptype == 'A'))
1223  {
1224  if (m_getrawframes)
1226 
1227  if (!m_mpa_audcodec)
1228  {
1229  if (m_frameheader.comptype == '3')
1230  InitAVCodecAudio(AV_CODEC_ID_MP3);
1231  else if (m_frameheader.comptype == 'A')
1232  InitAVCodecAudio(AV_CODEC_ID_AC3);
1233  else
1234  {
1235  LOG(VB_GENERAL, LOG_ERR, LOC + QString("GetFrame: "
1236  "Unknown audio comptype of '%1', skipping")
1237  .arg(m_frameheader.comptype));
1238  return false;
1239  }
1240  }
1241 
1242  av_init_packet(&pkt);
1243  pkt.data = m_strm;
1244  pkt.size = m_frameheader.packetlength;
1245 
1246  QMutexLocker locker(avcodeclock);
1247 
1248  while (pkt.size > 0 && m_audio->HasAudioOut())
1249  {
1250  int data_size = 0;
1251 
1253  data_size, &pkt);
1254  if (ret < 0)
1255  {
1256  LOG(VB_GENERAL, LOG_ERR, LOC + "Unknown audio decoding error");
1257  return false;
1258  }
1259 
1260  pkt.size -= ret;
1261  pkt.data += ret;
1262  if (data_size <= 0)
1263  continue;
1264 
1265  m_audio->AddAudioData((char *)m_audioSamples, data_size,
1266  m_frameheader.timecode, 0);
1267  }
1268  }
1269  else
1270  {
1271  m_getrawframes = false;
1272 #if HAVE_BIGENDIAN
1273  // Why endian correct the audio buffer here?
1274  // Don't big-endian clients have to do it in audiooutBlah.cpp?
1275  if (m_audio_bits_per_sample == 16) {
1276  // swap bytes
1277  for (int i = 0; i < (m_frameheader.packetlength & ~1); i+=2) {
1278  char tmp;
1279  tmp = m_strm[i+1];
1280  m_strm[i+1] = m_strm[i];
1281  m_strm[i] = tmp;
1282  }
1283  }
1284 #endif
1285  LOG(VB_PLAYBACK, LOG_DEBUG, QString("A audio timecode %1")
1286  .arg(m_frameheader.timecode));
1288  m_frameheader.timecode, 0);
1289  }
1290  }
1291 
1292  if (m_frameheader.frametype == 'T' && (kDecodeVideo & decodetype))
1293  {
1294  if (m_getrawframes)
1296 
1299  }
1300 
1301  if (m_frameheader.frametype == 'S' && m_frameheader.comptype == 'M')
1302  {
1303  unsigned char *eop = m_strm + m_frameheader.packetlength;
1304  unsigned char *cur = m_strm;
1305 
1306  struct rtfileheader tmphead;
1307  struct rtfileheader *fh = &tmphead;
1308 
1309  memcpy(fh, cur, min((int)sizeof(*fh), m_frameheader.packetlength));
1310 
1311  while (QString(fh->finfo) != "MythTVVideo" &&
1312  cur + m_frameheader.packetlength <= eop)
1313  {
1314  cur++;
1315  memcpy(fh, cur, min((int)sizeof(*fh), m_frameheader.packetlength));
1316  }
1317 
1318  if (QString(fh->finfo) == "MythTVVideo")
1319  {
1320 #if HAVE_BIGENDIAN
1321  fh->width = bswap_32(fh->width);
1322  fh->height = bswap_32(fh->height);
1323  fh->desiredwidth = bswap_32(fh->desiredwidth);
1324  fh->desiredheight = bswap_32(fh->desiredheight);
1325  fh->aspect = bswap_dbl(fh->aspect);
1326  fh->fps = bswap_dbl(fh->fps);
1327  fh->videoblocks = bswap_32(fh->videoblocks);
1328  fh->audioblocks = bswap_32(fh->audioblocks);
1329  fh->textsblocks = bswap_32(fh->textsblocks);
1330  fh->keyframedist = bswap_32(fh->keyframedist);
1331 #endif
1332 
1333  m_fileheader = *fh;
1334 
1335  if (m_fileheader.aspect > .999 && m_fileheader.aspect < 1.001)
1336  m_fileheader.aspect = 4.0 / 3;
1338 
1341  m_fileheader.fps);
1342  }
1343  }
1344  }
1345 
1347 
1348  return true;
1349 }
1350 
1351 void NuppelDecoder::SeekReset(long long newKey, uint skipFrames,
1352  bool doFlush, bool discardFrames)
1353 {
1354  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1355  QString("SeekReset(%1, %2, %3 flush, %4 discard)")
1356  .arg(newKey).arg(skipFrames)
1357  .arg((doFlush) ? "do" : "don't")
1358  .arg((discardFrames) ? "do" : "don't"));
1359 
1360  QMutexLocker locker(avcodeclock);
1361 
1362  DecoderBase::SeekReset(newKey, skipFrames, doFlush, discardFrames);
1363 
1364  if (m_mpa_vidcodec && doFlush)
1365  avcodec_flush_buffers(m_mpa_vidctx);
1366 
1367  if (discardFrames)
1368  GetPlayer()->DiscardVideoFrames(doFlush);
1369 
1370  for (;(skipFrames > 0) && !m_ateof; skipFrames--)
1371  {
1375  }
1376 }
1377 
1378 /* 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:680
#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:200
#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:893
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:832
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:3367
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