示例#1
0
文件: stream.c 项目: HermiG/mplayer2
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;
}
示例#2
0
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;
}
示例#3
0
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;
}
示例#4
0
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;
}
示例#5
0
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;

}