mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Improved replay at the begin and end of a recording; cDvbPlayer::Action() no longer calls DeviceFlush()
This commit is contained in:
parent
1b02cc9c94
commit
c886e69bc6
@ -1200,6 +1200,7 @@ Reinhard Nissl <rnissl@gmx.de>
|
||||
to cDevice::PlayTs()
|
||||
for reporting that the PAT/PMT is processed too often, even if its version
|
||||
hasn't changed
|
||||
for making sure vdr-xine no longer needs cDvbPlayer::Action() to call DeviceFlush()
|
||||
|
||||
Richard Robson <richard_robson@beeb.net>
|
||||
for reporting freezing replay if a timer starts while in Transfer Mode from the
|
||||
|
6
HISTORY
6
HISTORY
@ -5979,7 +5979,7 @@ Video Disk Recorder Revision History
|
||||
cDevice class reimplements PlayTs() or PlayPes(), it also needs to make sure this
|
||||
new function works as expected.
|
||||
|
||||
2009-03-28: Version 1.7.5
|
||||
2009-04-05: Version 1.7.5
|
||||
|
||||
- Fixed a hangup when replaying a TS recording with subtitles activated (reported
|
||||
by Timo Helkio).
|
||||
@ -6009,3 +6009,7 @@ Video Disk Recorder Revision History
|
||||
- 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).
|
||||
|
86
dvbplayer.c
86
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.6 2009/03/28 21:56:56 kls Exp $
|
||||
* $Id: dvbplayer.c 2.7 2009/04/05 09:05:54 kls Exp $
|
||||
*/
|
||||
|
||||
#include "dvbplayer.h"
|
||||
@ -18,7 +18,7 @@
|
||||
|
||||
// --- cPtsIndex -------------------------------------------------------------
|
||||
|
||||
#define PTSINDEX_ENTRIES 100
|
||||
#define PTSINDEX_ENTRIES 500
|
||||
|
||||
class cPtsIndex {
|
||||
private:
|
||||
@ -194,7 +194,7 @@ bool cNonBlockingFileReader::WaitForDataMs(int msToWait)
|
||||
#define PLAYERBUFSIZE MEGABYTE(1)
|
||||
|
||||
#define RESUMEBACKUP 10 // number of seconds to back up when resuming an interrupted replay session
|
||||
#define MAXSTUCKATEND 3 // max. number of seconds to wait in case the device doesn't play the last frame
|
||||
#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:
|
||||
@ -393,9 +393,11 @@ void cDvbPlayer::Action(void)
|
||||
int Length = 0;
|
||||
bool Sleep = false;
|
||||
bool WaitingForData = false;
|
||||
time_t StuckAtEnd = 0;
|
||||
time_t StuckAtEof = 0;
|
||||
uint32_t LastStc = 0;
|
||||
int LastReadIFrame = -1;
|
||||
|
||||
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
|
||||
@ -407,8 +409,6 @@ void cDvbPlayer::Action(void)
|
||||
if (DevicePoll(Poller, 100)) {
|
||||
|
||||
LOCK_THREAD;
|
||||
bool HitBegin = false;
|
||||
bool HitEnd = false;
|
||||
|
||||
// Read the next frame from the file:
|
||||
|
||||
@ -429,7 +429,10 @@ void cDvbPlayer::Action(void)
|
||||
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
|
||||
Index = index->GetNextIFrame(NewIndex, playDir == pdForward, &FileNumber, &FileOffset, &Length, TimeShiftMode);
|
||||
readIndependent = true;
|
||||
}
|
||||
if (Index >= 0) {
|
||||
@ -437,27 +440,16 @@ void cDvbPlayer::Action(void)
|
||||
if (!NextFile(FileNumber, FileOffset))
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
if (playDir == pdForward) {
|
||||
if (!TimeShiftMode) {
|
||||
// hit end of recording: signal end of file but don't change playMode
|
||||
else if (playDir != pdForward || !TimeShiftMode)
|
||||
eof = true;
|
||||
HitEnd = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
HitBegin = true; // hit begin of recording - trigger wait until device has replayed the very first frame:
|
||||
}
|
||||
}
|
||||
else if (index) {
|
||||
uint16_t FileNumber;
|
||||
off_t FileOffset;
|
||||
if (index->Get(readIndex + 1, &FileNumber, &FileOffset, &readIndependent, &Length) && NextFile(FileNumber, FileOffset))
|
||||
readIndex++;
|
||||
else {
|
||||
else
|
||||
eof = true;
|
||||
HitEnd = true;
|
||||
}
|
||||
}
|
||||
else // allows replay even if the index file is missing
|
||||
Length = MAXFRAMESIZE;
|
||||
@ -476,7 +468,9 @@ void cDvbPlayer::Action(void)
|
||||
uint32_t Pts = 0;
|
||||
if (readIndependent)
|
||||
Pts = isPesRecording ? PesGetPts(b) : TsGetPts(b, r);
|
||||
readFrame = new cFrame(b, -r, ftUnknown, readIndependent ? readIndex : -1, Pts); // hands over b to the ringBuffer
|
||||
readFrame = new cFrame(b, -r, ftUnknown, readIndex, Pts); // hands over b to the ringBuffer
|
||||
if (readIndependent)
|
||||
LastReadIFrame = readIndex;
|
||||
b = NULL;
|
||||
}
|
||||
else if (r == 0)
|
||||
@ -529,6 +523,8 @@ void cDvbPlayer::Action(void)
|
||||
}
|
||||
}
|
||||
if (p) {
|
||||
//XXX maybe make PlayTs() play as much as possible, until w == 0? would save this extra code here (and the goto)...
|
||||
while (pc > 0) {
|
||||
int w;
|
||||
if (isPesRecording)
|
||||
w = PlayPes(p, pc, playMode != pmPlay && DeviceIsPlayingVideo());
|
||||
@ -538,13 +534,17 @@ void cDvbPlayer::Action(void)
|
||||
p += w;
|
||||
pc -= w;
|
||||
}
|
||||
else if (w == 0)
|
||||
break;
|
||||
else if (w < 0 && FATALERRNO) {
|
||||
LOG_ERROR;
|
||||
break;
|
||||
goto End;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pc <= 0) {
|
||||
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;
|
||||
}
|
||||
@ -554,34 +554,36 @@ void cDvbPlayer::Action(void)
|
||||
|
||||
// Handle hitting begin/end of recording:
|
||||
|
||||
if (HitBegin || HitEnd) {
|
||||
if (DeviceFlush(10)) { // give device a chance to display the last frame
|
||||
cCondWait::SleepMs(10); // don't get into a tight loop
|
||||
if (eof) {
|
||||
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;
|
||||
}
|
||||
else
|
||||
HitBegin = HitEnd = false;
|
||||
LastStc = Stc;
|
||||
int Index = ptsIndex.FindIndex(Stc);
|
||||
if (playDir == pdForward) {
|
||||
if (Index >= LastReadIFrame)
|
||||
break; // automatically stop at end of recording
|
||||
}
|
||||
if (HitBegin) {
|
||||
if (ptsIndex.FindIndex(DeviceGetSTC()) <= 0) {
|
||||
else if (Index <= 0)
|
||||
SwitchToPlay = true;
|
||||
if (SwitchToPlay) {
|
||||
Empty();
|
||||
DevicePlay();
|
||||
playMode = pmPlay;
|
||||
playDir = pdForward;
|
||||
}
|
||||
}
|
||||
else if (HitEnd) {
|
||||
if (ptsIndex.FindIndex(DeviceGetSTC()) >= readIndex)
|
||||
break;
|
||||
else if (!StuckAtEnd)
|
||||
StuckAtEnd = time(NULL);
|
||||
else if (time(NULL) - StuckAtEnd > MAXSTUCKATEND)
|
||||
break;
|
||||
}
|
||||
else
|
||||
StuckAtEnd = 0;
|
||||
}
|
||||
}
|
||||
|
||||
End:
|
||||
cNonBlockingFileReader *nbfr = nonBlockingFileReader;
|
||||
nonBlockingFileReader = NULL;
|
||||
delete nbfr;
|
||||
|
Loading…
Reference in New Issue
Block a user