summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
authorHolger Waechtler <devnull@localhost>2003-12-02 12:01:26 +0000
committerHolger Waechtler <devnull@localhost>2003-12-02 12:01:26 +0000
commitd470469de4b9b0ae7d1815306a6713aa69b6244f (patch)
tree91641a0c759f2d0936a737c0476c566375912668 /linux
parent3680ccbf9a8c098794b1de328049ff9fe8c2cf55 (diff)
downloadmediapointer-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.h15
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_demux.c165
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;