From 74016967e4c947bb7f58fa82865b4587f0014ff0 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sun, 21 Oct 2001 13:36:27 +0200 Subject: [PATCH] Fixed handling trick modes near the beginning and end of a recording --- HISTORY | 3 +- dvbapi.c | 122 ++++++++++++++++++++++++++++++------------------------- thread.c | 4 +- 3 files changed, 71 insertions(+), 58 deletions(-) diff --git a/HISTORY b/HISTORY index 7e78de8a..d56af941 100644 --- a/HISTORY +++ b/HISTORY @@ -787,7 +787,7 @@ Video Disk Recorder Revision History - Made the volume, mute and power keys work when a menu is active, too (thanks to Matthias Weingart). -2001-10-20: Version 0.97 +2001-10-21: Version 0.97 - Implemented a lock file to prevent more than one instance of VDR from removing files from the video directory at the same time. @@ -828,3 +828,4 @@ Video Disk Recorder Revision History (thanks to Helmut Schächner). - Fixed reading timers.conf and channels.conf that contain blanks after numeric values. +- Fixed handling trick modes near the beginning and end of a recording. diff --git a/dvbapi.c b/dvbapi.c index 17758e82..786dff7f 100644 --- a/dvbapi.c +++ b/dvbapi.c @@ -7,7 +7,7 @@ * DVD support initially written by Andreas Schultz * based on dvdplayer-0.5 by Matjaz Thaler * - * $Id: dvbapi.c 1.131 2001/10/06 15:14:17 kls Exp $ + * $Id: dvbapi.c 1.132 2001/10/21 13:36:27 kls Exp $ */ //#define DVDDEBUG 1 @@ -72,6 +72,9 @@ extern "C" { // is broken: #define MAXBROKENTIMEOUT 30 // seconds +// The maximum time to wait before giving up while catching up on an index file: +#define MAXINDEXCATCHUP 2 // seconds + #define CHECK(s) { if ((s) < 0) LOG_ERROR; } // used for 'ioctl()' calls #define FATALERRNO (errno != EAGAIN && errno != EINTR) @@ -108,14 +111,14 @@ private: int size, last; tIndex *index; cResumeFile resumeFile; - bool CatchUp(void); + bool CatchUp(int Index = -1); public: cIndexFile(const char *FileName, bool Record); ~cIndexFile(); bool Ok(void) { return index != NULL; } void Write(uchar PictureType, uchar FileNumber, int FileOffset); bool Get(int Index, uchar *FileNumber, int *FileOffset, uchar *PictureType = NULL, int *Length = NULL); - int GetNextIFrame(int Index, bool Forward, uchar *FileNumber = NULL, int *FileOffset = NULL, int *Length = NULL); + int GetNextIFrame(int Index, bool Forward, uchar *FileNumber = NULL, int *FileOffset = NULL, int *Length = NULL, bool StayOffEnd = false); int Get(uchar FileNumber, int FileOffset); int Last(void) { CatchUp(); return last; } int GetResume(void) { return resumeFile.Read(); } @@ -199,42 +202,48 @@ cIndexFile::~cIndexFile() delete fileName; } -bool cIndexFile::CatchUp(void) +bool cIndexFile::CatchUp(int Index) { if (index && f >= 0) { - struct stat buf; - if (fstat(f, &buf) == 0) { - int newLast = buf.st_size / sizeof(tIndex) - 1; - if (newLast > last) { - if (size <= newLast) { - size *= 2; - if (size <= newLast) - size = newLast + 1; - } - index = (tIndex *)realloc(index, size * sizeof(tIndex)); - if (index) { - int offset = (last + 1) * sizeof(tIndex); - int delta = (newLast - last) * sizeof(tIndex); - if (lseek(f, offset, SEEK_SET) == offset) { - if (safe_read(f, &index[last + 1], delta) != delta) { - esyslog(LOG_ERR, "ERROR: can't read from index"); - delete index; - index = NULL; - close(f); - f = -1; - } - last = newLast; - return true; - } - else - LOG_ERROR; - } - else - esyslog(LOG_ERR, "ERROR: can't realloc() index"); - } - } - else - LOG_ERROR; + for (int i = 0; i <= MAXINDEXCATCHUP && (Index < 0 || Index >= last); i++) { + struct stat buf; + if (fstat(f, &buf) == 0) { + int newLast = buf.st_size / sizeof(tIndex) - 1; + if (newLast > last) { + if (size <= newLast) { + size *= 2; + if (size <= newLast) + size = newLast + 1; + } + index = (tIndex *)realloc(index, size * sizeof(tIndex)); + if (index) { + int offset = (last + 1) * sizeof(tIndex); + int delta = (newLast - last) * sizeof(tIndex); + if (lseek(f, offset, SEEK_SET) == offset) { + if (safe_read(f, &index[last + 1], delta) != delta) { + esyslog(LOG_ERR, "ERROR: can't read from index"); + delete index; + index = NULL; + close(f); + f = -1; + break; + } + last = newLast; + } + else + LOG_ERROR; + } + else + esyslog(LOG_ERR, "ERROR: can't realloc() index"); + } + } + else + LOG_ERROR; + if (Index >= last) + sleep(1); + else + return true; + } } return false; } @@ -256,7 +265,7 @@ void cIndexFile::Write(uchar PictureType, uchar FileNumber, int FileOffset) bool cIndexFile::Get(int Index, uchar *FileNumber, int *FileOffset, uchar *PictureType, int *Length) { if (index) { - CatchUp(); + CatchUp(Index); if (Index >= 0 && Index <= last) { *FileNumber = index[Index].number; *FileOffset = index[Index].offset; @@ -276,7 +285,7 @@ bool cIndexFile::Get(int Index, uchar *FileNumber, int *FileOffset, uchar *Pictu return false; } -int cIndexFile::GetNextIFrame(int Index, bool Forward, uchar *FileNumber, int *FileOffset, int *Length) +int cIndexFile::GetNextIFrame(int Index, bool Forward, uchar *FileNumber, int *FileOffset, int *Length, bool StayOffEnd) { if (index) { if (Forward) @@ -284,7 +293,7 @@ int cIndexFile::GetNextIFrame(int Index, bool Forward, uchar *FileNumber, int *F int d = Forward ? 1 : -1; for (;;) { Index += d; - if (Index >= 0 && Index <= last) { + if (Index >= 0 && Index < last - ((Forward && StayOffEnd) ? 100 : 0)) { if (index[Index].type == I_FRAME) { if (FileNumber) *FileNumber = index[Index].number; @@ -1049,17 +1058,26 @@ void cReplayBuffer::Input(void) if (playMode == pmFast || (playMode == pmSlow && playDir == pdBackward)) { uchar FileNumber; int FileOffset, Length; - int Index = index->GetNextIFrame(readIndex, playDir == pdForward, &FileNumber, &FileOffset, &Length); + int Index = index->GetNextIFrame(readIndex, playDir == pdForward, &FileNumber, &FileOffset, &Length, true); if (Index >= 0) { if (!NextFile(FileNumber, FileOffset)) break; } else { - Play(); + // 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 + CHECK(ioctl(audioDev, AUDIO_SET_AV_SYNC, true)); + CHECK(ioctl(videoDev, VIDEO_CONTINUE)); + playMode = pmPlay; + playDir = pdForward; continue; } readIndex = Index; r = ReadFrame(replayFile, b, Length, sizeof(b)); + // must call StripAudioPackets() here because the buffer is not emptied + // when falling back from "fast forward" to "play" (see above) + StripAudioPackets(b, r); } else if (index) { uchar FileNumber; @@ -1205,17 +1223,11 @@ void cReplayBuffer::SkipSeconds(int Seconds) Empty(true); int Index = writeIndex; if (Index >= 0) { - if (Seconds < 0) { - int sec = index->Last() / FRAMESPERSEC; - if (Seconds < -sec) - Seconds = -sec; - } - Index += Seconds * FRAMESPERSEC; - if (Index < 0) - Index = 1; // not '0', to allow GetNextIFrame() below to work! - uchar FileNumber; - int FileOffset; - readIndex = writeIndex = index->GetNextIFrame(Index, false, &FileNumber, &FileOffset) - 1; // Input() will first increment it! + Index = max(Index + Seconds * FRAMESPERSEC, 0); + if (Index > 0) + Index = index->GetNextIFrame(Index, false, NULL, NULL, NULL, true); + if (Index >= 0) + readIndex = writeIndex = Index - 1; // Input() will first increment it! } Empty(false); Play(); @@ -1250,9 +1262,9 @@ void cReplayBuffer::GetIndex(int &Current, int &Total, bool SnapToIFrame) { if (index) { if (playMode == pmStill) - Current = readIndex; + Current = max(readIndex, 0); else { - Current = writeIndex; + Current = max(writeIndex, 0); if (SnapToIFrame) { int i1 = index->GetNextIFrame(Current + 1, false); int i2 = index->GetNextIFrame(Current, true); diff --git a/thread.c b/thread.c index 878d769a..b51489ec 100644 --- a/thread.c +++ b/thread.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: thread.c 1.14 2001/10/20 10:26:35 kls Exp $ + * $Id: thread.c 1.15 2001/10/21 12:25:31 kls Exp $ */ #include "thread.h" @@ -161,7 +161,7 @@ void cThread::Cancel(int WaitSeconds) bool cThread::Lock(void) { - if (!lockingPid || lockingPid != getpid()) { + if (getpid() != lockingPid || !locked) { Mutex.Lock(); lockingPid = getpid(); }