service: trying to sort the service saving

This commit is contained in:
Adam Sutton 2013-05-31 21:45:29 +01:00
parent dc773b0380
commit c412f6e28c
12 changed files with 315 additions and 396 deletions

View file

@ -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__ */

View file

@ -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;
}
/* **************************************************************************

View file

@ -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 );
/******************************************************************************

View file

@ -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

View file

@ -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;

View file

@ -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?

View file

@ -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) },

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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__

View file

@ -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);
}

View file

@ -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)
{