1
0
mirror of https://github.com/VDR4Arch/vdr.git synced 2023-10-10 13:36:52 +02:00

Fixed handling trick modes near the beginning and end of a recording

This commit is contained in:
Klaus Schmidinger 2001-10-21 13:36:27 +02:00
parent 9fc8c13d60
commit 74016967e4
3 changed files with 71 additions and 58 deletions

View File

@ -787,7 +787,7 @@ Video Disk Recorder Revision History
- Made the volume, mute and power keys work when a menu is active, too (thanks - Made the volume, mute and power keys work when a menu is active, too (thanks
to Matthias Weingart). 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 - Implemented a lock file to prevent more than one instance of VDR from removing
files from the video directory at the same time. files from the video directory at the same time.
@ -828,3 +828,4 @@ Video Disk Recorder Revision History
(thanks to Helmut Schächner). (thanks to Helmut Schächner).
- Fixed reading timers.conf and channels.conf that contain blanks after numeric - Fixed reading timers.conf and channels.conf that contain blanks after numeric
values. values.
- Fixed handling trick modes near the beginning and end of a recording.

122
dvbapi.c
View File

@ -7,7 +7,7 @@
* DVD support initially written by Andreas Schultz <aschultz@warp10.net> * DVD support initially written by Andreas Schultz <aschultz@warp10.net>
* based on dvdplayer-0.5 by Matjaz Thaler <matjaz.thaler@guest.arnes.si> * based on dvdplayer-0.5 by Matjaz Thaler <matjaz.thaler@guest.arnes.si>
* *
* $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 //#define DVDDEBUG 1
@ -72,6 +72,9 @@ extern "C" {
// is broken: // is broken:
#define MAXBROKENTIMEOUT 30 // seconds #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 CHECK(s) { if ((s) < 0) LOG_ERROR; } // used for 'ioctl()' calls
#define FATALERRNO (errno != EAGAIN && errno != EINTR) #define FATALERRNO (errno != EAGAIN && errno != EINTR)
@ -108,14 +111,14 @@ private:
int size, last; int size, last;
tIndex *index; tIndex *index;
cResumeFile resumeFile; cResumeFile resumeFile;
bool CatchUp(void); bool CatchUp(int Index = -1);
public: public:
cIndexFile(const char *FileName, bool Record); cIndexFile(const char *FileName, bool Record);
~cIndexFile(); ~cIndexFile();
bool Ok(void) { return index != NULL; } bool Ok(void) { return index != NULL; }
void Write(uchar PictureType, uchar FileNumber, int FileOffset); void Write(uchar PictureType, uchar FileNumber, int FileOffset);
bool Get(int Index, uchar *FileNumber, int *FileOffset, uchar *PictureType = NULL, int *Length = NULL); 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 Get(uchar FileNumber, int FileOffset);
int Last(void) { CatchUp(); return last; } int Last(void) { CatchUp(); return last; }
int GetResume(void) { return resumeFile.Read(); } int GetResume(void) { return resumeFile.Read(); }
@ -199,42 +202,48 @@ cIndexFile::~cIndexFile()
delete fileName; delete fileName;
} }
bool cIndexFile::CatchUp(void) bool cIndexFile::CatchUp(int Index)
{ {
if (index && f >= 0) { if (index && f >= 0) {
struct stat buf; for (int i = 0; i <= MAXINDEXCATCHUP && (Index < 0 || Index >= last); i++) {
if (fstat(f, &buf) == 0) { struct stat buf;
int newLast = buf.st_size / sizeof(tIndex) - 1; if (fstat(f, &buf) == 0) {
if (newLast > last) { int newLast = buf.st_size / sizeof(tIndex) - 1;
if (size <= newLast) { if (newLast > last) {
size *= 2; if (size <= newLast) {
if (size <= newLast) size *= 2;
size = newLast + 1; if (size <= newLast)
} size = newLast + 1;
index = (tIndex *)realloc(index, size * sizeof(tIndex)); }
if (index) { index = (tIndex *)realloc(index, size * sizeof(tIndex));
int offset = (last + 1) * sizeof(tIndex); if (index) {
int delta = (newLast - last) * sizeof(tIndex); int offset = (last + 1) * sizeof(tIndex);
if (lseek(f, offset, SEEK_SET) == offset) { int delta = (newLast - last) * sizeof(tIndex);
if (safe_read(f, &index[last + 1], delta) != delta) { if (lseek(f, offset, SEEK_SET) == offset) {
esyslog(LOG_ERR, "ERROR: can't read from index"); if (safe_read(f, &index[last + 1], delta) != delta) {
delete index; esyslog(LOG_ERR, "ERROR: can't read from index");
index = NULL; delete index;
close(f); index = NULL;
f = -1; close(f);
} f = -1;
last = newLast; break;
return true; }
} last = newLast;
else }
LOG_ERROR; else
} LOG_ERROR;
else }
esyslog(LOG_ERR, "ERROR: can't realloc() index"); else
} esyslog(LOG_ERR, "ERROR: can't realloc() index");
} }
else }
LOG_ERROR; else
LOG_ERROR;
if (Index >= last)
sleep(1);
else
return true;
}
} }
return false; 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) bool cIndexFile::Get(int Index, uchar *FileNumber, int *FileOffset, uchar *PictureType, int *Length)
{ {
if (index) { if (index) {
CatchUp(); CatchUp(Index);
if (Index >= 0 && Index <= last) { if (Index >= 0 && Index <= last) {
*FileNumber = index[Index].number; *FileNumber = index[Index].number;
*FileOffset = index[Index].offset; *FileOffset = index[Index].offset;
@ -276,7 +285,7 @@ bool cIndexFile::Get(int Index, uchar *FileNumber, int *FileOffset, uchar *Pictu
return false; 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 (index) {
if (Forward) if (Forward)
@ -284,7 +293,7 @@ int cIndexFile::GetNextIFrame(int Index, bool Forward, uchar *FileNumber, int *F
int d = Forward ? 1 : -1; int d = Forward ? 1 : -1;
for (;;) { for (;;) {
Index += d; Index += d;
if (Index >= 0 && Index <= last) { if (Index >= 0 && Index < last - ((Forward && StayOffEnd) ? 100 : 0)) {
if (index[Index].type == I_FRAME) { if (index[Index].type == I_FRAME) {
if (FileNumber) if (FileNumber)
*FileNumber = index[Index].number; *FileNumber = index[Index].number;
@ -1049,17 +1058,26 @@ void cReplayBuffer::Input(void)
if (playMode == pmFast || (playMode == pmSlow && playDir == pdBackward)) { if (playMode == pmFast || (playMode == pmSlow && playDir == pdBackward)) {
uchar FileNumber; uchar FileNumber;
int FileOffset, Length; 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 (Index >= 0) {
if (!NextFile(FileNumber, FileOffset)) if (!NextFile(FileNumber, FileOffset))
break; break;
} }
else { 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; continue;
} }
readIndex = Index; readIndex = Index;
r = ReadFrame(replayFile, b, Length, sizeof(b)); 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) { else if (index) {
uchar FileNumber; uchar FileNumber;
@ -1205,17 +1223,11 @@ void cReplayBuffer::SkipSeconds(int Seconds)
Empty(true); Empty(true);
int Index = writeIndex; int Index = writeIndex;
if (Index >= 0) { if (Index >= 0) {
if (Seconds < 0) { Index = max(Index + Seconds * FRAMESPERSEC, 0);
int sec = index->Last() / FRAMESPERSEC; if (Index > 0)
if (Seconds < -sec) Index = index->GetNextIFrame(Index, false, NULL, NULL, NULL, true);
Seconds = -sec; if (Index >= 0)
} readIndex = writeIndex = Index - 1; // Input() will first increment it!
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!
} }
Empty(false); Empty(false);
Play(); Play();
@ -1250,9 +1262,9 @@ void cReplayBuffer::GetIndex(int &Current, int &Total, bool SnapToIFrame)
{ {
if (index) { if (index) {
if (playMode == pmStill) if (playMode == pmStill)
Current = readIndex; Current = max(readIndex, 0);
else { else {
Current = writeIndex; Current = max(writeIndex, 0);
if (SnapToIFrame) { if (SnapToIFrame) {
int i1 = index->GetNextIFrame(Current + 1, false); int i1 = index->GetNextIFrame(Current + 1, false);
int i2 = index->GetNextIFrame(Current, true); int i2 = index->GetNextIFrame(Current, true);

View File

@ -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: 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" #include "thread.h"
@ -161,7 +161,7 @@ void cThread::Cancel(int WaitSeconds)
bool cThread::Lock(void) bool cThread::Lock(void)
{ {
if (!lockingPid || lockingPid != getpid()) { if (getpid() != lockingPid || !locked) {
Mutex.Lock(); Mutex.Lock();
lockingPid = getpid(); lockingPid = getpid();
} }