]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
dvr: make data error threshold configurable master
authorBernhard Berger <bernhard.berger@gmail.com>
Sun, 31 May 2026 21:28:26 +0000 (23:28 +0200)
committerFlole <Flole998@users.noreply.github.com>
Sat, 6 Jun 2026 21:55:08 +0000 (23:55 +0200)
src/dvr/dvr.h
src/dvr/dvr_config.c
src/dvr/dvr_db.c

index ce85a59c46ee16e51942e8d3b6afb599b0011b68..8e3ec49e458ce1ca0e3cbcb3e426414efdaa4a22 100644 (file)
@@ -78,6 +78,7 @@ typedef struct dvr_config {
   int dvr_clone;
   int dvr_complex_scheduling;
   uint32_t dvr_rerecord_errors;
+  uint32_t dvr_max_data_errors;
   uint32_t dvr_retention_days;
   uint32_t dvr_removal_days;
   uint32_t dvr_removal_after_playback;
@@ -557,6 +558,13 @@ uint32_t dvr_entry_get_removal_days( dvr_entry_t *de );
 
 uint32_t dvr_entry_get_rerecord_errors( dvr_entry_t *de );
 
+static inline uint32_t dvr_entry_get_max_data_errors( dvr_entry_t *de )
+  { return de->de_config ? de->de_config->dvr_max_data_errors : DVR_MAX_DATA_ERRORS; }
+
+static inline int dvr_entry_data_error_limit_reached( dvr_entry_t *de )
+  { uint32_t max_data_errors = dvr_entry_get_max_data_errors(de);
+    return max_data_errors && de->de_data_errors >= max_data_errors; }
+
 int dvr_entry_get_epg_running( dvr_entry_t *de );
 
 time_t dvr_entry_get_start_time( dvr_entry_t *de, int warm );
index b2eb76828b2394a981ca3f367889a8c0d4e5bc9c..b4f396689bf826ed303e4e7f3221927a987b6749 100644 (file)
@@ -178,6 +178,7 @@ dvr_config_create(const char *name, const char *uuid, htsmsg_t *conf)
   cfg->dvr_config_name = strdup(name);
   cfg->dvr_retention_days = DVR_RET_ONREMOVE;
   cfg->dvr_removal_days = DVR_RET_REM_FOREVER;
+  cfg->dvr_max_data_errors = DVR_MAX_DATA_ERRORS;
   cfg->dvr_clone = 1;
   cfg->dvr_tag_files = 1;
   cfg->dvr_create_scene_markers = 1;
@@ -1095,6 +1096,18 @@ const idclass_t dvr_config_class = {
       .opts     = PO_ADVANCED,
       .group    = 1,
     },
+    {
+      .type     = PT_U32,
+      .id       = "data-error-threshold",
+      .name     = N_("Data error threshold for failed recordings (0=off)"),
+      .desc     = N_("If a completed recording has this many or more data "
+                     "errors, mark it as failed. Set to 0 to disable this "
+                     "check."),
+      .off      = offsetof(dvr_config_t, dvr_max_data_errors),
+      .opts     = PO_ADVANCED,
+      .def.u32  = DVR_MAX_DATA_ERRORS,
+      .group    = 1,
+    },
     {
       .type     = PT_BOOL,
       .id       = "complex-scheduling",
index 61b0e260c1d43392794a9188073a4a32e405c8cb..171cb5f7678aad1c991581585da7a0e11a51d7b7 100644 (file)
@@ -161,7 +161,7 @@ int dvr_entry_is_finished(dvr_entry_t *entry, int flags)
 
   if (success) {
     if (entry->de_last_error == SM_CODE_OK)
-      success = entry->de_data_errors < DVR_MAX_DATA_ERRORS;
+      success = !dvr_entry_data_error_limit_reached(entry);
     else
       success = dvr_entry_is_completed_ok(entry);
   }
@@ -679,7 +679,7 @@ dvr_entry_status(dvr_entry_t *de)
     if (dvr_get_filesize(de, 0) < 0 && !de->de_file_removed)
       return N_("File missing");
     if(de->de_last_error != SM_CODE_FORCE_OK &&
-       de->de_data_errors >= DVR_MAX_DATA_ERRORS) /* user configurable threshold? */
+       dvr_entry_data_error_limit_reached(de))
       return N_("Too many data errors");
     if(de->de_last_error)
       return streaming_code2txt(de->de_last_error);