diff options
author | Holger Waechtler <devnull@localhost> | 2002-11-08 20:36:16 +0000 |
---|---|---|
committer | Holger Waechtler <devnull@localhost> | 2002-11-08 20:36:16 +0000 |
commit | c6aaa123a676ccc478380f5ecf867cc05af855ae (patch) | |
tree | a071985cc9d2bd9cdb11220a4880c2eab82914c0 /linux/drivers | |
parent | 8d4dcb931ddd8841655a31b872a936a516eefac4 (diff) | |
download | mediapointer-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/drivers')
-rw-r--r-- | linux/drivers/media/dvb/dvb-core/demux.h | 7 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dvb-core/dvb_demux.c | 211 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dvb-core/dvb_demux.h | 15 |
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 |