int CacheHttp_Open(void ** handle,const char* headers) { CacheHttpContext * s = (CacheHttpContext *)av_malloc(sizeof(CacheHttpContext)); if(!s) { *handle = NULL; return AVERROR(EIO); } *handle = (void *)s; s->hd = NULL; s->item_duration = 0; s->item_pos = 0; s->item_starttime = 0; s->finish_flag = 0; s->seek_flag = 0; s->reset_flag = -1; s->have_list_end = -1; s->is_first_read = 1; memset(s->headers, 0x00, sizeof(s->headers)); s->fifo = NULL; float value=0.0; int config_ret; config_ret=am_getconfig_float("libplayer.ffmpeg.hlshttpbufmax",&value); if(config_ret<0 || value < 1024*32) s->fifo = av_fifo_alloc(CIRCULAR_BUFFER_SIZE); else { s->fifo = av_fifo_alloc(value); } pthread_mutex_init(&s->read_mutex,NULL); s->EXIT = 0; s->EXITED = 0; s->RESET = 0; if(headers) { av_strlcpy(s->headers,headers,BUFFER_SIZE); } int ret = am_getconfig_float("libplayer.hls.measured_buffer",&value); int meause_unit_max = 1024*1024*10;//10M if(ret>=0) { meause_unit_max = (int)value*1024; } if(meause_unit_max/TMP_BUFFER_SIZE<100) { s->bandwidth_measure=bandwidth_measure_alloc(100,0); } else { s->bandwidth_measure=bandwidth_measure_alloc(meause_unit_max/TMP_BUFFER_SIZE,0); } ret = ffmpeg_pthread_create(&s->circular_buffer_thread, NULL, circular_buffer_task, s); av_log(NULL, AV_LOG_INFO, "----------- pthread_create ret=%d\n",ret); return ret; }
static float _get_system_prop(SysPropType type){ float value = 0.0; float ret = -1; switch(type){ case PROP_DEBUG_LEVEL: ret = am_getconfig_float("libplayer.hls.debug",&value); if(ret<0){ ret = 0; value = 0; } break; case PROP_CMF_SUPPORT: ret = am_getconfig_bool("libplayer.hls.cmf"); if(ret<0){ value = -1; }else{ value= ret; } break; default: RLOG("Never see this line,type:%d\n",type); break; } if(ret < 0 || value <0){ ret = -1; }else{ ret = value; } return ret; }
static void find_best_keyframe(AVFormatContext *pFormatCtx, int video_index, int count, int64_t *time, int64_t *offset, int *maxsize) { int i = 0; int maxFrameSize = 0; int64_t thumbTime = 0; int64_t thumbOffset = 0; AVPacket packet; int r = 0; int find_ok = 0; int keyframe_index=0; AVStream *st=pFormatCtx->streams[video_index]; int havepts=0; int nopts=0; *maxsize=0; if(count<=0){ float newcnt=-0.1; count=100; if(am_getconfig_float("libplayer.thumbnail.scan.count",&newcnt)>=0 && newcnt>=1) count=(int)newcnt; } do{ r = av_read_next_video_frame(pFormatCtx, &packet,video_index); if(r<0) break; log_debug("[find_best_keyframe][%d]read frame packet.size=%d,pts=%lld\n",i,packet.size,packet.pts); havepts=(packet.pts>0||havepts); nopts=(i>10)&&!havepts; if (packet.size > maxFrameSize && (packet.pts>=0 || nopts)) { //packet.pts>=0 can used for seek. maxFrameSize = packet.size; thumbTime = packet.pts; thumbOffset = avio_tell(pFormatCtx->pb) - packet.size; keyframe_index=i; find_ok=1; } av_free_packet(&packet); if(i>5 && find_ok && maxFrameSize>100*1024/(1+i/20)) break; }while(i++<count); if(find_ok){ log_debug("[%s]return thumbTime=%lld thumbOffset=%llx\n", __FUNCTION__, thumbTime, thumbOffset); if(thumbTime>=0&&thumbTime != AV_NOPTS_VALUE) *time = av_rescale_q(thumbTime, st->time_base, AV_TIME_BASE_Q); else *time = AV_NOPTS_VALUE; *offset = thumbOffset; *maxsize = maxFrameSize; r=0; }else{ log_print("[%s]find_best_keyframe failed\n", __FUNCTION__); } return r; }
static float get_adaptation_ex_para(int type){ float value = 0.0; float ret = -1; if(type==0){ ret = am_getconfig_float("libplayer.hls.sensitivity", &value); if(ret<0){ value = 1.0; ret = 0; } }else if(type == 1){ ret = am_getconfig_float("libplayer.hls.upcounts", &value); if(ret<0){ ret =0; value = DEF_UP_COUNTS; } }else if(type == 2){ ret = am_getconfig_float("libplayer.hls.downcounts", &value); if(ret<0){ ret =0; value = DEF_DOWN_COUNTS; } }else if(type == 3){ ret = am_getconfig_float("libplayer.hls.fixed_bw", &value); }else if(type == 4){ ret = am_getconfig_float("libplayer.hls.debug", &value); if(ret<0){ ret = 0; value = 0; } }else if(type ==5){ ret = am_getconfig_float("libplayer.hls.initial_buffered", &value); if(ret<0){ ret = 0; value = 0; } }else if(type == 6){ ret = am_getconfig_float("libplayer.hls.measured_buffer", &value); if(ret<0){ ret = 0; value = 0; } } if(ret < 0 || value <0){ ret = -1; }else{ ret = value; } //av_log(NULL, AV_LOG_INFO,"just get adaptation extend parameter(value:%d): %f\n",type,ret); return ret; }
static int get_adaptation_profile(){ float value = 0.0; int ret = -1; ret = am_getconfig_float("libplayer.hls.profile", &value); if(ret < 0 || value <0){ ret = ADAPTATION_PROFILE_DEFAULT; }else{ ret= (int)value; } //av_log(NULL, AV_LOG_INFO,"just get adaptation profile: %d\n",ret); return ret; }
static void find_thumbnail_frame(AVFormatContext *pFormatCtx, int video_index, int64_t *thumb_time, int64_t *thumb_offset,int *pmaxframesize) { int64_t thumbTime = 0; int64_t thumbOffset = 0; AVPacket packet; AVStream *st = pFormatCtx->streams[video_index]; int duration = pFormatCtx->duration / AV_TIME_BASE; /// int64_t init_seek_time = (duration > 0) ? MIN(10, duration >> 1) : 10; int64_t init_seek_time = 10; int ret = 0; float starttime; int maxframesize; if(am_getconfig_float("libplayer.thumbnail.starttime",&starttime)>=0 && starttime>=0) { init_seek_time=(int64_t)starttime; if(init_seek_time >= duration) init_seek_time=duration-1; if(init_seek_time<=0) init_seek_time=0; }else{ if(duration > 360) init_seek_time=120;/*long file.don't do more seek..*/ else if(duration>6){ init_seek_time=duration/3; }else{ init_seek_time=0;/*file is too short,try from start.*/ } } init_seek_time *= AV_TIME_BASE; log_debug("[find_thumbnail_frame]duration=%lld init_seek_time=%lld\n", pFormatCtx->duration, init_seek_time); //init_seek_time = av_rescale_q(init_seek_time, st->time_base, AV_TIME_BASE_Q); //log_debug("[find_thumbnail_frame]init_seek_time=%lld timebase=%d:%d video_index=%d\n",init_seek_time,st->time_base.num,st->time_base.den, video_index); ret = av_seek_frame(pFormatCtx, video_index,init_seek_time, AVSEEK_FLAG_BACKWARD); if (ret < 0) { avio_seek(pFormatCtx->pb, 0, SEEK_SET); log_error("[%s]seek error, reset offset to 0\n", __FUNCTION__); return; } log_debug("[find_thumbnail_frame]offset=%llx \n", avio_tell(pFormatCtx->pb)); find_best_keyframe(pFormatCtx, video_index, 0, &thumbTime, &thumbOffset,&maxframesize); if (thumbTime != AV_NOPTS_VALUE) { *thumb_time = thumbTime; }else{ *thumb_time = AV_NOPTS_VALUE; } *thumb_offset = thumbOffset; *pmaxframesize=maxframesize; log_debug("[find_thumbnail_frame]return thumb_time=%lld thumb_offset=%lld\n", *thumb_time, *thumb_offset); }
float in_get_sys_prop_float(char* key){ float value = 0.0; #ifdef HAVE_ANDROID_OS int ret = am_getconfig_float(key,&value); if(ret<0){ return -1; } #else char * ev = getenv(key); if(ev==NULL){ return -1; } value = atof(ev); #endif return value; }
int CacheHttp_Read(void * handle, uint8_t * cache, int size) { if(!handle) return AVERROR(EIO); CacheHttpContext * s = (CacheHttpContext *)handle; pthread_mutex_lock(&s->read_mutex); if (s->fifo) { int avail; avail = av_fifo_size(s->fifo); //av_log(NULL, AV_LOG_INFO, "----------- http_read avail=%d, size=%d ",avail,size); if(s->is_first_read>0) { float value = 0.0; int ret = -1; ret = am_getconfig_float("libplayer.hls.initial_buffered", &value); if(ret>=0) { if(avail/1024<value) { //av_log(NULL, AV_LOG_INFO, "buffer data avail=%d, initial buffer buffered data size=%f ",avail,value*1024); pthread_mutex_unlock(&s->read_mutex); return AVERROR(EAGAIN); } } s->is_first_read = 0; } if(url_interrupt_cb()) { pthread_mutex_unlock(&s->read_mutex); return 0; } else if(avail) { // Maximum amount available size = FFMIN( avail, size); av_fifo_generic_read(s->fifo, cache, size, NULL); pthread_mutex_unlock(&s->read_mutex); return size; } else if(s->EXITED) { pthread_mutex_unlock(&s->read_mutex); return 0; } else if(!s->finish_flag) { pthread_mutex_unlock(&s->read_mutex); //read just need retry return AVERROR(EAGAIN); } } pthread_mutex_unlock(&s->read_mutex); return 0; }
static void *circular_buffer_task( void *_handle) { CacheHttpContext * s = (CacheHttpContext *)_handle; URLContext *h = NULL; float config_value = 0.0; void * fp = NULL; int config_ret = 0; while(!s->EXIT) { av_log(h, AV_LOG_ERROR, "----------circular_buffer_task item "); s->reset_flag = 1; if (url_interrupt_cb()) { s->circular_buffer_error = EINTR; goto FAIL; } if(h) { CacheHttp_ffurl_close(h); config_ret = am_getconfig_float("libplayer.hls.dump",&config_value); if(config_ret >= 0 && (int)config_value == 2) CacheHttp_dump_close(fp); h = NULL; } list_item_t * item = getCurrentSegment(NULL); if(!item||(!item->file&&!item->flags&ENDLIST_FLAG)) { usleep(WAIT_TIME); continue; } s->reset_flag = 0; s->item_starttime = item->start_time; s->item_duration = item->duration; s->have_list_end = item->have_list_end; s->ktype = item->ktype; if(item->key_ctx!=NULL&& s->ktype==KEY_AES_128) { ff_data_to_hex(s->iv, item->key_ctx->iv, sizeof(item->key_ctx->iv), 0); ff_data_to_hex(s->key, item->key_ctx->key, sizeof(item->key_ctx->key), 0); s->iv[32] = s->key[32] = '\0'; } if(item&&item->flags&ENDLIST_FLAG) { s->finish_flag =1; } else { s->finish_flag =0; } if(s->finish_flag) { av_log(NULL, AV_LOG_INFO, "ENDLIST_FLAG, return 0\n"); //break; usleep(500*1000); continue; } int err, http_code; char* filename = NULL; if(s->ktype == KEY_NONE) { filename = av_strdup(item->file); } else { char url[MAX_URL_SIZE]; if (strstr(item->file, "://")) snprintf(url, sizeof(url), "crypto+%s", item->file); else snprintf(url, sizeof(url), "crypto:%s", item->file); filename = av_strdup(url); } int retry_num = 0; OPEN_RETRY: if(s->RESET) goto SKIP; err = CacheHttp_advanced_ffurl_open_h(&h, filename,AVIO_FLAG_READ|AVIO_FLAG_NONBLOCK, s->headers, &http_code,s); if (err) { if(url_interrupt_cb()) { if(filename) { av_free(filename); filename = NULL; } break; } if(1 == http_code && !s->have_list_end) { av_log(h, AV_LOG_ERROR, "----------CacheHttpContext : ffurl_open_h 404\n"); if(retry_num++ < LIVE_HTTP_RETRY_TIMES) { usleep(WAIT_TIME); goto OPEN_RETRY; } else { goto SKIP; } } else if(s->have_list_end || ((2 == http_code || 3 == http_code)&& !s->have_list_end)) { usleep(1000*20); goto OPEN_RETRY; } else if(!s->have_list_end&&err ==AVERROR(EIO)) { if(retry_num++ < LIVE_HTTP_RETRY_TIMES) {//if live streaming,just keep on 2s. usleep(WAIT_TIME); goto OPEN_RETRY; } else { av_log(h, AV_LOG_ERROR, "----------CacheHttpContext : ffurl_open_h failed ,%d\n",err); if(filename) { av_free(filename); filename = NULL; } break; } } else { av_log(h, AV_LOG_ERROR, "----------CacheHttpContext : ffurl_open_h failed ,%d\n",err); if(filename) { av_free(filename); filename = NULL; } break; } } if(h && s->seek_flag) { int64_t cur_pos = CacheHttp_ffurl_seek(h, 0, SEEK_CUR); int64_t pos_ret = CacheHttp_ffurl_seek(h, s->seek_pos-cur_pos, SEEK_CUR); av_log(NULL,AV_LOG_INFO,"--------------> cachehttp_seek seek_pos=%lld, pos_ret=%lld", s->seek_pos, pos_ret); s->seek_flag = 0; } s->hd = h; s->item_pos = 0; s->item_size = CacheHttp_ffurl_seek(s->hd, 0, AVSEEK_SIZE); item->item_size = s->item_size; char tmpbuf[TMP_BUFFER_SIZE]; int left = 0; int tmpdatasize = 0; config_ret = am_getconfig_float("libplayer.hls.dump",&config_value); if(config_ret >= 0 && config_value > 0) CacheHttp_dump_open(&fp, filename, (int)config_value); while(!s->EXIT) { if(s->RESET) break; if (url_interrupt_cb()) { s->circular_buffer_error = EINTR; break; } if(!s->hd) break; if(s->hd && tmpdatasize <= 0) { bandwidth_measure_start_read(s->bandwidth_measure); tmpdatasize = CacheHttp_ffurl_read(s->hd, tmpbuf, TMP_BUFFER_SIZE); bandwidth_measure_finish_read(s->bandwidth_measure,tmpdatasize); } //if(tmpdatasize > 0) { pthread_mutex_lock(&s->read_mutex); left = av_fifo_space(s->fifo); left = FFMIN(left, s->fifo->end - s->fifo->wptr); if( !left) { pthread_mutex_unlock(&s->read_mutex); usleep(WAIT_TIME); continue; } left = FFMIN(left, tmpdatasize); if(left >0) { memcpy(s->fifo->wptr, tmpbuf , left); tmpdatasize-=left; } if(tmpdatasize>0) { memmove(tmpbuf, tmpbuf+left , tmpdatasize); } if (left > 0) { config_ret = am_getconfig_float("libplayer.hls.dump",&config_value); if(config_ret >= 0 && config_value > 0) CacheHttp_dump_write(fp, s->fifo->wptr, left); s->fifo->wptr += left; if (s->fifo->wptr >= s->fifo->end) s->fifo->wptr = s->fifo->buffer; s->fifo->wndx += left; s->item_pos += left; } else if(left == AVERROR(EAGAIN) || (left < 0 && s->have_list_end&& left != AVERROR_EOF)) { pthread_mutex_unlock(&s->read_mutex); continue; } else { pthread_mutex_unlock(&s->read_mutex); av_log(h, AV_LOG_ERROR, "---------- circular_buffer_task read left = %d\n", left); break; } pthread_mutex_unlock(&s->read_mutex); //} //usleep(WAIT_TIME); } SKIP: if(filename) { av_free(filename); filename = NULL; } if(!s->RESET) switchNextSegment(NULL); } FAIL: if(h) CacheHttp_ffurl_close(h); s->hd = NULL; s->EXITED = 1; config_ret = am_getconfig_float("libplayer.hls.dump",&config_value); if(config_ret >= 0 && config_value > 0) CacheHttp_dump_close(fp); av_log(NULL, AV_LOG_ERROR, "---------> CacheHttp thread quit !"); return NULL; }
int url_lpopen(URLContext *s,int size) { url_lpbuf_t *lp; int blocksize=32*1024; int ret; float value=0.0; int bufsize=0; if(size==0){ ret=am_getconfig_float("libplayer.ffmpeg.lpbufsizemax",&value); if(ret<0 || value < 1024*32) size=IO_LP_BUFFER_SIZE; else{ size=(int)value; } } lp_bprint( AV_LOG_INFO,"url_lpopen=%d\n",size); if(!s) return -1; lp_bprint( AV_LOG_INFO,"url_lpopen2=%d\n",size); ret=am_getconfig_float("libplayer.ffmpeg.lpbufblocksize",&value); if(ret>=0 && value>=32){ blocksize=(int)value; } lp_sprint( AV_LOG_INFO,"lpbuffer block size=%d\n",blocksize); lp=av_mallocz(sizeof(url_lpbuf_t)); if(!lp) return AVERROR(ENOMEM); lp->buffer=av_malloc(size); if(!lp->buffer) { int failedsize=size/2;/*if no memory used 1/2 size */ ret=am_getconfig_float("libplayer.ffmpeg.lpbuffaildsize",&value); if(ret>=0 && value>=1024){ failedsize=(int)value; } lp_sprint( AV_LOG_INFO,"malloc buf failed,used failed size=%d\n",failedsize); lp->buffer=av_malloc(failedsize); while(!lp->buffer){ failedsize=failedsize/2; if(failedsize<16*1024){/*do't malloc too small size failed size*/ av_free(lp); return AVERROR(ENOMEM); } lp->buffer=av_malloc(failedsize); } bufsize=failedsize; }else{ bufsize=size; } lp_sprint( AV_LOG_INFO,"url_lpopen used lp buf size=%d\n",bufsize); s->lpbuf=lp; lp->buffer_size=bufsize; lp->rp=lp->buffer; lp->wp=lp->buffer; lp->buffer_end=lp->buffer+bufsize; lp->valid_data_size=0; lp->pos=0; lp->block_read_size=FFMIN(blocksize,bufsize>>4); lp_lock_init(&lp->mutex,NULL); lp->file_size=url_lpseek(s,0,AVSEEK_SIZE); lp->cache_enable=0; lp->cache_id=aviolp_cache_open(s->filename,url_filesize(s)); lp->dbg_cnt=0; ret=am_getconfig_float("libplayer.ffmpeg.lpbufmaxbuflv",&value); if(ret<0) lp->max_forword_level=1; else{ lp->max_forword_level=value; } if(lp->cache_id!=0) lp->cache_enable=1; lp_bprint( AV_LOG_INFO,"url_lpopen4%d\n",bufsize); ret=am_getconfig_float("libplayer.ffmpeg.maxreadseek",&value); if(ret>=0 && value>=0) { lp->max_read_seek=value; }else { lp->max_read_seek=DEF_MAX_READ_SEEK; } return 0; }
static int m3u_format_parser(struct list_mgt *mgt,ByteIOContext *s) { unsigned char line[1024]; int ret; unsigned char *p; int getnum=0; struct list_item tmpitem; char prefix[1024]=""; char prefixex[1024]=""; int prefix_len=0,prefixex_len=0; int start_time=mgt->full_time; char *oprefix=mgt->location!=NULL?mgt->location:mgt->filename; if(oprefix){ char *tail,*tailex,*extoptions; extoptions=strchr(oprefix,'?');/*ext options is start with ? ,we don't need in nested*/ if(is_NET_URL(oprefix)){ tail=strchr(oprefix+10,'/');/*skip Http:// and shttp:,and to first '/'*/ if(!extoptions)// no ? tailex=strrchr(oprefix+10,'/');/*skip Http:// and shttp:,start to last '/'*/ else tailex=memrchr(oprefix+10,'/',extoptions-oprefix-10);/*skip Http:// and shttp:,start to last '/',between http-->? */ }else{ tail=strchr(oprefix,'/'); /*first '/'*/ if(!extoptions)//no ? tailex=strrchr(oprefix,'/'); /*to last '/' */ else tailex=memrchr(oprefix+10,'/',extoptions-oprefix-10);/*skip Http:// and shttp:,start to last '/',between http-->? */ } if(tail!=NULL){ prefix_len=tail-oprefix+1;/*left '/'..*/ memcpy(prefix,oprefix,prefix_len); prefix[prefix_len]='\0'; } if(tailex!=NULL){ prefixex_len=tailex-oprefix+1;/*left '/'..*/ memcpy(prefixex,oprefix,prefixex_len); prefixex[prefixex_len]='\0'; if(NULL!=mgt->prefix){ av_free(mgt->prefix); mgt->prefix = NULL; } mgt->prefix = strdup(prefixex); } } memset(&tmpitem,0,sizeof(tmpitem)); av_log(NULL, AV_LOG_INFO, "m3u_format_parser get prefix=%s\n",prefix); av_log(NULL, AV_LOG_INFO, "m3u_format_parser get prefixex=%s\n",prefixex); #if 0 if(mgt->n_variants>0){ free_variant_list(mgt); } #endif while(m3u_format_get_line(s,line,1024)>=0) { ret = m3u_parser_line(mgt,line,&tmpitem); if(ret>0) { struct list_item*item; int need_prefix=0; int size_file=tmpitem.file?(strlen(tmpitem.file)+32):4; tmpitem.start_time=start_time; if(tmpitem.file && (is_NET_URL(prefix)) && /*net protocal*/ !(is_NET_URL(tmpitem.file)))/*if item is not net protocal*/ {/*if m3u is http,item is not http,add prefix*/ need_prefix=1; size_file+=prefixex_len; } item=av_malloc(sizeof(struct list_item)+size_file); if(!item) return AVERROR(ENOMEM); memcpy(item,&tmpitem,sizeof(tmpitem)); item->file=NULL; if(tmpitem.file) { item->file=&item[1]; if(need_prefix){ if(tmpitem.file[0]=='/'){/*has '/',not need the dir */ strcpy(item->file,prefix); strcpy(item->file+prefix_len,tmpitem.file+1);/*don't copy two '/',we have left before*/ }else{/*no '/', some I save the full path frefix*/ if(!strncmp(prefixex,"shttps://",9)){ strcpy(item->file,"http"); strcpy(item->file+4,prefixex+6); strcpy(item->file+4+prefixex_len -6,tmpitem.file); }else{ strcpy(item->file,prefixex); strcpy(item->file+prefixex_len,tmpitem.file); } } } else{ strcpy(item->file,tmpitem.file); } } if(mgt->flags&KEY_FLAG&&NULL!= mgt->key_tmp&&mgt->key_tmp->is_have_key_file>0){ item->key_ctx = av_mallocz(sizeof(struct AES128KeyContext)); if(!item->key_ctx){ ret = AVERROR(ENOMEM); break; } memcpy(item->key_ctx->key,mgt->key_tmp->key,sizeof(item->key_ctx->key)); if(mgt->has_iv>0){ memcpy(item->key_ctx->iv,mgt->key_tmp->iv,sizeof(item->key_ctx->iv)); }else{//from applehttp.c int seq = mgt->seq+mgt->item_num; av_log(NULL,AV_LOG_INFO,"Current item seq number:%d\n",seq); AV_WB32(item->key_ctx->iv + 12, seq); } item->ktype = mgt->key_tmp->key_type; } if(mgt->flags&REAL_STREAMING_FLAG){ ret =list_test_and_add_item(mgt,item); if(ret==0){ start_time+=item->duration; } }else{ ret = list_add_item(mgt,item); start_time+=item->duration; } if(item->flags &ENDLIST_FLAG) { mgt->have_list_end=1; break; } else { memset(&tmpitem,0,sizeof(tmpitem)); if(ret == 0){ getnum++; } } } else if(ret <0){ if(ret ==-(TRICK_LOGIC_BASE+0)&&(mgt->flags&KEY_FLAG)&&NULL!= mgt->key_tmp&&0==mgt->key_tmp->is_have_key_file){//get key from server URLContext *uc; if (ffurl_open(&uc, mgt->key_tmp->key_from, AVIO_FLAG_READ) == 0) { if (ffurl_read_complete(uc, mgt->key_tmp->key, sizeof(mgt->key_tmp->key)) != sizeof(mgt->key_tmp->key)) { av_log(NULL, AV_LOG_ERROR, "Unable to read key file %s\n", mgt->key_tmp->key_from); } av_log(NULL,AV_LOG_INFO,"Just get aes key file from server\n"); mgt->key_tmp->is_have_key_file = 1; ffurl_close(uc); } else { av_log(NULL, AV_LOG_ERROR, "Unable to open key file %s\n", mgt->key_tmp->key_from); } memset(&tmpitem,0,sizeof(tmpitem)); continue; } if(ret ==-(TRICK_LOGIC_BASE+1)||ret ==-(TRICK_LOGIC_BASE+2)){ memset(&tmpitem,0,sizeof(tmpitem)); continue; } break; } else{ if(tmpitem.flags&ALLOW_CACHE_FLAG) mgt->flags|=ALLOW_CACHE_FLAG; if(mgt->flags&REAL_STREAMING_FLAG&&mgt->jump_item_num==INT_MAX){ mgt->jump_item_num = 0; av_log(NULL, AV_LOG_INFO, "drop this list,sequence number:%ld\n",mgt->seq); break; } } } if(mgt->key_tmp){ av_free(mgt->key_tmp); mgt->key_tmp = NULL; } if(mgt->n_variants>0){//just choose middle definition; float value; ret=am_getconfig_float("libplayer.hls.level",&value); if(ret==0&&value<1){ mgt->ctype =LOW_BANDWIDTH; }else if(ret==0&&value>0&&value<2){ mgt->ctype =MIDDLE_BANDWIDTH; }else if(ret==0&&value>1){ mgt->ctype =HIGH_BANDWIDTH; }else{ mgt->ctype =MIDDLE_BANDWIDTH; } } mgt->file_size=AVERROR_STREAM_SIZE_NOTVALID; mgt->full_time=start_time; mgt->last_load_time = av_gettime(); av_log(NULL, AV_LOG_INFO, "m3u_format_parser end num =%d,fulltime=%d\n",getnum,start_time); return getnum;
static int list_open(URLContext *h, const char *filename, int flags) { struct list_mgt *mgt; int ret; mgt = av_malloc(sizeof(struct list_mgt)); if (!mgt) { return AVERROR(ENOMEM); } memset(mgt, 0, sizeof(struct list_mgt)); mgt->key_tmp = NULL; mgt->start_seq = -1; mgt->next_seq = -1; mgt->filename = filename + 5; mgt->flags = flags; mgt->next_index = 0; mgt->playing_item_index = 0; mgt->playing_item_seq = 0; mgt->strategy_up_counts = 0; mgt->strategy_down_counts = 0; mgt->listclose = 0; mgt->cmf_item_index = 0; mgt->cur_uio = NULL; mgt->codec_buf_level=-1; mgt->switch_down_num = 0; mgt->switch_up_num = 0; mgt->debug_level = (int)get_adaptation_ex_para(4); char headers[1024]; char sess_id[40]; memset(headers, 0, sizeof(headers)); memset(sess_id, 0, sizeof(sess_id)); generate_segment_session_id(sess_id, 37); snprintf(headers, sizeof(headers), "Connection: keep-alive\r\n" /*"Range: bytes=0- \r\n"*/ "X-Playback-Session-Id: %s\r\n%s", sess_id,h!=NULL&&h->headers!=NULL?h->headers:""); //av_log(NULL, AV_LOG_INFO, "Generate ipad http request headers,\r\n%s\n", headers); mgt->ipad_ex_headers = strndup(headers, 1024); memset(headers, 0, sizeof(headers)); generate_playback_session_id(sess_id, 37); snprintf(headers, sizeof(headers), /*"Connection: keep-alive\r\n"*/ "X-Playback-Session-Id: %s\r\n%s", sess_id,h!=NULL&&h->headers!=NULL?h->headers:""); //av_log(NULL, AV_LOG_INFO, "Generate ipad http request media headers,\r\n%s\n", headers); mgt->ipad_req_media_headers = strndup(headers, 1024); gListMgt = mgt; if ((ret = list_open_internet(&mgt->cur_uio, mgt, mgt->filename, flags | URL_MINI_BUFFER | URL_NO_LP_BUFFER)) != 0) { av_free(mgt); return ret; } lp_lock_init(&mgt->mutex, NULL); float value = 0.0; ret = am_getconfig_float("libplayer.hls.stpos", &value); if (ret < 0 || value <= 0) { if (!mgt->have_list_end) { int itemindex =0; if(mgt->item_num<10&&mgt->target_duration<5){ itemindex = mgt->item_num / 2+1; /*for live streaming ,choose the middle item.*/ }else if(mgt->item_num>=10){ itemindex = mgt->item_num-3; //last item }else if(mgt->item_num<10&&mgt->target_duration>5){ itemindex = mgt->item_num -1; } mgt->current_item = list_find_item_by_index(mgt,itemindex-1); } else { mgt->current_item = mgt->item_list; } }else{ mgt->current_item = list_find_item_by_index(mgt,(int)value-1); } h->is_streamed = 1; h->is_slowmedia = 1; if (mgt->full_time > 0 && mgt->have_list_end) { h->support_time_seek = 1; } h->priv_data = mgt; mgt->cache_http_handle = NULL; ret = CacheHttp_Open(&mgt->cache_http_handle,mgt->ipad_req_media_headers); if(mgt->debug_level>0){ hls_base_info_dump(mgt); } return 0; }
static int fast_sort_streams(struct list_mgt * mgt){ int key,left,middle,right; struct variant *var= NULL; int i,j,tmp,stuff[mgt->n_variants]; int has_bandwidth = -1; for (i=0; i < mgt->n_variants; i++){ var = mgt->variants[i]; stuff[i] = var->bandwidth; if(has_bandwidth<0&&stuff[i] >0){ has_bandwidth = 1; } } if(has_bandwidth<0){ for (i=0; i < mgt->n_variants; i++){ var = mgt->variants[i]; var->priority = i; } mgt->playing_variant= mgt->variants[mgt->n_variants/2]; RLOG("Invalid bandwidth streaming,choose url:%s\n",mgt->playing_variant->url); return 0; } for (i=1; i < mgt->n_variants; i++){ key = stuff[i]; left = 0; right = i-1; while(left<=right){ middle=(left+right)/2; if (key>stuff[middle]) {//down order right=middle-1; }else{ left=middle+1; } } for (j=i;j>left;j--){ stuff[j]=stuff[j-1]; } stuff[left]=key; } j = mgt->n_variants - 1; for (i=0; i < mgt->n_variants; i++){ for (tmp=0; tmp < mgt->n_variants; tmp++){ var = mgt->variants[tmp]; if (var->bandwidth == stuff[i]){ var->priority = j--; //av_log(NULL,AV_LOG_INFO,"===priority:%d,bandwidth:%d\n",var->priority,var->bandwidth); break; } } } float value = 0.0; int ret = -1; ret = am_getconfig_float("libplayer.hls.bw_max", &value); if(ret>=0&&value>0){ for (i=0; i < mgt->n_variants; i++){ var = mgt->variants[i]; if(var->bandwidth>value){ var->priority = -1; } } } ret = am_getconfig_float("libplayer.hls.bw_min", &value); if(ret>=0&&value>0){ for (i=0; i < mgt->n_variants; i++){ var = mgt->variants[i]; if(var->bandwidth<value){ var->priority = -2; } } }else{ for (i=0; i < mgt->n_variants; i++){ var = mgt->variants[i]; if(var->bandwidth<AUDIO_BANDWIDTH_MAX){ var->priority = -2; } } } ret = am_getconfig_float("libplayer.hls.bw_start", &value); if(ret>=0&&value>=0){ for (i=0; i < mgt->n_variants; i++){ var = mgt->variants[i]; if(var->priority==(int)value){ mgt->playing_variant= var; break; } } }else{ ret =(int)get_adaptation_ex_para(3); for (i=0; i < mgt->n_variants; i++){ var = mgt->variants[i]; if(ret>=0){ if(ret>(mgt->n_variants-1)){ ret = mgt->n_variants-1; } if(var->priority==ret){ mgt->playing_variant= var; break; } }else{ if(var->priority>=0){ mgt->playing_variant= var; break; } } } } //av_log(NULL,AV_LOG_INFO,"Do fast sort streaming"); return 0; }