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 (!ringBuffer->IsDVD())
57  return;
58 
59  long long currentpos = (long long)(ringBuffer->DVD()->GetCurrentTime() * m_fps);
60  m_framesPlayed = m_framesRead = currentpos ;
61  m_parent->SetFramesPlayed(currentpos + 1);
62 }
63 
65 {
66  // Always try to decode audio and video for DVDs
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;
98 
99  do
100  {
101  gotPacket = true;
102 
103  do
104  {
105  if (ringBuffer->DVD()->IsReadingBlocked())
106  {
107  int32_t lastEvent = 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();
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 (ringBuffer->DVD()->IsReadingBlocked());
173 
174  if (result >= 0)
175  {
176  pkt->dts = ringBuffer->DVD()->AdjustTimestamp(pkt->dts);
177  pkt->pts = 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  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)
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);
289 
290  if( ret &&
291  m_curContext &&
292  pts != AV_NOPTS_VALUE &&
293  pts + pkt->duration == m_curContext->GetSeqEndPTS())
294  {
295  // If this video frame is the last in the sequence,
296  // make a copy of it so we can 'generate' more
297  // to fill in the gaps (e.g. when a single frame
298  // should be displayed with audio)
299  if (!m_lastVideoPkt)
300  {
301  m_lastVideoPkt = new AVPacket;
302  memset(m_lastVideoPkt, 0, sizeof(AVPacket));
303  }
304  else
305  {
306  av_packet_unref(m_lastVideoPkt);
307  }
308 
309  av_init_packet(m_lastVideoPkt);
310  av_packet_ref(m_lastVideoPkt, pkt);
312 
313  if (m_returnContext)
314  {
315  // After seeking in a slideshow, we needed to find
316  // the previous video frame to display.
317  // We've found it now, so we need to jump back to
318  // where we originally wanted to be.
319  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString( "Found video packet, jumping back to sector %1")
320  .arg(m_returnContext->GetLBA()));
321 
324  }
325  else
326  {
327  if (m_lastVideoPkt->pts != AV_NOPTS_VALUE)
328  m_lastVideoPkt->pts += pkt->duration;
329 
330  if (m_lastVideoPkt->dts != AV_NOPTS_VALUE)
331  m_lastVideoPkt->dts += pkt->duration;
332 
334 
335  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString( "SeqEnd @ %1 - require %2 frame(s)")
336  .arg(pkt->pts)
337  .arg(m_framesReq));
338  }
339  }
340 
341  return ret;
342 }
343 
344 bool AvFormatDecoderDVD::ProcessVideoFrame(AVStream *stream, AVFrame *mpa_pic)
345 {
346  bool ret = true;
347 
348  if (m_returnContext == nullptr)
349  {
350  // Only process video frames if we're not searching for
351  // the previous video frame after seeking in a slideshow.
352  ret = AvFormatDecoder::ProcessVideoFrame(stream, mpa_pic);
353  }
354 
355  return ret;
356 }
357 
358 bool AvFormatDecoderDVD::ProcessDataPacket(AVStream *curstream, AVPacket *pkt,
359  DecodeType decodetype)
360 {
361  bool ret = true;
362 
363  if (curstream->codecpar->codec_id == AV_CODEC_ID_DVD_NAV)
364  {
365  MythDVDContext* context = ringBuffer->DVD()->GetDVDContext();
366 
367  if (context)
368  m_contextList.append(context);
369 
370  if ((m_curContext == nullptr) && (!m_contextList.empty()))
371  {
372  // If we don't have a current context, use
373  // the first in the list
374  CheckContext(m_contextList.first()->GetStartPTS());
375 
377  {
378  // If there was no current context but there was
379  // a video packet, we've almost certainly been
380  // seeking so set the timestamps of the video
381  // packet to the new context to ensure we don't
382  // get sync errors.
384  m_lastVideoPkt->dts = m_lastVideoPkt->pts;
385  }
386  }
387  else
388  if (m_lastVideoPkt)
389  {
390  // If we've been generating frames, see whether this
391  // new context should be used already (handles
392  // situations where a VOBU consists of only a NAV
393  // packet and nothing else)
395  }
396  }
397  else
398  {
399  ret = AvFormatDecoder::ProcessDataPacket(curstream, pkt, decodetype);
400  }
401 
402  return ret;
403 }
404 
406 {
407  if (!ringBuffer)
408  return;
409  if (!ringBuffer->IsDVD())
410  return;
411 
412  if (m_tracks[kTrackTypeAudio].size() > 1)
413  {
414  stable_sort(m_tracks[kTrackTypeAudio].begin(),
415  m_tracks[kTrackTypeAudio].end());
416 
417  int trackNo = -1;
418  int dvdTrack = ringBuffer->DVD()->GetTrack(kTrackTypeAudio);
419 
420  for (uint i = 0; i < GetTrackCount(kTrackTypeAudio); i++)
421  {
422  LOG(VB_PLAYBACK, LOG_INFO, LOC +
423  QString("DVD Audio Track Map Stream id #%1, av_stream_idx %2, MPEG stream 0x%3, lang %4")
424  .arg(m_tracks[kTrackTypeAudio][i].m_stream_id)
425  .arg(m_tracks[kTrackTypeAudio][i].m_av_stream_index)
426  .arg(m_ic->streams[m_tracks[kTrackTypeAudio][i].m_av_stream_index]->id,0,16)
427  .arg(iso639_key_toName(m_tracks[kTrackTypeAudio][i].m_language)));
428 
429  // Find the audio track in our list that maps to the
430  // selected track in the ringbuffer (the ringbuffer's
431  // list should be in the same order but can have gaps,
432  // so we look for the track with the same index)
433  if (m_tracks[kTrackTypeAudio][i].m_stream_id == dvdTrack)
434  trackNo = i;
435  }
436 
437  if (trackNo < 0 && GetTrackCount(kTrackTypeAudio) > 0)
438  {
439  // Take the first track
440  trackNo = 0;
441  }
442 
443  if (trackNo >= 0)
444  SetTrack(kTrackTypeAudio, trackNo);
445  }
446 
447  if (!m_tracks[kTrackTypeSubtitle].empty())
448  {
449  map<int,uint> lang_sub_cnt;
450  map<int,int> stream2idx;
451 
452  // First, create a map containing stream id -> track index
453  // of the subtitle streams that have been found so far.
454  for (uint n = 0; n < GetTrackCount(kTrackTypeSubtitle); n++)
455  {
456  int stream_id = m_tracks[kTrackTypeSubtitle][n].m_stream_id & 0x1f;
457 
458  stream2idx[stream_id] = n;
459  }
460 
461  // Get all subtitle tracks from the DVD and filter out any that
462  // are not mapped in the current program chain.
463  sinfo_vec_t filteredTracks;
464 
465  if (!ringBuffer->DVD()->IsInMenu())
466  {
467  for (uint i = 0; i < 32; ++i)
468  {
469  int streamid = ringBuffer->DVD()->GetSubtitleTrackNum(i);
470  if (streamid >= 0)
471  {
472  // This stream is mapped in the current program chain
473  int lang = ringBuffer->DVD()->GetSubtitleLanguage(i);
474  int lang_indx = lang_sub_cnt[lang]++;
475  int trackNo = -1;
476 
477  if (stream2idx.count(streamid) != 0)
478  trackNo = stream2idx[streamid];
479 
480  if (trackNo == -1)
481  {
482  // Create a dummy track if the physical stream has not
483  // yet been seen.
484  filteredTracks.push_back(StreamInfo(-1, lang, lang_indx,
485  streamid, 0, 0, false, false, false));
486  }
487  else
488  {
489  // Otherwise use the real data
490  filteredTracks.push_back(m_tracks[kTrackTypeSubtitle][trackNo]);
491  filteredTracks.back().m_stream_id &= 0x1f;
492  filteredTracks.back().m_language = lang;
493  filteredTracks.back().m_language_index = lang_indx;
494  }
495  }
496  }
497  }
498  m_tracks[kTrackTypeSubtitle] = filteredTracks;
499 
500  stable_sort(m_tracks[kTrackTypeSubtitle].begin(),
502 
503  int trackNo = -1;
504  int selectedStream = ringBuffer->DVD()->GetTrack(kTrackTypeSubtitle);
505 
506  // Now iterate over the sorted list and try to find the index of the
507  // currently selected track.
508  for (uint idx = 0; idx < GetTrackCount(kTrackTypeSubtitle); idx++)
509  {
510  const StreamInfo& stream = m_tracks[kTrackTypeSubtitle][idx];
511  int avidx = stream.m_av_stream_index;
512  QString mpegstream;
513 
514  if (avidx >= 0)
515  mpegstream = QString( "0x%1").arg(m_ic->streams[avidx]->id,0,16);
516  else
517  mpegstream = "n/a";
518 
519  LOG(VB_PLAYBACK, LOG_INFO, LOC +
520  QString("DVD Subtitle Track Map Stream id #%1, av_stream_idx %2, MPEG #%3, lang %4")
521  .arg(stream.m_stream_id)
522  .arg(stream.m_av_stream_index)
523  .arg(mpegstream)
524  .arg(iso639_key_toName(stream. m_language)));
525 
526  if ((selectedStream != -1) && (stream.m_stream_id == selectedStream))
527  trackNo = (int)idx;
528  }
529 
530  uint captionmode = m_parent->GetCaptionMode();
531  int trackcount = (int)GetTrackCount(kTrackTypeSubtitle);
532 
533  if (captionmode == kDisplayAVSubtitle &&
534  (trackNo < 0 || trackNo >= trackcount))
535  {
536  m_parent->EnableSubtitles(false);
537  }
538  else if (trackNo >= 0 && trackNo < trackcount)
539  {
540  SetTrack(kTrackTypeSubtitle, trackNo);
541  m_parent->EnableSubtitles(true);
542  }
543  }
544 }
545 
546 bool AvFormatDecoderDVD::DoRewindSeek(long long desiredFrame)
547 {
548  if (!ringBuffer->IsDVD())
549  return false;
550 
551  ringBuffer->Seek(DVDFindPosition(desiredFrame), SEEK_SET);
552  m_framesPlayed = m_framesRead = m_lastKey = desiredFrame + 1;
553  return true;
554 }
555 
556 void AvFormatDecoderDVD::DoFastForwardSeek(long long desiredFrame, bool &needflush)
557 {
558  if (!ringBuffer->IsDVD())
559  return;
560 
561  ringBuffer->Seek(DVDFindPosition(desiredFrame),SEEK_SET);
562  needflush = true;
563  m_framesPlayed = m_framesRead = m_lastKey = desiredFrame + 1;
564 }
565 
567 {
568  if (!ringBuffer->IsDVD())
569  return;
570 
571  if (m_streams_changed)
572  {
573  // This was originally in HandleDVDStreamChange
574  QMutexLocker locker(avcodeclock);
575  ScanStreams(true);
576  avcodeclock->unlock();
577  m_streams_changed=false;
578  }
579 
580  // Update the title length
581  if (m_parent->AtNormalSpeed() &&
583  {
584  ResetPosMap();
585  SyncPositionMap();
587  }
588 
589  // rescan the non-video streams as necessary
591  ScanStreams(true);
592 
593  // Always use the first video stream
594  // (must come after ScanStreams above)
595  for (uint i = 0; i < m_ic->nb_streams; i++)
596  {
597  AVStream *st = m_ic->streams[i];
598  if (st && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
599  {
601  break;
602  }
603  }
604 }
605 
606 int AvFormatDecoderDVD::GetAudioLanguage(uint audio_index, uint stream_index)
607 {
608  (void)audio_index;
609  if ((m_ic->streams[stream_index]->id >= 0) &&
611  {
612  return ringBuffer->DVD()->GetAudioLanguage(
613  ringBuffer->DVD()->GetAudioTrackNum(m_ic->streams[stream_index]->id));
614  }
615  return iso639_str3_to_key("und");
616 }
617 
618 long long AvFormatDecoderDVD::DVDFindPosition(long long desiredFrame)
619 {
620  if (!ringBuffer->IsDVD())
621  return 0;
622 
623  int ffrewSkip = 1;
624  int current_speed = 0;
625  if (m_parent)
626  {
627  ffrewSkip = m_parent->GetFFRewSkip();
628  current_speed = (int)m_parent->GetNextPlaySpeed();
629  }
630 
631  if (ffrewSkip == 1 || ffrewSkip == 0)
632  {
633  int diffTime = (int)ceil((desiredFrame - m_framesPlayed) / m_fps);
634  long long desiredTimePos = ringBuffer->DVD()->GetCurrentTime() +
635  diffTime;
636  if (diffTime <= 0)
637  desiredTimePos--;
638  else
639  desiredTimePos++;
640 
641  if (desiredTimePos < 0)
642  desiredTimePos = 0;
643  return (desiredTimePos * 90000LL);
644  }
645  return current_speed;
646 }
647 
649 {
650  int type = 0;
651 
652  if (ringBuffer && ringBuffer->DVD())
653  {
654  int logical_idx = ringBuffer->DVD()->GetAudioTrackNum(m_ic->streams[stream_index]->id);
655  type = ringBuffer->DVD()->GetAudioTrackType(logical_idx);
656  }
657 
658  if (type > 0 && type < 5) // These are the only types defined in unofficial documentation
659  {
661  switch (type)
662  {
663  case 1:
664  ret = kAudioTypeNormal;
665  break;
666  case 2:
668  break;
669  case 3: case 4:
670  ret = kAudioTypeCommentary;
671  break;
672  }
673  return ret;
674  }
675 
676  // If the DVD metadata doesn't include the info then we might as well fall through, maybe we'll get lucky
677  return AvFormatDecoder::GetAudioTrackType(stream_index);
678 }
#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
uint GetAudioLanguage(int idx)
get the audio language from the dvd
int GetSubtitleTrackNum(uint stream_id)
get the logical subtitle track/stream number from the dvd
struct AVFrame AVFrame
bool ProcessVideoPacket(AVStream *stream, AVPacket *pkt) override
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:111
uint GetSubtitleLanguage(int id)
get the subtitle language from the dvd
virtual bool ProcessVideoPacket(AVStream *stream, AVPacket *pkt)
unsigned int uint
Definition: compat.h:140
void DiscardVideoFrames(bool next_frame_keyframe)
Places frames in the available frames queue.
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.
AudioPlayer * m_audio
Definition: decoderbase.h:297
bool ProcessVideoFrame(AVStream *stream, AVFrame *mpa_pic) override
void StreamChangeCheck(void) override
void SetFramesPlayed(uint64_t played)
void ReleaseContext(MythDVDContext *&context)
bool GetFrame(DecodeType decodetype) override
Demux, preprocess and possibly decode a frame of video/audio.
uint GetCaptionMode(void) const
Definition: mythplayer.h:294
RingBuffer * ringBuffer
Definition: decoderbase.h:298
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:356
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
virtual bool ProcessVideoFrame(AVStream *stream, AVFrame *mpa_pic)
long long m_framesPlayed
Definition: decoderbase.h:308
AudioTrackType GetAudioTrackType(uint stream_index) override
#define LOC
void UpdateFramesPlayed(void) override
int GetFFRewSkip(void) const
Definition: mythplayer.h:187
enum DecodeTypes DecodeType
int GetNumFrames() const
Returns the duration of this VOBU in frames.
virtual uint GetTrackCount(uint type) const
Definition: decoderbase.h:239
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:224
long long m_lastKey
Definition: decoderbase.h:311
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
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.
vector< StreamInfo > sinfo_vec_t
Definition: decoderbase.h:111
int32_t GetLastEvent(void) const
void EnableSubtitles(bool enable)
StreamInfo m_selectedTrack[(uint) kTrackTypeCount]
Definition: decoderbase.h:358
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
int m_av_stream_index
Definition: decoderbase.h:94
float GetNextPlaySpeed(void) const
Definition: mythplayer.h:192
bool GetFrame(DecodeType) override
Demux, preprocess and possibly decode a frame of video/audio.
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:309
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:295
virtual AudioTrackType GetAudioTrackType(uint stream_index)