From: Jaroslav Kysela Date: Fri, 22 Jan 2016 17:35:24 +0000 (+0100) Subject: mpegts service: fix wrong master/slave linking, fixes #3503 X-Git-Tag: v4.2.1~1133 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a3d672511f65047882b6ec343358ba4e969dfe00;p=thirdparty%2Ftvheadend.git mpegts service: fix wrong master/slave linking, fixes #3503 --- diff --git a/src/idnode.c b/src/idnode.c index a3f513b94..d7f1642aa 100644 --- a/src/idnode.c +++ b/src/idnode.c @@ -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 ) { diff --git a/src/idnode.h b/src/idnode.h index 490b2f0fa..e47dd5918 100644 --- a/src/idnode.h +++ b/src/idnode.h @@ -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__ */ diff --git a/src/input/mpegts.h b/src/input/mpegts.h index f9f61fe82..11344ac89 100644 --- a/src/input/mpegts.h +++ b/src/input/mpegts.h @@ -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; diff --git a/src/input/mpegts/mpegts_service.c b/src/input/mpegts/mpegts_service.c index cd08f2b34..a37ad4ad1 100644 --- a/src/input/mpegts/mpegts_service.c +++ b/src/input/mpegts/mpegts_service.c @@ -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); diff --git a/src/input/mpegts/tsdemux.c b/src/input/mpegts/tsdemux.c index b8e5060b2..56fcdfb31 100644 --- a/src/input/mpegts/tsdemux.c +++ b/src/input/mpegts/tsdemux.c @@ -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];