]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
subscription: add TABLES subscription type handling, fix some memory leaks
authorJaroslav Kysela <perex@perex.cz>
Wed, 11 Mar 2015 14:12:26 +0000 (15:12 +0100)
committerJaroslav Kysela <perex@perex.cz>
Wed, 11 Mar 2015 20:41:13 +0000 (21:41 +0100)
15 files changed:
src/epggrab/otamux.c
src/input/mpegts.h
src/input/mpegts/linuxdvb/linuxdvb_frontend.c
src/input/mpegts/mpegts_input.c
src/input/mpegts/mpegts_mux.c
src/input/mpegts/mpegts_network_scan.c
src/input/mpegts/mpegts_pid.c
src/input/mpegts/mpegts_service.c
src/input/mpegts/satip/satip_frontend.c
src/input/mpegts/tsdemux.c
src/input/mpegts/tvhdhomerun/tvhdhomerun_frontend.c
src/service.c
src/service.h
src/subscriptions.c
src/subscriptions.h

index 320a0900ed763df3cf7672dcd5647cffaf018b1d..31a08ce754e45457ec4b596ec0f208e72684405b 100644 (file)
@@ -546,8 +546,11 @@ next_one:
 
   /* Subscribe to the mux */
   om->om_requeue = 1;
-  if ((r = mpegts_mux_subscribe(mm, NULL, "epggrab", SUBSCRIPTION_PRIO_EPG,
-                                SUBSCRIPTION_EPG | SUBSCRIPTION_ONESHOT))) {
+  if ((r = mpegts_mux_subscribe(mm, NULL, "epggrab",
+                                SUBSCRIPTION_PRIO_EPG,
+                                SUBSCRIPTION_EPG |
+                                SUBSCRIPTION_ONESHOT |
+                                SUBSCRIPTION_TABLES))) {
     TAILQ_INSERT_TAIL(&epggrab_ota_pending, om, om_q_link);
     om->om_q_type = EPGGRAB_OTA_MUX_PENDING;
     if (r == SM_CODE_NO_FREE_ADAPTER)
index a1d1223e4b13ca36d917550042a4b0620946f851..92394c090695fabf8b1490a3caeb15edf16a5239 100644 (file)
@@ -34,6 +34,7 @@
 #define MPEGTS_TSID_NONE        0xFFFF
 #define MPEGTS_PSI_SECTION_SIZE 5000
 #define MPEGTS_FULLMUX_PID      0x2000
+#define MPEGTS_TABLES_PID       0x2001
 #define MPEGTS_PID_NONE         0xFFFF
 
 /* Types */
@@ -155,6 +156,7 @@ typedef struct mpegts_pid_sub
 #define MPS_SERVICE 0x08
 #define MPS_TABLE   0x10
 #define MPS_FTABLE  0x20
+#define MPS_TABLES  0x40
   int                       mps_type;
   void                     *mps_owner;
 } mpegts_pid_sub_t;
@@ -502,6 +504,8 @@ struct mpegts_service
 {
   service_t; // Parent
 
+  int      s_dvb_subscription_flags;
+
   /*
    * Fields defined by DVB standard EN 300 468
    */
@@ -680,7 +684,7 @@ struct mpegts_input
   int  (*mi_warm_mux)       (mpegts_input_t*,mpegts_mux_instance_t*);
   int  (*mi_start_mux)      (mpegts_input_t*,mpegts_mux_instance_t*);
   void (*mi_stop_mux)       (mpegts_input_t*,mpegts_mux_instance_t*);
-  void (*mi_open_service)   (mpegts_input_t*,mpegts_service_t*,int first);
+  void (*mi_open_service)   (mpegts_input_t*,mpegts_service_t*,int flags, int first);
   void (*mi_close_service)  (mpegts_input_t*,mpegts_service_t*);
   mpegts_pid_t *(*mi_open_pid)(mpegts_input_t*,mpegts_mux_t*,int,int,void*);
   void (*mi_close_pid)      (mpegts_input_t*,mpegts_mux_t*,int,int,void*);
@@ -737,7 +741,7 @@ int mpegts_input_set_networks ( mpegts_input_t *mi, htsmsg_t *msg );
 
 int mpegts_input_add_network  ( mpegts_input_t *mi, mpegts_network_t *mn );
 
-void mpegts_input_open_service ( mpegts_input_t *mi, mpegts_service_t *s, int init );
+void mpegts_input_open_service ( mpegts_input_t *mi, mpegts_service_t *s, int flags, int init );
 void mpegts_input_close_service ( mpegts_input_t *mi, mpegts_service_t *s );
 
 void mpegts_input_status_timer ( void *p );
@@ -887,7 +891,7 @@ void mpegts_input_close_pid
   ( mpegts_input_t *mi, mpegts_mux_t *mm, int pid, int type, void *owner );
 
 void mpegts_input_close_pids
-  ( mpegts_input_t *mi, mpegts_mux_t *mm, int type, void *owner );
+  ( mpegts_input_t *mi, mpegts_mux_t *mm, void *owner );
 
 static inline void
 tsdebug_write(mpegts_mux_t *mm, uint8_t *buf, size_t len)
index 2eb712051ef303eaa259acb122e312daa7618916..b58d617c102e8087f63226081adf5eb32b23e614 100644 (file)
@@ -366,6 +366,10 @@ linuxdvb_frontend_open_pid0
   struct dmx_pes_filter_params dmx_param;
   int fd;
 
+  /* Do not open internal PIDs */
+  if (mp->mp_pid > MPEGTS_FULLMUX_PID)
+    return;
+
   /* Already opened */
   if (mp->mp_fd != -1)
     return;
index 890120211b0c8099c8bcee75b9d45623d77e7489..f6533d2f9e3a4562174e66b9a19e01154dc22ed2 100644 (file)
@@ -408,28 +408,20 @@ mpegts_mps_cmp ( mpegts_pid_sub_t *a, mpegts_pid_sub_t *b )
 
 void
 mpegts_input_close_pids
-  ( mpegts_input_t *mi, mpegts_mux_t *mm, int type, void *owner )
+  ( mpegts_input_t *mi, mpegts_mux_t *mm, void *owner )
 {
   mpegts_pid_t *mp, *mp_next;
   mpegts_pid_sub_t *mps, *mps_next;
 
   for (mp = RB_FIRST(&mm->mm_pids); mp; mp = mp_next) {
     mp_next = RB_NEXT(mp, mp_link);
-    if ((mp->mp_type & MPS_RAW) == 0) continue;
     for (mps = RB_FIRST(&mp->mp_subs); mps; mps = mps_next) {
       mps_next = RB_NEXT(mps, mps_link);
       if (mps->mps_owner != owner) continue;
-      LIST_REMOVE(mps, mps_svcraw_link);
-      RB_REMOVE(&mp->mp_subs, mps, mps_link);
-      free(mps);
-      if (!RB_FIRST(&mp->mp_subs)) {
-        RB_REMOVE(&mm->mm_pids, mp, mp_link);
-        free(mp);
-      }
+      mi->mi_close_pid(mi, mm, mp->mp_pid, mps->mps_type, mps->mps_owner);
     }
   }
 }
-
 mpegts_pid_t *
 mpegts_input_open_pid
   ( mpegts_input_t *mi, mpegts_mux_t *mm, int pid, int type, void *owner )
@@ -437,6 +429,7 @@ mpegts_input_open_pid
   char buf[512];
   mpegts_pid_t *mp;
   mpegts_pid_sub_t *mps, *mps2;
+
   assert(owner != NULL);
   assert((type & (MPS_STREAM|MPS_SERVICE|MPS_RAW)) == 0 ||
          (((type & MPS_STREAM) ? 1 : 0) +
@@ -445,21 +438,21 @@ mpegts_input_open_pid
   lock_assert(&mi->mi_output_lock);
 
   if (pid == MPEGTS_FULLMUX_PID)
-    mpegts_input_close_pids(mi, mm, MPS_RAW, owner);
+    mpegts_input_close_pids(mi, mm, owner);
 
   if ((mp = mpegts_mux_find_pid(mm, pid, 1))) {
     mps = calloc(1, sizeof(*mps));
     mps->mps_type  = type;
     mps->mps_owner = owner;
-    if (pid == MPEGTS_FULLMUX_PID) {
-      mp->mp_type |= type | MPS_ALL;
+    if (pid == MPEGTS_FULLMUX_PID || pid == MPEGTS_TABLES_PID) {
+      mp->mp_type |= type;
       LIST_FOREACH(mps2, &mm->mm_all_subs, mps_svcraw_link)
         if (mps2->mps_owner == owner) break;
       if (mps2 == NULL) {
         LIST_INSERT_HEAD(&mm->mm_all_subs, mps, mps_svcraw_link);
         mpegts_mux_nice_name(mm, buf, sizeof(buf));
-        tvhdebug("mpegts", "%s - open PID fullmux subscription [%d/%p]",
-                 buf, type, owner);
+        tvhdebug("mpegts", "%s - open PID %s subscription [%04x/%p]",
+                 buf, (type & MPS_TABLES) ? "tables" : "fullmux", type, owner);
       }
     } else if (!RB_INSERT_SORTED(&mp->mp_subs, mps, mps_link, mpegts_mps_cmp)) {
       mp->mp_type |= type;
@@ -483,20 +476,27 @@ mpegts_input_close_pid
   char buf[512];
   mpegts_pid_sub_t *mps, skel;
   mpegts_pid_t *mp;
+  int mask;
   assert(owner != NULL);
   lock_assert(&mi->mi_output_lock);
   if (!(mp = mpegts_mux_find_pid(mm, pid, 0)))
     return;
-  if (pid == MPEGTS_FULLMUX_PID) {
+  if (pid == MPEGTS_FULLMUX_PID || pid == MPEGTS_TABLES_PID) {
     mpegts_mux_nice_name(mm, buf, sizeof(buf));
-    tvhdebug("mpegts", "%s - close PID fullmux subscription [%d/%p]",
-             buf, type, owner);
-    mpegts_input_close_pids(mi, mm, MPS_RAW, owner);
     LIST_FOREACH(mps, &mm->mm_all_subs, mps_svcraw_link)
       if (mps->mps_owner == owner) break;
     if (mps == NULL) return;
+    tvhdebug("mpegts", "%s - close PID %s subscription [%04x/%p]",
+             buf, pid == MPEGTS_TABLES_PID ? "tables" : "fullmux",
+             type, owner);
+    if (pid == MPEGTS_FULLMUX_PID)
+      mpegts_input_close_pids(mi, mm, owner);
     LIST_REMOVE(mps, mps_svcraw_link);
     free(mps);
+    mask = pid == MPEGTS_FULLMUX_PID ? MPS_ALL : MPS_TABLES;
+    LIST_FOREACH(mps, &mm->mm_all_subs, mps_svcraw_link)
+      if (mps->mps_type & mask) break;
+    if (mps) return;
   } else {
     skel.mps_type  = type;
     skel.mps_owner = owner;
@@ -529,7 +529,7 @@ mpegts_input_close_pid
 }
 
 void
-mpegts_input_open_service ( mpegts_input_t *mi, mpegts_service_t *s, int init )
+mpegts_input_open_service ( mpegts_input_t *mi, mpegts_service_t *s, int flags, int init )
 {
   elementary_stream_t *st;
   mpegts_apids_t *pids;
@@ -557,11 +557,13 @@ mpegts_input_open_service ( mpegts_input_t *mi, mpegts_service_t *s, int init )
   } else {
     if ((pids = s->s_pids) != NULL) {
       if (pids->all) {
-        mi->mi_open_pid(mi, s->s_dvb_mux, MPEGTS_FULLMUX_PID, MPS_RAW, s);
+        mi->mi_open_pid(mi, s->s_dvb_mux, MPEGTS_FULLMUX_PID, MPS_RAW | MPS_ALL, s);
       } else {
         for (i = 0; i < pids->count; i++)
           mi->mi_open_pid(mi, s->s_dvb_mux, pids->pids[i], MPS_RAW, s);
       }
+    } else if (flags & SUBSCRIPTION_TABLES) {
+      mi->mi_open_pid(mi, s->s_dvb_mux, MPEGTS_TABLES_PID, MPS_RAW | MPS_TABLES, s);
     }
   }
 
@@ -607,7 +609,7 @@ mpegts_input_close_service ( mpegts_input_t *mi, mpegts_service_t *s )
       }
     }
   } else {
-    mpegts_input_close_pids(mi, s->s_dvb_mux, MPS_RAW, s);
+    mpegts_input_close_pids(mi, s->s_dvb_mux, s);
   }
 
 
@@ -1058,10 +1060,13 @@ mpegts_input_process
 
       type = mp->mp_type;
       
+      /* Stream all PIDs */
+      LIST_FOREACH(mps, &mm->mm_all_subs, mps_svcraw_link)
+        if ((mps->mps_type & MPS_ALL) || (type & (MPS_TABLE|MPS_FTABLE)))
+          ts_recv_raw((mpegts_service_t *)mps->mps_owner, tsb);
+
       /* Stream raw PIDs */
       if (type & MPS_RAW) {
-        LIST_FOREACH(mps, &mm->mm_all_subs, mps_svcraw_link)
-          ts_recv_raw((mpegts_service_t *)mps->mps_owner, tsb);
         LIST_FOREACH(mps, &mp->mp_svc_subs, mps_svcraw_link)
           ts_recv_raw((mpegts_service_t *)mps->mps_owner, tsb);
       }
index 8cb6233540e1843734150afcf3d003acbca4aa93..738a1c43094e06ca8d715d0970364e9ad08738f3 100644 (file)
@@ -585,6 +585,7 @@ mpegts_mux_delete ( mpegts_mux_t *mm, int delconf )
 {
   mpegts_mux_instance_t *mmi;
   mpegts_service_t *s;
+  th_subscription_t *ths;
   char buf[256];
 
   mpegts_mux_nice_name(mm, buf, sizeof(buf));
@@ -604,6 +605,11 @@ mpegts_mux_delete ( mpegts_mux_t *mm, int delconf )
     mmi->mmi_delete(mmi);
   }
 
+  /* Remove raw subscribers */
+  while ((ths = LIST_FIRST(&mm->mm_raw_subs))) {
+    subscription_unsubscribe(ths, 0);
+  }
+
   /* Delete services */
   while ((s = LIST_FIRST(&mm->mm_services))) {
     service_destroy((service_t*)s, delconf);
@@ -712,10 +718,12 @@ mpegts_mux_stop ( mpegts_mux_t *mm, int force, int reason )
   mm->mm_last_mp = NULL;
   while ((mp = RB_FIRST(&mm->mm_pids))) {
     assert(mi);
-    if (mp->mp_pid == MPEGTS_FULLMUX_PID) {
+    if (mp->mp_pid == MPEGTS_FULLMUX_PID ||
+        mp->mp_pid == MPEGTS_TABLES_PID) {
       while ((mps = LIST_FIRST(&mm->mm_all_subs))) {
-        tvhdebug("mpegts", "%s - close PID fullmux subscription [%d/%p]",
-                 buf, mps->mps_type, mps->mps_owner);
+        tvhdebug("mpegts", "%s - close PID %s subscription [%d/%p]",
+                 buf, mp->mp_pid == MPEGTS_TABLES_PID ? "tables" : "fullmux",
+                 mps->mps_type, mps->mps_owner);
         LIST_REMOVE(mps, mps_svcraw_link);
         free(mps);
       }
@@ -1205,7 +1213,7 @@ mpegts_mux_find_pid_ ( mpegts_mux_t *mm, int pid, int create )
 {
   mpegts_pid_t skel, *mp;
 
-  if (pid > 0x2000) return NULL;
+  if (pid < 0 || pid > MPEGTS_TABLES_PID) return NULL;
 
   skel.mp_pid = pid;
   mp = RB_FIND(&mm->mm_pids, &skel, mp_link, mp_cmp);
index fb3bc14028bfd409d3c06845c0574ca34b8cf24e..442de7eb0a1d8486f842c6e75309ac936c006737 100644 (file)
@@ -54,7 +54,9 @@ mpegts_network_scan_timer_cb ( void *p )
 
     /* Attempt to tune */
     r = mpegts_mux_subscribe(mm, NULL, "scan", mm->mm_scan_weight,
-                             mm->mm_scan_flags | SUBSCRIPTION_ONESHOT);
+                             mm->mm_scan_flags |
+                             SUBSCRIPTION_ONESHOT |
+                             SUBSCRIPTION_TABLES);
 
     /* Started */
     if (!r) {
index 8bbea6034515f814e2948f936215743aa23a133b..9e3a926375c096300b7c206095ea3d33aec368a4 100644 (file)
@@ -41,6 +41,8 @@ mpegts_pid_init(mpegts_apids_t *pids, mpegts_apid_t *vals, int count)
 void
 mpegts_pid_done(mpegts_apids_t *pids)
 {
+  if (pids == NULL)
+    return;
   free(pids->pids);
   pids->pids = NULL;
   pids->alloc = pids->count = 0;
index 48e52de712918f0c2134861513aa27a1b949a9cb..8dc27ee5e876a567891e9b1010d6d5d2b5440ebd 100644 (file)
@@ -279,7 +279,7 @@ mpegts_service_enlist(service_t *t, tvh_input_t *ti,
  * Start service
  */
 static int
-mpegts_service_start(service_t *t, int instance)
+mpegts_service_start(service_t *t, int instance, int flags)
 {
   int r;
   mpegts_service_t      *s = (mpegts_service_t*)t;
@@ -306,7 +306,8 @@ mpegts_service_start(service_t *t, int instance)
   if (!r) {
 
     /* Open service */
-    mmi->mmi_input->mi_open_service(mmi->mmi_input, s, 1);
+    s->s_dvb_subscription_flags = flags;
+    mmi->mmi_input->mi_open_service(mmi->mmi_input, s, flags, 1);
   }
 
   return r;
@@ -348,7 +349,7 @@ mpegts_service_refresh(service_t *t)
   lock_assert(&global_lock);
 
   /* Re-open */
-  i->mi_open_service(i, s, 0);
+  i->mi_open_service(i, s, s->s_dvb_subscription_flags, 0);
 }
 
 /*
@@ -510,7 +511,8 @@ mpegts_service_delete ( service_t *t, int delconf )
   free(ms->s_dvb_provider);
   free(ms->s_dvb_cridauth);
   free(ms->s_dvb_charset);
-  LIST_REMOVE(ms, s_dvb_mux_link);
+  if (t->s_type == STYPE_STD)
+    LIST_REMOVE(ms, s_dvb_mux_link);
   sbuf_free(&ms->s_tsbuf);
 
   // Note: the ultimate deletion and removal from the idnode list
@@ -552,6 +554,7 @@ mpegts_service_create0
   
   s->s_delete         = mpegts_service_delete;
   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;
@@ -640,7 +643,7 @@ mpegts_service_raw_setsourceinfo(service_t *t, source_info_t *si)
   mpegts_service_setsourceinfo(t, si);
 
   free(si->si_service);
-  si->si_service = strdup("Raw Service");
+  si->si_service = strdup("Raw PID Subscription");
 }
 
 static int
@@ -667,12 +670,12 @@ mpegts_service_raw_update_pids(service_t *t, mpegts_apids_t *pids)
     t->s_pids = p;
     if (!pids->all && x && x->all) {
       mi->mi_close_pid(mi, mm, MPEGTS_FULLMUX_PID, MPS_RAW, t);
-      mpegts_input_close_pids(mi, mm, MPS_RAW, t);
+      mpegts_input_close_pids(mi, mm, t);
       for (i = 0; i < x->count; i++)
         mi->mi_open_pid(mi, mm, x->pids[i], MPS_RAW, t);
     } else {
       if (pids->all) {
-        mpegts_input_close_pids(mi, mm, MPS_RAW, t);
+        mpegts_input_close_pids(mi, mm, t);
         mi->mi_open_pid(mi, mm, MPEGTS_FULLMUX_PID, MPS_RAW, t);
       } else {
         mpegts_pid_compare(p, x, &add, &del);
index d5b50a3de053e55760a10f79947a64fa14a4b6d0..c5e7d1246fc612a28d8ff84214e484afb4e603bc 100644 (file)
@@ -604,6 +604,9 @@ satip_frontend_open_pid
   if (!(mp = mpegts_input_open_pid(mi, mm, pid, type, owner)))
     return NULL;
 
+  if (mp->mp_pid > MPEGTS_FULLMUX_PID)
+    return mp;
+
   if (pid == MPEGTS_FULLMUX_PID) {
     pthread_mutex_lock(&lfe->sf_dvr_lock);
     tr = lfe->sf_req;
@@ -649,6 +652,10 @@ satip_frontend_close_pid
   int change = 0;
   int mid, div, cnt;
 
+  /* Skip internal PIDs */
+  if (pid > MPEGTS_FULLMUX_PID)
+    goto finish;
+
   /* remove PID */
   if (pid == MPEGTS_FULLMUX_PID) {
     pthread_mutex_lock(&lfe->sf_dvr_lock);
index 9c8be7e31db0e8d8ebb6fd1e8b645a1266546e17..fbc47580c0da777856ad0b5f31620d909bf0fe89 100644 (file)
@@ -224,6 +224,7 @@ ts_recv_raw(mpegts_service_t *t, const uint8_t *tsb)
   int pid;
 
   pthread_mutex_lock(&t->s_stream_mutex);
+  service_set_streaming_status_flags((service_t*)t, TSS_MUX_PACKETS);
   if (t->s_parent) {
     /* If PID is owned by parent, let parent service to
      * deliver this PID (decrambling)
@@ -231,9 +232,15 @@ ts_recv_raw(mpegts_service_t *t, const uint8_t *tsb)
     pid = (tsb[1] & 0x1f) << 8 | tsb[2];
     st = service_stream_find(t->s_parent, pid);
   }
-  if(st == NULL)
+  if(st == NULL) {
     if (streaming_pad_probe_type(&t->s_streaming_pad, SMT_MPEGTS))
       ts_remux(t, tsb, 0);
+    else {
+      /* No subscriber - set OK markers */
+      service_set_streaming_status_flags((service_t*)t, TSS_PACKETS);
+      t->s_streaming_live |= TSS_LIVE;
+    }
+  }
   pthread_mutex_unlock(&t->s_stream_mutex);
 }
 
index 8a75dcbdd583c7d2cb97bacbc665f69a444d57a5..4de9fd7bbed41672937c5e01bbb02f78e3792302 100644 (file)
@@ -330,6 +330,10 @@ static void tvhdhomerun_device_open_pid(tvhdhomerun_frontend_t *hfe, mpegts_pid_
 
   //tvhdebug("tvhdhomerun", "adding PID 0x%x to pfilter", mp->mp_pid);
 
+  /* Skip internal PIDs */
+  if (mp->mp_pid > MPEGTS_FULLMUX_PID)
+    return;
+
   /* get the current filter */
   pthread_mutex_lock(&hfe->hf_hdhomerun_device_mutex);
   res = hdhomerun_device_get_tuner_filter(hfe->hf_hdhomerun_tuner, &pfilter);
index bf2b0e4b593ba3b76e292bdc427ce25a2cd7724c..38e3c51333731f61277a92f953747763d53b6373 100644 (file)
@@ -370,6 +370,12 @@ service_stop(service_t *t)
   t->s_status = SERVICE_IDLE;
   tvhlog_limit_reset(&t->s_tei_log);
 
+#if ENABLE_MPEGTS
+  mpegts_pid_done(t->s_pids);
+  free(t->s_pids);
+  t->s_pids = NULL;
+#endif
+
   pthread_mutex_unlock(&t->s_stream_mutex);
 }
 
@@ -639,7 +645,7 @@ ignore:
  *
  */
 int
-service_start(service_t *t, int instance, int timeout, int postpone)
+service_start(service_t *t, int instance, int flags, int timeout, int postpone)
 {
   elementary_stream_t *st;
   int r, stimeout = 10;
@@ -659,7 +665,7 @@ service_start(service_t *t, int instance, int timeout, int postpone)
   descrambler_caid_changed(t);
   pthread_mutex_unlock(&t->s_stream_mutex);
 
-  if((r = t->s_start_feed(t, instance)))
+  if((r = t->s_start_feed(t, instance, flags)))
     return r;
 
   descrambler_service_start(t);
@@ -778,7 +784,7 @@ service_find_instance
 
   /* Start */
   tvhtrace("service", "will start new instance %d", si->si_instance);
-  if (service_start(si->si_s, si->si_instance, timeout, postpone)) {
+  if (service_start(si->si_s, si->si_instance, flags, timeout, postpone)) {
     tvhtrace("service", "tuning failed");
     si->si_error = SM_CODE_TUNING_FAILED;
     if (*error < SM_CODE_TUNING_FAILED)
index e9e1b525471ef718e4117873631aa3725460132d..0d17b84c3c6f52d0c23455dc3cb9721d50cf09b5 100644 (file)
@@ -297,7 +297,7 @@ typedef struct service {
   void (*s_enlist)(struct service *s, struct tvh_input *ti,
                    service_instance_list_t *sil, int flags);
 
-  int (*s_start_feed)(struct service *s, int instance);
+  int (*s_start_feed)(struct service *s, int instance, int flags);
 
   void (*s_refresh_feed)(struct service *t);
 
@@ -486,7 +486,7 @@ typedef struct service {
 void service_init(void);
 void service_done(void);
 
-int service_start(service_t *t, int instance, int timeout, int postpone);
+int service_start(service_t *t, int instance, int flags, int timeout, int postpone);
 void service_stop(service_t *t);
 
 void service_build_filter(service_t *t);
index 28fe69dbdc26349361e79aef1ab0e21842b86f94..233d2da604eca027a091ae0f6fc692c78d0b54be 100644 (file)
@@ -262,6 +262,7 @@ subscription_reschedule(void)
 
   LIST_FOREACH(s, &subscriptions, ths_global_link) {
     if (!s->ths_service && !s->ths_channel) continue;
+    if (s->ths_flags & SUBSCRIPTION_ONESHOT) continue;
 
     /* Postpone the tuner decision */
     /* Leave some time to wakeup tuners through DBus or so */
@@ -533,11 +534,14 @@ subscription_unsubscribe(th_subscription_t *s, int quiet)
 
   if (t) {
     service_remove_subscriber(t, s, SM_CODE_OK);
+  }
+
 #if ENABLE_MPEGTS
-    if (t->s_type == STYPE_RAW)
-      LIST_REMOVE(s, ths_mux_link);
-#endif
+  if (s->ths_raw_service) {
+    LIST_REMOVE(s, ths_mux_link);
+    service_destroy(s->ths_raw_service, 0);
   }
+#endif
 
   streaming_msg_free(s->ths_start_message);
 
@@ -637,6 +641,7 @@ subscription_create_from_channel_or_service(profile_chain_t *prch,
                                             service_t *service)
 {
   th_subscription_t *s;
+  service_instance_t *si;
   channel_t *ch = NULL;
 
   assert(prch);
@@ -668,15 +673,18 @@ subscription_create_from_channel_or_service(profile_chain_t *prch,
 #if ENABLE_MPEGTS
   if (service && service->s_type == STYPE_RAW) {
     mpegts_mux_t *mm = prch->prch_id;
+    s->ths_raw_service = service;
     LIST_INSERT_HEAD(&mm->mm_raw_subs, s, ths_mux_link);
   }
 #endif
 
   if (flags & SUBSCRIPTION_ONESHOT) {
-    if (subscription_start_instance(s, error) == NULL) {
+    if ((si = subscription_start_instance(s, error)) == NULL) {
       subscription_unsubscribe(s, 1);
       return NULL;
     }
+    subscription_link_service(s, si->si_s);
+    subscription_show_info(s);
   } else {
     subscription_reschedule();
   }
@@ -859,11 +867,7 @@ subscription_init(void)
 void
 subscription_done(void)
 {
-  th_subscription_t *s;
-
   pthread_mutex_lock(&global_lock);
-  LIST_FOREACH(s, &subscriptions, ths_global_link)
-    subscription_unsubscribe(s, 0);
   /* clear remaining subscriptions */
   subscription_reschedule();
   pthread_mutex_unlock(&global_lock);
index 7221f21f86c77cc540b170d86b9f432fa1b5e483..e760a2d2dd80b402211bfa28c74f20d3029c3d53 100644 (file)
@@ -30,10 +30,11 @@ extern struct th_subscription_list subscriptions;
 #define SUBSCRIPTION_STREAMING  0x004
 #define SUBSCRIPTION_RESTART    0x008
 #define SUBSCRIPTION_ONESHOT    0x010
-#define SUBSCRIPTION_INITSCAN   0x020 ///< for mux subscriptions
-#define SUBSCRIPTION_IDLESCAN   0x040 ///< for mux subscriptions
-#define SUBSCRIPTION_USERSCAN   0x080 ///< for mux subscriptions
-#define SUBSCRIPTION_EPG        0x100 ///< for mux subscriptions
+#define SUBSCRIPTION_TABLES     0x020
+#define SUBSCRIPTION_INITSCAN   0x040 ///< for mux subscriptions
+#define SUBSCRIPTION_IDLESCAN   0x080 ///< for mux subscriptions
+#define SUBSCRIPTION_USERSCAN   0x100 ///< for mux subscriptions
+#define SUBSCRIPTION_EPG        0x200 ///< for mux subscriptions
 
 /* Some internal priorities */
 #define SUBSCRIPTION_PRIO_KEEP        1 ///< Keep input rolling
@@ -115,7 +116,10 @@ typedef struct th_subscription {
   /*
    * MPEG-TS mux chain
    */
+#if ENABLE_MPEGTS
+  service_t *ths_raw_service;
   LIST_ENTRY(th_subscription) ths_mux_link;
+#endif
 
 } th_subscription_t;