• Main Page
  • Classes
  • Files
  • File List

/Users/yzchen/ns/ns-allinone-2.33/ns-2.33/rap/media-app.h

00001 /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
00002 
00003 /*
00004  * media-app.h
00005  * Copyright (C) 1997 by the University of Southern California
00006  * $Id: media-app.h,v 1.12 2005/08/25 18:58:10 johnh Exp $
00007  *
00008  * This program is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU General Public License,
00010  * version 2, as published by the Free Software Foundation.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License along
00018  * with this program; if not, write to the Free Software Foundation, Inc.,
00019  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00020  *
00021  *
00022  * The copyright of this module includes the following
00023  * linking-with-specific-other-licenses addition:
00024  *
00025  * In addition, as a special exception, the copyright holders of
00026  * this module give you permission to combine (via static or
00027  * dynamic linking) this module with free software programs or
00028  * libraries that are released under the GNU LGPL and with code
00029  * included in the standard release of ns-2 under the Apache 2.0
00030  * license or under otherwise-compatible licenses with advertising
00031  * requirements (or modified versions of such code, with unchanged
00032  * license).  You may copy and distribute such a system following the
00033  * terms of the GNU GPL for this module and the licenses of the
00034  * other code concerned, provided that you include the source code of
00035  * that other code when and as the GNU GPL requires distribution of
00036  * source code.
00037  *
00038  * Note that people who make modified versions of this module
00039  * are not obligated to grant this special exception for their
00040  * modified versions; it is their choice whether to do so.  The GNU
00041  * General Public License gives permission to release a modified
00042  * version without this exception; this exception also makes it
00043  * possible to release a modified version which carries forward this
00044  * exception.
00045  *
00046  */
00047 
00048 //
00049 // Media applications: wrappers of transport agents for multimedia objects
00050 // 
00051 // Their tasks are to receive 'data' from underlying transport agents, 
00052 // and to notify "above" applications that such data has arrived. 
00053 //
00054 // When required (by RapAgent), it also provides callbacks to the 
00055 // transport agent, and contact the above application on behalf of the 
00056 // transport agent.
00057 //
00058 // $Header: /cvsroot/nsnam/ns-2/rap/media-app.h,v 1.12 2005/08/25 18:58:10 johnh Exp $
00059 
00060 #ifndef ns_media_app_h
00061 #define ns_media_app_h
00062 
00063 #include <stdlib.h>
00064 #include <tcl.h>
00065 #include "config.h"
00066 #include "agent.h"
00067 #include "app.h"
00068 #include "webcache/http-aux.h"
00069 #include "rap/rap.h"
00070 #include "rap/utilities.h"
00071 
00072 
00073 class HttpMediaData;
00074 
00075 // Fixed length segment in a multimedia stream
00076 class MediaSegment : public DoubleListElem {
00077 public: 
00078         MediaSegment() : start_(0), end_(0), flags_(0) {}
00079         MediaSegment(int start, int end) : start_(start),end_(end),flags_(0) {}
00080         MediaSegment(const HttpMediaData& d);
00081         MediaSegment(const MediaSegment& s) {
00082                 // XXX Don't copy pointers (prev_,next_)?
00083                 start_ = s.start_;
00084                 end_ = s.end_;
00085                 flags_ = s.flags_;
00086         }
00087 
00088         int start() const { return start_; }
00089         int end() const { return end_; }
00090         int datasize() const { return end_ - start_; }
00091         MediaSegment* next() const { 
00092                 return (MediaSegment *)DoubleListElem::next(); 
00093         }
00094         MediaSegment* prev() const { 
00095                 return (MediaSegment *)DoubleListElem::prev(); 
00096         }
00097 
00098         void set_start(int d) { start_ = d; }
00099         void set_end(int d) { end_ = d; }
00100         void set_datasize(int d) { end_ = start_ + d; }
00101         // Advance the segment by size
00102         void advance(int size) { start_ += size, end_ = start_ + size; }
00103 
00104         int in(const MediaSegment& s) const {
00105                 return ((start_ >= s.start_) && (end_ <= s.end_));
00106         }
00107         int before(const MediaSegment& s) const {
00108                 return (end_ <= s.start_);
00109         }
00110         int overlap(const MediaSegment& s) const {
00111                 assert(s.start_ <= s.end_);
00112                 return ((s.end_ >= start_) && (s.start_ <= end_));
00113         }
00114         // Return the overlapping size between the two
00115         int merge(const MediaSegment& s) {
00116                 if ((s.end_ < start_) || (s.start_ > end_))
00117                         // No overlap
00118                         return 0;
00119                 int size = datasize() + s.datasize();
00120                 if (s.start_ < start_) start_ = s.start_;
00121                 if (s.end_ > end_) end_ = s.end_;
00122                 assert(size >= datasize());
00123                 return (size - datasize());
00124         }
00125         // Return the amount of data evicted
00126         int evict_tail(int sz) {
00127                 // Adjust both the size and playout time
00128 #ifdef MCACHE_DEBUG
00129                 fprintf(stderr, "evicted (%d, %d) ", end_-sz, end_);
00130 #endif
00131                 if (datasize() >= sz) 
00132                         end_ -= sz;
00133                 else {
00134                         sz = datasize();
00135                         end_ = start_;
00136                 }
00137                 return sz;
00138         }
00139         // Return the amount of data evicted
00140         int evict_head(int sz) {
00141                 // Adjust both the size and playout time
00142                 if (datasize() >= sz) 
00143                         start_ += sz;
00144                 else {
00145                         sz = datasize();
00146                         end_ = start_;
00147                 }
00148                 return sz;
00149         }
00150         int is_empty() const { return end_ == start_; }
00151 
00152         // Whether this is the last segment of the available data
00153         enum { MS_LAST = 1, MS_PREF = 2 };
00154         int is_last() const { return (flags_ & MS_LAST); }
00155         void set_last() { flags_ |= MS_LAST; }
00156         int is_pref() const { return (flags_ & MS_PREF); }
00157         void set_pref() { flags_ |= MS_PREF; }
00158 
00159 private: 
00160         int start_;
00161         int end_;
00162         int flags_;
00163 };
00164 
00165 // Maintains received segments of every layer
00166 class MediaSegmentList : public DoubleList {
00167 public:
00168         MediaSegmentList() : DoubleList(), length_(0) {}
00169 
00170         int length() const { return length_; }
00171         void add(const MediaSegment& s);
00172         int in(const MediaSegment& s);
00173         MediaSegment get_nextseg(const MediaSegment& s);
00174         int evict_tail(int size);
00175         int evict_head(int size);
00176         int evict_head_offset(int offset);
00177         int overlap_size(const MediaSegment& s) const;
00178         MediaSegmentList check_holes(const MediaSegment& s);
00179 
00180         char* dump2buf();
00181         virtual void destroy() {
00182                 DoubleList::destroy();
00183                 length_ = 0;
00184         }
00185 
00186         // Debug only
00187         void print(void);
00188         int getsize();
00189         void check_integrity();
00190 
00191 protected:
00192         void merge_seg(MediaSegment* seg);
00193 
00194 private:
00195         int length_;
00196 };
00197 
00198 
00199 // Represents a multimedia segment transmitted through the network
00200 class HttpMediaData : public HttpData {
00201 private:
00202         char page_[HTTP_MAXURLLEN];     // Page ID
00203         char sender_[HTTP_MAXURLLEN];   // Sender name
00204         int layer_;                     // Layer id. 0 if no layered encoding
00205         int st_;                        // Segment start time
00206         int et_;                        // Segment end time
00207         int flags_;                     // flags: end of all data, etc.
00208         Application* conid_;            // Connection ID. Used for statistics
00209 public:
00210         struct hdr {
00211                 char sender_[HTTP_MAXURLLEN];
00212                 char page_[HTTP_MAXURLLEN];
00213                 int layer_;
00214                 int st_, et_;
00215                 int flags_;
00216         };
00217 
00218 public:
00219         HttpMediaData(const char* sender, const char* name, int layer, 
00220                       int st, int et);
00221         HttpMediaData(HttpMediaData& d) : HttpData(d) {
00222                 layer_ = d.layer_;
00223                 st_ = d.st_;
00224                 et_ = d.et_;
00225                 flags_ = d.flags_;
00226                 strcpy(page_, d.page_);
00227                 strcpy(sender_, d.sender_);
00228         }
00229 
00230         virtual int size() const { return HttpData::size() + sizeof(hdr); }
00231         virtual AppData* copy() { return (new HttpMediaData(*this)); }
00232 
00233         int st() const { return st_; }
00234         int et() const { return et_; }
00235         int datasize() const { return et_ - st_; }
00236         int layer() const { return layer_; }
00237         const char* page() const { return page_; }
00238         const char* sender() const { return sender_; }
00239 
00240         Application* conid() { return conid_; }
00241         void set_conid(Application* c) { conid_ = c; }
00242 
00243         // flags
00244         // MD_LAST: last segment of this layre
00245         // MD_FINISH: completed the entire stream
00246         enum {
00247                 MD_LAST = 1, 
00248                 MD_FINISH = 2,
00249                 MD_PREFETCH = 4
00250         }; 
00251 
00252         // Whether this is the last data segment of the layer
00253         int is_last() const { return (flags_ & MD_LAST); }
00254         void set_last() { flags_ |= MD_LAST; }
00255         int is_finished() const { return (flags_ & MD_FINISH); }
00256         void set_finish() { flags_ |= MD_FINISH; }
00257         int is_pref() const { return (flags_ & MD_PREFETCH); }
00258         void set_pref() { flags_ |= MD_PREFETCH; }
00259 };
00260 
00261 
00262 const int MEDIAREQ_GETSEG       = 1;
00263 const int MEDIAREQ_CHECKSEG     = 2;
00264 
00265 const int MEDIAREQ_SEGAVAIL     = 3;
00266 const int MEDIAREQ_SEGUNAVAIL   = 4;
00267 
00268 // It provides a MediaApp two types of requests: check data availability and 
00269 // request data. It won't be sent in a packet so we don't need copy(). 
00270 class MediaRequest : public AppData {
00271 private:
00272         int request_;                   // Request code
00273         char name_[HTTP_MAXURLLEN];     // Page URL
00274         int layer_;                     // Layer ID
00275         u_int st_;                      // Start playout time
00276         u_int et_;                      // End playout time
00277         Application* app_;              // Calling application
00278 public:
00279         MediaRequest(int rc) : AppData(MEDIA_REQUEST), request_(rc) {}
00280         MediaRequest(const MediaRequest& r) : AppData(MEDIA_REQUEST) {
00281                 request_ = r.request();
00282                 st_ = r.st();
00283                 et_ = r.et();
00284                 layer_ = r.layer();
00285                 strcpy(name_, r.name());
00286         }
00287         // We don't need it, but have to declare.
00288         virtual AppData* copy() { abort(); return NULL; }
00289 
00290         int request() const { return request_; }
00291         int st() const { return st_; }
00292         int et() const { return et_; }
00293         int datasize() const { return et_ - st_; }
00294         int layer() const { return layer_; }
00295         const char* name() const { return name_; }
00296         Application* app() const { return app_; }
00297 
00298         // These functions allow the caller to fill in only the 
00299         // necessary fields
00300         void set_st(int d) { st_ = d; }
00301         void set_et(int d) { et_ = d; }
00302         void set_datasize(int d) { et_ = st_ + d; }
00303         void set_name(const char *s) { strcpy(name_, s); }
00304         void set_layer(int d) { layer_ = d; }
00305         void set_app(Application* a) { app_ = a; }
00306 };
00307 
00308 
00309 
00310 // Maximum number of layers for all streams in the simulation
00311 const int MAX_LAYER = 10;
00312 
00313 // XXX A media app is only responsible for transmission of a single 
00314 // media stream!! Once the transmission is done, the media app will be 
00315 // deleted.
00316 class MediaApp : public Application {
00317 public:
00318         MediaApp(const char* page);
00319 
00320         virtual AppData* get_data(int& size, AppData* req_data = 0);
00321         virtual void process_data(int size, AppData* data) {
00322                 send_data(size, data);
00323         }
00324         void set_page(const char* pg) { strcpy(page_, pg); }
00325 
00326         void log(const char* fmt, ...);
00327         int command(int argc, const char*const* argv);
00328 
00329 protected:
00330         virtual void start();
00331         virtual void stop();
00332 
00333         // Helper function
00334         RapAgent* rap() { return (RapAgent*)agent_; }
00335 
00336         int seg_size_;                  // data segment size
00337         char page_[HTTP_MAXURLLEN];
00338         MediaSegment data_[MAX_LAYER];  // Pointer to next data to be sent
00339         Tcl_Channel log_;               // log file
00340 
00341         // XXX assuming all streams in the simulation have the same
00342         // number of layers.
00343         int num_layer_;
00344 private:
00345         int last_layer_;
00346 };
00347 
00348 
00349 
00350 class QA; 
00351 
00352 class QATimer : public TimerHandler {
00353 public:
00354         QATimer(QA *a) : TimerHandler() { a_ = a; }
00355 protected:
00356         virtual void expire(Event *e);
00357         QA *a_;
00358 };
00359 
00360 const double QA_EPSILON = 1e-6;
00361 
00362 class QA : public MediaApp { 
00363 public:
00364         QA(const char *page);
00365         virtual ~QA();
00366 
00367         virtual AppData* get_data(int& size, AppData* req_data = 0);
00368         void UpdateState();
00369         double UpdateInterval() { return rap()->srtt(); } 
00370 
00371 protected:
00372         virtual int command(int argc, const char*const* argv);
00373         virtual void stop();
00374 
00375         // Helper functions
00376         void check_availability(int layer, const MediaSegment& s);
00377         RapAgent* rap() { return (RapAgent*)agent_; }
00378 
00379         // Misc helpers
00380         inline double MWM(double srtt) {
00381                 return 2 * LAYERBW_ * srtt;
00382         }
00383         inline double rate() { 
00384                 return (double)seg_size_ / rap()->ipg();
00385         }
00386 
00387         // Calculate area of a triangle for a given side and slope
00388         inline double BufNeed(double side, double slope) {
00389                 return (side <= 0) ? 0.0 : ((side*side) / (2.0*slope));
00390         }
00391         int AllZero(double *arr, int len);
00392         double TotalBuf(int n, double *buffer);
00393         AppData* output(int& size, int layer);
00394         void DumpInfo(double t, double last_t, double rate, 
00395                       double avgrate, double srtt);
00396         double bufOptScen1(int layer, int layers, double currrate, 
00397                            double slope, int backoffs);
00398         double bufOptScen2(int layer, int layers, double currrate, 
00399                            double slope, int backoffs);
00400         void drain_buf(double* DrainArr, double bufToDrain, 
00401                        double* FinalDrainArray, double* bufAvail, 
00402                        int layers, double rate, double srtt);
00403         void DrainPacket(double bufToDrain, double* FinalDrainArray, 
00404                          int layers, double rate, double srtt, 
00405                          double* FinalBuffer);
00406 
00407         // Ack feedback information
00408         void DrainBuffers();
00409 
00410         // Debugging output
00411         void debug(const char* fmt, ...);
00412         void panic(const char* fmt, ...);
00413         void check_layers(int layer, MediaSegment& tmp);
00414 
00415         // Data members
00416         int layer_;
00417         double    playTime_; // playout time of the receiver
00418         double    startTime_; // Absoloute time when playout started
00419 
00420         // Internal state info for QA
00421         double   buffer_[MAX_LAYER];
00422         double   drained_[MAX_LAYER]; 
00423         double   bw_[MAX_LAYER];
00424         int      playing_[MAX_LAYER]; 
00425         int      sending_[MAX_LAYER];
00426         QATimer* updTimer_;
00427 
00428         // Average transmission rate and its moving average weight
00429         // Measured whenever a segment is sent out (XXX why??)
00430         double   avgrate_; 
00431         double   rate_weight_;
00432 
00433         // Variables related to playout buffer management
00434         int      poffset_;  /* The playout offset: estimation of client 
00435                                playout time */
00436         // Linked list keeping track of holes between poffset_ and current
00437         // transmission pointer
00438         MediaSegmentList outlist_[MAX_LAYER];
00439         // The end offset of the prefetch requests. Used to avoid redundant
00440         // prefetching requests
00441         int pref_[MAX_LAYER];
00442 
00443         // OTcl-bound variables
00444         int debug_;             // Turn on/off debug output
00445         double pref_srtt_;      // Prefetching SRTT
00446         int LAYERBW_;
00447         int MAXACTIVELAYERS_;
00448         double SRTTWEIGHT_;
00449         int SMOOTHFACTOR_;
00450         int MAXBKOFF_;
00451 }; 
00452 
00453 #endif // ns_media_app_h

Generated on Tue Aug 10 2010 16:16:08 for ns-2.33 by  doxygen 1.7.1