Lots more reworking and organisation
Heading towards the start of a tsfile based system that will be both a useful debugging tool and also a useful starting point for the generic mpegts framework
This commit is contained in:
parent
b708e28d42
commit
378b3a6b63
20 changed files with 749 additions and 38 deletions
19
Makefile
19
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 \
|
||||
|
|
3
configure
vendored
3
configure
vendored
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
31
src/input.h
Normal file
31
src/input.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* TVheadend
|
||||
* Copyright (C) 2007 - 2010 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/>.
|
||||
*/
|
||||
|
||||
#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__ */
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -16,7 +16,38 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "mpegts_input.h"
|
||||
#include "input/mpegts.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
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
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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
|
||||
*****************************************************************************/
|
45
src/input/mpegts/mpegts_network.c
Normal file
45
src/input/mpegts/mpegts_network.c
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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
|
||||
*****************************************************************************/
|
|
@ -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
|
||||
}
|
||||
|
|
35
src/input/mpegts/tsfile/rawts_input.h
Normal file
35
src/input/mpegts/tsfile/rawts_input.h
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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
|
||||
*****************************************************************************/
|
70
src/input/mpegts/tsfile/tsfile.c
Normal file
70
src/input/mpegts/tsfile/tsfile.c
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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
|
||||
*****************************************************************************/
|
35
src/input/mpegts/tsfile/tsfile.h
Normal file
35
src/input/mpegts/tsfile/tsfile.h
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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
|
||||
*****************************************************************************/
|
211
src/input/mpegts/tsfile/tsfile_input.c
Normal file
211
src/input/mpegts/tsfile/tsfile_input.c
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "tvheadend.h"
|
||||
#include "tsfile_private.h"
|
||||
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
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
|
||||
*****************************************************************************/
|
39
src/input/mpegts/tsfile/tsfile_mux.c
Normal file
39
src/input/mpegts/tsfile/tsfile_mux.c
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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
|
||||
*****************************************************************************/
|
59
src/input/mpegts/tsfile/tsfile_private.h
Normal file
59
src/input/mpegts/tsfile/tsfile_private.h
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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
|
||||
*****************************************************************************/
|
34
src/input/mpegts/tsfile/tsfile_service.c
Normal file
34
src/input/mpegts/tsfile/tsfile_service.c
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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
|
||||
*****************************************************************************/
|
45
src/main.c
45
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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue