00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 #include <stdarg.h>
00054
00055 #include "template.h"
00056 #include "media-app.h"
00057 #include "utilities.h"
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 MediaSegment::MediaSegment(const HttpMediaData& d) : flags_(0)
00069 {
00070 start_ = d.st();
00071 end_ = d.et();
00072 if (d.is_last())
00073 set_last();
00074 if (d.is_pref())
00075 set_pref();
00076 }
00077
00078 void MediaSegmentList::add(const MediaSegment& s)
00079 {
00080 MediaSegment* tmp = (MediaSegment *)head_;
00081 while ((tmp != NULL) && (tmp->before(s))) {
00082 tmp = tmp->next();
00083 }
00084
00085
00086 if (tmp == NULL) {
00087 length_ += s.datasize();
00088 if ((tail_ != NULL) && ((MediaSegment *)tail_)->overlap(s))
00089
00090 ((MediaSegment*)tail_)->merge(s);
00091 else {
00092 MediaSegment *p = new MediaSegment(s);
00093 if (head_ == NULL)
00094 head_ = tail_ = p;
00095 else
00096 append(p, tail_);
00097 }
00098 if (getsize() != length_) {
00099 fprintf(stderr,
00100 "MediaSegmentList corrupted: Point 1.\n");
00101 abort();
00102 }
00103 return;
00104 }
00105
00106
00107 if (tmp->in(s)) {
00108 fprintf(stderr,
00109 "MediaSegmentList: get a seg (%d %d) which is already in cache!\n",
00110 s.start(), s.end());
00111 fprintf(stderr, "List contents: ");
00112 print();
00113 #if 0
00114
00115
00116 #endif
00117
00118 return;
00119 }
00120
00121
00122 if (tmp->overlap(s)) {
00123 length_ += (s.datasize() - tmp->merge(s));
00124 } else {
00125 MediaSegment *p = new MediaSegment(s);
00126 insert(p, tmp);
00127 tmp = p;
00128 length_ += s.datasize();
00129 }
00130
00131 if (getsize() != length_) {
00132 fprintf(stderr, "MediaSegmentList corrupted: Point 2.\n");
00133 abort();
00134 }
00135
00136 merge_seg(tmp);
00137
00138 if (getsize() != length_) {
00139 fprintf(stderr, "MediaSegmentList corrupted: Point 3.\n");
00140 abort();
00141 }
00142 }
00143
00144 void MediaSegmentList::merge_seg(MediaSegment* tmp)
00145 {
00146
00147 MediaSegment *q = tmp->next();
00148 while (q && q->overlap(*tmp)) {
00149 #if 1
00150 if ((tmp->start() == q->start()) && (tmp->end() == q->end())) {
00151 abort();
00152 }
00153 #endif
00154 tmp->merge(*q);
00155 detach(q);
00156 delete q;
00157 q = tmp->next();
00158 }
00159
00160 q = tmp->prev();
00161 while (q && q->overlap(*tmp)) {
00162 tmp->merge(*q);
00163 assert(tail_ != q);
00164 detach(q);
00165 delete q;
00166 q = tmp->prev();
00167 }
00168 }
00169
00170 int MediaSegmentList::in(const MediaSegment& s)
00171 {
00172 MediaSegment* tmp = (MediaSegment *)head_;
00173 while ((tmp != NULL) && (tmp->before(s)))
00174 tmp = tmp->next();
00175
00176
00177
00178 if ((tmp == NULL) || !s.in(*tmp))
00179 return 0;
00180 else
00181 return 1;
00182 }
00183
00184
00185
00186 MediaSegment MediaSegmentList::get_nextseg(const MediaSegment& s)
00187 {
00188 MediaSegment res(0, 0);
00189
00190 MediaSegment* tmp = (MediaSegment *)head_;
00191 while ((tmp != NULL) && (tmp->before(s)))
00192 tmp = tmp->next();
00193 if (tmp == NULL) {
00194 res.set_last();
00195 return res;
00196 }
00197 assert(tmp->end() > s.start());
00198
00199
00200
00201
00202
00203
00204 res = s;
00205 int orig_size = s.datasize();
00206 if (res.start() < tmp->start()) {
00207
00208
00209
00210
00211
00212 res.set_start(tmp->start());
00213 if (tmp->datasize() < orig_size)
00214
00215 res.set_datasize(tmp->datasize());
00216 else
00217 res.set_datasize(orig_size);
00218 } else if (res.end() > tmp->end()) {
00219
00220
00221
00222
00223
00224 res.set_datasize(tmp->end()-res.start());
00225 }
00226
00227
00228
00229 assert(res.datasize() <= tmp->datasize());
00230 if ((res.end() == tmp->end()) && (tmp->next() == NULL))
00231
00232 res.set_last();
00233 return res;
00234 }
00235
00236
00237
00238 int MediaSegmentList::evict_tail(int size)
00239 {
00240 int sz = size, tz;
00241 MediaSegment *tmp = (MediaSegment *)tail_;
00242 while ((tmp != NULL) && (sz > 0)) {
00243
00244 tz = tmp->evict_tail(sz);
00245 length_ -= tz;
00246 sz -= tz;
00247 if (tmp->datasize() == 0) {
00248
00249 detach(tmp);
00250 delete tmp;
00251 tmp = (MediaSegment *)tail_;
00252 }
00253 }
00254 return size - sz;
00255 }
00256
00257
00258 int MediaSegmentList::evict_head(int size)
00259 {
00260 int sz = size, tz;
00261 MediaSegment *tmp = (MediaSegment *)head_;
00262 while ((tmp != NULL) && (sz > 0)) {
00263
00264 tz = tmp->evict_head(sz);
00265 sz -= tz;
00266 length_ -= tz;
00267 if (tmp->datasize() == 0) {
00268
00269 detach(tmp);
00270 delete tmp;
00271 tmp = (MediaSegment *)head_;
00272 }
00273 }
00274 return size - sz;
00275 }
00276
00277
00278
00279 int MediaSegmentList::evict_head_offset(int offset)
00280 {
00281 int sz = 0;
00282 MediaSegment *tmp = (MediaSegment *)head_;
00283 while ((tmp != NULL) && (tmp->start() < offset)) {
00284 if (tmp->end() <= offset) {
00285
00286 sz += tmp->datasize();
00287 length_ -= tmp->datasize();
00288 detach(tmp);
00289 delete tmp;
00290 tmp = (MediaSegment *)head_;
00291 } else {
00292
00293 sz += offset - tmp->start();
00294 length_ -= offset - tmp->start();
00295 tmp->set_start(offset);
00296 }
00297 }
00298 if (head_ == NULL)
00299 tail_ = NULL;
00300 return sz;
00301 }
00302
00303
00304 MediaSegmentList MediaSegmentList::check_holes(const MediaSegment& s)
00305 {
00306 MediaSegmentList res;
00307 MediaSegment* tmp = (MediaSegment *)head_;
00308 while ((tmp != NULL) && (tmp->before(s)))
00309 tmp = tmp->next();
00310
00311 if (tmp == NULL) {
00312 res.add(s);
00313 return res;
00314 }
00315
00316 if (s.in(*tmp))
00317 return res;
00318
00319
00320 int soff, eoff;
00321 soff = s.start();
00322 eoff = s.end();
00323 while ((tmp != NULL) && (tmp->overlap(s))) {
00324 if (soff < tmp->start()) {
00325
00326 res.add(MediaSegment(soff, min(eoff, tmp->start())));
00327 #if 1
00328
00329
00330 if (in(MediaSegment(soff, min(eoff, tmp->start())))) {
00331 fprintf(stderr, "Wrong hole: (%d %d) ",
00332 soff, min(eoff, tmp->start()));
00333 fprintf(stderr, "tmp(%d %d), s(%d %d)\n",
00334 tmp->start(), tmp->end(),
00335 soff, eoff);
00336 fprintf(stderr, "List content: ");
00337 print();
00338 }
00339 #endif
00340 }
00341 soff = tmp->end();
00342 tmp = tmp->next();
00343 }
00344 if (soff < eoff) {
00345 res.add(MediaSegment(soff, eoff));
00346 #if 1
00347
00348
00349 if (in(MediaSegment(soff, eoff))) {
00350 fprintf(stderr, "Wrong hole #2: (%d %d)\n",
00351 soff, eoff);
00352 fprintf(stderr, "List content: ");
00353 print();
00354 }
00355 #endif
00356 }
00357 #if 0
00358 check_integrity();
00359 #endif
00360 return res;
00361 }
00362
00363 void MediaSegmentList::check_integrity()
00364 {
00365 MediaSegment *p, *q;
00366 p = (MediaSegment*)head_;
00367 while (p != NULL) {
00368 q = p;
00369 p = p->next();
00370 if (p == NULL)
00371 break;
00372 if (!q->before(*p)) {
00373 fprintf(stderr,
00374 "Invalid segment added: (%d %d), (%d %d)\n",
00375 q->start(), q->end(), p->start(), p->end());
00376 abort();
00377 }
00378 }
00379 }
00380
00381
00382
00383
00384 int MediaSegmentList::overlap_size(const MediaSegment& s) const
00385 {
00386 int res = 0;
00387 MediaSegment* tmp = (MediaSegment *)head_;
00388 while ((tmp != NULL) && (tmp->before(s)))
00389 tmp = tmp->next();
00390
00391 if (tmp == NULL)
00392 return 0;
00393
00394 if (s.in(*tmp))
00395 return s.datasize();
00396
00397 int soff, eoff;
00398 soff = s.start();
00399 eoff = s.end();
00400 while ((tmp != NULL) && (tmp->overlap(s))) {
00401 res += min(eoff, tmp->end()) - max(soff, tmp->start());
00402 soff = tmp->end();
00403 tmp = tmp->next();
00404 }
00405 return res;
00406 }
00407
00408
00409 void MediaSegmentList::print()
00410 {
00411 MediaSegment *p = (MediaSegment *)head_;
00412 int i = 0, sz = 0;
00413 while (p != NULL) {
00414 printf("(%d, %d) ", p->start(), p->end());
00415 sz += p->datasize();
00416 p = p->next();
00417 if (++i % 8 == 0)
00418 printf("\n");
00419 }
00420 printf("\nTotal = %d\n", sz);
00421 }
00422
00423
00424 int MediaSegmentList::getsize()
00425 {
00426 MediaSegment *p = (MediaSegment *)head_;
00427 int sz = 0;
00428 while (p != NULL) {
00429 sz += p->datasize();
00430 p = p->next();
00431 }
00432 return sz;
00433 }
00434
00435
00436 char* MediaSegmentList::dump2buf()
00437 {
00438 char *buf = new char[1024];
00439 char *b = buf;
00440 MediaSegment *p = (MediaSegment *)head_;
00441 int i = 0, sz = 1024;
00442 buf[0] = 0;
00443 while (p != NULL) {
00444
00445
00446 i = snprintf(b, sz, "{%d %d} ", p->start(), p->end());
00447 sz -= i;
00448
00449 if (sz < 50) {
00450 char *tmp = new char[strlen(buf)+1024];
00451 strcpy(tmp, buf);
00452 delete []buf;
00453 buf = tmp;
00454 b = buf + strlen(buf);
00455 sz += 1024;
00456 } else
00457 b += i;
00458 p = p->next();
00459 }
00460 return buf;
00461 }
00462
00463
00464
00465 HttpMediaData::HttpMediaData(const char* sender, const char* page, int layer,
00466 int st, int et) :
00467 HttpData(MEDIA_DATA, 0), layer_(layer), st_(st), et_(et), flags_(0)
00468 {
00469 assert(strlen(page)+1 <= (size_t)HTTP_MAXURLLEN);
00470 strcpy(page_, page);
00471 assert(strlen(sender)+1 <= (size_t)HTTP_MAXURLLEN);
00472 strcpy(sender_, sender);
00473 }
00474
00475
00476
00477 static class MappClass : public TclClass {
00478 public:
00479 MappClass() : TclClass("Application/MediaApp") {}
00480 TclObject* create(int argc, const char*const* argv) {
00481 if (argc > 4)
00482 return (new MediaApp(argv[4]));
00483 return NULL;
00484 }
00485 } class_mapp;
00486
00487 MediaApp::MediaApp(const char* page) :
00488 log_(0), num_layer_(0), last_layer_(0)
00489 {
00490 strcpy(page_, page);
00491
00492
00493 for (int i = 0; i < MAX_LAYER; i++)
00494 data_[i].set_start(0);
00495
00496 bind("segmentSize_", &seg_size_);
00497 }
00498
00499 void MediaApp::start()
00500 {
00501 fprintf(stderr, "MediaApp::start() not supported\n");
00502 abort();
00503 }
00504
00505 void MediaApp::stop()
00506 {
00507
00508 rap()->stop();
00509 }
00510
00511 AppData* MediaApp::get_data(int& nbytes, AppData* req)
00512 {
00513 AppData *res;
00514 if (req == NULL) {
00515 MediaRequest p(MEDIAREQ_GETSEG);
00516 p.set_name(page_);
00517
00518 if (num_layer_ > 0) {
00519 p.set_layer(last_layer_++);
00520 last_layer_ = last_layer_ % num_layer_;
00521 } else
00522 p.set_layer(0);
00523 p.set_st(data_[0].start());
00524 p.set_datasize(seg_size_);
00525 p.set_app(this);
00526 res = target()->get_data(nbytes, &p);
00527 } else
00528 res = target()->get_data(nbytes, req);
00529
00530
00531 assert(res != NULL);
00532 HttpMediaData *p = (HttpMediaData *)res;
00533
00534
00535
00536
00537 if (p->datasize() <= 0) {
00538
00539
00540
00541
00542 delete p;
00543 return NULL;
00544 } else {
00545
00546
00547
00548
00549
00550
00551
00552
00553 assert((p->datasize() > 0) && (p->datasize() <= seg_size_));
00554 data_[p->layer()].set_start(p->et());
00555 data_[p->layer()].set_datasize(seg_size_);
00556 }
00557 return res;
00558 }
00559
00560 int MediaApp::command(int argc, const char*const* argv)
00561 {
00562 Tcl& tcl = Tcl::instance();
00563 if (strcmp(argv[1], "log") == 0) {
00564 int mode;
00565 log_ = Tcl_GetChannel(tcl.interp(),
00566 (char*)argv[2], &mode);
00567 if (log_ == 0) {
00568 tcl.resultf("%s: invalid log file handle %s\n",
00569 name(), argv[2]);
00570 return TCL_ERROR;
00571 }
00572 return TCL_OK;
00573 } else if (strcmp(argv[1], "evTrace") == 0) {
00574 char buf[1024], *p;
00575 if (log_ != 0) {
00576 sprintf(buf, "%.17g ",
00577 Scheduler::instance().clock());
00578 p = &(buf[strlen(buf)]);
00579 for (int i = 2; i < argc; i++) {
00580 strcpy(p, argv[i]);
00581 p += strlen(argv[i]);
00582 *(p++) = ' ';
00583 }
00584
00585 *(p++) = '\n', *p = 0;
00586 Tcl_Write(log_, buf, p-buf);
00587 }
00588 return TCL_OK;
00589 } else if (strcmp(argv[1], "set-layer") == 0) {
00590 int n = atoi(argv[2]);
00591 if (n >= MAX_LAYER) {
00592 fprintf(stderr,
00593 "Too many layers than maximum allowed.\n");
00594 return TCL_ERROR;
00595 }
00596 num_layer_ = n;
00597 return TCL_OK;
00598 }
00599 return Application::command(argc, argv);
00600 }
00601
00602 void MediaApp::log(const char* fmt, ...)
00603 {
00604 char buf[1024], *p;
00605 char *src = Address::instance().print_nodeaddr(rap()->addr());
00606 sprintf(buf, "%.17g i %s ", Scheduler::instance().clock(), src);
00607 delete []src;
00608 p = &(buf[strlen(buf)]);
00609 va_list ap;
00610 va_start(ap, fmt);
00611 vsprintf(p, fmt, ap);
00612 if (log_ != 0)
00613 Tcl_Write(log_, buf, strlen(buf));
00614 }
00615
00616
00617
00618
00619
00620 void QATimer::expire(Event *)
00621 {
00622 a_->UpdateState();
00623 resched(a_->UpdateInterval());
00624 }
00625
00626 static class QAClass : public TclClass {
00627 public:
00628 QAClass() : TclClass("Application/MediaApp/QA") {}
00629 TclObject* create(int argc, const char*const* argv) {
00630 if (argc > 4)
00631 return (new QA((const char *)(argv[4])));
00632 return NULL;
00633 }
00634 } class_qa_app;
00635
00636
00637
00638
00639 QA::QA(const char *page) : MediaApp(page)
00640 {
00641 updTimer_ = new QATimer(this);
00642
00643 bind("LAYERBW_", &LAYERBW_);
00644 bind("MAXACTIVELAYERS_", &MAXACTIVELAYERS_);
00645 bind("SRTTWEIGHT_", &SRTTWEIGHT_);
00646 bind("SMOOTHFACTOR_", &SMOOTHFACTOR_);
00647 bind("MAXBKOFF_", &MAXBKOFF_);
00648 bind("debug_output_", &debug_);
00649 bind("pref_srtt_", &pref_srtt_);
00650
00651 for(int j = 0; j < MAX_LAYER; j++) {
00652 buffer_[j] = 0.0;
00653 sending_[j] = 0;
00654 playing_[j] = 0;
00655 drained_[j] = 0.0;
00656 bw_[j] = 0.0;
00657 pref_[j] = 0;
00658 }
00659 poffset_ = 0;
00660 playTime_ = 0;
00661 startTime_ = -1;
00662
00663
00664 rate_weight_ = 0.01;
00665 avgrate_ = 0.0;
00666 }
00667
00668 QA::~QA()
00669 {
00670 if (updTimer_) {
00671 if (updTimer_->status() != TIMER_IDLE)
00672 updTimer_->cancel();
00673 delete updTimer_;
00674 }
00675 }
00676
00677 void QA::debug(const char* fmt, ...)
00678 {
00679 if (!debug_)
00680 return;
00681
00682 char buf[1024], *p;
00683 char *src = Address::instance().print_nodeaddr(rap()->addr());
00684 char *port = Address::instance().print_portaddr(rap()->addr());
00685 sprintf(buf, "# t %.17g i %s.%s QA ",
00686 Scheduler::instance().clock(), src, port);
00687 delete []port;
00688 delete []src;
00689 p = &(buf[strlen(buf)]);
00690 va_list ap;
00691 va_start(ap, fmt);
00692 vsprintf(p, fmt, ap);
00693 fprintf(stderr, "%s", buf);
00694 }
00695
00696 void QA::panic(const char* fmt, ...)
00697 {
00698 char buf[1024], *p;
00699 char *src = Address::instance().print_nodeaddr(rap()->addr());
00700 char *port = Address::instance().print_portaddr(rap()->addr());
00701 sprintf(buf, "# t %.17g i %s.%s QA PANIC ",
00702 Scheduler::instance().clock(), src, port);
00703 delete []port;
00704 delete []src;
00705 p = &(buf[strlen(buf)]);
00706 va_list ap;
00707 va_start(ap, fmt);
00708 vsprintf(p, fmt, ap);
00709 fprintf(stderr, "%s", buf);
00710
00711 #if 0
00712
00713 Tcl::instance().eval("[Simulator instance] flush-trace");
00714 abort();
00715 #endif
00716 }
00717
00718
00719 void QA::stop()
00720 {
00721 rap()->stop();
00722 if (updTimer_->status() != TIMER_IDLE)
00723 updTimer_->cancel();
00724 }
00725
00726
00727 int QA::command(int argc, const char*const* argv)
00728 {
00729 return MediaApp::command(argc, argv);
00730 }
00731
00732
00733
00734 AppData* QA::get_data(int& size, AppData*)
00735 {
00736 int layers, dropped, i, l, idx, bs1, bs2,scenario, done, cnt;
00737 double slope, bufavail, bufneeded, totbufs1, totbufs2,
00738 optbufs1[MAX_LAYER], optbufs2[MAX_LAYER], bufToDrain;
00739
00740 static double last_rate = 0.0, last_depart, nextAdjPoint = -1,
00741 FinalDrainArray[MAX_LAYER],
00742 tosend[MAX_LAYER], FinalBuffer[MAX_LAYER];
00743
00744 static int flag,
00745 tosendPtr = 0;
00746
00747
00748 double rate = seg_size_ / rap()->ipg();
00749 double srtt = rap()->srtt();
00750 Scheduler& s = Scheduler::instance();
00751 double now = s.clock();
00752 int anyAck = rap()->anyack();
00753
00754 assert((num_layer_ > 0) && (num_layer_ < MAX_LAYER));
00755
00756
00757
00758
00759
00760 if (anyAck == 0) {
00761 sending_[0] = 1;
00762 return output(size, 0);
00763 debug("INIT Phase, send packet: layer 0 in send_pkt, \
00764 rate: %.3f, avgrate: %.3f, srtt:%.3f\n", rate, avgrate_, srtt);
00765 }
00766
00767 layers = 0;
00768
00769
00770 slope = seg_size_/srtt;
00771 bufavail = 0.0;
00772
00773
00774 bufneeded = 0.0;
00775
00776
00777 for (i = 0; i < MAX_LAYER; i++) {
00778 layers += sending_[i];
00779 if (sending_[i] == 1)
00780 bufavail += buffer_[i];
00781 else
00782
00783 if ((i < MAX_LAYER - 1) && (sending_[i+1] == 1))
00784 panic("ERROR L%d is not sent but L%d is.\n",
00785 i, i+1);
00786 }
00787
00788
00789 if((layers == 1) && (playing_[0] != 1)){
00790
00791
00792 if (sending_[0] == 0) {
00793 panic("ERROR sending[0]=0 !!!");
00794 }
00795 AppData *res = output(size, 0);
00796 debug("STARTUP, send packet: layer 0\n");
00797
00798
00799
00800 bufneeded = max(4*BufNeed((LAYERBW_-rate/2.0), slope),
00801 2*MWM(srtt));
00802
00803 if (buffer_[0] >= bufneeded) {
00804 playing_[0] = 1;
00805 sending_[0] = 1;
00806 drained_[0] = 0;
00807 startTime_ = now;
00808 playTime_ = now;
00809 debug("... START Playing_ layer 0, buffer[0] = %f!\n",
00810 buffer_[0]);
00811
00812 if (updTimer_->status() == TIMER_IDLE)
00813 updTimer_->sched(srtt);
00814 }
00815 return(res);
00816 }
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842 if (rate < layers*LAYERBW_) {
00843 bufneeded = (MWM(srtt)*layers) +
00844 BufNeed((layers*LAYERBW_-rate), slope);
00845
00846
00847 dropped = 0;
00848
00849 while ((bufneeded > TotalBuf(layers, buffer_)) &&
00850 (layers > 1)) {
00851 debug("** Primary DROPPED L%d, TotBuf(avail:%.1f \
00852 needed:%.1f), buf[%d]: %.2f\n",
00853 layers-1, TotalBuf(layers, buffer_), bufneeded,
00854 layers-1,buffer_[layers-1]);
00855 layers--;
00856 dropped++;
00857 sending_[layers] = 0;
00858 bufneeded = (MWM(srtt)*layers)+
00859 BufNeed(((layers)*LAYERBW_-rate),slope);
00860 }
00861 }
00862
00863
00864
00865 if ((bufneeded > TotalBuf(layers, buffer_)) && (layers == 1)) {
00866
00867 debug("** Not enough buf to keep the base layer, \
00868 TotBuf(avail:%.1f, needed:%.1f), \n",
00869 TotalBuf(layers, buffer_), bufneeded);
00870 }
00871
00872 if (layers == 0) {
00873
00874 sending_[0] = 1;
00875 playing_[0] = 0;
00876 if (updTimer_->status() != TIMER_IDLE)
00877 updTimer_->cancel();
00878 debug("** RESTART Phase, set playing_[0] to 0 to rebuffer data\n");
00879 return output(size, 0);
00880 }
00881
00882
00883 if (rate >= layers*LAYERBW_) {
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894 last_rate = rate;
00895 flag = 1;
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907 for (i=0;i<layers;i++) {
00908 if (buffer_[i] < MWM(srtt)) {
00909 if ((buffer_[i-1] <= buffer_[i]+seg_size_) &&
00910 (i > 0))
00911 idx = i-1;
00912 else
00913 idx = i;
00914
00915
00916 return output(size, idx);
00917 }
00918 }
00919
00920
00921
00922
00923
00924
00925 bs1 = 0;
00926 bs2 = 0;
00927 totbufs1 = 0;
00928 totbufs2 = 0;
00929 for (l=0; l<MAX_LAYER; l++) {
00930 optbufs1[l] = 0.0;
00931 optbufs2[l] = 0.0;
00932 }
00933
00934
00935
00936
00937
00938
00939
00940 while ((totbufs1 <= TotalBuf(layers, buffer_)) &&
00941 (bs1 <= MAXBKOFF_)) {
00942 totbufs1 = 0.0;
00943 bs1++;
00944 for (l=0; l<layers;l++) {
00945 optbufs1[l] = bufOptScen1(l,layers,rate,slope,
00946 bs1)+MWM(srtt);
00947 totbufs1 += optbufs1[l];
00948 }
00949 }
00950
00951
00952
00953
00954 while ((totbufs2 <= TotalBuf(layers, buffer_)) &&
00955 (bs2 <= MAXBKOFF_)) {
00956 totbufs2 = 0.0;
00957 bs2++;
00958 for (l=0; l<layers;l++) {
00959 optbufs2[l] = bufOptScen2(l,layers,rate,slope,
00960 bs2)+MWM(srtt);
00961 totbufs2 += optbufs2[l];
00962 }
00963 }
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983 if (bs2 >= MAXBKOFF_)
00984 debug("WARNING: MAX No of backoff Reached, bs1: %d, \
00985 bs2: %d\n", bs1, bs2);
00986
00987
00988
00989
00990 if ((bs1 > SMOOTHFACTOR_) && (bs2 > SMOOTHFACTOR_)){
00991
00992
00993
00994 assert(layers <= num_layer_);
00995
00996
00997
00998
00999
01000
01001
01002 if (layers == num_layer_){
01003 #if 0
01004 if (rate < num_layer_*LAYERBW_)
01005 panic("ERROR: rate: %.2f is less than \
01006 MAX BW for all %d layers!\n", rate, layers);
01007 #endif
01008
01009 rap()->FixIpg((double)seg_size_/
01010 (double)(num_layer_*LAYERBW_));
01011
01012 return output(size, layers - 1);
01013 }
01014
01015
01016 int off_start = (int)floor((poffset_ + MWM(srtt)) /
01017 seg_size_) * seg_size_;
01018
01019
01020
01021
01022
01023 if (data_[layers].start() <= off_start) {
01024
01025
01026
01027
01028 data_[layers].set_start(off_start);
01029 data_[layers].set_datasize(seg_size_);
01030 }
01031
01032
01033
01034
01035 if (data_[layers].end() > data_[layers-1].start())
01036
01037
01038
01039 return NULL;
01040
01041
01042 sending_[layers] = 1;
01043 AppData *res = output(size, layers);
01044 if (res == NULL) {
01045
01046
01047 sending_[layers] = 0;
01048
01049
01050 int st = (int)floor((data_[layers].start()+
01051 pref_srtt_*LAYERBW_)
01052 /seg_size_+0.5)*seg_size_;
01053 int et = (int)floor((data_[layers].end()+
01054 pref_srtt_*LAYERBW_)
01055 /seg_size_+0.5)*seg_size_;
01056 if (et > pref_[layers]) {
01057 pref_[i] = et;
01058 MediaSegment s(st, et);
01059 check_availability(i, s);
01060 }
01061 for (i = 0; i < layers; i++)
01062 if (buffer_[i] < MWM(srtt)) {
01063 res = output(size, i);
01064 if (res != NULL)
01065 break;
01066 }
01067 } else {
01068
01069 drained_[layers]= 0;
01070 debug("sending Just ADDED layer %d, t: %.2f\n",
01071 i, now);
01072 }
01073 return res;
01074 }
01075
01076
01077
01078
01079
01080
01081 scenario = 0;
01082 if((totbufs1 <= totbufs2) &&
01083 (totbufs1 > TotalBuf(layers, buffer_))) {
01084
01085 scenario = 1;
01086 } else {
01087
01088 scenario = 2;
01089 }
01090
01091
01092 if (scenario == 1) {
01093 for (l=0; l<layers; l++) {
01094 if (buffer_[l] >= optbufs1[l])
01095 continue;
01096
01097 if ((buffer_[l-1] <= buffer_[l]+seg_size_) &&
01098 (l > 0))
01099 idx = l-1;
01100 else
01101 idx = l;
01102
01103
01104 return output(size, idx);
01105 }
01106 } else if (scenario == 2) {
01107 l=0;
01108 done = 0;
01109 while ((l<layers) && (!done)){
01110 if (TotalBuf(layers, buffer_) >= totbufs2) {
01111 done ++;
01112 } else {
01113 if (buffer_[l]<min(optbufs2[l],
01114 optbufs1[l])) {
01115 if((buffer_[l-1] <= buffer_[l]+
01116 seg_size_) && (l>0))
01117 idx = l-1;
01118 else
01119 idx = l;
01120
01121
01122 return output(size, idx);
01123 }
01124 l++;
01125 }
01126 }
01127 } else
01128 panic("# ERROR: Unknown scenario: %d !!\n", scenario);
01129
01130
01131 if(scenario == 1){
01132 panic("# Should not reach here, totbuf: %.2f, \
01133 totbufs1: %.2f, layers: %d\n",
01134 TotalBuf(layers, buffer_), totbufs1, layers);
01135 }
01136
01137 if (scenario == 2) {
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150 l=0;
01151 while (l < layers) {
01152 if (buffer_[l] < optbufs2[l]) {
01153 if ((buffer_[l-1] <= buffer_[l]+
01154 seg_size_) && (l>0))
01155 idx = l-1;
01156 else
01157 idx = l;
01158
01159 return output(size, idx);
01160 }
01161 l++;
01162 }
01163 }
01164
01165 panic("# Opps, should not reach here, bs1: %d, bs2: %d, \
01166 scen: %d, totbufs1: %.2f, totbufs2: %.2f, totbufavail: %.2f\n",
01167 bs1, bs2, scenario, totbufs1,
01168 totbufs2, TotalBuf(layers, buffer_));
01169
01170
01171
01172 } else {
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194 double lowest=buffer_[0];
01195 int lowix=0;
01196 for(i=0;i<layers;i++) {
01197 if (lowest>buffer_[i]) {
01198 lowest=buffer_[i];
01199 lowix=i;
01200 }
01201 }
01202 if (lowest<MWM(srtt)) {
01203 last_depart = now;
01204
01205
01206 return output(size, lowix);
01207 }
01208
01209 if((nextAdjPoint < 0) ||
01210 (flag >= 0) ||
01211 (now >= nextAdjPoint) ||
01212 ((rate < last_rate) && (flag < 0)) ||
01213 (AllZero(tosend, layers))) {
01214
01215
01216
01217
01218
01219
01220 nextAdjPoint = now + srtt;
01221 bufToDrain = LAYERBW_*layers - rate;
01222
01223
01224
01225
01226
01227 if (bufToDrain <= 0)
01228 panic("# ERROR: bufToDrain: %.2f\n",
01229 bufToDrain);
01230
01231 DrainPacket(bufToDrain, FinalDrainArray, layers, rate,
01232 srtt, FinalBuffer);
01233
01234 for(l=0; l<MAX_LAYER; l++){
01235 tosend[l] = 0;
01236 }
01237
01238 for(l=0; l<layers; l++){
01239 tosend[l] = srtt*LAYERBW_ - FinalDrainArray[l];
01240
01241 if (fabs(tosend[l]) < QA_EPSILON)
01242 tosend[l] = 0.0;
01243 }
01244
01245
01246
01247
01248
01249 tosendPtr = 0;
01250
01251
01252 if ((bufToDrain <= 0) ||
01253 AllZero(FinalDrainArray, layers) ||
01254 AllZero(tosend, layers)) {
01255 debug("# Error: bufToDrain: %.2f, %d layers, "
01256 "srtt: %.2f\n",
01257 bufToDrain, layers, srtt);
01258 for (l=0; l<layers; l++)
01259 debug("# FinalDrainArray[%d]: %.2f, "
01260 "tosend[%d]: %.2f\n", l,
01261 FinalDrainArray[l],l, tosend[l]);
01262 }
01263
01264 }
01265
01266 flag = -1;
01267 last_rate = rate;
01268 done = 0;
01269 cnt = 1;
01270 while ((!done) && (cnt <= layers)) {
01271 if (tosend[tosendPtr] > 0) {
01272 if ((buffer_[tosendPtr-1] <= buffer_[tosendPtr]
01273 + seg_size_) && (tosendPtr > 0))
01274 idx = tosendPtr-1;
01275 else
01276 idx = tosendPtr;
01277 tosend[tosendPtr] -= seg_size_;
01278 if (tosend[tosendPtr] < 0)
01279 tosend[tosendPtr] = 0;
01280 return output(size, idx);
01281 }
01282 cnt++;
01283 tosendPtr = (tosendPtr+1) % layers;
01284 }
01285
01286
01287
01288 return output(size, 0);
01289 }
01290
01291 panic("# QA::get_data() reached the end. \n");
01292
01293 return NULL;
01294 }
01295
01296
01297
01298
01299
01300
01301
01302 int QA::AllZero(double *arr, int len)
01303 {
01304 int i;
01305
01306 for (i=0; i<len; i++)
01307 if (arr[i] != 0.0)
01308
01309 return 0;
01310 return 1;
01311 }
01312
01313
01314
01315
01316
01317 double QA::TotalBuf(int n, double *buffer)
01318 {
01319 double totbuf = 0.0;
01320 int i;
01321
01322 for(i=0; i<n; i++)
01323 totbuf += buffer[i];
01324 return totbuf;
01325 }
01326
01327
01328
01329 AppData* QA::output(int& size, int layer)
01330 {
01331 int i;
01332 assert((sending_[layer] == 1) || (startTime_ == -1));
01333
01334
01335
01336 if (layer > 0)
01337 if (data_[layer-1].start() <= data_[layer].start())
01338 return output(size, layer-1);
01339
01340
01341 MediaRequest q(MEDIAREQ_GETSEG);
01342 q.set_name(page_);
01343 q.set_layer(layer);
01344 q.set_st(data_[layer].start());
01345 q.set_datasize(seg_size_);
01346 q.set_app(this);
01347 AppData* res = target()->get_data(size, &q);
01348
01349 assert(res != NULL);
01350 HttpMediaData *p = (HttpMediaData *)res;
01351
01352 if (p->datasize() <= 0) {
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363 if (p->is_finished()) {
01364 rap()->stop();
01365
01366 Tcl::instance().evalf("%s finish-stream %s",
01367 target()->name(), name());
01368 } else if (!p->is_last()) {
01369
01370
01371 MediaSegment tmp(q.et(), q.et()+seg_size_);
01372 check_layers(p->layer(), tmp);
01373
01374
01375 if (tmp.datasize() > 0) {
01376 assert(tmp.datasize() <= seg_size_);
01377 data_[p->layer()].set_start(tmp.start());
01378 data_[p->layer()].set_end(tmp.end());
01379 }
01380 }
01381 delete p;
01382 return NULL;
01383 }
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396 assert((p->datasize() > 0) && (p->datasize() <= seg_size_));
01397
01398
01399
01400 MediaSegment tmp(p->et(), p->et()+seg_size_);
01401 check_layers(p->layer(), tmp);
01402 if (tmp.datasize() > 0) {
01403 assert(tmp.datasize() <= seg_size_);
01404 data_[p->layer()].set_start(tmp.start());
01405 data_[p->layer()].set_end(tmp.end());
01406 } else {
01407
01408
01409
01410 fprintf(stderr, "# ERROR We cannot advance pointers for "
01411 "segment (%d %d)\n", tmp.start(), tmp.end());
01412 for (i = 0; i < layer; i++)
01413 fprintf(stderr, "Layer %d, data ptr (%d %d) \n",
01414 i, data_[i].start(), data_[i].end());
01415 delete p;
01416 return NULL;
01417 }
01418
01419
01420
01421 outlist_[p->layer()].add(MediaSegment(p->st(), p->et()));
01422
01423 buffer_[layer] += p->datasize();
01424 bw_[layer] += p->datasize();
01425 drained_[layer] -= p->datasize();
01426
01427
01428 avgrate_ = rate_weight_*rate() + (1-rate_weight_)*avgrate_;
01429
01430
01431 for (i = 0; i < layer-1; i++)
01432 if (data_[i].end() < data_[i+1].end()) {
01433 for (int j = 0; j < layer; j++)
01434 fprintf(stderr, "layer i: (%d %d)\n",
01435 data_[i].start(), data_[i].end());
01436 panic("# ERROR Wrong layer sending order!!\n");
01437 }
01438
01439 return res;
01440 }
01441
01442 void QA::check_layers(int layer, MediaSegment& tmp) {
01443
01444
01445 for (int i = layer-1; i >= 0; i--)
01446
01447 if (tmp.end() > data_[i].end())
01448 tmp.set_end(data_[i].end());
01449 }
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461 double QA::bufOptScen1(int layer, int layers, double currrate,
01462 double slope, int backoffs)
01463 {
01464 double smallt, larget, side, rate;
01465
01466 if (backoffs < 0) {
01467 panic("# ERROR: backoff: %d in bufOptScen1\n",
01468 backoffs);
01469 }
01470 rate = currrate/pow(2,backoffs);
01471 side = LAYERBW_*layers - (rate + layer*LAYERBW_);
01472 if (side <= 0.0)
01473 return(0.0);
01474 larget = BufNeed(side, slope);
01475 side = LAYERBW_*layers - (rate + (layer+1)*LAYERBW_);
01476 if (side < 0.0)
01477 side = 0.0;
01478 smallt = BufNeed(side, slope);
01479
01480 return (larget-smallt);
01481 }
01482
01483
01484
01485
01486
01487
01488
01489
01490 double QA::bufOptScen2(int layer, int layers, double currrate,
01491 double slope, int backoffs)
01492 {
01493 double bufopt = 0.0;
01494 int bmin, done;
01495
01496 if(backoffs < 0) {
01497 panic("# ERROR: backoff: %d in bufOptScen2\n",
01498 backoffs);
01499 }
01500 if ((currrate/pow(2,backoffs)) >= layers*LAYERBW_)
01501 return(0.0);
01502
01503 bmin = 0;
01504 done = 0;
01505 while ((!done) && bmin<=backoffs) {
01506 if(currrate/pow(2,bmin) >= LAYERBW_*layers)
01507 bmin++;
01508 else
01509 done++;
01510 }
01511
01512
01513 bufopt = bufOptScen1(layer, layers, currrate/pow(2,bmin), slope, 0);
01514
01515
01516 bufopt += (backoffs - bmin)*BufNeed(layers*LAYERBW_/2, slope);
01517 return(bufopt);
01518 }
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532 void QA::drain_buf(double* DrainArr, double bufToDrain,
01533 double* FinalDrainArray, double* bufAvail,
01534 int layers, double rate, double srtt)
01535 {
01536 double bufReq1, bufReq2, bufs1[MAX_LAYER], bufs2[MAX_LAYER], slope,
01537 extra, targetArr[MAX_LAYER], maxDrainRemain;
01538 int bs1, bs2, l;
01539
01540 slope = seg_size_/srtt;
01541 bs1 = MAXBKOFF_ + 1;
01542 bs2 = MAXBKOFF_ + 1;
01543 bufReq1 = bufReq2 = 0;
01544 for(l=0; l<layers; l++){
01545 bufReq1 += bufOptScen1(l, layers, rate, slope, bs1);
01546 bufReq2 += bufOptScen2(l, layers, rate, slope, bs2);
01547 }
01548
01549 for(l=0; l<MAX_LAYER; l++){
01550 bufs1[l] = 0;
01551 bufs2[l] = 0;
01552 DrainArr[l] = 0.0;
01553 }
01554
01555 while(bufReq1 > TotalBuf(layers, bufAvail)){
01556 bufReq1 = 0;
01557 bs1--;
01558 for(l=0; l<layers; l++){
01559 bufs1[l] = bufOptScen1(l, layers, rate, slope, bs1);
01560 bufReq1 += bufs1[l];
01561 }
01562 }
01563
01564 while(bufReq2 > TotalBuf(layers, bufAvail)){
01565 bufReq2 = 0;
01566 bs2--;
01567 for(l=0; l<layers; l++){
01568 bufs2[l] = bufOptScen2(l, layers, rate, slope, bs2);
01569 bufReq2 += bufs2[l];
01570 }
01571 }
01572
01573 if (bufReq1 >= bufReq2) {
01574
01575 for (l=layers-1; l>=0; l--){
01576
01577
01578
01579
01580 maxDrainRemain = srtt*LAYERBW_ - FinalDrainArray[l];
01581 if ((bufAvail[l] > bufs1[l] + maxDrainRemain) &&
01582 (bufToDrain >= maxDrainRemain)) {
01583 DrainArr[l] = maxDrainRemain;
01584 bufToDrain -= maxDrainRemain;
01585 } else {
01586 if(bufAvail[l] > bufs1[l] + maxDrainRemain){
01587 DrainArr[l] = bufToDrain;
01588 bufToDrain = 0.0;
01589 } else {
01590 DrainArr[l] = bufAvail[l] - bufs1[l];
01591 bufToDrain -= bufAvail[l] - bufs1[l];
01592
01593
01594 if(DrainArr[l] < 0.0){
01595
01596
01597 DrainArr[l] = 0.0;
01598 }
01599 }
01600 }
01601 if(bufToDrain == 0.0)
01602 return;
01603 }
01604 return;
01605 } else {
01606
01607
01608
01609
01610
01611
01612 extra = 0.0;
01613
01614 for (l=0; l<layers; l++) {
01615 if(bufs1[l] > bufs2[l])
01616 extra += bufs1[l] - bufs2[l];
01617 }
01618
01619 for (l=layers-1; l>=0; l--)
01620 if(bufs1[l] >= bufs2[l])
01621 targetArr[l] = bufs1[l];
01622 else
01623 if (bufs2[l] - bufs1[l] >= extra) {
01624 targetArr[l] = bufs2[l] - extra;
01625 extra = 0;
01626 } else {
01627
01628 if (extra > 0) {
01629 targetArr[l] = bufs2[l];
01630 extra -= bufs2[l] - bufs1[l];
01631 } else
01632 panic("# ERROR Should not \
01633 reach here, extra: %.2f, bufs2: %.2f, bufs1: %.2f, L%d\n",
01634 extra, bufs2[l], bufs1[l], l);
01635 }
01636 }
01637
01638
01639 for (l=layers-1; l>=0; l--) {
01640
01641
01642
01643
01644 maxDrainRemain = srtt*LAYERBW_ - FinalDrainArray[l];
01645 if ((bufAvail[l] > targetArr[l] + maxDrainRemain) &&
01646 (bufToDrain >= maxDrainRemain)) {
01647 DrainArr[l] = maxDrainRemain;
01648 bufToDrain -= maxDrainRemain;
01649 } else {
01650 if(bufAvail[l] > targetArr[l] + maxDrainRemain){
01651 DrainArr[l] = bufToDrain;
01652 bufToDrain = 0.0;
01653 } else {
01654 DrainArr[l] = bufAvail[l] - targetArr[l];
01655 bufToDrain -= bufAvail[l] - targetArr[l];
01656
01657
01658 if (DrainArr[l] < 0.0) {
01659
01660
01661 DrainArr[l] = 0;
01662 }
01663 }
01664 }
01665 if (bufToDrain == 0.0)
01666 return;
01667 }
01668 return;
01669 }
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681 void QA::DrainPacket(double bufToDrain, double* FinalDrainArray, int layers,
01682 double rate, double srtt, double* FinalBuffer)
01683 {
01684 double DrainArr[MAX_LAYER], bufAvail[MAX_LAYER], TotBufAvail;
01685 int l,cnt;
01686
01687 for(l=0; l<MAX_LAYER; l++){
01688 FinalDrainArray[l] = 0.0;
01689 bufAvail[l] = buffer_[l];
01690 }
01691
01692 TotBufAvail = TotalBuf(layers, bufAvail);
01693 cnt = 0;
01694 while ((bufToDrain > 0) && (cnt < 10)) {
01695
01696 drain_buf(DrainArr, bufToDrain, FinalDrainArray, bufAvail,
01697 layers, rate, srtt);
01698
01699 for(l=0; l<layers; l++){
01700 bufToDrain -= DrainArr[l];
01701 TotBufAvail -= DrainArr[l];
01702 FinalDrainArray[l] += DrainArr[l];
01703 bufAvail[l] -= DrainArr[l];
01704 FinalBuffer[l] = buffer_[l] - FinalDrainArray[l];
01705 }
01706 cnt++;
01707 }
01708 }
01709
01710 void QA::check_availability(int layer, const MediaSegment& s)
01711 {
01712 int dummy;
01713 MediaRequest p(MEDIAREQ_CHECKSEG);
01714 p.set_name(page_);
01715 p.set_layer(layer);
01716 p.set_st(s.start());
01717 p.set_et(s.end());
01718 p.set_app(this);
01719
01720 target()->get_data(dummy, &p);
01721 }
01722
01723
01724
01725
01726
01727 void QA::DrainBuffers()
01728 {
01729 int i, j, layers = 0;
01730 Scheduler& s = Scheduler::instance();
01731 double now = s.clock();
01732
01733 double interval = now - playTime_;
01734 playTime_ = now;
01735
01736 if ((layers > 1) && (playing_[0] != 1)) {
01737 panic("ERROR in DrainBuffer: layers>0 but L0 isn't playing\n");
01738 }
01739
01740
01741
01742
01743
01744
01745
01746 int todrain[MAX_LAYER];
01747
01748
01749
01750 poffset_ += (int)floor(interval*LAYERBW_+0.5);
01751
01752
01753 for (i = MAX_LAYER-1; i >= 0; i--) {
01754
01755 if (sending_[i] == 0) {
01756 todrain[i] = 0;
01757 drained_[i] = 0.0;
01758 continue;
01759 }
01760 todrain[i] = outlist_[i].evict_head_offset(poffset_);
01761 assert(todrain[i] >= 0);
01762 buffer_[i] -= todrain[i];
01763
01764 if ((int)buffer_[i] <= 0) {
01765 debug("Buffer %d ran dry: %.2f after draining, DROP\n",
01766 i, buffer_[i]);
01767 playing_[i] = 0;
01768 sending_[i] = 0;
01769 buffer_[i] = 0;
01770
01771
01772 for (j = i+1; j < MAX_LAYER; j++)
01773 if (sending_[j] == 1) {
01774
01775
01776
01777
01778
01779 debug("# DROP layer %d: it \
01780 is playing with %.2f buf but layer %d ran dry with %.2f buf\n",
01781 j, buffer_[j], i, buffer_[i]);
01782 sending_[j] = 0;
01783 playing_[j] = 0;
01784 buffer_[j] = 0;
01785 }
01786
01787
01788
01789
01790
01791
01792 } else {
01793
01794 int st = (int)floor((poffset_+pref_srtt_*LAYERBW_)
01795 /seg_size_+0.5)*seg_size_;
01796 int et = (int)floor((poffset_+(pref_srtt_+interval)*
01797 LAYERBW_)/seg_size_+0.5)*seg_size_;
01798 if (et > pref_[i]) {
01799 pref_[i] = et;
01800 MediaSegment s(st, et);
01801 check_availability(i, s);
01802 }
01803 }
01804 }
01805 }
01806
01807
01808
01809
01810
01811
01812
01813
01814 void QA::DumpInfo(double t, double last_t, double rate,
01815 double avgrate, double srtt)
01816 {
01817 #define MAXLEN 2000
01818 int i,j;
01819 char s1[MAXLEN], s2[MAXLEN], tmp[MAXLEN];
01820 static double last_srtt = 0, t1,t2 = 0;
01821 #undef MAXLEN
01822
01823 double tot_bw = 0.0, interval, diff;
01824
01825
01826
01827
01828 interval = t - last_t ;
01829
01830 if((t2 != last_t) && (t2 > 0)){
01831 diff = interval - last_srtt;
01832 if ((diff > 0.001) || (diff < -0.001)) {
01833 if (last_t == 0)
01834
01835 return;
01836
01837
01838
01839
01840
01841
01842 }
01843 } else
01844
01845 last_srtt = srtt;
01846
01847 t1 = last_t;
01848 t2 = t;
01849
01850 if (interval <= 0.0) {
01851 panic("# ERROR interval is negative\n");
01852 }
01853
01854 sprintf(s1, " %.2f %.2f %.2f X", last_t, rate, avgrate);
01855 sprintf(s2, " %.2f %.2f %.2f X", t, rate, avgrate);
01856
01857 j = 0;
01858 for (i = 0; i < MAX_LAYER; i++)
01859
01860 if (sending_[i] == 1)
01861 j++;
01862
01863 sprintf(tmp, " %d", j*LAYERBW_);
01864 strcat(s1, tmp);
01865 strcat(s2, tmp);
01866
01867 for (i = 0; i < MAX_LAYER; i++) {
01868 sprintf(tmp, " %.2g ", (bw_[i]/interval)+i*10000.0);
01869 strcat(s1,tmp);
01870 strcat(s2,tmp);
01871
01872 tot_bw += bw_[i]/interval;
01873 bw_[i] = 0;
01874 }
01875
01876 sprintf(tmp, " %.2f X", tot_bw );
01877 strcat(s1,tmp);
01878 strcat(s2,tmp);
01879
01880 j = 0;
01881 for (i = 0; i < MAX_LAYER; i++) {
01882
01883 if(sending_[i] ==1){
01884 j++;
01885
01886
01887 if (drained_[i] < 0.0) {
01888
01889
01890 drained_[i] = 0.0;
01891 }
01892
01893
01894 sprintf(tmp, " %.2f ",
01895 (drained_[i]/interval)+i*10000.0);
01896 strcat(s1,tmp);
01897 strcat(s2,tmp);
01898
01899
01900
01901
01902 drained_[i]=srtt*LAYERBW_;
01903 } else {
01904 sprintf(tmp, " %.2f ", i*10000.0);
01905 strcat(s1,tmp);
01906 strcat(s2,tmp);
01907 drained_[i] = 0.0;
01908 }
01909 }
01910
01911 for (i=0;i<MAX_LAYER;i++) {
01912 sprintf(tmp, " %.2f", buffer_[i]+i*10000);
01913 strcat(s1,tmp);
01914 strcat(s2,tmp);
01915 }
01916
01917 log("QA %s \n", s1);
01918 log("QA %s \n", s2);
01919 fflush(stdout);
01920 }
01921
01922
01923
01924
01925
01926 void QA::UpdateState()
01927 {
01928 double last_ptime = playTime_;
01929 DrainBuffers();
01930 DumpInfo(Scheduler::instance().clock(), last_ptime,
01931 rate(), avgrate_, rap()->srtt());
01932 }
01933
01934