vdr  2.6.1
recorder.c
Go to the documentation of this file.
1 /*
2  * recorder.c: The actual DVB recorder
3  *
4  * See the main source file 'vdr.c' for copyright information and
5  * how to reach the author.
6  *
7  * $Id: recorder.c 5.4 2021/06/19 14:21:16 kls Exp $
8  */
9 
10 #include "recorder.h"
11 #include "shutdown.h"
12 
13 #define RECORDERBUFSIZE (MEGABYTE(20) / TS_SIZE * TS_SIZE) // multiple of TS_SIZE
14 
15 // The maximum time we wait before assuming that a recorded video data stream
16 // is broken:
17 #define MAXBROKENTIMEOUT 30000 // milliseconds
18 
19 #define MINFREEDISKSPACE (512) // MB
20 #define DISKCHECKINTERVAL 100 // seconds
21 
22 static bool DebugChecks = false;
23 
24 // cTsChecker and cFrameChecker are used to detect errors in the recorded data stream.
25 // While cTsChecker checks the continuity counter of the incoming TS packets, cFrameChecker
26 // works on entire frames, checking their PTS (Presentation Time Stamps) to see whether
27 // all expected frames arrive. The resulting number of errors is not a precise value.
28 // If it is zero, the recording can be safely considered error free. The higher the value,
29 // the more damaged the recording is.
30 
31 // --- cTsChecker ------------------------------------------------------------
32 
33 #define TS_CC_UNKNOWN 0xFF
34 
35 class cTsChecker {
36 private:
38  int errors;
39  void Report(int Pid, const char *Message);
40 public:
41  cTsChecker(void);
42  void CheckTs(const uchar *Data, int Length);
43  int Errors(void) { return errors; }
44  };
45 
47 {
48  memset(counter, TS_CC_UNKNOWN, sizeof(counter));
49  errors = 0;
50 }
51 
52 void cTsChecker::Report(int Pid, const char *Message)
53 {
54  errors++;
55  if (DebugChecks)
56  fprintf(stderr, "%s: TS error #%d on PID %d (%s)\n", *TimeToString(time(NULL)), errors, Pid, Message);
57 }
58 
59 void cTsChecker::CheckTs(const uchar *Data, int Length)
60 {
61  int Pid = TsPid(Data);
62  uchar Cc = TsContinuityCounter(Data);
63  if (TsHasPayload(Data)) {
64  if (TsError(Data))
65  Report(Pid, "tei");
66  else if (TsIsScrambled(Data))
67  Report(Pid, "scrambled");
68  else {
69  uchar OldCc = counter[Pid];
70  if (OldCc != TS_CC_UNKNOWN) {
71  uchar NewCc = (OldCc + 1) & TS_CONT_CNT_MASK;
72  if (Cc != NewCc)
73  Report(Pid, "continuity");
74  }
75  }
76  }
77  counter[Pid] = Cc;
78 }
79 
80 // --- cFrameChecker ---------------------------------------------------------
81 
82 #define MAX_BACK_REFS 32
83 
85 private:
87  int64_t lastPts;
88  uint32_t backRefs;
90  int errors;
91  void Report(const char *Message, int NumErrors = 1);
92 public:
93  cFrameChecker(void);
94  void SetFrameDelta(int FrameDelta) { frameDelta = FrameDelta; }
95  void CheckFrame(const uchar *Data, int Length);
96  void ReportBroken(void);
97  int Errors(void) { return errors; }
98  };
99 
101 {
103  lastPts = -1;
104  backRefs = 0;
105  lastFwdRef = 0;
106  errors = 0;
107 }
108 
109 void cFrameChecker::Report(const char *Message, int NumErrors)
110 {
111  errors += NumErrors;
112  if (DebugChecks)
113  fprintf(stderr, "%s: frame error #%d (%s)\n", *TimeToString(time(NULL)), errors, Message);
114 }
115 
116 void cFrameChecker::CheckFrame(const uchar *Data, int Length)
117 {
118  int64_t Pts = TsGetPts(Data, Length);
119  if (Pts >= 0) {
120  if (lastPts >= 0) {
121  int Diff = int(round((PtsDiff(lastPts, Pts) / double(frameDelta))));
122  if (Diff > 0) {
123  if (Diff <= MAX_BACK_REFS) {
124  if (lastFwdRef > 1) {
125  if (backRefs != uint32_t((1 << (lastFwdRef - 1)) - 1))
126  Report("missing backref");
127  }
128  }
129  else
130  Report("missed", Diff);
131  backRefs = 0;
132  lastFwdRef = Diff;
133  lastPts = Pts;
134  }
135  else if (Diff < 0) {
136  Diff = -Diff;
137  if (Diff <= MAX_BACK_REFS) {
138  int b = 1 << (Diff - 1);
139  if ((backRefs & b) != 0)
140  Report("duplicate backref");
141  backRefs |= b;
142  }
143  else
144  Report("rev diff too big");
145  }
146  else
147  Report("zero diff");
148  }
149  else
150  lastPts = Pts;
151  }
152  else
153  Report("no PTS");
154 }
155 
157 {
158  int MissedFrames = MAXBROKENTIMEOUT / 1000 * PTSTICKS / frameDelta;
159  Report("missed", MissedFrames);
160 }
161 
162 // --- cRecorder -------------------------------------------------------------
163 
164 cRecorder::cRecorder(const char *FileName, const cChannel *Channel, int Priority)
165 :cReceiver(Channel, Priority)
166 ,cThread("recording")
167 {
168  tsChecker = new cTsChecker;
170  recordingName = strdup(FileName);
172  recordingInfo->Read();
173  oldErrors = max(0, recordingInfo->Errors()); // in case this is a re-started recording
174  errors = oldErrors;
175  lastErrors = errors;
176  firstIframeSeen = false;
177 
178  // Make sure the disk is up and running:
179 
180  SpinUpDisk(FileName);
181 
183  ringBuffer->SetTimeouts(0, 100);
185 
186  int Pid = Channel->Vpid();
187  int Type = Channel->Vtype();
188  if (!Pid && Channel->Apid(0)) {
189  Pid = Channel->Apid(0);
190  Type = 0x04;
191  }
192  if (!Pid && Channel->Dpid(0)) {
193  Pid = Channel->Dpid(0);
194  Type = 0x06;
195  }
196  frameDetector = new cFrameDetector(Pid, Type);
197  index = NULL;
198  fileSize = 0;
199  lastDiskSpaceCheck = time(NULL);
200  lastErrorLog = 0;
201  fileName = new cFileName(FileName, true);
202  int PatVersion, PmtVersion;
203  if (fileName->GetLastPatPmtVersions(PatVersion, PmtVersion))
204  patPmtGenerator.SetVersions(PatVersion + 1, PmtVersion + 1);
205  patPmtGenerator.SetChannel(Channel);
206  recordFile = fileName->Open();
207  if (!recordFile)
208  return;
209  // Create the index file:
210  index = new cIndexFile(FileName, true);
211  if (!index)
212  esyslog("ERROR: can't allocate index");
213  // let's continue without index, so we'll at least have the recording
214 }
215 
217 {
218  Detach();
219  delete index;
220  delete fileName;
221  delete frameDetector;
222  delete ringBuffer;
223  delete frameChecker;
224  delete tsChecker;
225  free(recordingName);
226 }
227 
228 #define ERROR_LOG_DELTA 1 // seconds between logging errors
229 
230 void cRecorder::HandleErrors(bool Force)
231 {
232  // We don't log every single error separately, to avoid spamming the log file:
233  if (Force || time(NULL) - lastErrorLog >= ERROR_LOG_DELTA) {
235  if (errors > lastErrors) {
236  int d = errors - lastErrors;
237  if (DebugChecks)
238  fprintf(stderr, "%s: %s: %d error%s\n", *TimeToString(time(NULL)), recordingName, d, d > 1 ? "s" : "");
239  esyslog("%s: %d error%s", recordingName, d, d > 1 ? "s" : "");
241  recordingInfo->Write();
243  Recordings->UpdateByName(recordingName);
244  }
245  lastErrors = errors;
246  lastErrorLog = time(NULL);
247  }
248 }
249 
251 {
252  if (time(NULL) > lastDiskSpaceCheck + DISKCHECKINTERVAL) {
253  int Free = FreeDiskSpaceMB(fileName->Name());
254  lastDiskSpaceCheck = time(NULL);
255  if (Free < MINFREEDISKSPACE) {
256  dsyslog("low disk space (%d MB, limit is %d MB)", Free, MINFREEDISKSPACE);
257  return true;
258  }
259  }
260  return false;
261 }
262 
264 {
265  if (recordFile && frameDetector->IndependentFrame()) { // every file shall start with an independent frame
268  fileSize = 0;
269  }
270  }
271  return recordFile != NULL;
272 }
273 
274 void cRecorder::Activate(bool On)
275 {
276  if (On)
277  Start();
278  else
279  Cancel(3);
280 }
281 
282 void cRecorder::Receive(const uchar *Data, int Length)
283 {
284  if (Running()) {
285  static const uchar aff[TS_SIZE - 4] = { 0xB7, 0x00,
286  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
287  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
288  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
289  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
290  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
291  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
292  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
293  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
294  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
295  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
296  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
297  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
298  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
299  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
300  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
301  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
302  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
303  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
304  0xFF, 0xFF}; // Length is always TS_SIZE!
305  if ((Data[3] & 0b00110000) == 0b00100000 && !memcmp(Data + 4, aff, sizeof(aff)))
306  return; // Adaptation Field Filler found, skipping
307  int p = ringBuffer->Put(Data, Length);
308  if (p != Length && Running())
309  ringBuffer->ReportOverflow(Length - p);
310  else if (firstIframeSeen) // we ignore any garbage before the first I-frame
311  tsChecker->CheckTs(Data, Length);
312  }
313 }
314 
316 {
318  bool InfoWritten = false;
319  while (Running()) {
320  int r;
321  uchar *b = ringBuffer->Get(r);
322  if (b) {
323  int Count = frameDetector->Analyze(b, r);
324  if (Count) {
325  if (!Running() && frameDetector->IndependentFrame()) // finish the recording before the next independent frame
326  break;
327  if (frameDetector->Synced()) {
328  if (!InfoWritten) {
331  recordingInfo->Write();
333  Recordings->UpdateByName(recordingName);
334  }
335  InfoWritten = true;
338  }
340  firstIframeSeen = true; // start recording with the first I-frame
341  if (!NextFile())
342  break;
343  if (frameDetector->NewFrame()) {
344  if (index)
346  if (frameChecker)
347  frameChecker->CheckFrame(b, Count);
348  }
351  fileSize += TS_SIZE;
352  int Index = 0;
353  while (uchar *pmt = patPmtGenerator.GetPmt(Index)) {
354  recordFile->Write(pmt, TS_SIZE);
355  fileSize += TS_SIZE;
356  }
358  }
359  if (recordFile->Write(b, Count) < 0) {
361  break;
362  }
363  HandleErrors();
364  fileSize += Count;
365  }
366  }
367  ringBuffer->Del(Count);
368  }
369  }
370  if (t.TimedOut()) {
372  HandleErrors(true);
373  esyslog("ERROR: video data stream broken");
376  }
377  }
378  HandleErrors(true);
379 }
cRecorder::tsChecker
cTsChecker * tsChecker
Definition: recorder.h:24
cIndexFile
Definition: recording.h:456
TS_SIZE
#define TS_SIZE
Definition: remux.h:34
cRecorder::recordingInfo
cRecordingInfo * recordingInfo
Definition: recorder.h:30
cFrameChecker
Definition: recorder.c:84
cRecorder::lastErrors
int lastErrors
Definition: recorder.h:40
cRecordingInfo::SetErrors
void SetErrors(int Errors)
Definition: recording.c:461
cFrameChecker::CheckFrame
void CheckFrame(const uchar *Data, int Length)
Definition: recorder.c:116
cFrameChecker::SetFrameDelta
void SetFrameDelta(int FrameDelta)
Definition: recorder.c:94
cPatPmtGenerator::GetPmt
uchar * GetPmt(int &Index)
Returns a pointer to the Index'th TS packet of the PMT section.
Definition: remux.c:600
cRecordingInfo::SetFramesPerSecond
void SetFramesPerSecond(double FramesPerSecond)
Definition: recording.c:449
recorder.h
cFrameChecker::Errors
int Errors(void)
Definition: recorder.c:97
cRingBuffer::SetTimeouts
void SetTimeouts(int PutTimeout, int GetTimeout)
Definition: ringbuffer.c:89
cReceiver
Definition: receiver.h:17
MAX_BACK_REFS
#define MAX_BACK_REFS
Definition: recorder.c:82
cRecorder::fileSize
off_t fileSize
Definition: recorder.h:35
cRingBufferLinear::Put
int Put(const uchar *Data, int Count)
Puts at most Count bytes of Data into the ring buffer.
Definition: ringbuffer.c:306
cChannel::Dpid
int Dpid(int i) const
Definition: channels.h:160
TS_CONT_CNT_MASK
#define TS_CONT_CNT_MASK
Definition: remux.h:42
cRecorder::errors
int errors
Definition: recorder.h:39
cFrameDetector::Synced
bool Synced(void)
Returns true if the frame detector has synced on the data stream.
Definition: remux.h:538
cFrameChecker::ReportBroken
void ReportBroken(void)
Definition: recorder.c:156
cRecorder::Action
virtual void Action(void)
A derived cThread class must implement the code it wants to execute as a separate thread in this func...
Definition: recorder.c:315
cFrameChecker::backRefs
uint32_t backRefs
Definition: recorder.c:88
cSetup::MaxVideoFileSize
int MaxVideoFileSize
Definition: config.h:344
cFileName::NextFile
cUnbufferedFile * NextFile(void)
Definition: recording.c:3078
cFileName::Open
cUnbufferedFile * Open(void)
Definition: recording.c:3002
cFrameDetector::Analyze
int Analyze(const uchar *Data, int Length)
Analyzes the TS packets pointed to by Data.
Definition: remux.c:1654
MIN_TS_PACKETS_FOR_FRAME_DETECTOR
#define MIN_TS_PACKETS_FOR_FRAME_DETECTOR
Definition: remux.h:503
cRecorder::patPmtGenerator
cPatPmtGenerator patPmtGenerator
Definition: recorder.h:28
TsError
bool TsError(const uchar *p)
Definition: remux.h:77
cRecordingInfo::FramesPerSecond
double FramesPerSecond(void) const
Definition: recording.h:89
cRecorder::Receive
virtual void Receive(const uchar *Data, int Length)
This function is called from the cDevice we are attached to, and delivers one TS packet from the set ...
Definition: recorder.c:282
cThread::Cancel
void Cancel(int WaitSeconds=0)
Cancels the thread by first setting 'running' to false, so that the Action() loop can finish in an or...
Definition: thread.c:354
FreeDiskSpaceMB
int FreeDiskSpaceMB(const char *Directory, int *UsedMB)
Definition: tools.c:464
cRecordingInfo::Errors
int Errors(void) const
Definition: recording.h:92
cFileName::GetLastPatPmtVersions
bool GetLastPatPmtVersions(int &PatVersion, int &PmtVersion)
Definition: recording.c:2951
cFrameChecker::frameDelta
int frameDelta
Definition: recorder.c:86
Setup
cSetup Setup
Definition: config.c:372
ShutdownHandler
cShutdownHandler ShutdownHandler
Definition: shutdown.c:27
cTimeMs::Set
void Set(int Ms=0)
Sets the timer.
Definition: tools.c:792
shutdown.h
cFrameChecker::lastPts
int64_t lastPts
Definition: recorder.c:87
cRecordingInfo
Definition: recording.h:63
MAXBROKENTIMEOUT
#define MAXBROKENTIMEOUT
Definition: recorder.c:17
cFileName::Number
uint16_t Number(void)
Definition: recording.h:506
RUC_STARTRECORDING
#define RUC_STARTRECORDING
Definition: recording.h:422
TsPid
int TsPid(const uchar *p)
Definition: remux.h:82
cRecorder::recordingName
char * recordingName
Definition: recorder.h:33
DoubleEqual
bool DoubleEqual(double a, double b)
Definition: tools.h:97
cRecordingUserCommand::InvokeCommand
static void InvokeCommand(const char *State, const char *RecordingFileName, const char *SourceFileName=NULL)
Definition: recording.c:2339
cThread::Running
bool Running(void)
Returns false if a derived cThread object shall leave its Action() function.
Definition: thread.h:101
cRecorder::frameDetector
cFrameDetector * frameDetector
Definition: recorder.h:27
cTsChecker::CheckTs
void CheckTs(const uchar *Data, int Length)
Definition: recorder.c:59
cRecorder::HandleErrors
void HandleErrors(bool Force=false)
Definition: recorder.c:230
cFileName
Definition: recording.h:494
cRingBufferLinear::Del
void Del(int Count)
Deletes at most Count bytes from the ring buffer.
Definition: ringbuffer.c:371
uchar
unsigned char uchar
Definition: tools.h:31
cRecorder::cRecorder
cRecorder(const char *FileName, const cChannel *Channel, int Priority)
Creates a new recorder for the given Channel and the given Priority that will record into the file Fi...
Definition: recorder.c:164
cRecorder::fileName
cFileName * fileName
Definition: recorder.h:29
ERROR_LOG_DELTA
#define ERROR_LOG_DELTA
Definition: recorder.c:228
TsHasPayload
bool TsHasPayload(const uchar *p)
Definition: remux.h:62
TsIsScrambled
bool TsIsScrambled(const uchar *p)
Definition: remux.h:93
cRecorder::ringBuffer
cRingBufferLinear * ringBuffer
Definition: recorder.h:26
cPatPmtGenerator::GetPat
uchar * GetPat(void)
Returns a pointer to the PAT section, which consists of exactly one TS packet.
Definition: remux.c:594
cRecorder::index
cIndexFile * index
Definition: recorder.h:31
cTimeMs
Definition: tools.h:401
cFrameChecker::cFrameChecker
cFrameChecker(void)
Definition: recorder.c:100
cRingBuffer::SetIoThrottle
void SetIoThrottle(void)
Definition: ringbuffer.c:95
DEFAULTFRAMESPERSECOND
#define DEFAULTFRAMESPERSECOND
Definition: recording.h:352
cTsChecker::errors
int errors
Definition: recorder.c:38
cRecorder::frameChecker
cFrameChecker * frameChecker
Definition: recorder.h:25
cShutdownHandler::RequestEmergencyExit
void RequestEmergencyExit(void)
Requests an emergency exit of the VDR main loop.
Definition: shutdown.c:93
cRecorder::~cRecorder
virtual ~cRecorder()
Definition: recorder.c:216
cPatPmtGenerator::SetVersions
void SetVersions(int PatVersion, int PmtVersion)
Sets the version numbers for the generated PAT and PMT, in case this generator is used to,...
Definition: remux.c:579
cTsChecker::cTsChecker
cTsChecker(void)
Definition: recorder.c:46
cChannel::Vpid
int Vpid(void) const
Definition: channels.h:153
cRingBufferLinear::Get
uchar * Get(int &Count)
Gets data from the ring buffer.
Definition: ringbuffer.c:346
dsyslog
#define dsyslog(a...)
Definition: tools.h:37
cRecorder::Activate
virtual void Activate(bool On)
If you override Activate() you need to call Detach() (which is a member of the cReceiver class) from ...
Definition: recorder.c:274
cChannel::Vtype
int Vtype(void) const
Definition: channels.h:155
cChannel
Definition: channels.h:87
cReceiver::Detach
void Detach(void)
Definition: receiver.c:125
cChannel::Apid
int Apid(int i) const
Definition: channels.h:159
TimeToString
cString TimeToString(time_t t)
Converts the given time to a string of the form "www mmm dd hh:mm:ss yyyy".
Definition: tools.c:1225
TsContinuityCounter
uchar TsContinuityCounter(const uchar *p)
Definition: remux.h:98
cFileName::Name
const char * Name(void)
Definition: recording.h:505
cRecorder::recordFile
cUnbufferedFile * recordFile
Definition: recorder.h:32
SpinUpDisk
bool SpinUpDisk(const char *FileName)
Definition: tools.c:685
MINFREEDISKSPACE
#define MINFREEDISKSPACE
Definition: recorder.c:19
cFrameDetector::IndependentFrame
bool IndependentFrame(void)
Returns true if a new frame was detected and this is an independent frame (i.e.
Definition: remux.h:543
cPatPmtGenerator::SetChannel
void SetChannel(const cChannel *Channel)
Sets the Channel for which the PAT/PMT shall be generated.
Definition: remux.c:585
cThread
Definition: thread.h:79
cTsChecker::Report
void Report(int Pid, const char *Message)
Definition: recorder.c:52
MAXPID
#define MAXPID
Definition: remux.c:464
PTSTICKS
#define PTSTICKS
Definition: remux.h:57
cFrameChecker::lastFwdRef
int lastFwdRef
Definition: recorder.c:89
cIndexFile::Write
bool Write(bool Independent, uint16_t FileNumber, off_t FileOffset)
Definition: recording.c:2742
cUnbufferedFile::Write
ssize_t Write(const void *Data, size_t Size)
Definition: tools.c:1947
cTsChecker::counter
uchar counter[MAXPID]
Definition: recorder.c:37
cRingBufferLinear
Definition: ringbuffer.h:48
RECORDERBUFSIZE
#define RECORDERBUFSIZE
Definition: recorder.c:13
cFrameChecker::errors
int errors
Definition: recorder.c:90
cTimeMs::TimedOut
bool TimedOut(void) const
Definition: tools.c:797
MEGABYTE
#define MEGABYTE(n)
Definition: tools.h:45
cRecordingInfo::Write
bool Write(FILE *f, const char *Prefix="") const
Definition: recording.c:527
DISKCHECKINTERVAL
#define DISKCHECKINTERVAL
Definition: recorder.c:20
max
T max(T a, T b)
Definition: tools.h:64
PtsDiff
int64_t PtsDiff(int64_t Pts1, int64_t Pts2)
Returns the difference between two PTS values.
Definition: remux.c:234
cRecordingInfo::Read
bool Read(FILE *f)
Definition: recording.c:466
cTsChecker
Definition: recorder.c:35
cRecorder::NextFile
bool NextFile(void)
Definition: recorder.c:263
DebugChecks
static bool DebugChecks
Definition: recorder.c:22
cRecorder::RunningLowOnDiskSpace
bool RunningLowOnDiskSpace(void)
Definition: recorder.c:250
cThread::Start
void bool Start(void)
Sets the description of this thread, which will be used when logging starting or stopping of the thre...
Definition: thread.c:304
cTsChecker::Errors
int Errors(void)
Definition: recorder.c:43
cRecorder::lastErrorLog
time_t lastErrorLog
Definition: recorder.h:37
cFrameDetector::FramesPerSecond
double FramesPerSecond(void)
Returns the number of frames per second, or 0 if this information is not available.
Definition: remux.h:547
TS_CC_UNKNOWN
#define TS_CC_UNKNOWN
Definition: recorder.c:33
cFrameDetector
Definition: remux.h:507
cFrameDetector::NewFrame
bool NewFrame(void)
Returns true if the data given to the last call to Analyze() started a new frame.
Definition: remux.h:540
cRecorder::firstIframeSeen
bool firstIframeSeen
Definition: recorder.h:34
TsGetPts
int64_t TsGetPts(const uchar *p, int l)
Definition: remux.c:160
cRingBuffer::ReportOverflow
void ReportOverflow(int Bytes)
Definition: ringbuffer.c:101
esyslog
#define esyslog(a...)
Definition: tools.h:35
cRecorder::lastDiskSpaceCheck
time_t lastDiskSpaceCheck
Definition: recorder.h:36
cRecorder::oldErrors
int oldErrors
Definition: recorder.h:38
LOG_ERROR_STR
#define LOG_ERROR_STR(s)
Definition: tools.h:40
LOCK_RECORDINGS_WRITE
#define LOCK_RECORDINGS_WRITE
Definition: recording.h:308
cFrameChecker::Report
void Report(const char *Message, int NumErrors=1)
Definition: recorder.c:109