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