summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
authorHolger Waechtler <devnull@localhost>2002-11-08 20:36:16 +0000
committerHolger Waechtler <devnull@localhost>2002-11-08 20:36:16 +0000
commitc6aaa123a676ccc478380f5ecf867cc05af855ae (patch)
treea071985cc9d2bd9cdb11220a4880c2eab82914c0 /linux
parent8d4dcb931ddd8841655a31b872a936a516eefac4 (diff)
downloadmediapointer-dvb-s2-c6aaa123a676ccc478380f5ecf867cc05af855ae.tar.gz
mediapointer-dvb-s2-c6aaa123a676ccc478380f5ecf867cc05af855ae.tar.bz2
- software section filter cleanup
- enable crc32 check again - add hooks for hardware accelerated memory transfer and crc32 checks (patch contributed by Florian Schirmer)
Diffstat (limited to 'linux')
-rw-r--r--linux/drivers/media/dvb/dvb-core/demux.h7
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_demux.c211
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_demux.h15
3 files changed, 152 insertions, 81 deletions
diff --git a/linux/drivers/media/dvb/dvb-core/demux.h b/linux/drivers/media/dvb/dvb-core/demux.h
index ce769ebf1..ceaa0c43b 100644
--- a/linux/drivers/media/dvb/dvb-core/demux.h
+++ b/linux/drivers/media/dvb/dvb-core/demux.h
@@ -144,6 +144,13 @@ struct dmx_section_feed_s {
int is_filtering; /* Set to non-zero when filtering in progress */
struct dmx_demux_s* parent; /* Back-pointer */
void* priv; /* Pointer to private data of the API client */
+
+ int check_crc;
+
+ u8 secbuf[4096];
+ int secbufp;
+ int seclen;
+
int (*set) (struct dmx_section_feed_s* feed,
__u16 pid,
size_t circular_buffer_size,
diff --git a/linux/drivers/media/dvb/dvb-core/dvb_demux.c b/linux/drivers/media/dvb/dvb-core/dvb_demux.c
index 0b199ef25..eeaf2b20a 100644
--- a/linux/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/linux/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -112,13 +112,30 @@ void dvb_set_crc32(u8 *data, int length)
{
u32 crc;
- crc=crc32_le(~0, data, length);
- data[length] = (crc>>24)&0xff;
- data[length+1] = (crc>>16)&0xff;
- data[length+2] = (crc>>8)&0xff;
- data[length+3] = (crc)&0xff;
+ crc = crc32_le(~0, data, length);
+
+ data[length] = (crc >> 24) & 0xff;
+ data[length+1] = (crc >> 16) & 0xff;
+ data[length+2] = (crc >> 8) & 0xff;
+ data[length+3] = (crc) & 0xff;
+}
+
+
+static
+u32 dvb_dmx_crc32 (struct dvb_demux_feed *dvbdmxfeed, u32 seed,
+ const u8 *src, size_t len)
+{
+ return crc32_le (seed, src, len);
+}
+
+
+static
+void dvb_dmx_memcopy (struct dvb_demux_feed *dvbdmxfeed, u8 *dst,
+ const u8 *src, size_t len)
+{
+ memcpy (dst, src, len);
}
-
+
/******************************************************************************
* Software filter functions
@@ -159,135 +176,176 @@ dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *dvbdmxfeed,
u8 xor, neq=0;
for (i=0; i<DVB_DEMUX_MASK_MAX; i++) {
- xor=filter->filter_value[i]^dvbdmxfeed->secbuf[i];
+ xor=filter->filter_value[i]^dvbdmxfeed->feed.sec.secbuf[i];
if (f->maskandmode[i]&xor)
return 0;
neq|=f->maskandnotmode[i]&xor;
}
+
if (f->doneq & !neq)
return 0;
- return dvbdmxfeed->cb.sec(dvbdmxfeed->secbuf, dvbdmxfeed->seclen,
+ return dvbdmxfeed->cb.sec(dvbdmxfeed->feed.sec.secbuf,
+ dvbdmxfeed->feed.sec.seclen,
0, 0, filter, DMX_OK);
}
static inline int
dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *dvbdmxfeed)
{
- u8 *buf=dvbdmxfeed->secbuf;
+ struct dvb_demux *demux = dvbdmxfeed->demux;
+ dmx_section_feed_t *sec = &dvbdmxfeed->feed.sec;
+ u8 *buf = sec->secbuf;
struct dvb_demux_filter *f;
- if (dvbdmxfeed->secbufp!=dvbdmxfeed->seclen)
+ if (sec->secbufp != sec->seclen)
return -1;
- if (!dvbdmxfeed->feed.sec.is_filtering)
+
+ if (!sec->is_filtering)
return 0;
- if (!(f=dvbdmxfeed->filter))
+
+ if (!(f = dvbdmxfeed->filter))
return 0;
- do
+
+ if (sec->check_crc &&
+ demux->check_crc32(dvbdmxfeed, ~0, sec->secbuf, sec->seclen))
+ return -1;
+
+ do {
if (dvb_dmx_swfilter_sectionfilter(dvbdmxfeed, f)<0)
return -1;
- while ((f=f->next) && dvbdmxfeed->feed.sec.is_filtering);
+ } while ((f = f->next) && sec->is_filtering);
- dvbdmxfeed->secbufp=dvbdmxfeed->seclen=0;
- memset(buf, 0, DVB_DEMUX_MASK_MAX);
- return 0;
+ sec->secbufp = sec->seclen = 0;
+
+ memset(buf, 0, DVB_DEMUX_MASK_MAX);
+
+ return 0;
}
-static inline int
-dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *dvbdmxfeed, const u8 *buf)
+
+static
+int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, const u8 *buf)
{
+ struct dvb_demux *demux = feed->demux;
+ dmx_section_feed_t *sec = &feed->feed.sec;
int p, count;
int ccok, rest;
u8 cc;
- if (!(count=payload(buf)))
+ if (!(count = payload(buf)))
return -1;
- p=188-count;
- cc=buf[3]&0x0f;
- ccok=((dvbdmxfeed->cc+1)&0x0f)==cc ? 1 : 0;
- dvbdmxfeed->cc=cc;
+ p = 188-count;
+
+ cc = buf[3]&0x0f;
+ ccok = ((feed->cc+1)&0x0f)==cc ? 1 : 0;
+ feed->cc = cc;
- if (buf[1]&0x40) { // PUSI set
+ if (buf[1] & 0x40) { // PUSI set
// offset to start of first section is in buf[p]
if (p+buf[p]>187) // trash if it points beyond packet
return -1;
- if (buf[p] && ccok) { // rest of previous section?
+
+ if (buf[p] && ccok) { // rest of previous section?
// did we have enough data in last packet to calc length?
- int tmp=3-dvbdmxfeed->secbufp;
- if (tmp>0 && tmp!=3) {
- if (p+tmp>=187)
+ int tmp = 3 - sec->secbufp;
+
+ if (tmp > 0 && tmp != 3) {
+ if (p + tmp >= 187)
return -1;
- memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp,
- buf+p+1, tmp);
- dvbdmxfeed->seclen=section_length(dvbdmxfeed->secbuf);
- if (dvbdmxfeed->seclen>4096)
+
+ demux->memcopy (feed, sec->secbuf+sec->secbufp,
+ buf+p+1, tmp);
+
+ sec->seclen = section_length(sec->secbuf);
+
+ if (sec->seclen > 4096)
return -1;
}
- rest=dvbdmxfeed->seclen-dvbdmxfeed->secbufp;
- if (rest==buf[p] && dvbdmxfeed->seclen) {
- memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp,
- buf+p+1, buf[p]);
- dvbdmxfeed->secbufp+=buf[p];
- dvb_dmx_swfilter_section_feed(dvbdmxfeed);
+
+ rest = sec->seclen - sec->secbufp;
+
+ if (rest == buf[p] && sec->seclen) {
+ demux->memcopy (feed, sec->secbuf + sec->secbufp,
+ buf+p+1, buf[p]);
+ sec->secbufp += buf[p];
+ dvb_dmx_swfilter_section_feed(feed);
}
}
- p+=buf[p]+1; // skip rest of last section
- count=188-p;
- while (count>0) {
- if ((count>2) && // enough data to determine sec length?
- ((dvbdmxfeed->seclen=section_length(buf+p))<=count)) {
- if (dvbdmxfeed->seclen>4096)
+
+ p += buf[p] + 1; // skip rest of last section
+ count = 188 - p;
+
+ while (count) {
+ if ((count>2) && // enough data to determine sec length?
+ ((sec->seclen = section_length(buf+p)) <= count)) {
+ if (sec->seclen>4096)
return -1;
- memcpy(dvbdmxfeed->secbuf, buf+p,
- dvbdmxfeed->seclen);
- dvbdmxfeed->secbufp=dvbdmxfeed->seclen;
- p+=dvbdmxfeed->seclen;
- count=188-p;
- dvb_dmx_swfilter_section_feed(dvbdmxfeed);
+
+ demux->memcopy (feed, sec->secbuf, buf+p,
+ sec->seclen);
+
+ sec->secbufp = sec->seclen;
+ p += sec->seclen;
+ count = 188 - p;
+
+ dvb_dmx_swfilter_section_feed(feed);
// filling bytes until packet end?
if (count && buf[p]==0xff)
count=0;
- } else { // section continues to following TS packet
- memcpy(dvbdmxfeed->secbuf, buf+p, count);
- dvbdmxfeed->secbufp+=count;
+
+ } else { // section continues to following TS packet
+ demux->memcopy(feed, sec->secbuf, buf+p, count);
+ sec->secbufp+=count;
count=0;
}
}
+
return 0;
}
// section continued below
if (!ccok)
return -1;
- if (!dvbdmxfeed->secbufp) // any data in last ts packet?
+
+ if (!sec->secbufp) // any data in last ts packet?
return -1;
+
// did we have enough data in last packet to calc section length?
- if (dvbdmxfeed->secbufp<3) {
- int tmp=3-dvbdmxfeed->secbufp;
+ if (sec->secbufp<3) {
+ int tmp = 3 - sec->secbufp;
if (tmp>count)
return -1;
- memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp, buf+p, tmp);
- dvbdmxfeed->seclen=section_length(dvbdmxfeed->secbuf);
- if (dvbdmxfeed->seclen>4096)
+
+ demux->memcopy (feed, sec->secbuf + sec->secbufp, buf+p, tmp);
+
+ sec->seclen = section_length(sec->secbuf);
+
+ if (sec->seclen > 4096)
return -1;
}
- rest=dvbdmxfeed->seclen-dvbdmxfeed->secbufp;
- if (rest<0)
+
+ rest = sec->seclen - sec->secbufp;
+
+ if (rest < 0)
return -1;
- if (rest<=count) { // section completed in this TS packet
- memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp, buf+p, rest);
- dvbdmxfeed->secbufp+=rest;
- dvb_dmx_swfilter_section_feed(dvbdmxfeed);
+
+ if (rest <= count) { // section completed in this TS packet
+ demux->memcopy (feed, sec->secbuf + sec->secbufp, buf+p, rest);
+ sec->secbufp += rest;
+ dvb_dmx_swfilter_section_feed(feed);
} else { // section continues in following ts packet
- memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp, buf+p, count);
- dvbdmxfeed->secbufp+=count;
+ demux->memcopy (feed, sec->secbuf + sec->secbufp, buf+p, count);
+ sec->secbufp += count;
}
+
return 0;
}
+
static inline void
dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *dvbdmxfeed, const u8 *buf)
{
@@ -312,7 +370,7 @@ dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *dvbdmxfeed, const u8 *buf)
if (!dvbdmxfeed->feed.sec.is_filtering)
break;
if (dvb_dmx_swfilter_section_packet(dvbdmxfeed, buf)<0)
- dvbdmxfeed->seclen=dvbdmxfeed->secbufp=0;
+ dvbdmxfeed->feed.sec.seclen=dvbdmxfeed->feed.sec.secbufp=0;
break;
default:
@@ -327,6 +385,7 @@ dvb_dmx_swfilter_packet(struct dvb_demux *dvbdmx, const u8 *buf)
if (!(dvbdmxfeed=dvbdmx->pid2feed[ts_pid(buf)]))
return;
+
dvb_dmx_swfilter_packet_type(dvbdmxfeed, buf);
}
@@ -717,7 +776,7 @@ dmx_section_feed_set(struct dmx_section_feed_s* feed,
return -ENOSYS;
}
- dvbdmxfeed->check_crc=check_crc;
+ dvbdmxfeed->feed.sec.check_crc=check_crc;
#ifdef NOBUFS
dvbdmxfeed->buffer=0;
#else
@@ -773,8 +832,8 @@ dmx_section_feed_start_filtering(dmx_section_feed_t *feed)
up(&dvbdmx->mutex);
return -EINVAL;
}
- dvbdmxfeed->secbufp=0;
- dvbdmxfeed->seclen=0;
+ dvbdmxfeed->feed.sec.secbufp=0;
+ dvbdmxfeed->feed.sec.seclen=0;
if (!dvbdmx->start_feed) {
up(&dvbdmx->mutex);
@@ -868,7 +927,7 @@ static int dvbdmx_allocate_section_feed(dmx_demux_t *demux,
dvbdmxfeed->cb.sec=callback;
dvbdmxfeed->demux=dvbdmx;
dvbdmxfeed->pid=0xffff;
- dvbdmxfeed->secbufp=0;
+ dvbdmxfeed->feed.sec.secbufp=0;
dvbdmxfeed->filter=0;
dvbdmxfeed->buffer=0;
@@ -1071,6 +1130,12 @@ dvb_dmx_init(struct dvb_demux *dvbdemux)
memset(dvbdemux->pid2feed, 0, (DMX_MAX_PID+1)*sizeof(struct dvb_demux_feed *));
dvbdemux->tsbufp=0;
+ if (!dvbdemux->check_crc32)
+ dvbdemux->check_crc32 = dvb_dmx_crc32;
+
+ if (!dvbdemux->memcopy)
+ dvbdemux->memcopy = dvb_dmx_memcopy;
+
dmx->frontend=0;
dmx->reg_list.next=dmx->reg_list.prev=&dmx->reg_list;
dmx->priv=(void *) dvbdemux;
diff --git a/linux/drivers/media/dvb/dvb-core/dvb_demux.h b/linux/drivers/media/dvb/dvb-core/dvb_demux.h
index e129c9ebf..c32cb3388 100644
--- a/linux/drivers/media/dvb/dvb-core/dvb_demux.h
+++ b/linux/drivers/media/dvb/dvb-core/dvb_demux.h
@@ -78,7 +78,6 @@ struct dvb_demux_feed {
u8 *buffer;
int buffer_size;
int descramble;
- int check_crc;
struct timespec timeout;
struct dvb_demux_filter *filter;
@@ -87,9 +86,6 @@ struct dvb_demux_feed {
int ts_type;
dmx_ts_pes_t pes_type;
- u8 secbuf[4096];
- int secbufp;
- int seclen;
int cc;
u16 peslen;
@@ -100,10 +96,13 @@ struct dvb_demux {
void *priv;
int filternum;
int feednum;
- int (*start_feed)(struct dvb_demux_feed *);
- int (*stop_feed)(struct dvb_demux_feed *);
- int (*write_to_decoder)(struct dvb_demux_feed *, u8 *, size_t);
-
+ int (*start_feed) (struct dvb_demux_feed *);
+ int (*stop_feed) (struct dvb_demux_feed *);
+ int (*write_to_decoder) (struct dvb_demux_feed *, u8 *buf, size_t len);
+ u32 (*check_crc32) (struct dvb_demux_feed *, u32 seed,
+ const u8 *buf, size_t len);
+ void (*memcopy) (struct dvb_demux_feed *, u8 *dst,
+ const u8 *src, size_t len);
int users;
#define MAX_DVB_DEMUX_USERS 10