changeset 33033:1aed51b973fa

Ensure we always pass a buffer of at least sector size to the read function. This is never an issue with streams that have actual sectors, the reads will always return a multiple of sector size and the cache is always used in blocks of sector size. However the rtp protocol misuses this so it can just assume it always has a sufficiently large buffer available and thus fails without this extra hack.
author reimar
date Sat, 26 Mar 2011 20:04:47 +0000
parents dba2e7218893
children e97e23af7e8f
files stream/cache2.c
diffstat 1 files changed, 18 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/stream/cache2.c	Sat Mar 26 18:37:05 2011 +0000
+++ b/stream/cache2.c	Sat Mar 26 20:04:47 2011 +0000
@@ -168,6 +168,7 @@
   int back,back2,newb,space,len,pos;
   off_t read=s->read_filepos;
   int read_chunk;
+  int wraparound_copy = 0;
 
   if(read<s->min_filepos || read>s->max_filepos){
       // seek...
@@ -209,8 +210,16 @@
 
 //  printf("### read=0x%X  back=%d  newb=%d  space=%d  pos=%d\n",read,back,newb,space,pos);
 
-  // reduce space if needed:
-  if(space>s->buffer_size-pos) space=s->buffer_size-pos;
+  // try to avoid wrap-around. If not possible due to sector size
+  // do an extra copy.
+  if(space>s->buffer_size-pos) {
+    if (s->buffer_size-pos >= s->sector_size) {
+      space=s->buffer_size-pos;
+    } else {
+      space = s->sector_size;
+      wraparound_copy = 1;
+    }
+  }
 
   // limit one-time block size
   read_chunk = s->stream->read_chunk;
@@ -225,6 +234,13 @@
   s->min_filepos=read-back; // avoid seeking-back to temp area...
 #endif
 
+  if (wraparound_copy) {
+    int to_copy;
+    len = stream_read_internal(s->stream, s->stream->buffer, space);
+    to_copy = FFMIN(len, s->buffer_size-pos);
+    memcpy(s->buffer + pos, s->stream->buffer, to_copy);
+    memcpy(s->buffer, s->stream->buffer + to_copy, len - to_copy);
+  } else
   len = stream_read_internal(s->stream, &s->buffer[pos], space);
   s->eof= !len;