int stream_read_internal(stream_t *s, void *buf, int len) { int orig_len = len; // we will retry even if we already reached EOF previously. switch(s->type){ case STREAMTYPE_STREAM: #ifdef CONFIG_NETWORKING if( s->streaming_ctrl!=NULL && s->streaming_ctrl->streaming_read ) { len=s->streaming_ctrl->streaming_read(s->fd, buf, len, s->streaming_ctrl); if (s->streaming_ctrl->status == streaming_stopped_e) s->eof = 1; } else #endif if (s->fill_buffer) len = s->fill_buffer(s, buf, len); else len = read(s->fd, buf, len); break; case STREAMTYPE_DS: len = demux_read_data((demux_stream_t*)s->priv, buf, len); break; default: len= s->fill_buffer ? s->fill_buffer(s, buf, len) : 0; } if(len<=0){ off_t pos = s->pos; // do not retry if this looks like proper eof if (s->eof || (s->end_pos && pos == s->end_pos)) goto eof_out; // dvdnav has some horrible hacks to "suspend" reads, // we need to skip this code or seeks will hang. if (s->type == STREAMTYPE_DVDNAV) goto eof_out; // just in case this is an error e.g. due to network // timeout reset and retry // Seeking is used as a hack to make network streams // reopen the connection, ideally they would implement // e.g. a STREAM_CTRL_RECONNECT to do this s->eof=1; stream_reset(s); if (stream_seek_internal(s, pos) >= 0 || s->pos != pos) // seek failed goto eof_out; // make sure EOF is set to ensure no endless loops s->eof=1; return stream_read_internal(s, buf, orig_len); eof_out: s->eof=1; return 0; } // When reading succeeded we are obviously not at eof. // This e.g. avoids issues with eof getting stuck when lavf seeks in MPEG-TS s->eof=0; s->pos+=len; return len; }
int stream_fill_buffer(stream_t *s){ int len = stream_read_internal(s, s->buffer, STREAM_BUFFER_SIZE); if (len <= 0) return 0; s->buf_pos=0; s->buf_len=len; // printf("[%d]",len);fflush(stdout); return len; }
int stream_fill_buffer(stream_t *s){ int len = stream_read_internal(s, s->buffer, STREAM_BUFFER_SIZE); if (len <= 0) return 0; s->buf_pos=0; s->buf_len=len; while (s->buf_len < STREAM_BUFFER_MIN) { assert(s->buf_len + STREAM_BUFFER_MIN < STREAM_BUFFER_SIZE); len = stream_read_internal(s, s->buffer + s->buf_len, STREAM_BUFFER_MIN); if (len <= 0) break; s->buf_len += len; } // since the first read succeeded we are // definitely not at EOF yet s->eof = 0; // printf("[%d]",len);fflush(stdout); if (s->capture_file) stream_capture_do(s); return s->buf_len; }
int stream_read_internal(stream_t *s, void *buf, int len) { int orig_len = len; // we will retry even if we already reached EOF previously. switch(s->type){ case STREAMTYPE_STREAM: #ifdef CONFIG_NETWORKING if( s->streaming_ctrl!=NULL && s->streaming_ctrl->streaming_read ) { len=s->streaming_ctrl->streaming_read(s->fd, buf, len, s->streaming_ctrl); if (s->streaming_ctrl->status == streaming_stopped_e && (!s->end_pos || s->pos == s->end_pos)) s->eof = 1; } else #endif if (s->fill_buffer) len = s->fill_buffer(s, buf, len); else len = read(s->fd, buf, len); break; case STREAMTYPE_DS: len = demux_read_data((demux_stream_t*)s->priv, buf, len); break; default: len= s->fill_buffer ? s->fill_buffer(s, buf, len) : 0; } if(len<=0){ // do not retry if this looks like proper eof if (s->eof || (s->end_pos && s->pos == s->end_pos)) goto eof_out; // just in case this is an error e.g. due to network // timeout reset and retry if (!stream_reconnect(s)) goto eof_out; // make sure EOF is set to ensure no endless loops s->eof=1; return stream_read_internal(s, buf, orig_len); eof_out: s->eof=1; return 0; } // When reading succeeded we are obviously not at eof. // This e.g. avoids issues with eof getting stuck when lavf seeks in MPEG-TS s->eof=0; s->pos+=len; return len; }
static int cache_fill(cache_vars_t *s) { 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... mp_msg(MSGT_CACHE,MSGL_DBG2,"Out of boundaries... seeking to 0x%"PRIX64" \n",(int64_t)read); // drop cache contents only if seeking backward or too much fwd. // This is also done for on-disk files, since it loses the backseek cache. // That in turn can cause major bandwidth increase and performance // issues with e.g. mov or badly interleaved files if(read<s->min_filepos || read>=s->max_filepos+s->seek_limit) { s->offset= // FIXME!? s->min_filepos=s->max_filepos=read; // drop cache content :( if(s->stream->eof) stream_reset(s->stream); stream_seek_internal(s->stream,read); mp_msg(MSGT_CACHE,MSGL_DBG2,"Seek done. new pos: 0x%"PRIX64" \n",(int64_t)stream_tell(s->stream)); } } // calc number of back-bytes: back=read - s->min_filepos; if(back<0) back=0; // strange... if(back>s->back_size) back=s->back_size; // calc number of new bytes: newb=s->max_filepos - read; if(newb<0) newb=0; // strange... // calc free buffer space: space=s->buffer_size - (newb+back); // calc bufferpos: pos=s->max_filepos - s->offset; if(pos>=s->buffer_size) pos-=s->buffer_size; // wrap-around if(space<s->fill_limit){ // printf("Buffer is full (%d bytes free, limit: %d)\n",space,s->fill_limit); return 0; // no fill... } // printf("### read=0x%X back=%d newb=%d space=%d pos=%d\n",read,back,newb,space,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; if (!read_chunk) read_chunk = 4*s->sector_size; space = FFMIN(space, read_chunk); #if 1 // back+newb+space <= buffer_size back2=s->buffer_size-(space+newb); // max back size if(s->min_filepos<(read-back2)) s->min_filepos=read-back2; #else 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; s->max_filepos+=len; if(pos+len>=s->buffer_size){ // wrap... s->offset+=s->buffer_size; } return len; }