Mailing List archive

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

[linux-dvb] Towards demux section rewrite....



HI

I was also experimenting with rewritten section code.

Namely, in the section code there are many 'special' cases
in the form of if()'s. 

However some cases that look 'special' at first glance
can be often generalized, therefore leading to code clarity
and simplicity.

Here is my attempt to rewrite section demux. Because I'm
not a dvb/ip encapsulator expert, the code is not working
especially great, the packet loss is mostly the same as before,

(it passes some bogus section packets, so there are IP/MPE warnings 
from the kernel).

So this can only serve as example of how nice and simple but
functional section code could look like.

Emard

--- dvb_demux.c.orig	Sun Nov  9 14:43:56 2003
+++ dvb_demux_new.c	Sun Nov  9 14:51:28 2003
@@ -89,14 +89,15 @@
 
 static inline int payload(const u8 *tsp)
 {
-	if (!(tsp[3] & 0x10)) // no payload?
+	if ((tsp[3] & 0x10) == 0) // adaptation field without payload or reserved for future use
 		return 0;
 
 	if (tsp[3] & 0x20) {  // adaptation field?
 		if (tsp[4] > 183)    // corrupted data?
 			return 0;
 		else
-			return 184-1-tsp[4];
+			return 184-1-tsp[4]; // warning payload is AFTER adaptation fielda 
+		// tsp[4] is payload length without the length byte itself
 	}
 
 	return 184;
@@ -221,128 +222,105 @@
 }
 
 
+void dvb_dmx_swfilter_section_payload(struct dvb_demux_feed *feed, const u8 *buf, u8 len)
+{
+	struct dvb_demux *demux = feed->demux;
+	struct dmx_section_feed *sec = &feed->feed.sec;
+	u8 copy_len;
+	u16 sec_len;
+
+	// append payload we got (don't let it exceed 
+	// maximum section length), then calculate length
+	// (if applicable)
+	// and if the final packet length
+	// fits the section length in section header
+	// then feed the section
+	
+	/* truncate copy length, never override section buffer size */
+	copy_len = sec->secbufp + len > 4096 ? 4096 - sec->secbufp : len;
+	
+	/* FIXME: start next section in a while() loop if there are
+	** excess data for more than one section
+	*/
+  
+	/* append the payload to the section buffer */
+	if(copy_len > 0)
+	{
+		demux->memcopy (feed, sec->secbuf + sec->secbufp,
+				buf, copy_len);
+		sec->secbufp += copy_len;
+	}
+  
+	/* for 3 (or more) bytes we can calculate the section length */
+	/* for 4 (or more) bytes there could be some payload to feed */
+	if(sec->secbufp >= 3)
+	{
+		sec_len = section_length(sec->secbuf);
+		if(sec_len <= 4096) // section including its header is never more than 4096 bytes long
+		{
+			sec->seclen = sec_len;
+			/* if the section length + header length fits in the section buffer 
+			** length, then feed the section (feed->filter->call the callback)
+			*/
+			if(sec->seclen <= sec->secbufp)
+			{
+				// printk("SECLEN %d\n", sec->seclen);
+				sec->secbufp = sec->seclen;
+				dvb_dmx_swfilter_section_feed(feed);
+				// reset secbufp because it has been used
+				sec->secbufp = 0;
+				sec->crc_val = ~0;
+			}
+		}
+	}
+}
+
 static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, const u8 *buf) 
 {
 	struct dvb_demux *demux = feed->demux;
 	struct dmx_section_feed *sec = &feed->feed.sec;
-	int p, count;
-	int ccok, rest;
+	u8 p;
+	u8 count;
+	int ccok;
 	u8 cc;
-
-	if (!(count = payload(buf)))
+	
+	if ((count = payload(buf)) == 0)
 		return -1;
-
-	p = 188-count;
-
+	
+	p = 188-count; // start of the payload
+	
 	cc = buf[3] & 0x0f;
 	ccok = ((feed->cc+1) & 0x0f) == cc ? 1 : 0;
 	feed->cc = cc;
-
+	
 	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
+		if (p + 1 + buf[p] > 188) // trash if it points beyond packet
 			return -1;
-
+		
 		if (buf[p] && ccok) { // rest of previous section?
-			// did we have enough data in last packet to calc length?
-			int tmp = 3 - sec->secbufp;
-
-			if (tmp > 0 && tmp != 3) {
-				if (p + tmp >= 187)
-					return -1;
-
-				demux->memcopy (feed, sec->secbuf+sec->secbufp,
-					       buf+p+1, tmp);
-
-				sec->seclen = section_length(sec->secbuf);
-
-				if (sec->seclen > 4096) 
-					return -1;
-			}
-
-			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);
-			}
+			dvb_dmx_swfilter_section_payload(feed, buf+p+1, buf[p]);
 		}
-
-		p += buf[p] + 1; 		// skip rest of last section
+		
+		p += 1 + buf[p]; 		// skip rest of last section
 		count = 188 - p;
-
-		while (count > 0) {
-
-			sec->crc_val = ~0;
-
-			if ((count>2) && // enough data to determine sec length?
-			    ((sec->seclen = section_length(buf+p)) <= count)) {
-				if (sec->seclen>4096) 
-					return -1;
-
-				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
-				demux->memcopy(feed, sec->secbuf, buf+p, count);
-				sec->secbufp+=count;
-				count=0;
-			}
-		}
-
+		
+		sec->crc_val = ~0;
+		sec->secbufp = 0;
+		if(count > 0)
+			dvb_dmx_swfilter_section_payload(feed, buf+p, count);
+		
 		return 0;
 	}
-
+	
 	// section continued below
 	if (!ccok)
+	{
+		printk("section discontinuity\n");
 		return -1;
-
-	if (!sec->secbufp) // any data in last ts packet?
-		return -1;
-
-	// did we have enough data in last packet to calc section length?
-	if (sec->secbufp < 3) {
-		int tmp = 3 - sec->secbufp;
-		
-		if (tmp>count)
-			return -1;
-
-		sec->crc_val = ~0;
-
-		demux->memcopy (feed, sec->secbuf + sec->secbufp, buf+p, tmp);
-
-		sec->seclen = section_length(sec->secbuf);
-
-		if (sec->seclen > 4096) 
-			return -1;
 	}
-
-	rest = sec->seclen - sec->secbufp;
-
-	if (rest < 0)
-		return -1;
-
-	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
-		demux->memcopy (feed, sec->secbuf + sec->secbufp, buf+p, count);
-		sec->secbufp += count;
-	}
-
+	
+	dvb_dmx_swfilter_section_payload(feed, buf+p, count);
 	return 0;
 }
 

Home | Main Index | Thread Index