28 void Flush(
uchar *Data,
int &Length,
int MaxLength);
49 int NewSize = (
length + Length) * 3 / 2;
63 if (Data &&
length > 0 && Length +
length <= MaxLength) {
79 void Flush(
int Pid,
uchar *Data,
int &Length,
int MaxLength);
84 for (
int i = 0; i <
MAXPID; i++)
90 for (
int i = 0; i <
MAXPID; i++)
111 bool FindHeader(uint32_t Code,
const char *Header);
117 void AdjGopTime(
int Offset,
int FramesPerSecond);
125 if (
TsPid(Data) == Vpid) {
126 Setup(Data, Length, Vpid);
137 esyslog(
"ERROR: %s header not found!", Header);
184 uchar Frame = ((Byte3 & 0x1F) << 1) | (Byte4 >> 7);
185 uchar Sec = ((Byte2 & 0x07) << 3) | (Byte3 >> 5);
186 uchar Min = ((Byte1 & 0x03) << 4) | (Byte2 >> 4);
187 uchar Hour = ((Byte1 & 0x7C) >> 2);
188 int GopTime = ((Hour * 60 + Min) * 60 + Sec) * FramesPerSecond + Frame;
192 GopTime += 24 * 60 * 60 * FramesPerSecond;
193 Frame = GopTime % FramesPerSecond;
194 GopTime = GopTime / FramesPerSecond;
196 GopTime = GopTime / 60;
198 GopTime = GopTime / 60;
200 SetByte((Byte1 & 0x80) | (Hour << 2) | (Min >> 4), Index1);
201 SetByte(((Min & 0x0F) << 4) | 0x08 | (Sec >> 3), Index2);
202 SetByte(((Sec & 0x07) << 3) | (Frame >> 1), Index3);
203 SetByte((Byte4 & 0x7F) | ((Frame & 0x01) << 7), Index4);
218 SetByte((Tref << 6) | (Byte2 & 0x3F), Index2);
249 bool LoadFrame(
int Index,
uchar *Buffer,
bool &Independent,
int &Length);
255 bool FixFrame(
uchar *Data,
int &Length,
bool Independent,
int Index,
bool CutIn,
bool CutOut);
256 bool ProcessSequence(
int LastEndIndex,
int BeginIndex,
int EndIndex,
int NextBeginIndex);
258 virtual void Action(
void);
300 esyslog(
"no editing sequences found for %s", FromFileName);
303 esyslog(
"no editing marks found for %s", FromFileName);
319 dsyslog(
"suspending cutter thread");
325 dsyslog(
"resuming cutter thread");
335 if (
fromIndex->
Get(Index, &FileNumber, &FileOffset, &Independent, &Length)) {
342 else if (len != Length)
344 return error == NULL;
378 if (!Buffer1 || !Buffer2)
383 if (
LoadFrame(Index1, Buffer1, Independent, Length1) &&
LoadFrame(Index2, Buffer2, Independent, Length2)) {
384 if (Length1 == Length2) {
386 for (
int i = 0; i < Length1; i++) {
387 if (Buffer1[i] != Buffer2[i]) {
403 bool Processed[
MAXPID] = {
false };
407 for (
int NumIndependentFrames = 0; NumIndependentFrames < 2; Index++) {
410 if (
LoadFrame(Index, Buffer, Independent, len)) {
412 NumIndependentFrames++;
418 int64_t d =
PtsDiff(LastPts, Pts);
422 NumIndependentFrames = 0;
423 Processed[Pid] =
true;
475 bool DeletedFrame =
false;
476 bool GotVidPts =
false;
536 if (!DeletedFrame && !GotVidPts) {
547 bool SeamlessBegin = LastEndIndex >= 0 &&
FramesAreEqual(LastEndIndex, BeginIndex);
548 bool SeamlessEnd = NextBeginIndex >= 0 &&
FramesAreEqual(EndIndex, NextBeginIndex);
555 for (
int Index = BeginIndex;
Running() && Index < EndIndex; Index++) {
558 if (
LoadFrame(Index, Buffer, Independent, Length)) {
561 bool CutIn = !SeamlessBegin && Index == BeginIndex;
562 bool CutOut = !SeamlessEnd && Index == EndIndex - 1;
563 bool DeletedFrame =
false;
565 DeletedFrame =
FixFrame(Buffer, Length, Independent, Index, CutIn, CutOut);
581 error =
"safe_write";
606 int LastEndIndex = -1;
607 while (BeginMark &&
Running()) {
617 int NextBeginIndex = -1;
620 NextBeginIndex = NextBeginMark->Position();
622 if (!
ProcessSequence(LastEndIndex, BeginMark->Position(), EndIndex, NextBeginIndex))
626 LastEndIndex = EndIndex;
639 esyslog(
"no editing marks found!");
700 isyslog(
"editing process has been interrupted");
726#define CUTTINGCHECKINTERVAL 500
732 if (Recording.
Name()) {
737 if (Cutter.
Start()) {
742 fprintf(stderr,
"error while cutting\n");
745 fprintf(stderr,
"can't start editing process\n");
748 fprintf(stderr,
"'%s' has no editing sequences\n", FileName);
751 fprintf(stderr,
"'%s' has no editing marks\n", FileName);
754 fprintf(stderr,
"'%s' is not a recording\n", FileName);
757 fprintf(stderr,
"'%s' is not a directory\n", FileName);
static void SleepMs(int TimeoutMs)
Creates a cCondWait object and uses it to sleep for TimeoutMs milliseconds, immediately giving up the...
static void Shutdown(void)
cCuttingThread * cuttingThread
bool Start(void)
Starts the actual cutting process.
cString editedVersionName
cCutter(const char *FileName)
Sets up a new cutter for the given FileName, which must be the full path name of an existing recordin...
void Stop(void)
Stops an ongoing cutting process.
bool Error(void)
Returns true if an error occurred while cutting the recording.
cString originalVersionName
bool Active(void)
Returns true if the cutter is currently active.
static cString EditedFileName(const char *FileName)
Returns the full path name of the edited version of the recording with the given FileName.
bool LoadFrame(int Index, uchar *Buffer, bool &Independent, int &Length)
cPatPmtParser patPmtParser
virtual ~cCuttingThread()
cUnbufferedFile * fromFile
bool SwitchFile(bool Force=false)
bool FixFrame(uchar *Data, int &Length, bool Independent, int Index, bool CutIn, bool CutOut)
virtual void Action(void)
A derived cThread class must implement the code it wants to execute as a separate thread in this func...
bool FramesAreEqual(int Index1, int Index2)
bool ProcessSequence(int LastEndIndex, int BeginIndex, int EndIndex, int NextBeginIndex)
cCuttingThread(const char *FromFileName, const char *ToFileName)
void GetPendingPackets(uchar *Buffer, int &Length, int Index)
cUnbufferedFile * NextFile(void)
cUnbufferedFile * Open(void)
cUnbufferedFile * SetOffset(int Number, off_t Offset=0)
bool Write(bool Independent, uint16_t FileNumber, off_t FileOffset)
bool Get(int Index, uint16_t *FileNumber, off_t *FileOffset, bool *Independent=NULL, int *Length=NULL)
int Last(void)
Returns the index of the last entry in this file, or -1 if the file is empty.
static bool Engaged(void)
Returns true if any I/O throttling object is currently active.
int GetNumSequences(void) const
Returns the actual number of sequences to be cut from the recording.
void Add(int Position)
If this cMarks object is used by multiple threads, the caller must Lock() it before calling Add() and...
const cMark * GetNextBegin(const cMark *EndMark=NULL) const
Returns the next "begin" mark after EndMark, skipping any marks at the same position as EndMark.
bool Load(const char *RecordingFileName, double FramesPerSecond=DEFAULTFRAMESPERSECOND, bool IsPesRecording=false)
const cMark * GetNextEnd(const cMark *BeginMark) const
Returns the next "end" mark after BeginMark, skipping any marks at the same position as BeginMark.
bool FindHeader(uint32_t Code, const char *Header)
void AdjTref(int TrefOffset)
void AdjGopTime(int Offset, int FramesPerSecond)
cMpeg2Fixer(uchar *Data, int Length, int Vpid)
void Append(uchar *Data, int Length)
Appends Length bytes of Data to this packet buffer.
void Flush(uchar *Data, int &Length, int MaxLength)
Flushes the content of this packet buffer into the given Data, starting at position Length,...
cPacketBuffer * buffers[MAXPID]
void Append(int Pid, uchar *Data, int Length)
void Flush(int Pid, uchar *Data, int &Length, int MaxLength)
int Vtype(void) const
Returns the video stream type as defined by the current PMT, or 0 if no video stream type has been de...
bool ParsePatPmt(const uchar *Data, int Length)
Parses the given Data (which may consist of several TS packets, typically an entire frame) and extrac...
bool IsPmtPid(int Pid) const
Returns true if Pid the one of the PMT pids as defined by the current PAT.
int Vpid(void) const
Returns the video pid as defined by the current PMT, or 0 if no video pid has been detected,...
static void InvokeCommand(const char *State, const char *RecordingFileName, const char *SourceFileName=NULL)
bool WriteInfo(const char *OtherFileName=NULL)
Writes in info file of this recording.
void SetStartTime(time_t Start)
Sets the start time of this recording to the given value.
const char * Name(void) const
Returns the full name of the recording (without the video directory).
const char * PrefixFileName(char Prefix)
double FramesPerSecond(void) const
bool IsPesRecording(void) const
static void SetBrokenLink(uchar *Data, int Length)
static const char * NowReplaying(void)
char SVDRPHostName[HOST_NAME_MAX]
static cString sprintf(const char *fmt,...) __attribute__((format(printf
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.
void Cancel(int WaitSeconds=0)
Cancels the thread by first setting 'running' to false, so that the Action() loop can finish in an or...
bool Active(void)
Checks whether the thread is still alive.
void SetByte(uchar Byte, int Index)
Sets the TS data byte at the given Index to the value Byte.
uchar GetByte(void)
Gets the next byte of the TS payload, skipping any intermediate TS header data.
int GetLastIndex(void)
Returns the index into the TS data of the payload byte that has most recently been read.
bool Find(uint32_t Code)
Searches for the four byte sequence given in Code and returns true if it was found within the payload...
bool SkipBytes(int Bytes)
Skips the given number of bytes in the payload and returns true if there is still data left to read.
cUnbufferedFile is used for large files that are mainly written or read in a streaming manner,...
void SetReadAhead(size_t ra)
ssize_t Write(const void *Data, size_t Size)
static bool RemoveVideoFile(const char *FileName)
#define CUTTINGCHECKINTERVAL
bool CutRecording(const char *FileName)
void AssertFreeDiskSpace(int Priority, bool Force)
The special Priority value -1 means that we shall get rid of any deleted recordings faster than norma...
int ReadFrame(cUnbufferedFile *f, uchar *b, int Length, int Max)
void SetRecordingTimerId(const char *Directory, const char *TimerId)
#define MAXVIDEOFILESIZEPES
#define RUC_EDITINGRECORDING
#define RUC_EDITEDRECORDING
void TsSetPcr(uchar *p, int64_t Pcr)
int64_t PtsDiff(int64_t Pts1, int64_t Pts2)
Returns the difference between two PTS values.
void TsHidePayload(uchar *p)
int64_t TsGetDts(const uchar *p, int l)
void TsSetDts(uchar *p, int l, int64_t Dts)
void TsSetPts(uchar *p, int l, int64_t Pts)
int64_t TsGetPts(const uchar *p, int l)
int TsPid(const uchar *p)
bool TsHasPayload(const uchar *p)
void TsSetContinuityCounter(uchar *p, uchar Counter)
uchar TsContinuityCounter(const uchar *p)
int64_t TsGetPcr(const uchar *p)
int64_t PtsAdd(int64_t Pts1, int64_t Pts2)
Adds the given PTS values, taking into account the 33bit wrap around.