psi parser: more code reorganization, add parser/remux helpers for other layers
This commit is contained in:
parent
75cad931c4
commit
d5c5f67bfe
6 changed files with 184 additions and 90 deletions
|
@ -696,7 +696,7 @@ static int _eit_start
|
|||
|
||||
/* Standard (0x12) */
|
||||
} else {
|
||||
pid = 0x12;
|
||||
pid = DVB_EIT_PID;
|
||||
opts = MT_RECORD;
|
||||
}
|
||||
mpegts_table_add(dm, 0, 0, _eit_callback, map, m->id, MT_CRC | opts, pid);
|
||||
|
|
|
@ -188,7 +188,6 @@ struct mpegts_table
|
|||
TAILQ_ENTRY(mpegts_table) mt_defer_link;
|
||||
mpegts_mux_t *mt_mux;
|
||||
|
||||
void *mt_opaque;
|
||||
void *mt_bat;
|
||||
mpegts_table_callback_t mt_callback;
|
||||
|
||||
|
@ -207,12 +206,6 @@ struct mpegts_table
|
|||
int mt_destroyed; // Refcounting
|
||||
int mt_arefcount;
|
||||
|
||||
int8_t mt_cc;
|
||||
|
||||
tvhlog_limit_t mt_err_log;
|
||||
|
||||
mpegts_psi_section_t mt_sect;
|
||||
|
||||
struct mpegts_table_mux_cb *mt_mux_cb;
|
||||
|
||||
mpegts_service_t *mt_service;
|
||||
|
|
|
@ -37,6 +37,7 @@ struct mpegts_mux;
|
|||
#define DVB_NIT_PID 0x10
|
||||
#define DVB_SDT_PID 0x11
|
||||
#define DVB_BAT_PID 0x11
|
||||
#define DVB_EIT_PID 0x12
|
||||
#define DVB_VCT_PID 0x1FFB
|
||||
|
||||
/* Tables */
|
||||
|
@ -207,6 +208,8 @@ do {\
|
|||
|
||||
typedef struct mpegts_psi_section
|
||||
{
|
||||
int8_t ps_cc;
|
||||
int8_t ps_cco;
|
||||
int ps_offset;
|
||||
int ps_lock;
|
||||
uint8_t ps_data[MPEGTS_PSI_SECTION_SIZE];
|
||||
|
@ -232,6 +235,7 @@ typedef struct mpegts_psi_table
|
|||
RB_HEAD(,mpegts_psi_table_state) mt_state;
|
||||
|
||||
char *mt_name;
|
||||
void *mt_opaque;
|
||||
|
||||
uint8_t mt_table; // SI table id (base)
|
||||
uint8_t mt_mask; // mask
|
||||
|
@ -241,16 +245,21 @@ typedef struct mpegts_psi_table
|
|||
int mt_complete;
|
||||
int mt_incomplete;
|
||||
uint8_t mt_finished;
|
||||
|
||||
mpegts_psi_section_t mt_sect;
|
||||
|
||||
tvhlog_limit_t mt_err_log;
|
||||
|
||||
} mpegts_psi_table_t;
|
||||
|
||||
/*
|
||||
* Assemble SI section
|
||||
*/
|
||||
void mpegts_psi_section_reassemble
|
||||
( mpegts_psi_section_t *ps, const uint8_t *tsb, int crc, int ccerr,
|
||||
( mpegts_psi_table_t *mt, const uint8_t *tsb, int crc,
|
||||
mpegts_psi_section_callback_t cb, void *opaque );
|
||||
|
||||
/* PSI table callbacks */
|
||||
/* PSI table parser helpers */
|
||||
|
||||
int dvb_table_end
|
||||
(mpegts_psi_table_t *mt, mpegts_psi_table_state_t *st, int sect );
|
||||
|
@ -261,6 +270,25 @@ int dvb_table_begin
|
|||
void dvb_table_reset (mpegts_psi_table_t *mt);
|
||||
void dvb_table_release (mpegts_psi_table_t *mt);
|
||||
|
||||
/* all-in-one parser */
|
||||
|
||||
typedef void (*mpegts_psi_parse_callback_t)
|
||||
( mpegts_psi_table_t *, const uint8_t *buf, int len );
|
||||
|
||||
void dvb_table_parse_init
|
||||
( mpegts_psi_table_t *mt, const char *name, int pid, void *opaque );
|
||||
|
||||
void dvb_table_parse_done ( mpegts_psi_table_t *mt);
|
||||
|
||||
void dvb_table_parse
|
||||
(mpegts_psi_table_t *mt, const uint8_t *tsb, int len,
|
||||
int crc, int full, mpegts_psi_parse_callback_t cb);
|
||||
|
||||
int dvb_table_append_crc32(uint8_t *dst, int off, int maxlen);
|
||||
|
||||
int dvb_table_remux
|
||||
(mpegts_psi_table_t *mt, const uint8_t *buf, int len, uint8_t **out);
|
||||
|
||||
extern htsmsg_t *satellites;
|
||||
|
||||
/*
|
||||
|
|
|
@ -63,42 +63,54 @@ dvb_servicetype_lookup ( int t )
|
|||
*/
|
||||
static int
|
||||
mpegts_psi_section_reassemble0
|
||||
( mpegts_psi_section_t *ps, const uint8_t *data,
|
||||
( mpegts_psi_table_t *mt, const uint8_t *data,
|
||||
int len, int start, int crc,
|
||||
mpegts_psi_section_callback_t cb, void *opaque)
|
||||
{
|
||||
uint8_t *p = mt->mt_sect.ps_data;
|
||||
int excess, tsize;
|
||||
|
||||
if(start) {
|
||||
// Payload unit start indicator
|
||||
ps->ps_offset = 0;
|
||||
ps->ps_lock = 1;
|
||||
mt->mt_sect.ps_offset = 0;
|
||||
mt->mt_sect.ps_lock = 1;
|
||||
}
|
||||
|
||||
if(!ps->ps_lock)
|
||||
if(!mt->mt_sect.ps_lock)
|
||||
return -1;
|
||||
|
||||
memcpy(ps->ps_data + ps->ps_offset, data, len);
|
||||
ps->ps_offset += len;
|
||||
memcpy(p + mt->mt_sect.ps_offset, data, len);
|
||||
mt->mt_sect.ps_offset += len;
|
||||
|
||||
if(ps->ps_offset < 3) {
|
||||
if(mt->mt_sect.ps_offset < 3) {
|
||||
/* We don't know the total length yet */
|
||||
return len;
|
||||
}
|
||||
|
||||
tsize = 3 + (((ps->ps_data[1] & 0xf) << 8) | ps->ps_data[2]);
|
||||
tsize = 3 + (((p[1] & 0xf) << 8) | p[2]);
|
||||
|
||||
if(ps->ps_offset < tsize)
|
||||
if(mt->mt_sect.ps_offset < tsize)
|
||||
return len; // Not there yet
|
||||
|
||||
excess = ps->ps_offset - tsize;
|
||||
if(p[0] == 0x72) { /* stuffing section */
|
||||
dvb_table_reset(mt);
|
||||
cb = NULL;
|
||||
crc = 0;
|
||||
}
|
||||
|
||||
if(crc && tvh_crc32(ps->ps_data, tsize, 0xffffffff))
|
||||
if(crc && tvh_crc32(p, tsize, 0xffffffff)) {
|
||||
if (tvhlog_limit(&mt->mt_err_log, 10))
|
||||
tvhwarn(mt->mt_name, "invalid checksum (len %i, errors %zi)",
|
||||
tsize, mt->mt_err_log.count);
|
||||
return -1;
|
||||
}
|
||||
|
||||
excess = mt->mt_sect.ps_offset - tsize;
|
||||
mt->mt_sect.ps_offset = 0;
|
||||
|
||||
ps->ps_offset = 0;
|
||||
if (cb)
|
||||
cb(ps->ps_data, tsize - (crc ? 4 : 0), opaque);
|
||||
cb(p, tsize - (crc ? 4 : 0), opaque);
|
||||
|
||||
return len - excess;
|
||||
}
|
||||
|
||||
|
@ -107,18 +119,25 @@ mpegts_psi_section_reassemble0
|
|||
*/
|
||||
void
|
||||
mpegts_psi_section_reassemble
|
||||
(mpegts_psi_section_t *ps, const uint8_t *tsb, int crc, int ccerr,
|
||||
(mpegts_psi_table_t *mt, const uint8_t *tsb, int crc,
|
||||
mpegts_psi_section_callback_t cb, void *opaque)
|
||||
{
|
||||
int off = tsb[3] & 0x20 ? tsb[4] + 5 : 4;
|
||||
int pusi = tsb[1] & 0x40;
|
||||
int pusi = tsb[1] & 0x40;
|
||||
uint8_t cc = tsb[3];
|
||||
int off = cc & 0x20 ? tsb[4] + 5 : 4;
|
||||
int r;
|
||||
|
||||
if (ccerr)
|
||||
ps->ps_lock = 0;
|
||||
if (cc & 0x10) {
|
||||
if (mt->mt_sect.ps_cc != -1 && mt->mt_sect.ps_cc != (cc & 0x0f)) {
|
||||
uint16_t pid = ((tsb[1] & 0x1f) << 8) | tsb[2];
|
||||
tvhdebug(mt->mt_name, "PID %04X CC error %d != %d", pid, cc & 0x0f, mt->mt_sect.ps_cc);
|
||||
mt->mt_sect.ps_lock = 0;
|
||||
}
|
||||
mt->mt_sect.ps_cc = (cc + 1) & 0x0f;
|
||||
}
|
||||
|
||||
if(off >= 188) {
|
||||
ps->ps_lock = 0;
|
||||
mt->mt_sect.ps_lock = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -126,19 +145,19 @@ mpegts_psi_section_reassemble
|
|||
int len = tsb[off++];
|
||||
if(len > 0) {
|
||||
if(len > 188 - off) {
|
||||
ps->ps_lock = 0;
|
||||
mt->mt_sect.ps_lock = 0;
|
||||
return;
|
||||
}
|
||||
mpegts_psi_section_reassemble0(ps, tsb + off, len, 0, crc, cb, opaque);
|
||||
mpegts_psi_section_reassemble0(mt, tsb + off, len, 0, crc, cb, opaque);
|
||||
off += len;
|
||||
}
|
||||
}
|
||||
|
||||
while(off < 188) {
|
||||
r = mpegts_psi_section_reassemble0(ps, tsb + off, 188 - off, pusi, crc,
|
||||
r = mpegts_psi_section_reassemble0(mt, tsb + off, 188 - off, pusi, crc,
|
||||
cb, opaque);
|
||||
if(r < 0) {
|
||||
ps->ps_lock = 0;
|
||||
mt->mt_sect.ps_lock = 0;
|
||||
break;
|
||||
}
|
||||
off += r;
|
||||
|
@ -349,3 +368,100 @@ dvb_table_release(mpegts_psi_table_t *mt)
|
|||
free(st);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
void dvb_table_parse_init
|
||||
( mpegts_psi_table_t *mt, const char *name, int pid, void *opaque )
|
||||
{
|
||||
memset(mt, 0, sizeof(*mt));
|
||||
mt->mt_name = strdup(name);
|
||||
mt->mt_opaque = opaque;
|
||||
mt->mt_pid = pid;
|
||||
mt->mt_sect.ps_cc = -1;
|
||||
}
|
||||
|
||||
void dvb_table_parse_done( mpegts_psi_table_t *mt )
|
||||
{
|
||||
free(mt->mt_name);
|
||||
}
|
||||
|
||||
struct psi_parse {
|
||||
mpegts_psi_table_t *mt;
|
||||
mpegts_psi_parse_callback_t cb;
|
||||
int full;
|
||||
};
|
||||
|
||||
static void
|
||||
dvb_table_parse_cb( const uint8_t *sec, size_t len, void *opaque )
|
||||
{
|
||||
struct psi_parse *parse = opaque;
|
||||
|
||||
parse->cb(parse->mt, sec + parse->full, len - parse->full);
|
||||
}
|
||||
|
||||
void dvb_table_parse
|
||||
(mpegts_psi_table_t *mt, const uint8_t *tsb, int len,
|
||||
int crc, int full, mpegts_psi_parse_callback_t cb)
|
||||
{
|
||||
const uint8_t *end;
|
||||
struct psi_parse parse;
|
||||
|
||||
parse.mt = mt;
|
||||
parse.cb = cb;
|
||||
parse.full = full ? 3 : 0;
|
||||
|
||||
for (end = tsb + len; tsb < end; tsb += 188)
|
||||
mpegts_psi_section_reassemble(mt, tsb, crc,
|
||||
dvb_table_parse_cb, &parse);
|
||||
}
|
||||
|
||||
int dvb_table_append_crc32(uint8_t *dst, int off, int maxlen)
|
||||
{
|
||||
if (off + 4 > maxlen)
|
||||
return -1;
|
||||
|
||||
uint32_t crc = tvh_crc32(dst, off, 0xffffffff);
|
||||
dst[off++] = crc >> 24;
|
||||
dst[off++] = crc >> 16;
|
||||
dst[off++] = crc >> 8;
|
||||
dst[off++] = crc;
|
||||
return off;
|
||||
}
|
||||
|
||||
int dvb_table_remux
|
||||
(mpegts_psi_table_t *mt, const uint8_t *buf, int len, uint8_t **out)
|
||||
{
|
||||
uint8_t *obuf, pusi;
|
||||
int ol = 0, l, m;
|
||||
|
||||
/* try to guess the output size here */
|
||||
obuf = malloc(((len + 183 + 1 /* pusi */) / 184) * 188);
|
||||
|
||||
pusi = 0x40;
|
||||
while (len > 0) {
|
||||
obuf[ol++] = 0x47;
|
||||
obuf[ol++] = pusi | ((mt->mt_pid >> 8) & 0x1f);
|
||||
obuf[ol++] = mt->mt_pid & 0xff;
|
||||
obuf[ol++] = 0x10 | ((mt->mt_sect.ps_cco++) & 0x0f);
|
||||
if (pusi) {
|
||||
obuf[ol++] = 0;
|
||||
m = 183;
|
||||
pusi = 0;
|
||||
} else {
|
||||
m = 184;
|
||||
}
|
||||
l = MIN(m, len);
|
||||
memcpy(obuf + ol, buf, l);
|
||||
if (l < m)
|
||||
memset(obuf + ol + l, 0xff, m - l);
|
||||
ol += m;
|
||||
len -= l;
|
||||
buf += l;
|
||||
}
|
||||
|
||||
*out = obuf;
|
||||
return ol;
|
||||
}
|
||||
|
|
|
@ -951,21 +951,10 @@ mpegts_input_table_dispatch ( mpegts_mux_t *mm, const uint8_t *tsb, int tsb_len
|
|||
for (i = 0; i < len; i++) {
|
||||
mt = vec[i];
|
||||
if (!mt->mt_destroyed && mt->mt_pid == pid)
|
||||
for (tsb2 = tsb, tsb2_end = tsb + tsb_len; tsb2 < tsb2_end; tsb2 += 188) {
|
||||
uint8_t cc = tsb2[3];
|
||||
if (cc & 0x10) {
|
||||
int ccerr = 0;
|
||||
if (mt->mt_cc != -1 && mt->mt_cc != (cc & 0xF)) {
|
||||
ccerr = 1;
|
||||
/* Ignore dupes (shouldn't have payload set, but some seem to) */
|
||||
//if (((mt->mt_cc + 15) & 0xf) != cc)
|
||||
tvhdebug("psi", "PID %04X CC error %d != %d", pid, cc, mt->mt_cc);
|
||||
}
|
||||
mt->mt_cc = (cc + 1) & 0xF;
|
||||
mpegts_psi_section_reassemble(&mt->mt_sect, tsb2, 0, ccerr,
|
||||
mpegts_table_dispatch, mt);
|
||||
}
|
||||
}
|
||||
for (tsb2 = tsb, tsb2_end = tsb + tsb_len; tsb2 < tsb2_end; tsb2 += 188)
|
||||
mpegts_psi_section_reassemble((mpegts_psi_table_t *)mt, tsb2,
|
||||
mt->mt_flags & MT_CRC,
|
||||
mpegts_table_dispatch, mt);
|
||||
mpegts_table_release(mt);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,49 +72,17 @@ mpegts_table_dispatch
|
|||
{
|
||||
int tid, len, ret;
|
||||
mpegts_table_t *mt = aux;
|
||||
int chkcrc = mt->mt_flags & MT_CRC;
|
||||
|
||||
if(mt->mt_destroyed)
|
||||
return;
|
||||
|
||||
/* Table info */
|
||||
tid = sec[0];
|
||||
len = ((sec[1] & 0x0f) << 8) | sec[2];
|
||||
|
||||
if (tid == 0x72) { /* stuffing section */
|
||||
if (len != r - 3) {
|
||||
if (tvhlog_limit(&mt->mt_err_log, 10))
|
||||
tvhwarn(mt->mt_name, "stuffing found with trailing data "
|
||||
"(len %i, total %zi, errors %zi)",
|
||||
len, r, mt->mt_err_log.count);
|
||||
}
|
||||
dvb_table_reset((mpegts_psi_table_t *)mt);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 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)) {
|
||||
if (tvhlog_limit(&mt->mt_err_log, 10))
|
||||
tvhwarn(mt->mt_name, "invalid checksum (len %zi, errors %zi)",
|
||||
r, mt->mt_err_log.count);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Not enough data */
|
||||
if(len < r - 3) {
|
||||
tvhtrace(mt->mt_name, "not enough data, %d < %d", (int)r, len);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check table mask */
|
||||
if((tid & mt->mt_mask) != mt->mt_table)
|
||||
return;
|
||||
|
||||
/* Strip trailing CRC */
|
||||
if(chkcrc)
|
||||
len -= 4;
|
||||
|
||||
/* Pass with tableid / len in data */
|
||||
if (mt->mt_flags & MT_FULL)
|
||||
ret = mt->mt_callback(mt, sec, len+3, tid);
|
||||
|
@ -236,16 +204,16 @@ mpegts_table_add
|
|||
|
||||
/* Create */
|
||||
mt = calloc(1, sizeof(mpegts_table_t));
|
||||
mt->mt_arefcount = 1;
|
||||
mt->mt_name = strdup(name);
|
||||
mt->mt_callback = callback;
|
||||
mt->mt_opaque = opaque;
|
||||
mt->mt_pid = pid;
|
||||
mt->mt_flags = flags & ~(MT_SKIPSUBS|MT_SCANSUBS);
|
||||
mt->mt_table = tableid;
|
||||
mt->mt_mask = mask;
|
||||
mt->mt_mux = mm;
|
||||
mt->mt_cc = -1;
|
||||
mt->mt_arefcount = 1;
|
||||
mt->mt_name = strdup(name);
|
||||
mt->mt_callback = callback;
|
||||
mt->mt_opaque = opaque;
|
||||
mt->mt_pid = pid;
|
||||
mt->mt_flags = flags & ~(MT_SKIPSUBS|MT_SCANSUBS);
|
||||
mt->mt_table = tableid;
|
||||
mt->mt_mask = mask;
|
||||
mt->mt_mux = mm;
|
||||
mt->mt_sect.ps_cc = -1;
|
||||
|
||||
/* Open table */
|
||||
if (pid < 0) {
|
||||
|
|
Loading…
Add table
Reference in a new issue