mirror of
https://github.com/vdr-projects/vdr.git
synced 2025-03-01 10:50:46 +00:00
The info file of an edited recording now contains the number of errors in the edited version
This commit is contained in:
parent
3d6b31b115
commit
292af5d4f4
5
HISTORY
5
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.
|
||||
|
6
config.h
6
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
|
||||
|
53
cutter.c
53
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;
|
||||
}
|
||||
}
|
||||
|
4
cutter.h
4
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:
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
4
vdr.5
4
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user