iptv: forgot to actually add most of the IPTV files.

This commit is contained in:
Adam Sutton 2013-04-30 11:44:23 +01:00
parent a7d7392661
commit 646bfe3e88
7 changed files with 702 additions and 0 deletions

28
src/input.c Normal file
View file

@ -0,0 +1,28 @@
/*
* Tvheadend
* Copyright (C) 2013 Adam Sutton
*
* 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 "input.h"
void input_init ( void )
{
#if ENABLE_MPEGTS
#if ENABLE_IPTV
iptv_input_init();
#endif
#endif
}

80
src/input/mpegts/dvb.h Normal file
View file

@ -0,0 +1,80 @@
/*
* TV Input - Linux DVB interface - Support
* 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/>.
*/
/*
* Based on:
*
* ITU-T Recommendation H.222.0 / ISO standard 13818-1
* EN 300 468 - V1.7.1
*/
#ifndef DVB_SUPPORT_H
#define DVB_SUPPORT_H
#define DVB_DESC_VIDEO_STREAM 0x02
#define DVB_DESC_REGISTRATION 0x05
#define DVB_DESC_CA 0x09
#define DVB_DESC_LANGUAGE 0x0a
/* Descriptors defined in EN 300 468 */
#define DVB_DESC_NETWORK_NAME 0x40
#define DVB_DESC_SERVICE_LIST 0x41
#define DVB_DESC_SAT 0x43
#define DVB_DESC_CABLE 0x44
#define DVB_DESC_SHORT_EVENT 0x4d
#define DVB_DESC_EXT_EVENT 0x4e
#define DVB_DESC_SERVICE 0x48
#define DVB_DESC_COMPONENT 0x50
#define DVB_DESC_CONTENT 0x54
#define DVB_DESC_PARENTAL_RAT 0x55
#define DVB_DESC_TELETEXT 0x56
#define DVB_DESC_SUBTITLE 0x59
#define DVB_DESC_TERR 0x5a
#define DVB_DESC_AC3 0x6a
#define DVB_DESC_DEF_AUTHORITY 0x73
#define DVB_DESC_CRID 0x76
#define DVB_DESC_EAC3 0x7a
#define DVB_DESC_AAC 0x7c
#define DVB_DESC_LOCAL_CHAN 0x83
typedef struct dvb_string_conv
{
uint8_t type;
size_t (*func) ( char *dst, size_t *dstlen,
const uint8_t* src, size_t srclen );
} dvb_string_conv_t;
int dvb_get_string(char *dst, size_t dstlen, const uint8_t *src,
const size_t srclen, const char *dvb_charset,
dvb_string_conv_t *conv);
int dvb_get_string_with_len(char *dst, size_t dstlen,
const uint8_t *buf, size_t buflen, const char *dvb_charset,
dvb_string_conv_t *conv);
#define bcdtoint(i) ((((i & 0xf0) >> 4) * 10) + (i & 0x0f))
time_t dvb_convert_date(uint8_t *dvb_buf);
const char *dvb_polarisation_to_str(int pol);
const char *dvb_polarisation_to_str_long(int pol);
void atsc_utf16_to_utf8(uint8_t *src, int len, char *buf, int buflen);
#endif /* DVB_SUPPORT_H */

31
src/input/mpegts/iptv.h Normal file
View file

@ -0,0 +1,31 @@
/*
* IPTV Input
*
* Copyright (C) 2013 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 __IPTV_H__
#define __IPTV_H__
void iptv_init ( void );
#endif /* __IPTV_H__ */
/******************************************************************************
* Editor Configuration
*
* vim:sts=2:ts=2:sw=2:et
*****************************************************************************/

View file

@ -0,0 +1,302 @@
/*
* IPTV Input
*
* Copyright (C) 2013 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 "iptv_private.h"
#include "tcp.h"
#include <string.h>
#include <sys/epoll.h>
#include <assert.h>
#include <regex.h>
/*
* Globals
*/
iptv_input_t iptv_input;
iptv_network_t iptv_network;
int iptv_poll_fd;
pthread_t iptv_thread;
pthread_mutex_t iptv_lock;
typedef struct url
{
char buf[2048];
const char *scheme;
const char *host;
uint16_t port;
const char *path;
} url_t;
static int
url_parse ( url_t *up, const char *urlstr )
{
char *t1, *t2;
strcpy(up->buf, urlstr);
/* Scheme */
up->scheme = t1 = up->buf;
if (!(t2 = strstr(t1, "://"))) {
return 1;
}
*t2 = 0;
/* Host */
up->host = t1 = t2 + 3;
up->path = NULL;
if ((t2 = strstr(t1, "/"))) {
*t2 = 0;
up->path = t2 + 1;
}
/* Port */
up->port = 0;
if (!(t2 = strstr(up->host, "::"))) {
if (!strcmp(up->scheme, "https"))
up->port = 443;
else if (!strcmp(up->scheme, "http"))
up->port = 80;
}
return 0;
}
static int http_connect (const char *urlstr, htsbuf_queue_t *spill)
{
int fd, c;
char buf[1024];
url_t url;
if (url_parse(&url, urlstr))
return -1;
/* Make connection */
fd = tcp_connect(url.host, url.port, buf, sizeof(buf), 10);
if (!fd)
return -1;
/* Send request (VERY basic) */
c = snprintf(buf, sizeof(buf), "GET %s HTTP/1.1\r\n", urlstr);
tvh_write(fd, buf, c);
c = snprintf(buf, sizeof(buf), "Hostname: %s\r\n", url.host);
tvh_write(fd, buf, c);
tvh_write(fd, "\r\n", 2);
/* Read back header */
htsbuf_queue_flush(spill);
while ((c = tcp_read_line(fd, buf, sizeof(buf), spill)))
if (!*buf) break;
return fd;
}
/*
* HTTP
*/
static int
iptv_input_start_http ( iptv_mux_t *im )
{
int ret = SM_CODE_TUNING_FAILED;
/* Setup connection */
im->mm_iptv_fd = http_connect(im->mm_iptv_url, &im->mm_iptv_spill);
return ret;
}
/*
* Input definition
*/
extern const idclass_t mpegts_input_class;
const idclass_t iptv_input_class = {
.ic_super = &mpegts_input_class,
.ic_class = "iptv_input",
.ic_caption = "IPTV Input",
.ic_properties = (const property_t[]){
}
};
static int
iptv_input_start_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi )
{
int ret = SM_CODE_TUNING_FAILED;
iptv_mux_t *im = (iptv_mux_t*)mmi->mmi_mux;
assert(mmi == &im->mm_iptv_instance);
pthread_mutex_lock(&iptv_lock);
if (!im->mm_active) {
/* HTTP */
if (!strcmp(im->mm_iptv_url, "http"))
ret = iptv_input_start_http(im);
/* OK */
if (!ret) {
struct epoll_event ev;
memset(&ev, 0, sizeof(ev));
ev.events = EPOLLIN;
ev.data.fd = im->mm_iptv_fd;
epoll_ctl(iptv_poll_fd, EPOLL_CTL_ADD, im->mm_iptv_fd, &ev);
im->mm_active = mmi;
}
}
pthread_mutex_unlock(&iptv_lock);
return ret;
}
static void
iptv_input_stop_mux ( mpegts_input_t *mi )
{
}
static int
iptv_input_is_free ( mpegts_input_t *mi )
{
return 1; // unlimited number of muxes
}
static int
iptv_input_current_weight ( mpegts_input_t *mi )
{
return 0; // unlimited number of muxes
}
static void *
iptv_input_thread ( void *aux )
{
#if 0
int nfds, fd;
uint8_t tsb[65536];
struct epoll_event ev;
iptv_mux_t *im;
mpegts_mux_t *mm;
while ( 1 ) {
nfds = epoll_wait(iptv_poll_fd, &ev, 1, -1);
if ( nfds < 0 ) {
tvhlog(LOG_ERR, "iptv", "epoll() error %s, sleeping 1 second",
strerror(errno));
sleep(1);
continue;
} else if ( nfds == 0 ) {
continue;
}
/* Read data */
fd = ev.data.fd;
r = read(fd, tsb+c, sizeof(tsb)-c);
/* Error */
if (r < 0) {
tvhlog(LOG_ERR, "iptv", "read() error %s", strerror(errno));
// TODO: close and remove?
continue;
}
pthread_mutex_lock(&iptv_lock);
/* Find mux */
LIST_FOREACH(mm, &iptv_network.mn_muxes, mm_network_link)
if (((iptv_mux_t*)mm)->im_fd == fd)
break;
if (!mm) {
pthread_mutex_unlock(&iptv_lock);
continue;
}
im = (iptv_mux_t*)mm;
/* Raw TS */
if (!strncmp(im->mm_iptv_url, "http", 4)) {
mpegts_input_recv_packets((mpegts_input_t*)&iptv_input,
&im->mm_mux_instance,
tsb, c, NULL, NULL);
}
pthread_mutex_lock(&iptv_unlock);
}
#endif
return NULL;
}
/*
* Network definition
*/
extern const idclass_t mpegts_network_class;
const idclass_t iptv_network_class = {
.ic_super = &mpegts_network_class,
.ic_class = "iptv_network",
.ic_caption = "IPTV Network",
.ic_properties = (const property_t[]){
}
};
static mpegts_service_t *
iptv_network_create_service
( mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid )
{
return NULL;
}
/*
* Intialise and load config
*/
void iptv_init ( void )
{
/* Init Input */
#if 0
mpegts_input_init((mpegts_input_t*)&iptv_input,
&itpv_input_class, NULL);
#endif
iptv_input.mi_start_mux = iptv_input_start_mux;
iptv_input.mi_stop_mux = iptv_input_stop_mux;
iptv_input.mi_is_free = iptv_input_is_free;
iptv_input.mi_current_weight = iptv_input_current_weight;
#if 0 // Use defaults
iptv_input.mi_open_service = iptv_input_open_service;
iptv_input.mi_close_sevice = iptv_input_close_service;
#endif
/* Init Network */
#if 0
mpegts_network_init((mpegts_network_t*)&iptv_network,
&iptv_network_class, NULL);
#endif
iptv_network.mn_network_name = strdup("IPTV Network");
iptv_network.mn_create_service = iptv_network_create_service;
/* Link */
iptv_input.mi_network = (mpegts_network_t*)&iptv_network;
//iptv_network.mn_input = (mpegts_input_t*)&iptv_input;
/* Setup thread */
// TODO: could set this up only when needed
iptv_poll_fd = epoll_create(10);
pthread_mutex_init(&iptv_lock, NULL);
pthread_create(&iptv_thread, NULL, iptv_input_thread, NULL);
/* Load config */
iptv_mux_load_all();
}
/******************************************************************************
* Editor Configuration
*
* vim:sts=2:ts=2:sw=2:et
*****************************************************************************/

View file

@ -0,0 +1,113 @@
/*
* IPTV Input
*
* Copyright (C) 2013 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 "iptv_private.h"
#include "settings.h"
/*
* Class
*/
extern const idclass_t mpegts_mux_class;
extern const idclass_t mpegts_mux_instance_class;
const idclass_t iptv_mux_class =
{
.ic_super = &mpegts_mux_class,
.ic_class = "iptv_mux",
.ic_caption = "IPTV Multiplex",
.ic_properties = (const property_t[]){
{ PROPDEF1("iptv_url", "URL",
PT_STR, iptv_mux_t, mm_iptv_url) },
#if 0
{ PROPDEF1("iptv_interface", "Interface",
PT_STR, iptv_mux_t, mm_iptv_interface) },
#endif
}
};
/*
* Create
*/
iptv_mux_t *
iptv_mux_create ( const char *uuid, const char *url )
{
/* Create Mux */
iptv_mux_t *im =
mpegts_mux_create(iptv_mux, NULL,
(mpegts_network_t*)&iptv_network,
MM_ONID_NONE, MM_TSID_NONE);
if (url)
im->mm_iptv_url = strdup(url);
htsbuf_queue_init(&im->mm_iptv_spill, 65536);
/* Create Instance */
mpegts_mux_instance_create0(&im->mm_iptv_instance,
&mpegts_mux_instance_class,
NULL,
(mpegts_input_t*)&iptv_input,
(mpegts_mux_t*)im);
return im;
}
/*
* Load
*/
static void
iptv_mux_load_one ( iptv_mux_t *im, htsmsg_t *c )
{
const char *str;
/* Load core */
mpegts_mux_load_one((mpegts_mux_t*)im, c);
/* URL */
if ((str = htsmsg_get_str(c, "url")))
tvh_str_update(&im->mm_iptv_url, str);
}
void
iptv_mux_load_all ( void )
{
htsmsg_t *s, *m;
htsmsg_field_t *f;
iptv_mux_t *im;
if ((s = hts_settings_load_r(1, "input/mpegts/iptv/muxes"))) {
HTSMSG_FOREACH(f, s) {
if (!(m = htsmsg_get_map_by_field(f))) {
tvhlog(LOG_ERR, "iptv", "failed to load mux config %s", f->hmf_name);
continue;
}
/* Create */
im = iptv_mux_create(f->hmf_name, NULL);
if (!im) {
tvhlog(LOG_ERR, "iptv", "failed to load mux config %s", f->hmf_name);
continue;
}
/* Configure */
iptv_mux_load_one(im, m);
/* Load services */
iptv_service_load_all(im, f->hmf_name);
}
}
}

View file

@ -0,0 +1,74 @@
/*
* IPTV Input
*
* Copyright (C) 2013 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 __IPTV_PRIVATE_H__
#define __IPTV_PRIVATE_H__
#include "input/mpegts.h"
#include "input/mpegts/iptv.h"
#include "htsbuf.h"
typedef struct iptv_input iptv_input_t;
typedef struct iptv_network iptv_network_t;
typedef struct iptv_mux iptv_mux_t;
typedef struct iptv_service iptv_service_t;
struct iptv_input
{
mpegts_input_t;
};
struct iptv_network
{
mpegts_network_t;
};
struct iptv_mux
{
mpegts_mux_t;
int mm_iptv_fd;
htsbuf_queue_t mm_iptv_spill;
mpegts_mux_instance_t mm_iptv_instance;
char *mm_iptv_url;
};
iptv_mux_t* iptv_mux_create ( const char *uuid, const char *url );
struct iptv_service
{
mpegts_service_t;
};
iptv_service_t *iptv_service_create
( const char *uuid, iptv_mux_t *im, uint16_t sid, uint16_t pmt_pid );
extern iptv_input_t iptv_input;
extern iptv_network_t iptv_network;
void iptv_mux_load_all ( void );
void iptv_service_load_all ( iptv_mux_t *im, const char *n );
#endif /* __IPTV_PRIVATE_H__ */
/******************************************************************************
* Editor Configuration
*
* vim:sts=2:ts=2:sw=2:et
*****************************************************************************/

View file

@ -0,0 +1,74 @@
/*
* IPTV Input
*
* Copyright (C) 2013 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 "iptv_private.h"
#include "settings.h"
extern const idclass_t mpegts_service_class;
/*
* Create
*/
iptv_service_t *
iptv_service_create
( const char *uuid, iptv_mux_t *im, uint16_t onid, uint16_t tsid )
{
iptv_service_t *is = (iptv_service_t*)
mpegts_service_create0(calloc(1, sizeof(mpegts_service_t)),
&mpegts_service_class, uuid,
(mpegts_mux_t*)im, onid, tsid);
return is;
}
/*
* Load
*/
static void
iptv_service_load_one ( iptv_service_t *is, htsmsg_t *c )
{
/* Load core */
mpegts_service_load_one((mpegts_service_t*)is, c);
}
void
iptv_service_load_all ( iptv_mux_t *im, const char *n )
{
htsmsg_t *s, *c;
htsmsg_field_t *f;
iptv_service_t *is;
if ((s = hts_settings_load_r(1, "input/mpegts/iptv/muxes/%s/services", n))) {
HTSMSG_FOREACH(f, s) {
if (!(c = htsmsg_get_map_by_field(f))) {
tvhlog(LOG_ERR, "iptv", "failed to load svc config %s", f->hmf_name);
continue;
}
/* Create */
if (!(is = iptv_service_create(f->hmf_name, im, 0, 0))) {
tvhlog(LOG_ERR, "iptv", "failed to load svc config %s", f->hmf_name);
continue;
}
/* Load */
iptv_service_load_one(is, c);
}
}
}