Mailing List archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[linux-dvb] [PATCH] Losless Section Demux version 1.4



HI All, specailly Holger and Ralph

Here's version 1.4 of LSD (Losless Section Demux).

I cleaned the code and incorporated Ralph's comments on latency 
and honouring of the continuity counter. Now the sections are 
dumped as soon as they are avaliable if they are considered
continuous.

Should someone look for missing data, he should look for the
bugs elsewhere, and definitely not in the LSD 1.4 because it 
receives sections 100% complete even in bounday conditions.

I improved the logging of the missing data and found out that only
data that doesn't go to sections are the continuous series of 0xff 
pad bytes. those 0xff's are used to fill up extra bandwidth if the 
section bandwidth can't use up the full ts band

I think we can let this patch go to CVS

Emard
diff -pur dvb-kernel.orig/linux/drivers/media/dvb/dvb-core/demux.h dvb-kernel/linux/drivers/media/dvb/dvb-core/demux.h
--- dvb-kernel.orig/linux/drivers/media/dvb/dvb-core/demux.h	2003-11-30 11:33:37.000000000 +0100
+++ dvb-kernel/linux/drivers/media/dvb/dvb-core/demux.h	2003-11-29 23:09:11.000000000 +0100
@@ -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 -pur dvb-kernel.orig/linux/drivers/media/dvb/dvb-core/dvb_demux.c dvb-kernel/linux/drivers/media/dvb/dvb-core/dvb_demux.c
--- dvb-kernel.orig/linux/drivers/media/dvb/dvb-core/dvb_demux.c	2003-11-30 11:33:37.000000000 +0100
+++ dvb-kernel/linux/drivers/media/dvb/dvb-core/dvb_demux.c	2003-11-30 12:21:03.000000000 +0100
@@ -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_secti
 	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_secti
 			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_secti
 }
 
 
+
+#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_pack
 	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_filter
 		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(
 	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;
 

Home | Main Index | Thread Index