-
Notifications
You must be signed in to change notification settings - Fork 14
/
sdt_desc.c
136 lines (115 loc) · 4.27 KB
/
sdt_desc.c
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
/*
* SDT descriptors 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_sdt_regenerate_packet_data(struct ts_sdt *sdt) {
uint8_t *ts_packets;
int num_packets;
ts_sdt_generate(sdt, &ts_packets, &num_packets);
memcpy(sdt->section_header->packet_data, ts_packets, num_packets * TS_PACKET_SIZE);
sdt->section_header->num_packets = num_packets;
free(ts_packets);
}
struct ts_sdt *ts_sdt_init(struct ts_sdt *sdt, uint16_t org_network_id, uint16_t transport_stream_id) {
sdt->ts_header.pid = 0x11;
sdt->ts_header.pusi = 1;
sdt->ts_header.payload_field = 1;
sdt->ts_header.payload_offset = 4;
sdt->section_header->table_id = 0x42;
sdt->section_header->version_number = 1;
sdt->section_header->current_next_indicator = 1;
sdt->section_header->section_syntax_indicator = 1;
sdt->section_header->private_indicator = 1;
sdt->section_header->section_length = 9 + 3; // Empty section (9) + 3 (16+8) for SDT table data
sdt->section_header->ts_id_number = transport_stream_id;
sdt->section_header->reserved1 = 3;
sdt->section_header->reserved2 = 3;
sdt->original_network_id = org_network_id; // 16 bits
sdt->reserved = 0xff; // 8 bits
sdt->streams_num = 0;
sdt->initialized = 1;
ts_sdt_regenerate_packet_data(sdt);
return sdt;
}
struct ts_sdt *ts_sdt_alloc_init(uint16_t org_network_id, uint16_t transport_stream_id) {
struct ts_sdt *sdt = ts_sdt_alloc();
if (!sdt)
return NULL;
return ts_sdt_init(sdt, org_network_id, transport_stream_id);
}
static int ts_sdt_add_stream(struct ts_sdt *sdt, uint16_t service_id, uint8_t *desc, uint8_t desc_size) {
if (sdt->streams_num == sdt->streams_max - 1 || desc_size == 0) {
FREE(desc);
return 0;
}
int stream_len = 2 + 1 + 2 + desc_size;
if (stream_len + sdt->section_header->section_length > 4093) {
ts_LOGf("SDT no space left, max 4093, current %d will become %d!\n",
sdt->section_header->section_length,
stream_len + sdt->section_header->section_length);
free(desc);
return 0;
}
sdt->section_header->section_length += stream_len;
struct ts_sdt_stream *sinfo = calloc(1, sizeof(struct ts_sdt_stream));
sinfo->service_id = service_id; // 16 bits (2 bytes)
sinfo->reserved1 = 63; // 6 bits are up
sinfo->EIT_schedule_flag = 0; // 1 bit
sinfo->EIT_present_following_flag = 1; // 1 bit (1 byte) We have EIT
sinfo->running_status = 4; // 3 bits
sinfo->free_CA_mode = 0; // 1 bit (0 == not scrambled)
sinfo->descriptor_size = desc_size; // 12 bits (2 bytes)
sinfo->descriptor_data = desc; // desc_size bytes
sdt->streams[sdt->streams_num] = sinfo;
sdt->streams_num++;
ts_sdt_regenerate_packet_data(sdt);
return 1;
}
int ts_sdt_add_service_descriptor(struct ts_sdt *sdt, uint16_t service_id, uint8_t video, char *provider_name, char *service_name) {
char *name;
if (!service_name && !provider_name)
return 0;
int desc_size = 2 + 1; // 2 tag, size; 1 service_type
desc_size += 1 + (provider_name ? strlen(provider_name) : 0);
desc_size += 1 + (service_name ? strlen(service_name) : 0);
if (desc_size > 257) {
ts_LOGf("SDT service_descriptor size > 255 is not supported (%d)!\n", desc_size);
return 0;
}
int dpos = 0;
uint8_t *desc = calloc(1, desc_size);
desc[dpos + 0] = 0x48; // Service descriptor
desc[dpos + 1] = desc_size - 2; // -2 Because of two byte header
desc[dpos + 2] = video ? 0x01 : 0x02; // DVB Table 75: Service type coding: 0x01 - digital tv, 0x02 - digital radio
desc[dpos + 3] = (provider_name ? strlen(provider_name) : 0);
dpos += 4;
if (!provider_name || strlen(provider_name) == 0) {
dpos++;
} else {
name = provider_name;
while (name[0]) {
desc[dpos++] = name[0];
name++;
}
}
if (!service_name || strlen(service_name) == 0) {
dpos++;
} else {
desc[dpos++] = (service_name ? strlen(service_name) : 0);
name = service_name;
while (name[0]) {
desc[dpos++] = name[0];
name++;
}
}
return ts_sdt_add_stream(sdt, service_id, desc, desc_size);
}