From f1eb285c8f83f95bcc736d576a192a27a39b4a6e Mon Sep 17 00:00:00 2001 From: Adam Sutton Date: Sat, 1 Jun 2013 20:51:10 +0100 Subject: [PATCH] mpegts: starting to tidy up input class --- src/input/mpegts.h | 24 +- src/input/mpegts/linuxdvb/linuxdvb_frontend.c | 206 ++++++++++-------- src/input/mpegts/mpegts_input.c | 153 ++++++++----- src/input/mpegts/mpegts_service.c | 6 + 4 files changed, 229 insertions(+), 160 deletions(-) diff --git a/src/input/mpegts.h b/src/input/mpegts.h index 0ebdc0c7..5d78e4e0 100644 --- a/src/input/mpegts.h +++ b/src/input/mpegts.h @@ -381,15 +381,14 @@ struct mpegts_input /* * Functions */ - + int (*mi_is_enabled) (mpegts_input_t*); + void (*mi_display_name) (mpegts_input_t*, char *buf, size_t len); + int (*mi_is_free) (mpegts_input_t*); + int (*mi_current_weight) (mpegts_input_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*); void (*mi_close_service) (mpegts_input_t*,mpegts_service_t*); - int (*mi_is_free) (mpegts_input_t*); - int (*mi_current_weight) (mpegts_input_t*); - int (*mi_is_enabled) (mpegts_input_t*); - void (*mi_display_name) (mpegts_input_t*, char *buf, size_t len); }; #endif /* __TVH_MPEGTS_H__ */ @@ -399,16 +398,15 @@ struct mpegts_input * ***************************************************************************/ mpegts_input_t *mpegts_input_create0 - ( mpegts_input_t *mi, const idclass_t *idc, const char *uuid ); + ( mpegts_input_t *mi, const idclass_t *idc, const char *uuid, htsmsg_t *c ); -#define mpegts_input_create(t, u)\ - (struct t*)mpegts_input_create0(calloc(1, sizeof(struct t)), &t##_class, u) +#define mpegts_input_create(t, u, c)\ + (struct t*)mpegts_input_create0(calloc(1, sizeof(struct t)), &t##_class, u, c) -#define mpegts_input_create1(u)\ +#define mpegts_input_create1(u, c)\ mpegts_input_create0(calloc(1, sizeof(mpegts_input_t)),\ - &mpegts_input_class, u) + &mpegts_input_class, u, c) - mpegts_network_t *mpegts_network_create0 ( mpegts_network_t *mn, const idclass_t *idc, const char *uuid, const char *name, htsmsg_t *conf ); @@ -456,7 +454,7 @@ int mpegts_mux_set_crid_authority ( mpegts_mux_t *mm, const char *defauth ); size_t mpegts_input_recv_packets (mpegts_input_t *mi, mpegts_mux_instance_t *mmi, uint8_t *tsb, size_t len, - int64_t *pcr, uint16_t *pcr_pid); + int64_t *pcr, uint16_t *pcr_pid, const char *name); void *mpegts_input_table_thread ( void *aux ); @@ -464,6 +462,8 @@ int mpegts_input_is_free ( mpegts_input_t *mi ); int mpegts_input_current_weight ( mpegts_input_t *mi ); +void mpegts_input_save ( mpegts_input_t *mi, htsmsg_t *c ); + void mpegts_table_dispatch (const uint8_t *sec, size_t r, void *mt); void mpegts_table_release diff --git a/src/input/mpegts/linuxdvb/linuxdvb_frontend.c b/src/input/mpegts/linuxdvb/linuxdvb_frontend.c index 06d43a69..ae2dce7a 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_frontend.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_frontend.c @@ -29,8 +29,16 @@ #include #include +static int +linuxdvb_frontend_tune + ( linuxdvb_frontend_t *lfe, linuxdvb_mux_t *lm ); +static void +linuxdvb_frontend_monitor ( void *aux ); +static void * +linuxdvb_frontend_input_thread ( void *aux ); + /* ************************************************************************** - * Class definitions + * Class definition * *************************************************************************/ extern const idclass_t linuxdvb_hardware_class; @@ -67,6 +75,8 @@ const idclass_t linuxdvb_frontend_class = PT_STR, linuxdvb_frontend_t, lfe_dvr_path, 1) }, { PROPDEF2("dmx_path", "Demux Path", PT_STR, linuxdvb_frontend_t, lfe_dmx_path, 1) }, + { PROPDEF2("number", "FE Number", + PT_INT, linuxdvb_frontend_t, lfe_number, 1) }, {} } }; @@ -112,24 +122,9 @@ const idclass_t linuxdvb_frontend_atsc_class = }; /* ************************************************************************** - * Frontend + * Class methods * *************************************************************************/ -void -linuxdvb_frontend_save ( linuxdvb_frontend_t *lfe, htsmsg_t *m ) -{ - htsmsg_add_u32(m, "number", lfe->lfe_number); - htsmsg_add_str(m, "type", dvb_type2str(lfe->lfe_info.type)); - if (lfe->mi_network) - htsmsg_add_str(m, "network", idnode_uuid_as_str(&lfe->mi_network->mn_id)); - if (lfe->lfe_fe_path) - htsmsg_add_str(m, "fe_path", lfe->lfe_fe_path); - if (lfe->lfe_dmx_path) - htsmsg_add_str(m, "dmx_path", lfe->lfe_dmx_path); - if (lfe->lfe_dvr_path) - htsmsg_add_str(m, "dvr_path", lfe->lfe_dvr_path); -} - static int linuxdvb_frontend_is_enabled ( mpegts_input_t *mi ) { @@ -185,12 +180,81 @@ linuxdvb_frontend_stop_mux } } +static int +linuxdvb_frontend_start_mux + ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi ) +{ + int r; + linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi; + mpegts_mux_instance_t *cur = LIST_FIRST(&mi->mi_mux_active); + tvhtrace("mpegts", "linuxdvb_frontend_start_mux(%p, %p)", mi, mmi); + + // Not sure if this is right place? + /* Currently active */ + if (cur != NULL) { + + /* Already tuned */ + if (mmi == cur) + return 0; + + /* Stop current */ + cur->mmi_mux->mm_stop(cur->mmi_mux); + } + assert(LIST_FIRST(&mi->mi_mux_active) == NULL); + + /* Open FE */ + if (lfe->lfe_fe_fd <= 0) { + lfe->lfe_fe_fd = tvh_open(lfe->lfe_fe_path, O_RDWR | O_NONBLOCK, 0); + if (lfe->lfe_fe_fd <= 0) { + return SM_CODE_TUNING_FAILED; + } + } + + /* Tune */ + r = linuxdvb_frontend_tune(lfe, (linuxdvb_mux_t*)mmi->mmi_mux); + + /* Failed */ + if (r != 0) { + tvhlog(LOG_ERR, "linuxdvb", "'%s' failed to tune '%s' error %s", + lfe->lfe_fe_path, "TODO", strerror(errno)); + if (errno == EINVAL) + mmi->mmi_tune_failed = 1; + return SM_CODE_TUNING_FAILED; + } + + /* Start monitor */ + time(&lfe->lfe_monitor); + lfe->lfe_monitor += 4; + gtimer_arm_ms(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, 50); + + /* Send alert */ + // TODO: should this be moved elsewhere? + return r; +} + +static void +linuxdvb_frontend_open_service + ( mpegts_input_t *mi, mpegts_service_t *ms ) +{ +} + +static void +linuxdvb_frontend_close_service + ( mpegts_input_t *mi, mpegts_service_t *ms ) +{ +} + +/* ************************************************************************** + * Data processing + * *************************************************************************/ + static void * linuxdvb_frontend_input_thread ( void *aux ) { linuxdvb_frontend_t *lfe = aux; mpegts_mux_instance_t *mmi; int dmx = -1, dvr = -1; + char buf[256]; uint8_t tsb[18800]; int pos = 0, nfds, efd; ssize_t c; @@ -199,6 +263,7 @@ linuxdvb_frontend_input_thread ( void *aux ) /* Get MMI */ pthread_mutex_lock(&global_lock); + lfe->mi_display_name((mpegts_input_t*)lfe, buf, sizeof(buf)); mmi = LIST_FIRST(&lfe->mi_mux_active); pthread_mutex_unlock(&global_lock); if (mmi == NULL) return NULL; @@ -206,7 +271,7 @@ linuxdvb_frontend_input_thread ( void *aux ) /* Open DMX */ dmx = tvh_open(lfe->lfe_dmx_path, O_RDWR, 0); if (dmx < 0) { - tvhlog(LOG_ERR, "linuxdvb", "failed to open %s", lfe->lfe_dmx_path); + tvherror("linuxdvb", "%s - failed to open %s", buf, lfe->lfe_dmx_path); return NULL; } memset(&dmx_param, 0, sizeof(dmx_param)); @@ -227,7 +292,7 @@ linuxdvb_frontend_input_thread ( void *aux ) dvr = tvh_open(lfe->lfe_dvr_path, O_RDONLY | O_NONBLOCK, 0); if (dvr < 0) { close(dmx); - tvhlog(LOG_ERR, "linuxdvb", "failed to open %s", lfe->lfe_dvr_path); + tvherror("linuxdvb", "%s - failed to open %s", buf, lfe->lfe_dvr_path); return NULL; } @@ -253,20 +318,19 @@ linuxdvb_frontend_input_thread ( void *aux ) if ((errno == EAGAIN) || (errno == EINTR)) continue; if (errno == EOVERFLOW) { - tvhlog(LOG_WARNING, "linuxdvb", "read() EOVERFLOW"); + tvhlog(LOG_WARNING, "linuxdvb", "%s - read() EOVERFLOW", buf); continue; } - tvhlog(LOG_ERR, "linuxdvb", "read() error %d (%s)", - errno, strerror(errno)); + tvhlog(LOG_ERR, "linuxdvb", "%s - read() error %d (%s)", + buf, errno, strerror(errno)); break; } /* Process */ pos = mpegts_input_recv_packets((mpegts_input_t*)lfe, mmi, tsb, c, - NULL, NULL); + NULL, NULL, buf); } -//exit: close(dmx); close(dvr); return NULL; @@ -372,75 +436,14 @@ linuxdvb_frontend_tune #endif -static int -linuxdvb_frontend_start_mux - ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi ) -{ - int r; - linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi; - mpegts_mux_instance_t *cur = LIST_FIRST(&mi->mi_mux_active); - tvhtrace("mpegts", "linuxdvb_frontend_start_mux(%p, %p)", mi, mmi); - - // Not sure if this is right place? - /* Currently active */ - if (cur != NULL) { - - /* Already tuned */ - if (mmi == cur) - return 0; - - /* Stop current */ - cur->mmi_mux->mm_stop(cur->mmi_mux); - } - assert(LIST_FIRST(&mi->mi_mux_active) == NULL); - - /* Open FE */ - if (lfe->lfe_fe_fd <= 0) { - lfe->lfe_fe_fd = tvh_open(lfe->lfe_fe_path, O_RDWR | O_NONBLOCK, 0); - if (lfe->lfe_fe_fd <= 0) { - return SM_CODE_TUNING_FAILED; - } - } - - /* Tune */ - r = linuxdvb_frontend_tune(lfe, (linuxdvb_mux_t*)mmi->mmi_mux); - - /* Failed */ - if (r != 0) { - tvhlog(LOG_ERR, "linuxdvb", "'%s' failed to tune '%s' error %s", - lfe->lfe_fe_path, "TODO", strerror(errno)); - if (errno == EINVAL) - mmi->mmi_tune_failed = 1; - return SM_CODE_TUNING_FAILED; - } - - /* Start monitor */ - time(&lfe->lfe_monitor); - lfe->lfe_monitor += 4; - gtimer_arm_ms(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, 50); - - /* Send alert */ - // TODO: should this be moved elsewhere? - return r; -} - -static void -linuxdvb_frontend_open_service - ( mpegts_input_t *mi, mpegts_service_t *ms ) -{ -} - -static void -linuxdvb_frontend_close_service - ( mpegts_input_t *mi, mpegts_service_t *ms ) -{ -} - +/* ************************************************************************** + * Creation/Config + * *************************************************************************/ + linuxdvb_frontend_t * linuxdvb_frontend_create0 ( linuxdvb_adapter_t *la, const char *uuid, htsmsg_t *conf, fe_type_t type ) { - uint32_t u32; const char *str; const idclass_t *idc; pthread_t tid; @@ -462,18 +465,19 @@ linuxdvb_frontend_create0 else if (type == FE_ATSC) idc = &linuxdvb_frontend_atsc_class; else { - tvhlog(LOG_ERR, "linuxdvb", "unknown FE type %d", type); + tvherror("linuxdvb", "unknown FE type %d", type); return NULL; } linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*) - mpegts_input_create0(calloc(1, sizeof(linuxdvb_frontend_t)), idc, uuid); + mpegts_input_create0(calloc(1, sizeof(linuxdvb_frontend_t)), + idc, uuid, conf); lfe->lfe_info.type = type; /* Input callbacks */ - lfe->mi_display_name = linuxdvb_frontend_display_name; lfe->mi_is_enabled = linuxdvb_frontend_is_enabled; + lfe->mi_display_name = linuxdvb_frontend_display_name; lfe->mi_start_mux = linuxdvb_frontend_start_mux; lfe->mi_stop_mux = linuxdvb_frontend_stop_mux; lfe->mi_open_service = linuxdvb_frontend_open_service; @@ -490,10 +494,7 @@ linuxdvb_frontend_create0 if (!conf) return lfe; - if (!htsmsg_get_u32(conf, "enabled", &u32) && u32) - lfe->mi_enabled = u32; - if (!htsmsg_get_u32(conf, "number", &u32)) - lfe->lfe_number = u32; + /* TODO: this should be done differently */ if ((str = htsmsg_get_str(conf, "network"))) { linuxdvb_network_t *ln = linuxdvb_network_find_by_uuid(str); if (ln) { @@ -553,3 +554,16 @@ linuxdvb_frontend_added return lfe; } + +void +linuxdvb_frontend_save ( linuxdvb_frontend_t *lfe, htsmsg_t *m ) +{ + mpegts_input_save((mpegts_input_t*)lfe, m); + htsmsg_add_str(m, "type", dvb_type2str(lfe->lfe_info.type)); +} + +/****************************************************************************** + * Editor Configuration + * + * vim:sts=2:ts=2:sw=2:et + *****************************************************************************/ diff --git a/src/input/mpegts/mpegts_input.c b/src/input/mpegts/mpegts_input.c index 91013d11..b34dfba2 100644 --- a/src/input/mpegts/mpegts_input.c +++ b/src/input/mpegts/mpegts_input.c @@ -26,20 +26,86 @@ #include #include +/* ************************************************************************** + * Class definition + * *************************************************************************/ + const idclass_t mpegts_input_class = { .ic_class = "mpegts_input", .ic_caption = "MPEGTS Input", .ic_properties = (const property_t[]){ + { PROPDEF1("enabled", "Enabled", + PT_BOOL, mpegts_input_t, mi_enabled) }, + {} } }; +/* ************************************************************************** + * Class methods + * *************************************************************************/ + +static int +mpegts_input_is_enabled ( mpegts_input_t *mi ) +{ + return mi->mi_enabled; +} + static void mpegts_input_display_name ( mpegts_input_t *mi, char *buf, size_t len ) { *buf = 0; } +int +mpegts_input_is_free ( mpegts_input_t *mi ) +{ + char buf[256]; + mpegts_mux_instance_t *mmi = LIST_FIRST(&mi->mi_mux_active); + mi->mi_display_name(mi, buf, sizeof(buf)); + tvhtrace("mpegts", "%s - is free? %d", buf, mmi == NULL); + return mmi ? 0 : 1; +} + +int +mpegts_input_current_weight ( mpegts_input_t *mi ) +{ + const mpegts_mux_instance_t *mmi; + const service_t *s; + const th_subscription_t *ths; + int w = 0; + + // TODO: we probably need a way for mux level subs + + /* 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; + } + } + + /* Check subscriptions */ + pthread_mutex_lock(&mi->mi_delivery_mutex); + LIST_FOREACH(s, &mi->mi_transports, s_active_link) { + LIST_FOREACH(ths, &s->s_subscriptions, ths_service_link) + w = MAX(w, ths->ths_weight); + } + pthread_mutex_unlock(&mi->mi_delivery_mutex); + return w; +} + +static int +mpegts_input_start_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi ) +{ + return SM_CODE_TUNING_FAILED; +} + +static void +mpegts_input_stop_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi ) +{ +} + static void mpegts_input_open_service ( mpegts_input_t *mi, mpegts_service_t *s ) { @@ -50,18 +116,26 @@ mpegts_input_close_service ( mpegts_input_t *mi, mpegts_service_t *s ) { } +/* ************************************************************************** + * Data processing + * *************************************************************************/ + size_t mpegts_input_recv_packets ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi, - uint8_t *tsb, size_t l, int64_t *pcr, uint16_t *pcr_pid ) + uint8_t *tsb, size_t l, int64_t *pcr, uint16_t *pcr_pid, + const char *name ) { - int len = l; // TODO: fix ts_resync() to remove this + int len = l; int i = 0, table_wakeup = 0; mpegts_mux_t *mm = mmi->mmi_mux; assert(mmi->mmi_input == mi); assert(mm != NULL); - tvhtrace("tsdemux", "recv_packets tsb=%p, len=%d, pcr=%p, pcr_pid=%p", - tsb, (int)len, pcr, pcr_pid); + assert(name != NULL); + + // TODO: get the input name + tvhtrace("tsdemux", "%s - recv_packets tsb=%p, len=%d, pcr=%p, pcr_pid=%p", + name, tsb, (int)len, pcr, pcr_pid); /* Not enough data */ if (len < 188) return 0; @@ -86,7 +160,7 @@ mpegts_input_recv_packets /* Sync */ if ( tsb[i] == 0x47 ) { int pid = ((tsb[i+1] & 0x1f) << 8) | tsb[i+2]; - tvhtrace("tsdemux", "recv_packet for pid %04X (%d)", pid, pid); + tvhtrace("tsdemux", "%s - recv_packet for pid %04X (%d)", name, pid, pid); /* SI data */ if (mm->mm_table_filter[pid]) { @@ -114,10 +188,9 @@ mpegts_input_recv_packets /* Re-sync */ } else { - // TODO: set flag (to avoid spam) - tvhdebug("tsdemux", "%s ts sync lost", "TODO"); + tvhdebug("tsdemux", "%s - ts sync lost", name); if (ts_resync(tsb, &len, &i)) break; - tvhdebug("tsdemux", "%s ts sync found", "TODO"); + tvhdebug("tsdemux", "%s - ts sync found", name); } } @@ -179,7 +252,6 @@ mpegts_input_table_thread ( void *aux ) /* Process */ pthread_mutex_lock(&global_lock); - // TODO: should we check the mux is active mpegts_input_table_dispatch(mtf->mtf_mux, mtf); pthread_mutex_unlock(&global_lock); free(mtf); @@ -187,59 +259,28 @@ mpegts_input_table_thread ( void *aux ) return NULL; } -int -mpegts_input_is_free ( mpegts_input_t *mi ) -{ - mpegts_mux_instance_t *mmi = LIST_FIRST(&mi->mi_mux_active); - tvhtrace("mpegts", "input_is_free(%p) mmi = %p", mi, mmi); - return mmi ? 0 : 1; -} - -int -mpegts_input_current_weight ( mpegts_input_t *mi ) -{ - const mpegts_mux_instance_t *mmi; - const service_t *s; - const th_subscription_t *ths; - int w = 0; - - LIST_FOREACH(mmi, &mi->mi_mux_active, mmi_active_link) { - if (mmi->mmi_mux->mm_initial_scan_status == MM_SCAN_CURRENT) { - w = 1; - break; - } - } - - pthread_mutex_lock(&mi->mi_delivery_mutex); - LIST_FOREACH(s, &mi->mi_transports, s_active_link) { - LIST_FOREACH(ths, &s->s_subscriptions, ths_service_link) - w = MAX(w, ths->ths_weight); - } - pthread_mutex_unlock(&mi->mi_delivery_mutex); - return w; -} - -static int -mpegts_input_is_enabled ( mpegts_input_t *mi ) -{ - return mi->mi_enabled; -} +/* ************************************************************************** + * Creation/Config + * *************************************************************************/ mpegts_input_t* mpegts_input_create0 - ( mpegts_input_t *mi, const idclass_t *class, const char *uuid ) + ( mpegts_input_t *mi, const idclass_t *class, const char *uuid, + htsmsg_t *c ) { idnode_insert(&mi->mi_id, uuid, class); + if (c) + idnode_load(&mi->mi_id, c); /* Defaults */ - mi->mi_start_mux = NULL; - mi->mi_stop_mux = NULL; - mi->mi_open_service = mpegts_input_open_service; - mi->mi_close_service = mpegts_input_close_service; mi->mi_is_enabled = mpegts_input_is_enabled; + mi->mi_display_name = mpegts_input_display_name; mi->mi_is_free = mpegts_input_is_free; mi->mi_current_weight = mpegts_input_current_weight; - mi->mi_display_name = mpegts_input_display_name; + mi->mi_start_mux = mpegts_input_start_mux; + mi->mi_stop_mux = mpegts_input_stop_mux; + mi->mi_open_service = mpegts_input_open_service; + mi->mi_close_service = mpegts_input_close_service; /* Init mutex */ pthread_mutex_init(&mi->mi_delivery_mutex, NULL); @@ -254,6 +295,14 @@ mpegts_input_create0 return mi; } +void +mpegts_input_save ( mpegts_input_t *mi, htsmsg_t *m ) +{ + idnode_save(&mi->mi_id, m); + if (mi->mi_network) + htsmsg_add_str(m, "network", idnode_uuid_as_str(&mi->mi_network->mn_id)); +} + /****************************************************************************** * Editor Configuration * diff --git a/src/input/mpegts/mpegts_service.c b/src/input/mpegts/mpegts_service.c index fa494a2a..0517717d 100644 --- a/src/input/mpegts/mpegts_service.c +++ b/src/input/mpegts/mpegts_service.c @@ -300,3 +300,9 @@ mpegts_service_save ( mpegts_service_t *s, htsmsg_t *c ) { service_save((service_t*)s, c); } + +/****************************************************************************** + * Editor Configuration + * + * vim:sts=2:ts=2:sw=2:et + *****************************************************************************/