linuxdvb: starting to see data input working

there are a lot of hacks in at the moment, need to go through and tidy
everything up.
This commit is contained in:
Adam Sutton 2013-05-29 14:22:22 +01:00
parent 3cb6be346f
commit 51eeb9af0d
7 changed files with 239 additions and 67 deletions

View file

@ -236,7 +236,6 @@ linuxdvb_device_create0 ( const char *uuid, htsmsg_t *conf )
/* Create */
ld = calloc(1, sizeof(linuxdvb_device_t));
printf("create device %p\n", ld);
if (idnode_insert(&ld->mi_id, uuid, &linuxdvb_device_class)) {
free(ld);
return NULL;
@ -277,9 +276,6 @@ linuxdvb_device_find_by_hwid ( const char *hwid )
{
linuxdvb_hardware_t *lh;
LIST_FOREACH(lh, &linuxdvb_device_all, lh_parent_link) {
printf("hwid = %s\n", hwid);
printf("lh = %p\n", lh);
printf("devid = %s\n", ((linuxdvb_device_t*)lh)->ld_devid.di_id);
if (!strcmp(hwid, ((linuxdvb_device_t*)lh)->ld_devid.di_id))
return (linuxdvb_device_t*)lh;
}
@ -306,7 +302,6 @@ linuxdvb_device_find_by_adapter ( int a )
}
/* Copy device info */
printf("added dev info to %p\n", ld);
memcpy(&ld->ld_devid, &dev, sizeof(dev));
ld->lh_displayname = strdup(dev.di_id);
return ld;
@ -325,7 +320,6 @@ void linuxdvb_device_init ( int adapter_mask )
if (!(e = htsmsg_get_map_by_field(f))) continue;
if (!(e = htsmsg_get_map(e, "config"))) continue;
(void)linuxdvb_device_create0(f->hmf_name, e);
printf("created from config\n");
}
}

View file

@ -20,7 +20,14 @@
#include "tvheadend.h"
#include "linuxdvb_private.h"
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <linux/dvb/dmx.h>
/* **************************************************************************
* Class definitions
@ -123,6 +130,7 @@ linuxdvb_frontend_save ( linuxdvb_frontend_t *lfe, htsmsg_t *m )
htsmsg_add_str(m, "dvr_path", lfe->lfe_dvr_path);
}
#if 0
static int
linuxdvb_frontend_is_free ( mpegts_input_t *mi )
{
@ -144,6 +152,7 @@ linuxdvb_frontend_current_weight ( mpegts_input_t *mi )
#endif
return 0;
}
#endif
static void
linuxdvb_frontend_stop_mux
@ -151,15 +160,131 @@ linuxdvb_frontend_stop_mux
{
}
#if 0
static void *
linuxdvb_frontend_input_thread ( void *aux )
{
linuxdvb_frontend_t *lfe = aux;
mpegts_mux_instance_t *mmi;
int dmx = -1, dvr = -1;
uint8_t tsb[18800];
int pos = 0, nfds, efd;
ssize_t c;
struct epoll_event ev;
struct dmx_pes_filter_params dmx_param;
/* Get MMI */
pthread_mutex_lock(&global_lock);
mmi = LIST_FIRST(&lfe->mi_mux_active);
pthread_mutex_unlock(&global_lock);
if (mmi == NULL) return NULL;
/* Open DMX */
dmx = tvh_open(lfe->lfe_dmx_path, O_RDWR, 0);
if (dmx < 0) {
tvhlog(LOG_ERR, "linuxdvb", "failed to open %s", lfe->lfe_dmx_path);
return NULL;
}
memset(&dmx_param, 0, sizeof(dmx_param));
dmx_param.pid = 0x2000;
dmx_param.input = DMX_IN_FRONTEND;
dmx_param.output = DMX_OUT_TS_TAP;
dmx_param.pes_type = DMX_PES_OTHER;
dmx_param.flags = DMX_IMMEDIATE_START;
if(ioctl(dmx, DMX_SET_PES_FILTER, &dmx_param) == -1) {
tvhlog(LOG_ERR, "dvb",
"Unable to configure demuxer \"%s\" for all PIDs -- %s",
lfe->lfe_dmx_path, strerror(errno));
close(dmx);
return NULL;
}
/* Open DVR */
dvr = tvh_open(lfe->lfe_dvr_path, O_RDONLY | O_NONBLOCK, 0);
if (dvr < 0) {
close(dmx);
tvhlog(LOG_ERR, "linuxdvb", "failed to open %s", lfe->lfe_dvr_path);
return NULL;
}
/* Setup poll */
efd = epoll_create(2);
memset(&ev, 0, sizeof(ev));
ev.events = EPOLLIN;
ev.data.fd = dvr;
epoll_ctl(efd, EPOLL_CTL_ADD, ev.data.fd, &ev);
/* Read */
while (1) {
nfds = epoll_wait(efd, &ev, 1, 10);
if (nfds < 1) continue;
if (ev.data.fd != dvr) break;
/* Read */
c = read(dvr, tsb+pos, sizeof(tsb)-pos);
if (c < 0) {
if ((errno == EAGAIN) || (errno == EINTR))
continue;
if (errno == EOVERFLOW) {
tvhlog(LOG_WARNING, "linuxdvb", "read() EOVERFLOW");
continue;
}
tvhlog(LOG_ERR, "linuxdvb", "read() error %d (%s)",
errno, strerror(errno));
break;
}
/* Process */
pos = mpegts_input_recv_packets((mpegts_input_t*)lfe, mmi, tsb, c,
NULL, NULL);
}
//exit:
close(dmx);
close(dvr);
return NULL;
}
static void
linuxdvb_frontend_monitor ( void *aux )
{
linuxdvb_frontend_t *lfe = aux;
mpegts_mux_instance_t *mmi = LIST_FIRST(&lfe->mi_mux_active);
mpegts_mux_t *mm;
pthread_t tid;
if (!mmi) return;
mm = mmi->mmi_mux;
fe_status_t fe_status;
if (!ioctl(lfe->lfe_fe_fd, FE_READ_STATUS, &fe_status))
tvhtrace("mpegts", "fe_status = %02X", fe_status);
else
tvhtrace("mpegts", "fe_status = unknown");
if (fe_status & FE_HAS_LOCK) {
// Note: the lock
// Open pending services
pthread_create(&tid, NULL, linuxdvb_frontend_input_thread, lfe);
mpegts_table_add(mm, DVB_PAT_BASE, DVB_PAT_MASK, dvb_pat_callback,
NULL, "pat", MT_QUICKREQ | MT_CRC, DVB_PAT_PID);
mpegts_table_add(mm, DVB_SDT_BASE, DVB_SDT_MASK, dvb_sdt_callback,
NULL, "sdt", MT_QUICKREQ | MT_CRC, DVB_SDT_PID);
mpegts_table_add(mm, DVB_BAT_BASE, DVB_BAT_MASK, dvb_bat_callback,
NULL, "bat", MT_CRC, DVB_BAT_PID);
} else {
gtimer_arm_ms(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, 1000);
}
}
#if DVB_API_VERSION >= 5
static int
linuxdvb_frontend_tune
( linuxdvb_frontend_t *lfe, mpegts_mux_instance_t *mmi )
( linuxdvb_frontend_t *lfe, linuxdvb_mux_t *lm )
{
#if 0
struct dvb_frontend_event ev;
dvb_mux_conf_t *dmc = &lm->lm_tuning;
struct dvb_frontend_parameters *p = &dmc->dmc_fe_params;
int r;
@ -171,62 +296,60 @@ linuxdvb_frontend_tune
.num = 1,
.props = clear_p
};
if ((ioctl(tda->tda_fe_fd, FE_SET_PROPERTY, &clear_cmdseq)) != 0)
if ((ioctl(lfe->lfe_fe_fd, FE_SET_PROPERTY, &clear_cmdseq)) != 0)
return -1;
/* Tune */
struct dtv_property _dvbs_cmdargs[] = {
{ .cmd = DTV_DELIVERY_SYSTEM, .u.data = dmc->dmc_fe_delsys },
{ .cmd = DTV_FREQUENCY, .u.data = p->frequency },
{ .cmd = DTV_MODULATION, .u.data = dmc->dmc_fe_modulation },
{ .cmd = DTV_SYMBOL_RATE, .u.data = p->u.qpsk.symbol_rate },
{ .cmd = DTV_INNER_FEC, .u.data = p->u.qpsk.fec_inner },
{ .cmd = DTV_INVERSION, .u.data = INVERSION_AUTO },
{ .cmd = DTV_ROLLOFF, .u.data = dmc->dmc_fe_rolloff },
{ .cmd = DTV_PILOT, .u.data = PILOT_AUTO },
{ .cmd = DTV_DELIVERY_SYSTEM, .u.data = SYS_DVBT /*TODO: fix this*/ },
{ .cmd = DTV_FREQUENCY, .u.data = p->frequency },
{ .cmd = DTV_INVERSION, .u.data = p->inversion },
{ .cmd = DTV_BANDWIDTH_HZ, .u.data = 8000000 },// TODO: fix this
{ .cmd = DTV_CODE_RATE_HP, .u.data = p->u.ofdm.code_rate_HP },
{ .cmd = DTV_CODE_RATE_LP, .u.data = p->u.ofdm.code_rate_LP },
{ .cmd = DTV_MODULATION, .u.data = p->u.ofdm.constellation },
{ .cmd = DTV_TRANSMISSION_MODE, .u.data = p->u.ofdm.transmission_mode },
{ .cmd = DTV_GUARD_INTERVAL, .u.data = p->u.ofdm.guard_interval },
{ .cmd = DTV_HIERARCHY, .u.data = p->u.ofdm.hierarchy_information },
{ .cmd = DTV_TUNE },
};
struct dtv_properties _dvbs_cmdseq = {
.num = 9,
.num = 11,
.props = _dvbs_cmdargs
};
/* discard stale QPSK events */
while (1) {
if (ioctl(tda->tda_fe_fd, FE_GET_EVENT, &ev) == -1)
if (ioctl(lfe->lfe_fe_fd, FE_GET_EVENT, &ev) == -1)
break;
}
/* do tuning now */
r = ioctl(tda->tda_fe_fd, FE_SET_PROPERTY, &_dvbs_cmdseq);
r = ioctl(lfe->lfe_fe_fd, FE_SET_PROPERTY, &_dvbs_cmdseq);
return r;
#endif
return 0;
}
#else
static int
linuxdvb_frontend_tune
( linuxdvb_frontend_t *lfe, mpegts_mux_instance_t *mmi )
{
}
#endif
#endif
static int
linuxdvb_frontend_start_mux
( mpegts_input_t *mi, mpegts_mux_instance_t *mmi )
{
printf("fe_start(%p, %p)\n", mi, mmi);
return SM_CODE_TUNING_FAILED;
#if 0
int r;
linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi;
mpegts_mux_instance_t *cur = LIST_FIRST(&mi->mi_mux_active);
tvhtrace("mpegts", "linuxdvb_frontend_start_mux(%p, %p)", mi, mmi);
// Not sure if this is right place?
/* Currently active */
if (cur != NULL) {
@ -239,8 +362,16 @@ linuxdvb_frontend_start_mux
}
assert(LIST_FIRST(&mi->mi_mux_active) == NULL);
/* Open FE */
if (lfe->lfe_fe_fd <= 0) {
lfe->lfe_fe_fd = tvh_open(lfe->lfe_fe_path, O_RDWR | O_NONBLOCK, 0);
if (lfe->lfe_fe_fd <= 0) {
return SM_CODE_TUNING_FAILED;
}
}
/* Tune */
r = 0;//linuxdvb_frontend_tune(lfe, (linuxdvb_mux_t*)mmi);
r = linuxdvb_frontend_tune(lfe, (linuxdvb_mux_t*)mmi->mmi_mux);
/* Failed */
if (r != 0) {
@ -254,12 +385,11 @@ linuxdvb_frontend_start_mux
/* Start monitor */
time(&lfe->lfe_monitor);
lfe->lfe_monitor += 4;
//gtimer_arm_ms(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, 50);
gtimer_arm_ms(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, 50);
/* Send alert */
// TODO: should this be moved elsewhere?
#endif
return r;
}
static void
@ -281,6 +411,7 @@ linuxdvb_frontend_create0
uint32_t u32;
const char *str;
const idclass_t *idc;
pthread_t tid;
/* Get type */
if (conf) {
@ -313,12 +444,17 @@ linuxdvb_frontend_create0
lfe->mi_stop_mux = linuxdvb_frontend_stop_mux;
lfe->mi_open_service = linuxdvb_frontend_open_service;
lfe->mi_close_service = linuxdvb_frontend_close_service;
#if 0
lfe->mi_is_free = linuxdvb_frontend_is_free;
lfe->mi_current_weight = linuxdvb_frontend_current_weight;
#endif
/* Adapter link */
lfe->lh_parent = (linuxdvb_hardware_t*)la;
LIST_INSERT_HEAD(&la->lh_children, (linuxdvb_hardware_t*)lfe, lh_parent_link);
/* Start table thread */
pthread_create(&tid, NULL, mpegts_input_table_thread, lfe);
/* No conf */
if (!conf)

View file

@ -122,6 +122,7 @@ linuxdvb_mux_create_instances ( mpegts_mux_t *mm )
}
}
#if 0
static void
linuxdvb_mux_open_table ( mpegts_mux_t *mm, mpegts_table_t *mt )
{
@ -131,68 +132,69 @@ static void
linuxdvb_mux_close_table ( mpegts_mux_t *mm, mpegts_table_t *mt )
{
}
#endif
static const char *
dvb_mux_conf_load ( fe_type_t type, dvb_mux_conf_t *dmc, htsmsg_t *m )
{
//const char *s;
int r;
const char *s;
dmc->dmc_fe_params.inversion = INVERSION_AUTO;
htsmsg_get_u32(m, "frequency", &dmc->dmc_fe_params.frequency);
#if 0
switch(tda->tda_type) {
switch(type) {
case FE_OFDM:
s = htsmsg_get_str(m, "bandwidth");
if(s == NULL || (r = str2val(s, bwtab)) < 0)
if(s == NULL || (r = dvb_str2bw(s)) < 0)
return "Invalid bandwidth";
dmc->dmc_fe_params.u.ofdm.bandwidth = r;
s = htsmsg_get_str(m, "constellation");
if(s == NULL || (r = str2val(s, qamtab)) < 0)
if(s == NULL || (r = dvb_str2qam(s)) < 0)
return "Invalid QAM constellation";
dmc->dmc_fe_params.u.ofdm.constellation = r;
s = htsmsg_get_str(m, "transmission_mode");
if(s == NULL || (r = str2val(s, modetab)) < 0)
if(s == NULL || (r = dvb_str2mode(s)) < 0)
return "Invalid transmission mode";
dmc->dmc_fe_params.u.ofdm.transmission_mode = r;
s = htsmsg_get_str(m, "guard_interval");
if(s == NULL || (r = str2val(s, guardtab)) < 0)
if(s == NULL || (r = dvb_str2guard(s)) < 0)
return "Invalid guard interval";
dmc->dmc_fe_params.u.ofdm.guard_interval = r;
s = htsmsg_get_str(m, "hierarchy");
if(s == NULL || (r = str2val(s, hiertab)) < 0)
if(s == NULL || (r = dvb_str2hier(s)) < 0)
return "Invalid heirarchy information";
dmc->dmc_fe_params.u.ofdm.hierarchy_information = r;
s = htsmsg_get_str(m, "fec_hi");
if(s == NULL || (r = str2val(s, fectab)) < 0)
if(s == NULL || (r = dvb_str2fec(s)) < 0)
return "Invalid hi-FEC";
dmc->dmc_fe_params.u.ofdm.code_rate_HP = r;
s = htsmsg_get_str(m, "fec_lo");
if(s == NULL || (r = str2val(s, fectab)) < 0)
if(s == NULL || (r = dvb_str2fec(s)) < 0)
return "Invalid lo-FEC";
dmc->dmc_fe_params.u.ofdm.code_rate_LP = r;
break;
default:
return "Not yet supported";
}
#endif
return "Not yet supported";
return NULL;
}
linuxdvb_mux_t *
linuxdvb_mux_create0
( linuxdvb_network_t *ln, const char *uuid, htsmsg_t *conf )
( linuxdvb_network_t *ln,
uint16_t onid, uint16_t tsid, const dvb_mux_conf_t *dmc,
const char *uuid )
{
uint32_t u32;
const char *str;
htsmsg_t *c, *e;
htsmsg_field_t *f;
mpegts_mux_t *mm;
linuxdvb_mux_t *lm;
const idclass_t *idc;
mpegts_mux_t *mm;
/* Search for existing */
/* Class */
if (ln->ln_type == FE_QPSK)
@ -210,16 +212,44 @@ linuxdvb_mux_create0
/* Create */
if (!(mm = mpegts_mux_create0(calloc(1, sizeof(linuxdvb_mux_t)), idc, uuid,
(mpegts_network_t*)ln,
MPEGTS_ONID_NONE,
MPEGTS_TSID_NONE)))
(mpegts_network_t*)ln, onid, tsid)))
return NULL;
lm = (linuxdvb_mux_t*)mm;
memcpy(&((linuxdvb_mux_t*)mm)->lm_tuning, dmc, sizeof(dvb_mux_conf_t));
return (linuxdvb_mux_t*)mm;
}
linuxdvb_mux_t *
linuxdvb_mux_create1
( linuxdvb_network_t *ln, const char *uuid, htsmsg_t *conf )
{
uint32_t u32;
const char *str;
htsmsg_t *c, *e;
htsmsg_field_t *f;
linuxdvb_mux_t *lm;
dvb_mux_conf_t dmc;
/* Check tuning */
memset(&dmc, 0, sizeof(dmc));
if (conf) {
if ((str = dvb_mux_conf_load(ln->ln_type, &dmc, conf))) {
tvhlog(LOG_ERR, "linuxdvb", "failed to load mux config [%s]", str);
return NULL;
}
}
lm = linuxdvb_mux_create0(ln, MPEGTS_ONID_NONE,
MPEGTS_TSID_NONE, &dmc, uuid);
if (!lm) printf("OH DEAR\n");
if (!lm) return NULL;
/* Callbacks */
lm->mm_config_save = linuxdvb_mux_config_save;
#if 0
lm->mm_open_table = linuxdvb_mux_open_table;
lm->mm_close_table = linuxdvb_mux_close_table;
#endif
lm->mm_create_instances = linuxdvb_mux_create_instances;
/* No config */
@ -236,10 +266,7 @@ linuxdvb_mux_create0
lm->mm_tsid = u32;
if ((str = htsmsg_get_str(conf, "default_authority")))
lm->mm_dvb_default_authority = strdup(str);
/* Tuning info */
if ((e = htsmsg_get_map(conf, "tuning")))
(void)dvb_mux_conf_load(ln->ln_type, &lm->lm_tuning, e);
memcpy(&lm->lm_tuning, &dmc, sizeof(dmc));
/* Services */
if ((c = hts_settings_load_r(1, "input/linuxdvb/networks/%s/muxes/%s/services",

View file

@ -50,7 +50,8 @@ static mpegts_mux_t *
linuxdvb_network_create_mux
( mpegts_mux_t *mm, uint16_t onid, uint16_t tsid, dvb_mux_conf_t *conf )
{
return NULL;
linuxdvb_network_t *ln = (linuxdvb_network_t*)mm->mm_network;
return (mpegts_mux_t*)linuxdvb_mux_create0(ln, onid, tsid, conf, NULL);
}
static mpegts_service_t *
@ -96,15 +97,12 @@ linuxdvb_network_create0
if (!htsmsg_get_u32(conf, "nid", &u32))
ln->mn_nid = u32;
printf("network created %s / %s / %d\n", dvb_type2str(ln->ln_type),
ln->mn_network_name, ln->mn_nid);
/* Load muxes */
if ((c = hts_settings_load_r(1, "input/linuxdvb/networks/%s/muxes", uuid))) {
HTSMSG_FOREACH(f, c) {
if (!(e = htsmsg_get_map_by_field(f))) continue;
if (!(e = htsmsg_get_map(e, "config"))) continue;
(void)linuxdvb_mux_create0(ln, f->hmf_name, e);
(void)linuxdvb_mux_create1(ln, f->hmf_name, e);
}
}

View file

@ -132,6 +132,9 @@ struct linuxdvb_frontend
char *lfe_dmx_path;
char *lfe_dvr_path;
int lfe_fe_fd;
int lfe_dvr_fd;
/*
* Tuning
*/
@ -177,6 +180,9 @@ struct linuxdvb_mux
};
linuxdvb_mux_t *linuxdvb_mux_create0
(linuxdvb_network_t *ln, uint16_t onid, uint16_t tsid,
const dvb_mux_conf_t *dmc, const char *uuid);
linuxdvb_mux_t *linuxdvb_mux_create1
(linuxdvb_network_t *ln, const char *uuid, htsmsg_t *conf);
#endif /* __TVH_LINUXDVB_PRIVATE_H__ */

View file

@ -76,7 +76,6 @@ mpegts_input_recv_packets
/* Process */
while ( len >= 188 ) {
//printf("tsb[%d] = %02X\n", i, tsb[i]);
/* Sync */
if ( tsb[i] == 0x47 ) {

View file

@ -120,6 +120,7 @@ void
mpegts_mux_initial_scan_done ( mpegts_mux_t *mm )
{
mpegts_network_t *mn = mm->mm_network;
tvhlog(LOG_DEBUG, "mpegts", "initial scan complete for mm %p", mm);
gtimer_disarm(&mm->mm_initial_scan_timeout);
assert(mm->mm_initial_scan_status == MM_SCAN_CURRENT);
mn->mn_initial_scan_num--;
@ -145,7 +146,7 @@ mpegts_mux_start ( mpegts_mux_t *mm, const char *reason, int weight )
}
/* Create mux instances (where needed) */
//mm->mm_create_instances(mm);
mm->mm_create_instances(mm);
/* Find */
// TODO: don't like this is unbounded, if for some reason mi_start_mux()
@ -159,9 +160,12 @@ mpegts_mux_start ( mpegts_mux_t *mm, const char *reason, int weight )
break;
if (mmi)
tvhtrace("mpegts", "found free mmi %p", mmi);
else
tvhtrace("mpegts", "no input is free");
/* Try and remove a lesser instance */
if (!mmi) {
#if 0
LIST_FOREACH(mmi, &mm->mm_instances, mmi_mux_link) {
/* Bad - skip */
@ -175,6 +179,7 @@ mpegts_mux_start ( mpegts_mux_t *mm, const char *reason, int weight )
if (mmi)
tvhtrace("mpegts", "found mmi %p to boot", mmi);
#endif
/* No free input */
if (!mmi) {
@ -184,13 +189,17 @@ mpegts_mux_start ( mpegts_mux_t *mm, const char *reason, int weight )
}
/* Tune */
if (!mmi->mmi_input->mi_start_mux(mmi->mmi_input, mmi))
if (!mmi->mmi_input->mi_start_mux(mmi->mmi_input, mmi)) {
LIST_INSERT_HEAD(&mmi->mmi_input->mi_mux_active, mmi, mmi_active_link);
mm->mm_active = mmi;
break;
}
tvhtrace("mpegts", "failed to run mmi %p", mmi);
}
/* Initial scanning */
if (mm->mm_initial_scan_status == MM_SCAN_PENDING) {
tvhtrace("mpegts", "adding mm %p to current scan Q", mm);
TAILQ_REMOVE(&mn->mn_initial_scan_pending_queue, mm, mm_initial_scan_link);
mm->mm_initial_scan_status = MM_SCAN_CURRENT;
TAILQ_INSERT_TAIL(&mn->mn_initial_scan_current_queue, mm, mm_initial_scan_link);
@ -207,6 +216,9 @@ mpegts_mux_stop ( mpegts_mux_t *mm )
mpegts_mux_instance_t *mmi = mm->mm_active;
mpegts_input_t *mi;
tvhtrace("mpegts", "stopping mux %p", mm);
assert(0);
/* Flush all subscribers */
if (mmi) {
mi = mmi->mmi_input;