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); }
int am_getconfig(const char * path, char *val, const char * def) { int i,ret; if (!amconfig_inited) { am_config_init(); } val[0]="\0"; lp_lock(&config_lock); i = get_matched_index(path); if (i >= 0) { strcpy(val, amconfigs[i] + CONFIG_VALUE_OFF); } else if (def != NULL) { strcpy(val, def); } lp_unlock(&config_lock); #ifdef ANDROID if(i<0){ /*get failed,get from android prop settings*/ ret=property_get(path, val, def); if(ret>0) i=1; } #else //if(i<0){ /*get failed,get from android prop settings*/ // val=getenv(path); // if(val!=NULL) // i=1; //} #endif return strlen(val) ; }
int url_lp_getbuffering_size(URLContext *s,int *forward_data,int *back_data) { url_lpbuf_t *lp; int valid_data_can_seek_forward; int valid_data_can_seek_back; int ret; if(!s || !s->lpbuf) return AVERROR(EINVAL); lp=s->lpbuf; lp_lock(&lp->mutex); 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); 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; lp_unlock(&lp->mutex); if(forward_data) *forward_data=valid_data_can_seek_forward; if(back_data) *back_data=valid_data_can_seek_back; return (valid_data_can_seek_back+valid_data_can_seek_forward); }
int64_t url_lpexseek(URLContext *s, int64_t offset, int whence) { url_lpbuf_t *lp; int64_t ret; if(!s || !s->lpbuf || !s->prot->url_exseek) return AVERROR(EINVAL); lp=s->lpbuf; lp_lock(&lp->mutex); if (whence == AVSEEK_FULLTIME) { ret=s->prot->url_exseek(s,0, AVSEEK_FULLTIME);/*clear the lowlevel errors*/ } else if (whence == AVSEEK_BUFFERED_TIME) { ret=s->prot->url_exseek(s,0, AVSEEK_BUFFERED_TIME);/*clear the lowlevel errors*/ } else if(whence == AVSEEK_TO_TIME ){ if(s->prot->url_exseek){ if((ret=s->prot->url_exseek(s, offset, AVSEEK_TO_TIME))>=0) { lp->rp=lp->buffer; lp->wp=lp->buffer; lp->valid_data_size=0; lp->pos=0; goto seek_end; } } ret= AVERROR(EPIPE); } seek_end: lp_unlock(&lp->mutex); return ret; }
int am_setconfig(const char * path, const char *val) { int i; char **pppath, *pconfig; char value[CONFIG_VALUE_MAX]; char *setval = NULL; int ret = -1; if (!amconfig_inited) { am_config_init(); } if (strlen(path) > CONFIG_PATH_MAX) { return -1; /*too long*/ } if (val != NULL) { setval = strdup(val); if(strlen(setval) >= CONFIG_VALUE_MAX) setval[CONFIG_VALUE_MAX] = '\0'; /*maybe val is too long,cut it*/ } lp_lock(&config_lock); i = get_matched_index(path); if (i >= 0) { pppath = &amconfigs[i]; if (!setval || strlen(setval) == 0) { //del value free_config_item(*pppath); amconfigs[i] = NULL; ret = 1; /*just not setting*/ goto end_out; } } else { i = get_unused_index(path); if (i < 0) { ret = i; goto end_out; } if (!setval || strlen(setval) == 0) { //value is nothing.exit now; ret = 1; /*just not setting*/ goto end_out; } DBGPRINT("used config index=%d,path=%s,val=%s\n", i, path, setval); pppath = &amconfigs[i]; *pppath = malloc_config_item(); if (!*pppath) { ret = -4; /*no MEM ?*/ goto end_out; } } pconfig = *pppath; strcpy(pconfig, path); strcpy(pconfig + CONFIG_VALUE_OFF, setval); ret = 0; end_out: if(setval!=NULL) free(setval); lp_unlock(&config_lock); return ret; }
int am_config_init(void) { lp_lock_init(&config_lock, NULL); lp_lock(&config_lock); //can do more init here. memset(amconfigs, 0, sizeof(amconfigs)); amconfig_inited = 1; lp_unlock(&config_lock); return 0; }
int am_dumpallconfigs(void) { int i; char *config; lp_lock(&config_lock); for (i = 0; i < MAX_CONFIG; i++) { config = amconfigs[i]; if (config != NULL) { fprintf(stderr, "[%d] %s=%s\n", i, config, config + CONFIG_VALUE_OFF); } } lp_unlock(&config_lock); return 0; }
int url_lpfree(URLContext *s) { if(s->lpbuf) { lp_lock(&s->lpbuf->mutex); if(s->lpbuf->cache_enable) aviolp_cache_close(s->lpbuf->cache_id); /*release other threadlater...*/ lp_unlock(&s->lpbuf->mutex); if(s->lpbuf->buffer) av_free(s->lpbuf->buffer); av_free(s->lpbuf); s->lpbuf=NULL; } return 0; }
int64_t url_lp_get_buffed_pos(URLContext *s) { url_lpbuf_t *lp; int64_t pos; int buffer_in_cache=0; if(!s || !s->lpbuf) return AVERROR(EINVAL); lp=s->lpbuf; pos=lp->pos; if(lp->cache_enable && !lp_trylock(&lp->mutex)){ if(lp->cache_enable){ buffer_in_cache=aviolp_cache_next_valid_bytes(lp->cache_id,pos,INT_MAX); if(buffer_in_cache>0) pos+=buffer_in_cache; } lp_unlock(&lp->mutex); } /*lp_sprint(AV_LOG_INFO,"buffered pos=%lld,file_size=%lld,percent=%d.%02d%%,buffer_in_cache=%d\n", pos,lp->file_size,(int)(pos*100/lp->file_size),(int)((pos*10000/lp->file_size)%100),buffer_in_cache); */ return pos; }
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; }
int url_lpfillbuffer(URLContext *s,int size) { url_lpbuf_t *lp; int rlen=0; int ssread; int cache_read_len=0; int64_t tmprp; if(!s || !s->lpbuf) return AVERROR(EINVAL); lp=s->lpbuf; lp_lock(&lp->mutex); if(lp->wp>=lp->rp) { if(lp->rp!=lp->buffer) ssread=FFMIN(size,lp->buffer_end-lp->wp); else ssread=FFMIN(size,lp->buffer_end-lp->wp-32); } else ssread=FFMIN(size,lp->rp-lp->wp-32);/*reversed 32bytes;*/ lp_bprint( AV_LOG_INFO,"fill buffer %d,buffer=%x,rp=%x,wp=%x,buffer_end=%x,size=%d\n",ssread,lp->buffer,lp->rp,lp->wp,lp->buffer_end,size); if(ssread<=0) { rlen=0; goto release; } if(lp->cache_enable){ /*do read on cache first*/ rlen=aviolp_cache_read(lp->cache_id,lp->pos,lp->wp,ssread); cache_read_len=rlen; lp_bprint(AV_LOG_INFO,"filled buffer from cache=%d\n",cache_read_len); } if(rlen<=0){ if(lp->file_size>0 && lp->pos>=lp->file_size){ rlen=0;/*file read end*/ goto release; }else if(lp->cache_enable && s->prot->url_seek(s,0,SEEK_CUR)!=lp->pos){/*maybe do read from cache file before,so seek it now*/ int ret=s->prot->url_seek(s,lp->pos,SEEK_SET); if(ret!=lp->pos){ rlen=-1;/*error*/ goto release; } } tmprp=lp->pos; lp_unlock(&lp->mutex);/*release lock for long time read*/ rlen=s->prot->url_read(s,lp->wp,ssread); lp_lock(&lp->mutex); if(tmprp!=lp->pos) rlen=AVERROR(EAGAIN);;/*pos have changed,so I think we have a seek on read*/ lp_bprint(AV_LOG_INFO,"filled buffer from remote=%d\n",rlen); } if(rlen>0) { if(lp->cache_enable&& cache_read_len<=0)/*not read from cache itself*/ aviolp_cache_write(lp->cache_id,lp->pos,lp->wp,rlen); lp->valid_data_size+=rlen; lp->pos+=rlen; lp->wp+=rlen; if(lp->wp>=lp->buffer_end) lp->wp=lp->buffer; } release: lp_unlock(&lp->mutex); lp_bprint( AV_LOG_INFO,"lpfilld=%d\n",rlen); return rlen; }
int64_t url_lpexseek(URLContext *s, int64_t offset, int whence) { url_lpbuf_t *lp; int64_t ret; if(!s || !s->lpbuf || !s->prot->url_exseek) return AVERROR(EINVAL); lp=s->lpbuf; lp_lock(&lp->mutex); if (whence == AVSEEK_FULLTIME) { ret=s->prot->url_exseek(s,0, AVSEEK_FULLTIME);/*clear the lowlevel errors*/ } else if (whence == AVSEEK_BUFFERED_TIME) { ret=s->prot->url_exseek(s,0, AVSEEK_BUFFERED_TIME);/*clear the lowlevel errors*/ } else if(whence == AVSEEK_TO_TIME ){ if(s->prot->url_exseek){ if(strcmp(s->prot->name, "vhls")==0){ // hls can return the stream offset lp_print( AV_LOG_INFO,"[%s:%d] doing LOOPBUFFER seek\n",__FUNCTION__,__LINE__); lp_unlock(&lp->mutex); ret=url_lpexseekoffset(s,offset); lp_lock(&lp->mutex); if(ret>=0){ lp_print( AV_LOG_INFO,"[%s:%d] LOOPBUFFER seek deal successful\n",__FUNCTION__,__LINE__); goto seek_end; } lp_print( AV_LOG_INFO,"[%s:%d] Failed LOOPBUFFER seek\n",__FUNCTION__,__LINE__); } if((ret=s->prot->url_exseek(s, offset, AVSEEK_TO_TIME))>=0) { lp->rp=lp->buffer; lp->wp=lp->buffer; lp->valid_data_size=0; lp->pos=0; goto seek_end; } } ret= AVERROR(EPIPE); } else if(whence == AVSEEK_CMF_TS_TIME ){ if(s->prot->url_exseek){ if((ret=s->prot->url_exseek(s, offset, AVSEEK_CMF_TS_TIME))>=0) { lp->rp=lp->buffer; lp->wp=lp->buffer; lp->valid_data_size=0; lp->pos=0; goto seek_end; } } ret= AVERROR(EPIPE); } else if (whence == AVSEEK_SLICE_BYTIME) { ret= s->prot->url_seek(s, offset, AVSEEK_SLICE_BYTIME); if (ret < 0){ lp_unlock(&lp->mutex); return -1; } lp_unlock(&lp->mutex); return ret; } else if (whence == AVSEEK_ITEM_TIME) { ret= s->prot->url_seek(s, offset, AVSEEK_ITEM_TIME); if (ret < 0){ lp_unlock(&lp->mutex); return -1; } lp_unlock(&lp->mutex); return ret; } seek_end: lp_unlock(&lp->mutex); return ret; }