13#define RECORDERBUFSIZE (MEGABYTE(20) / TS_SIZE * TS_SIZE)
17#define MAXBROKENTIMEOUT 30000
19#define MINFREEDISKSPACE (512)
20#define DISKCHECKINTERVAL 100
46 int Pid = Channel->
Vpid();
47 int Type = Channel->
Vtype();
48 if (!Pid && Channel->
Apid(0)) {
49 Pid = Channel->
Apid(0);
52 if (!Pid && Channel->
Dpid(0)) {
53 Pid = Channel->
Dpid(0);
73 esyslog(
"ERROR: can't allocate index");
94#define ERROR_LOG_DELTA 1
150 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
151 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
152 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
153 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
154 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
155 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
156 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
157 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
158 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
159 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
160 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
161 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
162 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
163 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
164 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
165 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
166 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
167 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
169 if ((Data[3] & 0b00110000) == 0b00100000 && !memcmp(Data + 4, aff,
sizeof(aff)))
177#define MIN_IFRAMES_FOR_LAST_PTS 2
181 dsyslog(
"getting last PTS of '%s'", RecordingName);
189 int64_t LastPts = -1;
192 bool GotPatPmtVersions =
false;
193 for (
int i = Index->Last(); i >= 0; i--) {
194 if (Index->Get(i, &FileNumber, &FileOffset, &Independent, &Length)) {
196 int l =
ReadFrame(f, Buffer, Length,
sizeof(Buffer));
199 if (LastPts < 0 ||
PtsDiff(LastPts, Pts) > 0) {
204 if (!GotPatPmtVersions && PatPmtParser.
ParsePatPmt(Buffer, l)) {
207 if (PatPmtParser.
GetVersions(PatVersion, PmtVersion)) {
209 GotPatPmtVersions =
true;
238 bool InfoWritten =
false;
239 bool pendIndependentFrame =
false;
240 uint16_t pendNumber = 0;
241 off_t pendFileSize = 0;
242 bool pendMissing =
false;
243 int NumIframesSeen = 0;
245 bool Stopping =
false;
249 int Vdsb = VdsbTimer.
Elapsed();
250 if (Vdsb > 30000 && Vdsb < TEST_VDSB) {
284 bool PreviousErrors =
false;
285 bool MissingFrames =
false;
289 index->
Write(pendIndependentFrame, pendNumber, pendFileSize, PreviousErrors, pendMissing);
293 pendMissing = MissingFrames;
313 if (NumIframesSeen >= 2)
322 esyslog(
"ERROR: video data stream broken");
324 if (pendNumber > 0) {
325 bool PreviousErrors =
false;
327 index->
Write(pendIndependentFrame, pendNumber, pendFileSize, PreviousErrors, pendMissing);
337 StopTimeout.
Set(2000);
350 if (pendNumber > 0) {
351 bool PreviousErrors =
false;
353 index->
Write(pendIndependentFrame, pendNumber, pendFileSize, PreviousErrors, pendMissing);
static void SleepMs(int TimeoutMs)
Creates a cCondWait object and uses it to sleep for TimeoutMs milliseconds, immediately giving up the...
cUnbufferedFile * NextFile(void)
cUnbufferedFile * Open(void)
cFileName(const char *FileName, bool Record, bool Blocking=false, bool IsPesRecording=false)
cUnbufferedFile * SetOffset(int Number, off_t Offset=0)
bool Synced(void)
Returns true if the frame detector has synced on the data stream.
bool IndependentFrame(void)
Returns true if a new frame was detected and this is an independent frame (i.e.
double FramesPerSecond(void)
Returns the number of frames per second, or 0 if this information is not available.
uint16_t FrameWidth(void)
Returns the frame width, or 0 if this information is not available.
int Errors(bool *PreviousErrors=NULL, bool *MissingFrames=NULL)
Returns the total number of errors so far.
eScanType ScanType(void)
Returns the scan type, or stUnknown if this information is not available.
bool NewFrame(int *PreviousErrors=NULL, int *MissingFrames=NULL)
int Analyze(const uchar *Data, int Length, bool ErrorCheck=true)
Analyzes the TS packets pointed to by Data.
uint16_t FrameHeight(void)
Returns the frame height, or 0 if this information is not available.
cFrameDetector(int Pid=0, int Type=0)
Sets up a frame detector for the given Pid and stream Type.
void SetLastPts(int64_t LastPts)
If this is a resumed recording, call this function with the last PTS of the previous recording.
eAspectRatio AspectRatio(void)
Returns the aspect ratio, or arUnknown if this information is not available.
bool Write(bool Independent, uint16_t FileNumber, off_t FileOffset, bool Errors=false, bool Missing=false)
cIndexFile(const char *FileName, bool Record, bool IsPesRecording=false, bool PauseLive=false)
uchar * GetPmt(int &Index)
Returns a pointer to the Index'th TS packet of the PMT section.
void SetChannel(const cChannel *Channel)
Sets the Channel for which the PAT/PMT shall be generated.
void SetVersions(int PatVersion, int PmtVersion)
Sets the version numbers for the generated PAT and PMT, in case this generator is used to,...
uchar * GetPat(void)
Returns a pointer to the PAT section, which consists of exactly one TS packet.
bool GetVersions(int &PatVersion, int &PmtVersion) const
Returns true if a valid PAT/PMT has been parsed and stores the current version numbers in the given v...
bool ParsePatPmt(const uchar *Data, int Length)
Parses the given Data (which may consist of several TS packets, typically an entire frame) and extrac...
cReceiver(const cChannel *Channel=NULL, int Priority=MINPRIORITY)
Creates a new receiver for the given Channel with the given Priority.
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...
virtual void Receive(const uchar *Data, int Length) override
This function is called from the cDevice we are attached to, and delivers one TS packet from the set ...
virtual void Activate(bool On) override
If you override Activate() you need to call Detach() (which is a member of the cReceiver class) from ...
std::atomic< bool > working
void HandleErrors(bool Force=false)
void GetLastPts(const char *RecordingName)
void Stop(void)
Stops the recorder.
cRecordingInfo * recordingInfo
cFrameDetector * frameDetector
time_t lastDiskSpaceCheck
cUnbufferedFile * recordFile
virtual void Action(void) override
A derived cThread class must implement the code it wants to execute as a separate thread in this func...
cRingBufferLinear * ringBuffer
bool RunningLowOnDiskSpace(void)
virtual ~cRecorder() override
cPatPmtGenerator patPmtGenerator
void SetFramesPerSecond(double FramesPerSecond)
int TmpErrors(void) const
uint16_t FrameHeight(void) const
cRecordingInfo(const cChannel *Channel=NULL, const cEvent *Event=NULL)
bool Write(FILE *f, const char *Prefix="") const
uint16_t FrameWidth(void) const
void SetFrameParams(uint16_t FrameWidth, uint16_t FrameHeight, eScanType ScanType, eAspectRatio AspectRatio)
eAspectRatio AspectRatio(void) const
bool Read(FILE *f, bool Force=false)
void SetErrors(int Errors, int TmpErrors=0)
double FramesPerSecond(void) const
static void InvokeCommand(const char *State, const char *RecordingFileName, const char *SourceFileName=NULL)
cRingBufferLinear(int Size, int Margin=0, bool Statistics=false, const char *Description=NULL)
Creates a linear ring buffer.
void Del(int Count)
Deletes at most Count bytes from the ring buffer.
int Put(const uchar *Data, int Count)
Puts at most Count bytes of Data into the ring buffer.
uchar * Get(int &Count)
Gets data from the ring buffer.
void SetTimeouts(int PutTimeout, int GetTimeout)
void ReportOverflow(int Bytes)
bool EmergencyExitRequested(void)
Returns true if an emergency exit was requested.
void RequestEmergencyExit(void)
Requests an emergency exit of the VDR main loop.
void bool Start(void)
Sets the description of this thread, which will be used when logging starting or stopping of the thre...
bool Running(void)
Returns false if a derived cThread object shall leave its Action() function.
cThread(const char *Description=NULL, bool LowPriority=false)
Creates a new thread.
void Cancel(int WaitSeconds=0)
Cancels the thread by first setting 'running' to false, so that the Action() loop can finish in an or...
uint64_t Elapsed(void) const
Returns the number of milliseconds that have elapsed since the last call to Set().
void Set(int Ms=0)
Sets the timer.
bool TimedOut(void) const
Returns true if the number of milliseconds given in the last call to Set() have passed.
void Reset(void)
Resets the timer to the same timeout as given in the last call to Set().
cUnbufferedFile is used for large files that are mainly written or read in a streaming manner,...
ssize_t Write(const void *Data, size_t Size)
#define DISKCHECKINTERVAL
#define MIN_IFRAMES_FOR_LAST_PTS
int ReadFrame(cUnbufferedFile *f, uchar *b, int Length, int Max)
#define DEFAULTFRAMESPERSECOND
#define LOCK_RECORDINGS_WRITE
#define RUC_STARTRECORDING
int64_t PtsDiff(int64_t Pts1, int64_t Pts2)
Returns the difference between two PTS values.
int64_t TsGetPts(const uchar *p, int l, int Pid)
#define MIN_TS_PACKETS_FOR_FRAME_DETECTOR
cShutdownHandler ShutdownHandler