⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 media-app.cc

📁 柯老师网站上找到的
💻 CC
📖 第 1 页 / 共 4 页
字号:
// to the lowest layer, i.e. it fills the triangle in a bottom-up// starting from the base layer. We use this routine instead of bufOpt,// for all cases during filling phase. Allocation based on diagonal strips//double QA::bufOptScen1(int layer, int layers, double currrate, 		       double slope, int backoffs){	double smallt, larget, side, rate;  	if (backoffs < 0) {		panic("# ERROR: backoff: %d in bufOptScen1\n", 		      backoffs);	}	rate = currrate/pow(2,backoffs);	side = LAYERBW_*layers - (rate + layer*LAYERBW_);	if (side <= 0.0) 		return(0.0);	larget = BufNeed(side, slope);	side = LAYERBW_*layers - (rate + (layer+1)*LAYERBW_);	if (side < 0.0) 		side = 0.0;	smallt = BufNeed(side, slope);	return (larget-smallt);}//// This routine calculate optimal buffer distribution for a layer// in scenario 2 based on the // 1) current rate, 2) no of layers, 3) no of backoffs//// Jan 28, 99bufOptScen1(layer, layers, currrate, slope, backoffs)//double QA::bufOptScen2(int layer, int layers, double currrate, 		       double slope, int backoffs){	double bufopt = 0.0;	int bmin, done;	if(backoffs < 0) {		panic("# ERROR: backoff: %d in bufOptScen2\n", 			backoffs);	}	if ((currrate/pow(2,backoffs)) >= layers*LAYERBW_)		return(0.0);	bmin = 0;	done = 0;	while ((!done) && bmin<=backoffs) {		if(currrate/pow(2,bmin) >= LAYERBW_*layers)			bmin++;		else 			done++;	}	// buf required for the first triangle	// we could have dec bmin and go for 1 backoff as well	bufopt = bufOptScen1(layer, layers, currrate/pow(2,bmin), slope, 0);  	// remaining sequential backoffs	bufopt += (backoffs - bmin)*BufNeed(layers*LAYERBW_/2, slope);	return(bufopt);}//// This routine returns the optimal distribution of requested-to-drained// buffer across active layers based on:// 1) curr rate, 2) curr drain distr(FinalDrainArry), etc// NOTE, the caller must update FinalDrainArray from // // Jan 29, 99//// DrainArr: return value, used as an incremental chaneg for //   FinalDrainArray// bufAvail:  current buffer_ statevoid QA::drain_buf(double* DrainArr, double bufToDrain, 		   double* FinalDrainArray, double* bufAvail, 		   int layers, double rate, double srtt){	double bufReq1, bufReq2, bufs1[MAX_LAYER], bufs2[MAX_LAYER], slope, 		extra, targetArr[MAX_LAYER], maxDrainRemain;	int bs1, bs2, l;	slope = seg_size_/srtt;	bs1 = MAXBKOFF_ + 1;	bs2 = MAXBKOFF_ + 1;	bufReq1 = bufReq2 = 0;	for(l=0; l<layers; l++){		bufReq1 += bufOptScen1(l, layers, rate, slope, bs1);		bufReq2 += bufOptScen2(l, layers, rate, slope, bs2);	} 	for(l=0; l<MAX_LAYER; l++){		bufs1[l] = 0;		bufs2[l] = 0;		DrainArr[l] = 0.0;	}	while(bufReq1 > TotalBuf(layers, bufAvail)){		bufReq1 = 0;		bs1--;		for(l=0; l<layers; l++){			bufs1[l] = bufOptScen1(l, layers, rate, slope, bs1);			bufReq1 += bufs1[l];		} 	}  	while(bufReq2 > TotalBuf(layers, bufAvail)){		bufReq2 = 0;		bs2--;		for(l=0; l<layers; l++){			bufs2[l] =  bufOptScen2(l, layers, rate, slope, bs2);			bufReq2 += bufs2[l];		} 	}	if (bufReq1 >= bufReq2) {		// drain toward last optimal scenario 1		for (l=layers-1; l>=0; l--){			// we try to drain the maximum amount from			// min no of highest layers			// note that there is a limit on total draining			// from a layer			maxDrainRemain = srtt*LAYERBW_ - FinalDrainArray[l];			if ((bufAvail[l] > bufs1[l] + maxDrainRemain) &&			    (bufToDrain >= maxDrainRemain)) {				DrainArr[l] = maxDrainRemain;				bufToDrain -= maxDrainRemain;			} else {				if(bufAvail[l] > bufs1[l] + maxDrainRemain){					DrainArr[l] = bufToDrain;					bufToDrain = 0.0;				} else {					DrainArr[l] = bufAvail[l] - bufs1[l];					bufToDrain -= bufAvail[l] - bufs1[l];					/* for debug */					if(DrainArr[l] < 0.0){// 	    panic("# ERROR, DrainArr[%d]: %.2f, bufAvail: %.2f, bufs1: %.2f\n",// 		  l, DrainArr[l], bufAvail[l], bufs1[l]);						DrainArr[l] = 0.0;					}				}			}			if(bufToDrain == 0.0)				return;		}		return;	} else {   /* if (bufReq1 >= bufReq2) */		// Drain towards he last optima scenario 2 		// We're draining - don't care about the upper bound on 		// scenario 2.		// Have to calculate all the layers together to get this max 		// thing to work		extra = 0.0;		// Calculate the extra buffering 		for (l=0; l<layers; l++) {			if(bufs1[l] > bufs2[l])				extra += bufs1[l] - bufs2[l];		}		for (l=layers-1; l>=0; l--)			if(bufs1[l] >= bufs2[l])				targetArr[l] = bufs1[l];			else				if (bufs2[l] - bufs1[l] >= extra) {					targetArr[l] = bufs2[l] - extra;					extra = 0;				} else {					// there is enough extra to compenstae the dif					if (extra > 0) {						targetArr[l] = bufs2[l];						extra -= bufs2[l] - bufs1[l];					} else 						panic("# ERROR Should not \reach here, extra: %.2f, bufs2: %.2f, bufs1: %.2f, L%d\n", 						extra, bufs2[l], bufs1[l], l);				}	} /* end of if (bufReq1 >= bufReq2) */   	// drain toward last optimal scenario 2	for (l=layers-1; l>=0; l--) {		// we try to drain the maximum amount from		// min no of highest layers		// note that there is a limit on total draining		// from a layer		maxDrainRemain = srtt*LAYERBW_ - FinalDrainArray[l];		if ((bufAvail[l] > targetArr[l] + maxDrainRemain) &&		    (bufToDrain >= maxDrainRemain)) {			DrainArr[l] = maxDrainRemain;			bufToDrain -= maxDrainRemain;		} else {			if(bufAvail[l] > targetArr[l] + maxDrainRemain){				DrainArr[l] = bufToDrain;				bufToDrain = 0.0;			} else {				DrainArr[l] = bufAvail[l] - targetArr[l];				bufToDrain -= bufAvail[l] - targetArr[l];					// for debug 				if (DrainArr[l] < 0.0) {// 	  panic("# ERROR, DrainArr[%d]: %.2f, bufAvail: %.2f, bufs1: %.2f\n",// 		l, DrainArr[l], bufAvail[l], bufs1[l]);					DrainArr[l] = 0;				}			}		}		if (bufToDrain == 0.0)			return;	} /* end of for */	return;}//// This routine calculate an optimal distribution of a given // amount of buffered data to drain.// the main algorithm is in drain_buf() and this one mainly init// the input and calls that routine ad then update FinalDrainArray,// based on its old value and return value for DrainArr.//// FinalDrainArray: output// FinalBuffer: output, expected buf state at the end of the intervalvoid QA::DrainPacket(double bufToDrain, double* FinalDrainArray, int layers,		     double rate, double srtt, double* FinalBuffer){	double DrainArr[MAX_LAYER],  bufAvail[MAX_LAYER], TotBufAvail;	int l,cnt;  	for(l=0; l<MAX_LAYER; l++){		FinalDrainArray[l] = 0.0;		bufAvail[l] = buffer_[l];	}	TotBufAvail = TotalBuf(layers, bufAvail);	cnt = 0;	while ((bufToDrain > 0) && (cnt < 10)) {		// debug("bufToDrain%d: %.2f\n", cnt, bufToDrain);		drain_buf(DrainArr, bufToDrain, FinalDrainArray, bufAvail, 			  layers, rate, srtt);				for(l=0; l<layers; l++){			bufToDrain -= DrainArr[l];			TotBufAvail -= DrainArr[l];			FinalDrainArray[l] += DrainArr[l];			bufAvail[l] -= DrainArr[l];			FinalBuffer[l] = buffer_[l] - FinalDrainArray[l];		}		cnt++;	}}void QA::check_availability(int layer, const MediaSegment& s) {	int dummy; 	MediaRequest p(MEDIAREQ_CHECKSEG);	p.set_name(page_);	p.set_layer(layer);	p.set_st(s.start());	p.set_et(s.end());	p.set_app(this);	// Ask cache/server to do prefetching if necessary.	target()->get_data(dummy, &p);}/*  * This routine is called once every SRTT to drain some data from * recv's buffer and src's image from recv's buf. */void QA::DrainBuffers(){	int i, j, layers = 0;	Scheduler& s = Scheduler::instance();	double now = s.clock();	// interval since last drain	double interval = now - playTime_;	playTime_ = now;  // update playTime	if ((layers > 1) && (playing_[0] != 1)) {		panic("ERROR in DrainBuffer: layers>0 but L0 isn't playing\n");	}	// Updating playout offset, but do nothing if we are in the initial	// startup filling phase! This offset measures the playing progress	// of the client side. It is actually the playing offset of the lowest	// layer.	// This is the real amount of data to be drained from layers	int todrain[MAX_LAYER]; 	// Expected offset of base layer after draining, without considering 	// holes in data. This has to be satisfied, otherwise base layer will	// be dropped and an error condition will be raised.	poffset_ += (int)floor(interval*LAYERBW_+0.5);	// Started from MAX_LAYER to make debugging easier	for (i = MAX_LAYER-1; i >= 0; i--) {		// If this layer is not being played, don't drain anything		if (sending_[i] == 0) {			todrain[i] = 0;			drained_[i] = 0.0;			continue; 		}		todrain[i] = outlist_[i].evict_head_offset(poffset_);		assert(todrain[i] >= 0);		buffer_[i] -= todrain[i];		// A buffer must have more than one byte		if ((int)buffer_[i] <= 0) {			debug("Buffer %d ran dry: %.2f after draining, DROP\n",			      i, buffer_[i]);			playing_[i] = 0;			sending_[i] = 0;			buffer_[i] = 0;	    			/* Drop all higher layers if they still have data */			for (j = i+1; j < MAX_LAYER; j++)				if (sending_[j] == 1) {/* 					panic("# ERROR: layer %d \is playing with %.2f buf but layer %d ran dry with %.2f buf\n", 					      j, buffer_[j], i, buffer_[i]);*/ 					debug("# DROP layer %d: it \is playing with %.2f buf but layer %d ran dry with %.2f buf\n", 					      j, buffer_[j], i, buffer_[i]);					sending_[j] = 0;					playing_[j] = 0;					buffer_[j] = 0;				}			// We don't need to set it to -1. The old address 			// will be used to see if we are sending old data if 			// that later is added again			//			// XXX Where is this -1 mark ever used????			// data_[i].set_start(-1); // drop layer i		} else {			// Prefetch for this layer. Round to whole segment			int st = (int)floor((poffset_+pref_srtt_*LAYERBW_)					    /seg_size_+0.5)*seg_size_;			int et = (int)floor((poffset_+(pref_srtt_+interval)*					   LAYERBW_)/seg_size_+0.5)*seg_size_;			if (et > pref_[i]) {				pref_[i] = et;				MediaSegment s(st, et);				check_availability(i, s);			}		}	} /* end of for */}// This routine dumps info into a file// format of each line is as follows://  time tot-rate avg-rate per-layer-bw[MAXLAYER] tot-bw drain-rate[MAXLAYER] //  & cumulative-buffer[MAXLAYER] & no-of-layers // ADDED: use the old value of SRTT for bw/etc estimation !!! Jan 26// XXX: need to be more compressed add more hooks to for ctrling from  // tcl levelvoid QA::DumpInfo(double t, double last_t, double rate, 		  double avgrate, double srtt){#define MAXLEN 2000	int i,j;	char s1[MAXLEN], s2[MAXLEN], tmp[MAXLEN];	static double last_srtt = 0, t1,t2 = 0;#undef MAXLEN	double  tot_bw = 0.0, interval, diff;// 	if(rate > 1000000.0){// 		debug("WARNING rate: %f is too large\n", rate);// 	}		interval = t - last_t ;  	if((t2 != last_t) && (t2 > 0)){		diff = interval - last_srtt;		if ((diff > 0.001) || (diff < -0.001)) {			if (last_t == 0) 				// Startup phase				return;/* 			debug("WARNING: last_srtt: %.4f != \interval: %.4f, diff: %f t1: %f, t2: %f, last_t: %f, t: %f\n", 				last_srtt, interval, diff, t1, t2, last_t, t);*/			//abort();		}	} else 		/* for the first call to init */		last_srtt = srtt;	t1 = last_t;	t2 = t;	if (interval <= 0.0) {		panic("# ERROR interval is negative\n");	}	sprintf(s1, " %.2f %.2f %.2f X", last_t, rate, avgrate); 	sprintf(s2, " %.2f %.2f %.2f X", t, rate, avgrate);		j = 0;	for (i = 0; i < MAX_LAYER; i++) 	  //if (playing_[i] == 1)	  if (sending_[i] == 1)	    j++;	//no of layers being playback	sprintf(tmp, " %d", j*LAYERBW_);	strcat(s1, tmp);	strcat(s2, tmp);	for (i = 0; i < MAX_LAYER; i++) {		sprintf(tmp, " %.2g ", (bw_[i]/interval)+i*10000.0);		strcat(s1,tmp);		strcat(s2,tmp);		tot_bw += bw_[i]/interval;		bw_[i] = 0;	}	sprintf(tmp, " %.2f X", tot_bw );	strcat(s1,tmp);	strcat(s2,tmp);  	j = 0;	for (i = 0; i < MAX_LAYER; i++) {	  //if (playing_[i] == 1) {	  if(sending_[i] ==1){	    j++;	    // drained_[] can be neg when allocated buf for this 	    // layer is more than consumed data	    if (drained_[i] < 0.0) {	      // this means that this layer was drained 	      // with max rate	      drained_[i] = 0.0;	    } 	    // XXX, we could have used interval*LAYERBW_ - bw_[i]	    // that was certainly better	    sprintf(tmp, " %.2f ", 		    (drained_[i]/interval)+i*10000.0);	    strcat(s1,tmp);	    strcat(s2,tmp);	    // Note that drained[] shows the amount of data that 	    // is used from buffered data, i.e. rd[i]	    // This must be srtt instead of interval because this 	    // is for next dumping.	    drained_[i]=srtt*LAYERBW_;	  } else {	    sprintf(tmp, " %.2f ", i*10000.0);	    strcat(s1,tmp);	    strcat(s2,tmp);	    drained_[i] = 0.0;	  }	}	for (i=0;i<MAX_LAYER;i++) {		sprintf(tmp, " %.2f", buffer_[i]+i*10000);		strcat(s1,tmp);		strcat(s2,tmp);	}		log("QA %s \n", s1);	log("QA %s \n", s2);	fflush(stdout);}// This routine models draining of buffers at the recv// it periodically updates state of buffers// Ir must be called once and then it reschedules itself// it is first called after playout is started!void QA::UpdateState(){	double last_ptime = playTime_; // Last time to drain buffer	DrainBuffers();	DumpInfo(Scheduler::instance().clock(), last_ptime, 		 rate(), avgrate_, rap()->srtt());}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -