mirror of
https://github.com/rofafor/vdr-plugin-iptv.git
synced 2023-10-10 13:37:03 +02:00
Refactored section filter class.
This commit is contained in:
parent
024ee7ba89
commit
abf0a5ece4
1
HISTORY
1
HISTORY
@ -88,3 +88,4 @@ VDR Plugin 'iptv' Revision History
|
|||||||
2009-xx-xx: Version 0.2.4
|
2009-xx-xx: Version 0.2.4
|
||||||
|
|
||||||
- Optimized TS packet data flow.
|
- Optimized TS packet data flow.
|
||||||
|
- Refactored section filter class.
|
||||||
|
2
common.h
2
common.h
@ -41,6 +41,8 @@
|
|||||||
|
|
||||||
#define SECTION_FILTER_TABLE_SIZE 7
|
#define SECTION_FILTER_TABLE_SIZE 7
|
||||||
|
|
||||||
|
#define TS_SYNC_BYTE 0x47
|
||||||
|
|
||||||
#define ERROR_IF_FUNC(exp, errstr, func, ret) \
|
#define ERROR_IF_FUNC(exp, errstr, func, ret) \
|
||||||
do { \
|
do { \
|
||||||
if (exp) { \
|
if (exp) { \
|
||||||
|
4
device.c
4
device.c
@ -333,7 +333,7 @@ int cIptvDevice::OpenFilter(u_short Pid, u_char Tid, u_char Mask)
|
|||||||
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
|
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
|
||||||
if (!secfilters[i]) {
|
if (!secfilters[i]) {
|
||||||
//debug("cIptvDevice::OpenFilter(%d): Pid=%d Tid=%02X Mask=%02X Index=%d\n", deviceIndex, Pid, Tid, Mask, i);
|
//debug("cIptvDevice::OpenFilter(%d): Pid=%d Tid=%02X Mask=%02X Index=%d\n", deviceIndex, Pid, Tid, Mask, i);
|
||||||
secfilters[i] = new cIptvSectionFilter(i, deviceIndex, Pid, Tid, Mask);
|
secfilters[i] = new cIptvSectionFilter(deviceIndex, i, Pid, Tid, Mask);
|
||||||
return secfilters[i]->GetReadDesc();
|
return secfilters[i]->GetReadDesc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -438,7 +438,7 @@ bool cIptvDevice::GetTSPacket(uchar *&Data)
|
|||||||
// Run the data through all filters
|
// Run the data through all filters
|
||||||
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
|
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
|
||||||
if (secfilters[i])
|
if (secfilters[i])
|
||||||
secfilters[i]->ProcessData(p);
|
secfilters[i]->Process(p);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
206
sectionfilter.c
206
sectionfilter.c
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#include "sectionfilter.h"
|
#include "sectionfilter.h"
|
||||||
|
|
||||||
cIptvSectionFilter::cIptvSectionFilter(int Index, int devInd,
|
cIptvSectionFilter::cIptvSectionFilter(int DeviceIndex, int Index,
|
||||||
u_short Pid, u_char Tid, u_char Mask)
|
u_short Pid, u_char Tid, u_char Mask)
|
||||||
: pusi_seen(0),
|
: pusi_seen(0),
|
||||||
feedcc(0),
|
feedcc(0),
|
||||||
@ -17,10 +17,13 @@ cIptvSectionFilter::cIptvSectionFilter(int Index, int devInd,
|
|||||||
seclen(0),
|
seclen(0),
|
||||||
tsfeedp(0),
|
tsfeedp(0),
|
||||||
pid(Pid),
|
pid(Pid),
|
||||||
|
devid(DeviceIndex),
|
||||||
id(Index),
|
id(Index),
|
||||||
pipeName("")
|
pipeName("")
|
||||||
{
|
{
|
||||||
//debug("cIptvSectionFilter::cIptvSectionFilter(%d)\n", Index);
|
//debug("cIptvSectionFilter::cIptvSectionFilter(%d, %d)\n", devid, id);
|
||||||
|
int i;
|
||||||
|
|
||||||
memset(secbuf_base, '\0', sizeof(secbuf_base));
|
memset(secbuf_base, '\0', sizeof(secbuf_base));
|
||||||
memset(filter_value, '\0', sizeof(filter_value));
|
memset(filter_value, '\0', sizeof(filter_value));
|
||||||
memset(filter_mask, '\0', sizeof(filter_mask));
|
memset(filter_mask, '\0', sizeof(filter_mask));
|
||||||
@ -28,17 +31,15 @@ cIptvSectionFilter::cIptvSectionFilter(int Index, int devInd,
|
|||||||
memset(maskandmode, '\0', sizeof(maskandmode));
|
memset(maskandmode, '\0', sizeof(maskandmode));
|
||||||
memset(maskandnotmode, '\0', sizeof(maskandnotmode));
|
memset(maskandnotmode, '\0', sizeof(maskandnotmode));
|
||||||
|
|
||||||
SetPipeName(devInd);
|
|
||||||
|
|
||||||
filter_value[0] = Tid;
|
filter_value[0] = Tid;
|
||||||
filter_mask[0] = Mask;
|
filter_mask[0] = Mask;
|
||||||
|
|
||||||
// Invert the filter
|
// Invert the filter
|
||||||
for (int i = 0; i < DMX_MAX_FILTER_SIZE; ++i)
|
for (i = 0; i < DMX_MAX_FILTER_SIZE; ++i)
|
||||||
filter_value[i] ^= 0xff;
|
filter_value[i] ^= 0xff;
|
||||||
|
|
||||||
uint8_t mask, mode, local_doneq = 0;
|
uint8_t mask, mode, local_doneq = 0;
|
||||||
for (int i = 0; i < DMX_MAX_FILTER_SIZE; ++i) {
|
for (i = 0; i < DMX_MAX_FILTER_SIZE; ++i) {
|
||||||
mode = filter_mode[i];
|
mode = filter_mode[i];
|
||||||
mask = filter_mask[i];
|
mask = filter_mask[i];
|
||||||
maskandmode[i] = mask & mode;
|
maskandmode[i] = mask & mode;
|
||||||
@ -47,11 +48,12 @@ cIptvSectionFilter::cIptvSectionFilter(int Index, int devInd,
|
|||||||
doneq = local_doneq ? 1 : 0;
|
doneq = local_doneq ? 1 : 0;
|
||||||
|
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
|
pipeName = cString::sprintf(IPTV_FILTER_FILENAME, devid, id);
|
||||||
stat(pipeName, &sb);
|
stat(pipeName, &sb);
|
||||||
if (S_ISFIFO(sb.st_mode))
|
if (S_ISFIFO(sb.st_mode))
|
||||||
unlink(pipeName);
|
unlink(pipeName);
|
||||||
int err = mknod(pipeName, 0644 | S_IFIFO, 0);
|
i = mknod(pipeName, 0644 | S_IFIFO, 0);
|
||||||
ERROR_IF_RET(err < 0, "mknod()", return);
|
ERROR_IF_RET(i < 0, "mknod()", return);
|
||||||
|
|
||||||
// Create descriptors
|
// Create descriptors
|
||||||
fifoDescriptor = open(pipeName, O_RDWR | O_NONBLOCK);
|
fifoDescriptor = open(pipeName, O_RDWR | O_NONBLOCK);
|
||||||
@ -60,7 +62,7 @@ cIptvSectionFilter::cIptvSectionFilter(int Index, int devInd,
|
|||||||
|
|
||||||
cIptvSectionFilter::~cIptvSectionFilter()
|
cIptvSectionFilter::~cIptvSectionFilter()
|
||||||
{
|
{
|
||||||
//debug("cIptvSectionFilter::~cIptvSectionfilter(%d)\n", id);
|
//debug("cIptvSectionFilter::~cIptvSectionfilter(%d, %d)\n", devid, id);
|
||||||
close(fifoDescriptor);
|
close(fifoDescriptor);
|
||||||
close(readDescriptor);
|
close(readDescriptor);
|
||||||
unlink(pipeName);
|
unlink(pipeName);
|
||||||
@ -68,119 +70,65 @@ cIptvSectionFilter::~cIptvSectionFilter()
|
|||||||
readDescriptor = -1;
|
readDescriptor = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cIptvSectionFilter::SetPipeName(int deviceIndex)
|
int cIptvSectionFilter::GetReadDesc(void)
|
||||||
{
|
|
||||||
pipeName = cString::sprintf(IPTV_FILTER_FILENAME, deviceIndex, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
int cIptvSectionFilter::GetReadDesc()
|
|
||||||
{
|
{
|
||||||
return readDescriptor;
|
return readDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint16_t cIptvSectionFilter::section_length(const uint8_t *buf)
|
inline uint16_t cIptvSectionFilter::GetLength(const uint8_t *Data)
|
||||||
{
|
{
|
||||||
return 3 + ((buf[1] & 0x0f) << 8) + buf[2];
|
return 3 + ((Data[1] & 0x0f) << 8) + Data[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
int cIptvSectionFilter::dmxdev_section_callback(const uint8_t *buffer1, size_t buffer1_len,
|
void cIptvSectionFilter::New(void)
|
||||||
const uint8_t *buffer2, size_t buffer2_len,
|
|
||||||
enum dmx_success success)
|
|
||||||
{
|
{
|
||||||
// See if there is data in the fifo
|
|
||||||
int retval = select_single_desc(fifoDescriptor, 0, false);
|
|
||||||
// There is no data in the fifo, more can be written
|
|
||||||
if (!retval) {
|
|
||||||
#ifdef DEBUG_PRINTF
|
|
||||||
printf("id = %d, pid %d would now write %d data to buffer\n", id, pid, buffer1_len);
|
|
||||||
for (unsigned int i = 0; i < buffer1_len; ++i)
|
|
||||||
printf("0x%X ", buffer1[i]);
|
|
||||||
printf("\n");
|
|
||||||
#endif
|
|
||||||
retval = write(fifoDescriptor, buffer1, buffer1_len);
|
|
||||||
ERROR_IF(retval < 0, "write()");
|
|
||||||
// Update statistics
|
|
||||||
AddSectionStatistic(retval, 1);
|
|
||||||
}
|
|
||||||
#ifdef DEBUG_PRINTF
|
|
||||||
else if (retval)
|
|
||||||
printf("id %d pid %d data is already present\n", id, pid);
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cIptvSectionFilter::demux_swfilter_section_new()
|
|
||||||
{
|
|
||||||
#ifdef DEMUX_SECTION_LOSS_LOG
|
|
||||||
if (secbufp < tsfeedp) {
|
|
||||||
int i, n = tsfeedp - secbufp;
|
|
||||||
/*
|
|
||||||
* Section padding is done with 0xff bytes entirely.
|
|
||||||
* Due to speed reasons, we won't check all of them
|
|
||||||
* but just first and last.
|
|
||||||
*/
|
|
||||||
if (secbuf[0] != 0xff || secbuf[n - 1] != 0xff) {
|
|
||||||
printf("sectionfilter.c section ts padding loss: %d/%d\n",
|
|
||||||
n, tsfeedp);
|
|
||||||
printf("sectionfilter.c pad data:");
|
|
||||||
for (i = 0; i < n; ++i)
|
|
||||||
printf(" %02x", secbuf[i]);
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
tsfeedp = secbufp = seclen = 0;
|
tsfeedp = secbufp = seclen = 0;
|
||||||
secbuf = secbuf_base;
|
secbuf = secbuf_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cIptvSectionFilter::demux_swfilter_sectionfilter()
|
int cIptvSectionFilter::Filter(void)
|
||||||
{
|
{
|
||||||
uint8_t neq = 0;
|
uint8_t neq = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < DMX_MAX_FILTER_SIZE; ++i) {
|
for (i = 0; i < DMX_MAX_FILTER_SIZE; ++i) {
|
||||||
uint8_t local_xor = filter_value[i] ^ secbuf[i];
|
uint8_t local_xor = filter_value[i] ^ secbuf[i];
|
||||||
if (maskandmode[i] & local_xor) {
|
if (maskandmode[i] & local_xor)
|
||||||
#ifdef DEBUG_PRINTF
|
|
||||||
printf("maskandmode discard\n");
|
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
neq |= maskandnotmode[i] & local_xor;
|
neq |= maskandnotmode[i] & local_xor;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doneq && !neq) {
|
if (doneq && !neq)
|
||||||
#ifdef DEBUG_PRINTF
|
|
||||||
printf("doneq discard, doneq = 0x%X, neq = 0x%X\n", doneq, !neq);
|
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
// There is no data in the fifo, more can be written
|
||||||
|
if (!select_single_desc(fifoDescriptor, 0, false)) {
|
||||||
|
i = write(fifoDescriptor, secbuf, seclen);
|
||||||
|
ERROR_IF(i < 0, "write()");
|
||||||
|
// Update statistics
|
||||||
|
AddSectionStatistic(i, 1);
|
||||||
}
|
}
|
||||||
return dmxdev_section_callback(secbuf, seclen, NULL, 0, DMX_OK);
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int cIptvSectionFilter::demux_swfilter_section_feed()
|
inline int cIptvSectionFilter::Feed(void)
|
||||||
{
|
{
|
||||||
if (demux_swfilter_sectionfilter() < 0)
|
if (Filter() < 0)
|
||||||
return -1;
|
return -1;
|
||||||
seclen = 0;
|
seclen = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cIptvSectionFilter::demux_swfilter_section_copy_dump(const uint8_t *buf, uint8_t len)
|
int cIptvSectionFilter::CopyDump(const uint8_t *buf, uint8_t len)
|
||||||
{
|
{
|
||||||
uint16_t limit, seclen_local, n;
|
uint16_t limit, seclen_local, n;
|
||||||
|
|
||||||
if (tsfeedp >= DMX_MAX_SECFEED_SIZE)
|
if (tsfeedp >= DMX_MAX_SECFEED_SIZE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (tsfeedp + len > DMX_MAX_SECFEED_SIZE) {
|
if (tsfeedp + len > DMX_MAX_SECFEED_SIZE)
|
||||||
#ifdef DEMUX_SECTION_LOSS_LOG
|
|
||||||
printf("sectionfilter.c section buffer full loss: %d/%d\n",
|
|
||||||
tsfeedp + len - DMX_MAX_SECFEED_SIZE,
|
|
||||||
DMX_MAX_SECFEED_SIZE);
|
|
||||||
#endif
|
|
||||||
len = DMX_MAX_SECFEED_SIZE - tsfeedp;
|
len = DMX_MAX_SECFEED_SIZE - tsfeedp;
|
||||||
}
|
|
||||||
|
|
||||||
if (len <= 0)
|
if (len <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
@ -188,108 +136,80 @@ int cIptvSectionFilter::demux_swfilter_section_copy_dump(const uint8_t *buf, uin
|
|||||||
memcpy(secbuf_base + tsfeedp, buf, len);
|
memcpy(secbuf_base + tsfeedp, buf, len);
|
||||||
tsfeedp += len;
|
tsfeedp += len;
|
||||||
|
|
||||||
/*
|
|
||||||
* Dump all the sections we can find in the data (Emard)
|
|
||||||
*/
|
|
||||||
limit = tsfeedp;
|
limit = tsfeedp;
|
||||||
if (limit > DMX_MAX_SECFEED_SIZE)
|
if (limit > DMX_MAX_SECFEED_SIZE)
|
||||||
return -1; /* internal error should never happen */
|
return -1; // internal error should never happen
|
||||||
|
|
||||||
/* to be sure always set secbuf */
|
// Always set secbuf
|
||||||
secbuf = secbuf_base + secbufp;
|
secbuf = secbuf_base + secbufp;
|
||||||
|
|
||||||
for (n = 0; secbufp + 2 < limit; ++n) {
|
for (n = 0; secbufp + 2 < limit; ++n) {
|
||||||
seclen_local = section_length(secbuf);
|
seclen_local = GetLength(secbuf);
|
||||||
if (seclen_local <= 0 || seclen_local > DMX_MAX_SECTION_SIZE ||
|
if (seclen_local <= 0 || seclen_local > DMX_MAX_SECTION_SIZE ||
|
||||||
seclen_local + secbufp > limit)
|
seclen_local + secbufp > limit)
|
||||||
return 0;
|
return 0;
|
||||||
#ifdef DEBUG_PRINTF
|
|
||||||
printf("Non-mismatching seclen! %d, limit = %d\n", seclen_local, limit);
|
|
||||||
#endif
|
|
||||||
seclen = seclen_local;
|
seclen = seclen_local;
|
||||||
/* dump [secbuf .. secbuf+seclen) */
|
|
||||||
if (pusi_seen)
|
if (pusi_seen)
|
||||||
demux_swfilter_section_feed();
|
Feed();
|
||||||
#ifdef DEMUX_SECTION_LOSS_LOG
|
secbufp += seclen_local;
|
||||||
else
|
secbuf += seclen_local;
|
||||||
printf("sectionfilter.c pusi not seen, discarding section data\n");
|
|
||||||
#endif
|
|
||||||
secbufp += seclen_local; /* secbufp and secbuf moving together is */
|
|
||||||
secbuf += seclen_local; /* redundant but saves pointer arithmetic */
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cIptvSectionFilter::ProcessData(const uint8_t* buf)
|
void cIptvSectionFilter::Process(const uint8_t* Data)
|
||||||
{
|
{
|
||||||
if (buf[0] != 0x47) {
|
if (Data[0] != TS_SYNC_BYTE)
|
||||||
error("Not TS packet: 0x%X\n", buf[0]);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// Stop if not the PID this filter is looking for
|
// Stop if not the PID this filter is looking for
|
||||||
if (ts_pid(buf) != pid)
|
if (ts_pid(Data) != pid)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint8_t count = payload(buf);
|
uint8_t count = payload(Data);
|
||||||
|
|
||||||
if (count == 0) /* count == 0 if no payload or out of range */
|
// Check if no payload or out of range
|
||||||
|
if (count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint8_t p = 188 - count; /* payload start */
|
// Payload start
|
||||||
|
uint8_t p = TS_SIZE - count;
|
||||||
|
|
||||||
uint8_t cc = buf[3] & 0x0f;
|
uint8_t cc = Data[3] & 0x0f;
|
||||||
int ccok = ((feedcc + 1) & 0x0f) == cc;
|
int ccok = ((feedcc + 1) & 0x0f) == cc;
|
||||||
feedcc = cc;
|
feedcc = cc;
|
||||||
|
|
||||||
int dc_i = 0;
|
int dc_i = 0;
|
||||||
if (buf[3] & 0x20) {
|
if (Data[3] & 0x20) {
|
||||||
/* adaption field present, check for discontinuity_indicator */
|
// Adaption field present, check for discontinuity_indicator
|
||||||
if ((buf[4] > 0) && (buf[5] & 0x80))
|
if ((Data[4] > 0) && (Data[5] & 0x80))
|
||||||
dc_i = 1;
|
dc_i = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ccok || dc_i) {
|
if (!ccok || dc_i) {
|
||||||
#ifdef DEMUX_SECTION_LOSS_LOG
|
// Discontinuity detected. Reset pusi_seen = 0 to
|
||||||
printf("sectionfilter.c discontinuity detected %d bytes lost\n",
|
// stop feeding of suspicious data until next PUSI=1 arrives
|
||||||
count);
|
|
||||||
/*
|
|
||||||
* those bytes under sume circumstances will again be reported
|
|
||||||
* in the following demux_swfilter_section_new
|
|
||||||
*/
|
|
||||||
#endif
|
|
||||||
/*
|
|
||||||
* Discontinuity detected. Reset pusi_seen = 0 to
|
|
||||||
* stop feeding of suspicious data until next PUSI=1 arrives
|
|
||||||
*/
|
|
||||||
pusi_seen = 0;
|
pusi_seen = 0;
|
||||||
demux_swfilter_section_new();
|
New();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf[1] & 0x40) {
|
if (Data[1] & 0x40) {
|
||||||
/* PUSI=1 (is set), section boundary is here */
|
// PUSI=1 (is set), section boundary is here
|
||||||
if (count > 1 && buf[p] < count) {
|
if (count > 1 && Data[p] < count) {
|
||||||
#ifdef DEBUG_PRINTF
|
const uint8_t *before = &Data[p + 1];
|
||||||
printf("Valid section\n");
|
uint8_t before_len = Data[p];
|
||||||
#endif
|
|
||||||
const uint8_t *before = &buf[p + 1];
|
|
||||||
uint8_t before_len = buf[p];
|
|
||||||
const uint8_t *after = &before[before_len];
|
const uint8_t *after = &before[before_len];
|
||||||
uint8_t after_len = (count - 1) - before_len;
|
uint8_t after_len = (count - 1) - before_len;
|
||||||
|
CopyDump(before, before_len);
|
||||||
|
|
||||||
demux_swfilter_section_copy_dump(before, before_len);
|
// Before start of new section, set pusi_seen = 1
|
||||||
/* before start of new section, set pusi_seen = 1 */
|
|
||||||
pusi_seen = 1;
|
pusi_seen = 1;
|
||||||
demux_swfilter_section_new();
|
New();
|
||||||
demux_swfilter_section_copy_dump(after, after_len);
|
CopyDump(after, after_len);
|
||||||
}
|
}
|
||||||
#ifdef DEMUX_SECTION_LOSS_LOG
|
|
||||||
else if (count > 0)
|
|
||||||
printf("sectionfilter.c PUSI=1 but %d bytes lost\n", count);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* PUSI=0 (is not set), no section boundary */
|
// PUSI=0 (is not set), no section boundary
|
||||||
demux_swfilter_section_copy_dump(&buf[p], count);
|
CopyDump(&Data[p], count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,18 +8,7 @@
|
|||||||
#ifndef __IPTV_SECTIONFILTER_H
|
#ifndef __IPTV_SECTIONFILTER_H
|
||||||
#define __IPTV_SECTIONFILTER_H
|
#define __IPTV_SECTIONFILTER_H
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <vdr/device.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <libgen.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "statistics.h"
|
#include "statistics.h"
|
||||||
@ -27,19 +16,19 @@
|
|||||||
class cIptvSectionFilter : public cIptvSectionStatistics {
|
class cIptvSectionFilter : public cIptvSectionStatistics {
|
||||||
private:
|
private:
|
||||||
enum dmx_success {
|
enum dmx_success {
|
||||||
DMX_OK = 0, /* Received Ok */
|
DMX_OK = 0, // Received OK
|
||||||
DMX_LENGTH_ERROR, /* Incorrect length */
|
DMX_LENGTH_ERROR, // Incorrect length
|
||||||
DMX_OVERRUN_ERROR, /* Receiver ring buffer overrun */
|
DMX_OVERRUN_ERROR, // Receiver ring buffer overrun
|
||||||
DMX_CRC_ERROR, /* Incorrect CRC */
|
DMX_CRC_ERROR, // Incorrect CRC
|
||||||
DMX_FRAME_ERROR, /* Frame alignment error */
|
DMX_FRAME_ERROR, // Frame alignment error
|
||||||
DMX_FIFO_ERROR, /* Receiver FIFO overrun */
|
DMX_FIFO_ERROR, // Receiver FIFO overrun
|
||||||
DMX_MISSED_ERROR /* Receiver missed packet */
|
DMX_MISSED_ERROR // Receiver missed packet
|
||||||
};
|
};
|
||||||
|
|
||||||
enum dmx_limits {
|
enum dmx_limits {
|
||||||
DMX_MAX_FILTER_SIZE = 18,
|
DMX_MAX_FILTER_SIZE = 18,
|
||||||
DMX_MAX_SECTION_SIZE = 4096,
|
DMX_MAX_SECTION_SIZE = 4096,
|
||||||
DMX_MAX_SECFEED_SIZE = (DMX_MAX_SECTION_SIZE + 188)
|
DMX_MAX_SECFEED_SIZE = (DMX_MAX_SECTION_SIZE + TS_SIZE)
|
||||||
};
|
};
|
||||||
|
|
||||||
int fifoDescriptor;
|
int fifoDescriptor;
|
||||||
@ -55,7 +44,10 @@ private:
|
|||||||
uint16_t seclen;
|
uint16_t seclen;
|
||||||
uint16_t tsfeedp;
|
uint16_t tsfeedp;
|
||||||
uint16_t pid;
|
uint16_t pid;
|
||||||
|
|
||||||
|
int devid;
|
||||||
int id;
|
int id;
|
||||||
|
cString pipeName;
|
||||||
|
|
||||||
uint8_t filter_value[DMX_MAX_FILTER_SIZE];
|
uint8_t filter_value[DMX_MAX_FILTER_SIZE];
|
||||||
uint8_t filter_mask[DMX_MAX_FILTER_SIZE];
|
uint8_t filter_mask[DMX_MAX_FILTER_SIZE];
|
||||||
@ -64,40 +56,20 @@ private:
|
|||||||
uint8_t maskandmode[DMX_MAX_FILTER_SIZE];
|
uint8_t maskandmode[DMX_MAX_FILTER_SIZE];
|
||||||
uint8_t maskandnotmode[DMX_MAX_FILTER_SIZE];
|
uint8_t maskandnotmode[DMX_MAX_FILTER_SIZE];
|
||||||
|
|
||||||
cString pipeName;
|
inline uint16_t GetLength(const uint8_t *Data);
|
||||||
|
void New(void);
|
||||||
inline uint16_t section_length(const uint8_t *buf);
|
int Filter(void);
|
||||||
|
inline int Feed(void);
|
||||||
int dmxdev_section_callback(const uint8_t *buffer1,
|
int CopyDump(const uint8_t *buf, uint8_t len);
|
||||||
size_t buffer1_len,
|
|
||||||
const uint8_t *buffer2,
|
|
||||||
size_t buffer2_len,
|
|
||||||
enum dmx_success success);
|
|
||||||
|
|
||||||
void demux_swfilter_section_new();
|
|
||||||
|
|
||||||
int demux_swfilter_sectionfilter();
|
|
||||||
|
|
||||||
inline int demux_swfilter_section_feed();
|
|
||||||
|
|
||||||
int demux_swfilter_section_copy_dump(const uint8_t *buf,
|
|
||||||
uint8_t len);
|
|
||||||
|
|
||||||
int GetFifoDesc();
|
|
||||||
void ClearPipeName();
|
|
||||||
void SetPipeName(int deviceIndex);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// constructor & destructor
|
// constructor & destructor
|
||||||
cIptvSectionFilter(int Index, int devInd, u_short Pid, u_char Tid,
|
cIptvSectionFilter(int Index, int DeviceIndex, u_short Pid,
|
||||||
u_char Mask);
|
u_char Tid, u_char Mask);
|
||||||
|
|
||||||
virtual ~cIptvSectionFilter();
|
virtual ~cIptvSectionFilter();
|
||||||
|
void Process(const uint8_t* Data);
|
||||||
void ProcessData(const uint8_t* buf);
|
int GetReadDesc(void);
|
||||||
|
uint16_t GetPid(void) { return pid; }
|
||||||
int GetReadDesc();
|
|
||||||
uint16_t GetPid() { return pid; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __IPTV_SECTIONFILTER_H
|
#endif // __IPTV_SECTIONFILTER_H
|
||||||
|
15
socket.c
15
socket.c
@ -51,10 +51,11 @@ bool cIptvSocket::OpenSocket(const int Port, const bool isUdp)
|
|||||||
socketDesc = socket(PF_INET, SOCK_STREAM, 0);
|
socketDesc = socket(PF_INET, SOCK_STREAM, 0);
|
||||||
ERROR_IF_RET(socketDesc < 0, "socket()", return false);
|
ERROR_IF_RET(socketDesc < 0, "socket()", return false);
|
||||||
// Make it use non-blocking I/O to avoid stuck read calls
|
// Make it use non-blocking I/O to avoid stuck read calls
|
||||||
ERROR_IF_FUNC(fcntl(socketDesc, F_SETFL, O_NONBLOCK), "fcntl()", CloseSocket(), return false);
|
ERROR_IF_FUNC(fcntl(socketDesc, F_SETFL, O_NONBLOCK), "fcntl()",
|
||||||
|
CloseSocket(), return false);
|
||||||
// Allow multiple sockets to use the same PORT number
|
// Allow multiple sockets to use the same PORT number
|
||||||
ERROR_IF_FUNC(setsockopt(socketDesc, SOL_SOCKET, SO_REUSEADDR, &yes,
|
ERROR_IF_FUNC(setsockopt(socketDesc, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0, "setsockopt()",
|
||||||
sizeof(yes)) < 0, "setsockopt()", CloseSocket(), return false);
|
CloseSocket(), return false);
|
||||||
// Bind socket
|
// Bind socket
|
||||||
memset(&sockAddr, '\0', sizeof(sockAddr));
|
memset(&sockAddr, '\0', sizeof(sockAddr));
|
||||||
sockAddr.sin_family = AF_INET;
|
sockAddr.sin_family = AF_INET;
|
||||||
@ -111,7 +112,7 @@ int cIptvUdpSocket::Read(unsigned char* BufferAddr, unsigned int BufferLen)
|
|||||||
if (isActive)
|
if (isActive)
|
||||||
len = recvfrom(socketDesc, BufferAddr, BufferLen, MSG_DONTWAIT,
|
len = recvfrom(socketDesc, BufferAddr, BufferLen, MSG_DONTWAIT,
|
||||||
(struct sockaddr *)&sockAddr, &addrlen);
|
(struct sockaddr *)&sockAddr, &addrlen);
|
||||||
if ((len > 0) && (BufferAddr[0] == 0x47)) {
|
if ((len > 0) && (BufferAddr[0] == TS_SYNC_BYTE)) {
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
else if (len > 3) {
|
else if (len > 3) {
|
||||||
@ -129,12 +130,14 @@ int cIptvUdpSocket::Read(unsigned char* BufferAddr, unsigned int BufferLen)
|
|||||||
// check if extension
|
// check if extension
|
||||||
if (x) {
|
if (x) {
|
||||||
// extension header length
|
// extension header length
|
||||||
unsigned int ehl = (((BufferAddr[headerlen + 2] & 0xFF) << 8) | (BufferAddr[headerlen + 3] & 0xFF));
|
unsigned int ehl = (((BufferAddr[headerlen + 2] & 0xFF) << 8) |
|
||||||
|
(BufferAddr[headerlen + 3] & 0xFF));
|
||||||
// update header length
|
// update header length
|
||||||
headerlen += (ehl + 1) * sizeof(uint32_t);
|
headerlen += (ehl + 1) * sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
// Check that rtp is version 2 and payload contains multiple of TS packet data
|
// Check that rtp is version 2 and payload contains multiple of TS packet data
|
||||||
if ((v == 2) && (((len - headerlen) % TS_SIZE) == 0) && (BufferAddr[headerlen] == 0x47)) {
|
if ((v == 2) && (((len - headerlen) % TS_SIZE) == 0) &&
|
||||||
|
(BufferAddr[headerlen] == TS_SYNC_BYTE)) {
|
||||||
// Set argument point to payload in read buffer
|
// Set argument point to payload in read buffer
|
||||||
memmove(BufferAddr, &BufferAddr[headerlen], (len - headerlen));
|
memmove(BufferAddr, &BufferAddr[headerlen], (len - headerlen));
|
||||||
return (len - headerlen);
|
return (len - headerlen);
|
||||||
|
@ -45,7 +45,7 @@ void cIptvStreamer::Action(void)
|
|||||||
int length = -1;
|
int length = -1;
|
||||||
if (protocol)
|
if (protocol)
|
||||||
length = protocol->Read(packetBuffer, packetBufferLen);
|
length = protocol->Read(packetBuffer, packetBufferLen);
|
||||||
if (length >= 0) {
|
if (length > 0) {
|
||||||
AddStreamerStatistic(length);
|
AddStreamerStatistic(length);
|
||||||
if (ringBuffer) {
|
if (ringBuffer) {
|
||||||
int p = ringBuffer->Put(packetBuffer, length);
|
int p = ringBuffer->Put(packetBuffer, length);
|
||||||
|
Loading…
Reference in New Issue
Block a user