mpegts: add the concept of a mux level subscription

This is necessary so that things like EPG grabbing can make
subscriptions that take precedence over initial scan but not
over standard subscriptions.

Will also be used for the debug mux dump from UI feature.
(cherry picked from commit 35a58bdf85008b819504e86e26f1072f79e79af3)
This commit is contained in:
Adam Sutton 2013-08-27 21:07:54 +01:00
parent e5140a9c75
commit 3a1cbb9f53
6 changed files with 88 additions and 30 deletions

View file

@ -34,6 +34,7 @@ typedef struct mpegts_network mpegts_network_t;
typedef struct mpegts_mux mpegts_mux_t;
typedef struct mpegts_service mpegts_service_t;
typedef struct mpegts_mux_instance mpegts_mux_instance_t;
typedef struct mpegts_mux_sub mpegts_mux_sub_t;
typedef struct mpegts_input mpegts_input_t;
typedef struct mpegts_table_feed mpegts_table_feed_t;
@ -251,8 +252,9 @@ struct mpegts_mux
void (*mm_config_save) (mpegts_mux_t *mm);
void (*mm_display_name) (mpegts_mux_t*, char *buf, size_t len);
int (*mm_is_enabled) (mpegts_mux_t *mm);
int (*mm_start) (mpegts_mux_t *mm, const char *r, int w);
void (*mm_stop) (mpegts_mux_t *mm);
int (*mm_start) (mpegts_mux_t *mm,
void *src, const char *r, int w);
void (*mm_stop) (mpegts_mux_t *mm, void *src, int force);
void (*mm_open_table) (mpegts_mux_t*,mpegts_table_t*);
void (*mm_close_table) (mpegts_mux_t*,mpegts_table_t*);
void (*mm_create_instances) (mpegts_mux_t*);
@ -349,12 +351,21 @@ struct mpegts_mux_instance
mpegts_mux_t *mmi_mux;
mpegts_input_t *mmi_input;
RB_HEAD(,mpegts_mux_sub) mmi_subs;
// TODO: remove this
int mmi_tune_failed; // this is really DVB
void (*mmi_delete) (mpegts_mux_instance_t *mmi);
};
struct mpegts_mux_sub
{
RB_ENTRY(mpegts_mux_sub) mms_link;
void *mms_src;
int mms_weight;
};
/* Input source */
struct mpegts_input
{
@ -512,7 +523,8 @@ mpegts_mux_instance_t *mpegts_mux_instance_create0
(struct type*)mpegts_mux_instance_create0(calloc(1, sizeof(struct type)),\
&type##_class, uuid,\
mi, mm);
int mpegts_mux_instance_start ( mpegts_mux_instance_t **mmiptr );
int mpegts_mux_instance_start
( mpegts_mux_instance_t **mmiptr, void *src, int weight );
int mpegts_mux_set_tsid ( mpegts_mux_t *mm, uint16_t tsid );
int mpegts_mux_set_onid ( mpegts_mux_t *mm, uint16_t onid );

View file

@ -673,7 +673,7 @@ linuxdvb_frontend_tune0
return 0;
/* Stop current */
cur->mmi_mux->mm_stop(cur->mmi_mux);
cur->mmi_mux->mm_stop(cur->mmi_mux, NULL, 1);
}
assert(LIST_FIRST(&lfe->mi_mux_active) == NULL);

View file

@ -93,6 +93,7 @@ int
mpegts_input_current_weight ( mpegts_input_t *mi )
{
const mpegts_mux_instance_t *mmi;
const mpegts_mux_sub_t *mms;
const service_t *s;
const th_subscription_t *ths;
int w = 0;
@ -101,10 +102,8 @@ mpegts_input_current_weight ( mpegts_input_t *mi )
/* Check for scan (weight 1) */
LIST_FOREACH(mmi, &mi->mi_mux_active, mmi_active_link) {
if (mmi->mmi_mux->mm_initial_scan_status == MM_SCAN_CURRENT) {
w = 1;
break;
}
RB_FOREACH(mms, &mmi->mmi_subs, mms_link)
w = MAX(w, mms->mms_weight);
}
/* Check subscriptions */

View file

@ -68,8 +68,17 @@ mpegts_mux_instance_create0
return mmi;
}
static int
mms_cmp ( mpegts_mux_sub_t *a, mpegts_mux_sub_t *b )
{
if (a->mms_src < b->mms_src) return -1;
if (a->mms_src > b->mms_src) return 1;
return 0;
}
int
mpegts_mux_instance_start ( mpegts_mux_instance_t **mmiptr )
mpegts_mux_instance_start
( mpegts_mux_instance_t **mmiptr, void *src, int weight )
{
int r;
char buf[256], buf2[256];;
@ -91,6 +100,21 @@ mpegts_mux_instance_start ( mpegts_mux_instance_t **mmiptr )
r = mmi->mmi_input->mi_start_mux(mmi->mmi_input, mmi);
if (r) return r;
/* Add sub */
if (src) {
mpegts_mux_sub_t *sub;
static mpegts_mux_sub_t *skel = NULL;
if (!skel)
skel = calloc(1, sizeof(mpegts_mux_sub_t));
skel->mms_src = src;
sub = RB_INSERT_SORTED(&mmi->mmi_subs, skel, mms_link, mms_cmp);
if (!sub) {
sub = skel;
skel = NULL;
sub->mms_weight = weight;
}
}
/* Start */
tvhdebug("mpegts", "%s - started", buf);
mmi->mmi_input->mi_started_mux(mmi->mmi_input, mmi);
@ -251,7 +275,7 @@ mpegts_mux_delete ( mpegts_mux_t *mm )
tvhinfo("mpegts", "%s - deleting", buf);
/* Stop */
mm->mm_stop(mm);
mm->mm_stop(mm, NULL, 1);
/* Remove from lists */
LIST_REMOVE(mm, mm_network_link);
@ -290,7 +314,8 @@ mpegts_mux_create_instances ( mpegts_mux_t *mm )
}
static int
mpegts_mux_start ( mpegts_mux_t *mm, const char *reason, int weight )
mpegts_mux_start
( mpegts_mux_t *mm, void *src, const char *reason, int weight )
{
int pass, fail;
char buf[256];
@ -353,7 +378,7 @@ mpegts_mux_start ( mpegts_mux_t *mm, const char *reason, int weight )
if (tune) {
tvhinfo("mpegts", "%s - starting for '%s' (weight %d)",
buf, reason, weight);
if (!(fail = mpegts_mux_instance_start(&tune))) break;
if (!(fail = mpegts_mux_instance_start(&tune, src, weight))) break;
tune = NULL;
tvhwarn("mpegts", "%s - failed to start, try another", buf);
}
@ -371,12 +396,44 @@ mpegts_mux_start ( mpegts_mux_t *mm, const char *reason, int weight )
return 0;
}
static int
mpegts_mux_has_subscribers ( mpegts_mux_t *mm )
{
mpegts_mux_instance_t *mmi = mm->mm_active;
if (mmi) {
if (RB_FIRST(&mmi->mmi_subs))
return 1;
return mmi->mmi_input->mi_has_subscription(mmi->mmi_input, mm);
}
return 0;
}
static void
mpegts_mux_stop ( mpegts_mux_t *mm )
mpegts_mux_stop ( mpegts_mux_t *mm, void *src, int force )
{
char buf[256];
mpegts_mux_instance_t *mmi = mm->mm_active;
mpegts_input_t *mi = NULL;
mpegts_mux_sub_t *sub, skel;
/* Remove subs */
if (mmi) {
if (force) {
while ((sub = RB_FIRST(&mmi->mmi_subs))) {
RB_REMOVE(&mmi->mmi_subs, sub, mms_link);
free(sub);
}
} else if (src) {
skel.mms_src = src;
if ((sub = RB_FIND(&mmi->mmi_subs, &skel, mms_link, mms_cmp))) {
RB_REMOVE(&mmi->mmi_subs, sub, mms_link);
free(sub);
}
}
}
if (mpegts_mux_has_subscribers(mm))
return;
mm->mm_display_name(mm, buf, sizeof(buf));
tvhdebug("mpegts", "%s - stopping mux", buf);
@ -442,15 +499,6 @@ mpegts_mux_close_table ( mpegts_mux_t *mm, mpegts_table_t *mt )
* Scanning
* *************************************************************************/
static int
mpegts_mux_has_subscribers ( mpegts_mux_t *mm )
{
mpegts_mux_instance_t *mmi = mm->mm_active;
if (mmi)
return mmi->mmi_input->mi_has_subscription(mmi->mmi_input, mm);
return 0;
}
static void
mpegts_mux_initial_scan_link ( mpegts_mux_t *mm )
{
@ -497,10 +545,7 @@ mpegts_mux_initial_scan_done ( mpegts_mux_t *mm )
mpegts_network_schedule_initial_scan(mn);
/* Stop */
if (!mpegts_mux_has_subscribers(mm)) {
tvhtrace("mpegts", "%s - no active subscribers, stop", buf);
mm->mm_stop(mm);
}
mm->mm_stop(mm, mn, 0);
/* Save */
mm->mm_initial_scan_done = 1;

View file

@ -241,7 +241,7 @@ mpegts_network_initial_scan(void *aux)
tvhtrace("mpegts", "setup initial scan for %p", mn);
while((mm = TAILQ_FIRST(&mn->mn_initial_scan_pending_queue)) != NULL) {
assert(mm->mm_initial_scan_status == MM_SCAN_PENDING);
if (mm->mm_start(mm, "initial scan", 1))
if (mm->mm_start(mm, mn, "initial scan", 1))
break;
assert(mm->mm_initial_scan_status == MM_SCAN_CURRENT);
}

View file

@ -182,7 +182,7 @@ mpegts_service_start(service_t *t, int instance)
return SM_CODE_UNDEFINED_ERROR;
/* Start Mux */
r = mpegts_mux_instance_start(&mmi);
r = mpegts_mux_instance_start(&mmi, NULL, 0);
/* Start */
if (!r) {
@ -200,8 +200,9 @@ mpegts_service_start(service_t *t, int instance)
static void
mpegts_service_stop(service_t *t)
{
mpegts_service_t *s = (mpegts_service_t*)t;
mpegts_input_t *i = s->s_dvb_active_input;
mpegts_service_t *s = (mpegts_service_t*)t;
mpegts_mux_t *mm = (mpegts_mux_t*)s->s_dvb_mux;
mpegts_input_t *i = s->s_dvb_active_input;
/* Validate */
assert(s->s_source_type == S_MPEG_TS);
@ -209,6 +210,7 @@ mpegts_service_stop(service_t *t)
lock_assert(&global_lock);
/* Stop */
mm->mm_stop(mm, NULL, 0);
i->mi_close_service(i, s);
s->s_status = SERVICE_IDLE;
}