mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Fixed distortions when switching to the next file during replay
This commit is contained in:
parent
fc54164405
commit
efd7427bbe
1
HISTORY
1
HISTORY
@ -6045,3 +6045,4 @@ Video Disk Recorder Revision History
|
|||||||
values larger than 2GB.
|
values larger than 2GB.
|
||||||
- Added cDevice::NumProvidedSystems() to PLUGINS.html (was missing since it had
|
- Added cDevice::NumProvidedSystems() to PLUGINS.html (was missing since it had
|
||||||
been implemented).
|
been implemented).
|
||||||
|
- Fixed distortions when switching to the next file during replay.
|
||||||
|
346
dvbplayer.c
346
dvbplayer.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: dvbplayer.c 2.12 2009/04/13 11:10:50 kls Exp $
|
* $Id: dvbplayer.c 2.13 2009/04/18 14:18:22 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dvbplayer.h"
|
#include "dvbplayer.h"
|
||||||
@ -398,189 +398,191 @@ void cDvbPlayer::Action(void)
|
|||||||
int LastReadIFrame = -1;
|
int LastReadIFrame = -1;
|
||||||
int SwitchToPlayFrame = 0;
|
int SwitchToPlayFrame = 0;
|
||||||
|
|
||||||
while (Running() && (NextFile() || readIndex >= 0 || ringBuffer->Available())) {
|
while (Running()) {
|
||||||
if (Sleep) {
|
if (WaitingForData)
|
||||||
if (WaitingForData)
|
nonBlockingFileReader->WaitForDataMs(3); // this keeps the CPU load low, but reacts immediately on new data
|
||||||
nonBlockingFileReader->WaitForDataMs(3); // this keeps the CPU load low, but reacts immediately on new data
|
else if (Sleep) {
|
||||||
else
|
cPoller Poller;
|
||||||
cCondWait::SleepMs(3); // this keeps the CPU load low
|
DevicePoll(Poller, 10);
|
||||||
Sleep = false;
|
Sleep = false;
|
||||||
}
|
}
|
||||||
cPoller Poller;
|
{
|
||||||
if (DevicePoll(Poller, 100)) {
|
LOCK_THREAD;
|
||||||
|
|
||||||
LOCK_THREAD;
|
// Read the next frame from the file:
|
||||||
|
|
||||||
// Read the next frame from the file:
|
if (playMode != pmStill && playMode != pmPause) {
|
||||||
|
if (!readFrame && (replayFile || readIndex >= 0)) {
|
||||||
|
if (!nonBlockingFileReader->Reading()) {
|
||||||
|
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, &readIndependent, &Length))
|
||||||
|
Index = readIndex + 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int d = int(round(0.4 * framesPerSecond));
|
||||||
|
if (playDir != pdForward)
|
||||||
|
d = -d;
|
||||||
|
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) {
|
||||||
|
readIndex = Index;
|
||||||
|
if (!NextFile(FileNumber, FileOffset))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
eof = true;
|
||||||
|
}
|
||||||
|
else if (index) {
|
||||||
|
uint16_t FileNumber;
|
||||||
|
off_t FileOffset;
|
||||||
|
if (index->Get(readIndex + 1, &FileNumber, &FileOffset, &readIndependent, &Length) && NextFile(FileNumber, FileOffset))
|
||||||
|
readIndex++;
|
||||||
|
else
|
||||||
|
eof = true;
|
||||||
|
}
|
||||||
|
else // allows replay even if the index file is missing
|
||||||
|
Length = MAXFRAMESIZE;
|
||||||
|
if (Length == -1)
|
||||||
|
Length = MAXFRAMESIZE; // this means we read up to EOF (see cIndex)
|
||||||
|
else if (Length > MAXFRAMESIZE) {
|
||||||
|
esyslog("ERROR: frame larger than buffer (%d > %d)", Length, MAXFRAMESIZE);
|
||||||
|
Length = MAXFRAMESIZE;
|
||||||
|
}
|
||||||
|
b = MALLOC(uchar, Length);
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (playMode != pmStill && playMode != pmPause) {
|
// Store the frame in the buffer:
|
||||||
if (!readFrame && (replayFile || readIndex >= 0)) {
|
|
||||||
if (!nonBlockingFileReader->Reading()) {
|
|
||||||
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, &readIndependent, &Length))
|
|
||||||
Index = readIndex + 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int d = int(round(0.4 * framesPerSecond));
|
|
||||||
if (playDir != pdForward)
|
|
||||||
d = -d;
|
|
||||||
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) {
|
|
||||||
readIndex = Index;
|
|
||||||
if (!NextFile(FileNumber, FileOffset))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
eof = true;
|
|
||||||
}
|
|
||||||
else if (index) {
|
|
||||||
uint16_t FileNumber;
|
|
||||||
off_t FileOffset;
|
|
||||||
if (index->Get(readIndex + 1, &FileNumber, &FileOffset, &readIndependent, &Length) && NextFile(FileNumber, FileOffset))
|
|
||||||
readIndex++;
|
|
||||||
else
|
|
||||||
eof = true;
|
|
||||||
}
|
|
||||||
else // allows replay even if the index file is missing
|
|
||||||
Length = MAXFRAMESIZE;
|
|
||||||
if (Length == -1)
|
|
||||||
Length = MAXFRAMESIZE; // this means we read up to EOF (see cIndex)
|
|
||||||
else if (Length > MAXFRAMESIZE) {
|
|
||||||
esyslog("ERROR: frame larger than buffer (%d > %d)", Length, MAXFRAMESIZE);
|
|
||||||
Length = MAXFRAMESIZE;
|
|
||||||
}
|
|
||||||
b = MALLOC(uchar, Length);
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store the frame in the buffer:
|
if (readFrame) {
|
||||||
|
if (ringBuffer->Put(readFrame))
|
||||||
|
readFrame = NULL;
|
||||||
|
else
|
||||||
|
Sleep = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Sleep = true;
|
||||||
|
|
||||||
if (readFrame) {
|
// Get the next frame from the buffer:
|
||||||
if (ringBuffer->Put(readFrame))
|
|
||||||
readFrame = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
Sleep = true;
|
|
||||||
|
|
||||||
// Get the next frame from the buffer:
|
if (!playFrame) {
|
||||||
|
playFrame = ringBuffer->Get();
|
||||||
|
p = NULL;
|
||||||
|
pc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!playFrame) {
|
// Play the frame:
|
||||||
playFrame = ringBuffer->Get();
|
|
||||||
p = NULL;
|
|
||||||
pc = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Play the frame:
|
if (playFrame) {
|
||||||
|
if (!p) {
|
||||||
|
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);
|
||||||
|
cRemux::SetBrokenLink(p, pc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
PlayTs(NULL, 0);
|
||||||
|
firstPacket = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p) {
|
||||||
|
int w;
|
||||||
|
if (isPesRecording)
|
||||||
|
w = PlayPes(p, pc, playMode != pmPlay && !(playMode == pmSlow && playDir == pdForward) && DeviceIsPlayingVideo());
|
||||||
|
else
|
||||||
|
w = PlayTs(p, pc, playMode != pmPlay && !(playMode == pmSlow && playDir == pdForward) && DeviceIsPlayingVideo());
|
||||||
|
if (w > 0) {
|
||||||
|
p += w;
|
||||||
|
pc -= w;
|
||||||
|
}
|
||||||
|
else if (w < 0 && FATALERRNO)
|
||||||
|
LOG_ERROR;
|
||||||
|
else
|
||||||
|
Sleep = true;
|
||||||
|
}
|
||||||
|
if (pc <= 0) {
|
||||||
|
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;
|
||||||
|
|
||||||
if (playFrame) {
|
// Handle hitting begin/end of recording:
|
||||||
if (!p) {
|
|
||||||
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);
|
|
||||||
cRemux::SetBrokenLink(p, pc);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
PlayTs(NULL, 0);
|
|
||||||
firstPacket = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (p) {
|
|
||||||
int w;
|
|
||||||
if (isPesRecording)
|
|
||||||
w = PlayPes(p, pc, playMode != pmPlay && !(playMode == pmSlow && playDir == pdForward) && DeviceIsPlayingVideo());
|
|
||||||
else
|
|
||||||
w = PlayTs(p, pc, playMode != pmPlay && !(playMode == pmSlow && playDir == pdForward) && DeviceIsPlayingVideo());
|
|
||||||
if (w > 0) {
|
|
||||||
p += w;
|
|
||||||
pc -= w;
|
|
||||||
}
|
|
||||||
else if (w < 0 && FATALERRNO)
|
|
||||||
LOG_ERROR;
|
|
||||||
}
|
|
||||||
if (pc <= 0) {
|
|
||||||
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;
|
||||||
if (eof || SwitchToPlayFrame) {
|
uint32_t Stc = DeviceGetSTC();
|
||||||
bool SwitchToPlay = false;
|
if (Stc != LastStc)
|
||||||
uint32_t Stc = DeviceGetSTC();
|
StuckAtEof = 0;
|
||||||
if (Stc != LastStc)
|
else if (!StuckAtEof)
|
||||||
StuckAtEof = 0;
|
StuckAtEof = time(NULL);
|
||||||
else if (!StuckAtEof)
|
else if (time(NULL) - StuckAtEof > MAXSTUCKATEOF) {
|
||||||
StuckAtEof = time(NULL);
|
if (playDir == pdForward)
|
||||||
else if (time(NULL) - StuckAtEof > MAXSTUCKATEOF) {
|
break; // automatically stop at end of recording
|
||||||
if (playDir == pdForward)
|
SwitchToPlay = true;
|
||||||
break; // automatically stop at end of recording
|
}
|
||||||
SwitchToPlay = true;
|
LastStc = Stc;
|
||||||
}
|
int Index = ptsIndex.FindIndex(Stc);
|
||||||
LastStc = Stc;
|
if (playDir == pdForward && !SwitchToPlayFrame) {
|
||||||
int Index = ptsIndex.FindIndex(Stc);
|
if (Index >= LastReadIFrame)
|
||||||
if (playDir == pdForward && !SwitchToPlayFrame) {
|
break; // automatically stop at end of recording
|
||||||
if (Index >= LastReadIFrame)
|
}
|
||||||
break; // automatically stop at end of recording
|
else if (Index <= 0 || SwitchToPlayFrame && Index >= SwitchToPlayFrame)
|
||||||
}
|
SwitchToPlay = true;
|
||||||
else if (Index <= 0 || SwitchToPlayFrame && Index >= SwitchToPlayFrame)
|
if (SwitchToPlay) {
|
||||||
SwitchToPlay = true;
|
if (!SwitchToPlayFrame)
|
||||||
if (SwitchToPlay) {
|
Empty();
|
||||||
if (!SwitchToPlayFrame)
|
DevicePlay();
|
||||||
Empty();
|
playMode = pmPlay;
|
||||||
DevicePlay();
|
playDir = pdForward;
|
||||||
playMode = pmPlay;
|
SwitchToPlayFrame = 0;
|
||||||
playDir = pdForward;
|
}
|
||||||
SwitchToPlayFrame = 0;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cNonBlockingFileReader *nbfr = nonBlockingFileReader;
|
cNonBlockingFileReader *nbfr = nonBlockingFileReader;
|
||||||
|
Loading…
Reference in New Issue
Block a user