Browse Source

Add support for LCN descriptor.

Georgi Makedonski 6 years ago
parent
commit
e1c1b54c88
4 changed files with 140 additions and 12 deletions
  1. 26 12
      descs.c
  2. 109 0
      nit_desc.c
  3. 1 0
      sections.c
  4. 4 0
      tsfuncs.h

+ 26 - 12
descs.c View File

@@ -438,6 +438,17 @@ void ts_descriptor_dump(uint8_t *desc_data, int desc_data_len) {
438 438
 				}
439 439
 				break;
440 440
 			}
441
+			case 0x5f: { // Private NorDig descriptor
442
+				ts_LOGf("%sTag 0x%02x (%02d), sz: %d, Private Nordig descriptor:\n", pad, tag, tag, this_length);
443
+				for (i=0; i<this_length; i+=4) {
444
+					uint8_t u1 = data[i + 0] ;
445
+					uint8_t u2 = data[i + 1] ;
446
+					uint8_t u3 = data[i + 2] ;
447
+					uint8_t u4 = data[i + 3] ;
448
+					ts_LOGf("%s  Data1: 0x%02x Data2: %02x Data3: %02x Data4: %02x\n", pad, u1, u2, u3 ,u4);
449
+				}
450
+				break;
451
+			}
441 452
 			case 0x62: { // frequency_list_descriptor
442 453
 				ts_LOGf("%sTag 0x%02x (%02d), sz: %d, Frequency_list_descriptor\n", pad, tag, tag, this_length);
443 454
 				uint8_t reserved    = data[0] >> 2;		// 111111xx
@@ -469,23 +480,26 @@ void ts_descriptor_dump(uint8_t *desc_data, int desc_data_len) {
469 480
 				ts_LOGf("%sTag 0x%02x (%02d), sz: %d, AC-3 descriptor\n", pad, tag, tag, this_length);
470 481
 				break;
471 482
 			}
472
-/*
473
-			case 0x87: { // Private descriptor! LCN Logical channel descriptor
483
+
484
+			case 0x83: { // Private descriptor! LCN Logical channel descriptor
474 485
 				ts_LOGf("%sTag 0x%02x (%02d), sz: %d, Logical channel descriptor\n", pad, tag, tag, this_length);
475
-				for (i=0; i<= this_length; i+=4) {
476
-					uint16_t service_id = (data[0+i] << 8) | data[1+i];	// xxxxxxxx xxxxxxxx
477
-					uint8_t  visible    = (data[2+i] >> 7);				// x1111111
478
-//					uint8_t  reserved1  = (data[2+i] &~ 0x80) >> 2;		// 1xxxxx11
479
-					uint16_t lcn        = (data[2+i] &~ 0x3f);			// 111111xx
480
-					         lcn       |=  data[3+i];					// xxxxxxxx
486
+				for (i=0; i<this_length; i+=4) {
487
+					uint16_t service_id;
488
+					uint8_t visible;
489
+//					uint8_t reserved1;
490
+					uint16_t lcn;
491
+					service_id   = data[i + 0] << 8;
492
+					service_id  |= data[i + 1];
493
+					visible      = data[i+2] >> 7;			// x1111111
494
+//					reserved1    = data[i+2] &~ 0x80 >> 6;		// 1x111111
495
+					lcn          = data[i+2] &~ 0xc0 << 8;		// 11xxxxxx
496
+					lcn         |= data[i+3];			// xxxxxxxx
481 497
 					ts_LOGf("%s  Service_ID: 0x%04x (%4d) LCN: %3d Visible: %d\n",
482
-						pad,
483
-						service_id, service_id,
484
-						lcn, visible);
498
+						pad, service_id, service_id, lcn, visible);
485 499
 				}
486 500
 				break;
487 501
 			}
488
-*/
502
+
489 503
 			default: {
490 504
 				char *dump = ts_hex_dump(data, this_length, 0);
491 505
 				ts_LOGf("%s*** Unknown Tag 0x%02x (%02d), sz: %d, data: %s\n", pad, tag, tag, this_length, dump);

+ 109 - 0
nit_desc.c View File

@@ -186,3 +186,112 @@ int ts_nit_add_service_list_descriptor(struct ts_nit *nit, uint16_t ts_id, uint1
186 186
 	}
187 187
 	return ts_nit_add_stream(nit, ts_id, org_net_id, desc, desc_size);
188 188
 }
189
+
190
+int ts_nit_add_nordig_specifier_descriptor(struct ts_nit *nit, uint16_t ts_id, uint16_t org_net_id) {
191
+	int desc_size = 2 + 4;		// 2 for header desc header, 3 for each service
192
+	uint8_t *desc = calloc(1, desc_size);
193
+	int dpos = 0;
194
+	desc[dpos + 0] = 0x5f;				// service_list_descriptor
195
+	desc[dpos + 1] = desc_size - 2;		// -2 Because of two byte header
196
+	desc[dpos + 2] = 0x00;				// -2 Because of two byte header
197
+	desc[dpos + 3] = 0x00;				// -2 Because of two byte header
198
+	desc[dpos + 4] = 0x00;				// -2 Because of two byte header
199
+	desc[dpos + 5] = 0x29;				// -2 Because of two byte header
200
+	dpos += 6;
201
+
202
+	return ts_nit_add_stream(nit, ts_id, org_net_id, desc, desc_size);
203
+}
204
+
205
+int ts_nit_add_lcn_descriptor(struct ts_nit *nit, uint16_t ts_id, uint16_t org_net_id, uint32_t *services, uint8_t num_services) {
206
+	uint8_t i;
207
+	if (!num_services || num_services > 85) 		// 85 * 3 == 255
208
+		return 0;
209
+	int desc_size = 2 + num_services * 4;			// 2 for header desc header, 4 for each service
210
+	uint8_t *desc = calloc(1, desc_size);
211
+	int dpos = 0;
212
+	desc[dpos + 0] = 0x83;					// service_lcn_descriptor
213
+	desc[dpos + 1] = desc_size - 2;				// -2 Because of two byte header
214
+	dpos += 2;
215
+	for(i=0;i<num_services;i++) {
216
+		uint32_t srv = services[i];
217
+		desc[dpos + 0] = (srv &~ 0x00ffffff) >> 24;	// service_id (16 bits)
218
+		desc[dpos + 1] = (srv &~ 0xff00ffff) >> 16;	// service_id
219
+		desc[dpos + 2] = (srv &~ 0xffff00ff) >>  8;	// visible (1 bit), private (1 bit), first (6 bits) from lcn_number 
220
+		desc[dpos + 3] = (srv &~ 0xffffff00);		// second (8 bits) lcn_number
221
+		dpos += 4;
222
+	}
223
+	return ts_nit_add_stream(nit, ts_id, org_net_id, desc, desc_size);
224
+}
225
+
226
+
227
+int ts_nit_add_stream_descriptors(struct ts_nit *nit, uint16_t ts_id, uint16_t org_net_id, uint32_t freq, uint8_t modulation, uint32_t symbol_rate, uint32_t *lcn_services, uint32_t *svc_services, uint8_t num_services) {
228
+	
229
+	int desc_size = 13 + 6 + 2 + 2 + num_services * 4 + num_services * 3;		// 2 for header desc header, + ....
230
+	
231
+	uint8_t *desc = calloc(1, desc_size);
232
+
233
+	desc[ 0] = 0x44;							// cable_delivey_system_descriptor
234
+	desc[ 1] = 11;								// -2 Because of two byte header
235
+	desc[ 2] = ((freq &~ 0x00ffffff) >> 24);	// 32 bits, frequency
236
+	desc[ 3] = ((freq &~ 0xff00ffff) >> 16);
237
+	desc[ 4] = ((freq &~ 0xffff00ff) >>  8);
238
+	desc[ 5] =  (freq &~ 0xffffff00);
239
+	desc[ 6] = 0xff;								// 8 bits reserved
240
+	desc[ 7] = 0xf0;								// 4 bits reserved, 4 bits FEC_outer (0 == not defined)
241
+	desc[ 8] = modulation;							// 8 bits reserved
242
+	desc[ 9] = (symbol_rate >> 20) &~ 0xffffff00;	// 28 bits, symbol_rate
243
+	desc[10] = (symbol_rate >> 12) &~ 0xffffff00;
244
+	desc[11] = (symbol_rate >> 4 ) &~ 0xffffff00;
245
+	desc[12] = (symbol_rate &~ 0xfffffff0) << 4;	// 4 bits
246
+	desc[12] |= 0;									// 4 bits FEC_inner (0 == not defined)
247
+
248
+	uint8_t i;
249
+	if (!num_services || num_services > 85) // 85 * 3 == 255
250
+		return 0;
251
+	
252
+	int desc_svc_size = 2 + num_services * 3;		// 2 for header desc header, 3 for each service
253
+	
254
+
255
+	int dpos = 13;
256
+
257
+	desc[dpos + 0] = 0x41;				// service_list_descriptor
258
+	desc[dpos + 1] = desc_svc_size - 2;		// -2 Because of two byte header
259
+	dpos += 2;
260
+	for(i=0;i<num_services;i++) {
261
+		uint32_t srv = svc_services[i];
262
+		desc[dpos + 0] = (srv &~ 0xff00ffff) >> 16;	// service_id (16 bits)
263
+		desc[dpos + 1] = (srv &~ 0xffff00ff) >>  8;
264
+		desc[dpos + 2] = (srv &~ 0xffffff00);		// service_type (8 bits)
265
+		dpos += 3;
266
+	}
267
+
268
+	int desc_prv_size = 2 + 4;		// 2 for header desc header, 3 for each service
269
+
270
+	desc[dpos + 0] = 0x5f;				// service_list_descriptor
271
+	desc[dpos + 1] = desc_prv_size - 2;		// -2 Because of two byte header
272
+	desc[dpos + 2] = 0x00;				// -2 Because of two byte header
273
+	desc[dpos + 3] = 0x00;				// -2 Because of two byte header
274
+	desc[dpos + 4] = 0x00;				// -2 Because of two byte header
275
+	desc[dpos + 5] = 0x29;				// -2 Because of two byte header
276
+	dpos += 6;
277
+
278
+	if (!num_services || num_services > 85) 		// 85 * 3 == 255
279
+		return 0;
280
+	int desc_lcn_size = 2 + num_services * 4;			// 2 for header desc header, 4 for each service
281
+
282
+	desc[dpos + 0] = 0x83;					// service_lcn_descriptor
283
+	desc[dpos + 1] = desc_lcn_size - 2;				// -2 Because of two byte header
284
+	dpos += 2;
285
+	for(i=0;i<(num_services);i++) {
286
+		uint32_t srv = lcn_services[i];
287
+		desc[dpos + 0] = (srv &~ 0x00ffffff) >> 24;	// service_id (16 bits)
288
+		desc[dpos + 1] = (srv &~ 0xff00ffff) >> 16;	// service_id
289
+		desc[dpos + 2] = (srv &~ 0xffff00ff) >>  8;	// visible (1 bit), private (1 bit), first (6 bits) from lcn_number 
290
+		desc[dpos + 3] = (srv &~ 0xffffff00);		// second (8 bits) lcn_number
291
+		dpos += 4;
292
+	}
293
+
294
+
295
+	return ts_nit_add_stream(nit, ts_id, org_net_id, desc, desc_size);
296
+}
297
+

+ 1 - 0
sections.c View File

@@ -127,6 +127,7 @@ void ts_section_header_dump(struct ts_section_header *t) {
127 127
 		t->table_id == 0x40         ? "network_information_section - actual_network" :
128 128
 		t->table_id == 0x41         ? "network_information_section - other_network" :
129 129
 		t->table_id == 0x42         ? "service_description_section - actual_transport_stream" :
130
+		t->table_id == 0x83         ? "lcn_description_section - other" :
130 131
 		IN(t->table_id, 0x43, 0x45) ? "reserved for future use" :
131 132
 		t->table_id == 0x46         ? "service_description_section - other_transport_stream" :
132 133
 		IN(t->table_id, 0x47, 0x49) ? "reserved for future use" :

+ 4 - 0
tsfuncs.h View File

@@ -205,6 +205,10 @@ int				ts_nit_add_network_name_descriptor			(struct ts_nit *nit, char *network_n
205 205
 int				ts_nit_add_frequency_list_descriptor_cable	(struct ts_nit *nit, uint16_t ts_id, uint16_t org_net_id, uint32_t *freqs, uint8_t num_freqs);
206 206
 int				ts_nit_add_cable_delivery_descriptor		(struct ts_nit *nit, uint16_t ts_id, uint16_t org_net_id, uint32_t freq, uint8_t modulation, uint32_t symbol_rate);
207 207
 int				ts_nit_add_service_list_descriptor			(struct ts_nit *nit, uint16_t ts_id, uint16_t org_net_id, uint32_t *services, uint8_t num_services);
208
+int				ts_nit_add_nordig_specifier_descriptor		(struct ts_nit *nit, uint16_t ts_id, uint16_t org_net_id);
209
+int				ts_nit_add_lcn_descriptor					(struct ts_nit *nit, uint16_t ts_id, uint16_t org_net_id, uint32_t *services, uint8_t num_services);
210
+int 			ts_nit_add_stream_descriptors				(struct ts_nit *nit, uint16_t ts_id, uint16_t org_net_id, uint32_t freq, uint8_t modulation, uint32_t symbol_rate, uint32_t *lcn_services, uint32_t *svc_services, uint8_t num_services);
211
+
208 212
 
209 213
 struct ts_nit *	ts_nit_copy			(struct ts_nit *nit);
210 214
 int				ts_nit_is_same		(struct ts_nit *nit1, struct ts_nit *nit2);