media-app.h
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:13k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
  2. /*
  3.  * media-app.h
  4.  * Copyright (C) 1997 by the University of Southern California
  5.  * $Id: media-app.h,v 1.12 2005/08/25 18:58:10 johnh Exp $
  6.  *
  7.  * This program is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU General Public License,
  9.  * version 2, as published by the Free Software Foundation.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License along
  17.  * with this program; if not, write to the Free Software Foundation, Inc.,
  18.  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  19.  *
  20.  *
  21.  * The copyright of this module includes the following
  22.  * linking-with-specific-other-licenses addition:
  23.  *
  24.  * In addition, as a special exception, the copyright holders of
  25.  * this module give you permission to combine (via static or
  26.  * dynamic linking) this module with free software programs or
  27.  * libraries that are released under the GNU LGPL and with code
  28.  * included in the standard release of ns-2 under the Apache 2.0
  29.  * license or under otherwise-compatible licenses with advertising
  30.  * requirements (or modified versions of such code, with unchanged
  31.  * license).  You may copy and distribute such a system following the
  32.  * terms of the GNU GPL for this module and the licenses of the
  33.  * other code concerned, provided that you include the source code of
  34.  * that other code when and as the GNU GPL requires distribution of
  35.  * source code.
  36.  *
  37.  * Note that people who make modified versions of this module
  38.  * are not obligated to grant this special exception for their
  39.  * modified versions; it is their choice whether to do so.  The GNU
  40.  * General Public License gives permission to release a modified
  41.  * version without this exception; this exception also makes it
  42.  * possible to release a modified version which carries forward this
  43.  * exception.
  44.  *
  45.  */
  46. //
  47. // Media applications: wrappers of transport agents for multimedia objects
  48. // 
  49. // Their tasks are to receive 'data' from underlying transport agents, 
  50. // and to notify "above" applications that such data has arrived. 
  51. //
  52. // When required (by RapAgent), it also provides callbacks to the 
  53. // transport agent, and contact the above application on behalf of the 
  54. // transport agent.
  55. //
  56. // $Header: /cvsroot/nsnam/ns-2/rap/media-app.h,v 1.12 2005/08/25 18:58:10 johnh Exp $
  57. #ifndef ns_media_app_h
  58. #define ns_media_app_h
  59. #include <stdlib.h>
  60. #include <tcl.h>
  61. #include "config.h"
  62. #include "agent.h"
  63. #include "app.h"
  64. #include "webcache/http-aux.h"
  65. #include "rap/rap.h"
  66. #include "rap/utilities.h"
  67. class HttpMediaData;
  68. // Fixed length segment in a multimedia stream
  69. class MediaSegment : public DoubleListElem {
  70. public: 
  71. MediaSegment() : start_(0), end_(0), flags_(0) {}
  72. MediaSegment(int start, int end) : start_(start),end_(end),flags_(0) {}
  73. MediaSegment(const HttpMediaData& d);
  74. MediaSegment(const MediaSegment& s) {
  75. // XXX Don't copy pointers (prev_,next_)?
  76. start_ = s.start_;
  77. end_ = s.end_;
  78. flags_ = s.flags_;
  79. }
  80. int start() const { return start_; }
  81. int end() const { return end_; }
  82. int datasize() const { return end_ - start_; }
  83. MediaSegment* next() const { 
  84. return (MediaSegment *)DoubleListElem::next(); 
  85. }
  86. MediaSegment* prev() const { 
  87. return (MediaSegment *)DoubleListElem::prev(); 
  88. }
  89. void set_start(int d) { start_ = d; }
  90. void set_end(int d) { end_ = d; }
  91. void set_datasize(int d) { end_ = start_ + d; }
  92. // Advance the segment by size
  93. void advance(int size) { start_ += size, end_ = start_ + size; }
  94. int in(const MediaSegment& s) const {
  95. return ((start_ >= s.start_) && (end_ <= s.end_));
  96. }
  97. int before(const MediaSegment& s) const {
  98. return (end_ <= s.start_);
  99. }
  100. int overlap(const MediaSegment& s) const {
  101. assert(s.start_ <= s.end_);
  102. return ((s.end_ >= start_) && (s.start_ <= end_));
  103. }
  104. // Return the overlapping size between the two
  105. int merge(const MediaSegment& s) {
  106. if ((s.end_ < start_) || (s.start_ > end_))
  107. // No overlap
  108. return 0;
  109. int size = datasize() + s.datasize();
  110. if (s.start_ < start_) start_ = s.start_;
  111. if (s.end_ > end_) end_ = s.end_;
  112. assert(size >= datasize());
  113. return (size - datasize());
  114. }
  115. // Return the amount of data evicted
  116. int evict_tail(int sz) {
  117. // Adjust both the size and playout time
  118. #ifdef MCACHE_DEBUG
  119. fprintf(stderr, "evicted (%d, %d) ", end_-sz, end_);
  120. #endif
  121. if (datasize() >= sz) 
  122. end_ -= sz;
  123. else {
  124. sz = datasize();
  125. end_ = start_;
  126. }
  127. return sz;
  128. }
  129. // Return the amount of data evicted
  130. int evict_head(int sz) {
  131. // Adjust both the size and playout time
  132. if (datasize() >= sz) 
  133. start_ += sz;
  134. else {
  135. sz = datasize();
  136. end_ = start_;
  137. }
  138. return sz;
  139. }
  140. int is_empty() const { return end_ == start_; }
  141. // Whether this is the last segment of the available data
  142. enum { MS_LAST = 1, MS_PREF = 2 };
  143. int is_last() const { return (flags_ & MS_LAST); }
  144. void set_last() { flags_ |= MS_LAST; }
  145. int is_pref() const { return (flags_ & MS_PREF); }
  146. void set_pref() { flags_ |= MS_PREF; }
  147. private: 
  148. int start_;
  149. int end_;
  150. int flags_;
  151. };
  152. // Maintains received segments of every layer
  153. class MediaSegmentList : public DoubleList {
  154. public:
  155. MediaSegmentList() : DoubleList(), length_(0) {}
  156. int length() const { return length_; }
  157. void add(const MediaSegment& s);
  158. int in(const MediaSegment& s);
  159. MediaSegment get_nextseg(const MediaSegment& s);
  160. int evict_tail(int size);
  161. int evict_head(int size);
  162. int evict_head_offset(int offset);
  163. int overlap_size(const MediaSegment& s) const;
  164. MediaSegmentList check_holes(const MediaSegment& s);
  165. char* dump2buf();
  166. virtual void destroy() {
  167. DoubleList::destroy();
  168. length_ = 0;
  169. }
  170. // Debug only
  171. void print(void);
  172. int getsize();
  173. void check_integrity();
  174. protected:
  175. void merge_seg(MediaSegment* seg);
  176. private:
  177. int length_;
  178. };
  179. // Represents a multimedia segment transmitted through the network
  180. class HttpMediaData : public HttpData {
  181. private:
  182. char page_[HTTP_MAXURLLEN]; // Page ID
  183. char sender_[HTTP_MAXURLLEN]; // Sender name
  184. int layer_; // Layer id. 0 if no layered encoding
  185. int st_; // Segment start time
  186. int et_;  // Segment end time
  187. int flags_;  // flags: end of all data, etc.
  188. Application* conid_; // Connection ID. Used for statistics
  189. public:
  190. struct hdr {
  191. char sender_[HTTP_MAXURLLEN];
  192. char page_[HTTP_MAXURLLEN];
  193. int layer_;
  194. int st_, et_;
  195. int flags_;
  196. };
  197. public:
  198. HttpMediaData(const char* sender, const char* name, int layer, 
  199.       int st, int et);
  200. HttpMediaData(HttpMediaData& d) : HttpData(d) {
  201. layer_ = d.layer_;
  202. st_ = d.st_;
  203. et_ = d.et_;
  204. flags_ = d.flags_;
  205. strcpy(page_, d.page_);
  206. strcpy(sender_, d.sender_);
  207. }
  208. virtual int size() const { return HttpData::size() + sizeof(hdr); }
  209. virtual AppData* copy() { return (new HttpMediaData(*this)); }
  210. int st() const { return st_; }
  211. int et() const { return et_; }
  212. int datasize() const { return et_ - st_; }
  213. int layer() const { return layer_; }
  214. const char* page() const { return page_; }
  215. const char* sender() const { return sender_; }
  216. Application* conid() { return conid_; }
  217. void set_conid(Application* c) { conid_ = c; }
  218. // flags
  219. // MD_LAST: last segment of this layre
  220. // MD_FINISH: completed the entire stream
  221. enum {
  222. MD_LAST = 1, 
  223. MD_FINISH = 2,
  224. MD_PREFETCH = 4
  225. }; 
  226. // Whether this is the last data segment of the layer
  227. int is_last() const { return (flags_ & MD_LAST); }
  228. void set_last() { flags_ |= MD_LAST; }
  229. int is_finished() const { return (flags_ & MD_FINISH); }
  230. void set_finish() { flags_ |= MD_FINISH; }
  231. int is_pref() const { return (flags_ & MD_PREFETCH); }
  232. void set_pref() { flags_ |= MD_PREFETCH; }
  233. };
  234. const int MEDIAREQ_GETSEG    = 1;
  235. const int MEDIAREQ_CHECKSEG  = 2;
  236. const int MEDIAREQ_SEGAVAIL  = 3;
  237. const int MEDIAREQ_SEGUNAVAIL  = 4;
  238. // It provides a MediaApp two types of requests: check data availability and 
  239. // request data. It won't be sent in a packet so we don't need copy(). 
  240. class MediaRequest : public AppData {
  241. private:
  242. int request_;  // Request code
  243. char name_[HTTP_MAXURLLEN]; // Page URL
  244. int layer_; // Layer ID
  245. u_int st_; // Start playout time
  246. u_int et_; // End playout time
  247. Application* app_; // Calling application
  248. public:
  249. MediaRequest(int rc) : AppData(MEDIA_REQUEST), request_(rc) {}
  250. MediaRequest(const MediaRequest& r) : AppData(MEDIA_REQUEST) {
  251. request_ = r.request();
  252. st_ = r.st();
  253. et_ = r.et();
  254. layer_ = r.layer();
  255. strcpy(name_, r.name());
  256. }
  257. // We don't need it, but have to declare.
  258. virtual AppData* copy() { abort(); return NULL; }
  259. int request() const { return request_; }
  260. int st() const { return st_; }
  261. int et() const { return et_; }
  262. int datasize() const { return et_ - st_; }
  263. int layer() const { return layer_; }
  264. const char* name() const { return name_; }
  265. Application* app() const { return app_; }
  266. // These functions allow the caller to fill in only the 
  267. // necessary fields
  268. void set_st(int d) { st_ = d; }
  269. void set_et(int d) { et_ = d; }
  270. void set_datasize(int d) { et_ = st_ + d; }
  271. void set_name(const char *s) { strcpy(name_, s); }
  272. void set_layer(int d) { layer_ = d; }
  273. void set_app(Application* a) { app_ = a; }
  274. };
  275. // Maximum number of layers for all streams in the simulation
  276. const int MAX_LAYER = 10;
  277. // XXX A media app is only responsible for transmission of a single 
  278. // media stream!! Once the transmission is done, the media app will be 
  279. // deleted.
  280. class MediaApp : public Application {
  281. public:
  282. MediaApp(const char* page);
  283. virtual AppData* get_data(int& size, AppData* req_data = 0);
  284. virtual void process_data(int size, AppData* data) {
  285. send_data(size, data);
  286. }
  287. void set_page(const char* pg) { strcpy(page_, pg); }
  288. void log(const char* fmt, ...);
  289. int command(int argc, const char*const* argv);
  290. protected:
  291. virtual void start();
  292. virtual void stop();
  293. // Helper function
  294. RapAgent* rap() { return (RapAgent*)agent_; }
  295. int seg_size_;  // data segment size
  296. char page_[HTTP_MAXURLLEN];
  297. MediaSegment data_[MAX_LAYER]; // Pointer to next data to be sent
  298. Tcl_Channel log_;  // log file
  299. // XXX assuming all streams in the simulation have the same
  300. // number of layers.
  301. int num_layer_;
  302. private:
  303. int last_layer_;
  304. };
  305. class QA; 
  306. class QATimer : public TimerHandler {
  307. public:
  308. QATimer(QA *a) : TimerHandler() { a_ = a; }
  309. protected:
  310. virtual void expire(Event *e);
  311. QA *a_;
  312. };
  313. const double QA_EPSILON = 1e-6;
  314. class QA : public MediaApp { 
  315. public:
  316. QA(const char *page);
  317. virtual ~QA();
  318. virtual AppData* get_data(int& size, AppData* req_data = 0);
  319. void UpdateState();
  320. double UpdateInterval() { return rap()->srtt(); } 
  321. protected:
  322. virtual int command(int argc, const char*const* argv);
  323. virtual void stop();
  324. // Helper functions
  325. void check_availability(int layer, const MediaSegment& s);
  326. RapAgent* rap() { return (RapAgent*)agent_; }
  327. // Misc helpers
  328. inline double MWM(double srtt) {
  329. return 2 * LAYERBW_ * srtt;
  330. }
  331. inline double rate() { 
  332. return (double)seg_size_ / rap()->ipg();
  333. }
  334. // Calculate area of a triangle for a given side and slope
  335. inline double BufNeed(double side, double slope) {
  336. return (side <= 0) ? 0.0 : ((side*side) / (2.0*slope));
  337. }
  338. int AllZero(double *arr, int len);
  339. double TotalBuf(int n, double *buffer);
  340. AppData* output(int& size, int layer);
  341. void DumpInfo(double t, double last_t, double rate, 
  342.       double avgrate, double srtt);
  343. double bufOptScen1(int layer, int layers, double currrate, 
  344.    double slope, int backoffs);
  345. double bufOptScen2(int layer, int layers, double currrate, 
  346.    double slope, int backoffs);
  347. void drain_buf(double* DrainArr, double bufToDrain, 
  348.        double* FinalDrainArray, double* bufAvail, 
  349.        int layers, double rate, double srtt);
  350. void DrainPacket(double bufToDrain, double* FinalDrainArray, 
  351.  int layers, double rate, double srtt, 
  352.  double* FinalBuffer);
  353. // Ack feedback information
  354. void DrainBuffers();
  355. // Debugging output
  356. void debug(const char* fmt, ...);
  357. void panic(const char* fmt, ...);
  358. void check_layers(int layer, MediaSegment& tmp);
  359. // Data members
  360. int layer_;
  361. double    playTime_; // playout time of the receiver
  362. double    startTime_; // Absoloute time when playout started
  363. // Internal state info for QA
  364. double   buffer_[MAX_LAYER];
  365. double   drained_[MAX_LAYER]; 
  366. double   bw_[MAX_LAYER];
  367. int  playing_[MAX_LAYER]; 
  368. int  sending_[MAX_LAYER];
  369. QATimer* updTimer_;
  370. // Average transmission rate and its moving average weight
  371. // Measured whenever a segment is sent out (XXX why??)
  372. double   avgrate_; 
  373. double   rate_weight_;
  374. // Variables related to playout buffer management
  375. int      poffset_;  /* The playout offset: estimation of client 
  376.        playout time */
  377. // Linked list keeping track of holes between poffset_ and current
  378. // transmission pointer
  379. MediaSegmentList outlist_[MAX_LAYER];
  380. // The end offset of the prefetch requests. Used to avoid redundant
  381. // prefetching requests
  382. int pref_[MAX_LAYER];
  383. // OTcl-bound variables
  384. int debug_;   // Turn on/off debug output
  385. double pref_srtt_; // Prefetching SRTT
  386. int LAYERBW_;
  387. int MAXACTIVELAYERS_;
  388. double SRTTWEIGHT_;
  389. int SMOOTHFACTOR_;
  390. int MAXBKOFF_;
  391. }; 
  392. #endif // ns_media_app_h