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:
parent
9fc8c13d60
commit
74016967e4
3
HISTORY
3
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
|
- 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
122
dvbapi.c
@ -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);
|
||||||
|
4
thread.c
4
thread.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: 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();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user