summaryrefslogtreecommitdiff
path: root/patch/0001-Record-TS-continuity-errors.patch
blob: c49cf5c7bf2e5fd1e7495aae037a7be66ce64f8b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
From 2e70ffdb5e8a7e06d48a5426c798fdae6df5abcf Mon Sep 17 00:00:00 2001
From: etobi <git@e-tobi.net>
Date: Sun, 2 Oct 2011 20:27:37 +0200
Subject: [PATCH] Record TS continuity errors

---
 recorder.c  |   11 +++++++++++
 recording.c |    9 +++++++++
 recording.h |    3 +++
 remux.c     |   41 +++++++++++++++++++++++++++++++++++++++++
 remux.h     |   25 +++++++++++++++++++++++++
 5 files changed, 89 insertions(+), 0 deletions(-)

diff --git a/recorder.c b/recorder.c
index a6cab47..182fb09 100644
--- a/recorder.c
+++ b/recorder.c
@@ -119,6 +119,7 @@ void cRecorder::Action(void)
   time_t t = time(NULL);
   bool InfoWritten = false;
   bool FirstIframeSeen = false;
+  cTsStreamErrorCounter TsStreamErrorCounter;
   while (Running()) {
         int r;
         uchar *b = ringBuffer->Get(r);
@@ -154,6 +155,16 @@ void cRecorder::Action(void)
                              fileSize += TS_SIZE;
                              }
                        }
+                    TsStreamErrorCounter.CheckTsPackets(b, Count);
+                    if (InfoWritten && TsStreamErrorCounter.ErrorCount() > 0) {
+                       cRecordingInfo RecordingInfo(recordingName);
+                       if (RecordingInfo.Read()) {
+                          RecordingInfo.SetErrorCount(RecordingInfo.ErrorCount() + TsStreamErrorCounter.ErrorCount());
+                          RecordingInfo.Write();
+                          Recordings.UpdateByName(recordingName);
+                          TsStreamErrorCounter.ResetErrorCount();
+                          }
+                       }
                     if (recordFile->Write(b, Count) < 0) {
                        LOG_ERROR_STR(fileName->Name());
                        break;
diff --git a/recording.c b/recording.c
index bea7eb6..47fd2c2 100644
--- a/recording.c
+++ b/recording.c
@@ -321,6 +321,7 @@ cRecordingInfo::cRecordingInfo(const cChannel *Channel, const cEvent *Event)
   event = ownEvent ? ownEvent : Event;
   aux = NULL;
   framesPerSecond = DEFAULTFRAMESPERSECOND;
+  errorCount = 0;
   priority = MAXPRIORITY;
   lifetime = MAXLIFETIME;
   fileName = NULL;
@@ -414,6 +415,11 @@ void cRecordingInfo::SetFramesPerSecond(double FramesPerSecond)
   framesPerSecond = FramesPerSecond;
 }
 
+void cRecordingInfo::SetErrorCount(int ErrorCount)
+{
+  errorCount = ErrorCount;
+}
+
 bool cRecordingInfo::Read(FILE *f)
 {
   if (ownEvent) {
@@ -453,6 +459,8 @@ bool cRecordingInfo::Read(FILE *f)
                        break;
              case 'F': framesPerSecond = atof(t);
                        break;
+             case 'R': errorCount = atoi(t);
+                       break;
              case 'L': lifetime = atoi(t);
                        break;
              case 'P': priority = atoi(t);
@@ -479,6 +487,7 @@ bool cRecordingInfo::Write(FILE *f, const char *Prefix) const
      fprintf(f, "%sC %s%s%s\n", Prefix, *channelID.ToString(), channelName ? " " : "", channelName ? channelName : "");
   event->Dump(f, Prefix, true);
   fprintf(f, "%sF %.10g\n", Prefix, framesPerSecond);
+  fprintf(f, "%sR %d\n", Prefix, errorCount);
   fprintf(f, "%sP %d\n", Prefix, priority);
   fprintf(f, "%sL %d\n", Prefix, lifetime);
   if (aux)
diff --git a/recording.h b/recording.h
index 37979ec..be03ecb 100644
--- a/recording.h
+++ b/recording.h
@@ -55,6 +55,7 @@ private:
   cEvent *ownEvent;
   char *aux;
   double framesPerSecond;
+  int errorCount;
   int priority;
   int lifetime;
   char *fileName;
@@ -75,6 +76,8 @@ public:
   const char *Aux(void) const { return aux; }
   double FramesPerSecond(void) const { return framesPerSecond; }
   void SetFramesPerSecond(double FramesPerSecond);
+  int ErrorCount(void) const { return errorCount; }
+  void SetErrorCount(int ErrorCount);
   bool Write(FILE *f, const char *Prefix = "") const;
   bool Read(void);
   bool Write(void) const;
diff --git a/remux.c b/remux.c
index 78ab294..eb6b0d9 100644
--- a/remux.c
+++ b/remux.c
@@ -1029,3 +1029,44 @@ int cFrameDetector::Analyze(const uchar *Data, int Length)
         }
   return Processed;
 }
+
+// --- cTsStreamErrorCounter -------------------------------------------------
+
+cTsStreamErrorCounter::cTsStreamErrorCounter(void)
+{
+  errorCount = 0;
+  for(int i=0; i < MAX_PIDS; i++) pids[i] = -1;
+  memset(counters, 0, sizeof(counters));
+}
+
+void cTsStreamErrorCounter::CheckTsPackets(uchar* Data, int Length)
+{
+  while (Length >= TS_SIZE) {
+        int pid = ((Data[1] & 0x1F) << 8) + Data[2];
+        char ctr = (Data[3] & 0x0F);
+        char adaption = (Data[3] & 0x30) >> 4;
+
+        if (adaption != 2)
+           CheckTsPacketContinuity(pid, ctr);
+
+        Length -= TS_SIZE;
+        Data += TS_SIZE;
+       }
+}
+
+void cTsStreamErrorCounter::CheckTsPacketContinuity(int pid, int counter)
+{
+  for (int i=0; i < MAX_PIDS; i++) {
+      if (pids[i] == -1) {
+         pids[i] = pid;
+         counters[i] = counter;
+         break;
+         }
+      if (pids[i] == pid) {
+         if (((counter - counters[i]) & 0x0F) != 1)
+            errorCount++;
+         counters[i] = counter;
+         break;
+         }
+      }
+}
diff --git a/remux.h b/remux.h
index b882279..72545e7 100644
--- a/remux.h
+++ b/remux.h
@@ -390,4 +390,29 @@ public:
       ///< available.
   };
 
+
+// TS stream error counter:
+// Count (continuity) errors in a TS packet stream
+
+#define MAX_PIDS 20
+
+class cTsStreamErrorCounter {
+private:
+  int errorCount;
+  int pids[MAX_PIDS];
+  uchar counters[MAX_PIDS];
+public:
+  cTsStreamErrorCounter(void);
+  void CheckTsPackets(uchar* Data, int Length);
+      ///< Check for errors in the TS packets pointed to by Data. Length is the
+      ///< number of bytes Data points to, and must be a multiple of 188.
+  int ErrorCount(void) const { return errorCount; };
+      ///< Return the number of errors found in the analyzed TS packet stream.
+      ///< Right now, only continuity errors are reported.
+  void ResetErrorCount(void) { errorCount = 0; };
+      ///< Reset error count to 0
+private:
+  void CheckTsPacketContinuity(int pid, int counter);
+  };
+
 #endif // __REMUX_H
-- 
1.7.6.3