]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
mpegts service: fix wrong master/slave linking, fixes #3503
authorJaroslav Kysela <perex@perex.cz>
Fri, 22 Jan 2016 17:35:24 +0000 (18:35 +0100)
committerJaroslav Kysela <perex@perex.cz>
Fri, 22 Jan 2016 17:35:24 +0000 (18:35 +0100)
src/idnode.c
src/idnode.h
src/input/mpegts.h
src/input/mpegts/mpegts_service.c
src/input/mpegts/tsdemux.c

index a3f513b949591a26866ff3aa4a8d2d52cc314e8a..d7f1642aae3709473c42cda690b5bf5c94b613df 100644 (file)
@@ -961,6 +961,16 @@ idnode_filter_clear
   }
 }
 
+void
+idnode_set_alloc
+  ( idnode_set_t *is, size_t alloc )
+{
+  if (is->is_alloc < alloc) {
+    is->is_alloc = alloc;
+    is->is_array = realloc(is->is_array, alloc * sizeof(idnode_t*));
+  }
+}
+
 void
 idnode_set_add
   ( idnode_set_t *is, idnode_t *in, idnode_filter_t *filt, const char *lang )
@@ -969,10 +979,8 @@ idnode_set_add
     return;
   
   /* Allocate more space */
-  if (is->is_alloc == is->is_count) {
-    is->is_alloc = MAX(100, is->is_alloc * 2);
-    is->is_array = realloc(is->is_array, is->is_alloc * sizeof(idnode_t*));
-  }
+  if (is->is_alloc == is->is_count)
+    idnode_set_alloc(is, MAX(100, is->is_alloc * 2));
   if (is->is_sorted) {
     size_t i;
     idnode_t **a = is->is_array;
@@ -1017,8 +1025,9 @@ idnode_set_remove
 {
   ssize_t i = idnode_set_find_index(is, in);
   if (i >= 0) {
-    memmove(&is->is_array[i], &is->is_array[i+1],
-            (is->is_count - i - 1) * sizeof(idnode_t *));
+    if (is->is_count > 1)
+      memmove(&is->is_array[i], &is->is_array[i+1],
+              (is->is_count - i - 1) * sizeof(idnode_t *));
     is->is_count--;
     return 1;
   }
@@ -1051,6 +1060,13 @@ idnode_set_as_htsmsg
   return l;
 }
 
+void
+idnode_set_clear ( idnode_set_t *is )
+{
+  free(is->is_array);
+  is->is_count = is->is_alloc = 0;
+}
+
 void
 idnode_set_free ( idnode_set_t *is )
 {
index 490b2f0fab06d3316ed7d5cf7240b81429f48556..e47dd591800d6f6d9aba64d6d192c6186327026d 100644 (file)
@@ -255,6 +255,7 @@ int  idnode_filter
 static inline idnode_set_t * idnode_set_create(int sorted)
   { idnode_set_t *is = calloc(1, sizeof(idnode_set_t));
     is->is_sorted = sorted; return is; }
+void idnode_set_alloc ( idnode_set_t *is, size_t alloc );
 void idnode_set_add
   ( idnode_set_t *is, idnode_t *in, idnode_filter_t *filt, const char *lang );
 int idnode_set_remove ( idnode_set_t *is, idnode_t *in );
@@ -264,6 +265,7 @@ static inline int idnode_set_exists ( idnode_set_t *is, idnode_t *in )
 void idnode_set_sort ( idnode_set_t *is, idnode_sort_t *s );
 void idnode_set_sort_by_title ( idnode_set_t *is, const char *lang );
 htsmsg_t *idnode_set_as_htsmsg ( idnode_set_t *is );
+void idnode_set_clear ( idnode_set_t *is );
 void idnode_set_free ( idnode_set_t *is );
 
 #endif /* __TVH_IDNODE_H__ */
index f9f61fe82ad331aebf25fca14e24546e92e99d5e..11344ac89c670e7799e3397b6305578644361c0a 100644 (file)
@@ -535,8 +535,7 @@ struct mpegts_service
   int      s_dvb_subscription_weight;
 
   mpegts_apids_t             *s_pids;
-  LIST_HEAD(, mpegts_service) s_masters;
-  LIST_ENTRY(mpegts_service)  s_masters_link;
+  idnode_set_t                s_masters;
   LIST_HEAD(, mpegts_service) s_slaves;
   LIST_ENTRY(mpegts_service)  s_slaves_link;
   mpegts_apids_t             *s_slaves_pids;
index cd08f2b34b91f373deedf26b5c9df02c5bb61fd9..a37ad4ad1181c6a3c6d1d147288a60571b386254 100644 (file)
@@ -670,7 +670,7 @@ mpegts_service_unref ( service_t *t )
 void
 mpegts_service_delete ( service_t *t, int delconf )
 {
-  mpegts_service_t *ms = (mpegts_service_t*)t;
+  mpegts_service_t *ms = (mpegts_service_t*)t, *mms;
   mpegts_mux_t     *mm = ms->s_dvb_mux;
   char ubuf0[UUID_HEX_SIZE];
   char ubuf1[UUID_HEX_SIZE];
@@ -689,8 +689,11 @@ mpegts_service_delete ( service_t *t, int delconf )
   sbuf_free(&ms->s_tsbuf);
 
   /* Remove master/slave linking */
-  LIST_SAFE_REMOVE(ms, s_masters_link);
-  LIST_SAFE_REMOVE(ms, s_slaves_link);
+  while (ms->s_masters.is_count > 0) {
+    mms = (mpegts_service_t *)ms->s_masters.is_array[0];
+    mms->s_unlink(mms, ms);
+  }
+  idnode_set_clear(&ms->s_masters);
 
   /* Remove PID lists */
   mpegts_pid_destroy(&ms->s_pids);
@@ -934,6 +937,7 @@ mpegts_service_update_slave_pids ( mpegts_service_t *s, int del )
   mpegts_service_t *s2;
   mpegts_apids_t *pids;
   elementary_stream_t *st;
+  int i;
 
   lock_assert(&s->s_stream_mutex);
 
@@ -948,7 +952,8 @@ mpegts_service_update_slave_pids ( mpegts_service_t *s, int del )
         st->es_pid >= 0 && st->es_pid < 8192)
       mpegts_pid_add(pids, st->es_pid, mpegts_mps_weight(st));
 
-  LIST_FOREACH(s2, &s->s_masters, s_masters_link) {
+  for (i = 0; i < s->s_masters.is_count; i++) {
+    s2 = (mpegts_service_t *)s->s_masters.is_array[i];
     pthread_mutex_lock(&s2->s_stream_mutex);
     if (!del)
       mpegts_pid_add_group(s2->s_slaves_pids, pids);
@@ -965,9 +970,10 @@ mpegts_service_link ( mpegts_service_t *master, mpegts_service_t *slave )
 {
   pthread_mutex_lock(&slave->s_stream_mutex);
   pthread_mutex_lock(&master->s_stream_mutex);
-  assert(LIST_SAFE_ENTRY(master, s_masters_link));
+  assert(!idnode_set_exists(&slave->s_masters, &master->s_id));
   assert(LIST_SAFE_ENTRY(slave, s_slaves_link));
-  LIST_INSERT_HEAD(&slave->s_masters, master, s_masters_link);
+  idnode_set_alloc(&slave->s_masters, 16);
+  idnode_set_add(&slave->s_masters, &master->s_id, NULL, NULL);
   LIST_INSERT_HEAD(&master->s_slaves, slave, s_slaves_link);
   pthread_mutex_unlock(&master->s_stream_mutex);
   mpegts_service_update_slave_pids(slave, 0);
@@ -981,7 +987,9 @@ mpegts_service_unlink ( mpegts_service_t *master, mpegts_service_t *slave )
   pthread_mutex_lock(&slave->s_stream_mutex);
   mpegts_service_update_slave_pids(slave, 1);
   pthread_mutex_lock(&master->s_stream_mutex);
-  LIST_SAFE_REMOVE(master, s_masters_link);
+  idnode_set_remove(&slave->s_masters, &master->s_id);
+  if (slave->s_masters.is_count == 0)
+    idnode_set_clear(&slave->s_masters);
   LIST_SAFE_REMOVE(slave, s_slaves_link);
   pthread_mutex_unlock(&master->s_stream_mutex);
   pthread_mutex_unlock(&slave->s_stream_mutex);
index b8e5060b264304d10517db1c971c3d1b4210b601..56fcdfb31d3c52d578476d13a4d76c23a9bf8544 100644 (file)
@@ -106,7 +106,8 @@ skip_cc:
   if(streaming_pad_probe_type(&t->s_streaming_pad, SMT_MPEGTS))
     ts_remux(t, tsb, len, errors);
 
-  LIST_FOREACH(m, &t->s_masters, s_masters_link) {
+  for(off = 0; off < t->s_masters.is_count; off++) {
+    m = (mpegts_service_t *)t->s_masters.is_array[off];
     pthread_mutex_lock(&m->s_stream_mutex);
     if(streaming_pad_probe_type(&m->s_streaming_pad, SMT_MPEGTS)) {
       pid = (tsb[1] & 0x1f) << 8 | tsb[2];
@@ -128,7 +129,7 @@ ts_recv_skipped0
   (mpegts_service_t *t, elementary_stream_t *st, const uint8_t *tsb, int len)
 {
   mpegts_service_t *m;
-  int len2, cc, pid;
+  int len2, off, cc, pid;
   const uint8_t *tsb2;
 
   if (!st)
@@ -162,7 +163,8 @@ skip_cc:
   if(streaming_pad_probe_type(&t->s_streaming_pad, SMT_MPEGTS))
     ts_skip(t, tsb, len);
 
-  LIST_FOREACH(m, &t->s_masters, s_masters_link) {
+  for(off = 0; off < t->s_masters.is_count; off++) {
+    m = (mpegts_service_t *)t->s_masters.is_array[off];
     pthread_mutex_lock(&m->s_stream_mutex);
     if(streaming_pad_probe_type(&m->s_streaming_pad, SMT_MPEGTS)) {
       pid = (tsb[1] & 0x1f) << 8 | tsb[2];