dvb: Move low level DVB table reception to dvb_input_filtered.c
This commit is contained in:
parent
7416dabc5f
commit
c26216ccba
4 changed files with 198 additions and 193 deletions
|
@ -25,6 +25,8 @@
|
|||
#include "htsmsg.h"
|
||||
|
||||
struct service;
|
||||
struct th_dvb_table;
|
||||
struct th_dvb_mux_instance;
|
||||
|
||||
#define DVB_VER_INT(maj,min) (((maj) << 16) + (min))
|
||||
|
||||
|
@ -235,6 +237,8 @@ typedef struct th_dvb_adapter {
|
|||
|
||||
void (*tda_open_service)(struct th_dvb_adapter *tda, struct service *s);
|
||||
void (*tda_close_service)(struct th_dvb_adapter *tda, struct service *s);
|
||||
void (*tda_open_table)(struct th_dvb_mux_instance *tdmi, struct th_dvb_table *s);
|
||||
void (*tda_close_table)(struct th_dvb_mux_instance *tdmi, struct th_dvb_table *s);
|
||||
|
||||
} th_dvb_adapter_t;
|
||||
|
||||
|
@ -458,6 +462,8 @@ void dvb_table_add_pmt(th_dvb_mux_instance_t *tdmi, int pmt_pid);
|
|||
|
||||
void dvb_table_rem_pmt(th_dvb_mux_instance_t *tdmi, int pmt_pid);
|
||||
|
||||
void dvb_table_fastswitch(th_dvb_mux_instance_t *tdmi);
|
||||
|
||||
void tdt_add(th_dvb_mux_instance_t *tdmi, int table, int mask,
|
||||
int (*callback)(th_dvb_mux_instance_t *tdmi, uint8_t *buf, int len,
|
||||
uint8_t tableid, void *opaque), void *opaque,
|
||||
|
|
|
@ -68,8 +68,6 @@ tda_alloc(void)
|
|||
tda->tda_allpids_dmx_fd = -1;
|
||||
tda->tda_dump_fd = -1;
|
||||
|
||||
dvb_input_filtered_setup(tda);
|
||||
|
||||
return tda;
|
||||
}
|
||||
|
||||
|
@ -479,8 +477,7 @@ tda_add(int adapter_num)
|
|||
|
||||
TAILQ_INSERT_TAIL(&dvb_adapters, tda, tda_global_link);
|
||||
|
||||
|
||||
dvb_table_init(tda);
|
||||
dvb_input_filtered_setup(tda);
|
||||
|
||||
if(tda->tda_sat)
|
||||
dvb_satconf_init(tda);
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
/**
|
||||
* DVB input using hardware filters
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
@ -27,6 +27,7 @@
|
|||
#include <fcntl.h>
|
||||
#include <linux/dvb/frontend.h>
|
||||
#include <linux/dvb/dmx.h>
|
||||
#include <sys/epoll.h>
|
||||
|
||||
#include "tvheadend.h"
|
||||
#include "dvb.h"
|
||||
|
@ -105,11 +106,197 @@ close_service(th_dvb_adapter_t *tda, service_t *s)
|
|||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
open_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt)
|
||||
{
|
||||
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
|
||||
struct epoll_event e;
|
||||
static int tdt_id_tally;
|
||||
|
||||
assert(tdt->tdt_fd == -1);
|
||||
TAILQ_REMOVE(&tdmi->tdmi_table_queue, tdt, tdt_pending_link);
|
||||
|
||||
tdt->tdt_fd = tvh_open(tda->tda_demux_path, O_RDWR, 0);
|
||||
|
||||
if(tdt->tdt_fd != -1) {
|
||||
|
||||
tdt->tdt_id = ++tdt_id_tally;
|
||||
|
||||
e.events = EPOLLIN;
|
||||
e.data.u64 = ((uint64_t)tdt->tdt_fd << 32) | tdt->tdt_id;
|
||||
|
||||
if(epoll_ctl(tda->tda_table_epollfd, EPOLL_CTL_ADD, tdt->tdt_fd, &e)) {
|
||||
close(tdt->tdt_fd);
|
||||
tdt->tdt_fd = -1;
|
||||
} else {
|
||||
|
||||
struct dmx_sct_filter_params fp = {0};
|
||||
|
||||
fp.filter.filter[0] = tdt->tdt_table;
|
||||
fp.filter.mask[0] = tdt->tdt_mask;
|
||||
|
||||
if(tdt->tdt_flags & TDT_CRC)
|
||||
fp.flags |= DMX_CHECK_CRC;
|
||||
fp.flags |= DMX_IMMEDIATE_START;
|
||||
fp.pid = tdt->tdt_pid;
|
||||
|
||||
if(ioctl(tdt->tdt_fd, DMX_SET_FILTER, &fp)) {
|
||||
close(tdt->tdt_fd);
|
||||
tdt->tdt_fd = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(tdt->tdt_fd == -1)
|
||||
TAILQ_INSERT_TAIL(&tdmi->tdmi_table_queue, tdt, tdt_pending_link);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Close FD for the given table and put table on the pending list
|
||||
*/
|
||||
static void
|
||||
tdt_close_fd(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt)
|
||||
{
|
||||
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
|
||||
|
||||
assert(tdt->tdt_fd != -1);
|
||||
|
||||
epoll_ctl(tda->tda_table_epollfd, EPOLL_CTL_DEL, tdt->tdt_fd, NULL);
|
||||
close(tdt->tdt_fd);
|
||||
|
||||
tdt->tdt_fd = -1;
|
||||
TAILQ_INSERT_TAIL(&tdmi->tdmi_table_queue, tdt, tdt_pending_link);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
dvb_proc_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt, uint8_t *sec,
|
||||
int r)
|
||||
{
|
||||
int chkcrc = tdt->tdt_flags & TDT_CRC;
|
||||
int tableid, len;
|
||||
uint8_t *ptr;
|
||||
int ret;
|
||||
|
||||
/* It seems some hardware (or is it the dvb API?) does not
|
||||
honour the DMX_CHECK_CRC flag, so we check it again */
|
||||
if(chkcrc && tvh_crc32(sec, r, 0xffffffff))
|
||||
return;
|
||||
|
||||
r -= 3;
|
||||
tableid = sec[0];
|
||||
len = ((sec[1] & 0x0f) << 8) | sec[2];
|
||||
|
||||
if(len < r)
|
||||
return;
|
||||
|
||||
ptr = &sec[3];
|
||||
if(chkcrc) len -= 4; /* Strip trailing CRC */
|
||||
|
||||
if(tdt->tdt_flags & TDT_CA)
|
||||
ret = tdt->tdt_callback((th_dvb_mux_instance_t *)tdt,
|
||||
sec, len + 3, tableid, tdt->tdt_opaque);
|
||||
else if(tdt->tdt_flags & TDT_TDT)
|
||||
ret = tdt->tdt_callback(tdmi, ptr, len, tableid, tdt);
|
||||
else
|
||||
ret = tdt->tdt_callback(tdmi, ptr, len, tableid, tdt->tdt_opaque);
|
||||
|
||||
if(ret == 0)
|
||||
tdt->tdt_count++;
|
||||
|
||||
if(tdt->tdt_flags & TDT_QUICKREQ)
|
||||
dvb_table_fastswitch(tdmi);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void *
|
||||
dvb_table_input(void *aux)
|
||||
{
|
||||
th_dvb_adapter_t *tda = aux;
|
||||
int r, i, tid, fd, x;
|
||||
struct epoll_event ev[1];
|
||||
uint8_t sec[4096];
|
||||
th_dvb_mux_instance_t *tdmi;
|
||||
th_dvb_table_t *tdt;
|
||||
int64_t cycle_barrier = 0;
|
||||
|
||||
while(1) {
|
||||
x = epoll_wait(tda->tda_table_epollfd, ev, sizeof(ev) / sizeof(ev[0]), -1);
|
||||
|
||||
for(i = 0; i < x; i++) {
|
||||
|
||||
tid = ev[i].data.u64 & 0xffffffff;
|
||||
fd = ev[i].data.u64 >> 32;
|
||||
|
||||
if(!(ev[i].events & EPOLLIN))
|
||||
continue;
|
||||
|
||||
if((r = read(fd, sec, sizeof(sec))) < 3)
|
||||
continue;
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
if((tdmi = tda->tda_mux_current) != NULL) {
|
||||
LIST_FOREACH(tdt, &tdmi->tdmi_tables, tdt_link)
|
||||
if(tdt->tdt_id == tid)
|
||||
break;
|
||||
|
||||
if(tdt != NULL) {
|
||||
dvb_proc_table(tdmi, tdt, sec, r);
|
||||
|
||||
/* Any tables pending (that wants a filter/fd), close this one */
|
||||
if(TAILQ_FIRST(&tdmi->tdmi_table_queue) != NULL &&
|
||||
cycle_barrier < getmonoclock()) {
|
||||
tdt_close_fd(tdmi, tdt);
|
||||
cycle_barrier = getmonoclock() + 100000;
|
||||
tdt = TAILQ_FIRST(&tdmi->tdmi_table_queue);
|
||||
assert(tdt != NULL);
|
||||
|
||||
open_table(tdmi, tdt);
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
close_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt)
|
||||
{
|
||||
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
|
||||
|
||||
if(tdt->tdt_fd == -1) {
|
||||
TAILQ_REMOVE(&tdmi->tdmi_table_queue, tdt, tdt_pending_link);
|
||||
} else {
|
||||
epoll_ctl(tda->tda_table_epollfd, EPOLL_CTL_DEL, tdt->tdt_fd, NULL);
|
||||
close(tdt->tdt_fd);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
dvb_input_filtered_setup(th_dvb_adapter_t *tda)
|
||||
{
|
||||
tda->tda_open_service = open_service;
|
||||
tda->tda_close_service = close_service;
|
||||
tda->tda_open_table = open_table;
|
||||
tda->tda_close_table = close_table;
|
||||
|
||||
pthread_t ptid;
|
||||
tda->tda_table_epollfd = epoll_create(50);
|
||||
pthread_create(&ptid, NULL, dvb_table_input, tda);
|
||||
}
|
||||
|
||||
|
|
|
@ -42,12 +42,11 @@
|
|||
#include "notify.h"
|
||||
#include "cwc.h"
|
||||
|
||||
static int tdt_id_tally;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
void
|
||||
dvb_table_fastswitch(th_dvb_mux_instance_t *tdmi)
|
||||
{
|
||||
th_dvb_table_t *tdt;
|
||||
|
@ -73,183 +72,6 @@ dvb_table_fastswitch(th_dvb_mux_instance_t *tdmi)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
tdt_open_fd(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt)
|
||||
{
|
||||
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
|
||||
struct epoll_event e;
|
||||
|
||||
assert(tdt->tdt_fd == -1);
|
||||
TAILQ_REMOVE(&tdmi->tdmi_table_queue, tdt, tdt_pending_link);
|
||||
|
||||
tdt->tdt_fd = tvh_open(tda->tda_demux_path, O_RDWR, 0);
|
||||
|
||||
if(tdt->tdt_fd != -1) {
|
||||
|
||||
tdt->tdt_id = ++tdt_id_tally;
|
||||
|
||||
e.events = EPOLLIN;
|
||||
e.data.u64 = ((uint64_t)tdt->tdt_fd << 32) | tdt->tdt_id;
|
||||
|
||||
if(epoll_ctl(tda->tda_table_epollfd, EPOLL_CTL_ADD, tdt->tdt_fd, &e)) {
|
||||
close(tdt->tdt_fd);
|
||||
tdt->tdt_fd = -1;
|
||||
} else {
|
||||
|
||||
struct dmx_sct_filter_params fp = {0};
|
||||
|
||||
fp.filter.filter[0] = tdt->tdt_table;
|
||||
fp.filter.mask[0] = tdt->tdt_mask;
|
||||
|
||||
if(tdt->tdt_flags & TDT_CRC)
|
||||
fp.flags |= DMX_CHECK_CRC;
|
||||
fp.flags |= DMX_IMMEDIATE_START;
|
||||
fp.pid = tdt->tdt_pid;
|
||||
|
||||
if(ioctl(tdt->tdt_fd, DMX_SET_FILTER, &fp)) {
|
||||
close(tdt->tdt_fd);
|
||||
tdt->tdt_fd = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(tdt->tdt_fd == -1)
|
||||
TAILQ_INSERT_TAIL(&tdmi->tdmi_table_queue, tdt, tdt_pending_link);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Close FD for the given table and put table on the pending list
|
||||
*/
|
||||
static void
|
||||
tdt_close_fd(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt)
|
||||
{
|
||||
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
|
||||
|
||||
assert(tdt->tdt_fd != -1);
|
||||
|
||||
epoll_ctl(tda->tda_table_epollfd, EPOLL_CTL_DEL, tdt->tdt_fd, NULL);
|
||||
close(tdt->tdt_fd);
|
||||
|
||||
tdt->tdt_fd = -1;
|
||||
TAILQ_INSERT_TAIL(&tdmi->tdmi_table_queue, tdt, tdt_pending_link);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
dvb_proc_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt, uint8_t *sec,
|
||||
int r)
|
||||
{
|
||||
int chkcrc = tdt->tdt_flags & TDT_CRC;
|
||||
int tableid, len;
|
||||
uint8_t *ptr;
|
||||
int ret;
|
||||
|
||||
/* It seems some hardware (or is it the dvb API?) does not
|
||||
honour the DMX_CHECK_CRC flag, so we check it again */
|
||||
if(chkcrc && tvh_crc32(sec, r, 0xffffffff))
|
||||
return;
|
||||
|
||||
r -= 3;
|
||||
tableid = sec[0];
|
||||
len = ((sec[1] & 0x0f) << 8) | sec[2];
|
||||
|
||||
if(len < r)
|
||||
return;
|
||||
|
||||
ptr = &sec[3];
|
||||
if(chkcrc) len -= 4; /* Strip trailing CRC */
|
||||
|
||||
if(tdt->tdt_flags & TDT_CA)
|
||||
ret = tdt->tdt_callback((th_dvb_mux_instance_t *)tdt,
|
||||
sec, len + 3, tableid, tdt->tdt_opaque);
|
||||
else if(tdt->tdt_flags & TDT_TDT)
|
||||
ret = tdt->tdt_callback(tdmi, ptr, len, tableid, tdt);
|
||||
else
|
||||
ret = tdt->tdt_callback(tdmi, ptr, len, tableid, tdt->tdt_opaque);
|
||||
|
||||
if(ret == 0)
|
||||
tdt->tdt_count++;
|
||||
|
||||
if(tdt->tdt_flags & TDT_QUICKREQ)
|
||||
dvb_table_fastswitch(tdmi);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void *
|
||||
dvb_table_input(void *aux)
|
||||
{
|
||||
th_dvb_adapter_t *tda = aux;
|
||||
int r, i, tid, fd, x;
|
||||
struct epoll_event ev[1];
|
||||
uint8_t sec[4096];
|
||||
th_dvb_mux_instance_t *tdmi;
|
||||
th_dvb_table_t *tdt;
|
||||
int64_t cycle_barrier = 0;
|
||||
|
||||
while(1) {
|
||||
x = epoll_wait(tda->tda_table_epollfd, ev, sizeof(ev) / sizeof(ev[0]), -1);
|
||||
|
||||
for(i = 0; i < x; i++) {
|
||||
|
||||
tid = ev[i].data.u64 & 0xffffffff;
|
||||
fd = ev[i].data.u64 >> 32;
|
||||
|
||||
if(!(ev[i].events & EPOLLIN))
|
||||
continue;
|
||||
|
||||
if((r = read(fd, sec, sizeof(sec))) < 3)
|
||||
continue;
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
if((tdmi = tda->tda_mux_current) != NULL) {
|
||||
LIST_FOREACH(tdt, &tdmi->tdmi_tables, tdt_link)
|
||||
if(tdt->tdt_id == tid)
|
||||
break;
|
||||
|
||||
if(tdt != NULL) {
|
||||
dvb_proc_table(tdmi, tdt, sec, r);
|
||||
|
||||
/* Any tables pending (that wants a filter/fd), close this one */
|
||||
if(TAILQ_FIRST(&tdmi->tdmi_table_queue) != NULL &&
|
||||
cycle_barrier < getmonoclock()) {
|
||||
tdt_close_fd(tdmi, tdt);
|
||||
cycle_barrier = getmonoclock() + 100000;
|
||||
tdt = TAILQ_FIRST(&tdmi->tdmi_table_queue);
|
||||
assert(tdt != NULL);
|
||||
|
||||
tdt_open_fd(tdmi, tdt);
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
dvb_table_init(th_dvb_adapter_t *tda)
|
||||
{
|
||||
pthread_t ptid;
|
||||
tda->tda_table_epollfd = epoll_create(50);
|
||||
pthread_create(&ptid, NULL, dvb_table_input, tda);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -258,14 +80,7 @@ dvb_tdt_destroy(th_dvb_adapter_t *tda, th_dvb_mux_instance_t *tdmi,
|
|||
th_dvb_table_t *tdt)
|
||||
{
|
||||
LIST_REMOVE(tdt, tdt_link);
|
||||
|
||||
if(tdt->tdt_fd == -1) {
|
||||
TAILQ_REMOVE(&tdmi->tdmi_table_queue, tdt, tdt_pending_link);
|
||||
} else {
|
||||
epoll_ctl(tda->tda_table_epollfd, EPOLL_CTL_DEL, tdt->tdt_fd, NULL);
|
||||
close(tdt->tdt_fd);
|
||||
}
|
||||
|
||||
tda->tda_close_table(tdmi, tdt);
|
||||
free(tdt->tdt_name);
|
||||
free(tdt);
|
||||
}
|
||||
|
@ -311,7 +126,7 @@ tdt_add(th_dvb_mux_instance_t *tdmi, int tableid, int mask,
|
|||
tdt->tdt_fd = -1;
|
||||
TAILQ_INSERT_TAIL(&tdmi->tdmi_table_queue, tdt, tdt_pending_link);
|
||||
|
||||
tdt_open_fd(tdmi, tdt);
|
||||
tdmi->tdmi_adapter->tda_open_table(tdmi, tdt);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Reference in a new issue