Skip to content

Commit

Permalink
Add LCN support
Browse files Browse the repository at this point in the history
This patch is a rewrite of the work done by @gmakedonski and Georgi Chorbadzhiyski committed on Feb 2, 2015.
Check the original work at lars18th@e38fb3b

The new implementation adds a new command line option to enable the LCN support. By default it's disabled. And when enabled a different code is executed to generate the NIT table. The original code is adapted and fixed.
  • Loading branch information
lars18th authored Mar 13, 2024
1 parent 4e1b1a3 commit 997aff0
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 29 deletions.
13 changes: 10 additions & 3 deletions config.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ int config_load_channels(CONFIG *conf) {
continue;

int is_radio = ini_get_bool(ini, 0, "Channel%d:radio", i);
int lcn = ini_get_int(ini, 0, "Channel%d:lcn", i);
int is_lcn_visible = ini_get_bool(ini, 0, "Channel%d:lcn_visible", i);

char *id = ini_get_string(ini, NULL, "Channel%d:id", i);
if (!id) {
Expand Down Expand Up @@ -145,7 +147,7 @@ int config_load_channels(CONFIG *conf) {
}
// Init channel
if (channel == NULL) {
channel = channel_new(service_id, is_radio, id, name, eit_mode, source, i);
channel = channel_new(service_id, is_radio, id, name, eit_mode, source, i, lcn, is_lcn_visible);
} else {
chansrc_add(channel, source);
}
Expand Down Expand Up @@ -225,7 +227,7 @@ int config_load_channels(CONFIG *conf) {
if (r->cookie != cookie) {
proxy_log(r, "Remove");
/* Replace channel reference with real object and instruct free_restreamer to free it */
r->channel = channel_new(r->channel->service_id, r->channel->radio, r->channel->id, r->channel->name, r->channel->eit_mode, r->channel->source, r->channel->index);
r->channel = channel_new(r->channel->service_id, r->channel->radio, r->channel->id, r->channel->name, r->channel->eit_mode, r->channel->source, r->channel->index, r->channel->lcn, r->channel->lcn_visible);
r->freechannel = 1;
r->dienow = 1;
}
Expand Down Expand Up @@ -450,6 +452,7 @@ static void show_usage(void) {
puts("\t-W\t\tWrite output file (recommended to use with -N)");
puts("\t-f\t\tThe output filename (default: mptsd-output.ts) (use - for stdout)");
puts("\t-E\t\tWrite input file");
puts("\t-9\t\tEnable LCN support (default: disabled)");
puts("");
}

Expand All @@ -466,7 +469,7 @@ void config_load(CONFIG *conf, int argc, char **argv) {
conf->server_socket = -1;
conf->write_output_network = 1;

while ((j = getopt(argc, argv, "i:b:p:g:c:n:e:d:t:o:O:P:l:L:B:m:s:f:qDHhEWN")) != -1) {
while ((j = getopt(argc, argv, "i:b:p:g:c:n:e:d:t:o:O:P:l:L:B:m:s:f:qDHhEWN9")) != -1) {
switch (j) {
case 'i':
conf->ident = strdup(optarg);
Expand Down Expand Up @@ -556,6 +559,9 @@ void config_load(CONFIG *conf, int argc, char **argv) {
case 'f':
conf->output_filename = strdup(optarg);
break;
case '9':
conf->use_lcn = 1;
break;
case 'D':
conf->debug = 1;
break;
Expand Down Expand Up @@ -638,6 +644,7 @@ void config_load(CONFIG *conf, int argc, char **argv) {
conf->pcr_mode == 2 ? "Rewrite PCRs using output bitrate" :
conf->pcr_mode == 3 ? "Move PCRs and rewrite them" : "???"
);
LOGf("\tLCN : %s\n", (conf->use_lcn)? "enabled" : "disabled");
if (conf->write_output_file)
LOGf("\tWrite output file : %s\n", conf->output_filename);
if (conf->write_input_file)
Expand Down
1 change: 1 addition & 0 deletions config.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ typedef struct {
// 1 - move PCRs to their calculated place
// 2 - rewrite PCRs using output bitrate
// 3 - move PCRs and rewrite them
int use_lcn;

uint16_t network_id; // For NIT && SDT
uint16_t transport_stream_id;// For NIT
Expand Down
4 changes: 3 additions & 1 deletion data.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ void chansrc_set(CHANNEL *c, uint8_t src_id) {



CHANNEL *channel_new(int service_id, int is_radio, const char *id, const char *name, int eit_mode, const char *source, int channel_index){
CHANNEL *channel_new(int service_id, int is_radio, const char *id, const char *name, int eit_mode, const char *source, int channel_index, int lcn, int is_lcn_visible){

if (channel_index<=0 || channel_index>=256)
{
Expand All @@ -135,6 +135,8 @@ CHANNEL *channel_new(int service_id, int is_radio, const char *id, const char *n
c->service_id = service_id;
c->radio = is_radio;
c->index = channel_index;
c->lcn = lcn;
c->lcn_visible = is_lcn_visible;
c->base_pid = c->index * 32; // The first pid is saved for PMT , channel_index must > 0
c->pmt_pid = c->base_pid; // The first pid is saved for PMT
c->id = strdup(id);
Expand Down
4 changes: 3 additions & 1 deletion data.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ typedef struct {
int service_id;
int pmt_pid;
int radio;
int lcn;
int lcn_visible;
char * id;
char * name;
int eit_mode; /* 0 = ignore EIT data from input
Expand Down Expand Up @@ -229,7 +231,7 @@ EPG_ENTRY * epg_new (time_t start, int duration, char *encoding, char *event,
void epg_free (EPG_ENTRY **e);
int epg_changed (EPG_ENTRY *a, EPG_ENTRY *b);

CHANNEL * channel_new (int service_id, int is_radio, const char *id, const char *name, int eit_mode, const char *source, int channel_index);
CHANNEL * channel_new (int service_id, int is_radio, const char *id, const char *name, int eit_mode, const char *source, int channel_index, int lcn, int is_lcn_visible);
void channel_free (CHANNEL **c);
void channel_free_epg(CHANNEL *c);

Expand Down
22 changes: 20 additions & 2 deletions mptsd_channels.conf
Original file line number Diff line number Diff line change
Expand Up @@ -6,61 +6,79 @@ transport_stream_id = 1
service_id = 1
id = btv
name = bTV
eit_mode = 0 # 0 = ignore EIT data from input
eit_mode = 0 # 0 = ignore EIT data from input
# 1 = forward EIT data for the configured service, ignore any other EIT data
source1 = http://signal-server/stb/btv.mpg
#source2 = http://signal-server2/stb/btv.mpg
#source3 = http://signal-server3/stb/btv.mpg
#source4 = udp://239.0.0.1:5000/
#source5 = rtp://239.78.78.2:5000/
#source5 = rtp://239.78.78.2:5000/
#worktime = 14:18-14:19
lcn = 2
lcn_visible = yes

[Channel2]
service_id = 2
id = kanal1
name = "Kanal 1"
source = http://signal-server/stb/kanal1.mpg
lcn = 2
lcn_visible = yes

[Channel3]
service_id = 3
id = novatv
name = "Nova"
source1 = http://signal-server/stb/novatv.mpg
lcn = 3
lcn_visible = yes

[Channel4]
service_id = 4
id = tv2
name = "TV 2"
source1 = http://signal-server/stb/tv2.mpg
lcn = 7
lcn_visible = yes

[Channel5]
service_id = 5
id = ngc
name = "NatGeo"
source1 = http://signal-server/stb/ngc.mpg
lcn = 72
lcn_visible = yes

[Channel6]
service_id = 6
id = tv1
name = "TV 1"
source1 = http://signal-server/stb/tv1.mpg
lcn = 25
lcn_visible = yes

[Channel7]
service_id = 7
id = planetahit
name = "Planeta HIT"
source1 = http://signal-server/stb/planetahit.mpg
lcn = 33
lcn_visible = no

[Channel8]
service_id = 8
id = fresh
name = "Radio Fresh"
radio = yes
source = http://signal-server/stb/fresh.mpg
lcn = 201
lcn_visible = yes

[Channel9]
service_id = 9
id = bgradio
name = "BG Radio"
radio = yes
source1 = http://signal-server/stb/bgradio.mpg
lcn = 202
lcn_visible = yes
123 changes: 101 additions & 22 deletions output_psi.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,40 +44,119 @@ static void output_psi_init_nit(CONFIG *conf, OUTPUT *o) {

ts_nit_add_network_name_descriptor(nit, conf->network_name);

if (conf->nit->items < 64) {
if (!conf->use_lcn) {

if (conf->nit->items < 64) {
int num;
LNODE *lc, *lctmp;
uint32_t *freqs = malloc(conf->nit->items * sizeof(uint32_t));
uint32_t *services = malloc(conf->channels->items * sizeof(uint32_t));

num = 0;
list_lock(conf->nit);
list_for_each(conf->nit, lc, lctmp) {
NIT *ndata = lc->data;
freqs[num++] = ndata->_freq;
}

ts_nit_add_frequency_list_descriptor_cable(nit, conf->transport_stream_id, conf->network_id, freqs, num);

list_for_each(conf->nit, lc, lctmp) {
NIT *ndata = lc->data;
ts_nit_add_cable_delivery_descriptor(nit, ndata->ts_id, conf->network_id, ndata->_freq, ndata->_modulation, ndata->_symbol_rate);
}
list_unlock(conf->nit);

num = 0;
list_lock(conf->channels);
list_for_each(conf->channels, lc, lctmp) {
CHANNEL *c = lc->data;
uint32_t srv = 0;
srv = (c->service_id &~ 0x00ff) << 8;
srv |= (c->service_id &~ 0xff00) << 8;
srv |= c->radio ? 0x02 : 0x01;
services[num++] = srv;
}
list_unlock(conf->channels);

ts_nit_add_service_list_descriptor(nit, conf->transport_stream_id, conf->network_id, services, num);
free(freqs);
free(services);
} else {
LOG("CONF : Too much items in the NIT, maximum is 64! NIT not generated.\n");
}

} else {

int num;
char *ts_freq = NULL;
char *ts_modulation = NULL;
char *ts_symbol_rate = NULL;
uint32_t ts__freq = 0;
uint8_t ts__modulation = 0;
uint32_t ts__symbol_rate = 0;
LNODE *lc, *lctmp;
uint32_t *freqs = malloc(conf->nit->items * sizeof(uint32_t));
uint32_t *services = malloc(conf->channels->items * sizeof(uint32_t));
num = 0;
uint32_t *svc_services = malloc(conf->channels->items * sizeof(uint32_t));
uint32_t *lcn_services = malloc(conf->channels->items * sizeof(uint32_t));

list_lock(conf->nit);
list_for_each(conf->nit, lc, lctmp) {
NIT *ndata = lc->data;
freqs[num++] = ndata->_freq;
}
ts_nit_add_frequency_list_descriptor_cable(nit, conf->transport_stream_id, conf->network_id, freqs, num);
list_for_each(conf->nit, lc, lctmp) {
NIT *ndata = lc->data;
ts_nit_add_cable_delivery_descriptor(nit, ndata->ts_id, conf->network_id, ndata->_freq, ndata->_modulation, ndata->_symbol_rate);
if (ndata->ts_id == conf->transport_stream_id) {
ts_freq = ndata->freq;
ts_modulation = ndata->modulation;
ts_symbol_rate = ndata->symbol_rate;
ts__freq = ndata->_freq;
ts__modulation = ndata->_modulation;
ts__symbol_rate = ndata->_symbol_rate;
}
}
list_unlock(conf->nit);
num = 0;

list_lock(conf->channels);
num = 0;
list_for_each(conf->channels, lc, lctmp) {
CHANNEL *c = lc->data;
uint32_t srv = 0;
srv = (c->service_id &~ 0x00ff) << 16;
srv |= (c->service_id &~ 0xff00) << 16;
srv |= (c->lcn_visible ? 0x01 : 0x00 &~ 0xf0 ) << 15;
srv |= (0X00 &~ 0xf0 ) << 14;
srv |= (c->lcn &~ 0xc0ff);
srv |= (c->lcn &~ 0xff00);
lcn_services[num++] = srv;
}

num = 0;
list_for_each(conf->channels, lc, lctmp) {
CHANNEL *c = lc->data;
uint32_t srv = 0;
srv = (c->service_id &~ 0x00ff) << 8;
srv |= (c->service_id &~ 0xff00) << 8;
srv |= c->radio ? 0x02 : 0x01;
services[num++] = srv;
CHANNEL *c = lc->data;
uint32_t srv = 0;
srv = (c->service_id &~ 0x00ff) << 8;
srv |= (c->service_id &~ 0xff00) << 8;
srv |= c->radio ? 0x02 : 0x01;
svc_services[num++] = srv;
}
list_unlock(conf->channels);
ts_nit_add_service_list_descriptor(nit, conf->transport_stream_id, conf->network_id, services, num);
free(freqs);
free(services);
} else {
LOG("CONF : Too much items in the NIT, maximum is 64! NIT not generated.\n");

NIT *ts_ndata = nit_new(conf->transport_stream_id, ts_freq, ts_modulation, ts_symbol_rate);
ts_nit_add_stream_descriptors(nit, ts_ndata->ts_id, conf->network_id, ts__freq, ts__modulation, ts__symbol_rate, lcn_services, svc_services, num);

if (conf->nit->items < 64) {
list_lock(conf->nit);
list_for_each(conf->nit, lc, lctmp) {
NIT *ndata = lc->data;
ts_nit_add_cable_delivery_descriptor(nit, ndata->ts_id, conf->network_id, ndata->_freq, ndata->_modulation, ndata->_symbol_rate);
}
list_unlock(conf->nit);

free(lcn_services);
free(svc_services);
} else {
LOG("CONF : Too much items in the NIT, maximum is 64! NIT not generated.\n");
}

}

gettimeofday(&o->nit_ts, NULL);
o->nit = nit;
}
Expand Down

0 comments on commit 997aff0

Please sign in to comment.