mirror of
https://github.com/vdr-projects/vdr.git
synced 2025-03-01 10:50:46 +00:00
Version 1.7.5
- Fixed a hangup when replaying a TS recording with subtitles activated (reported by Timo Helkio). - Fixed handling the 'new' indicator in the recordings menu for TS recordings (thanks to Derek Kelly). - Added cap_sys_nice to the capabilities that are not dropped (thanks to Rolf Ahrenberg). - Updated the Italian OSD texts (thanks to Diego Pierotto). - Added cRecordingInfo::GetEvent() (thanks to Marcel Unbehaun). - Improved synchronizing the progress display, trick modes and subtitle display to the actual audio/video. This now works independent of any buffer sizes the output device might use. + The cBackTrace class has been replaced with cPtsIndex, which keeps track of the PTS timestamps of recently played frames. + cDevice::GetSTC() is now required to deliver the STC even in trick modes. It is sufficient if it returns the PTS of the most recently presented audio/video frame. + The full-featured DVB cards need an improved firmware in order to return proper STC values in trick modes (thanks to Oliver Endriss for enhancing the av7110 firmware). - Adapted cFrameDetector::Analyze() to HD NTSC broadcasts that split frames over several payload units (thanks to Derek Kelly for reporting this and helping in testing). - Modified cFrameDetector::Analyze() to make it process whole frames at once, so that file I/O overhead is minimized during recording (reported by Günter Niedermeier). - Added command line help for the '-i' option. - Fixed cDvbPlayer::NextFile() to handle files larger than 2GB (thanks to Jose Alberto Reguero). - Improved replay at the begin and end of a recording. The very first and very last frame is now sent to the output device repeatedly until GetSTC() reports that it has been played. cDvbPlayer::Action() no longer calls DeviceFlush() (thanks to Reinhard Nissl for making sure vdr-xine no longer needs this). - Added missing '[]' to the delete operator in cMenuEditStrItem::~cMenuEditStrItem(). - Added missing virtual destructor to cPalette. - Now freeing configDirectory before setting it to a new value in cPlugin::SetConfigDirectory(). - Fixed a crash when jumping to an editing mark in an audio recording. - Fixed the 'VideoOnly' condition in the PlayPes() and PlayTs() calls in cDvbPlayer::Action() (thanks to Reinhard Nissl). - cDevice::PlayTs() now plays as many TS packets as possible in one call. - Making sure any floating point numbers written use a decimal point (thanks to Oliver Endriss for pointing out a problem with the F record in the info file of a recording). - Fixed detecting the frame rate for radio recordings. - Added missing AUDIO_PAUSE/AUDIO_CONTINUE calls to cDvbDevice (thanks to Oliver Endriss). - No longer writing the video type into channels.conf if VPID is 0 (thanks to Oliver Endriss for reporting this). - Improved efficiency of cEIT::cEIT() (thanks to Tobias Bratfisch).
This commit is contained in:
271
dvbplayer.c
271
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 2.3 2009/01/25 11:11:39 kls Exp $
|
||||
* $Id: dvbplayer.c 2.11 2009/04/05 13:04:33 kls Exp $
|
||||
*/
|
||||
|
||||
#include "dvbplayer.h"
|
||||
@@ -16,59 +16,69 @@
|
||||
#include "thread.h"
|
||||
#include "tools.h"
|
||||
|
||||
// --- cBackTrace ------------------------------------------------------------
|
||||
// --- cPtsIndex -------------------------------------------------------------
|
||||
|
||||
#define AVG_FRAME_SIZE 15000 // an assumption about the average frame size
|
||||
#define DVB_BUF_SIZE (256 * 1024) // an assumption about the dvb firmware buffer size
|
||||
#define BACKTRACE_ENTRIES (DVB_BUF_SIZE / AVG_FRAME_SIZE + 20) // how many entries are needed to backtrace buffer contents
|
||||
#define PTSINDEX_ENTRIES 500
|
||||
|
||||
class cBackTrace {
|
||||
class cPtsIndex {
|
||||
private:
|
||||
int index[BACKTRACE_ENTRIES];
|
||||
int length[BACKTRACE_ENTRIES];
|
||||
int pos, num;
|
||||
struct tPtsIndex {
|
||||
uint32_t pts; // no need for 33 bit - some devices don't even supply the msb
|
||||
int index;
|
||||
};
|
||||
tPtsIndex pi[PTSINDEX_ENTRIES];
|
||||
int w, r;
|
||||
int lastFound;
|
||||
cMutex mutex;
|
||||
public:
|
||||
cBackTrace(void);
|
||||
cPtsIndex(void);
|
||||
void Clear(void);
|
||||
void Add(int Index, int Length);
|
||||
int Get(bool Forward);
|
||||
void Put(uint32_t Pts, int Index);
|
||||
int FindIndex(uint32_t Pts);
|
||||
};
|
||||
|
||||
cBackTrace::cBackTrace(void)
|
||||
cPtsIndex::cPtsIndex(void)
|
||||
{
|
||||
lastFound = 0;
|
||||
Clear();
|
||||
}
|
||||
|
||||
void cBackTrace::Clear(void)
|
||||
void cPtsIndex::Clear(void)
|
||||
{
|
||||
pos = num = 0;
|
||||
cMutexLock MutexLock(&mutex);
|
||||
w = r = 0;
|
||||
}
|
||||
|
||||
void cBackTrace::Add(int Index, int Length)
|
||||
void cPtsIndex::Put(uint32_t Pts, int Index)
|
||||
{
|
||||
index[pos] = Index;
|
||||
length[pos] = Length;
|
||||
if (++pos >= BACKTRACE_ENTRIES)
|
||||
pos = 0;
|
||||
if (num < BACKTRACE_ENTRIES)
|
||||
num++;
|
||||
cMutexLock MutexLock(&mutex);
|
||||
pi[w].pts = Pts;
|
||||
pi[w].index = Index;
|
||||
w = (w + 1) % PTSINDEX_ENTRIES;
|
||||
if (w == r)
|
||||
r = (r + 1) % PTSINDEX_ENTRIES;
|
||||
}
|
||||
|
||||
int cBackTrace::Get(bool Forward)
|
||||
int cPtsIndex::FindIndex(uint32_t Pts)
|
||||
{
|
||||
int p = pos;
|
||||
int n = num;
|
||||
int l = DVB_BUF_SIZE + (Forward ? 0 : 256 * 1024); //XXX (256 * 1024) == DVB_BUF_SIZE ???
|
||||
int i = -1;
|
||||
|
||||
while (n && l > 0) {
|
||||
if (--p < 0)
|
||||
p = BACKTRACE_ENTRIES - 1;
|
||||
i = index[p] - 1;
|
||||
l -= length[p];
|
||||
n--;
|
||||
}
|
||||
return i;
|
||||
cMutexLock MutexLock(&mutex);
|
||||
if (w == r)
|
||||
return lastFound; // list is empty, let's not jump way off the last known position
|
||||
uint32_t Delta = 0xFFFFFFFF;
|
||||
int Index = -1;
|
||||
for (int i = w; i != r; ) {
|
||||
if (--i < 0)
|
||||
i = PTSINDEX_ENTRIES - 1;
|
||||
uint32_t d = pi[i].pts < Pts ? Pts - pi[i].pts : pi[i].pts - Pts;
|
||||
if (d > 0x7FFFFFFF)
|
||||
d = 0xFFFFFFFF - d; // handle rollover
|
||||
if (d < Delta) {
|
||||
Delta = d;
|
||||
Index = pi[i].index;
|
||||
}
|
||||
}
|
||||
lastFound = Index;
|
||||
return Index;
|
||||
}
|
||||
|
||||
// --- cNonBlockingFileReader ------------------------------------------------
|
||||
@@ -183,8 +193,8 @@ bool cNonBlockingFileReader::WaitForDataMs(int msToWait)
|
||||
|
||||
#define PLAYERBUFSIZE MEGABYTE(1)
|
||||
|
||||
// The number of seconds to back up when resuming an interrupted replay session:
|
||||
#define RESUMEBACKUP 10
|
||||
#define RESUMEBACKUP 10 // number of seconds to back up when resuming an interrupted replay session
|
||||
#define MAXSTUCKATEOF 3 // max. number of seconds to wait in case the device doesn't play the last frame
|
||||
|
||||
class cDvbPlayer : public cPlayer, cThread {
|
||||
private:
|
||||
@@ -193,7 +203,7 @@ private:
|
||||
static int Speeds[];
|
||||
cNonBlockingFileReader *nonBlockingFileReader;
|
||||
cRingBufferFrame *ringBuffer;
|
||||
cBackTrace *backTrace;
|
||||
cPtsIndex ptsIndex;
|
||||
cFileName *fileName;
|
||||
cIndexFile *index;
|
||||
cUnbufferedFile *replayFile;
|
||||
@@ -204,12 +214,13 @@ private:
|
||||
ePlayModes playMode;
|
||||
ePlayDirs playDir;
|
||||
int trickSpeed;
|
||||
int readIndex, writeIndex;
|
||||
int readIndex;
|
||||
bool readIndependent;
|
||||
cFrame *readFrame;
|
||||
cFrame *playFrame;
|
||||
void TrickSpeed(int Increment);
|
||||
void Empty(void);
|
||||
bool NextFile(uchar FileNumber = 0, int FileOffset = -1);
|
||||
bool NextFile(uint16_t FileNumber = 0, off_t FileOffset = -1);
|
||||
int Resume(void);
|
||||
bool Save(void);
|
||||
protected:
|
||||
@@ -242,7 +253,6 @@ cDvbPlayer::cDvbPlayer(const char *FileName)
|
||||
{
|
||||
nonBlockingFileReader = NULL;
|
||||
ringBuffer = NULL;
|
||||
backTrace = NULL;
|
||||
index = NULL;
|
||||
cRecording Recording(FileName);
|
||||
framesPerSecond = Recording.FramesPerSecond();
|
||||
@@ -252,7 +262,8 @@ cDvbPlayer::cDvbPlayer(const char *FileName)
|
||||
playMode = pmPlay;
|
||||
playDir = pdForward;
|
||||
trickSpeed = NORMAL_SPEED;
|
||||
readIndex = writeIndex = -1;
|
||||
readIndex = -1;
|
||||
readIndependent = false;
|
||||
readFrame = NULL;
|
||||
playFrame = NULL;
|
||||
isyslog("replay %s", FileName);
|
||||
@@ -269,17 +280,15 @@ cDvbPlayer::cDvbPlayer(const char *FileName)
|
||||
delete index;
|
||||
index = NULL;
|
||||
}
|
||||
backTrace = new cBackTrace;
|
||||
}
|
||||
|
||||
cDvbPlayer::~cDvbPlayer()
|
||||
{
|
||||
Detach();
|
||||
Save();
|
||||
Detach();
|
||||
delete readFrame; // might not have been stored in the buffer in Action()
|
||||
delete index;
|
||||
delete fileName;
|
||||
delete backTrace;
|
||||
delete ringBuffer;
|
||||
}
|
||||
|
||||
@@ -308,18 +317,18 @@ void cDvbPlayer::Empty(void)
|
||||
LOCK_THREAD;
|
||||
if (nonBlockingFileReader)
|
||||
nonBlockingFileReader->Clear();
|
||||
if ((readIndex = backTrace->Get(playDir == pdForward)) < 0)
|
||||
readIndex = writeIndex;
|
||||
if (!firstPacket) // don't set the readIndex twice if Empty() is called more than once
|
||||
readIndex = ptsIndex.FindIndex(DeviceGetSTC());
|
||||
delete readFrame; // might not have been stored in the buffer in Action()
|
||||
readFrame = NULL;
|
||||
playFrame = NULL;
|
||||
ringBuffer->Clear();
|
||||
backTrace->Clear();
|
||||
ptsIndex.Clear();
|
||||
DeviceClear();
|
||||
firstPacket = true;
|
||||
}
|
||||
|
||||
bool cDvbPlayer::NextFile(uchar FileNumber, int FileOffset)
|
||||
bool cDvbPlayer::NextFile(uint16_t FileNumber, off_t FileOffset)
|
||||
{
|
||||
if (FileNumber > 0)
|
||||
replayFile = fileName->SetOffset(FileNumber, FileOffset);
|
||||
@@ -346,7 +355,7 @@ int cDvbPlayer::Resume(void)
|
||||
bool cDvbPlayer::Save(void)
|
||||
{
|
||||
if (index) {
|
||||
int Index = writeIndex;
|
||||
int Index = ptsIndex.FindIndex(DeviceGetSTC());
|
||||
if (Index >= 0) {
|
||||
Index -= int(round(RESUMEBACKUP * framesPerSecond));
|
||||
if (Index > 0)
|
||||
@@ -384,8 +393,12 @@ void cDvbPlayer::Action(void)
|
||||
int Length = 0;
|
||||
bool Sleep = false;
|
||||
bool WaitingForData = false;
|
||||
time_t StuckAtEof = 0;
|
||||
uint32_t LastStc = 0;
|
||||
int LastReadIFrame = -1;
|
||||
int SwitchToPlayFrame = 0;
|
||||
|
||||
while (Running() && (NextFile() || readIndex >= 0 || ringBuffer->Available() || !DeviceFlush(100))) {
|
||||
while (Running() && (NextFile() || readIndex >= 0 || ringBuffer->Available())) {
|
||||
if (Sleep) {
|
||||
if (WaitingForData)
|
||||
nonBlockingFileReader->WaitForDataMs(3); // this keeps the CPU load low, but reacts immediately on new data
|
||||
@@ -403,60 +416,47 @@ void cDvbPlayer::Action(void)
|
||||
if (playMode != pmStill && playMode != pmPause) {
|
||||
if (!readFrame && (replayFile || readIndex >= 0)) {
|
||||
if (!nonBlockingFileReader->Reading()) {
|
||||
if (playMode == pmFast || (playMode == pmSlow && playDir == pdBackward)) {
|
||||
if (!SwitchToPlayFrame && (playMode == pmFast || (playMode == pmSlow && playDir == pdBackward))) {
|
||||
uint16_t FileNumber;
|
||||
off_t FileOffset;
|
||||
bool TimeShiftMode = index->IsStillRecording();
|
||||
int Index = -1;
|
||||
readIndependent = false;
|
||||
if (DeviceHasIBPTrickSpeed() && playDir == pdForward) {
|
||||
if (index->Get(readIndex + 1, &FileNumber, &FileOffset, NULL, &Length))
|
||||
if (index->Get(readIndex + 1, &FileNumber, &FileOffset, &readIndependent, &Length))
|
||||
Index = readIndex + 1;
|
||||
}
|
||||
else {
|
||||
int d = int(round(0.4 * framesPerSecond));
|
||||
if (playDir != pdForward)
|
||||
d = -d;
|
||||
Index = index->GetNextIFrame(readIndex + d, playDir == pdForward, &FileNumber, &FileOffset, &Length, TimeShiftMode);
|
||||
int NewIndex = readIndex + d;
|
||||
if (NewIndex <= 0 && readIndex > 0)
|
||||
NewIndex = 1; // make sure the very first frame is delivered
|
||||
NewIndex = index->GetNextIFrame(NewIndex, playDir == pdForward, &FileNumber, &FileOffset, &Length, TimeShiftMode);
|
||||
if (NewIndex < 0 && TimeShiftMode && playDir == pdForward)
|
||||
SwitchToPlayFrame = Index;
|
||||
Index = NewIndex;
|
||||
readIndependent = true;
|
||||
}
|
||||
if (Index >= 0) {
|
||||
if (!NextFile(FileNumber, FileOffset)) {
|
||||
readIndex = Index;
|
||||
readIndex = Index;
|
||||
if (!NextFile(FileNumber, FileOffset))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!TimeShiftMode && playDir == pdForward) {
|
||||
// hit end of recording: signal end of file but don't change playMode
|
||||
readIndex = -1;
|
||||
eof = true;
|
||||
continue;
|
||||
}
|
||||
// hit begin of recording: wait for device buffers to drain
|
||||
// before changing play mode:
|
||||
if (!DeviceFlush(100))
|
||||
continue;
|
||||
// can't call Play() here, because those functions may only be
|
||||
// called from the foreground thread - and we also don't need
|
||||
// to empty the buffer here
|
||||
DevicePlay();
|
||||
playMode = pmPlay;
|
||||
playDir = pdForward;
|
||||
continue;
|
||||
}
|
||||
readIndex = Index;
|
||||
else
|
||||
eof = true;
|
||||
}
|
||||
else if (index) {
|
||||
uint16_t FileNumber;
|
||||
off_t FileOffset;
|
||||
readIndex++;
|
||||
if (!(index->Get(readIndex, &FileNumber, &FileOffset, NULL, &Length) && NextFile(FileNumber, FileOffset))) {
|
||||
readIndex = -1;
|
||||
if (index->Get(readIndex + 1, &FileNumber, &FileOffset, &readIndependent, &Length) && NextFile(FileNumber, FileOffset))
|
||||
readIndex++;
|
||||
else
|
||||
eof = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else // allows replay even if the index file is missing
|
||||
Length = MAXFRAMESIZE;
|
||||
Length = MAXFRAMESIZE / TS_SIZE * TS_SIZE;// FIXME: use a linear ringbuffer in this case, and fix cDevice::PlayPes()
|
||||
if (Length == -1)
|
||||
Length = MAXFRAMESIZE; // this means we read up to EOF (see cIndex)
|
||||
else if (Length > MAXFRAMESIZE) {
|
||||
@@ -465,19 +465,26 @@ void cDvbPlayer::Action(void)
|
||||
}
|
||||
b = MALLOC(uchar, Length);
|
||||
}
|
||||
int r = nonBlockingFileReader->Read(replayFile, b, Length);
|
||||
if (r > 0) {
|
||||
WaitingForData = false;
|
||||
readFrame = new cFrame(b, -r, ftUnknown, readIndex); // hands over b to the ringBuffer
|
||||
b = NULL;
|
||||
}
|
||||
else if (r == 0)
|
||||
eof = true;
|
||||
else if (r < 0 && errno == EAGAIN)
|
||||
WaitingForData = true;
|
||||
else if (r < 0 && FATALERRNO) {
|
||||
LOG_ERROR;
|
||||
break;
|
||||
if (!eof) {
|
||||
int r = nonBlockingFileReader->Read(replayFile, b, Length);
|
||||
if (r > 0) {
|
||||
WaitingForData = false;
|
||||
uint32_t Pts = 0;
|
||||
if (readIndependent) {
|
||||
Pts = isPesRecording ? PesGetPts(b) : TsGetPts(b, r);
|
||||
LastReadIFrame = readIndex;
|
||||
}
|
||||
readFrame = new cFrame(b, -r, ftUnknown, readIndex, Pts); // hands over b to the ringBuffer
|
||||
b = NULL;
|
||||
}
|
||||
else if (r == 0)
|
||||
eof = true;
|
||||
else if (r < 0 && errno == EAGAIN)
|
||||
WaitingForData = true;
|
||||
else if (r < 0 && FATALERRNO) {
|
||||
LOG_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -506,6 +513,8 @@ void cDvbPlayer::Action(void)
|
||||
p = playFrame->Data();
|
||||
pc = playFrame->Count();
|
||||
if (p) {
|
||||
if (playFrame->Index() >= 0)
|
||||
ptsIndex.Put(playFrame->Pts(), playFrame->Index());
|
||||
if (firstPacket) {
|
||||
if (isPesRecording) {
|
||||
PlayPes(NULL, 0);
|
||||
@@ -520,28 +529,57 @@ void cDvbPlayer::Action(void)
|
||||
if (p) {
|
||||
int w;
|
||||
if (isPesRecording)
|
||||
w = PlayPes(p, pc, playMode != pmPlay && DeviceIsPlayingVideo());
|
||||
w = PlayPes(p, pc, playMode != pmPlay && !(playMode == pmSlow && playDir == pdForward) && DeviceIsPlayingVideo());
|
||||
else
|
||||
w = PlayTs(p, TS_SIZE, playMode != pmPlay && DeviceIsPlayingVideo());
|
||||
w = PlayTs(p, pc, playMode != pmPlay && !(playMode == pmSlow && playDir == pdForward) && DeviceIsPlayingVideo());
|
||||
if (w > 0) {
|
||||
p += w;
|
||||
pc -= w;
|
||||
}
|
||||
else if (w < 0 && FATALERRNO) {
|
||||
else if (w < 0 && FATALERRNO)
|
||||
LOG_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pc <= 0) {
|
||||
writeIndex = playFrame->Index();
|
||||
backTrace->Add(playFrame->Index(), playFrame->Count());
|
||||
ringBuffer->Drop(playFrame);
|
||||
if (!eof || (playDir != pdForward && playFrame->Index() > 0) || (playDir == pdForward && playFrame->Index() < readIndex))
|
||||
ringBuffer->Drop(playFrame); // the very first and last frame are continously repeated to flush data through the device
|
||||
playFrame = NULL;
|
||||
p = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
Sleep = true;
|
||||
|
||||
// Handle hitting begin/end of recording:
|
||||
|
||||
if (eof || SwitchToPlayFrame) {
|
||||
bool SwitchToPlay = false;
|
||||
uint32_t Stc = DeviceGetSTC();
|
||||
if (Stc != LastStc)
|
||||
StuckAtEof = 0;
|
||||
else if (!StuckAtEof)
|
||||
StuckAtEof = time(NULL);
|
||||
else if (time(NULL) - StuckAtEof > MAXSTUCKATEOF) {
|
||||
if (playDir == pdForward)
|
||||
break; // automatically stop at end of recording
|
||||
SwitchToPlay = true;
|
||||
}
|
||||
LastStc = Stc;
|
||||
int Index = ptsIndex.FindIndex(Stc);
|
||||
if (playDir == pdForward && !SwitchToPlayFrame) {
|
||||
if (Index >= LastReadIFrame)
|
||||
break; // automatically stop at end of recording
|
||||
}
|
||||
else if (Index <= 0 || SwitchToPlayFrame && Index >= SwitchToPlayFrame)
|
||||
SwitchToPlay = true;
|
||||
if (SwitchToPlay) {
|
||||
if (!SwitchToPlayFrame)
|
||||
Empty();
|
||||
DevicePlay();
|
||||
playMode = pmPlay;
|
||||
playDir = pdForward;
|
||||
SwitchToPlayFrame = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -614,6 +652,7 @@ void cDvbPlayer::Forward(void)
|
||||
Pause();
|
||||
break;
|
||||
}
|
||||
Empty();
|
||||
// run into pmPause
|
||||
case pmStill:
|
||||
case pmPause:
|
||||
@@ -661,6 +700,7 @@ void cDvbPlayer::Backward(void)
|
||||
Pause();
|
||||
break;
|
||||
}
|
||||
Empty();
|
||||
// run into pmPause
|
||||
case pmStill:
|
||||
case pmPause: {
|
||||
@@ -696,14 +736,14 @@ void cDvbPlayer::SkipSeconds(int Seconds)
|
||||
{
|
||||
if (index && Seconds) {
|
||||
LOCK_THREAD;
|
||||
int Index = ptsIndex.FindIndex(DeviceGetSTC());
|
||||
Empty();
|
||||
int Index = writeIndex;
|
||||
if (Index >= 0) {
|
||||
Index = max(Index + SecondsToFrames(Seconds, framesPerSecond), 0);
|
||||
if (Index > 0)
|
||||
Index = index->GetNextIFrame(Index, false, NULL, NULL, NULL, true);
|
||||
if (Index >= 0)
|
||||
readIndex = writeIndex = Index - 1; // Action() will first increment it!
|
||||
readIndex = Index - 1; // Action() will first increment it!
|
||||
}
|
||||
Play();
|
||||
}
|
||||
@@ -727,25 +767,22 @@ void cDvbPlayer::Goto(int Index, bool Still)
|
||||
if (playMode == pmPause)
|
||||
DevicePlay();
|
||||
DeviceStillPicture(b, r);
|
||||
ptsIndex.Put(isPesRecording ? PesGetPts(b) : TsGetPts(b, r), Index);
|
||||
}
|
||||
playMode = pmStill;
|
||||
}
|
||||
readIndex = writeIndex = Index;
|
||||
readIndex = Index;
|
||||
}
|
||||
}
|
||||
|
||||
bool cDvbPlayer::GetIndex(int &Current, int &Total, bool SnapToIFrame)
|
||||
{
|
||||
if (index) {
|
||||
if (playMode == pmStill)
|
||||
Current = max(readIndex, 0);
|
||||
else {
|
||||
Current = max(writeIndex, 0);
|
||||
if (SnapToIFrame) {
|
||||
int i1 = index->GetNextIFrame(Current + 1, false);
|
||||
int i2 = index->GetNextIFrame(Current, true);
|
||||
Current = (abs(Current - i1) <= abs(Current - i2)) ? i1 : i2;
|
||||
}
|
||||
Current = ptsIndex.FindIndex(DeviceGetSTC());
|
||||
if (SnapToIFrame) {
|
||||
int i1 = index->GetNextIFrame(Current + 1, false);
|
||||
int i2 = index->GetNextIFrame(Current, true);
|
||||
Current = (abs(Current - i1) <= abs(Current - i2)) ? i1 : i2;
|
||||
}
|
||||
Total = index->Last();
|
||||
return true;
|
||||
|
Reference in New Issue
Block a user