Browse Source

Report TS discontinuity in input stream

Georgi Chorbadzhiyski 13 years ago
parent
commit
7e24a02a29
5 changed files with 88 additions and 2 deletions
  1. 4
    0
      data.c
  2. 3
    0
      data.h
  3. 1
    1
      libts
  4. 74
    0
      process.c
  5. 6
    1
      tsdecrypt.c

+ 4
- 0
data.c View File

@@ -23,6 +23,8 @@ void data_init(struct ts *ts) {
23 23
 	ts->last_ecm = ts_privsec_alloc();
24 24
 
25 25
 	pidmap_clear(&ts->pidmap);
26
+	pidmap_clear(&ts->cc);
27
+	pidmap_clear(&ts->pid_seen);
26 28
 
27 29
 	// Key
28 30
 	memset(&ts->key, 0, sizeof(ts->key));
@@ -41,6 +43,8 @@ void data_init(struct ts *ts) {
41 43
 	strcpy(ts->camd35.pass, "pass");
42 44
 
43 45
 	// Config
46
+	ts->ts_discont  = 1;
47
+
44 48
 	ts->debug_level = 0;
45 49
 	ts->req_CA_sys  = CA_CONNAX;
46 50
 	ts->emm_send    = 1;

+ 3
- 0
data.h View File

@@ -81,6 +81,8 @@ struct ts {
81 81
 	uint16_t			ecm_caid, ecm_pid;
82 82
 	uint16_t			ecm_counter;
83 83
 	pidmap_t			pidmap;
84
+	pidmap_t			cc; // Continuity counters
85
+	pidmap_t			pid_seen;
84 86
 
85 87
 	// CAMD handling
86 88
 	struct key			key;
@@ -96,6 +98,7 @@ struct ts {
96 98
 	struct io			output;
97 99
 
98 100
 	int					debug_level;
101
+	int					ts_discont;
99 102
 
100 103
 	int					camd_stop;
101 104
 	int					is_cw_error;

+ 1
- 1
libts

@@ -1 +1 @@
1
-Subproject commit 69322e5eeff4826d5faceb0bcaef442f15fe5dab
1
+Subproject commit a2a3c0b9af834b7f598f0ec004ebe5cbf5487e4c

+ 74
- 0
process.c View File

@@ -1,4 +1,5 @@
1 1
 #include <unistd.h>
2
+#include <string.h>
2 3
 
3 4
 #include "data.h"
4 5
 #include "tables.h"
@@ -6,6 +7,47 @@
6 7
 static unsigned long ts_pack;
7 8
 static int ts_pack_shown;
8 9
 
10
+static char *get_pid_desc(struct ts *ts, uint16_t pid) {
11
+	int i;
12
+	uint16_t nitpid = 0x0010, pmtpid = 0xffff, pcrpid = 0xffff;
13
+
14
+	if (ts->pat->initialized) {
15
+		for (i=0;i<ts->pat->programs_num;i++) {
16
+			struct ts_pat_program *prg = ts->pat->programs[i];
17
+			if (prg->pid) {
18
+				if (prg->program == 0)
19
+					nitpid = prg->pid;
20
+			}
21
+		}
22
+	}
23
+
24
+	if (ts->pmt->initialized) {
25
+		pmtpid = ts->pmt->ts_header.pid;
26
+		pcrpid = ts->pmt->PCR_pid;
27
+		for (i=0;i<ts->pmt->streams_num;i++) {
28
+			struct ts_pmt_stream *stream = ts->pmt->streams[i];
29
+			if (pid == stream->pid)
30
+				return h222_stream_type_desc(stream->stream_type);
31
+		}
32
+	}
33
+
34
+	switch (pid) {
35
+		case 0x0000: return "PAT"; break;
36
+		case 0x0001: return "CAT"; break;
37
+		case 0x0011: return "SDT"; break;
38
+		case 0x0012: return "EPG"; break;
39
+		case 0x0014: return "TDT/TOT"; break;
40
+	}
41
+
42
+	if (pid == nitpid)		return "NIT";
43
+	else if (pid == pmtpid)	return "PMT";
44
+	else if (pid == pcrpid)	return "PCR";
45
+	else if (pid == ts->emm_pid)	return "EMM";
46
+	else if (pid == ts->ecm_pid)	return "ECM";
47
+
48
+	return "Unknown";
49
+}
50
+
9 51
 void show_ts_pack(struct ts *ts, uint16_t pid, char *wtf, char *extra, uint8_t *ts_packet) {
10 52
 	char cw1_dump[8 * 6];
11 53
 	char cw2_dump[8 * 6];
@@ -160,6 +202,36 @@ void *write_thread(void *_ts) {
160 202
 	return NULL;
161 203
 }
162 204
 
205
+static void detect_discontinuity(struct ts *ts, uint8_t *ts_packet) {
206
+	uint16_t pid;
207
+	uint8_t cur_cc, last_cc;
208
+
209
+	if (!ts->ts_discont)
210
+		return;
211
+
212
+	pid = ts_packet_get_pid(ts_packet);
213
+	cur_cc = ts_packet_get_cont(ts_packet);
214
+
215
+	if (!pidmap_get(&ts->pid_seen, pid)) {
216
+		if (strcmp(get_pid_desc(ts, pid), "Unknown") == 0)
217
+			return;
218
+
219
+		pidmap_set(&ts->pid_seen, pid);
220
+		pidmap_set_val(&ts->cc, pid, cur_cc);
221
+		ts_LOGf("Input PID 0x%03x appeared (%s)\n",
222
+				pid, get_pid_desc(ts, pid));
223
+		return;
224
+	}
225
+
226
+	last_cc = pidmap_get(&ts->cc, pid);
227
+	if (last_cc != cur_cc && ((last_cc + 1) & 0x0f) != cur_cc)
228
+		ts_LOGf("Input discontinuity (expected %2d got %2d) PID 0x%03x (%s)\n",
229
+				((last_cc + 1) & 0x0f), cur_cc,
230
+				pid,
231
+				get_pid_desc(ts, pid));
232
+	pidmap_set_val(&ts->cc, pid, cur_cc);
233
+}
234
+
163 235
 void process_packets(struct ts *ts, uint8_t *data, ssize_t data_len) {
164 236
 	ssize_t i;
165 237
 	for (i=0; i<data_len; i += 188) {
@@ -174,6 +246,8 @@ void process_packets(struct ts *ts, uint8_t *data, ssize_t data_len) {
174 246
 		process_emm(ts, pid, ts_packet);
175 247
 		process_ecm(ts, pid, ts_packet);
176 248
 
249
+		detect_discontinuity(ts, ts_packet);
250
+
177 251
 		if (!ts_pack_shown)
178 252
 			dump_ts_pack(ts, pid, ts_packet);
179 253
 

+ 6
- 1
tsdecrypt.c View File

@@ -35,6 +35,7 @@ static void show_help(struct ts *ts) {
35 35
 	printf("                   |    -I -              (read from STDIN, the default)\n");
36 36
 	printf("\n");
37 37
 	printf("    -c ca_system   | default: %s valid: IRDETO, CONNAX, CRYPTOWORKS\n", ts_get_CA_sys_txt(ts->req_CA_sys));
38
+	printf("    -z             | Detect discontinuty errors in input stream (default: %s).\n", ts->ts_discont ? "report" : "ignore");
38 39
 	printf("\n");
39 40
 	printf("  Output options:\n");
40 41
 	printf("    -O output      | Where to send output. Supports files and multicast\n");
@@ -92,7 +93,7 @@ static int parse_io_param(struct io *io, char *opt, int open_flags, mode_t open_
92 93
 
93 94
 static void parse_options(struct ts *ts, int argc, char **argv) {
94 95
 	int j, ca_err = 0, server_err = 1, input_addr_err = 0, output_addr_err = 0, output_intf_err = 0;
95
-	while ((j = getopt(argc, argv, "cFs:I:O:i:t:U:P:epD:h")) != -1) {
96
+	while ((j = getopt(argc, argv, "cFs:I:O:i:t:U:P:ezpD:h")) != -1) {
96 97
 		char *p = NULL;
97 98
 		switch (j) {
98 99
 			case 'c':
@@ -144,6 +145,9 @@ static void parse_options(struct ts *ts, int argc, char **argv) {
144 145
 				ts->camd35.pass[sizeof(ts->camd35.pass) - 1] = 0;
145 146
 				break;
146 147
 
148
+			case 'z':
149
+				ts->ts_discont = !ts->ts_discont;
150
+				break;
147 151
 			case 'e':
148 152
 				ts->emm_send = !ts->emm_send;
149 153
 				break;
@@ -192,6 +196,7 @@ static void parse_options(struct ts *ts, int argc, char **argv) {
192 196
 	ts_LOGf("Server pass: %s\n", ts->camd35.pass);
193 197
 	ts_LOGf("EMM send   : %s\n", ts->emm_send   ? "enabled" : "disabled");
194 198
 	ts_LOGf("PID filter : %s\n", ts->pid_filter ? "enabled" : "disabled");
199
+	ts_LOGf("TS discont : %s\n", ts->ts_discont ? "report" : "ignore");
195 200
 	ts->threaded = !(ts->input.type == FILE_IO && ts->input.fd != 0);
196 201
 	ts_LOGf("Decoding   : %s\n", ts->threaded ? "threaded" : "single thread");
197 202
 }

Loading…
Cancel
Save