Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
dvb: Add table parsing when in raw mode
  • Loading branch information
andoma committed Oct 25, 2012
1 parent 43509ec commit f4fc438
Show file tree
Hide file tree
Showing 9 changed files with 232 additions and 75 deletions.
40 changes: 37 additions & 3 deletions src/dvb/dvb.h
Expand Up @@ -23,6 +23,7 @@
#include <linux/dvb/frontend.h>
#include <pthread.h>
#include "htsmsg.h"
#include "psi.h"

struct service;
struct th_dvb_table;
Expand Down Expand Up @@ -107,6 +108,8 @@ typedef struct th_dvb_mux_instance {


LIST_HEAD(, th_dvb_table) tdmi_tables;
int tdmi_num_tables;

TAILQ_HEAD(, th_dvb_table) tdmi_table_queue;
int tdmi_table_initial;

Expand Down Expand Up @@ -150,6 +153,22 @@ typedef struct th_dvb_mux_instance {
} th_dvb_mux_instance_t;




/**
* When in raw mode we need to enqueue raw TS packet
* to a different thread because we need to hold
* global_lock when doing delivery of the tables
*/
TAILQ_HEAD(dvb_table_feed_queue, dvb_table_feed);

typedef struct dvb_table_feed {
TAILQ_ENTRY(dvb_table_feed) dtf_link;
uint8_t dtf_tsb[188];
} dvb_table_feed_t;



/**
* DVB Adapter (one of these per physical adapter)
*/
Expand Down Expand Up @@ -236,6 +255,14 @@ typedef struct th_dvb_adapter {

int tda_rawmode;


struct dvb_table_feed_queue tda_table_feed;
pthread_cond_t tda_table_feed_cond; // Bound to tda_delivery_mutex

// PIDs that needs to be requeued and processed as tables
uint8_t tda_table_filter[8192];


} th_dvb_adapter_t;

/**
Expand All @@ -262,6 +289,7 @@ typedef struct th_dvb_table {
int tdt_fd;

LIST_ENTRY(th_dvb_table) tdt_link;
th_dvb_mux_instance_t *tdt_tdmi;

char *tdt_name;

Expand All @@ -278,6 +306,10 @@ typedef struct th_dvb_table {
int tdt_table;
int tdt_mask;

int tdt_destroyed;
int tdt_refcount;

psi_section_t tdt_sect; // Manual reassembly

} th_dvb_table_t;

Expand Down Expand Up @@ -459,12 +491,10 @@ 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,
const char *name, int flags, int pid, th_dvb_table_t *tdt);
const char *name, int flags, int pid);

int dvb_pidx11_callback
(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len,
Expand All @@ -475,6 +505,10 @@ int dvb_pidx11_callback
#define TDT_CA 0x4
#define TDT_TDT 0x8

void dvb_table_dispatch(uint8_t *sec, int r, th_dvb_table_t *tdt);

void dvb_table_release(th_dvb_table_t *tdt);

/**
* Satellite configuration
*/
Expand Down
18 changes: 17 additions & 1 deletion src/dvb/dvb_adapter.c
Expand Up @@ -451,7 +451,7 @@ tda_add(int adapter_num)

TAILQ_INSERT_TAIL(&dvb_adapters, tda, tda_global_link);

dvb_input_filtered_setup(tda);
dvb_input_raw_setup(tda);

if(tda->tda_sat)
dvb_satconf_init(tda);
Expand Down Expand Up @@ -796,12 +796,25 @@ dvb_adapter_input_dvr(void *aux)
/* not enough data */
if (r < 188) continue;

int wakeup_table_feed = 0; // Just wanna wakeup once

pthread_mutex_lock(&tda->tda_delivery_mutex);
/* Process */
while (r >= 188) {

/* sync */
if (tsb[i] == 0x47) {

if(!(tsb[i+1] & 0x80)) { // Only dispatch to table parser if not error
int pid = (tsb[i+1] & 0x1f) << 8 | tsb[i+2];
if(tda->tda_table_filter[pid]) {
dvb_table_feed_t *dtf = malloc(sizeof(dvb_table_feed_t));
memcpy(dtf->dtf_tsb, tsb + i, 188);
TAILQ_INSERT_TAIL(&tda->tda_table_feed, dtf, dtf_link);
wakeup_table_feed = 1;
}
}

LIST_FOREACH(t, &tda->tda_transports, s_active_link)
if(t->s_dvb_mux_instance == tda->tda_mux_current)
ts_recv_packet1(t, tsb + i, NULL);
Expand All @@ -816,6 +829,9 @@ dvb_adapter_input_dvr(void *aux)
}
}

if(wakeup_table_feed)
pthread_cond_signal(&tda->tda_table_feed_cond);

pthread_mutex_unlock(&tda->tda_delivery_mutex);

/* reset buffer */
Expand Down
2 changes: 2 additions & 0 deletions src/dvb/dvb_fe.c
Expand Up @@ -226,6 +226,8 @@ dvb_fe_stop(th_dvb_mux_instance_t *tdmi, int retune)
{
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;

lock_assert(&global_lock);

assert(tdmi == tda->tda_mux_current);
tda->tda_mux_current = NULL;

Expand Down
47 changes: 2 additions & 45 deletions src/dvb/dvb_input_filtered.c
Expand Up @@ -116,9 +116,6 @@ open_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt)
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) {
Expand Down Expand Up @@ -173,47 +170,6 @@ tdt_close_fd(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt)
}


/**
*
*/
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);
}

/**
*
Expand Down Expand Up @@ -250,7 +206,7 @@ dvb_table_input(void *aux)
break;

if(tdt != NULL) {
dvb_proc_table(tdmi, tdt, sec, r);
dvb_table_dispatch(sec, r, tdt);

/* Any tables pending (that wants a filter/fd), close this one */
if(TAILQ_FIRST(&tdmi->tdmi_table_queue) != NULL &&
Expand All @@ -259,6 +215,7 @@ dvb_table_input(void *aux)
cycle_barrier = getmonoclock() + 100000;
tdt = TAILQ_FIRST(&tdmi->tdmi_table_queue);
assert(tdt != NULL);
TAILQ_REMOVE(&tdmi->tdmi_table_queue, tdt, tdt_pending_link);

open_table(tdmi, tdt);
}
Expand Down
88 changes: 88 additions & 0 deletions src/dvb/dvb_input_raw.c
Expand Up @@ -42,6 +42,7 @@
static void
open_service(th_dvb_adapter_t *tda, service_t *s)
{
// NOP -- We receive all PIDs anyway
}


Expand All @@ -53,6 +54,7 @@ open_service(th_dvb_adapter_t *tda, service_t *s)
static void
close_service(th_dvb_adapter_t *tda, service_t *s)
{
// NOP -- open_service() is a NOP
}


Expand All @@ -62,6 +64,9 @@ 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;
assert(tdt->tdt_pid < 0x2000);
tda->tda_table_filter[tdt->tdt_pid] = 1;
}


Expand All @@ -71,8 +76,84 @@ open_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt)
static void
close_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt)
{
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
assert(tdt->tdt_pid < 0x2000);
tda->tda_table_filter[tdt->tdt_pid] = 0;
}


/**
*
*/
static void
got_section(const uint8_t *data, size_t len, void *opaque)
{
th_dvb_table_t *tdt = opaque;
dvb_table_dispatch((uint8_t *)data, len, tdt);
}



/**
* All the tables can be destroyed from any of the callbacks
* so we need to be a bit careful here
*/
static void
dvb_table_raw_dispatch(th_dvb_mux_instance_t *tdmi,
const dvb_table_feed_t *dtf)
{
int pid = (dtf->dtf_tsb[1] & 0x1f) << 8 | dtf->dtf_tsb[2];
th_dvb_table_t *vec[tdmi->tdmi_num_tables], *tdt;
int i = 0;
LIST_FOREACH(tdt, &tdmi->tdmi_tables, tdt_link) {
vec[i++] = tdt;
tdt->tdt_refcount++;
}
assert(i == tdmi->tdmi_num_tables);
int len = tdmi->tdmi_num_tables; // can change during callbacks
for(i = 0; i < len; i++) {
tdt = vec[i];
if(!tdt->tdt_destroyed) {
if(tdt->tdt_pid == pid)
psi_section_reassemble(&tdt->tdt_sect, dtf->dtf_tsb,
0, got_section, tdt);
}
dvb_table_release(tdt);
}
}

/**
*
*/
static void *
dvb_table_input(void *aux)
{
th_dvb_adapter_t *tda = aux;
th_dvb_mux_instance_t *tdmi;
dvb_table_feed_t *dtf;

while(1) {

pthread_mutex_lock(&tda->tda_delivery_mutex);

while((dtf = TAILQ_FIRST(&tda->tda_table_feed)) == NULL)
pthread_cond_wait(&tda->tda_table_feed_cond, &tda->tda_delivery_mutex);
TAILQ_REMOVE(&tda->tda_table_feed, dtf, dtf_link);

pthread_mutex_unlock(&tda->tda_delivery_mutex);

pthread_mutex_lock(&global_lock);

if((tdmi = tda->tda_mux_current) != NULL)
dvb_table_raw_dispatch(tdmi, dtf);

pthread_mutex_unlock(&global_lock);
free(dtf);
}
return NULL;
}


/**
*
*/
Expand All @@ -84,5 +165,12 @@ dvb_input_raw_setup(th_dvb_adapter_t *tda)
tda->tda_close_service = close_service;
tda->tda_open_table = open_table;
tda->tda_close_table = close_table;

TAILQ_INIT(&tda->tda_table_feed);
pthread_cond_init(&tda->tda_table_feed_cond, NULL);

pthread_t ptid;
pthread_create(&ptid, NULL, dvb_table_input, tda);

}

1 comment on commit f4fc438

@killerops
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some reason, from this commit onwards i get a lot of @ #510: Continuity counter error, 618 duplicate log lines suppressed
Any hints what could be the cause?
I'm using 5+5 skystar 2 cards with vtunerd.

Please sign in to comment.