another swing back to looking at the tsfile input as access to home is crap atm

This commit is contained in:
Adam Sutton 2013-04-30 13:46:47 +01:00
parent 523c47de37
commit 8e2ed3f466
13 changed files with 151 additions and 105 deletions

View file

@ -25,6 +25,9 @@
#if ENABLE_MPEGTS
#include "input/mpegts.h"
#if ENABLE_TSFILE
#include "input/mpegts/tsfile.h"
#endif
#endif
void input_init ( void );

View file

@ -23,8 +23,8 @@
#include "service.h"
#include "src/input/mpegts/psi.h"
#define MM_ONID_NONE 0xFFFF
#define MM_TSID_NONE 0xFFFF
#define MPEGTS_ONID_NONE 0xFFFF
#define MPEGTS_TSID_NONE 0xFFFF
/* Types */
typedef struct mpegts_table mpegts_table_t;
@ -406,6 +406,11 @@ mpegts_input_t *mpegts_input_create0
#define mpegts_input_create(t, u)\
(struct t*)mpegts_input_create0(calloc(1, sizeof(struct t)), t##_class, u)
#define mpegts_input_create1(u)\
mpegts_input_create0(calloc(1, sizeof(mpegts_input_t)),\
&mpegts_input_class, u)
mpegts_network_t *mpegts_network_create0
( mpegts_network_t *mn, const idclass_t *idc, const char *uuid,
const char *name );
@ -426,6 +431,9 @@ mpegts_mux_t *mpegts_mux_create0
(struct type*)mpegts_mux_create0(calloc(1, sizeof(struct type)),\
&type##_class, uuid,\
mn, onid, tsid)
#define mpegts_mux_create1(uuid, mn, onid, tsid)\
mpegts_mux_create0(calloc(1, sizeof(mpegts_mux_t)), &mpegts_mux_class, uuid,\
mn, onid, tsid)
void mpegts_mux_initial_scan_done ( mpegts_mux_t *mm );
@ -470,11 +478,14 @@ mpegts_service_t *mpegts_service_create0
( mpegts_service_t *ms, const idclass_t *class, const char *uuid,
mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid );
/* Create */
#define mpegts_service_create(t, u, m, s, p)\
(struct t*)mpegts_service_create0(calloc(1, sizeof(struct t)),\
&t##_class, u, m, s, p)
#define mpegts_service_create1(u, m, s, p)\
mpegts_service_create0(calloc(1, sizeof(mpegts_service_t)),\
&mpegts_service_class, u, m, s, p)
void mpegts_service_load_one ( mpegts_service_t *ms, htsmsg_t *c );
mpegts_service_t *mpegts_service_find ( mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid, const char *uuid, int *save );

View file

@ -54,7 +54,7 @@ mpegts_input_recv_packets
mpegts_mux_t *mm = mmi->mmi_mux;
assert(mmi->mmi_input == mi);
assert(mm != NULL);
tvhtrace("mpegts", "recv_packets tsb=%p, len=%d, pcr=%p, pcr_pid=%p",
tvhtrace("tsdemux", "recv_packets tsb=%p, len=%d, pcr=%p, pcr_pid=%p",
tsb, (int)len, pcr, pcr_pid);
/* Not enough data */
@ -81,6 +81,7 @@ mpegts_input_recv_packets
/* Sync */
if ( tsb[i] == 0x47 ) {
int pid = ((tsb[i+1] & 0x1f) << 8) | tsb[i+2];
tvhtrace("tsdemux", "recv_packet for pid %04X (%d)", pid, pid);
/* SI data */
if (mm->mm_table_filter[pid]) {
@ -116,9 +117,9 @@ mpegts_input_recv_packets
/* Re-sync */
} else {
// TODO: set flag (to avoid spam)
tvhlog(LOG_DEBUG, "mpegts", "%s ts sync lost", "TODO");
tvhlog(LOG_DEBUG, "tsdemux", "%s ts sync lost", "TODO");
if (ts_resync(tsb, &len, &i)) break;
tvhlog(LOG_DEBUG, "mpegts", "%s ts sync found", "TODO");
tvhlog(LOG_DEBUG, "tsdemux", "%s ts sync found", "TODO");
}
}
@ -191,10 +192,8 @@ mpegts_input_table_thread ( void *aux )
int
mpegts_input_is_free ( mpegts_input_t *mi )
{
int r;
r = (LIST_FIRST(&mi->mi_mux_active) == NULL);
printf("mpegts_input_is_free(%p) = %d\n", mi, r);
return r;
mpegts_mux_instance_t *mmi = LIST_FIRST(&mi->mi_mux_active);
return mmi ? 0 : 1;
}
int

View file

@ -43,7 +43,6 @@ mpegts_mux_instance_create0
mmi->mmi_input = mi; // TODO: is this required?
LIST_INSERT_HEAD(&mm->mm_instances, mmi, mmi_mux_link);
printf("added to mm_instances\n");
return mmi;
}
@ -65,7 +64,7 @@ void mpegts_mux_set_onid ( mpegts_mux_t *mm, uint16_t onid, int force )
{
if (onid == mm->mm_onid)
return;
if (!force && mm->mm_onid != MM_ONID_NONE)
if (!force && mm->mm_onid != MPEGTS_ONID_NONE)
return;
mm->mm_onid = onid;
}
@ -74,7 +73,7 @@ void mpegts_mux_set_tsid ( mpegts_mux_t *mm, uint16_t tsid, int force )
{
if (tsid == mm->mm_tsid)
return;
if (!force && mm->mm_tsid != MM_ONID_NONE)
if (!force && mm->mm_tsid != MPEGTS_TSID_NONE)
return;
mm->mm_tsid = tsid;
}
@ -91,7 +90,8 @@ mpegts_mux_initial_scan_link ( mpegts_mux_t *mm )
TAILQ_INSERT_TAIL(&mn->mn_initial_scan_pending_queue, mm,
mm_initial_scan_link);
mn->mn_initial_scan_num++;
printf("initial_scan_num = %d\n", mn->mn_initial_scan_num);
tvhtrace("mpegts", "added mm %p to initial scan for mn %p pending %d",
mm, mn, mn->mn_initial_scan_num);
mpegts_network_schedule_initial_scan(mn);
}
@ -99,7 +99,7 @@ static void
mpegts_mux_initial_scan_timeout ( void *aux )
{
mpegts_mux_t *mm = aux;
tvhlog(LOG_DEBUG, "mpegts", "Initial scan timed out for %s", "TODO");
tvhlog(LOG_DEBUG, "mpegts", "initial scan timed out for mm %p", mm);
mpegts_mux_initial_scan_done(mm);
}
@ -122,12 +122,14 @@ mpegts_mux_start ( mpegts_mux_t *mm, const char *reason, int weight )
mpegts_network_t *mn = mm->mm_network;
mpegts_mux_instance_t *mmi;
printf("mpegts_mux_start(%p, %s, %d)\n", mm, reason, weight);
tvhtrace("mpegts", "mm %p starting for '%s' (weight %d)",
mm, reason, weight);
/* Already tuned */
if (mm->mm_active)
if (mm->mm_active) {
tvhtrace("mpegts", "mm %p already active", mm);
return 0;
printf("not already tuned\n");
}
/* Find */
// TODO: don't like this is unbounded, if for some reason mi_start_mux()
@ -135,12 +137,12 @@ mpegts_mux_start ( mpegts_mux_t *mm, const char *reason, int weight )
while (1) {
/* Find free input */
printf("checking for free input\n");
LIST_FOREACH(mmi, &mm->mm_instances, mmi_mux_link)
if (!mmi->mmi_tune_failed &&
!mmi->mmi_input->mi_is_free(mmi->mmi_input))
mmi->mmi_input->mi_is_free(mmi->mmi_input))
break;
printf("free input ?= %p\n", mmi);
if (mmi)
tvhtrace("mpegts", "found free mmi %p", mmi);
/* Try and remove a lesser instance */
if (!mmi) {
@ -155,6 +157,9 @@ mpegts_mux_start ( mpegts_mux_t *mm, const char *reason, int weight )
break;
}
if (mmi)
tvhtrace("mpegts", "found mmi %p to boot", mmi);
/* No free input */
if (!mmi)
return SM_CODE_NO_FREE_ADAPTER;
@ -182,7 +187,8 @@ mpegts_mux_open_table ( mpegts_mux_t *mm, mpegts_table_t *mt )
if (mt->mt_pid >= 0x2000)
return;
if (!mm->mm_table_filter[mt->mt_pid])
printf("table opened %04X\n", mt->mt_pid);
tvhtrace("mpegts", "mm %p opened table pid %04X (%d)",
mm, mt->mt_pid, mt->mt_pid);
mm->mm_table_filter[mt->mt_pid] = 1;
}
@ -191,8 +197,9 @@ mpegts_mux_close_table ( mpegts_mux_t *mm, mpegts_table_t *mt )
{
if (mt->mt_pid >= 0x2000)
return;
tvhtrace("mpegts", "mm %p closed table pid %04X (%d)",
mm, mt->mt_pid, mt->mt_pid);
mm->mm_table_filter[mt->mt_pid] = 0;
printf("table closed %04X\n", mt->mt_pid);
}
void

View file

@ -28,13 +28,19 @@ const idclass_t mpegts_network_class =
}
};
static mpegts_mux_t *
mpegts_network_create_mux
( mpegts_mux_t *mm, uint16_t sid, uint16_t tsid, void *aux )
{
return NULL;
}
static void
mpegts_network_initial_scan(void *aux)
{
mpegts_network_t *mn = aux;
mpegts_mux_t *mm;
printf("mpegts_network_initial_scan(%p)\n", aux);
while((mm = TAILQ_FIRST(&mn->mn_initial_scan_pending_queue)) != NULL) {
assert(mm->mm_initial_scan_status == MM_SCAN_PENDING);
if (mm->mm_start(mm, "initial scan", 1))
@ -63,6 +69,7 @@ mpegts_network_create0
const char *netname )
{
idnode_insert(&mn->mn_id, uuid, idc);
mn->mn_create_mux = mpegts_network_create_mux;
mn->mn_network_name = strdup(netname);
TAILQ_INIT(&mn->mn_initial_scan_pending_queue);
TAILQ_INIT(&mn->mn_initial_scan_current_queue);

View file

@ -248,7 +248,6 @@ mpegts_service_create0
mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid )
{
service_create0((service_t*)s, class, uuid, S_MPEG_TS);
printf("mpegts_service_create0 = %p\n", s);
/* Create */
tvhlog(LOG_DEBUG, "mpegts", "Add service %04X on %s", sid, "TODO");

View file

@ -21,6 +21,26 @@
#include <assert.h>
static void
mpegts_table_fastswitch ( mpegts_mux_t *mm )
{
mpegts_table_t *mt;
if(mm->mm_initial_scan_status == MM_SCAN_DONE)
return;
LIST_FOREACH(mt, &mm->mm_tables, mt_link)
if((mt->mt_flags & MT_QUICKREQ) && mt->mt_count == 0)
return;
// TODO:
//dvb_mux_save(dm);
tvhlog(LOG_DEBUG, "mpegts", "initial scan for mm %p done", mm);
mpegts_mux_initial_scan_done(mm);
}
void
mpegts_table_dispatch
( const uint8_t *sec, size_t r, void *aux )
@ -65,10 +85,8 @@ mpegts_table_dispatch
if(ret == 0)
mt->mt_count++;
/* TODO
if(mt->mt_flags & TDT_QUICKREQ)
dvb_table_fastswitch(tdmi);
*/
if(mt->mt_flags & MT_QUICKREQ)
mpegts_table_fastswitch(mt->mt_mux);
}
void
@ -109,6 +127,9 @@ mpegts_table_add
mt->mt_opaque == opaque )
return;
tvhtrace("mpegts", "add %s table %02X/%02X (%d) pid %04X (%d)",
name, tableid, mask, tableid, pid, pid);
/* Create */
mt = calloc(1, sizeof(mpegts_table_t));
mt->mt_refcount = 1;

View file

@ -20,35 +20,28 @@
#include "tvheadend.h"
#include "input.h"
#include "channels.h"
#include "tsfile.h"
#include "tsfile_private.h"
extern const idclass_t mpegts_service_class;
static mpegts_network_t *tsfile_network;
LIST_HEAD(,mpegts_input) tsfile_inputs;
/*
* Cannot create muxes
* Globals
*/
static mpegts_mux_t *
tsfile_network_create_mux
( mpegts_mux_t *src, uint16_t onid, uint16_t tsid, void *aux )
{
return NULL;
}
mpegts_network_t tsfile_network;
mpegts_input_list_t tsfile_inputs;
extern const idclass_t mpegts_service_class;
extern const idclass_t mpegts_network_class;
/*
* Service creation
* Network definition
*/
static mpegts_service_t *
tsfile_network_create_service
( mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid )
{
static int t = 0;
mpegts_service_t *s = mpegts_service_create0(sizeof(mpegts_service_t),
&mpegts_service_class,
NULL, mm, sid, pmt_pid);
mpegts_service_t *s = mpegts_service_create1(NULL, mm, sid, pmt_pid);
// TODO: HACK: REMOVE ME
if (s) {
char buf[128];
sprintf(buf, "channel-%d", t);
@ -67,15 +60,19 @@ void tsfile_init ( int tuners )
mpegts_input_t *mi;
/* Shared network */
tsfile_network = mpegts_network_create0(NULL, "tsfile network");
tsfile_network->mn_create_mux = tsfile_network_create_mux;
tsfile_network->mn_create_service = tsfile_network_create_service;
mpegts_network_create0(&tsfile_network, &mpegts_network_class, NULL,
"TSfile Network");
tsfile_network.mn_create_service = tsfile_network_create_service;
/* Create inputs */
for (i = 0; i < tuners; i++) {
mi = tsfile_input_create();
mi->mi_network = tsfile_network;
LIST_INSERT_HEAD(&tsfile_inputs, mi, mi_global_link);
/* IPTV like setup */
if (tuners <= 0) {
mi = tsfile_input_create(0);
mpegts_network_add_input(&tsfile_network, mi);
} else {
for (i = 0; i < tuners; i++) {
mi = tsfile_input_create(i+1);
mpegts_network_add_input(&tsfile_network, mi);
}
}
}
@ -86,10 +83,10 @@ void tsfile_add_file ( const char *path )
{
mpegts_input_t *mi;
mpegts_mux_t *mm;
printf("tsfile_add_file(%s)\n", path);
tvhtrace("tsfile", "add file %s", path);
/* Create logical instance */
mm = tsfile_mux_create0(NULL, tsfile_network, MM_ONID_NONE, MM_TSID_NONE);
mm = tsfile_mux_create(&tsfile_network);
/* Create physical instance (for each tuner) */
LIST_FOREACH(mi, &tsfile_inputs, mi_global_link)

View file

@ -29,6 +29,9 @@
#include <unistd.h>
#include <errno.h>
#include <assert.h>
#include <sched.h>
extern const idclass_t mpegts_input_class;
static void *
tsfile_input_thread ( void *aux )
@ -40,25 +43,24 @@ tsfile_input_thread ( void *aux )
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;
mpegts_mux_instance_t *mmi;
tsfile_mux_instance_t *tmi;
/* Open file */
printf("waiting for lock..\n");
pthread_mutex_lock(&global_lock);
printf("got lock\n");
if ((mmi = LIST_FIRST(&mi->mi_mux_active))) {
tsfile_mux_instance_t *tmi = (tsfile_mux_instance_t*)mmi;
tmi = (tsfile_mux_instance_t*)mmi;
fd = tvh_open(tmi->mmi_tsfile_path, O_RDONLY | O_NONBLOCK, 0);
if (fd == -1)
tvhlog(LOG_ERR, "tsfile", "open(%s) failed %d (%s)",
tmi->mmi_tsfile_path, errno, strerror(errno));
else
tvhtrace("tsfile", "adapter %d opened %s", mi->mi_instance, tmi->mmi_tsfile_path);
}
pthread_mutex_unlock(&global_lock);
if (fd == -1) return NULL;
printf("file opened = %d\n", fd);
/* Polling */
memset(&ev, 0, sizeof(ev));
@ -77,7 +79,8 @@ printf("got lock\n");
/* Check for extra (incomplete) packet at end */
rem = st.st_size % 188;
len = 0;
printf("file size = %lu, rem = %lu\n", st.st_size, rem);
tvhtrace("tsfile", "adapter %d file size %"PRIsize_t " rem %"PRIsize_t,
mi->mi_instance, st.st_size, rem);
/* Process input */
while (1) {
@ -101,6 +104,7 @@ printf("file size = %lu, rem = %lu\n", st.st_size, rem);
if (len == st.st_size) {
len = 0;
c -= rem;
//tvhtrace("tsfile", "adapter %d reached eof, resetting", mi->mi_instance);
lseek(fd, 0, SEEK_SET);
pcr_last = PTS_UNSET;
}
@ -108,7 +112,8 @@ printf("file size = %lu, rem = %lu\n", st.st_size, rem);
/* Process */
if (c >= 0) {
pcr = PTS_UNSET;
pos = mpegts_input_recv_packets(mi, mmi, tsb, c, &pcr, &pcr_pid);
pos = mpegts_input_recv_packets(mi, mmi, tsb, c, &pcr, &tmi->mmi_tsfile_pcr_pid);
printf("pcr = %lu, pcr_pid = %d\n", pcr, tmi->mmi_tsfile_pcr_pid);
/* Delay */
if (pcr != PTS_UNSET) {
@ -129,6 +134,7 @@ printf("file size = %lu, rem = %lu\n", st.st_size, rem);
pcr_last_realtime = getmonoclock();
}
}
sched_yield();
}
exit:
@ -138,11 +144,9 @@ exit:
}
static void
tsfile_input_stop_mux ( mpegts_input_t *mi )
tsfile_input_stop_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi )
{
int err;
mpegts_mux_instance_t *mmi = LIST_FIRST(&mi->mi_mux_active);
assert(mmi != NULL);
/* Stop thread */
if (mi->mi_thread_pipe.rd != -1) {
@ -164,17 +168,20 @@ tsfile_input_start_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *t )
struct stat st;
mpegts_mux_t *mm = t->mmi_mux;
tsfile_mux_instance_t *mmi = (tsfile_mux_instance_t*)t;
printf("tsfile_input_start_mux(%p, %p)\n", mi, t);
tvhtrace("tsfile", "adapter %d starting mmi %p", mi->mi_instance, mmi);
/* Already tuned */
#if 0
if (mmi->mmi_mux->mm_active == t) {
tvhtrace("tsfile", "mmi %p is already active", mmi);
return 0;
}
assert(mmi->mmi_mux->mm_active == NULL);
assert(LIST_FIRST(&mi->mi_mux_active) == NULL);
#endif
/* Check file is accessible */
if (lstat(mmi->mmi_tsfile_path, &st)) {
printf("could not stat %s\n", mmi->mmi_tsfile_path);
tvhlog(LOG_ERR, "tsfile", "mmi %p could not stat %s",
mmi, mmi->mmi_tsfile_path);
mmi->mmi_tune_failed = 1;
return SM_CODE_TUNING_FAILED;
}
@ -205,32 +212,18 @@ tsfile_input_start_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *t )
return 0;
}
/* TODO: I think most of these can be moved to mpegts */
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 )
{
}
mpegts_input_t *
tsfile_input_create ( void )
tsfile_input_create ( int idx )
{
pthread_t tid;
mpegts_input_t *mi;
/* Create object */
mi = mpegts_input_create0(NULL);
mi = mpegts_input_create1(NULL);
mi->mi_instance = idx;
mi->mi_start_mux = tsfile_input_start_mux;
mi->mi_stop_mux = tsfile_input_stop_mux;
mi->mi_open_service = tsfile_input_open_service;
mi->mi_close_service = tsfile_input_close_service;
mi->mi_is_free = mpegts_input_is_free;
mi->mi_current_weight = mpegts_input_current_weight;
LIST_INSERT_HEAD(&tsfile_inputs, mi, mi_global_link);
/* Start table thread */
pthread_create(&tid, NULL, mpegts_input_table_thread, mi);

View file

@ -17,29 +17,31 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tsfile.h"
#include "tsfile_private.h"
extern const idclass_t mpegts_mux_class;
extern const idclass_t mpegts_service_class;
extern const idclass_t mpegts_mux_instance_class;
tsfile_mux_instance_t *
tsfile_mux_instance_create
( const char *path, mpegts_input_t *mi, mpegts_mux_t *mm )
{
tsfile_mux_instance_t *mmi = (tsfile_mux_instance_t*)
mpegts_mux_instance_create0(sizeof(tsfile_mux_instance_t),
NULL, mi, mm);
mmi->mmi_tsfile_path = strdup(path);
printf("mmi craeated %p path %s\n", mmi, mmi->mmi_tsfile_path);
#define tsfile_mux_instance_class mpegts_mux_instance_class
tsfile_mux_instance_t *mmi =
mpegts_mux_instance_create(tsfile_mux_instance, NULL, mi, mm);
#undef tsfile_mux_instance_class
mmi->mmi_tsfile_path = strdup(path);
mmi->mmi_tsfile_pcr_pid = 0;
tvhtrace("tsfile", "mmi created %p path %s", mmi, mmi->mmi_tsfile_path);
return mmi;
}
mpegts_mux_t *
tsfile_mux_create0
( const char *uuid, mpegts_network_t *mn, uint16_t onid, uint16_t tsid )
tsfile_mux_create ( mpegts_network_t *mn )
{
mpegts_mux_t *mm = mpegts_mux_create0(NULL, mn, onid, tsid);
mpegts_mux_t *mm
= mpegts_mux_create1(NULL, mn, MPEGTS_ONID_NONE, MPEGTS_TSID_NONE);
tvhtrace("tsfile", "mm created %p", mm);
return mm;
}

View file

@ -22,6 +22,12 @@
#include "input/mpegts.h"
/*
* Globals
*/
extern mpegts_network_t tsfile_network;
extern mpegts_input_list_t tsfile_inputs;
/*
* Typedefs
*/
@ -43,21 +49,22 @@ struct tsfile_mux_instance
* File input
*/
char *mmi_tsfile_path; ///< Source file path
th_pipe_t mmi_tsfile_pipe; ///< Thread control pipe
char *mmi_tsfile_path; ///< Source file path
th_pipe_t mmi_tsfile_pipe; ///< Thread control pipe
uint16_t mmi_tsfile_pcr_pid; ///< Timing control
};
/*
* Prototypes
*/
mpegts_input_t *tsfile_input_create ( void );
mpegts_input_t *tsfile_input_create ( int idx );
tsfile_mux_instance_t *tsfile_mux_instance_create
( const char *path, mpegts_input_t *mi, mpegts_mux_t *mm );
struct mpegts_mux *
tsfile_mux_create0
( const char *uuid, struct mpegts_network *mn, uint16_t onid, uint16_t tsid );
mpegts_mux_t *
tsfile_mux_create ( mpegts_network_t *mn );
#endif /* __TVH_TSFILE_PRIVATE_H__ */

View file

@ -719,7 +719,7 @@ main(int argc, char **argv)
htsp_init(opt_bindaddr);
#if 0
#if ENABLE_TSFILE
if(opt_tsfile.num) {
tsfile_init(opt_tsfile_tuner ?: opt_tsfile.num);
for (i = 0; i < opt_tsfile.num; i++)