|
@@ -9,182 +9,177 @@
|
9
|
9
|
|
10
|
10
|
struct ts_tdt *ts_tdt_alloc() {
|
11
|
11
|
struct ts_tdt *tdt = calloc(1, sizeof(struct ts_tdt));
|
12
|
|
- tdt->packet_data = malloc(TS_PACKET_SIZE);
|
13
|
|
- memset(tdt->packet_data, 0x32, TS_PACKET_SIZE);
|
|
12
|
+ tdt->section_header = ts_section_data_alloc();
|
14
|
13
|
return tdt;
|
15
|
14
|
}
|
16
|
15
|
|
17
|
16
|
void ts_tdt_free(struct ts_tdt **ptdt) {
|
18
|
17
|
struct ts_tdt *tdt = *ptdt;
|
19
|
18
|
if (tdt) {
|
20
|
|
- FREE(tdt->packet_data);
|
|
19
|
+ ts_section_data_free(&tdt->section_header);
|
21
|
20
|
FREE(tdt->descriptors);
|
22
|
21
|
FREE(*ptdt);
|
23
|
22
|
}
|
24
|
23
|
}
|
25
|
24
|
|
26
|
|
-static void ts_tdt_init_empty(struct ts_tdt *tdt, time_t ts, int tot) {
|
27
|
|
- tdt->ts_header.pid = 0x14;
|
28
|
|
- tdt->ts_header.pusi = 1;
|
29
|
|
- tdt->ts_header.payload_field = 1;
|
30
|
|
- tdt->ts_header.payload_offset = 4;
|
31
|
|
- tdt->ts_header.continuity = 7;
|
32
|
|
-
|
33
|
|
- tdt->table_id = 0x70;
|
34
|
|
- tdt->section_syntax_indicator = 0;
|
35
|
|
- tdt->reserved_1 = 1;
|
36
|
|
- tdt->reserved_2 = 3;
|
37
|
|
- tdt->section_length = 5;
|
38
|
|
-
|
39
|
|
- ts_time_encode_mjd(&tdt->mjd, &tdt->bcd, &ts, NULL);
|
|
25
|
+static struct ts_tdt *ts_tdt_reset(struct ts_tdt *tdt) {
|
|
26
|
+ struct ts_tdt *newtdt = ts_tdt_alloc();
|
|
27
|
+ ts_tdt_free(&tdt);
|
|
28
|
+ return newtdt;
|
|
29
|
+}
|
|
30
|
+
|
|
31
|
+struct ts_tdt *ts_tdt_push_packet(struct ts_tdt *tdt, uint8_t *ts_packet) {
|
|
32
|
+ struct ts_header ts_header;
|
|
33
|
+ memset(&ts_header, 0, sizeof(struct ts_header));
|
|
34
|
+
|
|
35
|
+ if (ts_packet_header_parse(ts_packet, &ts_header)) {
|
|
36
|
+ // TDT/TOT should be with PID 0x11
|
|
37
|
+ if (ts_header.pid != 0x14)
|
|
38
|
+ goto OUT;
|
|
39
|
+ if (!tdt->ts_header.pusi)
|
|
40
|
+ tdt->ts_header = ts_header;
|
|
41
|
+ }
|
|
42
|
+
|
|
43
|
+ if (ts_header.pusi) {
|
|
44
|
+ struct ts_section_header section_header;
|
|
45
|
+ memset(§ion_header, 0, sizeof(struct ts_section_header));
|
|
46
|
+
|
|
47
|
+ uint8_t *section_data = ts_section_header_parse(ts_packet, &tdt->ts_header, §ion_header);
|
|
48
|
+ if (!section_data) {
|
|
49
|
+ memset(&tdt->ts_header, 0, sizeof(struct ts_header));
|
|
50
|
+ goto OUT;
|
|
51
|
+ }
|
|
52
|
+ // table_id should be 0x70 (time_date_section)
|
|
53
|
+ // or table_id should be 0x73 (time_offset_section)
|
|
54
|
+ if (section_header.table_id != 0x70 && section_header.table_id != 0x73) {
|
|
55
|
+ memset(&tdt->ts_header, 0, sizeof(struct ts_header));
|
|
56
|
+ goto OUT;
|
|
57
|
+ }
|
|
58
|
+
|
|
59
|
+ // Set correct section_header
|
|
60
|
+ ts_section_header_parse(ts_packet, &tdt->ts_header, tdt->section_header);
|
|
61
|
+ }
|
|
62
|
+
|
|
63
|
+ if (!tdt->initialized) {
|
|
64
|
+ ts_section_add_packet(tdt->section_header, &ts_header, ts_packet);
|
|
65
|
+ if (tdt->section_header->initialized) {
|
|
66
|
+ if (!ts_tdt_parse(tdt))
|
|
67
|
+ goto ERROR;
|
|
68
|
+ }
|
|
69
|
+ }
|
|
70
|
+
|
|
71
|
+OUT:
|
|
72
|
+ return tdt;
|
|
73
|
+
|
|
74
|
+ERROR:
|
|
75
|
+ return ts_tdt_reset(tdt);
|
|
76
|
+}
|
|
77
|
+
|
|
78
|
+int ts_tdt_parse(struct ts_tdt *tdt) {
|
|
79
|
+ struct ts_section_header *sec = tdt->section_header;
|
|
80
|
+ uint8_t *data = sec->data;
|
|
81
|
+
|
|
82
|
+ tdt->mjd = (data[0] << 8) | data[1];
|
|
83
|
+ tdt->bcd = ((data[2] << 16) | (data[3] << 8)) | data[4];
|
|
84
|
+ data += 5;
|
|
85
|
+
|
40
|
86
|
tdt->utc = ts_time_decode_mjd(tdt->mjd, tdt->bcd, &tdt->tm);
|
41
|
87
|
|
42
|
|
- if (tot) {
|
43
|
|
- tdt->table_id = 0x73;
|
44
|
|
- tdt->reserved_3 = 0xf;
|
45
|
|
- tdt->descriptors_size = 0;
|
46
|
|
- tdt->CRC = 0;
|
47
|
|
- tdt->section_length += 2 + 4; // 2 bytes reserved+descripts_size
|
48
|
|
- }
|
49
|
|
-
|
50
|
|
- ts_tdt_generate(tdt, tdt->packet_data);
|
51
|
|
-
|
52
|
|
- tdt->initialized = 1;
|
53
|
|
-}
|
54
|
|
-
|
55
|
|
-struct ts_tdt *ts_tdt_alloc_init(time_t ts) {
|
56
|
|
- struct ts_tdt *tdt = ts_tdt_alloc();
|
57
|
|
- ts_tdt_init_empty(tdt, ts, 0);
|
58
|
|
- return tdt;
|
59
|
|
-}
|
60
|
|
-
|
61
|
|
-struct ts_tdt *ts_tot_alloc_init(time_t ts) {
|
62
|
|
- struct ts_tdt *tdt = ts_tdt_alloc();
|
63
|
|
- ts_tdt_init_empty(tdt, ts, 1);
|
64
|
|
- return tdt;
|
65
|
|
-}
|
66
|
|
-
|
67
|
|
-static void ts_tdt_check_generator(struct ts_tdt *tdt) {
|
68
|
|
- struct ts_tdt *tdt1 = ts_tdt_alloc();
|
69
|
|
- ts_tdt_parse(tdt1, tdt->packet_data);
|
70
|
|
- ts_compare_data("TDT/TOT (packet->data)", tdt1->packet_data, tdt->packet_data, TS_PACKET_SIZE);
|
71
|
|
- ts_tdt_free(&tdt1);
|
72
|
|
-
|
73
|
|
- uint8_t *tmp = malloc(TS_PACKET_SIZE);
|
74
|
|
- ts_tdt_generate(tdt, tmp);
|
75
|
|
- ts_compare_data("TDT/TOT (data->packet)", tdt->packet_data, tmp, TS_PACKET_SIZE);
|
76
|
|
- free(tmp);
|
77
|
|
-}
|
78
|
|
-
|
79
|
|
-int ts_tdt_parse(struct ts_tdt *tdt, uint8_t *ts_packet) {
|
80
|
|
- uint8_t *data = ts_packet_header_parse(ts_packet, &tdt->ts_header);
|
81
|
|
-
|
82
|
|
- if (!data)
|
83
|
|
- return 0;
|
84
|
|
-
|
85
|
|
- if (tdt->ts_header.pid != 0x14) // TOT/TDT
|
86
|
|
- return 0;
|
87
|
|
-
|
88
|
|
- tdt->pointer_field = data[0];
|
89
|
|
- data += tdt->pointer_field + 1;
|
90
|
|
-
|
91
|
|
- if ((data + 8) - ts_packet > TS_PACKET_SIZE) {
|
92
|
|
- ts_LOGf("!!! Section start outside of TS packet!\n");
|
93
|
|
- return 0;
|
94
|
|
- }
|
95
|
|
-
|
96
|
|
- if (data[0] != 0x70 && data[0] != 0x73) { // TDT or TOT
|
97
|
|
- ts_LOGf("Invalid TDT/TOT Table_ID 0x%02x\n", data[0]);
|
98
|
|
- return 0;
|
99
|
|
- }
|
100
|
|
-
|
101
|
|
- tdt->table_id = data[0];
|
102
|
|
- tdt->section_syntax_indicator = data[1] >> 7; // x1111111
|
103
|
|
- tdt->reserved_1 = (data[1] &~ 0xBF) >> 6; // 1x111111
|
104
|
|
- tdt->reserved_2 = (data[1] &~ 0xCF) >> 4; // 11xx1111
|
105
|
|
- tdt->section_length = ((data[1] &~ 0xF0) << 8) | data[2]; // 1111xxxx xxxxxxxx
|
106
|
|
- if (tdt->section_length > TS_MAX_PAYLOAD_SIZE - 8) {
|
107
|
|
- ts_LOGf("TDT/TOT section length is too big: %d (max: %d)\n", tdt->section_length, TS_MAX_PAYLOAD_SIZE - 8);
|
108
|
|
- return 0;
|
109
|
|
- }
|
110
|
|
-
|
111
|
|
- tdt->mjd = (data[3] << 8) | data[4];
|
112
|
|
- tdt->bcd = ((data[5] << 16) | (data[6] << 8)) | data[7];
|
113
|
|
-
|
114
|
|
- if (tdt->table_id == 0x73) { // TOT
|
115
|
|
- tdt->reserved_3 = data[8] >> 4; // xxxx1111
|
116
|
|
- tdt->descriptors_size = data[8] &~ 0xf0; // 1111xxxx
|
117
|
|
- tdt->descriptors_size |= data[9]; // xxxxxxxx
|
118
|
|
- if (tdt->descriptors_size > TS_MAX_PAYLOAD_SIZE - 10) {
|
119
|
|
- ts_LOGf("TDT/TOT descriptors_size is too big: %d (max: %d)\n", tdt->descriptors_size, TS_MAX_PAYLOAD_SIZE - 10);
|
120
|
|
- return 0;
|
121
|
|
- }
|
|
88
|
+ if (sec->table_id == 0x73) { // TOT
|
|
89
|
+ tdt->reserved_3 = data[0] >> 4; // xxxx1111
|
|
90
|
+ tdt->descriptors_size = data[0] &~ 0xf0; // 1111xxxx
|
|
91
|
+ tdt->descriptors_size |= data[1]; // xxxxxxxx
|
|
92
|
+ data += 2;
|
122
|
93
|
if (tdt->descriptors_size) {
|
123
|
94
|
tdt->descriptors = malloc(tdt->descriptors_size);
|
124
|
|
- memcpy(tdt->descriptors, &data[10], tdt->descriptors_size);
|
|
95
|
+ memcpy(tdt->descriptors, data, tdt->descriptors_size);
|
125
|
96
|
}
|
126
|
|
- tdt->CRC = (tdt->CRC << 8) | data[10 + tdt->descriptors_size + 3];
|
127
|
|
- tdt->CRC = (tdt->CRC << 8) | data[10 + tdt->descriptors_size + 2];
|
128
|
|
- tdt->CRC = (tdt->CRC << 8) | data[10 + tdt->descriptors_size + 1];
|
129
|
|
- tdt->CRC = (tdt->CRC << 8) | data[10 + tdt->descriptors_size + 0];
|
|
97
|
+ if (!ts_crc32_section_check(tdt->section_header, "TOT"))
|
|
98
|
+ return 0;
|
130
|
99
|
}
|
131
|
100
|
|
132
|
|
- tdt->utc = ts_time_decode_mjd(tdt->mjd, tdt->bcd, &tdt->tm);
|
133
|
|
-
|
134
|
|
- memcpy(tdt->packet_data, ts_packet, TS_PACKET_SIZE);
|
135
|
|
-
|
136
|
101
|
tdt->initialized = 1;
|
137
|
|
-
|
138
|
102
|
return 1;
|
139
|
103
|
}
|
140
|
104
|
|
141
|
|
-void ts_tdt_generate(struct ts_tdt *tdt, uint8_t *ts_packet) {
|
142
|
|
- ts_packet_header_generate(ts_packet, &tdt->ts_header);
|
|
105
|
+void ts_tdt_generate(struct ts_tdt *tdt, uint8_t **ts_packets, int *num_packets) {
|
|
106
|
+ uint8_t *secdata = ts_section_data_alloc_section();
|
|
107
|
+ ts_section_header_generate(secdata, tdt->section_header, 0);
|
|
108
|
+ int curpos = 3; // Compensate for the section header, first data byte is at offset 3
|
143
|
109
|
|
144
|
|
- uint8_t start = 4;
|
145
|
|
- ts_packet[start + 0] = tdt->pointer_field;
|
146
|
|
- start += tdt->pointer_field + 1;
|
|
110
|
+ secdata[curpos + 0] = (tdt->mjd &~ 0x00ff) >> 8;
|
|
111
|
+ secdata[curpos + 1] = (tdt->mjd &~ 0xff00);
|
147
|
112
|
|
148
|
|
- ts_packet[start + 0] = tdt->table_id;
|
149
|
|
- ts_packet[start + 1] = tdt->section_syntax_indicator << 7; // x1111111
|
150
|
|
- ts_packet[start + 1] |= tdt->reserved_1 << 6; // 1x111111
|
151
|
|
- ts_packet[start + 1] |= tdt->reserved_2 << 4; // 11xx1111
|
152
|
|
- ts_packet[start + 1] |= tdt->section_length >> 8; // 1111xxxx xxxxxxxx
|
153
|
|
- ts_packet[start + 2] = tdt->section_length &~ 0xff00; // 1111xxxx xxxxxxxx
|
|
113
|
+ secdata[curpos + 2] = (tdt->bcd >> 16);
|
|
114
|
+ secdata[curpos + 3] = (tdt->bcd >> 8) &~ 0xff00;
|
|
115
|
+ secdata[curpos + 4] = (tdt->bcd << 16) >> 16;
|
|
116
|
+ curpos += 5; // For the fields above
|
154
|
117
|
|
155
|
|
- ts_packet[start + 3] = (tdt->mjd &~ 0x00ff) >> 8;
|
156
|
|
- ts_packet[start + 4] = (tdt->mjd &~ 0xff00);
|
|
118
|
+ if (tdt->section_header->table_id == 0x73) { // TOT
|
|
119
|
+ secdata[curpos + 0] = tdt->reserved_3 << 4;
|
|
120
|
+ secdata[curpos + 0] |= tdt->descriptors_size >> 8;
|
|
121
|
+ secdata[curpos + 1] = tdt->descriptors_size &~ 0xf00;
|
|
122
|
+ curpos += 2;
|
157
|
123
|
|
158
|
|
- ts_packet[start + 5] = (tdt->bcd >> 16);
|
159
|
|
- ts_packet[start + 6] = (tdt->bcd >> 8) &~ 0xff00;
|
160
|
|
- ts_packet[start + 7] = (tdt->bcd << 16) >> 16;
|
161
|
|
-
|
162
|
|
- if (tdt->table_id == 0x73) { // TOT
|
163
|
|
- ts_packet[start + 8] = tdt->reserved_3 << 4;
|
164
|
|
- ts_packet[start + 8] |= tdt->descriptors_size >> 8;
|
165
|
|
- ts_packet[start + 9] = tdt->descriptors_size &~ 0xf00;
|
166
|
|
- if (tdt->descriptors_size) {
|
167
|
|
- memcpy(&ts_packet[start + 10], tdt->descriptors, tdt->descriptors_size);
|
|
124
|
+ if (tdt->descriptors_size > 0) {
|
|
125
|
+ memcpy(secdata + curpos, tdt->descriptors, tdt->descriptors_size);
|
|
126
|
+ curpos += tdt->descriptors_size;
|
168
|
127
|
}
|
169
|
|
- tdt->CRC = ts_section_data_calculate_crc(ts_packet + start, 10 + tdt->descriptors_size);
|
|
128
|
+
|
|
129
|
+ tdt->section_header->CRC = ts_section_data_calculate_crc(secdata, curpos);
|
|
130
|
+ curpos += 4; // CRC
|
170
|
131
|
}
|
|
132
|
+
|
|
133
|
+ ts_section_data_gen_ts_packets(&tdt->ts_header, secdata, curpos, tdt->section_header->pointer_field, ts_packets, num_packets);
|
|
134
|
+
|
|
135
|
+ FREE(secdata);
|
|
136
|
+}
|
|
137
|
+
|
|
138
|
+void ts_tdt_check_generator(struct ts_tdt *tdt) {
|
|
139
|
+ struct ts_tdt *tdt1 = ts_tdt_alloc();
|
|
140
|
+ int i;
|
|
141
|
+
|
|
142
|
+ char *prefix1 = "TDT (tspacket->struct)";
|
|
143
|
+ char *prefix2 = "TDT (struct->tspacket)";
|
|
144
|
+ if (tdt->section_header->table_id == 0x73) {
|
|
145
|
+ prefix1[1] = 'O';
|
|
146
|
+ prefix2[1] = 'O';
|
|
147
|
+ }
|
|
148
|
+
|
|
149
|
+ for (i=0;i<tdt->section_header->num_packets;i++) {
|
|
150
|
+ tdt1 = ts_tdt_push_packet(tdt1, tdt->section_header->packet_data + (i * TS_PACKET_SIZE));
|
|
151
|
+ }
|
|
152
|
+
|
|
153
|
+ ts_compare_data(prefix1, // "TDT (tspacket->struct)",
|
|
154
|
+ tdt1->section_header->packet_data,
|
|
155
|
+ tdt->section_header->packet_data,
|
|
156
|
+ tdt->section_header->num_packets * TS_PACKET_SIZE);
|
|
157
|
+ ts_tdt_free(&tdt1);
|
|
158
|
+
|
|
159
|
+ uint8_t *ts_packets;
|
|
160
|
+ int num_packets;
|
|
161
|
+ ts_tdt_generate(tdt, &ts_packets, &num_packets);
|
|
162
|
+ if (num_packets != tdt->section_header->num_packets) {
|
|
163
|
+ ts_LOGf("ERROR: num_packets:%d != sec->num_packets:%d\n", num_packets, tdt->section_header->num_packets);
|
|
164
|
+ }
|
|
165
|
+ ts_compare_data(prefix2 /* "TDT (struct->tspacket)" */, tdt->section_header->packet_data, ts_packets, num_packets * TS_PACKET_SIZE);
|
|
166
|
+
|
|
167
|
+ free(ts_packets);
|
171
|
168
|
}
|
172
|
169
|
|
173
|
170
|
void ts_tdt_dump(struct ts_tdt *tdt) {
|
|
171
|
+ struct ts_section_header *sec = tdt->section_header;
|
174
|
172
|
struct tm tm;
|
175
|
173
|
time_t ts;
|
176
|
174
|
uint16_t mjd_check;
|
177
|
175
|
uint32_t bcd_check;
|
178
|
|
- char *prefix = tdt->table_id == 0x70 ? "TDT" : "TOT"; // TDT table_id == 0x70, TOT table_id == 0x73
|
|
176
|
+
|
|
177
|
+ ts_section_dump(sec);
|
179
|
178
|
|
180
|
179
|
ts = ts_time_decode_mjd(tdt->mjd, tdt->bcd, &tm);
|
181
|
180
|
ts_time_encode_mjd(&mjd_check, &bcd_check, &ts, &tm);
|
182
|
181
|
|
183
|
|
- ts_LOGf("%s packet dump\n", prefix);
|
184
|
|
- ts_packet_header_dump(&tdt->ts_header);
|
185
|
|
- ts_LOGf(" - Table id : %03x (%d) %s\n", tdt->table_id, tdt->table_id, prefix);
|
186
|
|
- ts_LOGf(" - Section length : %03x (%d)\n", tdt->section_length, tdt->section_length);
|
187
|
|
- ts_LOGf(" * %s data\n", prefix);
|
|
182
|
+ ts_LOGf(" * %s data\n", sec->table_id == 0x70 ? "TDT" : "TOT");
|
188
|
183
|
ts_LOGf(" - MJD : 0x%04x (%04d-%02d-%02d) unixts: %ld check:0x%04x\n",
|
189
|
184
|
tdt->mjd,
|
190
|
185
|
tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
|
|
@@ -193,132 +188,12 @@ void ts_tdt_dump(struct ts_tdt *tdt) {
|
193
|
188
|
tdt->bcd,
|
194
|
189
|
tm.tm_hour, tm.tm_min, tm.tm_sec,
|
195
|
190
|
bcd_check);
|
196
|
|
- ts_LOGf(" - UTC Time : %lu\n" , tdt->utc);
|
197
|
|
- if (tdt->table_id == 0x73) { // TOT
|
198
|
|
- if (tdt->descriptors) {
|
199
|
|
- ts_descriptor_dump(tdt->descriptors, tdt->descriptors_size);
|
200
|
|
- }
|
201
|
|
- ts_LOGf(" * CRC 0x%04x\n", tdt->CRC);
|
|
191
|
+ ts_LOGf(" - UTC Time : %lu (%04d-%02d-%02d %02d:%02d:%02d)\n" , tdt->utc,
|
|
192
|
+ tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
|
|
193
|
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
|
|
194
|
+ if (sec->table_id == 0x73 && tdt->descriptors_size) { // TOT
|
|
195
|
+ ts_descriptor_dump(tdt->descriptors, tdt->descriptors_size);
|
202
|
196
|
}
|
203
|
197
|
|
204
|
198
|
ts_tdt_check_generator(tdt);
|
205
|
199
|
}
|
206
|
|
-
|
207
|
|
-void ts_tdt_set_time(struct ts_tdt *tdt, time_t now) {
|
208
|
|
- tdt->ts_header.continuity++;
|
209
|
|
- ts_time_encode_mjd(&tdt->mjd, &tdt->bcd, &now, NULL);
|
210
|
|
- tdt->utc = ts_time_decode_mjd(tdt->mjd, tdt->bcd, &tdt->tm);
|
211
|
|
- ts_tdt_generate(tdt, tdt->packet_data);
|
212
|
|
-}
|
213
|
|
-
|
214
|
|
-void ts_tot_set_localtime_offset(struct ts_tdt *tdt, time_t now, time_t change_time, uint8_t polarity, uint16_t ofs, uint16_t ofs_next) {
|
215
|
|
- if (tdt->table_id != 0x73)
|
216
|
|
- return;
|
217
|
|
- tdt->ts_header.continuity++;
|
218
|
|
-
|
219
|
|
- ts_time_encode_mjd(&tdt->mjd, &tdt->bcd, &now, NULL);
|
220
|
|
- tdt->utc = ts_time_decode_mjd(tdt->mjd, tdt->bcd, &tdt->tm);
|
221
|
|
-
|
222
|
|
- uint16_t mjd = 0;
|
223
|
|
- uint32_t bcd = 0;
|
224
|
|
- ts_time_encode_mjd(&mjd, &bcd, &change_time, NULL);
|
225
|
|
-
|
226
|
|
- uint8_t *lto; // Local time offset
|
227
|
|
- if (tdt->descriptors_size == 0) {
|
228
|
|
- tdt->descriptors_size = 15;
|
229
|
|
- tdt->descriptors = calloc(1, tdt->descriptors_size);
|
230
|
|
- tdt->section_length += tdt->descriptors_size;
|
231
|
|
- }
|
232
|
|
- lto = tdt->descriptors;
|
233
|
|
- lto[0 ] = 0x58; // Descriptor tag
|
234
|
|
- lto[1 ] = 13; // 13 octets
|
235
|
|
- lto[2 + 0] = 'B'; // Country code
|
236
|
|
- lto[2 + 1] = 'U';
|
237
|
|
- lto[2 + 2] = 'L';
|
238
|
|
- lto[2 + 3] = 0; // 111111xx (Country region, 6 bit)
|
239
|
|
- lto[2 + 3] |= bit_2; // xxxxxx1x (Reserved, 1 bit) !!!!
|
240
|
|
- lto[2 + 3] |= polarity; // xxxxxxx1 (Polarity, 1 bit, 0 +utc, 1 -utc) !!!!
|
241
|
|
-
|
242
|
|
- lto[2 + 4] = ofs >> 8; // (LocalTime offset 16 bits, bcd)
|
243
|
|
- lto[2 + 5] = ofs &~ 0xff00;
|
244
|
|
-
|
245
|
|
- lto[2 + 6] = mjd >> 8; // Time of change (40 bcd)
|
246
|
|
- lto[2 + 7] = mjd &~ 0xff00;
|
247
|
|
- lto[2 + 8] = bcd >> 16;
|
248
|
|
- lto[2 + 9] = bcd >> 8;
|
249
|
|
- lto[2 + 10] = bcd &~ 0xffff00;
|
250
|
|
-
|
251
|
|
- lto[2 + 11] = ofs_next >> 8; // Next time offset (16 bits, bcd)
|
252
|
|
- lto[2 + 12] = ofs_next &~ 0xff00;
|
253
|
|
-
|
254
|
|
- ts_tdt_generate(tdt, tdt->packet_data);
|
255
|
|
-}
|
256
|
|
-
|
257
|
|
-// Calculate change time for European summer time, see:
|
258
|
|
-// http://en.wikipedia.org/wiki/European_Summer_Time
|
259
|
|
-static time_t euro_dst_start(int year) {
|
260
|
|
- struct tm tm;
|
261
|
|
- int dst_start_date;
|
262
|
|
- memset(&tm, 0, sizeof(struct tm));
|
263
|
|
- tm.tm_year = year - 1900;
|
264
|
|
- tm.tm_mon = 2; // March
|
265
|
|
- tm.tm_mday = (31 - (5 * year / 4 + 4) % 7); // Sunday DST_START March at 01:00 GMT
|
266
|
|
- tm.tm_hour = 1;
|
267
|
|
- dst_start_date = timegm(&tm);
|
268
|
|
- //ts_LOGf("year: %d ts: %d dst_start: %s", year, dst_start_date, asctime(&tm));
|
269
|
|
- return dst_start_date;
|
270
|
|
-}
|
271
|
|
-
|
272
|
|
-static time_t euro_dst_end(int year) {
|
273
|
|
- struct tm tm;
|
274
|
|
- int dst_end_date;
|
275
|
|
- memset(&tm, 0, sizeof(struct tm));
|
276
|
|
- tm.tm_year = year - 1900;
|
277
|
|
- tm.tm_mon = 9; // October
|
278
|
|
- tm.tm_mday = (31 - (5 * year / 4 + 1) % 7); // Sunday DST_END October at 01:00 GMT
|
279
|
|
- tm.tm_hour = 1;
|
280
|
|
- dst_end_date = timegm(&tm);
|
281
|
|
- //ts_LOGf("year: %d ts: %d dst_end: %s", year, dst_end_date, asctime(&tm));
|
282
|
|
- return dst_end_date;
|
283
|
|
-}
|
284
|
|
-
|
285
|
|
-void ts_tot_set_localtime_offset_sofia(struct ts_tdt *tdt) {
|
286
|
|
- time_t now = time(NULL);
|
287
|
|
- uint8_t polarity = 0; // 0 == UTC + offset, 1 == UTC - offset
|
288
|
|
- time_t change_time; // When the next DST change will be
|
289
|
|
- uint16_t current_offset;
|
290
|
|
- uint16_t next_offset;
|
291
|
|
- struct tm tm;
|
292
|
|
-
|
293
|
|
- gmtime_r(&now, &tm);
|
294
|
|
- //ts_LOGf("nowts: %d now: %s", now, asctime(&tm));
|
295
|
|
- int curyear = tm.tm_year + 1900;
|
296
|
|
- int dst_start_date = euro_dst_start(curyear);
|
297
|
|
- int dst_end_date = euro_dst_end(curyear);
|
298
|
|
- if (now < dst_start_date) {
|
299
|
|
- current_offset = 0x0200; // We are in winter time now
|
300
|
|
- next_offset = 0x0300; // Next is the summer
|
301
|
|
- change_time = dst_start_date;
|
302
|
|
- } else {
|
303
|
|
- if (now >= dst_start_date && now < dst_end_date) {
|
304
|
|
- current_offset = 0x0300; // We are in summer time time
|
305
|
|
- next_offset = 0x0200; // Next time it should be winter
|
306
|
|
- change_time = dst_end_date;
|
307
|
|
- } else {
|
308
|
|
- current_offset = 0x0200; // We are in winter time
|
309
|
|
- next_offset = 0x0300; // Next time it should be summer
|
310
|
|
- change_time = euro_dst_start(curyear + 1);
|
311
|
|
- }
|
312
|
|
- }
|
313
|
|
- //ts_LOGf("curofs: %04x next_ofs: %04x change_time:%d\n", current_offset, next_offset, change_time);
|
314
|
|
- ts_tot_set_localtime_offset(tdt, time(NULL), change_time, polarity, current_offset, next_offset);
|
315
|
|
-}
|
316
|
|
-
|
317
|
|
-int parse_tdt(uint8_t *ts_packet, int dump) {
|
318
|
|
- struct ts_tdt *tdt = ts_tdt_alloc();
|
319
|
|
- int ret = ts_tdt_parse(tdt, ts_packet);
|
320
|
|
- if (ret && dump)
|
321
|
|
- ts_tdt_dump(tdt);
|
322
|
|
- ts_tdt_free(&tdt);
|
323
|
|
- return ret;
|
324
|
|
-}
|