> definitely valid - otherwise you could not use them for robust firmware 
> updates, DSMCC and MHP downloads etc.

Here's my try to chop off the individual memcopy's but althought
the code looks great and it's even not so cumbersome as I first
thouhgt, it doesn't work. :(. Let it lurk anyway, here maybe more
eyes can see more

Emard
--- /usr/local/src/dvb-kernel/linux/drivers/media/dvb/dvb-core/dvb_demux.c      
2003-12-30 13:58:16.000000000 +0100
+++ dvb_demux.c 2003-12-30 19:21:45.000000000 +0100
@@ -259,7 +259,7 @@ static int dvb_dmx_swfilter_section_copy
 {
        struct dvb_demux *demux = feed->demux;
        struct dmx_section_feed *sec = &feed->feed.sec;
-       u16 limit, seclen, n;
+       u16 limit, seclen, n, rest, offset;
 
        if(sec->tsfeedp >= DMX_MAX_SECFEED_SIZE)
                return 0;
@@ -276,7 +276,106 @@ static int dvb_dmx_swfilter_section_copy
        if(len <= 0)
                return 0;
 
-       demux->memcopy(feed, sec->secbuf_base + sec->tsfeedp, buf, len);
+       /* use cumbersome code for slow CPU that must 
+       ** calculate crc on-the-fly during demux->memcopy()
+       ** fast CPU better not execute cumbersome code
+       */
+       if(1 == 1)
+       {
+               /* cumbersome code starts here */
+               if(len < 2)
+               {
+                       /* boundary condition - here's the best we can do */
+                       demux->memcopy(feed, sec->secbuf_base + sec->tsfeedp, buf, 
len);
+                       goto proceed_dump;
+               }
+               /* enough bytes to patch the boundary condition, 
+               ** caution, this memcpy must be normal (no crc yet) 
+               */
+               memcpy(sec->secbuf_base + sec->tsfeedp, buf, 2);
+
+               limit = sec->tsfeedp;
+               /* to be sure always set secbuf */
+               sec->secbuf = sec->secbuf_base + sec->secbufp;
+
+               /* processing stale data in buffer...
+               ** who knows in which state we are left so better
+               ** flush remnants if any. This for() loop should
+               ** in most cases be run only just to calculate 'rest'
+               ** and goto copy_limited;
+               ** for() it's is here also to gracefully clean up after
+               ** internal errors if they should ever happen
+               */
+               for(rest = 0; sec->secbufp < limit; )
+               {
+                       seclen = section_length(sec->secbuf);
+                       if(seclen <= 0 || seclen > DMX_MAX_SECFEED_SIZE)
+                               return 0;
+                       if(seclen + sec->secbufp > limit)
+                       {
+                               /* (rest = how many bytes from new buffer should be
+                               ** appended to the secbuf to get one complete section)
+                               */
+                               rest = seclen + sec->secbufp - limit;
+                               goto copy_limited;
+                       }
+                       /* internal error probably occured, try to
+                       ** gracefully fix the situation. We must reset
+                       ** crc though, in the given circumstances we
+                       ** can only dump correct data but without having
+                       ** correct crc from memcopy()
+                       */
+                       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 */
+               }
+       copy_limited:;
+               /* at this point, we enter the for()
+               ** loop with correct number of 'rest' bytes that
+               ** should be copied from the new buffer to the
+               ** secbufp to complete the section at the boundary
+               ** condition between data in secbufp and secbuf
+               ** offset is offset to tne new buffer that is
+               ** memcopyed each section separately with crc 
+               ** reset inbetween them
+               */
+               for(offset = 0; offset + rest <= len &&
+                               sec->secbufp + rest <= DMX_MAX_SECFEED_SIZE; )
+               {               
+                       if(rest > 0)
+                       {
+                               demux->memcopy(feed, sec->secbuf_base + sec->tsfeedp, 
buf + offset, rest);
+                               offset += rest;
+                               sec->tsfeedp += rest;
+
+                               limit = sec->tsfeedp;
+                               if(limit > DMX_MAX_SECFEED_SIZE)
+                                       return -1;
+
+                               seclen = section_length(sec->secbuf);
+                               if(seclen <= 0 || seclen > DMX_MAX_SECFEED_SIZE 
+                                  || seclen + sec->secbufp > limit)
+                                       return 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 */
+                               sec->crc_val = ~0; /* after feed, reset crc for the 
next section */
+                       }
+                       rest = section_length(buf + offset);
+                       if(rest <= 0)
+                               return 0;
+               }
+               return 0;
+       }
+
+       // demux->memcopy(feed, sec->secbuf_base + sec->tsfeedp, buf, len);
+       memcpy(sec->secbuf_base + sec->tsfeedp, buf, len);
+ proceed_dump:;
        sec->tsfeedp += len;
 
        /* -----------------------------------------------------
@@ -287,6 +386,7 @@ static int dvb_dmx_swfilter_section_copy
        if(limit > DMX_MAX_SECFEED_SIZE)
                return -1; /* internal error should never happen */
 
+
        /* to be sure always set secbuf */
        sec->secbuf = sec->secbuf_base + sec->secbufp;
 

Reply via email to