summaryrefslogtreecommitdiff
path: root/recorder.c
diff options
context:
space:
mode:
authorKlaus Schmidinger <vdr@tvdr.de>2004-10-16 09:36:28 +0200
committerKlaus Schmidinger <vdr@tvdr.de>2004-10-16 09:36:28 +0200
commit6415cc900de3361925d22f879077be687fce3858 (patch)
tree98ab10cda016e125e33966e371ccfe01e5fd9bd1 /recorder.c
parent15030f6acece1060f9736f875fe3abbcf9392263 (diff)
downloadvdr-6415cc900de3361925d22f879077be687fce3858.tar.gz
vdr-6415cc900de3361925d22f879077be687fce3858.tar.bz2
Improved buffer handling
Diffstat (limited to 'recorder.c')
-rw-r--r--recorder.c170
1 files changed, 106 insertions, 64 deletions
diff --git a/recorder.c b/recorder.c
index 4270fbed..3508b0ae 100644
--- a/recorder.c
+++ b/recorder.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: recorder.c 1.10 2004/03/20 10:33:21 kls Exp $
+ * $Id: recorder.c 1.11 2004/10/16 09:23:01 kls Exp $
*/
#include <stdarg.h>
@@ -12,9 +12,7 @@
#include <unistd.h>
#include "recorder.h"
-// The size of the array used to buffer video data:
-// (must be larger than MINVIDEODATA - see remux.h)
-#define VIDEOBUFSIZE MEGABYTE(5)
+#define RECORDERBUFSIZE MEGABYTE(5)
// The maximum time we wait before assuming that a recorded video data stream
// is broken:
@@ -23,25 +21,35 @@
#define MINFREEDISKSPACE (512) // MB
#define DISKCHECKINTERVAL 100 // seconds
-cRecorder::cRecorder(const char *FileName, int Ca, int Priority, int VPid, int APid1, int APid2, int DPid1, int DPid2)
-:cReceiver(Ca, Priority, Setup.RecordDolbyDigital ? 5 : 3, VPid, APid1, APid2, DPid1, DPid2)
-,cThread("recording")
+class cFileWriter : public cThread {
+private:
+ cRemux *remux;
+ cFileName *fileName;
+ cIndexFile *index;
+ uchar pictureType;
+ int fileSize;
+ int recordFile;
+ bool active;
+ time_t lastDiskSpaceCheck;
+ bool RunningLowOnDiskSpace(void);
+ bool NextFile(void);
+protected:
+ virtual void Action(void);
+public:
+ cFileWriter(const char *FileName, cRemux *Remux);
+ virtual ~cFileWriter();
+ };
+
+cFileWriter::cFileWriter(const char *FileName, cRemux *Remux)
+:cThread("file writer")
{
- ringBuffer = NULL;
- remux = NULL;
+ active = false;
fileName = NULL;
+ remux = Remux;
index = NULL;
pictureType = NO_PICTURE;
fileSize = 0;
- active = false;
lastDiskSpaceCheck = time(NULL);
-
- // Make sure the disk is up and running:
-
- SpinUpDisk(FileName);
-
- ringBuffer = new cRingBufferLinear(VIDEOBUFSIZE, TS_SIZE * 2, true);
- remux = new cRemux(VPid, APid1, APid2, DPid1, DPid2, true);
fileName = new cFileName(FileName, true);
recordFile = fileName->Open();
if (recordFile < 0)
@@ -53,28 +61,15 @@ cRecorder::cRecorder(const char *FileName, int Ca, int Priority, int VPid, int A
// let's continue without index, so we'll at least have the recording
}
-cRecorder::~cRecorder()
+cFileWriter::~cFileWriter()
{
- Detach();
+ active = false;
+ Cancel(3);
delete index;
delete fileName;
- delete remux;
- delete ringBuffer;
}
-void cRecorder::Activate(bool On)
-{
- if (On) {
- if (recordFile >= 0)
- Start();
- }
- else if (active) {
- active = false;
- Cancel(3);
- }
-}
-
-bool cRecorder::RunningLowOnDiskSpace(void)
+bool cFileWriter::RunningLowOnDiskSpace(void)
{
if (time(NULL) > lastDiskSpaceCheck + DISKCHECKINTERVAL) {
int Free = FreeDiskSpaceMB(fileName->Name());
@@ -87,7 +82,7 @@ bool cRecorder::RunningLowOnDiskSpace(void)
return false;
}
-bool cRecorder::NextFile(void)
+bool cFileWriter::NextFile(void)
{
if (recordFile >= 0 && pictureType == I_FRAME) { // every file shall start with an I_FRAME
if (fileSize > MEGABYTE(Setup.MaxVideoFileSize) || RunningLowOnDiskSpace()) {
@@ -98,40 +93,29 @@ bool cRecorder::NextFile(void)
return recordFile >= 0;
}
-void cRecorder::Receive(uchar *Data, int Length)
-{
- int p = ringBuffer->Put(Data, Length);
- if (p != Length && active)
- ringBuffer->ReportOverflow(Length - p);
-}
-
-void cRecorder::Action(void)
+void cFileWriter::Action(void)
{
time_t t = time(NULL);
active = true;
while (active) {
- int r;
- const uchar *b = ringBuffer->Get(r);
- if (b) {
- int Count = r, Result;
- uchar *p = remux->Process(b, Count, Result, &pictureType);
- ringBuffer->Del(Count);
- if (p) {
- //XXX+ active??? see old version (Busy)
- if (!active && pictureType == I_FRAME) // finish the recording before the next 'I' frame
+ int Count;
+ uchar *p = remux->Get(Count, &pictureType);
+ if (p) {
+ //XXX+ active??? see old version (Busy)
+ if (!active && pictureType == I_FRAME) // finish the recording before the next 'I' frame
+ break;
+ if (NextFile()) {
+ if (index && pictureType != NO_PICTURE)
+ index->Write(pictureType, fileName->Number(), fileSize);
+ if (safe_write(recordFile, p, Count) < 0) {
+ LOG_ERROR_STR(fileName->Name());
break;
- if (NextFile()) {
- if (index && pictureType != NO_PICTURE)
- index->Write(pictureType, fileName->Number(), fileSize);
- if (safe_write(recordFile, p, Result) < 0) {
- LOG_ERROR_STR(fileName->Name());
- break;
- }
- fileSize += Result;
}
- else
- break;
+ fileSize += Count;
+ remux->Del(Count);
}
+ else
+ break;
t = time(NULL);
}
else if (time(NULL) - t > MAXBROKENTIMEOUT) {
@@ -139,7 +123,65 @@ void cRecorder::Action(void)
cThread::EmergencyExit(true);
t = time(NULL);
}
- else
- usleep(1); // this keeps the CPU load low
+ }
+ active = false;
+}
+
+cRecorder::cRecorder(const char *FileName, int Ca, int Priority, int VPid, int APid1, int APid2, int DPid1, int DPid2)
+:cReceiver(Ca, Priority, Setup.RecordDolbyDigital ? 5 : 3, VPid, APid1, APid2, DPid1, DPid2)
+,cThread("recording")
+{
+ active = false;
+
+ // Make sure the disk is up and running:
+
+ SpinUpDisk(FileName);
+
+ ringBuffer = new cRingBufferLinear(RECORDERBUFSIZE, TS_SIZE * 2, true, "Recorder");
+ ringBuffer->SetTimeouts(0, 100);
+ remux = new cRemux(VPid, APid1, APid2, DPid1, DPid2, true);
+ writer = new cFileWriter(FileName, remux);
+}
+
+cRecorder::~cRecorder()
+{
+ Detach();
+ delete writer;
+ delete remux;
+ delete ringBuffer;
+}
+
+void cRecorder::Activate(bool On)
+{
+ if (On) {
+ writer->Start();
+ Start();
+ }
+ else if (active) {
+ active = false;
+ Cancel(3);
+ }
+}
+
+void cRecorder::Receive(uchar *Data, int Length)
+{
+ if (active) {
+ int p = ringBuffer->Put(Data, Length);
+ if (p != Length && active)
+ ringBuffer->ReportOverflow(Length - p);
+ }
+}
+
+void cRecorder::Action(void)
+{
+ active = true;
+ while (active) {
+ int r;
+ uchar *b = ringBuffer->Get(r);
+ if (b) {
+ int Count = remux->Put(b, r);
+ if (Count)
+ ringBuffer->Del(Count);
+ }
}
}