From 3a1cbb9f530760eb8f5f679205830db51bc13e63 Mon Sep 17 00:00:00 2001 From: Adam Sutton Date: Tue, 27 Aug 2013 21:07:54 +0100 Subject: [PATCH] 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) --- src/input/mpegts.h | 18 ++++- src/input/mpegts/linuxdvb/linuxdvb_frontend.c | 2 +- src/input/mpegts/mpegts_input.c | 7 +- src/input/mpegts/mpegts_mux.c | 81 ++++++++++++++----- src/input/mpegts/mpegts_network.c | 2 +- src/input/mpegts/mpegts_service.c | 8 +- 6 files changed, 88 insertions(+), 30 deletions(-) diff --git a/src/input/mpegts.h b/src/input/mpegts.h index 59bb3086..d0400af3 100644 --- a/src/input/mpegts.h +++ b/src/input/mpegts.h @@ -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 ); diff --git a/src/input/mpegts/linuxdvb/linuxdvb_frontend.c b/src/input/mpegts/linuxdvb/linuxdvb_frontend.c index bd6838b8..874c10a8 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_frontend.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_frontend.c @@ -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); diff --git a/src/input/mpegts/mpegts_input.c b/src/input/mpegts/mpegts_input.c index 79b39c75..9bc5de8c 100644 --- a/src/input/mpegts/mpegts_input.c +++ b/src/input/mpegts/mpegts_input.c @@ -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 */ diff --git a/src/input/mpegts/mpegts_mux.c b/src/input/mpegts/mpegts_mux.c index b7143d53..5dd688da 100644 --- a/src/input/mpegts/mpegts_mux.c +++ b/src/input/mpegts/mpegts_mux.c @@ -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; diff --git a/src/input/mpegts/mpegts_network.c b/src/input/mpegts/mpegts_network.c index 91e82677..8774df67 100644 --- a/src/input/mpegts/mpegts_network.c +++ b/src/input/mpegts/mpegts_network.c @@ -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); } diff --git a/src/input/mpegts/mpegts_service.c b/src/input/mpegts/mpegts_service.c index f3d83810..e68e7de4 100644 --- a/src/input/mpegts/mpegts_service.c +++ b/src/input/mpegts/mpegts_service.c @@ -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; }