Add function for automating probing of services and if successful, map to a channel

This commit is contained in:
Andreas Öman 2008-05-02 10:17:22 +00:00
parent 7c849df9c3
commit 5879cd4d14
10 changed files with 225 additions and 3 deletions

View file

@ -3,7 +3,7 @@
SRCS = main.c dispatch.c channels.c transports.c teletext.c psi.c \
subscriptions.c mux.c tsdemux.c buffer.c tcp.c \
resolver.c tsmux.c parsers.c bitstream.c parser_h264.c spawn.c \
notify.c intercom.c access.c
notify.c intercom.c access.c serviceprobe.c
SRCS += http.c

View file

@ -33,6 +33,7 @@
#include "channels.h"
#include "psi.h"
#include "transports.h"
#include "serviceprobe.h"
/**
@ -227,6 +228,8 @@ ajax_transport_build_list(http_connection_t *hc, tcp_queue_t *tq,
ajax_a_jsfuncf(tq, "Map selected", "selected_do('map');");
tcp_qprintf(tq, " / ");
ajax_a_jsfuncf(tq, "Unmap selected", "selected_do('unmap');");
tcp_qprintf(tq, " / ");
ajax_a_jsfuncf(tq, "Test and map selected", "selected_do('probe');");
tcp_qprintf(tq, "</div></div>");
@ -337,6 +340,9 @@ ajax_transport_op(http_connection_t *hc, http_reply_t *hr,
dvb_map_channel(t, tq);
} else if(!strcmp(op, "unmap") && t->tht_channel != NULL) {
dvb_unmap_channel(t, tq);
} else if(!strcmp(op, "probe")) {
serviceprobe_add(t);
continue;
}
t->tht_config_change(t);
}

2
main.c
View file

@ -62,6 +62,7 @@
#include "ajaxui/ajaxui.h"
#include "webui/webui.h"
#include "access.h"
#include "serviceprobe.h"
#include <libhts/htsparachute.h>
@ -237,6 +238,7 @@ main(int argc, char **argv)
av_log_set_level(AV_LOG_INFO);
tffm_init();
pkt_init();
serviceprobe_setup();
if(!disable_dvb)
dvb_init();

175
serviceprobe.c Normal file
View file

@ -0,0 +1,175 @@
/*
* Output functions for fixed multicast streaming
* Copyright (C) 2007 Andreas Öman
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <fcntl.h>
#include <errno.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include "tvhead.h"
#include "iptv_output.h"
#include "dispatch.h"
#include "channels.h"
#include "subscriptions.h"
#include "serviceprobe.h"
#include "transports.h"
#include "mux.h"
static void serviceprobe_engage(void);
struct th_transport_queue probequeue;
typedef struct sp {
dtimer_t sp_timer;
th_muxer_t *sp_muxer;
th_subscription_t *sp_s;
int sp_ok;
} sp_t;
static void
sp_done(sp_t *sp)
{
th_subscription_t *s = sp->sp_s;
th_transport_t *t = sp->sp_s->ths_transport;
dtimer_disarm(&sp->sp_timer);
muxer_deinit(sp->sp_muxer, s);
LIST_REMOVE(s, ths_transport_link);
free(s);
TAILQ_REMOVE(&probequeue, t, tht_probe_link);
t->tht_on_probe_queue = 0;
subscription_reschedule();
serviceprobe_engage();
free(sp);
}
/**
*
*/
static void
sp_timeout(void *aux, int64_t now)
{
sp_t *sp = aux;
th_transport_t *t = sp->sp_s->ths_transport;
syslog(LOG_INFO,
"Probe %6s %s\n",
sp->sp_ok ? "Ok" : "Failed", t->tht_servicename);
if(sp->sp_ok) {
if(t->tht_channel == NULL && t->tht_servicename != NULL) {
transport_set_channel(t, t->tht_servicename);
t->tht_config_change(t);
}
}
sp_done(sp);
}
static void
sp_packet_input(void *opaque, th_muxstream_t *tms, th_pkt_t *pkt)
{
sp_t *sp = opaque;
if(tms->tms_stream->st_type == HTSTV_MPEG2VIDEO ||
tms->tms_stream->st_type == HTSTV_H264) {
sp->sp_ok = 1;
dtimer_arm(&sp->sp_timer, sp_timeout, sp, 0);
}
}
/**
* Setup IPTV (TS over UDP) output
*/
static void
serviceprobe_engage(void)
{
th_transport_t *t;
th_subscription_t *s;
th_muxer_t *tm;
sp_t *sp;
if((t = TAILQ_FIRST(&probequeue)) == NULL)
return;
sp = calloc(1, sizeof(sp_t));
sp->sp_s = s = calloc(1, sizeof(th_subscription_t));
s->ths_title = "probe";
s->ths_weight = INT32_MAX;
if(t->tht_status != TRANSPORT_RUNNING)
transport_start(t, INT32_MAX);
s->ths_transport = t;
LIST_INSERT_HEAD(&t->tht_subscriptions, s, ths_transport_link);
sp->sp_muxer = tm = muxer_init(s, sp_packet_input, sp);
muxer_play(tm, AV_NOPTS_VALUE);
dtimer_arm(&sp->sp_timer, sp_timeout, sp, 4);
}
/**
*
*/
void
serviceprobe_add(th_transport_t *t)
{
int was_first = TAILQ_FIRST(&probequeue) == NULL;
if(t->tht_on_probe_queue)
return;
TAILQ_INSERT_TAIL(&probequeue, t, tht_probe_link);
t->tht_on_probe_queue = 1;
if(was_first)
serviceprobe_engage();
}
void
serviceprobe_setup(void)
{
TAILQ_INIT(&probequeue);
}

26
serviceprobe.h Normal file
View file

@ -0,0 +1,26 @@
/*
* Functions for transport probing
* Copyright (C) 2007 Andreas Öman
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SERVICE_PROBE_H_
#define SERVICE_PROBE_H_
void serviceprobe_setup(void);
void serviceprobe_add(th_transport_t *t);
#endif /* SERVICE_PROBE_H_ */

View file

@ -52,7 +52,7 @@ struct th_subscription_list subscriptions;
static dtimer_t auto_reschedule_timer;
static void
void
subscription_reschedule(void)
{
th_subscription_t *s;
@ -151,6 +151,7 @@ subscription_create(th_channel_t *ch, unsigned int weight, const char *name,
return s;
}
void
subscription_set_weight(th_subscription_t *s, unsigned int weight)
{

View file

@ -32,4 +32,6 @@ void subscriptions_init(void);
void subscription_stop(th_subscription_t *s);
void subscription_reschedule(void);
#endif /* SUBSCRIPTIONS_H */

View file

@ -151,7 +151,7 @@ transport_stop(th_transport_t *t, int flush_subscriptions)
/*
*
*/
static int
int
transport_start(th_transport_t *t, unsigned int weight)
{
th_stream_t *st;

View file

@ -23,6 +23,8 @@
unsigned int transport_compute_weight(struct th_transport_list *head);
int transport_start(th_transport_t *t, unsigned int weight);
void transport_stop(th_transport_t *t, int flush_subscriptions);
th_transport_t *transport_create(const char *identifier, int type,

View file

@ -80,6 +80,7 @@ TAILQ_HEAD(event_queue, event);
LIST_HEAD(pvr_rec_list, pvr_rec);
TAILQ_HEAD(ref_update_queue, ref_update);
LIST_HEAD(th_transport_list, th_transport);
TAILQ_HEAD(th_transport_queue, th_transport);
LIST_HEAD(th_dvb_mux_list, th_dvb_mux);
LIST_HEAD(th_dvb_mux_instance_list, th_dvb_mux_instance);
LIST_HEAD(th_stream_list, th_stream);
@ -500,6 +501,13 @@ typedef struct th_transport {
int tht_scrambled;
int tht_caid;
/**
* Autoprobing support
*/
TAILQ_ENTRY(th_transport) tht_probe_link;
int tht_on_probe_queue;
} th_transport_t;