struct mpegts_mux
{
idnode_t mm_id;
+ int mm_refcount;
/*
* Identification
*/
void (*mm_delete) (mpegts_mux_t *mm, int delconf);
+ void (*mm_free) (mpegts_mux_t *mm);
htsmsg_t *(*mm_config_save) (mpegts_mux_t *mm, char *filename, size_t fsize);
void (*mm_display_name) (mpegts_mux_t*, char *buf, size_t len);
int (*mm_is_enabled) (mpegts_mux_t *mm);
void mpegts_mux_delete ( mpegts_mux_t *mm, int delconf );
+void mpegts_mux_free ( mpegts_mux_t *mm );
+
+static inline void mpegts_mux_grab ( mpegts_mux_t *mm )
+{
+ int v = atomic_add(&mm->mm_refcount, 1);
+ assert(v > 0);
+}
+
+static inline int mpegts_mux_release ( mpegts_mux_t *mm )
+{
+ int v = atomic_dec(&mm->mm_refcount, 1);
+ assert(v > 0);
+ if (v == 1) {
+ mm->mm_free(mm);
+ return 1;
+ }
+ return 0;
+}
+
void mpegts_mux_save ( mpegts_mux_t *mm, htsmsg_t *c );
void mpegts_mux_tuning_error( const char *mux_uuid, mpegts_mux_instance_t *mmi_match );
return c;
}
+static void
+iptv_mux_free ( mpegts_mux_t *mm )
+{
+ iptv_mux_t *im = (iptv_mux_t *)mm;
+ free(im->mm_iptv_url);
+ free(im->mm_iptv_url_sane);
+ free(im->mm_iptv_url_raw);
+ free(im->mm_iptv_muxname);
+ free(im->mm_iptv_interface);
+ free(im->mm_iptv_svcname);
+ free(im->mm_iptv_env);
+ free(im->mm_iptv_hdr);
+ free(im->mm_iptv_tags);
+ free(im->mm_iptv_icon);
+ free(im->mm_iptv_epgid);
+ mpegts_mux_free(mm);
+}
+
static void
iptv_mux_delete ( mpegts_mux_t *mm, int delconf )
{
idnode_uuid_as_str(&mm->mm_network->mn_id, ubuf1),
idnode_uuid_as_str(&mm->mm_id, ubuf2));
- copy = *im; /* keep pointers */
mpegts_mux_delete(mm, delconf);
- free(copy.mm_iptv_url);
- free(copy.mm_iptv_url_sane);
- free(copy.mm_iptv_url_raw);
- free(copy.mm_iptv_muxname);
- free(copy.mm_iptv_interface);
- free(copy.mm_iptv_svcname);
- free(copy.mm_iptv_env);
- free(copy.mm_iptv_hdr);
- free(copy.mm_iptv_tags);
- free(copy.mm_iptv_icon);
- free(copy.mm_iptv_epgid);
}
static void
im->mm_display_name = iptv_mux_display_name;
im->mm_config_save = iptv_mux_config_save;
im->mm_delete = iptv_mux_delete;
+ im->mm_free = iptv_mux_free;
if (!im->mm_iptv_kill_timeout)
im->mm_iptv_kill_timeout = 5;
if (mi->mi_input_queue_size < 50*1024*1024) {
mi->mi_input_queue_size += len2;
memoryinfo_alloc(&mpegts_input_queue_memoryinfo, sizeof(mpegts_packet_t) + len2);
+ mpegts_mux_grab(mp->mp_mux);
TAILQ_INSERT_TAIL(&mi->mi_input_queue, mp, mp_link);
tvh_cond_signal(&mi->mi_input_cond, 0);
} else {
}
/* Cleanup */
+ if (mp->mp_mux)
+ mpegts_mux_release(mp->mp_mux);
free(mp);
#if ENABLE_TSDEBUG
while ((mp = TAILQ_FIRST(&mi->mi_input_queue))) {
memoryinfo_free(&mpegts_input_queue_memoryinfo, sizeof(mpegts_packet_t) + mp->mp_len);
TAILQ_REMOVE(&mi->mi_input_queue, mp, mp_link);
+ if (mp->mp_mux)
+ mpegts_mux_release(mp->mp_mux);
free(mp);
}
mi->mi_input_queue_size = 0;
/* Flush input Q */
pthread_mutex_lock(&mi->mi_input_lock);
TAILQ_FOREACH(mp, &mi->mi_input_queue, mp_link) {
- if (mp->mp_mux == mm)
+ if (mp->mp_mux == mm) {
+ mpegts_mux_release(mm);
mp->mp_mux = NULL;
+ }
}
pthread_mutex_unlock(&mi->mi_input_lock);
mtimer_disarm(&mm->mm_update_pids_timer);
}
+void
+mpegts_mux_free ( mpegts_mux_t *mm )
+{
+ free(mm->mm_provider_network_name);
+ free(mm->mm_crid_authority);
+ free(mm->mm_charset);
+ free(mm);
+}
+
void
mpegts_mux_delete ( mpegts_mux_t *mm, int delconf )
{
/* Free memory */
idnode_save_check(&mm->mm_id, 1);
idnode_unlink(&mm->mm_id);
- free(mm->mm_provider_network_name);
- free(mm->mm_crid_authority);
- free(mm->mm_charset);
- free(mm);
+ mpegts_mux_release(mm);
}
static htsmsg_t *
return NULL;
}
+ mm->mm_refcount = 1;
+
/* Enabled by default */
mm->mm_enabled = MM_ENABLE;
mm->mm_epg = MM_EPG_ENABLE;
/* Debug/Config */
mm->mm_delete = mpegts_mux_delete;
+ mm->mm_free = mpegts_mux_free;
mm->mm_display_name = mpegts_mux_display_name;
mm->mm_config_save = mpegts_mux_config_save;
mm->mm_is_enabled = mpegts_mux_is_enabled;