service: trying to sort the service saving
This commit is contained in:
parent
dc773b0380
commit
c412f6e28c
12 changed files with 315 additions and 396 deletions
|
@ -63,6 +63,7 @@ LIST_HEAD(caid_list, caid);
|
|||
void descrambler_init ( void );
|
||||
void descrambler_service_start ( struct service *t );
|
||||
const char *descrambler_caid2name(uint16_t caid);
|
||||
uint16_t descrambler_name2caid(const char *str);
|
||||
|
||||
#endif /* __TVH_DESCRAMBLER_H__ */
|
||||
|
||||
|
|
|
@ -137,6 +137,13 @@ descrambler_caid2name(uint16_t caid)
|
|||
return buf;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
descrambler_name2caid(const char *s)
|
||||
{
|
||||
int i = str2val(s, caidnametab);
|
||||
return (i < 0) ? strtol(s, NULL, 0) : i;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* **************************************************************************
|
||||
|
|
|
@ -258,20 +258,6 @@ struct mpegts_service
|
|||
{
|
||||
service_t; // Parent
|
||||
|
||||
#if 0 // TODO: temporarily moved to service_t
|
||||
/**
|
||||
* PID carrying the programs PCR.
|
||||
* XXX: We don't support transports that does not carry
|
||||
* the PCR in one of the content streams.
|
||||
*/
|
||||
uint16_t s_pcr_pid;
|
||||
|
||||
/**
|
||||
* PID for the PMT of this MPEG-TS stream.
|
||||
*/
|
||||
uint16_t s_pmt_pid;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Fields defined by DVB standard EN 300 468
|
||||
*/
|
||||
|
@ -280,7 +266,7 @@ struct mpegts_service
|
|||
uint16_t s_dvb_channel_num;
|
||||
char *s_dvb_svcname;
|
||||
char *s_dvb_provider;
|
||||
char *s_dvb_default_authority;
|
||||
char *s_dvb_cridauth;
|
||||
uint16_t s_dvb_servicetype;
|
||||
char *s_dvb_charset;
|
||||
|
||||
|
@ -492,19 +478,20 @@ void mpegts_table_destroy ( mpegts_table_t *mt );
|
|||
|
||||
mpegts_service_t *mpegts_service_create0
|
||||
( mpegts_service_t *ms, const idclass_t *class, const char *uuid,
|
||||
mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid );
|
||||
mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid, htsmsg_t *conf );
|
||||
|
||||
#define mpegts_service_create(t, u, m, s, p)\
|
||||
#define mpegts_service_create(t, u, m, s, p, c)\
|
||||
(struct t*)mpegts_service_create0(calloc(1, sizeof(struct t)),\
|
||||
&t##_class, u, m, s, p)
|
||||
&t##_class, u, m, s, p, c)
|
||||
|
||||
#define mpegts_service_create1(u, m, s, p)\
|
||||
#define mpegts_service_create1(u, m, s, p, c)\
|
||||
mpegts_service_create0(calloc(1, sizeof(mpegts_service_t)),\
|
||||
&mpegts_service_class, u, m, s, p)
|
||||
&mpegts_service_class, u, m, s, p, c)
|
||||
|
||||
void mpegts_service_load_one ( mpegts_service_t *ms, htsmsg_t *c );
|
||||
mpegts_service_t *mpegts_service_find
|
||||
( mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid, int create, int *save );
|
||||
|
||||
mpegts_service_t *mpegts_service_find ( mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid, const char *uuid, int *save );
|
||||
void mpegts_service_save ( mpegts_service_t *s, htsmsg_t *c );
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "tsdemux.h"
|
||||
#include "parsers.h"
|
||||
#include "lang_codes.h"
|
||||
#include "service.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
@ -335,7 +336,7 @@ dvb_desc_service_list
|
|||
tvhtrace(dstr, " service %04X (%d) type %d", sid, sid, stype);
|
||||
if (mm) {
|
||||
int save = 0;
|
||||
s = mpegts_service_find(mm, sid, 0, NULL, &save);
|
||||
s = mpegts_service_find(mm, sid, 0, 1, &save);
|
||||
if (save)
|
||||
s->s_config_save((service_t*)s);
|
||||
}
|
||||
|
@ -355,7 +356,7 @@ dvb_desc_local_channel
|
|||
lcn = ((ptr[2] & 3) << 8) | ptr[3];
|
||||
tvhtrace(dstr, " sid %d lcn %d", sid, lcn);
|
||||
if (lcn && mm) {
|
||||
mpegts_service_t *s = mpegts_service_find(mm, sid, 0, NULL, &save);
|
||||
mpegts_service_t *s = mpegts_service_find(mm, sid, 0, 0, &save);
|
||||
if (s) {
|
||||
if (s->s_dvb_channel_num != lcn) {
|
||||
s->s_dvb_channel_num = lcn;
|
||||
|
@ -476,7 +477,7 @@ dvb_pat_callback
|
|||
} else if (pid) {
|
||||
tvhtrace("pat", " sid %04X (%d) on pid %04X (%d)", sid, sid, pid, pid);
|
||||
int save = 0;
|
||||
if (mpegts_service_find(mm, sid, pid, NULL, &save))
|
||||
if (mpegts_service_find(mm, sid, pid, 1, &save))
|
||||
if (save)
|
||||
mpegts_table_add(mm, DVB_PMT_BASE, DVB_PMT_MASK, dvb_pmt_callback,
|
||||
NULL, "pmt", MT_CRC | MT_QUICKREQ, pid);
|
||||
|
@ -754,8 +755,8 @@ dvb_sdt_callback
|
|||
master = 1;
|
||||
|
||||
/* Update CRID authority */
|
||||
if (*sauth && strcmp(s->s_dvb_default_authority ?: "", sauth)) {
|
||||
tvh_str_update(&s->s_dvb_default_authority, sauth);
|
||||
if (*sauth && strcmp(s->s_dvb_cridauth ?: "", sauth)) {
|
||||
tvh_str_update(&s->s_dvb_cridauth, sauth);
|
||||
save = 1;
|
||||
}
|
||||
|
||||
|
@ -971,43 +972,6 @@ psi_desc_teletext(mpegts_service_t *t, const uint8_t *ptr, int size,
|
|||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static int
|
||||
pidcmp(const void *A, const void *B)
|
||||
{
|
||||
elementary_stream_t *a = *(elementary_stream_t **)A;
|
||||
elementary_stream_t *b = *(elementary_stream_t **)B;
|
||||
return a->es_position - b->es_position;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
sort_pids(mpegts_service_t *t)
|
||||
{
|
||||
elementary_stream_t *st, **v;
|
||||
int num = 0, i = 0;
|
||||
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link)
|
||||
num++;
|
||||
|
||||
v = alloca(num * sizeof(elementary_stream_t *));
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link)
|
||||
v[i++] = st;
|
||||
|
||||
qsort(v, num, sizeof(elementary_stream_t *), pidcmp);
|
||||
|
||||
TAILQ_INIT(&t->s_components);
|
||||
for(i = 0; i < num; i++)
|
||||
TAILQ_INSERT_TAIL(&t->s_components, v[i], es_link);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* PMT parser, from ISO 13818-1 and ETSI EN 300 468
|
||||
*/
|
||||
|
@ -1254,7 +1218,7 @@ psi_parse_pmt(mpegts_service_t *t, const uint8_t *ptr, int len, int chksvcid,
|
|||
}
|
||||
|
||||
if(update & PMT_REORDERED)
|
||||
sort_pids(t);
|
||||
sort_elementary_streams((service_t*)t);
|
||||
|
||||
if(update) {
|
||||
tvhlog(LOG_DEBUG, "PSI", "Service \"%s\" PMT (version %d) updated"
|
||||
|
@ -1287,219 +1251,3 @@ psi_parse_pmt(mpegts_service_t *t, const uint8_t *ptr, int len, int chksvcid,
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* Store service settings into message
|
||||
*/
|
||||
void
|
||||
psi_save_service_settings(htsmsg_t *m, mpegts_service_t *t)
|
||||
{
|
||||
elementary_stream_t *st;
|
||||
htsmsg_t *sub;
|
||||
|
||||
htsmsg_add_u32(m, "pcr", t->s_pcr_pid);
|
||||
|
||||
htsmsg_add_u32(m, "disabled", !t->s_enabled);
|
||||
|
||||
lock_assert(&t->s_stream_mutex);
|
||||
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link) {
|
||||
sub = htsmsg_create_map();
|
||||
|
||||
htsmsg_add_u32(sub, "pid", st->es_pid);
|
||||
#ifdef TODO_FIXME
|
||||
htsmsg_add_str(sub, "type", val2str(st->es_type, streamtypetab) ?: "?");
|
||||
#endif
|
||||
htsmsg_add_u32(sub, "position", st->es_position);
|
||||
|
||||
if(st->es_lang[0])
|
||||
htsmsg_add_str(sub, "language", st->es_lang);
|
||||
|
||||
if(st->es_type == SCT_CA) {
|
||||
|
||||
caid_t *c;
|
||||
htsmsg_t *v = htsmsg_create_list();
|
||||
|
||||
LIST_FOREACH(c, &st->es_caids, link) {
|
||||
htsmsg_t *caid = htsmsg_create_map();
|
||||
|
||||
htsmsg_add_u32(caid, "caid", c->caid);
|
||||
if(c->providerid)
|
||||
htsmsg_add_u32(caid, "providerid", c->providerid);
|
||||
htsmsg_add_msg(v, NULL, caid);
|
||||
}
|
||||
|
||||
htsmsg_add_msg(sub, "caidlist", v);
|
||||
}
|
||||
|
||||
if(st->es_type == SCT_DVBSUB) {
|
||||
htsmsg_add_u32(sub, "compositionid", st->es_composition_id);
|
||||
htsmsg_add_u32(sub, "ancillartyid", st->es_ancillary_id);
|
||||
}
|
||||
|
||||
if(st->es_type == SCT_TEXTSUB)
|
||||
htsmsg_add_u32(sub, "parentpid", st->es_parent_pid);
|
||||
|
||||
if(st->es_type == SCT_MPEG2VIDEO || st->es_type == SCT_H264) {
|
||||
if(st->es_width && st->es_height) {
|
||||
htsmsg_add_u32(sub, "width", st->es_width);
|
||||
htsmsg_add_u32(sub, "height", st->es_height);
|
||||
}
|
||||
if(st->es_frame_duration)
|
||||
htsmsg_add_u32(sub, "duration", st->es_frame_duration);
|
||||
}
|
||||
|
||||
htsmsg_add_msg(m, "stream", sub);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
add_caid(elementary_stream_t *st, uint16_t caid, uint32_t providerid)
|
||||
{
|
||||
caid_t *c = malloc(sizeof(caid_t));
|
||||
c->caid = caid;
|
||||
c->providerid = providerid;
|
||||
c->delete_me = 0;
|
||||
LIST_INSERT_HEAD(&st->es_caids, c, link);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
load_legacy_caid(htsmsg_t *c, elementary_stream_t *st)
|
||||
{
|
||||
#if TODO_FIXME
|
||||
uint32_t a, b;
|
||||
const char *v;
|
||||
|
||||
if(htsmsg_get_u32(c, "caproviderid", &b))
|
||||
b = 0;
|
||||
|
||||
if(htsmsg_get_u32(c, "caidnum", &a)) {
|
||||
if((v = htsmsg_get_str(c, "caid")) != NULL) {
|
||||
int i = str2val(v, caidnametab);
|
||||
a = i < 0 ? strtol(v, NULL, 0) : i;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
add_caid(st, a, b);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
load_caid(htsmsg_t *m, elementary_stream_t *st)
|
||||
{
|
||||
htsmsg_field_t *f;
|
||||
htsmsg_t *c, *v = htsmsg_get_list(m, "caidlist");
|
||||
uint32_t a, b;
|
||||
|
||||
if(v == NULL)
|
||||
return;
|
||||
|
||||
HTSMSG_FOREACH(f, v) {
|
||||
if((c = htsmsg_get_map_by_field(f)) == NULL)
|
||||
continue;
|
||||
|
||||
if(htsmsg_get_u32(c, "caid", &a))
|
||||
continue;
|
||||
|
||||
if(htsmsg_get_u32(c, "providerid", &b))
|
||||
b = 0;
|
||||
|
||||
add_caid(st, a, b);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Load service info from htsmsg
|
||||
*/
|
||||
void
|
||||
psi_load_service_settings(htsmsg_t *m, mpegts_service_t *t)
|
||||
{
|
||||
htsmsg_t *c;
|
||||
htsmsg_field_t *f;
|
||||
uint32_t u32, pid;
|
||||
elementary_stream_t *st;
|
||||
streaming_component_type_t type = 0; // TODO: FIXME
|
||||
const char *v;
|
||||
|
||||
if(!htsmsg_get_u32(m, "pcr", &u32))
|
||||
t->s_pcr_pid = u32;
|
||||
|
||||
if(!htsmsg_get_u32(m, "disabled", &u32))
|
||||
t->s_enabled = !u32;
|
||||
else
|
||||
t->s_enabled = 1;
|
||||
|
||||
HTSMSG_FOREACH(f, m) {
|
||||
if(strcmp(f->hmf_name, "stream"))
|
||||
continue;
|
||||
|
||||
if((c = htsmsg_get_map_by_field(f)) == NULL)
|
||||
continue;
|
||||
|
||||
if((v = htsmsg_get_str(c, "type")) == NULL)
|
||||
continue;
|
||||
|
||||
#ifdef TODO_FIXME
|
||||
type = str2val(v, streamtypetab);
|
||||
if(type == -1)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
if(htsmsg_get_u32(c, "pid", &pid))
|
||||
continue;
|
||||
|
||||
st = service_stream_create((service_t*)t, pid, type);
|
||||
|
||||
if((v = htsmsg_get_str(c, "language")) != NULL)
|
||||
strncpy(st->es_lang, lang_code_get(v), 3);
|
||||
|
||||
if(!htsmsg_get_u32(c, "position", &u32))
|
||||
st->es_position = u32;
|
||||
|
||||
load_legacy_caid(c, st);
|
||||
load_caid(c, st);
|
||||
|
||||
if(type == SCT_DVBSUB) {
|
||||
if(!htsmsg_get_u32(c, "compositionid", &u32))
|
||||
st->es_composition_id = u32;
|
||||
|
||||
if(!htsmsg_get_u32(c, "ancillartyid", &u32))
|
||||
st->es_ancillary_id = u32;
|
||||
}
|
||||
|
||||
if(type == SCT_TEXTSUB) {
|
||||
if(!htsmsg_get_u32(c, "parentpid", &u32))
|
||||
st->es_parent_pid = u32;
|
||||
}
|
||||
|
||||
if(type == SCT_MPEG2VIDEO || type == SCT_H264) {
|
||||
if(!htsmsg_get_u32(c, "width", &u32))
|
||||
st->es_width = u32;
|
||||
|
||||
if(!htsmsg_get_u32(c, "height", &u32))
|
||||
st->es_height = u32;
|
||||
|
||||
if(!htsmsg_get_u32(c, "duration", &u32))
|
||||
st->es_frame_duration = u32;
|
||||
}
|
||||
|
||||
}
|
||||
sort_pids(t);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -130,6 +130,16 @@ linuxdvb_frontend_save ( linuxdvb_frontend_t *lfe, htsmsg_t *m )
|
|||
htsmsg_add_str(m, "dvr_path", lfe->lfe_dvr_path);
|
||||
}
|
||||
|
||||
static int
|
||||
linuxdvb_frontend_is_enabled ( mpegts_input_t *mi )
|
||||
{
|
||||
linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi;
|
||||
if (lfe->lfe_fe_path == NULL) return 0;
|
||||
if (!lfe->mi_enabled) return 0;
|
||||
if (access(lfe->lfe_fe_path, R_OK | W_OK)) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int
|
||||
linuxdvb_frontend_is_free ( mpegts_input_t *mi )
|
||||
|
@ -456,14 +466,11 @@ linuxdvb_frontend_create0
|
|||
lfe->lfe_info.type = type;
|
||||
|
||||
/* Input callbacks */
|
||||
lfe->mi_is_enabled = linuxdvb_frontend_is_enabled;
|
||||
lfe->mi_start_mux = linuxdvb_frontend_start_mux;
|
||||
lfe->mi_stop_mux = linuxdvb_frontend_stop_mux;
|
||||
lfe->mi_open_service = linuxdvb_frontend_open_service;
|
||||
lfe->mi_close_service = linuxdvb_frontend_close_service;
|
||||
#if 0
|
||||
lfe->mi_is_free = linuxdvb_frontend_is_free;
|
||||
lfe->mi_current_weight = linuxdvb_frontend_current_weight;
|
||||
#endif
|
||||
|
||||
/* Adapter link */
|
||||
lfe->lh_parent = (linuxdvb_hardware_t*)la;
|
||||
|
|
|
@ -101,10 +101,9 @@ linuxdvb_network_create_mux
|
|||
static void
|
||||
linuxdvb_service_config_save ( service_t *t )
|
||||
{
|
||||
mpegts_service_t *s = (mpegts_service_t*)t;
|
||||
htsmsg_t *c = htsmsg_create_map();
|
||||
idnode_save(&s->s_id, c);
|
||||
service_save(t, c);
|
||||
mpegts_service_t *s = (mpegts_service_t*)t;
|
||||
mpegts_service_save(s, c);
|
||||
hts_settings_save(c, "input/linuxdvb/networks/%s/muxes/%s/services/%s",
|
||||
idnode_uuid_as_str(&s->s_dvb_mux->mm_network->mn_id),
|
||||
idnode_uuid_as_str(&s->s_dvb_mux->mm_id),
|
||||
|
@ -117,7 +116,7 @@ linuxdvb_network_create_service
|
|||
( mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid )
|
||||
{
|
||||
extern const idclass_t mpegts_service_class;
|
||||
mpegts_service_t *s = mpegts_service_create1(NULL, mm, sid, pmt_pid);
|
||||
mpegts_service_t *s = mpegts_service_create1(NULL, mm, sid, pmt_pid, NULL);
|
||||
if (s)
|
||||
s->s_config_save = linuxdvb_service_config_save;
|
||||
// TODO: do we need any DVB specific fields?
|
||||
|
|
|
@ -47,10 +47,18 @@ mpegts_mux_instance_create0
|
|||
return mmi;
|
||||
}
|
||||
|
||||
static void
|
||||
mpegts_mux_class_save ( idnode_t *self )
|
||||
{
|
||||
mpegts_mux_t *mm = (mpegts_mux_t*)self;
|
||||
mm->mm_config_save(mm);
|
||||
}
|
||||
|
||||
const idclass_t mpegts_mux_class =
|
||||
{
|
||||
.ic_class = "mpegts_mux",
|
||||
.ic_caption = "MPEGTS Multiplex",
|
||||
.ic_save = mpegts_mux_class_save,
|
||||
.ic_properties = (const property_t[]){
|
||||
{ PROPDEF1("enabled", "Enabled",
|
||||
PT_BOOL, mpegts_mux_t, mm_enabled) },
|
||||
|
|
|
@ -22,51 +22,60 @@
|
|||
#include "service.h"
|
||||
#include "input/mpegts.h"
|
||||
|
||||
/* **************************************************************************
|
||||
* Class definition
|
||||
* *************************************************************************/
|
||||
|
||||
const idclass_t mpegts_service_class =
|
||||
{
|
||||
.ic_class = "mpegts_service",
|
||||
.ic_caption = "MPEGTS Service",
|
||||
.ic_properties = (const property_t[]){
|
||||
{ PROPDEF2("sid", "Service ID",
|
||||
PT_U16, mpegts_service_t, s_dvb_service_id, 1) },
|
||||
{ PROPDEF2("lcn", "Local Channel Number",
|
||||
PT_U16, mpegts_service_t, s_dvb_channel_num, 1) },
|
||||
{ PROPDEF2("svcname", "Service Name",
|
||||
PT_STR, mpegts_service_t, s_dvb_svcname, 1) },
|
||||
{ PROPDEF2("provider", "Provider",
|
||||
PT_STR, mpegts_service_t, s_dvb_provider, 1) },
|
||||
{ PROPDEF2("cridauth", "CRID Authority",
|
||||
PT_STR, mpegts_service_t, s_dvb_cridauth, 1) },
|
||||
{ PROPDEF2("servicetype", "Service Type",
|
||||
PT_U16, mpegts_service_t, s_dvb_servicetype, 1) },
|
||||
{ PROPDEF2("charset", "Character Set",
|
||||
PT_STR, mpegts_service_t, s_dvb_charset, 0) },
|
||||
{},
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: why not static?
|
||||
int mpegts_service_is_enabled (service_t *);
|
||||
void mpegts_service_enlist (service_t *, struct service_instance_list*);
|
||||
int mpegts_service_start (service_t *, int);
|
||||
void mpegts_service_stop (service_t *);
|
||||
void mpegts_service_refresh (service_t *);
|
||||
void mpegts_service_setsourceinfo (service_t *, source_info_t *);
|
||||
void mpegts_service_config_save (service_t *);
|
||||
|
||||
/*
|
||||
* Save
|
||||
*/
|
||||
void
|
||||
mpegts_service_config_save ( service_t *t )
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
/* **************************************************************************
|
||||
* Class methods
|
||||
* *************************************************************************/
|
||||
|
||||
/*
|
||||
* Check the service is enabled
|
||||
*/
|
||||
int
|
||||
static int
|
||||
mpegts_service_is_enabled(service_t *t)
|
||||
{
|
||||
mpegts_service_t *s = (mpegts_service_t*)t;
|
||||
#if 0
|
||||
mpegts_mux_t *m = t->s_dvb_mux;
|
||||
mpegts_mux_instance_t *mi;
|
||||
#endif
|
||||
assert(s->s_source_type == S_MPEG_TS);
|
||||
return 1; // TODO: check heirarchy
|
||||
mpegts_service_t *s = (mpegts_service_t*)t;
|
||||
mpegts_mux_t *mm = s->s_dvb_mux;
|
||||
return mm->mm_is_enabled(mm) ? s->s_enabled : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save
|
||||
*/
|
||||
static void
|
||||
mpegts_service_config_save(service_t *t)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Service instance list
|
||||
*/
|
||||
void
|
||||
static void
|
||||
mpegts_service_enlist(service_t *t, struct service_instance_list *sil)
|
||||
{
|
||||
mpegts_service_t *s = (mpegts_service_t*)t;
|
||||
|
@ -90,7 +99,7 @@ mpegts_service_enlist(service_t *t, struct service_instance_list *sil)
|
|||
/*
|
||||
* Start service
|
||||
*/
|
||||
int
|
||||
static int
|
||||
mpegts_service_start(service_t *t, int instance)
|
||||
{
|
||||
int r;
|
||||
|
@ -125,7 +134,6 @@ mpegts_service_start(service_t *t, int instance)
|
|||
|
||||
/* Open service */
|
||||
mi->mmi_input->mi_open_service(mi->mmi_input, s);
|
||||
// TODO: revisit this
|
||||
}
|
||||
|
||||
return r;
|
||||
|
@ -134,7 +142,7 @@ mpegts_service_start(service_t *t, int instance)
|
|||
/*
|
||||
* Stop service
|
||||
*/
|
||||
void
|
||||
static void
|
||||
mpegts_service_stop(service_t *t)
|
||||
{
|
||||
mpegts_service_t *s = (mpegts_service_t*)t;
|
||||
|
@ -159,7 +167,7 @@ mpegts_service_stop(service_t *t)
|
|||
/*
|
||||
* Refresh
|
||||
*/
|
||||
void
|
||||
static void
|
||||
mpegts_service_refresh(service_t *t)
|
||||
{
|
||||
mpegts_service_t *s = (mpegts_service_t*)t;
|
||||
|
@ -177,9 +185,10 @@ mpegts_service_refresh(service_t *t)
|
|||
/*
|
||||
* Source info
|
||||
*/
|
||||
void
|
||||
static void
|
||||
mpegts_service_setsourceinfo(service_t *t, source_info_t *si)
|
||||
{
|
||||
char buf[128];
|
||||
mpegts_service_t *s = (mpegts_service_t*)t;
|
||||
mpegts_mux_t *m = s->s_dvb_mux;
|
||||
|
||||
|
@ -194,7 +203,8 @@ mpegts_service_setsourceinfo(service_t *t, source_info_t *si)
|
|||
if(m->mm_network->mn_network_name != NULL)
|
||||
si->si_network = strdup(m->mm_network->mn_network_name);
|
||||
|
||||
si->si_mux = strdup("TODO:mpegts_mux_nicename(m)");
|
||||
m->mm_display_name(m, buf, sizeof(buf));
|
||||
si->si_mux = strdup(buf);
|
||||
|
||||
if(s->s_dvb_provider != NULL)
|
||||
si->si_provider = strdup(s->s_dvb_provider);
|
||||
|
@ -203,41 +213,9 @@ mpegts_service_setsourceinfo(service_t *t, source_info_t *si)
|
|||
si->si_service = strdup(s->s_dvb_svcname);
|
||||
}
|
||||
|
||||
/*
|
||||
* Load
|
||||
*/
|
||||
void
|
||||
mpegts_service_load_one
|
||||
( mpegts_service_t *ms, htsmsg_t *c )
|
||||
{
|
||||
uint32_t u32;
|
||||
const char *str;
|
||||
|
||||
/* Load core */
|
||||
service_load((service_t*)ms, c);
|
||||
|
||||
/* Load local */
|
||||
if (!htsmsg_get_u32(c, "pcr_pid", &u32))
|
||||
ms->s_pcr_pid = u32;
|
||||
if (!htsmsg_get_u32(c, "pmt_pid", &u32))
|
||||
ms->s_pmt_pid = u32;
|
||||
if (!htsmsg_get_u32(c, "sid", &u32))
|
||||
ms->s_dvb_service_id = u32;
|
||||
if (!htsmsg_get_u32(c, "channel_num", &u32))
|
||||
ms->s_dvb_channel_num = u32;
|
||||
if ((str = htsmsg_get_str(c, "svcname")))
|
||||
tvh_str_update(&ms->s_dvb_svcname, str);
|
||||
if ((str = htsmsg_get_str(c, "provider")))
|
||||
tvh_str_update(&ms->s_dvb_provider, str);
|
||||
if ((str = htsmsg_get_str(c, "default_authority")))
|
||||
tvh_str_update(&ms->s_dvb_default_authority, str);
|
||||
if (!htsmsg_get_u32(c, "servicetype", &u32))
|
||||
ms->s_dvb_servicetype = u32;
|
||||
if ((str = htsmsg_get_str(c, "charset")))
|
||||
tvh_str_update(&ms->s_dvb_charset, str);
|
||||
if (!htsmsg_get_u32(c, "eit_enable", &u32))
|
||||
ms->s_dvb_eit_enable = u32 ? 1 : 0;
|
||||
}
|
||||
/* **************************************************************************
|
||||
* Creation/Location
|
||||
* *************************************************************************/
|
||||
|
||||
/*
|
||||
* Create service
|
||||
|
@ -245,9 +223,9 @@ mpegts_service_load_one
|
|||
mpegts_service_t *
|
||||
mpegts_service_create0
|
||||
( mpegts_service_t *s, const idclass_t *class, const char *uuid,
|
||||
mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid )
|
||||
mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid, htsmsg_t *conf )
|
||||
{
|
||||
service_create0((service_t*)s, class, uuid, S_MPEG_TS);
|
||||
service_create0((service_t*)s, class, uuid, S_MPEG_TS, conf);
|
||||
|
||||
/* Create */
|
||||
tvhlog(LOG_DEBUG, "mpegts", "Add service %04X on %s", sid, "TODO");
|
||||
|
@ -260,12 +238,12 @@ mpegts_service_create0
|
|||
LIST_INSERT_HEAD(&mm->mm_services, s, s_dvb_mux_link);
|
||||
|
||||
s->s_is_enabled = mpegts_service_is_enabled;
|
||||
s->s_config_save = mpegts_service_config_save;
|
||||
s->s_enlist = mpegts_service_enlist;
|
||||
s->s_start_feed = mpegts_service_start;
|
||||
s->s_stop_feed = mpegts_service_stop;
|
||||
s->s_refresh_feed = mpegts_service_refresh;
|
||||
s->s_setsourceinfo = mpegts_service_setsourceinfo;
|
||||
s->s_config_save = mpegts_service_config_save;
|
||||
#if 0
|
||||
s->s_grace_period = mpegts_service_grace_period;
|
||||
#endif
|
||||
|
@ -283,7 +261,7 @@ mpegts_service_create0
|
|||
mpegts_service_t *
|
||||
mpegts_service_find
|
||||
( mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid,
|
||||
const char *uuid, int *save )
|
||||
int create, int *save )
|
||||
{
|
||||
mpegts_service_t *s;
|
||||
|
||||
|
@ -301,13 +279,20 @@ mpegts_service_find
|
|||
}
|
||||
}
|
||||
|
||||
/* Ignore */
|
||||
if (!pmt_pid)
|
||||
return NULL;
|
||||
|
||||
/* Create */
|
||||
s = mm->mm_network->mn_create_service(mm, sid, pmt_pid);
|
||||
if (save) *save = 1;
|
||||
if (create) {
|
||||
s = mm->mm_network->mn_create_service(mm, sid, pmt_pid);
|
||||
if (save) *save = 1;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save
|
||||
*/
|
||||
void
|
||||
mpegts_service_save ( mpegts_service_t *s, htsmsg_t *c )
|
||||
{
|
||||
service_save((service_t*)s, c);
|
||||
}
|
||||
|
|
222
src/service.c
222
src/service.c
|
@ -42,27 +42,27 @@
|
|||
#include "atomic.h"
|
||||
#include "htsp_server.h"
|
||||
#include "lang_codes.h"
|
||||
#include "descrambler.h"
|
||||
|
||||
static void service_data_timeout(void *aux);
|
||||
static const char *service_channel_get(void *obj);
|
||||
static void service_channel_set(void *obj, const char *str);
|
||||
static const char *service_class_channel_get(void *obj);
|
||||
static void service_class_channel_set(void *obj, const char *str);
|
||||
static void service_class_save(struct idnode *self);
|
||||
|
||||
const idclass_t service_class = {
|
||||
.ic_class = "service",
|
||||
.ic_caption = "Service",
|
||||
.ic_save = service_class_save,
|
||||
.ic_class = "service",
|
||||
.ic_caption = "Service",
|
||||
.ic_save = service_class_save,
|
||||
.ic_properties = (const property_t[]){
|
||||
{
|
||||
{
|
||||
"channel", "Channel", PT_STR,
|
||||
|
||||
.str_get = service_channel_get,
|
||||
.str_set = service_channel_set,
|
||||
}, {
|
||||
"enabled", "Enabled", PT_BOOL,
|
||||
offsetof(service_t, s_enabled)
|
||||
}, {
|
||||
}}
|
||||
.str_get = service_class_channel_get,
|
||||
.str_set = service_class_channel_set,
|
||||
},
|
||||
{ PROPDEF1("enabled", "Enabled",
|
||||
PT_BOOL, service_t, s_enabled) },
|
||||
{}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -482,7 +482,8 @@ service_destroy(service_t *t)
|
|||
*/
|
||||
service_t *
|
||||
service_create0
|
||||
( service_t *t, const idclass_t *class, const char *uuid, int source_type)
|
||||
( service_t *t, const idclass_t *class, const char *uuid,
|
||||
int source_type, htsmsg_t *conf )
|
||||
{
|
||||
idnode_insert(&t->s_id, uuid, class);
|
||||
|
||||
|
@ -493,16 +494,13 @@ service_create0
|
|||
t->s_source_type = source_type;
|
||||
t->s_refcount = 1;
|
||||
t->s_enabled = 1;
|
||||
#ifdef MOVE_TO_TODO
|
||||
t->s_pcr_last = PTS_UNSET;
|
||||
#endif
|
||||
TAILQ_INIT(&t->s_components);
|
||||
|
||||
#ifdef MOVE_TO_MPEGTS
|
||||
sbuf_init(&t->s_tsbuf);
|
||||
#endif
|
||||
|
||||
streaming_pad_init(&t->s_streaming_pad);
|
||||
|
||||
/* Load config */
|
||||
if (conf)
|
||||
service_load(t, conf);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
@ -669,7 +667,8 @@ service_map_channel(service_t *t, channel_t *ch, int save)
|
|||
/**
|
||||
*
|
||||
*/
|
||||
static const char *service_channel_get(void *obj)
|
||||
static const char *
|
||||
service_class_channel_get(void *obj)
|
||||
{
|
||||
service_t *s = obj;
|
||||
return s->s_ch ? s->s_ch->ch_name : NULL;
|
||||
|
@ -680,7 +679,7 @@ static const char *service_channel_get(void *obj)
|
|||
*
|
||||
*/
|
||||
static void
|
||||
service_channel_set(void *obj, const char *str)
|
||||
service_class_channel_set(void *obj, const char *str)
|
||||
{
|
||||
service_map_channel(obj, str ? channel_find_by_name(str, 1, 0) : NULL, 0);
|
||||
}
|
||||
|
@ -1280,8 +1279,6 @@ void service_save ( service_t *t, htsmsg_t *m )
|
|||
|
||||
htsmsg_add_u32(m, "pcr", t->s_pcr_pid);
|
||||
|
||||
htsmsg_add_u32(m, "disabled", !t->s_enabled);
|
||||
|
||||
lock_assert(&t->s_stream_mutex);
|
||||
|
||||
list = htsmsg_create_list();
|
||||
|
@ -1337,6 +1334,177 @@ void service_save ( service_t *t, htsmsg_t *m )
|
|||
htsmsg_add_msg(m, "stream", list);
|
||||
}
|
||||
|
||||
void service_load ( service_t *s, htsmsg_t *c )
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static int
|
||||
escmp(const void *A, const void *B)
|
||||
{
|
||||
elementary_stream_t *a = *(elementary_stream_t **)A;
|
||||
elementary_stream_t *b = *(elementary_stream_t **)B;
|
||||
return a->es_position - b->es_position;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
sort_elementary_streams(service_t *t)
|
||||
{
|
||||
elementary_stream_t *st, **v;
|
||||
int num = 0, i = 0;
|
||||
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link)
|
||||
num++;
|
||||
|
||||
v = alloca(num * sizeof(elementary_stream_t *));
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link)
|
||||
v[i++] = st;
|
||||
|
||||
qsort(v, num, sizeof(elementary_stream_t *), escmp);
|
||||
|
||||
TAILQ_INIT(&t->s_components);
|
||||
for(i = 0; i < num; i++)
|
||||
TAILQ_INSERT_TAIL(&t->s_components, v[i], es_link);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
add_caid(elementary_stream_t *st, uint16_t caid, uint32_t providerid)
|
||||
{
|
||||
caid_t *c = malloc(sizeof(caid_t));
|
||||
c->caid = caid;
|
||||
c->providerid = providerid;
|
||||
c->delete_me = 0;
|
||||
LIST_INSERT_HEAD(&st->es_caids, c, link);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
load_legacy_caid(htsmsg_t *c, elementary_stream_t *st)
|
||||
{
|
||||
uint32_t a, b;
|
||||
const char *v;
|
||||
|
||||
if(htsmsg_get_u32(c, "caproviderid", &b))
|
||||
b = 0;
|
||||
|
||||
if(htsmsg_get_u32(c, "caidnum", &a)) {
|
||||
if((v = htsmsg_get_str(c, "caid")) != NULL) {
|
||||
a = descrambler_name2caid(v);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
add_caid(st, a, b);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
load_caid(htsmsg_t *m, elementary_stream_t *st)
|
||||
{
|
||||
htsmsg_field_t *f;
|
||||
htsmsg_t *c, *v = htsmsg_get_list(m, "caidlist");
|
||||
uint32_t a, b;
|
||||
|
||||
if(v == NULL)
|
||||
return;
|
||||
|
||||
HTSMSG_FOREACH(f, v) {
|
||||
if((c = htsmsg_get_map_by_field(f)) == NULL)
|
||||
continue;
|
||||
|
||||
if(htsmsg_get_u32(c, "caid", &a))
|
||||
continue;
|
||||
|
||||
if(htsmsg_get_u32(c, "providerid", &b))
|
||||
b = 0;
|
||||
|
||||
add_caid(st, a, b);
|
||||
}
|
||||
}
|
||||
|
||||
void service_load ( service_t *t, htsmsg_t *c )
|
||||
{
|
||||
htsmsg_t *m;
|
||||
htsmsg_field_t *f;
|
||||
uint32_t u32, pid;
|
||||
elementary_stream_t *st;
|
||||
streaming_component_type_t type;
|
||||
const char *v;
|
||||
|
||||
idnode_load(&t->s_id, c);
|
||||
|
||||
if(!htsmsg_get_u32(c, "pcr", &u32))
|
||||
t->s_pcr_pid = u32;
|
||||
|
||||
m = htsmsg_get_map(c, "stream");
|
||||
if (m) {
|
||||
HTSMSG_FOREACH(f, m) {
|
||||
if((c = htsmsg_get_map_by_field(f)) == NULL)
|
||||
continue;
|
||||
|
||||
if((v = htsmsg_get_str(c, "type")) == NULL)
|
||||
continue;
|
||||
|
||||
type = streaming_component_txt2type(v);
|
||||
if(type == -1)
|
||||
continue;
|
||||
|
||||
if(htsmsg_get_u32(c, "pid", &pid))
|
||||
continue;
|
||||
|
||||
st = service_stream_create(t, pid, type);
|
||||
|
||||
if((v = htsmsg_get_str(c, "language")) != NULL)
|
||||
strncpy(st->es_lang, lang_code_get(v), 3);
|
||||
|
||||
#if 0
|
||||
if (SCT_ISAUDIO(type)) {
|
||||
if(!htsmsg_get_u32(c, "audio_type", &u32))
|
||||
st->es_audio_type = u32;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(!htsmsg_get_u32(c, "position", &u32))
|
||||
st->es_position = u32;
|
||||
|
||||
load_legacy_caid(c, st);
|
||||
load_caid(c, st);
|
||||
|
||||
if(type == SCT_DVBSUB) {
|
||||
if(!htsmsg_get_u32(c, "compositionid", &u32))
|
||||
st->es_composition_id = u32;
|
||||
|
||||
if(!htsmsg_get_u32(c, "ancillartyid", &u32))
|
||||
st->es_ancillary_id = u32;
|
||||
}
|
||||
|
||||
if(type == SCT_TEXTSUB) {
|
||||
if(!htsmsg_get_u32(c, "parentpid", &u32))
|
||||
st->es_parent_pid = u32;
|
||||
}
|
||||
|
||||
if(type == SCT_MPEG2VIDEO || type == SCT_H264) {
|
||||
if(!htsmsg_get_u32(c, "width", &u32))
|
||||
st->es_width = u32;
|
||||
|
||||
if(!htsmsg_get_u32(c, "height", &u32))
|
||||
st->es_height = u32;
|
||||
|
||||
if(!htsmsg_get_u32(c, "duration", &u32))
|
||||
st->es_frame_duration = u32;
|
||||
}
|
||||
}
|
||||
}
|
||||
sort_elementary_streams(t);
|
||||
}
|
||||
|
|
|
@ -423,10 +423,10 @@ void service_init(void);
|
|||
|
||||
int service_start(service_t *t, int instance);
|
||||
|
||||
service_t *service_create0(service_t *t, const idclass_t *idc, const char *uuid, int source_type);
|
||||
service_t *service_create0(service_t *t, const idclass_t *idc, const char *uuid, int source_type, htsmsg_t *conf);
|
||||
|
||||
#define service_create(t, c, u, s)\
|
||||
(struct t*)service_create0(calloc(1, sizeof(struct t), &t##_class, c, u, s)
|
||||
#define service_create(t, c, u, s, m)\
|
||||
(struct t*)service_create0(calloc(1, sizeof(struct t), &t##_class, c, u, s, m)
|
||||
|
||||
void service_unref(service_t *t);
|
||||
|
||||
|
@ -517,4 +517,6 @@ void service_load ( service_t *s, htsmsg_t *c );
|
|||
|
||||
void service_save ( service_t *s, htsmsg_t *c );
|
||||
|
||||
void sort_elementary_streams(service_t *t);
|
||||
|
||||
#endif // SERVICE_H__
|
||||
|
|
|
@ -521,3 +521,9 @@ streaming_component_type2txt(streaming_component_type_t s)
|
|||
{
|
||||
return val2str(s, streamtypetab) ?: "INVALID";
|
||||
}
|
||||
|
||||
streaming_component_type_t
|
||||
streaming_component_txt2type(const char *s)
|
||||
{
|
||||
return str2val(s, streamtypetab);
|
||||
}
|
||||
|
|
|
@ -427,6 +427,7 @@ typedef struct sbuf {
|
|||
|
||||
|
||||
const char *streaming_component_type2txt(streaming_component_type_t s);
|
||||
streaming_component_type_t streaming_component_txt2type(const char *s);
|
||||
|
||||
static inline unsigned int tvh_strhash(const char *s, unsigned int mod)
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue