diff options
author | Holger Waechtler <devnull@localhost> | 2003-12-02 12:01:26 +0000 |
---|---|---|
committer | Holger Waechtler <devnull@localhost> | 2003-12-02 12:01:26 +0000 |
commit | d470469de4b9b0ae7d1815306a6713aa69b6244f (patch) | |
tree | 91641a0c759f2d0936a737c0476c566375912668 /linux | |
parent | 3680ccbf9a8c098794b1de328049ff9fe8c2cf55 (diff) | |
download | mediapointer-dvb-s2-d470469de4b9b0ae7d1815306a6713aa69b6244f.tar.gz mediapointer-dvb-s2-d470469de4b9b0ae7d1815306a6713aa69b6244f.tar.bz2 |
emard's new section demux code. Please test!
Diffstat (limited to 'linux')
-rw-r--r-- | linux/drivers/media/dvb/dvb-core/demux.h | 15 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dvb-core/dvb_demux.c | 165 |
2 files changed, 171 insertions, 9 deletions
diff --git a/linux/drivers/media/dvb/dvb-core/demux.h b/linux/drivers/media/dvb/dvb-core/demux.h index 5ceb6f2c8..03e12b683 100644 --- a/linux/drivers/media/dvb/dvb-core/demux.h +++ b/linux/drivers/media/dvb/dvb-core/demux.h @@ -44,6 +44,15 @@ #endif /* + * DMX_MAX_SECFEED_SIZE: Maximum length (in bytes) of a private section feed filter. + */ + +#ifndef DMX_MAX_SECFEED_SIZE +#define DMX_MAX_SECFEED_SIZE 4096 +#endif + + +/* * enum dmx_success: Success codes for the Demux Callback API. */ @@ -143,9 +152,9 @@ struct dmx_section_feed { int check_crc; u32 crc_val; - u8 secbuf[4096]; - int secbufp; - int seclen; + u8 *secbuf; + u8 secbuf_base[DMX_MAX_SECFEED_SIZE]; + u16 secbufp, seclen, tsfeedp; int (*set) (struct dmx_section_feed* feed, u16 pid, diff --git a/linux/drivers/media/dvb/dvb-core/dvb_demux.c b/linux/drivers/media/dvb/dvb-core/dvb_demux.c index b2716a616..2dee75948 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_demux.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_demux.c @@ -87,7 +87,7 @@ static inline u16 ts_pid(const u8 *buf) } -static inline int payload(const u8 *tsp) +static inline u8 payload(const u8 *tsp) { if (!(tsp[3] & 0x10)) // no payload? return 0; @@ -192,9 +192,6 @@ static inline int dvb_dmx_swfilter_section_feed (struct dvb_demux_feed *feed) u8 *buf = sec->secbuf; int section_syntax_indicator; - if (sec->secbufp != sec->seclen) - return -1; - if (!sec->is_filtering) return 0; @@ -213,7 +210,7 @@ static inline int dvb_dmx_swfilter_section_feed (struct dvb_demux_feed *feed) return -1; } while ((f = f->next) && sec->is_filtering); - sec->secbufp = sec->seclen = 0; + sec->seclen = 0; memset(buf, 0, DVB_DEMUX_MASK_MAX); @@ -221,6 +218,157 @@ static inline int dvb_dmx_swfilter_section_feed (struct dvb_demux_feed *feed) } + +#if 1 +/* +** #define DVB_DEMUX_SECTION_LOSS_LOG to monitor payload loss in the syslog +*/ +// #define DVB_DEMUX_SECTION_LOSS_LOG + +static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed) +{ + struct dmx_section_feed *sec = &feed->feed.sec; + +#ifdef DVB_DEMUX_SECTION_LOSS_LOG + if(sec->secbufp < sec->tsfeedp) + { + int i, n = sec->tsfeedp - sec->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(sec->secbuf[0] != 0xff || sec->secbuf[n-1] != 0xff) + { + printk("dvb_demux.c section ts padding loss: %d/%d\n", + n, sec->tsfeedp); + printk("dvb_demux.c pad data:"); + for(i = 0; i < n; i++) + printk(" %02x", sec->secbuf[i]); + printk("\n"); + } + } +#endif + + sec->tsfeedp = sec->secbufp = sec->seclen = 0; + sec->secbuf = sec->secbuf_base; +} + +/* +** Losless Section Demux 1.4 by Emard +*/ +static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed, const u8 *buf, u8 len) +{ + struct dvb_demux *demux = feed->demux; + struct dmx_section_feed *sec = &feed->feed.sec; + u16 limit, seclen, n; + + if(sec->tsfeedp >= DMX_MAX_SECFEED_SIZE) + return 0; + + if(sec->tsfeedp + len > DMX_MAX_SECFEED_SIZE) + { +#ifdef DVB_DEMUX_SECTION_LOSS_LOG + printk("dvb_demux.c section buffer full loss: %d/%d\n", + sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE, DMX_MAX_SECFEED_SIZE); +#endif + len = DMX_MAX_SECFEED_SIZE - sec->tsfeedp; + } + + if(len <= 0) + return 0; + + demux->memcopy(feed, sec->secbuf_base + sec->tsfeedp, buf, len); + sec->tsfeedp += len; + + /* ----------------------------------------------------- + ** Dump all the sections we can find in the data (Emard) + */ + + limit = sec->tsfeedp; + if(limit > DMX_MAX_SECFEED_SIZE) + return -1; /* internal error shoud never happen */ + + /* to be sure always set secbuf */ + sec->secbuf = sec->secbuf_base + sec->secbufp; + + for(n = 0; sec->secbufp + 2 < limit; n++) + { + seclen = section_length(sec->secbuf); + if(seclen <= 0 || seclen > DMX_MAX_SECFEED_SIZE + || seclen + sec->secbufp > limit) + return 0; + sec->seclen = seclen; + sec->crc_val = ~0; + /* dump [secbuf .. secbuf+seclen) */ + dvb_dmx_swfilter_section_feed(feed); + sec->secbufp += seclen; /* secbufp and secbuf moving together is */ + sec->secbuf += seclen; /* redundand but saves pointer arithmetic */ + } + + return 0; +} + + +static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, const u8 *buf) +{ + u8 p, count; + int ccok; + u8 cc; + + count = payload(buf); + + if (count == 0) /* count == 0 if no payload or out of range */ + return -1; + + p = 188-count; /* payload start */ + + cc = buf[3] & 0x0f; + ccok = ((feed->cc+1) & 0x0f) == cc ? 1 : 0; + feed->cc = cc; + if(ccok == 0) + { +#ifdef DVB_DEMUX_SECTION_LOSS_LOG + printk("dvb_demux.c discontinuity detected %d bytes lost\n", count); + /* those bytes under sume circumstances will again be reported + ** in the fullowing dvb_dmx_swfilter_section_new + */ +#endif + dvb_dmx_swfilter_section_new(feed); + return 0; + } + + if(buf[1] & 0x40) + { + // PUSI=1 (is set), section boundary is here + if(count > 1 && buf[p] < count) + { + const u8 *before = buf+p+1; + u8 before_len = buf[p]; + const u8 *after = before+before_len; + u8 after_len = count-1-before_len; + + dvb_dmx_swfilter_section_copy_dump(feed, before, before_len); + dvb_dmx_swfilter_section_new(feed); + dvb_dmx_swfilter_section_copy_dump(feed, after, after_len); + } +#ifdef DVB_DEMUX_SECTION_LOSS_LOG + else + if(count > 0) + printk("dvb_demux.c PUSI=1 but %d bytes lost\n", count); +#endif + } + else + { + // PUSI=0 (is not set), no section boundary + const u8 *entire = buf+p; + u8 entire_len = count; + + dvb_dmx_swfilter_section_copy_dump(feed, entire, entire_len); + } + return 0; +} +#else static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, const u8 *buf) { struct dvb_demux *demux = feed->demux; @@ -346,6 +494,7 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, const u8 return 0; } +#endif static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, const u8 *buf) { @@ -904,6 +1053,8 @@ static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed) return -EINVAL; } + dvbdmxfeed->feed.sec.tsfeedp = 0; + dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base; dvbdmxfeed->feed.sec.secbufp = 0; dvbdmxfeed->feed.sec.seclen = 0; @@ -1009,7 +1160,9 @@ static int dvbdmx_allocate_section_feed(struct dmx_demux *demux, dvbdmxfeed->cb.sec = callback; dvbdmxfeed->demux = dvbdmx; dvbdmxfeed->pid = 0xffff; - dvbdmxfeed->feed.sec.secbufp = 0; + dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base; + dvbdmxfeed->feed.sec.secbufp = dvbdmxfeed->feed.sec.seclen = 0; + dvbdmxfeed->feed.sec.tsfeedp = 0; dvbdmxfeed->filter = 0; dvbdmxfeed->buffer = 0; |