diff --git a/Makefile b/Makefile index 56d42c31..50c84d81 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/ajaxui/ajaxui_config_transport.c b/ajaxui/ajaxui_config_transport.c index 18451a25..13bb54bf 100644 --- a/ajaxui/ajaxui_config_transport.c +++ b/ajaxui/ajaxui_config_transport.c @@ -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, ""); @@ -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); } diff --git a/main.c b/main.c index de7c207f..ef291e7b 100644 --- a/main.c +++ b/main.c @@ -62,6 +62,7 @@ #include "ajaxui/ajaxui.h" #include "webui/webui.h" #include "access.h" +#include "serviceprobe.h" #include @@ -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(); diff --git a/serviceprobe.c b/serviceprobe.c new file mode 100644 index 00000000..6c35dea9 --- /dev/null +++ b/serviceprobe.c @@ -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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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); +} diff --git a/serviceprobe.h b/serviceprobe.h new file mode 100644 index 00000000..e28a31df --- /dev/null +++ b/serviceprobe.h @@ -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 . + */ + +#ifndef SERVICE_PROBE_H_ +#define SERVICE_PROBE_H_ + +void serviceprobe_setup(void); + +void serviceprobe_add(th_transport_t *t); + +#endif /* SERVICE_PROBE_H_ */ diff --git a/subscriptions.c b/subscriptions.c index aa1ffd5a..22f839bb 100644 --- a/subscriptions.c +++ b/subscriptions.c @@ -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) { diff --git a/subscriptions.h b/subscriptions.h index 63ed55ba..a171a656 100644 --- a/subscriptions.h +++ b/subscriptions.h @@ -32,4 +32,6 @@ void subscriptions_init(void); void subscription_stop(th_subscription_t *s); +void subscription_reschedule(void); + #endif /* SUBSCRIPTIONS_H */ diff --git a/transports.c b/transports.c index 4842e25b..657e86af 100644 --- a/transports.c +++ b/transports.c @@ -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; diff --git a/transports.h b/transports.h index 754dc7fc..f528b5b9 100644 --- a/transports.h +++ b/transports.h @@ -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, diff --git a/tvhead.h b/tvhead.h index 9d8c369c..471662a8 100644 --- a/tvhead.h +++ b/tvhead.h @@ -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;