stream status: add possibility to clear statistics, introduce tvh_input_instance_t

This commit is contained in:
Jaroslav Kysela 2015-04-17 11:11:00 +02:00
parent abb14095cb
commit bda5d8ce25
11 changed files with 232 additions and 117 deletions

View file

@ -37,8 +37,10 @@ api_status_inputs
tvh_input_stream_t *st;
tvh_input_stream_list_t stl = { 0 };
pthread_mutex_lock(&global_lock);
TVH_INPUT_FOREACH(ti)
ti->ti_get_streams(ti, &stl);
pthread_mutex_unlock(&global_lock);
l = htsmsg_create_list();
while ((st = LIST_FIRST(&stl))) {
@ -67,11 +69,13 @@ api_status_subscriptions
l = htsmsg_create_list();
c = 0;
pthread_mutex_lock(&global_lock);
LIST_FOREACH(ths, &subscriptions, ths_global_link) {
e = subscription_create_msg(ths);
htsmsg_add_msg(l, NULL, e);
c++;
}
pthread_mutex_unlock(&global_lock);
*resp = htsmsg_create_map();
htsmsg_add_msg(*resp, "entries", l);
@ -120,12 +124,48 @@ api_connections_cancel
return 0;
}
static void
input_clear_stats(const char *uuid)
{
tvh_input_instance_t *tii;
pthread_mutex_lock(&global_lock);
if ((tii = tvh_input_instance_find_by_uuid(uuid)) != NULL)
if (tii->tii_clear_stats)
tii->tii_clear_stats(tii);
pthread_mutex_unlock(&global_lock);
}
static int
api_status_input_clear_stats
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
{
htsmsg_field_t *f;
htsmsg_t *ids;
const char *uuid;
if (!(f = htsmsg_field_find(args, "uuid")))
return EINVAL;
if (!(ids = htsmsg_field_get_list(f))) {
if ((uuid = htsmsg_field_get_str(f)) == NULL)
return EINVAL;
input_clear_stats(uuid);
} else {
HTSMSG_FOREACH(f, ids) {
if ((uuid = htsmsg_field_get_str(f)) == NULL) continue;
input_clear_stats(uuid);
}
}
return 0;
}
void api_status_init ( void )
{
static api_hook_t ah[] = {
{ "status/connections", ACCESS_ADMIN, api_status_connections, NULL },
{ "status/subscriptions", ACCESS_ADMIN, api_status_subscriptions, NULL },
{ "status/inputs", ACCESS_ADMIN, api_status_inputs, NULL },
{ "status/inputclrstats", ACCESS_ADMIN, api_status_input_clear_stats, NULL },
{ "connections/cancel", ACCESS_ADMIN, api_connections_cancel, NULL },
{ NULL },
};

View file

@ -18,10 +18,18 @@
#include "input.h"
#include "notify.h"
#include "access.h"
tvh_input_list_t tvh_inputs;
tvh_hardware_list_t tvh_hardware;
const idclass_t tvh_input_instance_class =
{
.ic_class = "tvh_input_instance",
.ic_caption = "Input Instance",
.ic_perm_def = ACCESS_ADMIN
};
/*
* Create entry
*/
@ -59,6 +67,23 @@ tvh_hardware_delete ( tvh_hardware_t *th )
idnode_unlink(&th->th_id);
}
/*
*
*/
void
tvh_input_instance_clear_stats ( tvh_input_instance_t *tii )
{
tvh_input_stream_stats_t *s = &tii->tii_stats;
atomic_exchange(&s->ber, 0);
atomic_exchange(&s->unc, 0);
atomic_exchange(&s->cc, 0);
atomic_exchange(&s->te, 0);
atomic_exchange(&s->ec_block, 0);
atomic_exchange(&s->tc_block, 0);
}
/*
* Input status handling
*/

View file

@ -27,6 +27,7 @@
*/
typedef struct tvh_hardware tvh_hardware_t;
typedef struct tvh_input tvh_input_t;
typedef struct tvh_input_instance tvh_input_instance_t;
typedef struct tvh_input_stream tvh_input_stream_t;
typedef struct tvh_input_stream_stats tvh_input_stream_stats_t;
@ -87,6 +88,20 @@ struct tvh_input {
void (*ti_get_streams) (struct tvh_input *, tvh_input_stream_list_t*);
};
/*
* Generic input instance super-class
*/
struct tvh_input_instance {
idnode_t tii_id;
LIST_ENTRY(tvh_input_instance) tii_input_link;
tvh_input_stream_stats_t tii_stats;
void (*tii_delete) (tvh_input_instance_t *tii);
void (*tii_clear_stats) (tvh_input_instance_t *tii);
};
/*
* Generic hardware super-class
*/
@ -103,6 +118,7 @@ void tvh_hardware_delete ( tvh_hardware_t *th );
* Class and Global list defs
*/
extern const idclass_t tvh_input_class;
extern const idclass_t tvh_input_instance_class;
tvh_input_list_t tvh_inputs;
tvh_hardware_list_t tvh_hardware;
@ -120,6 +136,12 @@ htsmsg_t * tvh_input_stream_create_msg ( tvh_input_stream_t *st );
void tvh_input_stream_destroy ( tvh_input_stream_t *st );
static inline tvh_input_instance_t *
tvh_input_instance_find_by_uuid(const char *uuid)
{ return (tvh_input_instance_t*)idnode_find(uuid, &tvh_input_instance_class, NULL); }
void tvh_input_instance_clear_stats ( tvh_input_instance_t *tii );
/*
* Input subsystem includes
*/

View file

@ -548,10 +548,9 @@ struct mpegts_service
/* Physical mux instance */
struct mpegts_mux_instance
{
idnode_t mmi_id;
tvh_input_instance_t;
LIST_ENTRY(mpegts_mux_instance) mmi_mux_link;
LIST_ENTRY(mpegts_mux_instance) mmi_input_link;
LIST_ENTRY(mpegts_mux_instance) mmi_active_link;
streaming_pad_t mmi_streaming_pad;
@ -559,11 +558,7 @@ struct mpegts_mux_instance
mpegts_mux_t *mmi_mux;
mpegts_input_t *mmi_input;
tvh_input_stream_stats_t mmi_stats;
int mmi_tune_failed;
void (*mmi_delete) (mpegts_mux_instance_t *mmi);
};
struct mpegts_mux_sub
@ -598,7 +593,7 @@ struct mpegts_input
mpegts_network_link_list_t mi_networks;
LIST_HEAD(,mpegts_mux_instance) mi_mux_instances;
LIST_HEAD(,tvh_input_instance) mi_mux_instances;
/*
@ -795,7 +790,7 @@ mpegts_service_t *mpegts_mux_find_service(mpegts_mux_t *ms, uint16_t sid);
&type##_class, uuid,\
mi, mm);
void mpegts_mux_instance_delete ( mpegts_mux_instance_t *mmi );
void mpegts_mux_instance_delete ( tvh_input_instance_t *tii );
int mpegts_mux_instance_start
( mpegts_mux_instance_t **mmiptr );

View file

@ -662,18 +662,18 @@ linuxdvb_frontend_monitor ( void *aux )
gotprop = 0;
if(ioctl_check(lfe, 1) && fe_properties[0].u.st.len > 0) {
if(fe_properties[0].u.st.stat[0].scale == FE_SCALE_RELATIVE) {
mmi->mmi_stats.signal_scale = SIGNAL_STATUS_SCALE_RELATIVE;
mmi->mmi_stats.signal = fe_properties[0].u.st.stat[0].uvalue;
mmi->tii_stats.signal_scale = SIGNAL_STATUS_SCALE_RELATIVE;
mmi->tii_stats.signal = fe_properties[0].u.st.stat[0].uvalue;
gotprop = 1;
}
else if(fe_properties[0].u.st.stat[0].scale == FE_SCALE_DECIBEL) {
mmi->mmi_stats.signal_scale = SIGNAL_STATUS_SCALE_DECIBEL;
mmi->mmi_stats.signal = fe_properties[0].u.st.stat[0].svalue;
mmi->tii_stats.signal_scale = SIGNAL_STATUS_SCALE_DECIBEL;
mmi->tii_stats.signal = fe_properties[0].u.st.stat[0].svalue;
gotprop = 1;
}
else {
ioctl_bad(lfe, 1);
mmi->mmi_stats.signal_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
mmi->tii_stats.signal_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
if (logit)
tvhlog(LOG_WARNING, "linuxdvb", "Unhandled signal scale: %d",
fe_properties[0].u.st.stat[0].scale);
@ -682,12 +682,12 @@ linuxdvb_frontend_monitor ( void *aux )
if(!gotprop && ioctl_check(lfe, 2)) {
/* try old API */
if (!ioctl(lfe->lfe_fe_fd, FE_READ_SIGNAL_STRENGTH, &u16)) {
mmi->mmi_stats.signal_scale = SIGNAL_STATUS_SCALE_RELATIVE;
mmi->mmi_stats.signal = u16;
mmi->tii_stats.signal_scale = SIGNAL_STATUS_SCALE_RELATIVE;
mmi->tii_stats.signal = u16;
}
else {
ioctl_bad(lfe, 2);
mmi->mmi_stats.signal_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
mmi->tii_stats.signal_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
if (logit)
tvhlog(LOG_WARNING, "linuxdvb", "Unable to provide signal strength value.");
}
@ -697,7 +697,7 @@ linuxdvb_frontend_monitor ( void *aux )
gotprop = 0;
if(ioctl_check(lfe, 3) && fe_properties[1].u.st.len > 0) {
if(fe_properties[1].u.st.stat[0].scale == FE_SCALE_COUNTER) {
mmi->mmi_stats.ec_bit = fe_properties[1].u.st.stat[0].uvalue;
mmi->tii_stats.ec_bit = fe_properties[1].u.st.stat[0].uvalue;
gotprop = 1;
}
else {
@ -711,12 +711,12 @@ linuxdvb_frontend_monitor ( void *aux )
if(gotprop && (fe_properties[2].u.st.len > 0)) {
gotprop = 0;
if(ioctl_check(lfe, 4) && fe_properties[2].u.st.stat[0].scale == FE_SCALE_COUNTER) {
mmi->mmi_stats.tc_bit = fe_properties[2].u.st.stat[0].uvalue;
mmi->tii_stats.tc_bit = fe_properties[2].u.st.stat[0].uvalue;
gotprop = 1;
}
else {
ioctl_bad(lfe, 4);
mmi->mmi_stats.ec_bit = 0; /* both values or none */
mmi->tii_stats.ec_bit = 0; /* both values or none */
if (logit)
tvhlog(LOG_WARNING, "linuxdvb", "Unhandled TOTAL_BIT_COUNT scale: %d",
fe_properties[2].u.st.stat[0].scale);
@ -725,7 +725,7 @@ linuxdvb_frontend_monitor ( void *aux )
if(!gotprop && ioctl_check(lfe, 5)) {
/* try old API */
if (!ioctl(lfe->lfe_fe_fd, FE_READ_BER, &u32))
mmi->mmi_stats.ber = u32;
mmi->tii_stats.ber = u32;
else {
ioctl_bad(lfe, 5);
if (logit)
@ -737,18 +737,18 @@ linuxdvb_frontend_monitor ( void *aux )
gotprop = 0;
if(ioctl_check(lfe, 6) && fe_properties[3].u.st.len > 0) {
if(fe_properties[3].u.st.stat[0].scale == FE_SCALE_RELATIVE) {
mmi->mmi_stats.snr_scale = SIGNAL_STATUS_SCALE_RELATIVE;
mmi->mmi_stats.snr = fe_properties[3].u.st.stat[0].uvalue;
mmi->tii_stats.snr_scale = SIGNAL_STATUS_SCALE_RELATIVE;
mmi->tii_stats.snr = fe_properties[3].u.st.stat[0].uvalue;
gotprop = 1;
}
else if(fe_properties[3].u.st.stat[0].scale == FE_SCALE_DECIBEL) {
mmi->mmi_stats.snr_scale = SIGNAL_STATUS_SCALE_DECIBEL;
mmi->mmi_stats.snr = fe_properties[3].u.st.stat[0].svalue;
mmi->tii_stats.snr_scale = SIGNAL_STATUS_SCALE_DECIBEL;
mmi->tii_stats.snr = fe_properties[3].u.st.stat[0].svalue;
gotprop = 1;
}
else {
ioctl_bad(lfe, 6);
mmi->mmi_stats.snr_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
mmi->tii_stats.snr_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
if (logit)
tvhlog(LOG_WARNING, "linuxdvb", "Unhandled SNR scale: %d",
fe_properties[3].u.st.stat[0].scale);
@ -757,12 +757,12 @@ linuxdvb_frontend_monitor ( void *aux )
if(!gotprop && ioctl_check(lfe, 7)) {
/* try old API */
if (!ioctl(lfe->lfe_fe_fd, FE_READ_SNR, &u16)) {
mmi->mmi_stats.snr_scale = SIGNAL_STATUS_SCALE_RELATIVE;
mmi->mmi_stats.snr = u16;
mmi->tii_stats.snr_scale = SIGNAL_STATUS_SCALE_RELATIVE;
mmi->tii_stats.snr = u16;
}
else {
ioctl_bad(lfe, 7);
mmi->mmi_stats.snr_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
mmi->tii_stats.snr_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
if (logit)
tvhlog(LOG_WARNING, "linuxdvb", "Unable to provide SNR value.");
}
@ -772,7 +772,7 @@ linuxdvb_frontend_monitor ( void *aux )
gotprop = 0;
if(ioctl_check(lfe, 8) && fe_properties[4].u.st.len > 0) {
if(fe_properties[4].u.st.stat[0].scale == FE_SCALE_COUNTER) {
mmi->mmi_stats.unc = mmi->mmi_stats.ec_block = fe_properties[4].u.st.stat[0].uvalue;
mmi->tii_stats.unc = mmi->tii_stats.ec_block = fe_properties[4].u.st.stat[0].uvalue;
gotprop = 1;
}
else {
@ -787,12 +787,12 @@ linuxdvb_frontend_monitor ( void *aux )
if(gotprop && (fe_properties[5].u.st.len > 0)) {
gotprop = 0;
if(ioctl_check(lfe, 9) && fe_properties[5].u.st.stat[0].scale == FE_SCALE_COUNTER) {
mmi->mmi_stats.tc_block = fe_properties[5].u.st.stat[0].uvalue;
mmi->tii_stats.tc_block = fe_properties[5].u.st.stat[0].uvalue;
gotprop = 1;
}
else {
ioctl_bad(lfe, 9);
mmi->mmi_stats.ec_block = mmi->mmi_stats.unc = 0; /* both values or none */
mmi->tii_stats.ec_block = mmi->tii_stats.unc = 0; /* both values or none */
if (logit)
tvhlog(LOG_WARNING, "linuxdvb", "Unhandled TOTAL_BLOCK_COUNT scale: %d",
fe_properties[5].u.st.stat[0].scale);
@ -801,7 +801,7 @@ linuxdvb_frontend_monitor ( void *aux )
if(!gotprop && ioctl_check(lfe, 10)) {
/* try old API */
if (!ioctl(lfe->lfe_fe_fd, FE_READ_UNCORRECTED_BLOCKS, &u32)) {
mmi->mmi_stats.unc = u32;
mmi->tii_stats.unc = u32;
gotprop = 1;
}
else {
@ -816,34 +816,34 @@ linuxdvb_frontend_monitor ( void *aux )
{
ioctl_bad(lfe, 0);
if (ioctl_check(lfe, 1) && !ioctl(lfe->lfe_fe_fd, FE_READ_SIGNAL_STRENGTH, &u16)) {
mmi->mmi_stats.signal_scale = SIGNAL_STATUS_SCALE_RELATIVE;
mmi->mmi_stats.signal = u16;
mmi->tii_stats.signal_scale = SIGNAL_STATUS_SCALE_RELATIVE;
mmi->tii_stats.signal = u16;
}
else {
ioctl_bad(lfe, 1);
mmi->mmi_stats.signal_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
mmi->tii_stats.signal_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
if (logit)
tvhlog(LOG_WARNING, "linuxdvb", "Unable to provide signal strength value.");
}
if (ioctl_check(lfe, 2) && !ioctl(lfe->lfe_fe_fd, FE_READ_BER, &u32))
mmi->mmi_stats.ber = u32;
mmi->tii_stats.ber = u32;
else {
ioctl_bad(lfe, 2);
if (logit)
tvhlog(LOG_WARNING, "linuxdvb", "Unable to provide BER value.");
}
if (ioctl_check(lfe, 3) && !ioctl(lfe->lfe_fe_fd, FE_READ_SNR, &u16)) {
mmi->mmi_stats.snr_scale = SIGNAL_STATUS_SCALE_RELATIVE;
mmi->mmi_stats.snr = u16;
mmi->tii_stats.snr_scale = SIGNAL_STATUS_SCALE_RELATIVE;
mmi->tii_stats.snr = u16;
}
else {
ioctl_bad(lfe, 3);
mmi->mmi_stats.snr_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
mmi->tii_stats.snr_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
if (logit)
tvhlog(LOG_WARNING, "linuxdvb", "Unable to provide SNR value.");
}
if (ioctl_check(lfe, 4) && !ioctl(lfe->lfe_fe_fd, FE_READ_UNCORRECTED_BLOCKS, &u32))
mmi->mmi_stats.unc = u32;
mmi->tii_stats.unc = u32;
else {
ioctl_bad(lfe, 4);
if (logit)
@ -853,16 +853,16 @@ linuxdvb_frontend_monitor ( void *aux )
/* Send message */
sigstat.status_text = signal2str(status);
sigstat.snr = mmi->mmi_stats.snr;
sigstat.signal = mmi->mmi_stats.signal;
sigstat.ber = mmi->mmi_stats.ber;
sigstat.unc = mmi->mmi_stats.unc;
sigstat.signal_scale = mmi->mmi_stats.signal_scale;
sigstat.snr_scale = mmi->mmi_stats.snr_scale;
sigstat.ec_bit = mmi->mmi_stats.ec_bit;
sigstat.tc_bit = mmi->mmi_stats.tc_bit;
sigstat.ec_block = mmi->mmi_stats.ec_block;
sigstat.tc_block = mmi->mmi_stats.tc_block;
sigstat.snr = mmi->tii_stats.snr;
sigstat.signal = mmi->tii_stats.signal;
sigstat.ber = mmi->tii_stats.ber;
sigstat.unc = mmi->tii_stats.unc;
sigstat.signal_scale = mmi->tii_stats.signal_scale;
sigstat.snr_scale = mmi->tii_stats.snr_scale;
sigstat.ec_bit = mmi->tii_stats.ec_bit;
sigstat.tc_bit = mmi->tii_stats.tc_bit;
sigstat.ec_block = mmi->tii_stats.ec_block;
sigstat.tc_block = mmi->tii_stats.tc_block;
sm.sm_type = SMT_SIGNAL_STATUS;
sm.sm_data = &sigstat;
LIST_FOREACH(s, &lfe->mi_transports, s_active_link) {

View file

@ -673,10 +673,10 @@ mpegts_input_create_mux_instance
( mpegts_input_t *mi, mpegts_mux_t *mm )
{
extern const idclass_t mpegts_mux_instance_class;
mpegts_mux_instance_t *mmi;
LIST_FOREACH(mmi, &mi->mi_mux_instances, mmi_input_link)
if (mmi->mmi_mux == mm) break;
if (!mmi)
tvh_input_instance_t *tii;
LIST_FOREACH(tii, &mi->mi_mux_instances, tii_input_link)
if (((mpegts_mux_instance_t *)tii)->mmi_mux == mm) break;
if (!tii)
(void)mpegts_mux_instance_create(mpegts_mux_instance, NULL, mi, mm);
}
@ -871,7 +871,7 @@ mpegts_input_recv_packets
/* Check for sync */
while ( (len >= MIN_TS_SYN) &&
((len2 = ts_sync_count(tsb, len)) < MIN_TS_SYN) ) {
mmi->mmi_stats.unc++;
mmi->tii_stats.unc++;
--len;
++tsb;
++off;
@ -1079,7 +1079,7 @@ mpegts_input_process
/* Transport error */
if (pid & 0x8000) {
if ((pid & 0x1FFF) != 0x1FFF)
++mmi->mmi_stats.te;
++mmi->tii_stats.te;
}
pid &= 0x1FFF;
@ -1102,7 +1102,7 @@ mpegts_input_process
cc = tsb2[3] & 0x0f;
if (cc2 != 0xff && cc2 != cc) {
tvhtrace("mpegts", "pid %04X cc err %2d != %2d", pid, cc, cc2);
++mmi->mmi_stats.cc;
++mmi->tii_stats.cc;
}
cc2 = (cc + 1) & 0xF;
}
@ -1214,7 +1214,7 @@ done:
pthread_cond_signal(&mi->mi_table_cond);
/* Bandwidth monitoring */
atomic_add(&mmi->mmi_stats.bps, tsb - mpkt->mp_data);
atomic_add(&mmi->tii_stats.bps, tsb - mpkt->mp_data);
}
static void *
@ -1352,15 +1352,15 @@ mpegts_input_stream_status
w = MAX(w, ths->ths_weight);
}
st->uuid = strdup(idnode_uuid_as_str(&mmi->mmi_id));
st->uuid = strdup(idnode_uuid_as_str(&mmi->tii_id));
mi->mi_display_name(mi, buf, sizeof(buf));
st->input_name = strdup(buf);
mpegts_mux_nice_name(mm, buf, sizeof(buf));
st->stream_name = strdup(buf);
st->subs_count = s;
st->max_weight = w;
st->stats = mmi->mmi_stats;
st->stats.bps = atomic_exchange(&mmi->mmi_stats.bps, 0) * 8;
st->stats = mmi->tii_stats;
st->stats.bps = atomic_exchange(&mmi->tii_stats.bps, 0) * 8;
}
static void
@ -1524,19 +1524,19 @@ void
mpegts_input_delete ( mpegts_input_t *mi, int delconf )
{
mpegts_network_link_t *mnl;
mpegts_mux_instance_t *mmi, *mmi_next;
tvh_input_instance_t *tii, *tii_next;
/* Remove networks */
while ((mnl = LIST_FIRST(&mi->mi_networks)))
mpegts_input_del_network(mnl);
/* Remove mux instances assigned to this input */
mmi = LIST_FIRST(&mi->mi_mux_instances);
while (mmi) {
mmi_next = LIST_NEXT(mmi, mmi_input_link);
if (mmi->mmi_input == mi)
mmi->mmi_delete(mmi);
mmi = mmi_next;
tii = LIST_FIRST(&mi->mi_mux_instances);
while (tii) {
tii_next = LIST_NEXT(tii, tii_input_link);
if (((mpegts_mux_instance_t *)tii)->mmi_input == mi)
tii->tii_delete(tii);
tii = tii_next;
}
/* Remove global refs */

View file

@ -37,6 +37,7 @@ static void mpegts_mux_scan_timeout ( void *p );
const idclass_t mpegts_mux_instance_class =
{
.ic_super = &tvh_input_instance_class,
.ic_class = "mpegts_mux_instance",
.ic_caption = "MPEGTS Multiplex Phy",
.ic_perm_def = ACCESS_ADMIN
@ -44,11 +45,13 @@ const idclass_t mpegts_mux_instance_class =
void
mpegts_mux_instance_delete
( mpegts_mux_instance_t *mmi )
( tvh_input_instance_t *tii )
{
idnode_unlink(&mmi->mmi_id);
mpegts_mux_instance_t *mmi = (mpegts_mux_instance_t *)tii;
idnode_unlink(&tii->tii_id);
LIST_REMOVE(mmi, mmi_mux_link);
LIST_REMOVE(mmi, mmi_input_link);
LIST_REMOVE(tii, tii_input_link);
free(mmi);
}
@ -58,7 +61,7 @@ mpegts_mux_instance_create0
mpegts_input_t *mi, mpegts_mux_t *mm )
{
// TODO: does this need to be an idnode?
if (idnode_insert(&mmi->mmi_id, uuid, class, 0)) {
if (idnode_insert(&mmi->tii_id, uuid, class, 0)) {
free(mmi);
return NULL;
}
@ -68,10 +71,11 @@ mpegts_mux_instance_create0
mmi->mmi_input = mi;
/* Callbacks */
mmi->mmi_delete = mpegts_mux_instance_delete;
mmi->tii_delete = mpegts_mux_instance_delete;
mmi->tii_clear_stats = tvh_input_instance_clear_stats;
LIST_INSERT_HEAD(&mm->mm_instances, mmi, mmi_mux_link);
LIST_INSERT_HEAD(&mi->mi_mux_instances, mmi, mmi_input_link);
LIST_INSERT_HEAD(&mi->mi_mux_instances, (tvh_input_instance_t *)mmi, tii_input_link);
return mmi;
@ -621,7 +625,7 @@ mpegts_mux_delete ( mpegts_mux_t *mm, int delconf )
/* Remove instances */
while ((mmi = LIST_FIRST(&mm->mm_instances))) {
mmi->mmi_delete(mmi);
mmi->tii_delete((tvh_input_instance_t *)mmi);
}
/* Remove raw subscribers */

View file

@ -76,16 +76,16 @@ satip_frontend_signal_cb( void *aux )
lfe->sf_tables = 1;
}
sigstat.status_text = signal2str(lfe->sf_status);
sigstat.snr = mmi->mmi_stats.snr;
sigstat.signal = mmi->mmi_stats.signal;
sigstat.ber = mmi->mmi_stats.ber;
sigstat.unc = mmi->mmi_stats.unc;
sigstat.signal_scale = mmi->mmi_stats.signal_scale;
sigstat.snr_scale = mmi->mmi_stats.snr_scale;
sigstat.ec_bit = mmi->mmi_stats.ec_bit;
sigstat.tc_bit = mmi->mmi_stats.tc_bit;
sigstat.ec_block = mmi->mmi_stats.ec_block;
sigstat.tc_block = mmi->mmi_stats.tc_block;
sigstat.snr = mmi->tii_stats.snr;
sigstat.signal = mmi->tii_stats.signal;
sigstat.ber = mmi->tii_stats.ber;
sigstat.unc = mmi->tii_stats.unc;
sigstat.signal_scale = mmi->tii_stats.signal_scale;
sigstat.snr_scale = mmi->tii_stats.snr_scale;
sigstat.ec_bit = mmi->tii_stats.ec_bit;
sigstat.tc_bit = mmi->tii_stats.tc_bit;
sigstat.ec_block = mmi->tii_stats.ec_block;
sigstat.tc_block = mmi->tii_stats.tc_block;
sm.sm_type = SMT_SIGNAL_STATUS;
sm.sm_data = &sigstat;
LIST_FOREACH(svc, &lfe->mi_transports, s_active_link) {
@ -722,20 +722,20 @@ satip_frontend_decode_rtcp( satip_frontend_t *lfe, const char *name,
return;
if (atoi(argv[0]) != lfe->sf_number)
return;
mmi->mmi_stats.signal =
mmi->tii_stats.signal =
atoi(argv[1]) * 0xffff / lfe->sf_device->sd_sig_scale;
mmi->mmi_stats.signal_scale =
mmi->tii_stats.signal_scale =
SIGNAL_STATUS_SCALE_RELATIVE;
if (atoi(argv[2]) > 0)
status = SIGNAL_GOOD;
mmi->mmi_stats.snr = atoi(argv[3]) * 0xffff / 15;
mmi->mmi_stats.snr_scale =
mmi->tii_stats.snr = atoi(argv[3]) * 0xffff / 15;
mmi->tii_stats.snr_scale =
SIGNAL_STATUS_SCALE_RELATIVE;
if (status == SIGNAL_GOOD &&
mmi->mmi_stats.signal == 0 && mmi->mmi_stats.snr == 0) {
mmi->tii_stats.signal == 0 && mmi->tii_stats.snr == 0) {
/* some values that we're tuned */
mmi->mmi_stats.signal = 50 * 0xffff / 100;
mmi->mmi_stats.snr = 12 * 0xffff / 15;
mmi->tii_stats.signal = 50 * 0xffff / 100;
mmi->tii_stats.snr = 12 * 0xffff / 15;
}
goto ok;
} else if (strncmp(s, "ver=1.0;", 8) == 0) {
@ -747,14 +747,14 @@ satip_frontend_decode_rtcp( satip_frontend_t *lfe, const char *name,
return;
if (atoi(argv[0]) != lfe->sf_number)
return;
mmi->mmi_stats.signal =
mmi->tii_stats.signal =
atoi(argv[1]) * 0xffff / lfe->sf_device->sd_sig_scale;
mmi->mmi_stats.signal_scale =
mmi->tii_stats.signal_scale =
SIGNAL_STATUS_SCALE_RELATIVE;
if (atoi(argv[2]) > 0)
status = SIGNAL_GOOD;
mmi->mmi_stats.snr = atoi(argv[3]) * 0xffff / 15;
mmi->mmi_stats.snr_scale =
mmi->tii_stats.snr = atoi(argv[3]) * 0xffff / 15;
mmi->tii_stats.snr_scale =
SIGNAL_STATUS_SCALE_RELATIVE;
goto ok;
} else if (strncmp(s, "ver=1.1;tuner=", 14) == 0) {
@ -763,14 +763,14 @@ satip_frontend_decode_rtcp( satip_frontend_t *lfe, const char *name,
return;
if (atoi(argv[0]) != lfe->sf_number)
return;
mmi->mmi_stats.signal =
mmi->tii_stats.signal =
atoi(argv[1]) * 0xffff / lfe->sf_device->sd_sig_scale;
mmi->mmi_stats.signal_scale =
mmi->tii_stats.signal_scale =
SIGNAL_STATUS_SCALE_RELATIVE;
if (atoi(argv[2]) > 0)
status = SIGNAL_GOOD;
mmi->mmi_stats.snr = atoi(argv[3]) * 0xffff / 15;
mmi->mmi_stats.snr_scale =
mmi->tii_stats.snr = atoi(argv[3]) * 0xffff / 15;
mmi->tii_stats.snr_scale =
SIGNAL_STATUS_SCALE_RELATIVE;
goto ok;
}
@ -782,9 +782,9 @@ satip_frontend_decode_rtcp( satip_frontend_t *lfe, const char *name,
return;
ok:
if (mmi->mmi_stats.snr < 2 && status == SIGNAL_GOOD)
if (mmi->tii_stats.snr < 2 && status == SIGNAL_GOOD)
status = SIGNAL_BAD;
else if (mmi->mmi_stats.snr < 4 && status == SIGNAL_GOOD)
else if (mmi->tii_stats.snr < 4 && status == SIGNAL_GOOD)
status = SIGNAL_FAINT;
lfe->sf_status = status;
}
@ -1503,7 +1503,7 @@ new_tune:
}
pthread_mutex_lock(&lfe->sf_dvr_lock);
if (lfe->sf_req == lfe->sf_req_thread) {
mmi->mmi_stats.unc += unc;
mmi->tii_stats.unc += unc;
mpegts_input_recv_packets((mpegts_input_t*)lfe, mmi,
&sb, NULL, NULL);
} else

View file

@ -23,12 +23,12 @@ extern const idclass_t mpegts_mux_class;
extern const idclass_t mpegts_mux_instance_class;
static void
tsfile_mux_instance_delete( mpegts_mux_instance_t *_mmi )
tsfile_mux_instance_delete( tvh_input_instance_t *tii )
{
tsfile_mux_instance_t *mmi = (tsfile_mux_instance_t *)_mmi;
tsfile_mux_instance_t *mmi = (tsfile_mux_instance_t *)tii;
free(mmi->mmi_tsfile_path);
mpegts_mux_instance_delete(_mmi);
mpegts_mux_instance_delete(tii);
}
tsfile_mux_instance_t *
@ -41,7 +41,7 @@ tsfile_mux_instance_create
#undef tsfile_mux_instance_class
mmi->mmi_tsfile_path = strdup(path);
mmi->mmi_tsfile_pcr_pid = MPEGTS_PID_NONE;
mmi->mmi_delete = tsfile_mux_instance_delete;
mmi->tii_delete = tsfile_mux_instance_delete;
tvhtrace("tsfile", "mmi created %p path %s", mmi, mmi->mmi_tsfile_path);
return mmi;
}

View file

@ -300,19 +300,19 @@ tvhdhomerun_frontend_monitor_cb( void *aux )
if(tuner_status.signal_present) {
/* TODO: totaly stupid conversion from 0-100 scale to 0-655.35 */
mmi->mmi_stats.snr = tuner_status.signal_to_noise_quality * 655.35;
mmi->mmi_stats.signal = tuner_status.signal_strength * 655.35;
mmi->tii_stats.snr = tuner_status.signal_to_noise_quality * 655.35;
mmi->tii_stats.signal = tuner_status.signal_strength * 655.35;
} else {
mmi->mmi_stats.snr = 0;
mmi->tii_stats.snr = 0;
}
sigstat.status_text = signal2str(hfe->hf_status);
sigstat.snr = mmi->mmi_stats.snr;
sigstat.snr_scale = mmi->mmi_stats.snr_scale = SIGNAL_STATUS_SCALE_RELATIVE;
sigstat.signal = mmi->mmi_stats.signal;
sigstat.signal_scale = mmi->mmi_stats.signal_scale = SIGNAL_STATUS_SCALE_RELATIVE;
sigstat.ber = mmi->mmi_stats.ber;
sigstat.unc = mmi->mmi_stats.unc;
sigstat.snr = mmi->tii_stats.snr;
sigstat.snr_scale = mmi->tii_stats.snr_scale = SIGNAL_STATUS_SCALE_RELATIVE;
sigstat.signal = mmi->tii_stats.signal;
sigstat.signal_scale = mmi->tii_stats.signal_scale = SIGNAL_STATUS_SCALE_RELATIVE;
sigstat.ber = mmi->tii_stats.ber;
sigstat.unc = mmi->tii_stats.unc;
sm.sm_type = SMT_SIGNAL_STATUS;
sm.sm_data = &sigstat;

View file

@ -231,6 +231,33 @@ tvheadend.status_streams = function(panel, index)
if (grid)
return;
var actions = new Ext.ux.grid.RowActions({
header: '',
width: 10,
actions: [
{
iconCls: 'undo',
qtip: 'Clear statistics',
cb: function(grid, rec, act, row) {
var uuid = grid.getStore().getAt(row).data.uuid;
Ext.MessageBox.confirm('Clear statistics',
'Clear statistics for selected input?',
function(button) {
if (button === 'no')
return;
Ext.Ajax.request({
url: 'api/status/inputclrstats',
params: { uuid: uuid }
});
}
);
}
},
],
destroy: function() {
}
});
store = new Ext.data.JsonStore({
root: 'entries',
totalProperty: 'totalCount',
@ -288,6 +315,7 @@ tvheadend.status_streams = function(panel, index)
}
var cm = new Ext.grid.ColumnModel([
actions,
{
width: 120,
header: "Input",
@ -402,7 +430,8 @@ tvheadend.status_streams = function(panel, index)
flex: 1,
viewConfig: {
forceFit: true
}
},
plugins: [actions]
});
dpanel.add(grid);