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) {