mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
The new class cUnbufferedFile is used for the recording files to avoid thrashing the file system cache
This commit is contained in:
parent
998e3bd2c7
commit
697261c981
@ -1520,3 +1520,6 @@ Nicolas Huillard <nhuillard@e-dition.fr>
|
|||||||
|
|
||||||
Patrick Fischer <patrick_fischer@gmx.de>
|
Patrick Fischer <patrick_fischer@gmx.de>
|
||||||
for reporting an error in the cFilter example in PLUGINS.html
|
for reporting an error in the cFilter example in PLUGINS.html
|
||||||
|
|
||||||
|
Ralf Müller <ralf@bj-ig.de>
|
||||||
|
for a patch that was used to implement cUnbufferedFile
|
||||||
|
4
HISTORY
4
HISTORY
@ -3886,7 +3886,7 @@ Video Disk Recorder Revision History
|
|||||||
- The 'sub-title' and 'bottom text' in the CAM menu can now consist of several lines.
|
- The 'sub-title' and 'bottom text' in the CAM menu can now consist of several lines.
|
||||||
- Improved the CAM enquiry menu.
|
- Improved the CAM enquiry menu.
|
||||||
|
|
||||||
2005-10-30: Version 1.3.35
|
2005-10-31: Version 1.3.35
|
||||||
|
|
||||||
- Updated 'sources.conf' (thanks to Philip Prindeville).
|
- Updated 'sources.conf' (thanks to Philip Prindeville).
|
||||||
- Now using daemon() instead of fork() to run VDR in daemon mode (thanks to
|
- Now using daemon() instead of fork() to run VDR in daemon mode (thanks to
|
||||||
@ -3910,3 +3910,5 @@ Video Disk Recorder Revision History
|
|||||||
- Updated the Greek OSD texts (thanks to Dimitrios Dimitrakos).
|
- Updated the Greek OSD texts (thanks to Dimitrios Dimitrakos).
|
||||||
- Updated the French OSD texts (thanks to Nicolas Huillard).
|
- Updated the French OSD texts (thanks to Nicolas Huillard).
|
||||||
- Fixed the cFilter example in PLUGINS.html (reported by Patrick Fischer).
|
- Fixed the cFilter example in PLUGINS.html (reported by Patrick Fischer).
|
||||||
|
- The new class cUnbufferedFile is used for the recording files to avoid
|
||||||
|
trashing the file system cache (based on a patch by Ralf Müller).
|
||||||
|
12
cutter.c
12
cutter.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: cutter.c 1.10 2005/08/14 10:51:54 kls Exp $
|
* $Id: cutter.c 1.11 2005/10/31 12:26:44 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "cutter.h"
|
#include "cutter.h"
|
||||||
@ -18,7 +18,7 @@
|
|||||||
class cCuttingThread : public cThread {
|
class cCuttingThread : public cThread {
|
||||||
private:
|
private:
|
||||||
const char *error;
|
const char *error;
|
||||||
int fromFile, toFile;
|
cUnbufferedFile *fromFile, *toFile;
|
||||||
cFileName *fromFileName, *toFileName;
|
cFileName *fromFileName, *toFileName;
|
||||||
cIndexFile *fromIndex, *toIndex;
|
cIndexFile *fromIndex, *toIndex;
|
||||||
cMarks fromMarks, toMarks;
|
cMarks fromMarks, toMarks;
|
||||||
@ -34,7 +34,7 @@ cCuttingThread::cCuttingThread(const char *FromFileName, const char *ToFileName)
|
|||||||
:cThread("video cutting")
|
:cThread("video cutting")
|
||||||
{
|
{
|
||||||
error = NULL;
|
error = NULL;
|
||||||
fromFile = toFile = -1;
|
fromFile = toFile = NULL;
|
||||||
fromFileName = toFileName = NULL;
|
fromFileName = toFileName = NULL;
|
||||||
fromIndex = toIndex = NULL;
|
fromIndex = toIndex = NULL;
|
||||||
if (fromMarks.Load(FromFileName) && fromMarks.Count()) {
|
if (fromMarks.Load(FromFileName) && fromMarks.Count()) {
|
||||||
@ -64,7 +64,7 @@ void cCuttingThread::Action(void)
|
|||||||
if (Mark) {
|
if (Mark) {
|
||||||
fromFile = fromFileName->Open();
|
fromFile = fromFileName->Open();
|
||||||
toFile = toFileName->Open();
|
toFile = toFileName->Open();
|
||||||
if (fromFile < 0 || toFile < 0)
|
if (!fromFile || !toFile)
|
||||||
return;
|
return;
|
||||||
int Index = Mark->position;
|
int Index = Mark->position;
|
||||||
Mark = fromMarks.Next(Mark);
|
Mark = fromMarks.Next(Mark);
|
||||||
@ -92,7 +92,7 @@ void cCuttingThread::Action(void)
|
|||||||
fromFile = fromFileName->SetOffset(FileNumber, FileOffset);
|
fromFile = fromFileName->SetOffset(FileNumber, FileOffset);
|
||||||
CurrentFileNumber = FileNumber;
|
CurrentFileNumber = FileNumber;
|
||||||
}
|
}
|
||||||
if (fromFile >= 0) {
|
if (fromFile) {
|
||||||
int len = ReadFrame(fromFile, buffer, Length, sizeof(buffer));
|
int len = ReadFrame(fromFile, buffer, Length, sizeof(buffer));
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
error = "ReadFrame";
|
error = "ReadFrame";
|
||||||
@ -131,7 +131,7 @@ void cCuttingThread::Action(void)
|
|||||||
cutIn = false;
|
cutIn = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (safe_write(toFile, buffer, Length) < 0) {
|
if (toFile->Write(buffer, Length) < 0) {
|
||||||
error = "safe_write";
|
error = "safe_write";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
30
dvbplayer.c
30
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 1.40 2005/08/29 15:43:30 kls Exp $
|
* $Id: dvbplayer.c 1.41 2005/10/31 12:33:48 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dvbplayer.h"
|
#include "dvbplayer.h"
|
||||||
@ -74,7 +74,7 @@ int cBackTrace::Get(bool Forward)
|
|||||||
|
|
||||||
class cNonBlockingFileReader : public cThread {
|
class cNonBlockingFileReader : public cThread {
|
||||||
private:
|
private:
|
||||||
int f;
|
cUnbufferedFile *f;
|
||||||
uchar *buffer;
|
uchar *buffer;
|
||||||
int wanted;
|
int wanted;
|
||||||
int length;
|
int length;
|
||||||
@ -86,14 +86,14 @@ public:
|
|||||||
cNonBlockingFileReader(void);
|
cNonBlockingFileReader(void);
|
||||||
~cNonBlockingFileReader();
|
~cNonBlockingFileReader();
|
||||||
void Clear(void);
|
void Clear(void);
|
||||||
int Read(int FileHandle, uchar *Buffer, int Length);
|
int Read(cUnbufferedFile *File, uchar *Buffer, int Length);
|
||||||
bool Reading(void) { return buffer; }
|
bool Reading(void) { return buffer; }
|
||||||
};
|
};
|
||||||
|
|
||||||
cNonBlockingFileReader::cNonBlockingFileReader(void)
|
cNonBlockingFileReader::cNonBlockingFileReader(void)
|
||||||
:cThread("non blocking file reader")
|
:cThread("non blocking file reader")
|
||||||
{
|
{
|
||||||
f = -1;
|
f = NULL;
|
||||||
buffer = NULL;
|
buffer = NULL;
|
||||||
wanted = length = 0;
|
wanted = length = 0;
|
||||||
hasData = false;
|
hasData = false;
|
||||||
@ -110,7 +110,7 @@ cNonBlockingFileReader::~cNonBlockingFileReader()
|
|||||||
void cNonBlockingFileReader::Clear(void)
|
void cNonBlockingFileReader::Clear(void)
|
||||||
{
|
{
|
||||||
Lock();
|
Lock();
|
||||||
f = -1;
|
f = NULL;
|
||||||
free(buffer);
|
free(buffer);
|
||||||
buffer = NULL;
|
buffer = NULL;
|
||||||
wanted = length = 0;
|
wanted = length = 0;
|
||||||
@ -119,7 +119,7 @@ void cNonBlockingFileReader::Clear(void)
|
|||||||
newSet.Signal();
|
newSet.Signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
int cNonBlockingFileReader::Read(int FileHandle, uchar *Buffer, int Length)
|
int cNonBlockingFileReader::Read(cUnbufferedFile *File, uchar *Buffer, int Length)
|
||||||
{
|
{
|
||||||
if (hasData && buffer) {
|
if (hasData && buffer) {
|
||||||
if (buffer != Buffer) {
|
if (buffer != Buffer) {
|
||||||
@ -131,7 +131,7 @@ int cNonBlockingFileReader::Read(int FileHandle, uchar *Buffer, int Length)
|
|||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
f = FileHandle;
|
f = File;
|
||||||
buffer = Buffer;
|
buffer = Buffer;
|
||||||
wanted = Length;
|
wanted = Length;
|
||||||
length = 0;
|
length = 0;
|
||||||
@ -146,8 +146,8 @@ void cNonBlockingFileReader::Action(void)
|
|||||||
{
|
{
|
||||||
while (Running()) {
|
while (Running()) {
|
||||||
Lock();
|
Lock();
|
||||||
if (!hasData && f >= 0 && buffer) {
|
if (!hasData && f && buffer) {
|
||||||
int r = safe_read(f, buffer + length, wanted - length);
|
int r = f->Read(buffer + length, wanted - length);
|
||||||
if (r >= 0) {
|
if (r >= 0) {
|
||||||
length += r;
|
length += r;
|
||||||
if (!r || length == wanted) // r == 0 means EOF
|
if (!r || length == wanted) // r == 0 means EOF
|
||||||
@ -181,7 +181,7 @@ private:
|
|||||||
cBackTrace *backTrace;
|
cBackTrace *backTrace;
|
||||||
cFileName *fileName;
|
cFileName *fileName;
|
||||||
cIndexFile *index;
|
cIndexFile *index;
|
||||||
int replayFile;
|
cUnbufferedFile *replayFile;
|
||||||
bool eof;
|
bool eof;
|
||||||
bool firstPacket;
|
bool firstPacket;
|
||||||
ePlayModes playMode;
|
ePlayModes playMode;
|
||||||
@ -237,7 +237,7 @@ cDvbPlayer::cDvbPlayer(const char *FileName)
|
|||||||
isyslog("replay %s", FileName);
|
isyslog("replay %s", FileName);
|
||||||
fileName = new cFileName(FileName, false);
|
fileName = new cFileName(FileName, false);
|
||||||
replayFile = fileName->Open();
|
replayFile = fileName->Open();
|
||||||
if (replayFile < 0)
|
if (!replayFile)
|
||||||
return;
|
return;
|
||||||
ringBuffer = new cRingBufferFrame(PLAYERBUFSIZE);
|
ringBuffer = new cRingBufferFrame(PLAYERBUFSIZE);
|
||||||
// Create the index file:
|
// Create the index file:
|
||||||
@ -302,10 +302,10 @@ bool cDvbPlayer::NextFile(uchar FileNumber, int FileOffset)
|
|||||||
{
|
{
|
||||||
if (FileNumber > 0)
|
if (FileNumber > 0)
|
||||||
replayFile = fileName->SetOffset(FileNumber, FileOffset);
|
replayFile = fileName->SetOffset(FileNumber, FileOffset);
|
||||||
else if (replayFile >= 0 && eof)
|
else if (replayFile && eof)
|
||||||
replayFile = fileName->NextFile();
|
replayFile = fileName->NextFile();
|
||||||
eof = false;
|
eof = false;
|
||||||
return replayFile >= 0;
|
return replayFile != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cDvbPlayer::Resume(void)
|
int cDvbPlayer::Resume(void)
|
||||||
@ -342,7 +342,7 @@ bool cDvbPlayer::Save(void)
|
|||||||
void cDvbPlayer::Activate(bool On)
|
void cDvbPlayer::Activate(bool On)
|
||||||
{
|
{
|
||||||
if (On) {
|
if (On) {
|
||||||
if (replayFile >= 0)
|
if (replayFile)
|
||||||
Start();
|
Start();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -376,7 +376,7 @@ void cDvbPlayer::Action(void)
|
|||||||
// Read the next frame from the file:
|
// Read the next frame from the file:
|
||||||
|
|
||||||
if (playMode != pmStill && playMode != pmPause) {
|
if (playMode != pmStill && playMode != pmPause) {
|
||||||
if (!readFrame && (replayFile >= 0 || readIndex >= 0)) {
|
if (!readFrame && (replayFile || readIndex >= 0)) {
|
||||||
if (!nonBlockingFileReader->Reading()) {
|
if (!nonBlockingFileReader->Reading()) {
|
||||||
if (playMode == pmFast || (playMode == pmSlow && playDir == pdBackward)) {
|
if (playMode == pmFast || (playMode == pmSlow && playDir == pdBackward)) {
|
||||||
uchar FileNumber;
|
uchar FileNumber;
|
||||||
|
12
recorder.c
12
recorder.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: recorder.c 1.15 2005/08/14 10:53:28 kls Exp $
|
* $Id: recorder.c 1.16 2005/10/31 12:35:29 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
@ -28,7 +28,7 @@ private:
|
|||||||
cIndexFile *index;
|
cIndexFile *index;
|
||||||
uchar pictureType;
|
uchar pictureType;
|
||||||
int fileSize;
|
int fileSize;
|
||||||
int recordFile;
|
cUnbufferedFile *recordFile;
|
||||||
time_t lastDiskSpaceCheck;
|
time_t lastDiskSpaceCheck;
|
||||||
bool RunningLowOnDiskSpace(void);
|
bool RunningLowOnDiskSpace(void);
|
||||||
bool NextFile(void);
|
bool NextFile(void);
|
||||||
@ -50,7 +50,7 @@ cFileWriter::cFileWriter(const char *FileName, cRemux *Remux)
|
|||||||
lastDiskSpaceCheck = time(NULL);
|
lastDiskSpaceCheck = time(NULL);
|
||||||
fileName = new cFileName(FileName, true);
|
fileName = new cFileName(FileName, true);
|
||||||
recordFile = fileName->Open();
|
recordFile = fileName->Open();
|
||||||
if (recordFile < 0)
|
if (!recordFile)
|
||||||
return;
|
return;
|
||||||
// Create the index file:
|
// Create the index file:
|
||||||
index = new cIndexFile(FileName, true);
|
index = new cIndexFile(FileName, true);
|
||||||
@ -81,13 +81,13 @@ bool cFileWriter::RunningLowOnDiskSpace(void)
|
|||||||
|
|
||||||
bool cFileWriter::NextFile(void)
|
bool cFileWriter::NextFile(void)
|
||||||
{
|
{
|
||||||
if (recordFile >= 0 && pictureType == I_FRAME) { // every file shall start with an I_FRAME
|
if (recordFile && pictureType == I_FRAME) { // every file shall start with an I_FRAME
|
||||||
if (fileSize > MEGABYTE(Setup.MaxVideoFileSize) || RunningLowOnDiskSpace()) {
|
if (fileSize > MEGABYTE(Setup.MaxVideoFileSize) || RunningLowOnDiskSpace()) {
|
||||||
recordFile = fileName->NextFile();
|
recordFile = fileName->NextFile();
|
||||||
fileSize = 0;
|
fileSize = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return recordFile >= 0;
|
return recordFile != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cFileWriter::Action(void)
|
void cFileWriter::Action(void)
|
||||||
@ -102,7 +102,7 @@ void cFileWriter::Action(void)
|
|||||||
if (NextFile()) {
|
if (NextFile()) {
|
||||||
if (index && pictureType != NO_PICTURE)
|
if (index && pictureType != NO_PICTURE)
|
||||||
index->Write(pictureType, fileName->Number(), fileSize);
|
index->Write(pictureType, fileName->Number(), fileSize);
|
||||||
if (safe_write(recordFile, p, Count) < 0) {
|
if (recordFile->Write(p, Count) < 0) {
|
||||||
LOG_ERROR_STR(fileName->Name());
|
LOG_ERROR_STR(fileName->Name());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
38
recording.c
38
recording.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: recording.c 1.121 2005/10/09 13:09:51 kls Exp $
|
* $Id: recording.c 1.122 2005/10/31 12:27:58 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "recording.h"
|
#include "recording.h"
|
||||||
@ -1258,7 +1258,7 @@ int cIndexFile::Get(uchar FileNumber, int FileOffset)
|
|||||||
|
|
||||||
cFileName::cFileName(const char *FileName, bool Record, bool Blocking)
|
cFileName::cFileName(const char *FileName, bool Record, bool Blocking)
|
||||||
{
|
{
|
||||||
file = -1;
|
file = NULL;
|
||||||
fileNumber = 0;
|
fileNumber = 0;
|
||||||
record = Record;
|
record = Record;
|
||||||
blocking = Blocking;
|
blocking = Blocking;
|
||||||
@ -1279,21 +1279,21 @@ cFileName::~cFileName()
|
|||||||
free(fileName);
|
free(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cFileName::Open(void)
|
cUnbufferedFile *cFileName::Open(void)
|
||||||
{
|
{
|
||||||
if (file < 0) {
|
if (!file) {
|
||||||
int BlockingFlag = blocking ? 0 : O_NONBLOCK;
|
int BlockingFlag = blocking ? 0 : O_NONBLOCK;
|
||||||
if (record) {
|
if (record) {
|
||||||
dsyslog("recording to '%s'", fileName);
|
dsyslog("recording to '%s'", fileName);
|
||||||
file = OpenVideoFile(fileName, O_RDWR | O_CREAT | BlockingFlag);
|
file = OpenVideoFile(fileName, O_RDWR | O_CREAT | BlockingFlag);
|
||||||
if (file < 0)
|
if (!file)
|
||||||
LOG_ERROR_STR(fileName);
|
LOG_ERROR_STR(fileName);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (access(fileName, R_OK) == 0) {
|
if (access(fileName, R_OK) == 0) {
|
||||||
dsyslog("playing '%s'", fileName);
|
dsyslog("playing '%s'", fileName);
|
||||||
file = open(fileName, O_RDONLY | BlockingFlag);
|
file = cUnbufferedFile::Create(fileName, O_RDONLY | BlockingFlag);
|
||||||
if (file < 0)
|
if (!file)
|
||||||
LOG_ERROR_STR(fileName);
|
LOG_ERROR_STR(fileName);
|
||||||
}
|
}
|
||||||
else if (errno != ENOENT)
|
else if (errno != ENOENT)
|
||||||
@ -1305,14 +1305,14 @@ int cFileName::Open(void)
|
|||||||
|
|
||||||
void cFileName::Close(void)
|
void cFileName::Close(void)
|
||||||
{
|
{
|
||||||
if (file >= 0) {
|
if (file) {
|
||||||
if ((record && CloseVideoFile(file) < 0) || (!record && close(file) < 0))
|
if ((record && CloseVideoFile(file) < 0) || (!record && file->Close() < 0))
|
||||||
LOG_ERROR_STR(fileName);
|
LOG_ERROR_STR(fileName);
|
||||||
file = -1;
|
file = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int cFileName::SetOffset(int Number, int Offset)
|
cUnbufferedFile *cFileName::SetOffset(int Number, int Offset)
|
||||||
{
|
{
|
||||||
if (fileNumber != Number)
|
if (fileNumber != Number)
|
||||||
Close();
|
Close();
|
||||||
@ -1337,23 +1337,23 @@ int cFileName::SetOffset(int Number, int Offset)
|
|||||||
}
|
}
|
||||||
else if (errno != ENOENT) { // something serious has happened
|
else if (errno != ENOENT) { // something serious has happened
|
||||||
LOG_ERROR_STR(fileName);
|
LOG_ERROR_STR(fileName);
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
// found a non existing file suffix
|
// found a non existing file suffix
|
||||||
}
|
}
|
||||||
if (Open() >= 0) {
|
if (Open() >= 0) {
|
||||||
if (!record && Offset >= 0 && lseek(file, Offset, SEEK_SET) != Offset) {
|
if (!record && Offset >= 0 && file->Seek(Offset, SEEK_SET) != Offset) {
|
||||||
LOG_ERROR_STR(fileName);
|
LOG_ERROR_STR(fileName);
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
esyslog("ERROR: max number of files (%d) exceeded", MAXFILESPERRECORDING);
|
esyslog("ERROR: max number of files (%d) exceeded", MAXFILESPERRECORDING);
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cFileName::NextFile(void)
|
cUnbufferedFile *cFileName::NextFile(void)
|
||||||
{
|
{
|
||||||
return SetOffset(fileNumber + 1);
|
return SetOffset(fileNumber + 1);
|
||||||
}
|
}
|
||||||
@ -1387,7 +1387,7 @@ int SecondsToFrames(int Seconds)
|
|||||||
|
|
||||||
// --- ReadFrame -------------------------------------------------------------
|
// --- ReadFrame -------------------------------------------------------------
|
||||||
|
|
||||||
int ReadFrame(int f, uchar *b, int Length, int Max)
|
int ReadFrame(cUnbufferedFile *f, uchar *b, int Length, int Max)
|
||||||
{
|
{
|
||||||
if (Length == -1)
|
if (Length == -1)
|
||||||
Length = Max; // this means we read up to EOF (see cIndex)
|
Length = Max; // this means we read up to EOF (see cIndex)
|
||||||
@ -1395,10 +1395,8 @@ int ReadFrame(int f, uchar *b, int Length, int Max)
|
|||||||
esyslog("ERROR: frame larger than buffer (%d > %d)", Length, Max);
|
esyslog("ERROR: frame larger than buffer (%d > %d)", Length, Max);
|
||||||
Length = Max;
|
Length = Max;
|
||||||
}
|
}
|
||||||
int r = safe_read(f, b, Length);
|
int r = f->Read(b, Length);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
LOG_ERROR;
|
LOG_ERROR;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
12
recording.h
12
recording.h
@ -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: recording.h 1.45 2005/10/01 10:24:41 kls Exp $
|
* $Id: recording.h 1.46 2005/10/31 12:27:12 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __RECORDING_H
|
#ifndef __RECORDING_H
|
||||||
@ -203,7 +203,7 @@ public:
|
|||||||
|
|
||||||
class cFileName {
|
class cFileName {
|
||||||
private:
|
private:
|
||||||
int file;
|
cUnbufferedFile *file;
|
||||||
int fileNumber;
|
int fileNumber;
|
||||||
char *fileName, *pFileNumber;
|
char *fileName, *pFileNumber;
|
||||||
bool record;
|
bool record;
|
||||||
@ -213,10 +213,10 @@ public:
|
|||||||
~cFileName();
|
~cFileName();
|
||||||
const char *Name(void) { return fileName; }
|
const char *Name(void) { return fileName; }
|
||||||
int Number(void) { return fileNumber; }
|
int Number(void) { return fileNumber; }
|
||||||
int Open(void);
|
cUnbufferedFile *Open(void);
|
||||||
void Close(void);
|
void Close(void);
|
||||||
int SetOffset(int Number, int Offset = 0);
|
cUnbufferedFile *SetOffset(int Number, int Offset = 0);
|
||||||
int NextFile(void);
|
cUnbufferedFile *NextFile(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
cString IndexToHMSF(int Index, bool WithFrame = false);
|
cString IndexToHMSF(int Index, bool WithFrame = false);
|
||||||
@ -226,7 +226,7 @@ int HMSFToIndex(const char *HMSF);
|
|||||||
int SecondsToFrames(int Seconds); //XXX+ ->player???
|
int SecondsToFrames(int Seconds); //XXX+ ->player???
|
||||||
// Returns the number of frames corresponding to the given number of seconds.
|
// Returns the number of frames corresponding to the given number of seconds.
|
||||||
|
|
||||||
int ReadFrame(int f, uchar *b, int Length, int Max);
|
int ReadFrame(cUnbufferedFile *f, uchar *b, int Length, int Max);
|
||||||
|
|
||||||
char *ExchangeChars(char *s, bool ToFileSystem);
|
char *ExchangeChars(char *s, bool ToFileSystem);
|
||||||
// Exchanges the characters in the given string to or from a file system
|
// Exchanges the characters in the given string to or from a file system
|
||||||
|
125
tools.c
125
tools.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: tools.c 1.99 2005/09/25 12:56:06 kls Exp $
|
* $Id: tools.c 1.100 2005/10/31 12:56:15 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
@ -836,6 +836,129 @@ bool cSafeFile::Close(void)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- cUnbufferedFile -------------------------------------------------------
|
||||||
|
|
||||||
|
#define READ_AHEAD MEGABYTE(2)
|
||||||
|
#define WRITE_BUFFER MEGABYTE(10)
|
||||||
|
|
||||||
|
cUnbufferedFile::cUnbufferedFile(void)
|
||||||
|
{
|
||||||
|
fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cUnbufferedFile::~cUnbufferedFile()
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
int cUnbufferedFile::Open(const char *FileName, int Flags, mode_t Mode)
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
fd = open(FileName, Flags, Mode);
|
||||||
|
begin = end = ahead = -1;
|
||||||
|
written = 0;
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cUnbufferedFile::Close(void)
|
||||||
|
{
|
||||||
|
if (fd >= 0) {
|
||||||
|
if (ahead > end)
|
||||||
|
end = ahead;
|
||||||
|
if (begin >= 0 && end > begin) {
|
||||||
|
//dsyslog("close buffer: %d (flush: %d bytes, %ld-%ld)", fd, written, begin, end);
|
||||||
|
if (written)
|
||||||
|
fdatasync(fd);
|
||||||
|
posix_fadvise(fd, begin, end - begin, POSIX_FADV_DONTNEED);
|
||||||
|
}
|
||||||
|
begin = end = ahead = -1;
|
||||||
|
written = 0;
|
||||||
|
}
|
||||||
|
int OldFd = fd;
|
||||||
|
fd = -1;
|
||||||
|
return close(OldFd);
|
||||||
|
}
|
||||||
|
|
||||||
|
off_t cUnbufferedFile::Seek(off_t Offset, int Whence)
|
||||||
|
{
|
||||||
|
if (fd >= 0)
|
||||||
|
return lseek(fd, Offset, Whence);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t cUnbufferedFile::Read(void *Data, size_t Size)
|
||||||
|
{
|
||||||
|
if (fd >= 0) {
|
||||||
|
off_t pos = lseek(fd, 0, SEEK_CUR);
|
||||||
|
// jump forward - adjust end position
|
||||||
|
if (pos > end)
|
||||||
|
end = pos;
|
||||||
|
// after adjusting end - don't clear more than previously requested
|
||||||
|
if (end > ahead)
|
||||||
|
end = ahead;
|
||||||
|
// jump backward - drop read ahead of previous run
|
||||||
|
if (pos < begin)
|
||||||
|
end = ahead;
|
||||||
|
if (begin >= 0 && end > begin)
|
||||||
|
posix_fadvise(fd, begin - KILOBYTE(200), end - begin + KILOBYTE(200), POSIX_FADV_DONTNEED);//XXX macros/parameters???
|
||||||
|
begin = pos;
|
||||||
|
ssize_t bytesRead = safe_read(fd, Data, Size);
|
||||||
|
if (bytesRead > 0) {
|
||||||
|
pos += bytesRead;
|
||||||
|
end = pos;
|
||||||
|
// this seems to trigger a non blocking read - this
|
||||||
|
// may or may not have been finished when we will be called next time.
|
||||||
|
// If it is not finished we can't release the not yet filled buffers.
|
||||||
|
// So this is commented out till we find a better solution.
|
||||||
|
//posix_fadvise(fd, pos, READ_AHEAD, POSIX_FADV_WILLNEED);
|
||||||
|
ahead = pos + READ_AHEAD;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
end = pos;
|
||||||
|
return bytesRead;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t cUnbufferedFile::Write(const void *Data, size_t Size)
|
||||||
|
{
|
||||||
|
if (fd >=0) {
|
||||||
|
off_t pos = lseek(fd, 0, SEEK_CUR);
|
||||||
|
ssize_t bytesWritten = safe_write(fd, Data, Size);
|
||||||
|
if (bytesWritten >= 0) {
|
||||||
|
written += bytesWritten;
|
||||||
|
if (begin >= 0) {
|
||||||
|
if (pos < begin)
|
||||||
|
begin = pos;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
begin = pos;
|
||||||
|
if (pos + bytesWritten > end)
|
||||||
|
end = pos + bytesWritten;
|
||||||
|
if (written > WRITE_BUFFER) {
|
||||||
|
//dsyslog("flush buffer: %d (%d bytes, %ld-%ld)", fd, written, begin, end);
|
||||||
|
fdatasync(fd);
|
||||||
|
if (begin >= 0 && end > begin)
|
||||||
|
posix_fadvise(fd, begin, end - begin, POSIX_FADV_DONTNEED);
|
||||||
|
begin = end = -1;
|
||||||
|
written = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bytesWritten;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cUnbufferedFile *cUnbufferedFile::Create(const char *FileName, int Flags, mode_t Mode)
|
||||||
|
{
|
||||||
|
cUnbufferedFile *File = new cUnbufferedFile;
|
||||||
|
if (File->Open(FileName, Flags, Mode) < 0) {
|
||||||
|
delete File;
|
||||||
|
File = NULL;
|
||||||
|
}
|
||||||
|
return File;
|
||||||
|
}
|
||||||
|
|
||||||
// --- cLockFile -------------------------------------------------------------
|
// --- cLockFile -------------------------------------------------------------
|
||||||
|
|
||||||
#define LOCKFILENAME ".lock-vdr"
|
#define LOCKFILENAME ".lock-vdr"
|
||||||
|
23
tools.h
23
tools.h
@ -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: tools.h 1.80 2005/10/09 11:13:06 kls Exp $
|
* $Id: tools.h 1.81 2005/10/31 12:54:36 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TOOLS_H
|
#ifndef __TOOLS_H
|
||||||
@ -198,6 +198,27 @@ public:
|
|||||||
bool Close(void);
|
bool Close(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// cUnbufferedFile is used for large files that are mainly written or read
|
||||||
|
/// in a streaming manner, and thus should not be cached.
|
||||||
|
|
||||||
|
class cUnbufferedFile {
|
||||||
|
private:
|
||||||
|
int fd;
|
||||||
|
off_t begin;
|
||||||
|
off_t end;
|
||||||
|
off_t ahead;
|
||||||
|
ssize_t written;
|
||||||
|
public:
|
||||||
|
cUnbufferedFile(void);
|
||||||
|
~cUnbufferedFile();
|
||||||
|
int Open(const char *FileName, int Flags, mode_t Mode = DEFFILEMODE);
|
||||||
|
int Close(void);
|
||||||
|
off_t Seek(off_t Offset, int Whence);
|
||||||
|
ssize_t Read(void *Data, size_t Size);
|
||||||
|
ssize_t Write(const void *Data, size_t Size);
|
||||||
|
static cUnbufferedFile *Create(const char *FileName, int Flags, mode_t Mode = DEFFILEMODE);
|
||||||
|
};
|
||||||
|
|
||||||
class cLockFile {
|
class cLockFile {
|
||||||
private:
|
private:
|
||||||
char *fileName;
|
char *fileName;
|
||||||
|
21
videodir.c
21
videodir.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: videodir.c 1.12 2005/08/06 09:53:21 kls Exp $
|
* $Id: videodir.c 1.13 2005/10/31 12:07:41 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "videodir.h"
|
#include "videodir.h"
|
||||||
@ -102,7 +102,7 @@ const char *cVideoDirectory::Adjust(const char *FileName)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int OpenVideoFile(const char *FileName, int Flags)
|
cUnbufferedFile *OpenVideoFile(const char *FileName, int Flags)
|
||||||
{
|
{
|
||||||
const char *ActualFileName = FileName;
|
const char *ActualFileName = FileName;
|
||||||
|
|
||||||
@ -110,7 +110,7 @@ int OpenVideoFile(const char *FileName, int Flags)
|
|||||||
if (strstr(FileName, VideoDirectory) != FileName) {
|
if (strstr(FileName, VideoDirectory) != FileName) {
|
||||||
esyslog("ERROR: %s not in %s", FileName, VideoDirectory);
|
esyslog("ERROR: %s not in %s", FileName, VideoDirectory);
|
||||||
errno = ENOENT; // must set 'errno' - any ideas for a better value?
|
errno = ENOENT; // must set 'errno' - any ideas for a better value?
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
// Are we going to create a new file?
|
// Are we going to create a new file?
|
||||||
if ((Flags & O_CREAT) != 0) {
|
if ((Flags & O_CREAT) != 0) {
|
||||||
@ -128,25 +128,26 @@ int OpenVideoFile(const char *FileName, int Flags)
|
|||||||
if (Dir.Stored()) {
|
if (Dir.Stored()) {
|
||||||
ActualFileName = Dir.Adjust(FileName);
|
ActualFileName = Dir.Adjust(FileName);
|
||||||
if (!MakeDirs(ActualFileName, false))
|
if (!MakeDirs(ActualFileName, false))
|
||||||
return -1; // errno has been set by MakeDirs()
|
return NULL; // errno has been set by MakeDirs()
|
||||||
if (symlink(ActualFileName, FileName) < 0) {
|
if (symlink(ActualFileName, FileName) < 0) {
|
||||||
LOG_ERROR_STR(FileName);
|
LOG_ERROR_STR(FileName);
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
ActualFileName = strdup(ActualFileName); // must survive Dir!
|
ActualFileName = strdup(ActualFileName); // must survive Dir!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int Result = open(ActualFileName, Flags, DEFFILEMODE);
|
cUnbufferedFile *File = cUnbufferedFile::Create(ActualFileName, Flags, DEFFILEMODE);
|
||||||
if (ActualFileName != FileName)
|
if (ActualFileName != FileName)
|
||||||
free((char *)ActualFileName);
|
free((char *)ActualFileName);
|
||||||
return Result;
|
return File;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CloseVideoFile(int FileHandle)
|
int CloseVideoFile(cUnbufferedFile *File)
|
||||||
{
|
{
|
||||||
// just in case we ever decide to do something special when closing the file!
|
int Result = File->Close();
|
||||||
return close(FileHandle);
|
delete File;
|
||||||
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RenameVideoFile(const char *OldName, const char *NewName)
|
bool RenameVideoFile(const char *OldName, const char *NewName)
|
||||||
|
@ -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: videodir.h 1.5 2004/12/26 11:52:56 kls Exp $
|
* $Id: videodir.h 1.6 2005/10/31 11:50:23 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __VIDEODIR_H
|
#ifndef __VIDEODIR_H
|
||||||
@ -15,8 +15,8 @@
|
|||||||
|
|
||||||
extern const char *VideoDirectory;
|
extern const char *VideoDirectory;
|
||||||
|
|
||||||
int OpenVideoFile(const char *FileName, int Flags);
|
cUnbufferedFile *OpenVideoFile(const char *FileName, int Flags);
|
||||||
int CloseVideoFile(int FileHandle);
|
int CloseVideoFile(cUnbufferedFile *File);
|
||||||
bool RenameVideoFile(const char *OldName, const char *NewName);
|
bool RenameVideoFile(const char *OldName, const char *NewName);
|
||||||
bool RemoveVideoFile(const char *FileName);
|
bool RemoveVideoFile(const char *FileName);
|
||||||
bool VideoFileSpaceAvailable(int SizeMB);
|
bool VideoFileSpaceAvailable(int SizeMB);
|
||||||
|
Loading…
Reference in New Issue
Block a user