int url_lpread(URLContext *s,unsigned char * buf,int size) { url_lpbuf_t *lp; int len=size; int valid_data_can_read; unsigned char *tbuf=buf; if(!s || !s->lpbuf) return -1; lp=s->lpbuf; lp_lock(&lp->mutex); lp_rprint(AV_LOG_INFO, "url_lpread:buffer=%x,rp=%x,wp=%x,end=%x,lp->valid_data_size=%d,pos=%lld\n", lp->buffer,lp->rp,lp->wp,lp->buffer_end,lp->valid_data_size,lp->pos); while(len>0) { if(lp->wp>=lp->rp) valid_data_can_read=lp->wp-lp->rp; else valid_data_can_read=lp->buffer_end-lp->rp; valid_data_can_read=FFMIN(len,valid_data_can_read); LP_ASSERT(valid_data_can_read>=0); if(valid_data_can_read==0) { int rlen; lp_unlock(&lp->mutex); if((len<lp->block_read_size) && (lp->seekflags & LESS_BUFF_DATA)) rlen=url_lpfillbuffer(s,len); else rlen=url_lpfillbuffer(s,lp->block_read_size); if(rlen<=0) { lp_unlock(&lp->mutex); return ((size-len)>0)?(size-len):rlen; } lp_lock(&lp->mutex); } lp_rprint( AV_LOG_INFO, "url_lpread:buffer=%x,rp=%x,wp=%x,end=%x,tbuf=%x,valid_data_can_read=%x(%d)\n", lp->buffer,lp->rp,lp->wp,lp->buffer_end,tbuf,valid_data_can_read,valid_data_can_read); if(valid_data_can_read>0) { if(tbuf!=NULL) { memcpy(tbuf,lp->rp,valid_data_can_read); tbuf+=valid_data_can_read; } lp->rp+=valid_data_can_read; if(lp->rp>=lp->buffer_end) lp->rp=lp->buffer; len-=valid_data_can_read; } LP_ASSERT(lp->rp>=lp->buffer); LP_ASSERT(lp->rp<lp->buffer_end); } lp_unlock(&lp->mutex); return (size-len); }
int64_t url_lpseek(URLContext *s, int64_t offset, int whence) { int64_t pos_on_read; url_lpbuf_t *lp; int valid_data_can_seek_forward; int valid_data_can_seek_back; int64_t offset1; int ret; if(!s || !s->lpbuf) return AVERROR(EINVAL); lp=s->lpbuf; lp_lock(&lp->mutex); lp_sprint( AV_LOG_INFO, "url_lpseek:offset=%lld whence=%d,buffer=%x,rp=%x,wp=%x,end=%x,pos=%lld\n", offset,whence,lp->buffer,lp->rp,lp->wp,lp->buffer_end,lp->pos); if (whence == AVSEEK_SIZE) { int64_t size; if(!s->prot->url_seek){ lp_unlock(&lp->mutex); return -1; } size = s->prot->url_seek(s, 0, AVSEEK_SIZE); if(size<0){ if ((size = s->prot->url_seek(s, -1, SEEK_END)) < 0) { lp_unlock(&lp->mutex); return size; } size++; s->prot->url_seek(s,lp->pos, SEEK_SET); } lp_sprint(AV_LOG_INFO,"get file size=%lld\n",size); lp_unlock(&lp->mutex); return size; } else if(whence == SEEK_END) { if(!s->prot->url_seek){ lp_unlock(&lp->mutex); return -1; } if ((offset1=s->prot->url_seek(s, offset, SEEK_END)) < 0) { lp_unlock(&lp->mutex); return offset1; } lp->rp=lp->buffer; lp->wp=lp->buffer; lp->valid_data_size=0; lp->pos=offset1; lp_unlock(&lp->mutex); return offset1; } if (whence != SEEK_CUR && whence != SEEK_SET) { lp_unlock(&lp->mutex); return AVERROR(EINVAL); } if(lp->wp>=lp->rp) valid_data_can_seek_forward=lp->wp-lp->rp; else valid_data_can_seek_forward=lp->buffer_size-(lp->rp-lp->wp); pos_on_read = lp->pos-valid_data_can_seek_forward; if(whence == SEEK_CUR) { offset1 = pos_on_read; if (offset == 0) { lp_unlock(&lp->mutex); return offset1; } offset += offset1; } valid_data_can_seek_back=FFMIN(lp->valid_data_size-valid_data_can_seek_forward, lp->buffer_size-valid_data_can_seek_forward-64); if(valid_data_can_seek_back<0) valid_data_can_seek_back=0; offset1 = offset - pos_on_read;/*seek forword or back*/ lp_sprint( AV_LOG_INFO, "url_lpseek:pos_on_read=%lld,can seek forwart=%d,can seek bacd=%d,offset1=%lld\n", pos_on_read,valid_data_can_seek_forward,valid_data_can_seek_back,offset1); if(offset1>=0 && offset1<=valid_data_can_seek_forward) {/*seek forward in lp buffer*/ lp_sprint( AV_LOG_INFO, "url_lpseek:buffer seek forword offset=%lld offset1=%lld whence=%d\n",offset,offset1,whence); lp->rp+=(int)offset1; if(lp->rp>=lp->buffer_end) lp->rp-=lp->buffer_size; }else if(offset1<0 && (-offset1)<=valid_data_can_seek_back) {/*seek back in lp buffer*/ lp_sprint( AV_LOG_INFO, "url_lpseek:buffer seek back offset=%lld offset1=%lld whence=%d,(int)offset1=%d\n",offset,offset1,whence,(int)offset1); lp->rp+=(int)offset1; if(lp->rp<lp->buffer) lp->rp+=lp->buffer_size; }else if(offset1>0 && (s->is_streamed || s->is_slowmedia) && (offset1<lp->buffer_size-lp->block_read_size) && (lp->file_size<=0 || (lp->file_size>0 && offset1<lp->file_size/2)))/*if offset1>filesize/2,thendo first seek end,don't buffer*/ {/*seek to buffer end,but buffer is not full,do read seek*/ int read_offset,ret; lp_sprint( AV_LOG_INFO, "url_lpseek:buffer read seek forward offset=%lld offset1=%lld whence=%d\n",offset,offset1,whence); lp->rp+=valid_data_can_seek_forward; if(lp->rp>=lp->buffer_end) lp->rp-=lp->buffer_size; lp_unlock(&lp->mutex); read_offset=offset1-valid_data_can_seek_forward; while(read_offset>0){ ret=url_lpread(s,NULL,read_offset);/*do read seek*/ if(ret>0) read_offset-=ret; else if(ret!=AVERROR(EAGAIN)){ offset=ret;/*get error,exit now*/ break; } } lp_lock(&lp->mutex); }else {/*not support in buffer seek,do low level seek now*/ lp_sprint( AV_LOG_INFO, "url_lpseek:buffer lowlevel seek offset=%lld offset1=%lld whence=%d\n",offset,offset1,whence); if(!s->prot->url_seek){ lp_unlock(&lp->mutex); return -1; } if(lp->cache_enable && offset<lp->file_size){ /*if cache enable not need to seek here,seek on cache missed*/ ;/*do't do seek here*/ }else if ((offset1=s->prot->url_seek(s, offset, SEEK_SET)) < 0) { lp->valid_data_size=0;/*seek failed clear all old datas*/ offset1 = s->prot->url_seek(s, lp->pos, SEEK_SET);/*clear the lowlevel errors*/ lp_unlock(&lp->mutex); return offset1; } lp->rp=lp->buffer; lp->wp=lp->buffer; lp->valid_data_size=0; lp->pos=offset; } lp_sprint( AV_LOG_INFO, "url_lpseekend:offset=%lld whence=%d,buffer=%x,rp=%x,wp=%x,end=%x,pos=%lld\n", offset,whence,lp->buffer,lp->rp,lp->wp,lp->buffer_end,lp->pos); LP_ASSERT(lp->rp>=lp->buffer); LP_ASSERT(lp->rp<lp->buffer_end); lp_unlock(&lp->mutex); return offset; }