mirror of
https://github.com/rofafor/vdr-plugin-iptv.git
synced 2023-10-10 11:37:03 +00:00
Cleaned up the code.
This commit is contained in:
170
sectionfilter.c
170
sectionfilter.c
@@ -8,101 +8,101 @@
|
||||
#include "config.h"
|
||||
#include "sectionfilter.h"
|
||||
|
||||
cIptvSectionFilter::cIptvSectionFilter(int DeviceIndex, uint16_t Pid, uint8_t Tid, uint8_t Mask)
|
||||
: pusi_seen(0),
|
||||
feedcc(0),
|
||||
doneq(0),
|
||||
secbuf(NULL),
|
||||
secbufp(0),
|
||||
seclen(0),
|
||||
tsfeedp(0),
|
||||
pid(Pid),
|
||||
devid(DeviceIndex)
|
||||
cIptvSectionFilter::cIptvSectionFilter(int deviceIndexP, uint16_t pidP, uint8_t tidP, uint8_t maskP)
|
||||
: pusiSeenM(0),
|
||||
feedCcM(0),
|
||||
doneqM(0),
|
||||
secBufM(NULL),
|
||||
secBufpM(0),
|
||||
secLenM(0),
|
||||
tsFeedpM(0),
|
||||
pidM(pidP),
|
||||
devIdM(deviceIndexP)
|
||||
{
|
||||
//debug("cIptvSectionFilter::cIptvSectionFilter(%d, %d)\n", devid, pid);
|
||||
//debug("cIptvSectionFilter::cIptvSectionFilter(%d, %d)\n", devIdM, pidM);
|
||||
int i;
|
||||
|
||||
memset(secbuf_base, '\0', sizeof(secbuf_base));
|
||||
memset(filter_value, '\0', sizeof(filter_value));
|
||||
memset(filter_mask, '\0', sizeof(filter_mask));
|
||||
memset(filter_mode, '\0', sizeof(filter_mode));
|
||||
memset(maskandmode, '\0', sizeof(maskandmode));
|
||||
memset(maskandnotmode, '\0', sizeof(maskandnotmode));
|
||||
memset(secBufBaseM, 0, sizeof(secBufBaseM));
|
||||
memset(filterValueM, 0, sizeof(filterValueM));
|
||||
memset(filterMaskM, 0, sizeof(filterMaskM));
|
||||
memset(filterModeM, 0, sizeof(filterModeM));
|
||||
memset(maskAndModeM, 0, sizeof(maskAndModeM));
|
||||
memset(maskAndNotModeM, 0, sizeof(maskAndNotModeM));
|
||||
|
||||
filter_value[0] = Tid;
|
||||
filter_mask[0] = Mask;
|
||||
filterValueM[0] = tidP;
|
||||
filterMaskM[0] = maskP;
|
||||
|
||||
// Invert the filter
|
||||
for (i = 0; i < DMX_MAX_FILTER_SIZE; ++i)
|
||||
filter_value[i] ^= 0xff;
|
||||
filterValueM[i] ^= 0xFF;
|
||||
|
||||
uint8_t mask, mode, local_doneq = 0;
|
||||
uint8_t mask, mode, doneq = 0;
|
||||
for (i = 0; i < DMX_MAX_FILTER_SIZE; ++i) {
|
||||
mode = filter_mode[i];
|
||||
mask = filter_mask[i];
|
||||
maskandmode[i] = (uint8_t)(mask & mode);
|
||||
maskandnotmode[i] = (uint8_t)(mask & ~mode);
|
||||
local_doneq |= maskandnotmode[i];
|
||||
mode = filterModeM[i];
|
||||
mask = filterMaskM[i];
|
||||
maskAndModeM[i] = (uint8_t)(mask & mode);
|
||||
maskAndNotModeM[i] = (uint8_t)(mask & ~mode);
|
||||
doneq |= maskAndNotModeM[i];
|
||||
}
|
||||
doneq = local_doneq ? 1 : 0;
|
||||
doneqM = doneq ? 1 : 0;
|
||||
|
||||
// Create filtering buffer
|
||||
ringbuffer = new cRingBufferLinear(KILOBYTE(128), 0, false, *cString::sprintf("IPTV SECTION %d/%d", devid, pid));
|
||||
if (ringbuffer)
|
||||
ringbuffer->SetTimeouts(10, 10);
|
||||
ringbufferM = new cRingBufferLinear(KILOBYTE(128), 0, false, *cString::sprintf("IPTV SECTION %d/%d", devIdM, pidM));
|
||||
if (ringbufferM)
|
||||
ringbufferM->SetTimeouts(10, 10);
|
||||
else
|
||||
error("Failed to allocate buffer for section filter (device=%d pid=%d): ", devid, pid);
|
||||
error("Failed to allocate buffer for section filter (device=%d pid=%d): ", devIdM, pidM);
|
||||
}
|
||||
|
||||
cIptvSectionFilter::~cIptvSectionFilter()
|
||||
{
|
||||
//debug("cIptvSectionFilter::~cIptvSectionfilter(%d, %d)\n", devid, pid);
|
||||
DELETE_POINTER(ringbuffer);
|
||||
secbuf = NULL;
|
||||
//debug("cIptvSectionFilter::~cIptvSectionfilter(%d, %d)\n", devIdM, pidM);
|
||||
DELETE_POINTER(ringbufferM);
|
||||
secBufM = NULL;
|
||||
}
|
||||
|
||||
int cIptvSectionFilter::Read(void *Data, size_t Length)
|
||||
{
|
||||
int count = 0;
|
||||
uchar *p = ringbuffer->Get(count);
|
||||
uchar *p = ringbufferM->Get(count);
|
||||
if (p && count > 0) {
|
||||
memcpy(Data, p, count);
|
||||
ringbuffer->Del(count);
|
||||
ringbufferM->Del(count);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
inline uint16_t cIptvSectionFilter::GetLength(const uint8_t *Data)
|
||||
inline uint16_t cIptvSectionFilter::GetLength(const uint8_t *dataP)
|
||||
{
|
||||
return (uint16_t)(3 + ((Data[1] & 0x0f) << 8) + Data[2]);
|
||||
return (uint16_t)(3 + ((dataP[1] & 0x0f) << 8) + dataP[2]);
|
||||
}
|
||||
|
||||
void cIptvSectionFilter::New(void)
|
||||
{
|
||||
tsfeedp = secbufp = seclen = 0;
|
||||
secbuf = secbuf_base;
|
||||
tsFeedpM = secBufpM = secLenM = 0;
|
||||
secBufM = secBufBaseM;
|
||||
}
|
||||
|
||||
int cIptvSectionFilter::Filter(void)
|
||||
{
|
||||
if (secbuf) {
|
||||
if (secBufM) {
|
||||
int i;
|
||||
uint8_t neq = 0;
|
||||
|
||||
for (i = 0; i < DMX_MAX_FILTER_SIZE; ++i) {
|
||||
uint8_t local_xor = (uint8_t)(filter_value[i] ^ secbuf[i]);
|
||||
if (maskandmode[i] & local_xor)
|
||||
uint8_t calcxor = (uint8_t)(filterValueM[i] ^ secBufM[i]);
|
||||
if (maskAndModeM[i] & calcxor)
|
||||
return 0;
|
||||
neq |= (maskandnotmode[i] & local_xor);
|
||||
neq |= (maskAndNotModeM[i] & calcxor);
|
||||
}
|
||||
|
||||
if (doneq && !neq)
|
||||
if (doneqM && !neq)
|
||||
return 0;
|
||||
|
||||
if (ringbuffer) {
|
||||
int len = ringbuffer->Put(secbuf, seclen);
|
||||
if (len != seclen)
|
||||
ringbuffer->ReportOverflow(seclen - len);
|
||||
if (ringbufferM) {
|
||||
int len = ringbufferM->Put(secBufM, secLenM);
|
||||
if (len != secLenM)
|
||||
ringbufferM->ReportOverflow(secLenM - len);
|
||||
// Update statistics
|
||||
AddSectionStatistic(len, 1);
|
||||
}
|
||||
@@ -114,56 +114,56 @@ inline int cIptvSectionFilter::Feed(void)
|
||||
{
|
||||
if (Filter() < 0)
|
||||
return -1;
|
||||
seclen = 0;
|
||||
secLenM = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cIptvSectionFilter::CopyDump(const uint8_t *buf, uint8_t len)
|
||||
int cIptvSectionFilter::CopyDump(const uint8_t *bufP, uint8_t lenP)
|
||||
{
|
||||
uint16_t limit, seclen_local, n;
|
||||
uint16_t limit, seclen, n;
|
||||
|
||||
if (tsfeedp >= DMX_MAX_SECFEED_SIZE)
|
||||
if (tsFeedpM >= DMX_MAX_SECFEED_SIZE)
|
||||
return 0;
|
||||
|
||||
if (tsfeedp + len > DMX_MAX_SECFEED_SIZE)
|
||||
len = (uint8_t)(DMX_MAX_SECFEED_SIZE - tsfeedp);
|
||||
if (tsFeedpM + lenP > DMX_MAX_SECFEED_SIZE)
|
||||
lenP = (uint8_t)(DMX_MAX_SECFEED_SIZE - tsFeedpM);
|
||||
|
||||
if (len <= 0)
|
||||
if (lenP <= 0)
|
||||
return 0;
|
||||
|
||||
memcpy(secbuf_base + tsfeedp, buf, len);
|
||||
tsfeedp = uint16_t(tsfeedp + len);
|
||||
memcpy(secBufBaseM + tsFeedpM, bufP, lenP);
|
||||
tsFeedpM = uint16_t(tsFeedpM + lenP);
|
||||
|
||||
limit = tsfeedp;
|
||||
limit = tsFeedpM;
|
||||
if (limit > DMX_MAX_SECFEED_SIZE)
|
||||
return -1; // internal error should never happen
|
||||
|
||||
// Always set secbuf
|
||||
secbuf = secbuf_base + secbufp;
|
||||
secBufM = secBufBaseM + secBufpM;
|
||||
|
||||
for (n = 0; secbufp + 2 < limit; ++n) {
|
||||
seclen_local = GetLength(secbuf);
|
||||
if ((seclen_local <= 0) || (seclen_local > DMX_MAX_SECTION_SIZE) || ((seclen_local + secbufp) > limit))
|
||||
for (n = 0; secBufpM + 2 < limit; ++n) {
|
||||
seclen = GetLength(secBufM);
|
||||
if ((seclen <= 0) || (seclen > DMX_MAX_SECTION_SIZE) || ((seclen + secBufpM) > limit))
|
||||
return 0;
|
||||
seclen = seclen_local;
|
||||
if (pusi_seen)
|
||||
secLenM = seclen;
|
||||
if (pusiSeenM)
|
||||
Feed();
|
||||
secbufp = uint16_t(secbufp + seclen_local);
|
||||
secbuf += seclen_local;
|
||||
secBufpM = uint16_t(secBufpM + seclen);
|
||||
secBufM += seclen;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cIptvSectionFilter::Process(const uint8_t* Data)
|
||||
void cIptvSectionFilter::Process(const uint8_t* dataP)
|
||||
{
|
||||
if (Data[0] != TS_SYNC_BYTE)
|
||||
if (dataP[0] != TS_SYNC_BYTE)
|
||||
return;
|
||||
|
||||
// Stop if not the PID this filter is looking for
|
||||
if (ts_pid(Data) != pid)
|
||||
if (ts_pid(dataP) != pidM)
|
||||
return;
|
||||
|
||||
uint8_t count = payload(Data);
|
||||
uint8_t count = payload(dataP);
|
||||
|
||||
// Check if no payload or out of range
|
||||
if (count == 0)
|
||||
@@ -172,41 +172,41 @@ void cIptvSectionFilter::Process(const uint8_t* Data)
|
||||
// Payload start
|
||||
uint8_t p = (uint8_t)(TS_SIZE - count);
|
||||
|
||||
uint8_t cc = (uint8_t)(Data[3] & 0x0f);
|
||||
int ccok = ((feedcc + 1) & 0x0f) == cc;
|
||||
feedcc = cc;
|
||||
uint8_t cc = (uint8_t)(dataP[3] & 0x0f);
|
||||
int ccok = ((feedCcM + 1) & 0x0f) == cc;
|
||||
feedCcM = cc;
|
||||
|
||||
int dc_i = 0;
|
||||
if (Data[3] & 0x20) {
|
||||
if (dataP[3] & 0x20) {
|
||||
// Adaption field present, check for discontinuity_indicator
|
||||
if ((Data[4] > 0) && (Data[5] & 0x80))
|
||||
if ((dataP[4] > 0) && (dataP[5] & 0x80))
|
||||
dc_i = 1;
|
||||
}
|
||||
|
||||
if (!ccok || dc_i) {
|
||||
// Discontinuity detected. Reset pusi_seen = 0 to
|
||||
// Discontinuity detected. Reset pusiSeenM = 0 to
|
||||
// stop feeding of suspicious data until next PUSI=1 arrives
|
||||
pusi_seen = 0;
|
||||
pusiSeenM = 0;
|
||||
New();
|
||||
}
|
||||
|
||||
if (Data[1] & 0x40) {
|
||||
if (dataP[1] & 0x40) {
|
||||
// PUSI=1 (is set), section boundary is here
|
||||
if (count > 1 && Data[p] < count) {
|
||||
const uint8_t *before = &Data[p + 1];
|
||||
uint8_t before_len = Data[p];
|
||||
if (count > 1 && dataP[p] < count) {
|
||||
const uint8_t *before = &dataP[p + 1];
|
||||
uint8_t before_len = dataP[p];
|
||||
const uint8_t *after = &before[before_len];
|
||||
uint8_t after_len = (uint8_t)(count - 1 - before_len);
|
||||
CopyDump(before, before_len);
|
||||
|
||||
// Before start of new section, set pusi_seen = 1
|
||||
pusi_seen = 1;
|
||||
// Before start of new section, set pusiSeenM = 1
|
||||
pusiSeenM = 1;
|
||||
New();
|
||||
CopyDump(after, after_len);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// PUSI=0 (is not set), no section boundary
|
||||
CopyDump(&Data[p], count);
|
||||
CopyDump(&dataP[p], count);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user