diff options
author | Klaus Schmidinger <vdr@tvdr.de> | 2016-12-22 11:33:12 +0100 |
---|---|---|
committer | Klaus Schmidinger <vdr@tvdr.de> | 2016-12-22 11:33:12 +0100 |
commit | be4cdcf17027e2f6f5482fb13d273693145d11a1 (patch) | |
tree | aa3877153e4640746b6833dae1a0891928907065 /dvbplayer.c | |
parent | fd85701a84c976318afbb69e13d96c1ec44112fc (diff) | |
download | vdr-be4cdcf17027e2f6f5482fb13d273693145d11a1.tar.gz vdr-be4cdcf17027e2f6f5482fb13d273693145d11a1.tar.bz2 |
Improved handling frame numbers to have a smoother progress display during replay of recordings with B-frames
Diffstat (limited to 'dvbplayer.c')
-rw-r--r-- | dvbplayer.c | 66 |
1 files changed, 60 insertions, 6 deletions
diff --git a/dvbplayer.c b/dvbplayer.c index e5c9270b..6db497e3 100644 --- a/dvbplayer.c +++ b/dvbplayer.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: dvbplayer.c 4.2 2016/12/22 09:40:30 kls Exp $ + * $Id: dvbplayer.c 4.3 2016/12/22 10:43:10 kls Exp $ */ #include "dvbplayer.h" @@ -17,13 +17,14 @@ // --- cPtsIndex ------------------------------------------------------------- -#define PTSINDEX_ENTRIES 500 +#define PTSINDEX_ENTRIES 1024 class cPtsIndex { private: struct tPtsIndex { uint32_t pts; // no need for 33 bit - some devices don't even supply the msb int index; + bool independent; }; tPtsIndex pi[PTSINDEX_ENTRIES]; int w, r; @@ -33,8 +34,9 @@ public: cPtsIndex(void); void Clear(void); bool IsEmpty(void); - void Put(uint32_t Pts, int Index); + void Put(uint32_t Pts, int Index, bool Independent); int FindIndex(uint32_t Pts); + int FindFrameNumber(uint32_t Pts); }; cPtsIndex::cPtsIndex(void) @@ -55,10 +57,11 @@ bool cPtsIndex::IsEmpty(void) return w == r; } -void cPtsIndex::Put(uint32_t Pts, int Index) +void cPtsIndex::Put(uint32_t Pts, int Index, bool Independent) { cMutexLock MutexLock(&mutex); pi[w].pts = Pts; + pi[w].independent = Independent; pi[w].index = Index; w = (w + 1) % PTSINDEX_ENTRIES; if (w == r) @@ -87,6 +90,36 @@ int cPtsIndex::FindIndex(uint32_t Pts) return Index; } +int cPtsIndex::FindFrameNumber(uint32_t Pts) +{ + cMutexLock MutexLock(&mutex); + if (w == r) + return lastFound; // replay always starts at an I frame + bool Valid = false; + int d; + int FrameNumber = 0; + int UnplayedIFrame = 2; // GOPs may intersect, so we're looping until we found two unplayed I frames + for (int i = r; i != w && UnplayedIFrame; ) { + d = Pts - pi[i].pts; + if (d > 0x7FFFFFFF) + d = 0xFFFFFFFF - d; // handle rollover + if (d > 0) { + if (pi[i].independent) { + FrameNumber = pi[i].index; // an I frame's index represents its frame number + Valid = true; + } + else + FrameNumber++; // for every played non-I frame, increase frame number + } + else + if (pi[i].independent) + --UnplayedIFrame; + if (++i >= PTSINDEX_ENTRIES) + i = 0; + } + return Valid ? FrameNumber : FindIndex(Pts); // fall back during trick speeds +} + // --- cNonBlockingFileReader ------------------------------------------------ class cNonBlockingFileReader : public cThread { @@ -251,6 +284,7 @@ public: virtual double FramesPerSecond(void) { return framesPerSecond; } virtual void SetAudioTrack(eTrackType Type, const tTrackId *TrackId); virtual bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false); + virtual bool GetFrameNumber(int &Current, int &Total); virtual bool GetReplayMode(bool &Play, bool &Forward, int &Speed); }; @@ -606,7 +640,7 @@ void cDvbPlayer::Action(void) pc = playFrame->Count(); if (p) { if (playFrame->Index() >= 0 && playFrame->Pts() != 0) - ptsIndex.Put(playFrame->Pts(), playFrame->Index()); + ptsIndex.Put(playFrame->Pts(), playFrame->Index(), playFrame->Independent()); if (firstPacket) { if (isPesRecording) { PlayPes(NULL, 0); @@ -880,7 +914,7 @@ void cDvbPlayer::Goto(int Index, bool Still) if (playMode == pmPause) DevicePlay(); DeviceStillPicture(b, r); - ptsIndex.Put(isPesRecording ? PesGetPts(b) : TsGetPts(b, r), Index); + ptsIndex.Put(isPesRecording ? PesGetPts(b) : TsGetPts(b, r), Index, true); } playMode = pmStill; readIndex = Index; @@ -925,6 +959,17 @@ bool cDvbPlayer::GetIndex(int &Current, int &Total, bool SnapToIFrame) return false; } +bool cDvbPlayer::GetFrameNumber(int &Current, int &Total) +{ + if (index) { + Current = ptsIndex.FindFrameNumber(DeviceGetSTC()); + Total = index->Last(); + return true; + } + Current = Total = -1; + return false; +} + bool cDvbPlayer::GetReplayMode(bool &Play, bool &Forward, int &Speed) { Play = (playMode == pmPlay || playMode == pmFast); @@ -1011,6 +1056,15 @@ bool cDvbPlayerControl::GetIndex(int &Current, int &Total, bool SnapToIFrame) return false; } +bool cDvbPlayerControl::GetFrameNumber(int &Current, int &Total) +{ + if (player) { + player->GetFrameNumber(Current, Total); + return true; + } + return false; +} + bool cDvbPlayerControl::GetReplayMode(bool &Play, bool &Forward, int &Speed) { return player && player->GetReplayMode(Play, Forward, Speed); |