📄 media-app.h
字号:
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- *///// Copyright (c) 1997 by the University of Southern California// All rights reserved.//// Permission to use, copy, modify, and distribute this software and its// documentation in source and binary forms for non-commercial purposes// and without fee is hereby granted, provided that the above copyright// notice appear in all copies and that both the copyright notice and// this permission notice appear in supporting documentation. and that// any documentation, advertising materials, and other materials related// to such distribution and use acknowledge that the software was// developed by the University of Southern California, Information// Sciences Institute. The name of the University may not be used to// endorse or promote products derived from this software without// specific prior written permission.//// THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about// the suitability of this software for any purpose. THIS SOFTWARE IS// PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,// INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.//// Other copyrights might apply to parts of this software and are so// noted when applicable.//// Media applications: wrappers of transport agents for multimedia objects// // Their tasks are to receive 'data' from underlying transport agents, // and to notify "above" applications that such data has arrived. //// When required (by RapAgent), it also provides callbacks to the // transport agent, and contact the above application on behalf of the // transport agent.//// $Header: /nfs/jade/vint/CVSROOT/ns-2/rap/media-app.h,v 1.11 1999/11/18 23:14:32 haoboy Exp $#ifndef ns_media_app_h#define ns_media_app_h#include <stdlib.h>#include <tcl.h>#include "config.h"#include "agent.h"#include "app.h"#include "webcache/http-aux.h"#include "rap/rap.h"#include "rap/utilities.h"class HttpMediaData;// Fixed length segment in a multimedia streamclass MediaSegment : public DoubleListElem {public: MediaSegment() : start_(0), end_(0), flags_(0) {} MediaSegment(int start, int end) : start_(start),end_(end),flags_(0) {} MediaSegment(const HttpMediaData& d); MediaSegment(const MediaSegment& s) { // XXX Don't copy pointers (prev_,next_)? start_ = s.start_; end_ = s.end_; flags_ = s.flags_; } int start() const { return start_; } int end() const { return end_; } int datasize() const { return end_ - start_; } MediaSegment* next() const { return (MediaSegment *)DoubleListElem::next(); } MediaSegment* prev() const { return (MediaSegment *)DoubleListElem::prev(); } void set_start(int d) { start_ = d; } void set_end(int d) { end_ = d; } void set_datasize(int d) { end_ = start_ + d; } // Advance the segment by size void advance(int size) { start_ += size, end_ = start_ + size; } int in(const MediaSegment& s) const { return ((start_ >= s.start_) && (end_ <= s.end_)); } int before(const MediaSegment& s) const { return (end_ <= s.start_); } int overlap(const MediaSegment& s) const { assert(s.start_ <= s.end_); return ((s.end_ >= start_) && (s.start_ <= end_)); } // Return the overlapping size between the two int merge(const MediaSegment& s) { if ((s.end_ < start_) || (s.start_ > end_)) // No overlap return 0; int size = datasize() + s.datasize(); if (s.start_ < start_) start_ = s.start_; if (s.end_ > end_) end_ = s.end_; assert(size >= datasize()); return (size - datasize()); } // Return the amount of data evicted int evict_tail(int sz) { // Adjust both the size and playout time#ifdef MCACHE_DEBUG fprintf(stderr, "evicted (%d, %d) ", end_-sz, end_);#endif if (datasize() >= sz) end_ -= sz; else { sz = datasize(); end_ = start_; } return sz; } // Return the amount of data evicted int evict_head(int sz) { // Adjust both the size and playout time if (datasize() >= sz) start_ += sz; else { sz = datasize(); end_ = start_; } return sz; } int is_empty() const { return end_ == start_; } // Whether this is the last segment of the available data enum { MS_LAST = 1, MS_PREF = 2 }; int is_last() const { return (flags_ & MS_LAST); } void set_last() { flags_ |= MS_LAST; } int is_pref() const { return (flags_ & MS_PREF); } void set_pref() { flags_ |= MS_PREF; }private: int start_; int end_; int flags_;};// Maintains received segments of every layerclass MediaSegmentList : public DoubleList {public: MediaSegmentList() : DoubleList(), length_(0) {} int length() const { return length_; } void add(const MediaSegment& s); int in(const MediaSegment& s); MediaSegment get_nextseg(const MediaSegment& s); int evict_tail(int size); int evict_head(int size); int evict_head_offset(int offset); int overlap_size(const MediaSegment& s) const; MediaSegmentList check_holes(const MediaSegment& s); char* dump2buf(); virtual void destroy() { DoubleList::destroy(); length_ = 0; } // Debug only void print(void); int getsize(); void check_integrity();protected: void merge_seg(MediaSegment* seg);private: int length_;};// Represents a multimedia segment transmitted through the networkclass HttpMediaData : public HttpData {private: char page_[HTTP_MAXURLLEN]; // Page ID char sender_[HTTP_MAXURLLEN]; // Sender name int layer_; // Layer id. 0 if no layered encoding int st_; // Segment start time int et_; // Segment end time int flags_; // flags: end of all data, etc. Application* conid_; // Connection ID. Used for statisticspublic: struct hdr { char sender_[HTTP_MAXURLLEN]; char page_[HTTP_MAXURLLEN]; int layer_; int st_, et_; int flags_; };public: HttpMediaData(const char* sender, const char* name, int layer, int st, int et); HttpMediaData(HttpMediaData& d) : HttpData(d) { layer_ = d.layer_; st_ = d.st_; et_ = d.et_; flags_ = d.flags_; strcpy(page_, d.page_); strcpy(sender_, d.sender_); } virtual int size() const { return HttpData::size() + sizeof(hdr); } virtual AppData* copy() { return (new HttpMediaData(*this)); } int st() const { return st_; } int et() const { return et_; } int datasize() const { return et_ - st_; } int layer() const { return layer_; } const char* page() const { return page_; } const char* sender() const { return sender_; } Application* conid() { return conid_; } void set_conid(Application* c) { conid_ = c; } // flags // MD_LAST: last segment of this layre // MD_FINISH: completed the entire stream enum { MD_LAST = 1, MD_FINISH = 2, MD_PREFETCH = 4 }; // Whether this is the last data segment of the layer int is_last() const { return (flags_ & MD_LAST); } void set_last() { flags_ |= MD_LAST; } int is_finished() const { return (flags_ & MD_FINISH); } void set_finish() { flags_ |= MD_FINISH; } int is_pref() const { return (flags_ & MD_PREFETCH); } void set_pref() { flags_ |= MD_PREFETCH; }};const int MEDIAREQ_GETSEG = 1;const int MEDIAREQ_CHECKSEG = 2;const int MEDIAREQ_SEGAVAIL = 3;const int MEDIAREQ_SEGUNAVAIL = 4;// It provides a MediaApp two types of requests: check data availability and // request data. It won't be sent in a packet so we don't need copy(). class MediaRequest : public AppData {private: int request_; // Request code char name_[HTTP_MAXURLLEN]; // Page URL int layer_; // Layer ID u_int st_; // Start playout time u_int et_; // End playout time Application* app_; // Calling applicationpublic: MediaRequest(int rc) : AppData(MEDIA_REQUEST), request_(rc) {} MediaRequest(const MediaRequest& r) : AppData(MEDIA_REQUEST) { request_ = r.request(); st_ = r.st(); et_ = r.et(); layer_ = r.layer(); strcpy(name_, r.name()); } // We don't need it, but have to declare. virtual AppData* copy() { abort(); return NULL; } int request() const { return request_; } int st() const { return st_; } int et() const { return et_; } int datasize() const { return et_ - st_; } int layer() const { return layer_; } const char* name() const { return name_; } Application* app() const { return app_; } // These functions allow the caller to fill in only the // necessary fields void set_st(int d) { st_ = d; } void set_et(int d) { et_ = d; } void set_datasize(int d) { et_ = st_ + d; } void set_name(const char *s) { strcpy(name_, s); } void set_layer(int d) { layer_ = d; } void set_app(Application* a) { app_ = a; }};// Maximum number of layers for all streams in the simulationconst int MAX_LAYER = 10;// XXX A media app is only responsible for transmission of a single // media stream!! Once the transmission is done, the media app will be // deleted.class MediaApp : public Application {public: MediaApp(const char* page); virtual AppData* get_data(int& size, AppData* req_data = 0); virtual void process_data(int size, AppData* data) { send_data(size, data); } void set_page(const char* pg) { strcpy(page_, pg); } void log(const char* fmt, ...); int command(int argc, const char*const* argv);protected: virtual void start(); virtual void stop(); // Helper function RapAgent* rap() { return (RapAgent*)agent_; } int seg_size_; // data segment size char page_[HTTP_MAXURLLEN]; MediaSegment data_[MAX_LAYER]; // Pointer to next data to be sent Tcl_Channel log_; // log file // XXX assuming all streams in the simulation have the same // number of layers. int num_layer_;private: int last_layer_;};class QA; class QATimer : public TimerHandler {public: QATimer(QA *a) : TimerHandler() { a_ = a; }protected: virtual void expire(Event *e); QA *a_;};const double QA_EPSILON = 1e-6;class QA : public MediaApp { public: QA(const char *page); virtual ~QA(); virtual AppData* get_data(int& size, AppData* req_data = 0); void UpdateState(); double UpdateInterval() { return rap()->srtt(); } protected: virtual int command(int argc, const char*const* argv); virtual void stop(); // Helper functions void check_availability(int layer, const MediaSegment& s); RapAgent* rap() { return (RapAgent*)agent_; } // Misc helpers inline double MWM(double srtt) { return 2 * LAYERBW_ * srtt; } inline double rate() { return (double)seg_size_ / rap()->ipg(); } // Calculate area of a triangle for a given side and slope inline double BufNeed(double side, double slope) { return (side <= 0) ? 0.0 : ((side*side) / (2.0*slope)); } int AllZero(double *arr, int len); double TotalBuf(int n, double *buffer); AppData* output(int& size, int layer); void DumpInfo(double t, double last_t, double rate, double avgrate, double srtt); double bufOptScen1(int layer, int layers, double currrate, double slope, int backoffs); double bufOptScen2(int layer, int layers, double currrate, double slope, int backoffs); void drain_buf(double* DrainArr, double bufToDrain, double* FinalDrainArray, double* bufAvail, int layers, double rate, double srtt); void DrainPacket(double bufToDrain, double* FinalDrainArray, int layers, double rate, double srtt, double* FinalBuffer); // Ack feedback information void DrainBuffers(); // Debugging output void debug(const char* fmt, ...); void panic(const char* fmt, ...); void check_layers(int layer, MediaSegment& tmp); // Data members int layer_; double playTime_; // playout time of the receiver double startTime_; // Absoloute time when playout started // Internal state info for QA double buffer_[MAX_LAYER]; double drained_[MAX_LAYER]; double bw_[MAX_LAYER]; int playing_[MAX_LAYER]; int sending_[MAX_LAYER]; QATimer* updTimer_; // Average transmission rate and its moving average weight // Measured whenever a segment is sent out (XXX why??) double avgrate_; double rate_weight_; // Variables related to playout buffer management int poffset_; /* The playout offset: estimation of client playout time */ // Linked list keeping track of holes between poffset_ and current // transmission pointer MediaSegmentList outlist_[MAX_LAYER]; // The end offset of the prefetch requests. Used to avoid redundant // prefetching requests int pref_[MAX_LAYER]; // OTcl-bound variables int debug_; // Turn on/off debug output double pref_srtt_; // Prefetching SRTT int LAYERBW_; int MAXACTIVELAYERS_; double SRTTWEIGHT_; int SMOOTHFACTOR_; int MAXBKOFF_;}; #endif // ns_media_app_h
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -