From 292af5d4f4da41ea6faf43767f47685250cf1d2e Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Thu, 19 Sep 2024 20:21:58 +0200 Subject: [PATCH] The info file of an edited recording now contains the number of errors in the edited version --- HISTORY | 5 +++++ config.h | 6 +++--- cutter.c | 53 ++++++++++++++++++++++++++++++++++++++++++----------- cutter.h | 4 +++- recording.c | 8 ++++++-- recording.h | 4 ++-- vdr.5 | 4 ++-- 7 files changed, 63 insertions(+), 21 deletions(-) diff --git a/HISTORY b/HISTORY index e20dbaf5..605dfa2c 100644 --- a/HISTORY +++ b/HISTORY @@ -10009,3 +10009,8 @@ Video Disk Recorder Revision History APIVERSNUM is now 30004. - When the index file of a recording is regenerated, errors in the recording are now stored in the index file. +- The info file of an edited recording now contains the number of errors in the edited + version. Note that this applies only to recordings that have errors stored in their + index file. If errors are not stored in the index file, the edited version will have + its number of errors set to zero. + APIVERSNUM is now 30005. diff --git a/config.h b/config.h index 598e718a..25b84242 100644 --- a/config.h +++ b/config.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: config.h 5.21 2024/09/19 09:49:02 kls Exp $ + * $Id: config.h 5.22 2024/09/19 20:21:58 kls Exp $ */ #ifndef __CONFIG_H @@ -27,8 +27,8 @@ // The plugin API's version number: -#define APIVERSION "4" -#define APIVERSNUM 30004 +#define APIVERSION "5" +#define APIVERSNUM 30005 // When loading plugins, VDR searches files by their APIVERSION, which // is different from VDRVERSION. APIVERSION is a plain number, incremented diff --git a/cutter.c b/cutter.c index e53f78d2..e61dec6a 100644 --- a/cutter.c +++ b/cutter.c @@ -4,12 +4,11 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: cutter.c 5.1 2022/11/06 11:25:13 kls Exp $ + * $Id: cutter.c 5.2 2024/09/19 20:21:58 kls Exp $ */ #include "cutter.h" #include "menu.h" -#include "recording.h" #include "remux.h" #include "videodir.h" @@ -232,6 +231,10 @@ private: int numSequences; off_t maxVideoFileSize; off_t fileSize; + int frameErrors; + time_t lastErrorHandling; + cString editedRecordingName; + cRecordingInfo *recordingInfo; bool suspensionLogged; int sequence; // cutting sequence int delta; // time between two frames (PTS ticks) @@ -246,7 +249,7 @@ private: cPatPmtParser patPmtParser; bool Throttled(void); bool SwitchFile(bool Force = false); - bool LoadFrame(int Index, uchar *Buffer, bool &Independent, int &Length); + bool LoadFrame(int Index, uchar *Buffer, bool &Independent, int &Length, bool *Errors = NULL, bool *Missing = NULL); bool FramesAreEqual(int Index1, int Index2); void GetPendingPackets(uchar *Buffer, int &Length, int Index); // Gather all non-video TS packets from Index upward that either belong to @@ -254,15 +257,16 @@ private: // and add them to the end of the given Data. bool FixFrame(uchar *Data, int &Length, bool Independent, int Index, bool CutIn, bool CutOut); bool ProcessSequence(int LastEndIndex, int BeginIndex, int EndIndex, int NextBeginIndex); + void HandleErrors(bool Force = false); protected: virtual void Action(void); public: - cCuttingThread(const char *FromFileName, const char *ToFileName); + cCuttingThread(const char *FromFileName, const char *ToFileName, cRecordingInfo *RecordingInfo); virtual ~cCuttingThread(); const char *Error(void) { return error; } }; -cCuttingThread::cCuttingThread(const char *FromFileName, const char *ToFileName) +cCuttingThread::cCuttingThread(const char *FromFileName, const char *ToFileName, cRecordingInfo *RecordingInfo) :cThread("video cutting", true) { error = NULL; @@ -274,6 +278,10 @@ cCuttingThread::cCuttingThread(const char *FromFileName, const char *ToFileName) framesPerSecond = Recording.FramesPerSecond(); suspensionLogged = false; fileSize = 0; + frameErrors = 0; + lastErrorHandling = 0; + editedRecordingName = ToFileName; + recordingInfo = RecordingInfo; sequence = 0; delta = int(round(PTSTICKS / framesPerSecond)); lastVidPts = -1; @@ -328,11 +336,11 @@ bool cCuttingThread::Throttled(void) return false; } -bool cCuttingThread::LoadFrame(int Index, uchar *Buffer, bool &Independent, int &Length) +bool cCuttingThread::LoadFrame(int Index, uchar *Buffer, bool &Independent, int &Length, bool *Errors, bool *Missing) { uint16_t FileNumber; off_t FileOffset; - if (fromIndex->Get(Index, &FileNumber, &FileOffset, &Independent, &Length)) { + if (fromIndex->Get(Index, &FileNumber, &FileOffset, &Independent, &Length, Errors, Missing)) { fromFile = fromFileName->SetOffset(FileNumber, FileOffset); if (fromFile) { fromFile->SetReadAhead(MEGABYTE(20)); @@ -555,7 +563,9 @@ bool cCuttingThread::ProcessSequence(int LastEndIndex, int BeginIndex, int EndIn for (int Index = BeginIndex; Running() && Index < EndIndex; Index++) { bool Independent; int Length; - if (LoadFrame(Index, Buffer, Independent, Length)) { + bool Errors; + bool Missing; + if (LoadFrame(Index, Buffer, Independent, Length, &Errors, &Missing)) { // Make sure there is enough disk space: AssertFreeDiskSpace(-1); bool CutIn = !SeamlessBegin && Index == BeginIndex; @@ -572,10 +582,12 @@ bool cCuttingThread::ProcessSequence(int LastEndIndex, int BeginIndex, int EndIn return false; } // Write index: - if (!DeletedFrame && !toIndex->Write(Independent, toFileName->Number(), fileSize)) { + if (!DeletedFrame && !toIndex->Write(Independent, toFileName->Number(), fileSize, Errors, Missing)) { error = "toIndex"; return false; } + frameErrors += Errors + Missing; + HandleErrors(); // Write data: if (toFile->Write(Buffer, Length) < 0) { error = "safe_write"; @@ -596,6 +608,21 @@ bool cCuttingThread::ProcessSequence(int LastEndIndex, int BeginIndex, int EndIn return true; } +#define ERROR_HANDLING_DELTA 1 // seconds between handling errors + +void cCuttingThread::HandleErrors(bool Force) +{ + if (Force || time(NULL) - lastErrorHandling >= ERROR_HANDLING_DELTA) { + if (frameErrors > recordingInfo->Errors()) { + recordingInfo->SetErrors(frameErrors); + recordingInfo->Write(); + LOCK_RECORDINGS_WRITE; + Recordings->UpdateByName(editedRecordingName); + } + lastErrorHandling = time(NULL); + } +} + void cCuttingThread::Action(void) { if (cMark *BeginMark = fromMarks.GetNextBegin()) { @@ -634,6 +661,7 @@ void cCuttingThread::Action(void) } } } + HandleErrors(true); } else esyslog("no editing marks found!"); @@ -642,6 +670,7 @@ void cCuttingThread::Action(void) // --- cCutter --------------------------------------------------------------- cCutter::cCutter(const char *FileName) +:recordingInfo(FileName) { cuttingThread = NULL; error = false; @@ -676,9 +705,11 @@ bool cCutter::Start(void) if (strcmp(originalVersionName, editedVersionName) != 0) { // names must be different! cRecordingUserCommand::InvokeCommand(RUC_EDITINGRECORDING, editedVersionName, originalVersionName); if (cVideoDirectory::RemoveVideoFile(editedVersionName) && MakeDirs(editedVersionName, true)) { - Recording.WriteInfo(editedVersionName); + recordingInfo.Read(); + recordingInfo.SetErrors(0); + recordingInfo.SetFileName(editedVersionName); SetRecordingTimerId(editedVersionName, cString::sprintf("%d@%s", 0, Setup.SVDRPHostName)); - cuttingThread = new cCuttingThread(originalVersionName, editedVersionName); + cuttingThread = new cCuttingThread(originalVersionName, editedVersionName, &recordingInfo); return true; } } diff --git a/cutter.h b/cutter.h index c67429a1..fc87c842 100644 --- a/cutter.h +++ b/cutter.h @@ -4,12 +4,13 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: cutter.h 3.1 2013/10/05 11:34:55 kls Exp $ + * $Id: cutter.h 5.1 2024/09/19 20:21:58 kls Exp $ */ #ifndef __CUTTER_H #define __CUTTER_H +#include "recording.h" #include "thread.h" #include "tools.h" @@ -19,6 +20,7 @@ class cCutter { private: cString originalVersionName; cString editedVersionName; + cRecordingInfo recordingInfo; cCuttingThread *cuttingThread; bool error; public: diff --git a/recording.c b/recording.c index 6ce31fab..3edb13c4 100644 --- a/recording.c +++ b/recording.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: recording.c 5.33 2024/09/19 12:06:55 kls Exp $ + * $Id: recording.c 5.34 2024/09/19 20:21:58 kls Exp $ */ #include "recording.h" @@ -2946,7 +2946,7 @@ bool cIndexFile::Write(bool Independent, uint16_t FileNumber, off_t FileOffset, return f >= 0; } -bool cIndexFile::Get(int Index, uint16_t *FileNumber, off_t *FileOffset, bool *Independent, int *Length) +bool cIndexFile::Get(int Index, uint16_t *FileNumber, off_t *FileOffset, bool *Independent, int *Length, bool *Errors, bool *Missing) { if (CatchUp(Index)) { if (Index >= 0 && Index <= last) { @@ -2966,6 +2966,10 @@ bool cIndexFile::Get(int Index, uint16_t *FileNumber, off_t *FileOffset, bool *I else *Length = -1; } + if (Errors) + *Errors = index[Index].errors; + if (Missing) + *Missing = index[Index].missing; return true; } } diff --git a/recording.h b/recording.h index c58575d1..8bc0547c 100644 --- a/recording.h +++ b/recording.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: recording.h 5.10 2024/09/19 09:49:02 kls Exp $ + * $Id: recording.h 5.11 2024/09/19 20:21:58 kls Exp $ */ #ifndef __RECORDING_H @@ -504,7 +504,7 @@ public: ~cIndexFile(); bool Ok(void) { return index != NULL; } bool Write(bool Independent, uint16_t FileNumber, off_t FileOffset, bool Errors = false, bool Missing = false); - bool Get(int Index, uint16_t *FileNumber, off_t *FileOffset, bool *Independent = NULL, int *Length = NULL); + bool Get(int Index, uint16_t *FileNumber, off_t *FileOffset, bool *Independent = NULL, int *Length = NULL, bool *Errors = NULL, bool *Missing = NULL); const cErrors *GetErrors(void); ///< Returns the frame indexes of errors in the recording (if any). int GetNextIFrame(int Index, bool Forward, uint16_t *FileNumber = NULL, off_t *FileOffset = NULL, int *Length = NULL); diff --git a/vdr.5 b/vdr.5 index 90ab93a9..09cebeae 100644 --- a/vdr.5 +++ b/vdr.5 @@ -8,7 +8,7 @@ .\" License as specified in the file COPYING that comes with the .\" vdr distribution. .\" -.\" $Id: vdr.5 5.10 2024/09/09 10:58:55 kls Exp $ +.\" $Id: vdr.5 5.11 2024/09/19 20:21:58 kls Exp $ .\" .TH vdr 5 "27 Dec 2021" "2.7" "Video Disk Recorder Files" .SH NAME @@ -824,7 +824,7 @@ l l. The 'O' tag contains the number of errors that occurred during recording. If it is zero, the recording can be safely considered error free. The higher the value, the more damaged the recording is. -If this is an edited recording, the number of errors is that of the original +If this is an edited recording, the number of errors is that of the edited recording. .SS RESUME The file \fIresume\fR (if present in a recording directory) contains