diff --git a/Makefile b/Makefile
index 9f7c6a60..62baeca2 100644
--- a/Makefile
+++ b/Makefile
@@ -149,6 +149,7 @@ SRCS += src/muxer.c \
# MPEGTS core
SRCS-$(CONFIG_MPEGTS) += \
src/input/mpegts/mpegts_input.c \
+ src/input/mpegts/mpegts_network.c \
src/input/mpegts/mpegts_mux.c \
src/input/mpegts/mpegts_service.c \
src/input/mpegts/psi.c \
@@ -168,14 +169,6 @@ SRCS-${CONFIG_TIMESHIFT} += \
src/timeshift/timeshift_writer.c \
src/timeshift/timeshift_reader.c \
-# IPTV
-SRCS-${CONFIG_IPTV} += \
- src/input/mepgts/iptv.c
-
-# RawTS
-SRCS-${CONFIG_RAWTS} += \
- src/input/mpegts/rawts/rawts.c
-
# DVB
SRCS-${CONFIG_LINUXDVB} += \
src/dvb/dvb.c \
@@ -198,6 +191,16 @@ SRCS-${CONFIG_LINUXDVB} += \
src/muxes.c \
src/tvadapters.c \
+# IPTV
+SRCS-${CONFIG_IPTV} += \
+ src/input/mepgts/iptv.c
+
+# TSfile
+SRCS-$(CONFIG_TSFILE) += \
+ src/input/mpegts/tsfile/tsfile.c \
+ src/input/mpegts/tsfile/tsfile_input.c \
+ src/input/mpegts/tsfile/tsfile_mux.c \
+
# Inotify
SRCS-${CONFIG_INOTIFY} += \
src/dvr/dvr_inotify.c \
diff --git a/configure b/configure
index aaa379b7..ddae4e05 100755
--- a/configure
+++ b/configure
@@ -20,6 +20,7 @@ OPTIONS=(
"v4l:yes"
"linuxdvb:yes"
"iptv:yes"
+ "tsfile:yes"
"dvbscan:yes"
"timeshift:yes"
"trace:yes"
@@ -195,7 +196,7 @@ fi
#
disable mpegts
disable mpegps
-if enabled linuxdvb || enabled iptv; then
+if enabled linuxdvb || enabled iptv || enabled tsfile; then
enable mpegts
fi
diff --git a/src/idnode.c b/src/idnode.c
index c41c3788..f4bddfa9 100644
--- a/src/idnode.c
+++ b/src/idnode.c
@@ -343,7 +343,7 @@ idnode_notify_title_changed(void *obj)
}
idnode_t *
-idnode_create ( size_t alloc, const idclass_t *class, const char *uuid )
+idnode_create0 ( size_t alloc, const idclass_t *class, const char *uuid )
{
idnode_t *self = calloc(1, alloc);
idnode_insert(self, uuid, class);
diff --git a/src/idnode.h b/src/idnode.h
index bec280dc..f5cf45c0 100644
--- a/src/idnode.h
+++ b/src/idnode.h
@@ -56,5 +56,8 @@ idnode_t *idnode_load ( htsmsg_field_t *cfg, void*(*create)(const char*) );
void idnode_load_all ( const char *path, void *(*create)(const char*) );
-idnode_t *idnode_create
+idnode_t *idnode_create0
( size_t alloc, const idclass_t *class, const char *uuid );
+
+#define idnode_create(c, uuid)\
+ (struct c*)idnode_create0(sizeof(struct c), &c##_class, uuid)
diff --git a/src/input.h b/src/input.h
new file mode 100644
index 00000000..f49e27d4
--- /dev/null
+++ b/src/input.h
@@ -0,0 +1,31 @@
+/*
+ * TVheadend
+ * Copyright (C) 2007 - 2010 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 __TVH_INPUT_H__
+#define __TVH_INPUT_H__
+
+#if ENABLE_MPEGPS
+#include "input/mpegps.h"
+#endif
+
+#if ENABLE_MPEGTS
+#include "input/mpegts.h"
+#include "input/mpegts/tsfile/tsfile.h" // TODO: move
+#endif
+
+#endif /* __TVH_INPUT_H__ */
diff --git a/src/input/mpegts.h b/src/input/mpegts.h
index 7b006f72..a6758b56 100644
--- a/src/input/mpegts.h
+++ b/src/input/mpegts.h
@@ -22,6 +22,9 @@
#include "service.h"
+#define MM_ONID_NONE 0xFFFF
+#define MM_TSID_NONE 0xFFFF
+
/* Types */
typedef struct mpegts_table mpegts_table_t;
typedef struct mpegts_network mpegts_network_t;
@@ -100,7 +103,7 @@ struct mpegts_network
*/
char *mn_network_name;
- uint16_t mn_network_id; // ONID/NID??
+ //uint16_t mn_network_id; // ONID/NID??
/*
* Scanning
@@ -139,7 +142,8 @@ struct mpegts_mux
LIST_ENTRY(mpegts_mux) mm_network_link;
mpegts_network_t *mm_network;
- uint16_t mm_mux_id;
+ uint16_t mm_onid;
+ uint16_t mm_tsid;
/*
* Services
@@ -287,16 +291,11 @@ mpegts_service_t * mpegts_service_create0
* Physical Network
* *************************************************************************/
-// TODO: do we need the concept of multiple physical networks that provide
-// the same logical network (this is common for DVB-T)
-
-struct mpegts_phy_network
-{
-};
-
/* Physical mux instance */
struct mpegts_mux_instance
{
+ idnode_t mmi_id;
+
LIST_ENTRY(mpegts_mux_instance) mmi_mux_link;
LIST_ENTRY(mpegts_mux_instance) mmi_active_link;
@@ -309,13 +308,24 @@ struct mpegts_mux_instance
/* Input source */
struct mpegts_input
{
+ idnode_t mi_id;
+
int mi_instance;
+ LIST_ENTRY(mpegts_input) mi_global_link;
+
LIST_HEAD(,service) mi_transports;
pthread_mutex_t mi_delivery_mutex;
+
+ mpegts_network_t *mi_network; // TODO: this may need altering for DVB-S
+ mpegts_mux_instance_t *mi_mux_current;
+
+ pthread_t mi_thread_id;
+ th_pipe_t mi_thread_pipe;
int (*mi_start_mux) (mpegts_input_t*,mpegts_mux_instance_t*);
+ void (*mi_stop_mux) (mpegts_input_t*);
void (*mi_open_service) (mpegts_input_t*,mpegts_service_t*);
void (*mi_close_service) (mpegts_input_t*,mpegts_service_t*);
void (*mi_open_table) (mpegts_input_t*,mpegts_table_t*);
@@ -324,6 +334,23 @@ struct mpegts_input
#endif /* __TVH_MPEGTS_H__ */
+/* ****************************************************************************
+ * Functions
+ * ***************************************************************************/
+
+mpegts_input_t *mpegts_input_create0
+ ( const char *uuid );
+
+mpegts_network_t *mpegts_network_create0
+ ( const char *uuid, const char *name );
+
+mpegts_mux_t *mpegts_mux_create0
+ ( const char *uuid, mpegts_network_t *net, uint16_t onid, uint16_t tsid );
+
+void mpegts_input_recv_packets
+ (mpegts_input_t *mi, const uint8_t *tsb, size_t len,
+ int64_t *pcr, uint16_t *pcr_pid);
+
/******************************************************************************
* Editor Configuration
*
diff --git a/src/input/mpegts/mpegts_input.c b/src/input/mpegts/mpegts_input.c
index 169fd262..c614758f 100644
--- a/src/input/mpegts/mpegts_input.c
+++ b/src/input/mpegts/mpegts_input.c
@@ -16,7 +16,38 @@
* along with this program. If not, see .
*/
-#include "mpegts_input.h"
+#include "input/mpegts.h"
+
+#include
+
+const idclass_t mpegts_input_class =
+{
+ .ic_class = "mpegts_input",
+ .ic_caption = "MPEGTS Input",
+ .ic_properties = (const property_t[]){
+ }
+};
+
+void
+mpegts_input_recv_packets
+ ( mpegts_input_t *mi, const uint8_t *tsb, size_t len,
+ int64_t *pcr, uint16_t *pcr_pid )
+{
+}
+
+mpegts_input_t*
+mpegts_input_create0 ( const char *uuid )
+{
+ mpegts_input_t *mi = idnode_create(mpegts_input, uuid);
+
+ /* Init mutex */
+ pthread_mutex_init(&mi->mi_delivery_mutex, NULL);
+
+ /* Init input thread control */
+ mi->mi_thread_pipe.rd = mi->mi_thread_pipe.wr = -1;
+
+ return mi;
+}
/******************************************************************************
* Editor Configuration
diff --git a/src/input/mpegts/mpegts_mux.c b/src/input/mpegts/mpegts_mux.c
index e69de29b..3a5ee3d7 100644
--- a/src/input/mpegts/mpegts_mux.c
+++ b/src/input/mpegts/mpegts_mux.c
@@ -0,0 +1,56 @@
+/*
+ * Tvheadend - MPEGTS multiplex
+ *
+ * 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 .
+ */
+
+#include "idnode.h"
+#include "queue.h"
+#include "input/mpegts.h"
+
+const idclass_t mpegts_mux_class =
+{
+ .ic_class = "mpegts_mux",
+ .ic_caption = "MPEGTS Multiplex",
+ .ic_properties = (const property_t[]){
+ }
+};
+
+mpegts_mux_t *
+mpegts_mux_create0
+ ( const char *uuid, mpegts_network_t *net, uint16_t onid, uint16_t tsid )
+{
+ mpegts_mux_t *mm = idnode_create(mpegts_mux, uuid);
+
+ /* Identification */
+ mm->mm_onid = onid;
+ mm->mm_tsid = tsid;
+
+ /* Add to network */
+ mm->mm_network = net;
+ mm->mm_initial_scan_status = MM_SCAN_PENDING;
+ TAILQ_INSERT_TAIL(&net->mn_initial_scan_pending_queue, mm,
+ mm_initial_scan_link);
+
+ return mm;
+}
+
+
+/******************************************************************************
+ * Editor Configuration
+ *
+ * vim:sts=2:ts=2:sw=2:et
+ *****************************************************************************/
diff --git a/src/input/mpegts/mpegts_network.c b/src/input/mpegts/mpegts_network.c
new file mode 100644
index 00000000..9c60425e
--- /dev/null
+++ b/src/input/mpegts/mpegts_network.c
@@ -0,0 +1,45 @@
+/*
+ * Tvheadend - MPEGTS input source
+ * 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 .
+ */
+
+#include "input/mpegts.h"
+
+const idclass_t mpegts_network_class =
+{
+ .ic_class = "mpegts_network",
+ .ic_caption = "MPEGTS Network",
+ .ic_properties = (const property_t[]){
+ }
+};
+
+
+mpegts_network_t *
+mpegts_network_create0
+ ( const char *uuid, const char *netname )
+{
+ mpegts_network_t *mn = idnode_create(mpegts_network, uuid);
+ mn->mn_network_name = strdup(netname);
+ TAILQ_INIT(&mn->mn_initial_scan_pending_queue);
+ TAILQ_INIT(&mn->mn_initial_scan_current_queue);
+ return mn;
+}
+
+/******************************************************************************
+ * Editor Configuration
+ *
+ * vim:sts=2:ts=2:sw=2:et
+ *****************************************************************************/
diff --git a/src/input/mpegts/mpegts_service.c b/src/input/mpegts/mpegts_service.c
index 75f715e6..18c0c9c9 100644
--- a/src/input/mpegts/mpegts_service.c
+++ b/src/input/mpegts/mpegts_service.c
@@ -92,12 +92,19 @@ mpegts_service_start(service_t *t, int instance)
if (mi == NULL)
return SM_CODE_UNDEFINED_ERROR;
+ /* Start Mux */
+ r = mi->mmi_input->mi_start_mux(mi->mmi_input, mi);
+
/* Start */
- if (!(r = mi->mmi_input->mi_start_mux(mi->mmi_input, mi))) {
+ if (!r) {
+
+ /* Add to active set */
pthread_mutex_lock(&mi->mmi_input->mi_delivery_mutex);
LIST_INSERT_HEAD(&mi->mmi_input->mi_transports, t, s_active_link);
s->s_dvb_active_input = mi->mmi_input;
pthread_mutex_unlock(&mi->mmi_input->mi_delivery_mutex);
+
+ /* Open service */
mi->mmi_input->mi_open_service(mi->mmi_input, s);
// TODO: revisit this
}
diff --git a/src/input/mpegts/tsfile/rawts_input.h b/src/input/mpegts/tsfile/rawts_input.h
new file mode 100644
index 00000000..a52d33d0
--- /dev/null
+++ b/src/input/mpegts/tsfile/rawts_input.h
@@ -0,0 +1,35 @@
+/*
+ * Tvheadend - TS file based input (debugging)
+ *
+ * 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 .
+ */
+
+#ifndef __TVH_TSFILE_INPUT_H__
+#define __TVH_TSFILE_INPUT_H__
+
+typedef struct tsfile_input
+{
+
+
+} tsfile_input_t;
+
+#endif /* __TVH_TSFILE_INPUT_H__ */
+
+/******************************************************************************
+ * Editor Configuration
+ *
+ * vim:sts=2:ts=2:sw=2:et
+ *****************************************************************************/
diff --git a/src/input/mpegts/tsfile/tsfile.c b/src/input/mpegts/tsfile/tsfile.c
new file mode 100644
index 00000000..b86ce65a
--- /dev/null
+++ b/src/input/mpegts/tsfile/tsfile.c
@@ -0,0 +1,70 @@
+/*
+ * Tvheadend - TS file input system
+ *
+ * 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 .
+ */
+
+#include "tsfile.h"
+#include "tsfile_private.h"
+
+static mpegts_network_t *tsfile_network;
+LIST_HEAD(,mpegts_input) tsfile_inputs;
+
+/*
+ * Initialise
+ */
+void tsfile_init ( int tuners )
+{
+ int i;
+ mpegts_input_t *mi;
+printf("tsfile_init(%d)\n", tuners);
+
+ /* Shared network */
+printf("create network\n");
+ tsfile_network = mpegts_network_create0(NULL, "tsfile network");
+
+ /* Create inputs */
+printf("create inputs\n");
+ for (i = 0; i < tuners; i++) {
+ mi = tsfile_input_create();
+ mi->mi_network = tsfile_network;
+ }
+}
+
+/*
+ * Add multiplex
+ */
+void tsfile_add_file ( const char *path )
+{
+ mpegts_input_t *mi;
+ mpegts_mux_t *mm;
+printf("tsfile_add_file(%s)\n", path);
+
+ /* Create logical instance */
+printf("create logical mux\n");
+ mm = mpegts_mux_create0(NULL, tsfile_network, MM_ONID_NONE, MM_TSID_NONE);
+
+printf("create physical mux\n");
+ /* Create physical instance (for each tuner) */
+ LIST_FOREACH(mi, &tsfile_inputs, mi_global_link)
+ tsfile_mux_instance_create(path, mi, mm);
+}
+
+/******************************************************************************
+ * Editor Configuration
+ *
+ * vim:sts=2:ts=2:sw=2:et
+ *****************************************************************************/
diff --git a/src/input/mpegts/tsfile/tsfile.h b/src/input/mpegts/tsfile/tsfile.h
new file mode 100644
index 00000000..0785a41a
--- /dev/null
+++ b/src/input/mpegts/tsfile/tsfile.h
@@ -0,0 +1,35 @@
+/*
+ * Tvheadend - TS file input system
+ *
+ * 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 .
+ */
+
+#ifndef __TVH_TSFILE_H__
+#define __TVH_TSFILE_H__
+
+/* Initialise system (with N tuners) */
+void tsfile_init ( int tuners );
+
+/* Add a new file (multiplex) */
+void tsfile_add_file ( const char *path );
+
+#endif /* __TVH_TSFILE_H__ */
+
+/******************************************************************************
+ * Editor Configuration
+ *
+ * vim:sts=2:ts=2:sw=2:et
+ *****************************************************************************/
diff --git a/src/input/mpegts/tsfile/tsfile_input.c b/src/input/mpegts/tsfile/tsfile_input.c
new file mode 100644
index 00000000..432f1755
--- /dev/null
+++ b/src/input/mpegts/tsfile/tsfile_input.c
@@ -0,0 +1,211 @@
+/*
+ * Tvheadend - TS file input system
+ *
+ * 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 .
+ */
+
+#include "tvheadend.h"
+#include "tsfile_private.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+static void *
+tsfile_input_thread ( void *aux )
+{
+ int fd = -1, efd, nfds;
+ size_t len, rem;
+ ssize_t c;
+ struct epoll_event ev;
+ struct stat st;
+ uint8_t tsb[188*10];
+ int64_t pcr, pcr_last = PTS_UNSET, pcr_last_realtime = 0;
+ uint16_t pcr_pid = 0;
+ mpegts_input_t *mi = aux;
+ tsfile_mux_instance_t *mmi;
+
+ /* Open file */
+ pthread_mutex_lock(&global_lock);
+ if (mi->mi_mux_current) {
+ mmi = (tsfile_mux_instance_t*)mi->mi_mux_current;
+ fd = tvh_open(mmi->mmi_tsfile_path, O_RDONLY | O_NONBLOCK, 0);
+ if (fd == -1) {
+ tvhlog(LOG_ERR, "tsfile", "open(%s) failed %d (%s)",
+ mmi->mmi_tsfile_path, errno, strerror(errno));
+ }
+ }
+ pthread_mutex_unlock(&global_lock);
+ if (fd == -1) return NULL;
+
+ /* Polling */
+ memset(&ev, 0, sizeof(ev));
+ efd = epoll_create(2);
+ ev.events = EPOLLIN;
+ ev.data.fd = mi->mi_thread_pipe.rd;
+ epoll_ctl(efd, EPOLL_CTL_ADD, ev.data.fd, &ev);
+
+ /* Get file length */
+ if (fstat(fd, &st)) {
+ tvhlog(LOG_ERR, "tsfile", "stat() failed %d (%s)",
+ errno, strerror(errno));
+ goto exit;
+ }
+
+ /* Check for extra (incomplete) packet at end */
+ rem = st.st_size % 188;
+ len = 0;
+
+ /* Process input */
+ while (1) {
+
+ /* Check for terminate */
+ nfds = epoll_wait(efd, &ev, 1, 0);
+ if (nfds == 1) break;
+
+ /* Read */
+ c = read(fd, tsb, sizeof(tsb));
+ if (c < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+ tvhlog(LOG_ERR, "tsfile", "read() error %d (%s)",
+ errno, strerror(errno));
+ break;
+ }
+ len += c;
+
+ /* Reset */
+ if (len == st.st_size) {
+ len = 0;
+ c -= rem;
+ lseek(fd, 0, SEEK_SET);
+ pcr_last = PTS_UNSET;
+ }
+
+ /* Process */
+ if (c >= 0) {
+ pcr = PTS_UNSET;
+ mpegts_input_recv_packets(mi, tsb, c, &pcr, &pcr_pid);
+
+ /* Delay */
+ if (pcr != PTS_UNSET) {
+ if (pcr_last != PTS_UNSET) {
+ struct timespec slp;
+ int64_t d = pcr - pcr_last;
+ if (d < 0)
+ d = 0;
+ else if (d > 90000)
+ d = 90000;
+ d *= 11;
+ d += pcr_last_realtime;
+ slp.tv_sec = (d / 1000000);
+ slp.tv_nsec = (d % 1000000) * 1000;
+ clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &slp, NULL);
+ }
+ pcr_last = pcr;
+ pcr_last_realtime = getmonoclock();
+ }
+ }
+ }
+
+exit:
+ close(efd);
+ close(fd);
+ return NULL;
+}
+
+static void
+tsfile_input_stop_mux ( mpegts_input_t *mi )
+{
+ int err;
+
+ /* Stop thread */
+ if (mi->mi_thread_pipe.rd != -1) {
+ tvhtrace("tsfile", "adapter %d stopping thread", mi->mi_instance);
+ err = tvh_write(mi->mi_thread_pipe.wr, "", 1);
+ assert(err != -1);
+ pthread_join(mi->mi_thread_id, NULL);
+ tvh_pipe_close(&mi->mi_thread_pipe);
+ tvhtrace("tsfile", "adapter %d stopped thread", mi->mi_instance);
+ }
+}
+
+static int
+tsfile_input_start_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *t )
+{
+ struct stat st;
+ tsfile_mux_instance_t *mmi = (tsfile_mux_instance_t*)t;
+
+ /* Check file is accessible */
+ if (lstat(mmi->mmi_tsfile_path, &st))
+ return SM_CODE_TUNING_FAILED;
+
+ /* Start thread */
+ if (mi->mi_thread_pipe.rd == -1) {
+ if (tvh_pipe(O_NONBLOCK, &mi->mi_thread_pipe)) {
+ tvhlog(LOG_ERR, "tsfile", "failed to create thread pipe");
+ return SM_CODE_TUNING_FAILED;
+ }
+ tvhtrace("tsfile", "adapter %d starting thread", mi->mi_instance);
+ pthread_create(&mi->mi_thread_id, NULL, tsfile_input_thread, mi);
+ }
+
+ return 0;
+}
+
+static void
+tsfile_input_open_service ( mpegts_input_t *mi, mpegts_service_t *t )
+{
+}
+
+static void
+tsfile_input_close_service ( mpegts_input_t *mi, mpegts_service_t *t )
+{
+}
+
+static void
+tsfile_input_open_table ( mpegts_input_t *mi, mpegts_table_t *mt )
+{
+}
+
+static void
+tsfile_input_close_table ( mpegts_input_t *mi, mpegts_table_t *mt )
+{
+}
+
+mpegts_input_t *
+tsfile_input_create ( void )
+{
+ mpegts_input_t *mi;
+ mi = mpegts_input_create0(NULL);
+ mi->mi_start_mux = tsfile_input_start_mux;
+ mi->mi_stop_mux = tsfile_input_stop_mux;
+ mi->mi_open_table = tsfile_input_open_table;
+ mi->mi_close_table = tsfile_input_close_table;
+ mi->mi_open_service = tsfile_input_open_service;
+ mi->mi_close_service = tsfile_input_close_service;
+ return mi;
+}
+
+/******************************************************************************
+ * Editor Configuration
+ *
+ * vim:sts=2:ts=2:sw=2:et
+ *****************************************************************************/
diff --git a/src/input/mpegts/tsfile/tsfile_mux.c b/src/input/mpegts/tsfile/tsfile_mux.c
new file mode 100644
index 00000000..d4cc2f7c
--- /dev/null
+++ b/src/input/mpegts/tsfile/tsfile_mux.c
@@ -0,0 +1,39 @@
+/*
+ * Tvheadend - TS file input system
+ *
+ * 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 .
+ */
+
+#include "tsfile_private.h"
+
+tsfile_mux_instance_t *
+tsfile_mux_instance_create
+ ( const char *path, mpegts_input_t *mi, mpegts_mux_t *mm )
+{
+ tsfile_mux_instance_t *mmi = NULL;
+ // super constructor
+#if 0
+ mmi->mmi_tsfile_path = strdup(path);
+#endif
+ return mmi;
+}
+
+
+/******************************************************************************
+ * Editor Configuration
+ *
+ * vim:sts=2:ts=2:sw=2:et
+ *****************************************************************************/
diff --git a/src/input/mpegts/tsfile/tsfile_private.h b/src/input/mpegts/tsfile/tsfile_private.h
new file mode 100644
index 00000000..62bbc36c
--- /dev/null
+++ b/src/input/mpegts/tsfile/tsfile_private.h
@@ -0,0 +1,59 @@
+/*
+ * Tvheadend - TS file private data
+ *
+ * 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 .
+ */
+
+#ifndef __TVH_TSFILE_PRIVATE_H__
+#define __TVH_TSFILE_PRIVATE_H__
+
+#include "input/mpegts.h"
+
+/*
+ * Typedefs
+ */
+typedef struct tsfile_mux_instance tsfile_mux_instance_t;
+
+/*
+ * Mux instance
+ */
+struct tsfile_mux_instance
+{
+ mpegts_mux_instance_t; ///< Parent obj
+
+ /*
+ * File input
+ */
+
+ char *mmi_tsfile_path; ///< Source file path
+ th_pipe_t mmi_tsfile_pipe; ///< Thread control pipe
+};
+
+/*
+ * Prototypes
+ */
+mpegts_input_t *tsfile_input_create ( void );
+
+tsfile_mux_instance_t *tsfile_mux_instance_create
+ ( const char *path, mpegts_input_t *mi, mpegts_mux_t *mm );
+
+#endif /* __TVH_TSFILE_PRIVATE_H__ */
+
+/******************************************************************************
+ * Editor Configuration
+ *
+ * vim:sts=2:ts=2:sw=2:et
+ *****************************************************************************/
diff --git a/src/input/mpegts/tsfile/tsfile_service.c b/src/input/mpegts/tsfile/tsfile_service.c
new file mode 100644
index 00000000..70999e27
--- /dev/null
+++ b/src/input/mpegts/tsfile/tsfile_service.c
@@ -0,0 +1,34 @@
+/*
+ * Tvheadend - TS file input service
+ *
+ * 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 .
+ */
+
+mpegts_service_t *tsfile_service_create ( const char *path )
+{
+ mpegts_service_t *s = mpegts_service_create(NULL);
+
+ s->s_dvb_service_id = 0;
+ s->s_dvb_pmt_pid = 0;
+ s->s_dvb_
+}
+
+
+/******************************************************************************
+ * Editor Configuration
+ *
+ * vim:sts=2:ts=2:sw=2:et
+ *****************************************************************************/
diff --git a/src/main.c b/src/main.c
index 8672371f..9ff4b413 100644
--- a/src/main.c
+++ b/src/main.c
@@ -48,11 +48,8 @@
#include "descrambler.h"
#include "dvr/dvr.h"
#include "htsp_server.h"
-//#include "rawtsinput.h"
#include "avahi.h"
-//#include "input/mpegts/linuxdvb.h"
-#include "input/mpegts/iptv.h"
-#include "input/mpegps/v4l.h"
+#include "input.h"
#include "service.h"
#include "trap.h"
#include "settings.h"
@@ -66,6 +63,12 @@
#endif
/* Command line option struct */
+typedef struct str_list
+{
+ int max;
+ int num;
+ char **str;
+} str_list_t;
typedef struct {
const char sopt;
const char *lopt;
@@ -73,7 +76,8 @@ typedef struct {
enum {
OPT_STR,
OPT_INT,
- OPT_BOOL
+ OPT_BOOL,
+ OPT_STR_LIST,
} type;
void *param;
} cmdline_opt_t;
@@ -415,7 +419,8 @@ main(int argc, char **argv)
opt_noacl = 0,
opt_trace = 0,
opt_fileline = 0,
- opt_ipv6 = 0;
+ opt_ipv6 = 0,
+ opt_tsfile_tuner = 0;
const char *opt_config = NULL,
*opt_user = NULL,
*opt_group = NULL,
@@ -426,9 +431,9 @@ main(int argc, char **argv)
*opt_dvb_adapters = NULL,
*opt_dvb_raw = NULL,
#endif
- *opt_rawts = NULL,
*opt_bindaddr = NULL,
*opt_subscribe = NULL;
+ str_list_t opt_tsfile = { .max = 10, .num = 0, .str = calloc(10, sizeof(char*)) };
cmdline_opt_t cmdline_opts[] = {
{ 0, NULL, "Generic Options", OPT_BOOL, NULL },
{ 'h', "help", "Show this page", OPT_BOOL, &opt_help },
@@ -475,14 +480,14 @@ main(int argc, char **argv)
{ 'A', "abort", "Immediately abort", OPT_BOOL, &opt_abort },
{ 0, "noacl", "Disable all access control checks",
OPT_BOOL, &opt_noacl },
-#if ENABLE_LINUXDVB
- { 'R', "dvbraw", "Use rawts file to create virtual adapter",
- OPT_STR, &opt_dvb_raw },
-#endif
- { 'r', "rawts", "Use rawts file to generate virtual services",
- OPT_STR, &opt_rawts },
{ 'j', "join", "Subscribe to a service permanently",
- OPT_STR, &opt_subscribe }
+ OPT_STR, &opt_subscribe },
+
+
+ { 0, NULL, "TODO: testing", OPT_BOOL, NULL },
+ { 0, "tsfile_tuners", "Number of tsfile tuners", OPT_INT, &opt_tsfile_tuner },
+ { 0, "tsfile", "tsfile input (mux file)", OPT_STR_LIST, &opt_tsfile },
+
};
/* Get current directory */
@@ -513,6 +518,11 @@ main(int argc, char **argv)
"option %s requires a value", opt->lopt);
else if (opt->type == OPT_INT)
*((int*)opt->param) = atoi(argv[i]);
+ else if (opt->type == OPT_STR_LIST) {
+ str_list_t *strl = opt->param;
+ if (strl->num < strl->max)
+ strl->str[strl->num++] = argv[i];
+ }
else
*((char**)opt->param) = argv[i];
@@ -720,8 +730,11 @@ main(int argc, char **argv)
htsp_init(opt_bindaddr);
- if(opt_rawts != NULL)
- printf("TODO: rawts_init(opt_rawts);\n");
+ if(opt_tsfile.num) {
+ tsfile_init(opt_tsfile_tuner ?: opt_tsfile.num);
+ for (i = 0; i < opt_tsfile.num; i++)
+ tsfile_add_file(opt_tsfile.str[i]);
+ }
if(opt_subscribe != NULL)
subscription_dummy_join(opt_subscribe, 1);
diff --git a/src/tvheadend.h b/src/tvheadend.h
index 801186fb..f97d4570 100644
--- a/src/tvheadend.h
+++ b/src/tvheadend.h
@@ -507,6 +507,8 @@ int tvh_socket(int domain, int type, int protocol);
int tvh_pipe(int flags, th_pipe_t *pipe);
+void tvh_pipe_close(th_pipe_t *pipe);
+
int tvh_write(int fd, const void *buf, size_t len);
void hexdump(const char *pfx, const uint8_t *data, int len);
diff --git a/src/wrappers.c b/src/wrappers.c
index 5b08d3ce..c9b79c1a 100644
--- a/src/wrappers.c
+++ b/src/wrappers.c
@@ -49,6 +49,15 @@ tvh_pipe(int flags, th_pipe_t *p)
return err;
}
+void
+tvh_pipe_close(th_pipe_t *p)
+{
+ close(p->rd);
+ close(p->wr);
+ p->rd = -1;
+ p->wr = -1;
+}
+
int
tvh_write(int fd, const void *buf, size_t len)
{