Browse Source

Automatically change ECM pid if more than one is available

This allows tsdecrypt to automatically do the right thing
without having to use --ecm-pid option.

Tested on swiss viaccess encrypted streams.
Georgi Chorbadzhiyski 6 years ago
parent
commit
ac4a46b68a
3 changed files with 70 additions and 1 deletions
  1. 8
    0
      camd.c
  2. 4
    0
      data.h
  3. 58
    1
      tables.c

+ 8
- 0
camd.c View File

127
 		return 0;
127
 		return 0;
128
 
128
 
129
 	if (ret <= 0) {
129
 	if (ret <= 0) {
130
+		// get_cw returned error, lets try other ecm pids, we might be lucky...
131
+		if (ts->n_ecm_pids > 1) {
132
+			ts->ecm_pid_idx++;
133
+			if (ts->ecm_pid_idx + 1 > ts->n_ecm_pids)
134
+				ts->ecm_pid_idx = 0;
135
+			ts->ecm_pid = ts->ecm_pids[ts->ecm_pid_idx];
136
+			ts_LOGf("ECM | Switching ECM pid to 0x%04x (%d) idx:%d\n", ts->ecm_pid, ts->ecm_pid, ts->ecm_pid_idx);
137
+		}
130
 		if (ret == -1) { // Fatal error it is better to reconnect to server.
138
 		if (ret == -1) { // Fatal error it is better to reconnect to server.
131
 			ts_LOGf("ERR | No code word has been received (ret = %d)\n", ret);
139
 			ts_LOGf("ERR | No code word has been received (ret = %d)\n", ret);
132
 			camd_reconnect(c);
140
 			camd_reconnect(c);

+ 4
- 0
data.h View File

233
 };
233
 };
234
 
234
 
235
 #define MAX_PIDS 8192
235
 #define MAX_PIDS 8192
236
+#define MAX_ECM_PIDS 16
236
 
237
 
237
 struct ts {
238
 struct ts {
238
 	// Stream handling
239
 	// Stream handling
251
 	uint16_t			forced_service_id;
252
 	uint16_t			forced_service_id;
252
 	uint16_t			emm_caid, emm_pid;
253
 	uint16_t			emm_caid, emm_pid;
253
 	uint16_t			ecm_caid, ecm_pid;
254
 	uint16_t			ecm_caid, ecm_pid;
255
+	unsigned int		n_ecm_pids;
256
+	unsigned int		ecm_pid_idx;
257
+	uint16_t			ecm_pids[MAX_ECM_PIDS];
254
 	uint16_t			forced_caid;
258
 	uint16_t			forced_caid;
255
 	uint16_t			forced_emm_pid;
259
 	uint16_t			forced_emm_pid;
256
 	uint16_t			forced_ecm_pid;
260
 	uint16_t			forced_ecm_pid;

+ 58
- 1
tables.c View File

126
 	}
126
 	}
127
 }
127
 }
128
 
128
 
129
+// Copied from libtsfuncs with added logic to return more than one PID
130
+static int find_CA_descriptor(uint8_t *data, int data_len, enum CA_system req_CA_type, uint16_t *CA_id, uint16_t *CA_pid, uint16_t *CA_pids, unsigned int *n_pids) {
131
+	while (data_len >= 2) {
132
+		uint8_t tag         = data[0];
133
+		uint8_t this_length = data[1];
134
+		data     += 2;
135
+		data_len -= 2;
136
+		if (tag == 9 && this_length >= 4) {
137
+			uint16_t CA_ID = (data[0] << 8) | data[1];
138
+			uint16_t CA_PID = ((data[2] & 0x1F) << 8) | data[3];
139
+			if (ts_get_CA_sys(CA_ID) == req_CA_type) {
140
+				*CA_id = CA_ID;
141
+				*CA_pid = CA_PID;
142
+				if (*n_pids < MAX_ECM_PIDS) {
143
+					unsigned int i, exist = 0;
144
+					for (i = 0; i < MAX_ECM_PIDS; i++) {
145
+						if (CA_pids[i] == CA_PID) {
146
+							exist = 1;
147
+							break;
148
+						}
149
+					}
150
+					if (!exist) {
151
+						CA_pids[(*n_pids)++] = CA_PID;
152
+					}
153
+				}
154
+			}
155
+		}
156
+		data_len -= this_length;
157
+		data += this_length;
158
+	}
159
+	return 0;
160
+}
161
+
162
+// Copied from libtsfuncs with added logic to return more than one PID
163
+int __ts_get_ecm_info(struct ts_pmt *pmt, enum CA_system req_CA_type, uint16_t *CA_id, uint16_t *CA_pid, uint16_t *CA_pids, unsigned int *n_pids) {
164
+	int i, result = find_CA_descriptor(pmt->program_info, pmt->program_info_size, req_CA_type, CA_id, CA_pid, CA_pids, n_pids);
165
+	if (!result) {
166
+		for(i=0;i<pmt->streams_num;i++) {
167
+			struct ts_pmt_stream *stream = pmt->streams[i];
168
+			if (stream->ES_info) {
169
+				result = find_CA_descriptor(stream->ES_info, stream->ES_info_size, req_CA_type, CA_id, CA_pid, CA_pids, n_pids);
170
+				if (result)
171
+					break;
172
+			}
173
+		}
174
+	}
175
+	return result;
176
+}
177
+
129
 void process_pmt(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
178
 void process_pmt(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
130
 	int i;
179
 	int i;
131
 	if (!pid || pid != ts->pmt_pid)
180
 	if (!pid || pid != ts->pmt_pid)
156
 	if (ts->camd.constant_codeword)
205
 	if (ts->camd.constant_codeword)
157
 		return;
206
 		return;
158
 
207
 
208
+	ts->n_ecm_pids = 0;
159
 	if (ts->forced_caid) {
209
 	if (ts->forced_caid) {
160
 		ts->ecm_caid = ts->forced_caid;
210
 		ts->ecm_caid = ts->forced_caid;
161
 		ts_get_ecm_info_by_caid(ts->pmt, ts->ecm_caid, &ts->ecm_pid);
211
 		ts_get_ecm_info_by_caid(ts->pmt, ts->ecm_caid, &ts->ecm_pid);
212
+		ts->n_ecm_pids = 1; // TODO/FIXME: We should get the list of PIDS similar to how __ts_get_ecm_info does it
213
+		ts->ecm_pids[0] = ts->ecm_pid;
162
 	} else {
214
 	} else {
163
-		ts_get_ecm_info(ts->pmt, ts->req_CA_sys, &ts->ecm_caid, &ts->ecm_pid);
215
+		__ts_get_ecm_info(ts->pmt, ts->req_CA_sys, &ts->ecm_caid, &ts->ecm_pid, &ts->ecm_pids[0], &ts->n_ecm_pids);
164
 	}
216
 	}
165
 
217
 
166
 	if (ts->forced_ecm_pid)
218
 	if (ts->forced_ecm_pid)
176
 				ts->ecm_pid, CA_sys, ts->forced_ecm_pid);
228
 				ts->ecm_pid, CA_sys, ts->forced_ecm_pid);
177
 			ts->ecm_pid = ts->forced_ecm_pid;
229
 			ts->ecm_pid = ts->forced_ecm_pid;
178
 		}
230
 		}
231
+		if (ts->n_ecm_pids > 1) {
232
+			for (i = 0; i < (int)ts->n_ecm_pids; i++) {
233
+				ts_LOGf("--- | ECM pid : 0x%04x (%s) idx:%d\n", ts->ecm_pids[i], CA_sys, i);
234
+			}
235
+		}
179
 	} else {
236
 	} else {
180
 		ts_LOGf("*** | ERROR: Can't detect ECM pid.\n");
237
 		ts_LOGf("*** | ERROR: Can't detect ECM pid.\n");
181
 	}
238
 	}

Loading…
Cancel
Save