File: nit_desc.c

package info (click to toggle)
tsdecrypt 10.0-5
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,288 kB
  • sloc: ansic: 14,377; makefile: 245; sh: 166
file content (188 lines) | stat: -rw-r--r-- 6,643 bytes parent folder | download | duplicates (6)
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
/*
 * NIT descriptor generator
 * Copyright (C) 2010-2011 Unix Solutions Ltd.
 *
 * Released under MIT license.
 * See LICENSE-MIT.txt for license terms.
 */
#include <stdio.h>
#include <unistd.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>

#include "tsfuncs.h"

static void ts_nit_regenerate_packet_data(struct ts_nit *nit) {
	uint8_t *ts_packets;
	int num_packets;
	ts_nit_generate(nit, &ts_packets, &num_packets);
	memcpy(nit->section_header->packet_data, ts_packets, num_packets * TS_PACKET_SIZE);
	nit->section_header->num_packets = num_packets;
	free(ts_packets);
}

struct ts_nit *ts_nit_init(struct ts_nit *nit, uint16_t network_id) {
	nit->ts_header.pid            = 0x10;
	nit->ts_header.pusi           = 1;
	nit->ts_header.payload_field  = 1;
	nit->ts_header.payload_offset = 4;

	nit->section_header->table_id                 = 0x40;
	nit->section_header->version_number           = 1;
	nit->section_header->current_next_indicator   = 1;
	nit->section_header->section_syntax_indicator = 1;
	nit->section_header->private_indicator        = 1;
	nit->section_header->section_length           = 9 + 4; // Empty section, +4 (16+16) for NIT table data
	nit->section_header->ts_id_number             = network_id;
	nit->section_header->reserved1                = 3;
	nit->section_header->reserved2                = 3;

	nit->reserved1           = 0xf;
	nit->network_info_size   = 0;		// 16 bits
	nit->reserved2           = 0xf;
	nit->ts_loop_size        = 0;		// 16 bits

	nit->streams_num = 0;

	nit->initialized = 1;

	ts_nit_regenerate_packet_data(nit);

	return nit;
}

struct ts_nit *ts_nit_alloc_init(uint16_t network_id) {
	struct ts_nit *nit = ts_nit_alloc();
	if (!nit)
		return NULL;
	return ts_nit_init(nit, network_id);
}

int ts_nit_add_network_name_descriptor(struct ts_nit *nit, char *network_name) {
	if (!network_name || strlen(network_name) > 255)
		return 0;

	nit->network_info_size = strlen(network_name) + 2;

	uint8_t *descriptor = calloc(1, nit->network_info_size);
	int dpos = 0;
	descriptor[dpos + 0] = 0x40;						// Network name descriptor
	descriptor[dpos + 1] = nit->network_info_size - 2;	// -2 Because of two byte header
	dpos += 2;
	char *name = network_name;
	while (name[0]) {
		descriptor[dpos++] = name[0];
		name++;
	}
	nit->network_info = descriptor;
	nit->section_header->section_length += nit->network_info_size;

	ts_nit_regenerate_packet_data(nit);

	return 1;
}

static int ts_nit_add_stream(struct ts_nit *nit, uint16_t ts_id, uint16_t org_net_id, uint8_t *desc, uint8_t desc_size) {
	if (nit->streams_num == nit->streams_max - 1 || desc_size == 0) {
		FREE(desc);
		return 0;
	}

	int stream_len = 2 + 2 + 1 + 1 + desc_size;
	if (stream_len + nit->section_header->section_length > 4093) {
		ts_LOGf("NIT no space left, max 4093, current %d will become %d!\n",
			nit->section_header->section_length,
			stream_len + nit->section_header->section_length);
		free(desc);
		return 0;
	}

	nit->ts_loop_size                   += stream_len;
	nit->section_header->section_length += stream_len;

	struct ts_nit_stream *sinfo = calloc(1, sizeof(struct ts_nit_stream));
	sinfo->transport_stream_id = ts_id;			// 2 bytes
	sinfo->original_network_id = org_net_id;	// 2 bytes
	sinfo->reserved1           = 15;			// 1 byte
	sinfo->descriptor_size     = desc_size;		// 1 byte
	sinfo->descriptor_data     = desc;			// desc_size bytes

	nit->streams[nit->streams_num] = sinfo;
	nit->streams_num++;

	ts_nit_regenerate_packet_data(nit);

	return 1;
}

// freq_type 0 == undefined
// freq_type 1 == satellite
// freq_type 2 == cable
// freq_type 3 == terrestrial
static int ts_nit_add_frequency_list_descriptor(struct ts_nit *nit, uint16_t ts_id, uint16_t org_net_id, uint8_t freq_type, uint32_t *freqs, uint8_t num_freqs) {
	uint8_t i;
	if (!num_freqs || num_freqs > 63)
		return 0;
	int desc_size = 2 + 1 + num_freqs * 4;		// 2 for header desc header, 1 for coding type, 4 for each frequency
	uint8_t *desc = calloc(1, desc_size);
	int dpos = 0;
	desc[dpos + 0] = 0x62;				// frequency_list_descriptor
	desc[dpos + 1] = desc_size - 2;		// -2 Because of two byte header
	desc[dpos + 2] = 0xfc | freq_type;	// 6 bits reserved, 2 bits freq_type
	dpos += 3;
	for(i=0;i<num_freqs;i++) {
		uint32_t freq = freqs[i];
		desc[dpos + 0] = ((freq &~ 0x00ffffff) >> 24);
		desc[dpos + 1] = ((freq &~ 0xff00ffff) >> 16);
		desc[dpos + 2] = ((freq &~ 0xffff00ff) >>  8);
		desc[dpos + 3] =  (freq &~ 0xffffff00);
		dpos += 4;
	}
	return ts_nit_add_stream(nit, ts_id, org_net_id, desc, desc_size);
}


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) {
	return ts_nit_add_frequency_list_descriptor(nit, ts_id, org_net_id, 2, freqs, num_freqs);
}

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) {
	int desc_size = 13;
	uint8_t *desc = calloc(1, desc_size);
	desc[ 0] = 0x44;							// cable_delivey_system_descriptor
	desc[ 1] = 11;								// -2 Because of two byte header
	desc[ 2] = ((freq &~ 0x00ffffff) >> 24);	// 32 bits, frequency
	desc[ 3] = ((freq &~ 0xff00ffff) >> 16);
	desc[ 4] = ((freq &~ 0xffff00ff) >>  8);
	desc[ 5] =  (freq &~ 0xffffff00);
	desc[ 6] = 0xff;								// 8 bits reserved
	desc[ 7] = 0xf0;								// 4 bits reserved, 4 bits FEC_outer (0 == not defined)
	desc[ 8] = modulation;							// 8 bits reserved
	desc[ 9] = (symbol_rate >> 20) &~ 0xffffff00;	// 28 bits, symbol_rate
	desc[10] = (symbol_rate >> 12) &~ 0xffffff00;
	desc[11] = (symbol_rate >> 4 ) &~ 0xffffff00;
	desc[12] = (symbol_rate &~ 0xfffffff0) << 4;	// 4 bits
	desc[12] |= 0;									// 4 bits FEC_inner (0 == not defined)
	return ts_nit_add_stream(nit, ts_id, org_net_id, desc, desc_size);
}

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) {
	uint8_t i;
	if (!num_services || num_services > 85) // 85 * 3 == 255
		return 0;
	int desc_size = 2 + num_services * 3;		// 2 for header desc header, 3 for each service
	uint8_t *desc = calloc(1, desc_size);
	int dpos = 0;
	desc[dpos + 0] = 0x41;				// service_list_descriptor
	desc[dpos + 1] = desc_size - 2;		// -2 Because of two byte header
	dpos += 2;
	for(i=0;i<num_services;i++) {
		uint32_t srv = services[i];
		desc[dpos + 0] = (srv &~ 0xff00ffff) >> 16;	// service_id (16 bits)
		desc[dpos + 1] = (srv &~ 0xffff00ff) >>  8;
		desc[dpos + 2] = (srv &~ 0xffffff00);		// service_type (8 bits)
		dpos += 3;
	}
	return ts_nit_add_stream(nit, ts_id, org_net_id, desc, desc_size);
}