Mailing List archive

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

[linux-dvb] Re: [PATCH] section demux rewritten



Hi,

at a first glance your code looks good but I didn't had the time to analyze and test it more in detail. If some people report it working without bugs I'd like to apply your patch. Johannes, Michael - what do you think? Should we start an experimental branch for this or should this go into the main trunk?

Holger


Emard wrote:
HI all


After I read the specs, and I understood what was the functional
purpose of the old code (gosh, what a messy coding) I rewrote it cleanly.

The direct improvement compared to the old code is that the
new one properly handles all PUSI boundary conditions without intrudicing additionaly level of buffering and copying

Another news is that this code now can track the section payload
loss.

The new code's logic builds a sequential chunk of data between each PUSI=1 bit and uses section start "pointer" byte to determine the end the sequential chunk
After the sequential chunk is complete, it may contain one or more sections. Section separation loop starts at the begin of the
chunk, calculates the section_length, calls the section_dump code
and adds to the pointer section_length bytes to jump to the next potential section, until the end of the sequential chunk is reached.

There are safety if() to cleanly handle the out-of-boundary data,
corrupted streams etc. (no crash during my tests).

I think this code can even be applied to the CVS,
but it would be good that others test it too.

Owners of non-7146 full TS cards, please test and post syslog of network when active receiving packets with compiled in #define TRACK_LOSS in dvb_demux.c after the attached patch
it will printk() how may bytes of TS payload are lost (and not gone into the section).
short guide:

# dvbnet -p 451
# ifconfig dvb0_0 inet 1.2.3.4
# ifconfig dvb0_0 promisc
# szap -r hsi &
# tail -f /var/log/syslog

Best regards, Emard



------------------------------------------------------------------------

diff -pur ../dvb-kernel/linux/drivers/media/dvb/dvb-core/demux.h dvb-kernel/linux/drivers/media/dvb/dvb-core/demux.h
--- ../dvb-kernel/linux/drivers/media/dvb/dvb-core/demux.h 2003-11-23 21:18:12.000000000 +0100
+++ dvb-kernel/linux/drivers/media/dvb/dvb-core/demux.h 2003-11-23 15:27:01.000000000 +0100
@@ -143,7 +143,8 @@ struct dmx_section_feed { int check_crc;
u32 crc_val;
- u8 secbuf[4096];
+ u8 *secbuf;
+ u8 secbuf_real[16384];
int secbufp;
int seclen;
diff -pur ../dvb-kernel/linux/drivers/media/dvb/dvb-core/dvb_demux.c dvb-kernel/linux/drivers/media/dvb/dvb-core/dvb_demux.c
--- ../dvb-kernel/linux/drivers/media/dvb/dvb-core/dvb_demux.c 2003-11-23 21:18:12.000000000 +0100
+++ dvb-kernel/linux/drivers/media/dvb/dvb-core/dvb_demux.c 2003-11-23 21:06:26.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;
@@ -221,6 +221,122 @@ static inline int dvb_dmx_swfilter_secti
}
+
+#if 1
+static int dvb_dmx_swfilter_section_buffer_dump(struct dvb_demux_feed *feed)
+{
+ struct dmx_section_feed *sec = &feed->feed.sec;
+ u8 *buf;
+ u16 p = 0, count, seclen;
+ int n = 0;
+
+ buf = sec->secbuf;
+ count = sec->secbufp;
+ seclen = count;
+
+// goto exit;
+
+ for(p = 0; p + 2 < count; n++)
+ {
+ seclen = section_length(buf + p);
+ if(seclen <= 0 || seclen > 4096 || seclen + p > count)
+ goto exit;
+ /* some would view next 2 lines as a slight hack,
+ ** but it's a good one, saving a lot of code and CPU
+ */
+ sec->secbuf = buf + p;
+ sec->seclen = sec->secbufp = seclen;
+ sec->crc_val = ~0;
+ dvb_dmx_swfilter_section_feed(feed); /* dump single secbuf */
+ p += seclen;
+ }
+
+ exit:; /* restore buffer memory pointer and reset pointer values before exit */
+#ifdef TRACK_LOSS
+ if(p < count)
+ printk("dvb_demux.c section syntax loss: %d/%d (n=%d)\n",
+ count - p, count, n);
+#endif
+ sec->secbuf = buf;
+ sec->seclen = sec->secbufp = 0;
+
+ return 0;
+}
+
+#define MAX_SECBUFP 4096
+
+static int dvb_dmx_swfilter_section_truncate_copy(struct dvb_demux_feed *feed, const u8 *buf, u8 len)
+{
+ struct dvb_demux *demux = feed->demux;
+ struct dmx_section_feed *sec = &feed->feed.sec;
+
+ if(sec->secbufp >= MAX_SECBUFP)
+ return 0;
+
+ if(sec->secbufp + len > MAX_SECBUFP)
+ {
+#ifdef TRACK_LOSS
+ printk("dvb_demux.c section buffer full loss: %d/%d\n", + sec->secbufp + len - MAX_SECBUFP, MAX_SECBUFP);
+#endif
+ len = MAX_SECBUFP - sec->secbufp;
+ }
+ if(len > 0)
+ {
+ demux->memcopy(feed, sec->secbuf + sec->secbufp, buf, len);
+ sec->secbufp += len;
+ }
+ 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(buf[1] & 0x40)
+ {
+ // PUSI 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_truncate_copy(feed, before, before_len);
+ dvb_dmx_swfilter_section_buffer_dump(feed);
+ dvb_dmx_swfilter_section_truncate_copy(feed, after, after_len);
+ }
+#ifdef TRACK_LOSS
+ else
+ printk("dvb_demux.c PUSI set and %d bytes lost\n", count);
+#endif
+ }
+ else
+ {
+ // PUSI is not set, no section boundary
+ const u8 *entire = buf+p;
+ u8 entire_len = count;
+
+ dvb_dmx_swfilter_section_truncate_copy(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 +462,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)
{
@@ -1009,6 +1126,7 @@ static int dvbdmx_allocate_section_feed(
dvbdmxfeed->cb.sec = callback;
dvbdmxfeed->demux = dvbdmx;
dvbdmxfeed->pid = 0xffff;
+ dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_real;
dvbdmxfeed->feed.sec.secbufp = 0;
dvbdmxfeed->filter = 0;
dvbdmxfeed->buffer = 0;
Only in dvb-kernel/linux/drivers/media/dvb/dvb-core: dvb_demux.c~



--
Info:
To unsubscribe send a mail to ecartis@linuxtv.org with "unsubscribe linux-dvb" as subject.



Home | Main Index | Thread Index