MythTV  master
avformatdecoderdvd.cpp
Go to the documentation of this file.
1 
2 #include "dvdringbuffer.h"
3 #include "mythdvdplayer.h"
4 #include "avformatdecoderdvd.h"
5 
6 #include "iso639.h"
7 
8 extern "C" {
9 #include "libavcodec/avcodec.h"
10 }
11 
12 #include <unistd.h> // for usleep()
13 
14 #define LOC QString("AFD_DVD: ")
15 
17 {
20 
21  while (!m_contextList.empty())
22  m_contextList.takeFirst()->DecrRef();
23 
25 }
26 
28 {
29  if (m_lastVideoPkt)
30  {
31  av_packet_unref(m_lastVideoPkt);
32  delete m_lastVideoPkt;
33  m_lastVideoPkt = nullptr;
35  }
36 }
37 
39 {
40  if (context)
41  {
42  context->DecrRef();
43  context = nullptr;
44  }
45 }
46 
47 void AvFormatDecoderDVD::Reset(bool reset_video_data, bool seek_reset, bool reset_file)
48 {
49  AvFormatDecoder::Reset(reset_video_data, seek_reset, reset_file);
51 }
52 
53 
55 {
56  if (!m_ringBuffer->IsDVD())
57  return;
58 
59  auto currentpos = (long long)(m_ringBuffer->DVD()->GetCurrentTime() * m_fps);
60  m_framesPlayed = m_framesRead = currentpos ;
61  m_parent->SetFramesPlayed(currentpos + 1);
62 }
63 
64 bool AvFormatDecoderDVD::GetFrame(DecodeType /*Type*/, bool &Retry)
65 {
66  // Always try to decode audio and video for DVDs
67  return AvFormatDecoder::GetFrame(kDecodeAV, Retry);
68 }
69 
70 int AvFormatDecoderDVD::ReadPacket(AVFormatContext *ctx, AVPacket* pkt, bool& storePacket)
71 {
72  int result = 0;
73 
74  if (m_framesReq > 0)
75  {
76  m_framesReq--;
77 
78  if (m_lastVideoPkt)
79  {
80  av_packet_ref(pkt, m_lastVideoPkt);
81 
82  if (m_lastVideoPkt->pts != AV_NOPTS_VALUE)
83  m_lastVideoPkt->pts += pkt->duration;
84 
85  if (m_lastVideoPkt->dts != AV_NOPTS_VALUE)
86  m_lastVideoPkt->dts += pkt->duration;
87  }
88  else
89  {
90  LOG(VB_GENERAL, LOG_ERR, LOC + QString( "Need to generate frame @ %1 - %2 but no frame available!")
91  .arg(pkt->pts)
92  .arg(m_framesReq));
93  }
94  }
95  else
96  {
97  bool gotPacket = false;
98 
99  do
100  {
101  gotPacket = true;
102 
103  do
104  {
106  {
107  int32_t lastEvent = m_ringBuffer->DVD()->GetLastEvent();
108  switch(lastEvent)
109  {
110  case DVDNAV_HOP_CHANNEL:
111  // Non-seamless jump - clear all buffers
112  m_framesReq = 0;
114 
115  while (!m_contextList.empty())
116  m_contextList.takeFirst()->DecrRef();
117 
118  Reset(true, false, false);
119  m_audio->Reset();
120  m_parent->DiscardVideoFrames(false, false);
121  break;
122 
123  case DVDNAV_WAIT:
124  case DVDNAV_STILL_FRAME:
125  if (m_storedPackets.count() > 0)
126  {
127  // Ringbuffer is waiting for the player
128  // to empty its buffers but we have one or
129  // more frames in our buffer that have not
130  // yet been sent to the player.
131  // Make sure no more frames will be buffered
132  // for the time being and start emptying our
133  // buffer.
134 
135  // Force AvFormatDecoder to stop buffering frames
136  storePacket = false;
137 
138  // Return the first buffered packet
139  AVPacket *storedPkt = m_storedPackets.takeFirst();
140  av_packet_ref(pkt, storedPkt);
141  av_packet_unref(storedPkt);
142  delete storedPkt;
143 
144  return 0;
145  }
146  break;
147 
148  case DVDNAV_NAV_PACKET:
149  // Don't need to do anything here. There was a timecode discontinuity
150  // and the ringbuffer returned to make sure that any packets still in
151  // ffmpeg's buffers were flushed.
152  break;
153 
154  default:
155  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Unexpected DVD event - %1")
156  .arg(lastEvent));
157  break;
158  }
159 
161  }
162 
163  avcodeclock->lock();
164  result = av_read_frame(ctx, pkt);
165  avcodeclock->unlock();
166 
167  // Make sure we yield. Otherwise other threads may not
168  // get chance to take the lock. Shouldn't be necessary
169  // but calling up the OSD menu in a still frame without
170  // this still causes a deadlock.
171  usleep(0);
172  }while (m_ringBuffer->DVD()->IsReadingBlocked());
173 
174  if (result >= 0)
175  {
176  pkt->dts = m_ringBuffer->DVD()->AdjustTimestamp(pkt->dts);
177  pkt->pts = m_ringBuffer->DVD()->AdjustTimestamp(pkt->pts);
178 
179  if (m_returnContext)
180  {
181  // We've jumped in a slideshow and have had to jump again
182  // to find the right video packet to show so only allow
183  // the packets through that let us find it.
184  gotPacket = false;
185 
186  AVStream *curstream = m_ic->streams[pkt->stream_index];
187 
188  if ((curstream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) ||
189  (curstream->codecpar->codec_id == AV_CODEC_ID_DVD_NAV))
190  {
191  // Allow video or NAV packets through
192  gotPacket = true;
193  }
194  }
195  }
196  }while(!gotPacket);
197  }
198 
199  return result;
200 }
201 
203 {
204  if (pts != AV_NOPTS_VALUE)
205  {
206  // Remove any contexts we should have
207  // already processed.(but have somehow jumped past)
208  while (!m_contextList.empty() &&
209  pts >= m_contextList.first()->GetEndPTS())
210  {
212  m_curContext = m_contextList.takeFirst();
213 
214  LOG(VB_GENERAL, LOG_ERR, LOC +
215  QString("DVD context missed! lba: %1, curpts: %2, nav end pts: %3")
216  .arg(m_curContext->GetLBA())
217  .arg(pts)
218  .arg(m_curContext->GetEndPTS()));
219  }
220 
221  // See whether we can take the next context from the list
222  if (!m_contextList.empty() &&
223  pts >= m_contextList.first()->GetStartPTS())
224  {
226  m_curContext = m_contextList.takeFirst();
227 
230 
231  if (m_curContext->GetNumFramesPresent() == 0)
232  {
233  if (m_lastVideoPkt)
234  {
235  // No video frames present, so we need to generate
236  // them based on the last 'sequence end' video packet.
238  }
239  else
240  {
241  // There are no video frames in this VOBU and
242  // we don't have one stored. We've probably
243  // jumped into the middle of a cell.
244  // Jump back to the first VOBU that contains
245  // video so we can get the video frame we need
246  // before jumping back again.
247  m_framesReq = 0;
248  uint32_t lastVideoSector = m_curContext->GetLBAPrevVideoFrame();
249 
250  if (lastVideoSector != INVALID_LBA)
251  {
252  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString( "Missing video. Jumping to sector %1")
253  .arg(lastVideoSector));
254 
255  m_ringBuffer->DVD()->SectorSeek(lastVideoSector);
256 
258  m_curContext = nullptr;
259  }
260  else
261  {
262  LOG(VB_GENERAL, LOG_ERR, LOC +
263  QString("Missing video frame and no previous frame available! lba: %1")
264  .arg(m_curContext->GetLBA()));
265  }
266  }
267  }
268  else
269  {
270  // Normal VOBU with at least one video frame so we don't need to generate frames.
271  m_framesReq = 0;
273  }
274  }
275  }
276 }
277 
278 
279 bool AvFormatDecoderDVD::ProcessVideoPacket(AVStream *stream, AVPacket *pkt, bool &Retry)
280 {
281  int64_t pts = pkt->pts;
282 
283  if (pts == AV_NOPTS_VALUE)
284  pts = pkt->dts;
285 
286  CheckContext(pts);
287 
288  bool ret = AvFormatDecoder::ProcessVideoPacket(stream, pkt, Retry);
289  if (Retry)
290  return ret;
291 
292  if( ret &&
293  m_curContext &&
294  pts != AV_NOPTS_VALUE &&
295  pts + pkt->duration == m_curContext->GetSeqEndPTS())
296  {
297  // If this video frame is the last in the sequence,
298  // make a copy of it so we can 'generate' more
299  // to fill in the gaps (e.g. when a single frame
300  // should be displayed with audio)
301  if (!m_lastVideoPkt)
302  {
303  m_lastVideoPkt = new AVPacket;
304  memset(m_lastVideoPkt, 0, sizeof(AVPacket));
305  }
306  else
307  {
308  av_packet_unref(m_lastVideoPkt);
309  }
310 
311  av_init_packet(m_lastVideoPkt);
312  av_packet_ref(m_lastVideoPkt, pkt);
314 
315  if (m_returnContext)
316  {
317  // After seeking in a slideshow, we needed to find
318  // the previous video frame to display.
319  // We've found it now, so we need to jump back to
320  // where we originally wanted to be.
321  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString( "Found video packet, jumping back to sector %1")
322  .arg(m_returnContext->GetLBA()));
323 
326  }
327  else
328  {
329  if (m_lastVideoPkt->pts != AV_NOPTS_VALUE)
330  m_lastVideoPkt->pts += pkt->duration;
331 
332  if (m_lastVideoPkt->dts != AV_NOPTS_VALUE)
333  m_lastVideoPkt->dts += pkt->duration;
334 
336 
337  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString( "SeqEnd @ %1 - require %2 frame(s)")
338  .arg(pkt->pts)
339  .arg(m_framesReq));
340  }
341  }
342 
343  return ret;
344 }
345 
346 bool AvFormatDecoderDVD::ProcessVideoFrame(AVStream *stream, AVFrame *mpa_pic)
347 {
348  bool ret = true;
349 
350  if (m_returnContext == nullptr)
351  {
352  // Only process video frames if we're not searching for
353  // the previous video frame after seeking in a slideshow.
354  ret = AvFormatDecoder::ProcessVideoFrame(stream, mpa_pic);
355  }
356 
357  return ret;
358 }
359 
360 bool AvFormatDecoderDVD::ProcessDataPacket(AVStream *curstream, AVPacket *pkt,
361  DecodeType decodetype)
362 {
363  bool ret = true;
364 
365  if (curstream->codecpar->codec_id == AV_CODEC_ID_DVD_NAV)
366  {
367  MythDVDContext* context = m_ringBuffer->DVD()->GetDVDContext();
368 
369  if (context)
370  m_contextList.append(context);
371 
372  if ((m_curContext == nullptr) && (!m_contextList.empty()))
373  {
374  // If we don't have a current context, use
375  // the first in the list
376  CheckContext(m_contextList.first()->GetStartPTS());
377 
379  {
380  // If there was no current context but there was
381  // a video packet, we've almost certainly been
382  // seeking so set the timestamps of the video
383  // packet to the new context to ensure we don't
384  // get sync errors.
386  m_lastVideoPkt->dts = m_lastVideoPkt->pts;
387  }
388  }
389  else
390  if (m_lastVideoPkt)
391  {
392  // If we've been generating frames, see whether this
393  // new context should be used already (handles
394  // situations where a VOBU consists of only a NAV
395  // packet and nothing else)
397  }
398  }
399  else
400  {
401  ret = AvFormatDecoder::ProcessDataPacket(curstream, pkt, decodetype);
402  }
403 
404  return ret;
405 }
406 
408 {
409  if (!m_ringBuffer)
410  return;
411  if (!m_ringBuffer->IsDVD())
412  return;
413 
414  if (m_tracks[kTrackTypeAudio].size() > 1)
415  {
416  stable_sort(m_tracks[kTrackTypeAudio].begin(),
417  m_tracks[kTrackTypeAudio].end());
418 
419  int trackNo = -1;
420  int dvdTrack = m_ringBuffer->DVD()->GetTrack(kTrackTypeAudio);
421 
422  for (uint i = 0; i < GetTrackCount(kTrackTypeAudio); i++)
423  {
424  LOG(VB_PLAYBACK, LOG_INFO, LOC +
425  QString("DVD Audio Track Map Stream id #%1, av_stream_idx %2, MPEG stream 0x%3, lang %4")
426  .arg(m_tracks[kTrackTypeAudio][i].m_stream_id)
427  .arg(m_tracks[kTrackTypeAudio][i].m_av_stream_index)
428  .arg(m_ic->streams[m_tracks[kTrackTypeAudio][i].m_av_stream_index]->id,0,16)
429  .arg(iso639_key_toName(m_tracks[kTrackTypeAudio][i].m_language)));
430 
431  // Find the audio track in our list that maps to the
432  // selected track in the ringbuffer (the ringbuffer's
433  // list should be in the same order but can have gaps,
434  // so we look for the track with the same index)
435  if (m_tracks[kTrackTypeAudio][i].m_stream_id == dvdTrack)
436  trackNo = i;
437  }
438 
439  if (trackNo < 0 && GetTrackCount(kTrackTypeAudio) > 0)
440  {
441  // Take the first track
442  trackNo = 0;
443  }
444 
445  if (trackNo >= 0)
446  SetTrack(kTrackTypeAudio, trackNo);
447  }
448 
449  if (!m_tracks[kTrackTypeSubtitle].empty())
450  {
451  map<int,uint> lang_sub_cnt;
452  map<int,int> stream2idx;
453 
454  // First, create a map containing stream id -> track index
455  // of the subtitle streams that have been found so far.
456  for (uint n = 0; n < GetTrackCount(kTrackTypeSubtitle); n++)
457  {
458  int stream_id = m_tracks[kTrackTypeSubtitle][n].m_stream_id & 0x1f;
459 
460  stream2idx[stream_id] = n;
461  }
462 
463  // Get all subtitle tracks from the DVD and filter out any that
464  // are not mapped in the current program chain.
465  sinfo_vec_t filteredTracks;
466 
467  if (!m_ringBuffer->DVD()->IsInMenu())
468  {
469  for (uint i = 0; i < 32; ++i)
470  {
471  int streamid = m_ringBuffer->DVD()->GetSubtitleTrackNum(i);
472  if (streamid >= 0)
473  {
474  // This stream is mapped in the current program chain
475  int lang = m_ringBuffer->DVD()->GetSubtitleLanguage(i);
476  int lang_indx = lang_sub_cnt[lang]++;
477  int trackNo = -1;
478 
479  if (stream2idx.count(streamid) != 0)
480  trackNo = stream2idx[streamid];
481 
482  if (trackNo == -1)
483  {
484  // Create a dummy track if the physical stream has not
485  // yet been seen.
486  filteredTracks.push_back(StreamInfo(-1, lang, lang_indx,
487  streamid, 0, 0, false, false, false));
488  }
489  else
490  {
491  // Otherwise use the real data
492  filteredTracks.push_back(m_tracks[kTrackTypeSubtitle][trackNo]);
493  filteredTracks.back().m_stream_id &= 0x1f;
494  filteredTracks.back().m_language = lang;
495  filteredTracks.back().m_language_index = lang_indx;
496  }
497  }
498  }
499  }
500  m_tracks[kTrackTypeSubtitle] = filteredTracks;
501 
502  stable_sort(m_tracks[kTrackTypeSubtitle].begin(),
504 
505  int trackNo = -1;
506  int selectedStream = m_ringBuffer->DVD()->GetTrack(kTrackTypeSubtitle);
507 
508  // Now iterate over the sorted list and try to find the index of the
509  // currently selected track.
510  for (uint idx = 0; idx < GetTrackCount(kTrackTypeSubtitle); idx++)
511  {
512  const StreamInfo& stream = m_tracks[kTrackTypeSubtitle][idx];
513  int avidx = stream.m_av_stream_index;
514  QString mpegstream;
515 
516  if (avidx >= 0)
517  mpegstream = QString( "0x%1").arg(m_ic->streams[avidx]->id,0,16);
518  else
519  mpegstream = "n/a";
520 
521  LOG(VB_PLAYBACK, LOG_INFO, LOC +
522  QString("DVD Subtitle Track Map Stream id #%1, av_stream_idx %2, MPEG #%3, lang %4")
523  .arg(stream.m_stream_id)
524  .arg(stream.m_av_stream_index)
525  .arg(mpegstream)
526  .arg(iso639_key_toName(stream. m_language)));
527 
528  if ((selectedStream != -1) && (stream.m_stream_id == selectedStream))
529  trackNo = (int)idx;
530  }
531 
532  uint captionmode = m_parent->GetCaptionMode();
533  int trackcount = (int)GetTrackCount(kTrackTypeSubtitle);
534 
535  if (captionmode == kDisplayAVSubtitle &&
536  (trackNo < 0 || trackNo >= trackcount))
537  {
538  m_parent->EnableSubtitles(false);
539  }
540  else if (trackNo >= 0 && trackNo < trackcount)
541  {
542  SetTrack(kTrackTypeSubtitle, trackNo);
543  m_parent->EnableSubtitles(true);
544  }
545  }
546 }
547 
548 bool AvFormatDecoderDVD::DoRewindSeek(long long desiredFrame)
549 {
550  if (!m_ringBuffer->IsDVD())
551  return false;
552 
553  m_ringBuffer->Seek(DVDFindPosition(desiredFrame), SEEK_SET);
554  m_framesPlayed = m_framesRead = m_lastKey = desiredFrame + 1;
555  m_frameCounter += 100;
556  return true;
557 }
558 
559 void AvFormatDecoderDVD::DoFastForwardSeek(long long desiredFrame, bool &needflush)
560 {
561  if (!m_ringBuffer->IsDVD())
562  return;
563 
564  m_ringBuffer->Seek(DVDFindPosition(desiredFrame),SEEK_SET);
565  needflush = true;
566  m_framesPlayed = m_framesRead = m_lastKey = desiredFrame + 1;
567  m_frameCounter += 100;
568 }
569 
571 {
572  if (!m_ringBuffer->IsDVD())
573  return;
574 
575  if (m_streamsChanged)
576  {
577  // This was originally in HandleDVDStreamChange
578  QMutexLocker locker(avcodeclock);
579  ScanStreams(true);
580  avcodeclock->unlock();
581  m_streamsChanged=false;
582  }
583 
584  // Update the title length
585  if (m_parent->AtNormalSpeed() &&
587  {
588  ResetPosMap();
589  SyncPositionMap();
591  }
592 
593  // rescan the non-video streams as necessary
595  ScanStreams(true);
596 
597  // Always use the first video stream
598  // (must come after ScanStreams above)
599  for (uint i = 0; i < m_ic->nb_streams; i++)
600  {
601  AVStream *st = m_ic->streams[i];
602  if (st && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
603  {
605  break;
606  }
607  }
608 }
609 
610 int AvFormatDecoderDVD::GetAudioLanguage(uint audio_index, uint stream_index)
611 {
612  (void)audio_index;
613  if ((m_ic->streams[stream_index]->id >= 0) &&
615  {
616  return m_ringBuffer->DVD()->GetAudioLanguage(
617  m_ringBuffer->DVD()->GetAudioTrackNum(m_ic->streams[stream_index]->id));
618  }
619  return iso639_str3_to_key("und");
620 }
621 
622 long long AvFormatDecoderDVD::DVDFindPosition(long long desiredFrame)
623 {
624  if (!m_ringBuffer->IsDVD())
625  return 0;
626 
627  int ffrewSkip = 1;
628  int current_speed = 0;
629  if (m_parent)
630  {
631  ffrewSkip = m_parent->GetFFRewSkip();
632  current_speed = (int)m_parent->GetNextPlaySpeed();
633  }
634 
635  if (ffrewSkip == 1 || ffrewSkip == 0)
636  {
637  int diffTime = (int)ceil((desiredFrame - m_framesPlayed) / m_fps);
638  long long desiredTimePos = m_ringBuffer->DVD()->GetCurrentTime() +
639  diffTime;
640  if (diffTime <= 0)
641  desiredTimePos--;
642  else
643  desiredTimePos++;
644 
645  if (desiredTimePos < 0)
646  desiredTimePos = 0;
647  return (desiredTimePos * 90000LL);
648  }
649  return current_speed;
650 }
651 
653 {
654  int type = 0;
655 
656  if (m_ringBuffer && m_ringBuffer->DVD())
657  {
658  int logical_idx = m_ringBuffer->DVD()->GetAudioTrackNum(m_ic->streams[stream_index]->id);
659  type = m_ringBuffer->DVD()->GetAudioTrackType(logical_idx);
660  }
661 
662  if (type > 0 && type < 5) // These are the only types defined in unofficial documentation
663  {
665  switch (type)
666  {
667  case 1:
668  ret = kAudioTypeNormal;
669  break;
670  case 2:
672  break;
673  case 3: case 4:
674  ret = kAudioTypeCommentary;
675  break;
676  }
677  return ret;
678  }
679 
680  // If the DVD metadata doesn't include the info then we might as well fall through, maybe we'll get lucky
681  return AvFormatDecoder::GetAudioTrackType(stream_index);
682 }
#define INVALID_LBA
virtual bool ProcessDataPacket(AVStream *curstream, AVPacket *pkt, DecodeType decodetype)
bool SectorSeek(uint64_t sector)
ISO 639-1 and ISO 639-2 support functions.
long long DVDFindPosition(long long desiredFrame)
MythDVDContext * m_curContext
Encapsulates playback context at any given moment.
Definition: dvdringbuffer.h:32
const DVDRingBuffer * DVD(void) const
void DiscardVideoFrames(bool KeyFrame, bool Flushed)
Places frames in the available frames queue.
Definition: mythplayer.cpp:944
uint GetAudioLanguage(int idx)
get the audio language from the dvd
unsigned long long m_frameCounter
Definition: decoderbase.h:308
int GetSubtitleTrackNum(uint stream_id)
get the logical subtitle track/stream number from the dvd
bool PGCLengthChanged(void)
check if pgc length has changed
int GetAudioTrackType(uint idx)
AudioTrackType
Definition: decoderbase.h:55
QString iso639_key_toName(int iso639_2)
Converts a canonical key to language name in English.
Definition: iso639.cpp:110
uint GetSubtitleLanguage(int id)
get the subtitle language from the dvd
struct AVFrame AVFrame
virtual bool ProcessVideoPacket(AVStream *stream, AVPacket *pkt, bool &Retry)
bool ProcessVideoPacket(AVStream *stream, AVPacket *pkt, bool &Retry) override
static int iso639_str3_to_key(const unsigned char *iso639_2)
Definition: iso639.h:63
void CheckContext(int64_t pts)
uint32_t GetLBAPrevVideoFrame() const
Returns the logical block address of the previous VOBU containing video.
bool GetFrame(DecodeType Type, bool &Retry) override
Demux, preprocess and possibly decode a frame of video/audio.
AudioPlayer * m_audio
Definition: decoderbase.h:295
bool GetFrame(DecodeType Type, bool &Retry) override
Demux, preprocess and possibly decode a frame of video/audio.
bool ProcessVideoFrame(AVStream *stream, AVFrame *mpa_pic) override
void StreamChangeCheck(void) override
void SetFramesPlayed(uint64_t played)
Definition: mythplayer.cpp:860
static void ReleaseContext(MythDVDContext *&context)
uint GetCaptionMode(void) const
Definition: mythplayer.h:323
bool IsDVD(void) const
bool IsReadingBlocked(void)
int GetTrack(uint type)
get the track the dvd should be playing.
QList< MythDVDContext * > m_contextList
void PostProcessTracks(void) override
void Reset(bool reset_video_data, bool seek_reset, bool reset_file) override
int ReadPacket(AVFormatContext *ctx, AVPacket *pkt, bool &storePacket) override
AVFormatContext * m_ic
int GetAudioLanguage(uint audio_index, uint stream_index) override
sinfo_vec_t m_tracks[kTrackTypeCount]
Definition: decoderbase.h:355
MythDVDContext * m_returnContext
virtual void ResetPosMap(void)
uint32_t GetLBA() const
Definition: dvdringbuffer.h:43
int64_t GetStartPTS() const
Definition: dvdringbuffer.h:40
int SetTrack(uint type, int trackNo) override
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
bool DoRewindSeek(long long desiredFrame) override
int m_stream_id
Definition: decoderbase.h:99
long long m_framesPlayed
Definition: decoderbase.h:306
AudioTrackType GetAudioTrackType(uint stream_index) override
unsigned int uint
Definition: compat.h:140
#define LOC
void UpdateFramesPlayed(void) override
int GetFFRewSkip(void) const
Definition: mythplayer.h:220
int GetNumFrames() const
Returns the duration of this VOBU in frames.
virtual uint GetTrackCount(uint type) const
Definition: decoderbase.h:237
virtual bool SyncPositionMap(void)
Updates the position map used for skipping frames.
int ScanStreams(bool novideo)
MythDVDContext * GetDVDContext(void)
bool AtNormalSpeed(void) const
Definition: mythplayer.h:253
long long m_lastKey
Definition: decoderbase.h:310
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
RingBuffer * m_ringBuffer
Definition: decoderbase.h:296
void Reset(bool reset_video_data, bool seek_reset, bool reset_file) override
QMutex * avcodeclock
This global variable is used to makes certain calls to avlib threadsafe.
DecodeType
Definition: decoderbase.h:47
int32_t GetLastEvent(void) const
void EnableSubtitles(bool enable)
StreamInfo m_selectedTrack[(uint) kTrackTypeCount]
Definition: decoderbase.h:357
virtual bool ProcessVideoFrame(AVStream *Stream, AVFrame *AvFrame)
int64_t GetEndPTS() const
Definition: dvdringbuffer.h:41
int GetNumFramesPresent() const
Returns the number of video frames present in this VOBU.
int64_t GetSeqEndPTS() const
Definition: dvdringbuffer.h:42
QList< AVPacket * > m_storedPackets
bool ProcessDataPacket(AVStream *curstream, AVPacket *pkt, DecodeType decodetype) override
bool IsInMenu(void) const override
vector< StreamInfo > sinfo_vec_t
Definition: decoderbase.h:111
int m_av_stream_index
Definition: decoderbase.h:94
float GetNextPlaySpeed(void) const
Definition: mythplayer.h:225
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 GetAudioTrackNum(uint stream_id)
get the logical track index (into PGC_AST_CTL) of the element that maps the given physical stream id.
int64_t GetCurrentTime(void)
void DoFastForwardSeek(long long desiredFrame, bool &needflush) override
Seeks to the keyframe just before the desiredFrame if exact seeks is enabled, or the frame just after...
long long m_framesRead
Definition: decoderbase.h:307
void Reset(void)
Definition: audioplayer.cpp:83
void UnblockReading(void)
uint32_t AdjustTimestamp(uint32_t timestamp)
bool AudioStreamsChanged(void) const
MythPlayer * m_parent
Definition: decoderbase.h:293
virtual AudioTrackType GetAudioTrackType(uint stream_index)