2008-05-02 10:17:22 +00:00
|
|
|
|
/*
|
|
|
|
|
* Output functions for fixed multicast streaming
|
|
|
|
|
* Copyright (C) 2007 Andreas <EFBFBD>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 {
|
|
|
|
|
th_muxer_t *sp_muxer;
|
|
|
|
|
th_subscription_t *sp_s;
|
2008-05-04 18:32:46 +00:00
|
|
|
|
dtimer_t sp_timer;
|
2008-05-02 10:17:22 +00:00
|
|
|
|
} sp_t;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2008-05-04 18:32:46 +00:00
|
|
|
|
sp_done_callback(void *aux, int64_t now)
|
2008-05-02 10:17:22 +00:00
|
|
|
|
{
|
2008-05-04 18:32:46 +00:00
|
|
|
|
sp_t *sp = aux;
|
2008-05-02 10:17:22 +00:00
|
|
|
|
th_subscription_t *s = sp->sp_s;
|
|
|
|
|
th_transport_t *t = sp->sp_s->ths_transport;
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
2008-05-02 13:54:39 +00:00
|
|
|
|
transport_stop(t, 0);
|
|
|
|
|
|
2008-05-02 10:17:22 +00:00
|
|
|
|
subscription_reschedule();
|
|
|
|
|
|
|
|
|
|
serviceprobe_engage();
|
|
|
|
|
free(sp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2008-05-04 18:32:46 +00:00
|
|
|
|
* Got a packet, map it
|
2008-05-02 10:17:22 +00:00
|
|
|
|
*/
|
|
|
|
|
static void
|
2008-05-04 18:32:46 +00:00
|
|
|
|
sp_packet_input(void *opaque, th_muxstream_t *tms, th_pkt_t *pkt)
|
2008-05-02 10:17:22 +00:00
|
|
|
|
{
|
2008-05-04 18:32:46 +00:00
|
|
|
|
sp_t *sp = opaque;
|
2008-05-02 10:17:22 +00:00
|
|
|
|
th_transport_t *t = sp->sp_s->ths_transport;
|
2008-05-03 06:55:56 +00:00
|
|
|
|
channel_t *ch;
|
2008-05-02 15:22:42 +00:00
|
|
|
|
|
2008-05-04 18:32:46 +00:00
|
|
|
|
syslog(LOG_INFO, "Probed \"%s\" -- Ok\n", t->tht_svcname);
|
2008-05-02 10:17:22 +00:00
|
|
|
|
|
2008-05-04 18:32:46 +00:00
|
|
|
|
if(t->tht_ch == NULL && t->tht_svcname != NULL) {
|
|
|
|
|
ch = channel_find(t->tht_svcname, 1, NULL);
|
|
|
|
|
transport_map_channel(t, ch);
|
|
|
|
|
|
|
|
|
|
t->tht_config_change(t);
|
2008-05-02 10:17:22 +00:00
|
|
|
|
}
|
2008-05-04 18:32:46 +00:00
|
|
|
|
dtimer_arm(&sp->sp_timer, sp_done_callback, sp, 0);
|
2008-05-02 10:17:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-05-02 14:18:56 +00:00
|
|
|
|
/**
|
2008-05-04 15:31:39 +00:00
|
|
|
|
* Callback when transport changes status
|
2008-05-02 14:18:56 +00:00
|
|
|
|
*/
|
|
|
|
|
static void
|
2008-05-04 15:31:39 +00:00
|
|
|
|
sp_status_callback(struct th_subscription *s, int status, void *opaque)
|
2008-05-02 14:18:56 +00:00
|
|
|
|
{
|
|
|
|
|
sp_t *sp = opaque;
|
2008-05-04 18:32:46 +00:00
|
|
|
|
th_transport_t *t = sp->sp_s->ths_transport;
|
|
|
|
|
char *errtxt;
|
|
|
|
|
|
2008-05-04 15:31:39 +00:00
|
|
|
|
s->ths_status_callback = NULL;
|
2008-05-02 14:18:56 +00:00
|
|
|
|
|
2008-05-04 15:31:39 +00:00
|
|
|
|
switch(status) {
|
|
|
|
|
case TRANSPORT_STATUS_OK:
|
|
|
|
|
return;
|
|
|
|
|
case TRANSPORT_STATUS_NO_DESCRAMBLER:
|
2008-05-04 18:32:46 +00:00
|
|
|
|
errtxt = "No descrambler for stream";
|
2008-05-04 15:31:39 +00:00
|
|
|
|
break;
|
|
|
|
|
case TRANSPORT_STATUS_NO_ACCESS:
|
2008-05-04 18:32:46 +00:00
|
|
|
|
errtxt = "Access denied";
|
|
|
|
|
break;
|
|
|
|
|
case TRANSPORT_STATUS_NO_INPUT:
|
|
|
|
|
errtxt = "No input detected";
|
2008-05-04 15:31:39 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2008-05-04 18:32:46 +00:00
|
|
|
|
errtxt = "Other error";
|
2008-05-04 15:31:39 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
2008-05-04 18:32:46 +00:00
|
|
|
|
|
|
|
|
|
syslog(LOG_INFO, "Probed \"%s\" -- %s\n", t->tht_svcname, errtxt);
|
|
|
|
|
dtimer_arm(&sp->sp_timer, sp_done_callback, sp, 0);
|
2008-05-02 14:18:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-05-02 10:17:22 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 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;
|
2008-05-02 14:18:56 +00:00
|
|
|
|
s->ths_opaque = sp;
|
|
|
|
|
|
2008-05-04 18:51:00 +00:00
|
|
|
|
if(t->tht_runstatus != TRANSPORT_RUNNING)
|
2008-05-02 10:17:22 +00:00
|
|
|
|
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);
|
|
|
|
|
|
2008-05-04 15:31:39 +00:00
|
|
|
|
s->ths_status_callback = sp_status_callback;
|
2008-05-02 10:17:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
serviceprobe_add(th_transport_t *t)
|
|
|
|
|
{
|
|
|
|
|
int was_first = TAILQ_FIRST(&probequeue) == NULL;
|
|
|
|
|
|
2008-05-02 14:24:36 +00:00
|
|
|
|
if(!transport_is_tv(t))
|
|
|
|
|
return;
|
|
|
|
|
|
2008-05-02 10:17:22 +00:00
|
|
|
|
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);
|
|
|
|
|
}
|