Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members
Statistics.hpp
00001 /*********************************************************************** 00002 * * 00003 * ViTooKi * 00004 * * 00005 * title: Statistics.hpp * 00006 * * 00007 * * 00008 * * 00009 * ITEC institute of the University of Klagenfurt (Austria) * 00010 * http://www.itec.uni-klu.ac.at * 00011 * * 00012 * * 00013 * For more information visit the ViTooKi homepage: * 00014 * http://ViTooKi.sourceforge.net * 00015 * vitooki-user@lists.sourceforge.net * 00016 * vitooki-devel@lists.sourceforge.net * 00017 * * 00018 * This file is part of ViTooKi, a free video toolkit. * 00019 * ViTooKi is free software; you can redistribute it and/or * 00020 * modify it under the terms of the GNU General Public License * 00021 * as published by the Free Software Foundation; either version 2 * 00022 * of the License, or (at your option) any later version. * 00023 * * 00024 * This program is distributed in the hope that it will be useful, * 00025 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00026 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00027 * GNU General Public License for more details. * 00028 * * 00029 * You should have received a copy of the GNU General Public License * 00030 * along with this program; if not, write to the Free Software * 00031 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * 00032 * MA 02111-1307, USA. * 00033 * * 00034 ***********************************************************************/ 00035 00036 /*********************************************************************** 00037 * * 00038 * REVISION HISTORY: * 00039 * * 00040 * * 00041 * * 00042 ***********************************************************************/ 00043 00044 #ifndef MK_STATISTICS_HPP 00045 #define MK_STATISTICS_HPP 00046 00047 #include "global.hpp" 00048 #include "ESInfo.hpp" 00049 00061 class Statistics { 00062 00063 #define RTP_AVG_RTT_ALPHA 0.75 00064 00065 #define RTP_STAT_SECS 30 00066 00067 public: 00068 00069 Statistics(ESInfo *esi, bool channelIsWriter); 00070 00071 virtual ~Statistics(); 00072 00073 void setESInfo(ESInfo *new_es); 00074 00075 //REALLY PUBLIC METHODS FOR GUI AND OTHER STAT READERS 00076 00079 u32 getStreamoutSec() { return streamout_sec; }; 00080 00083 double getStreamoutFloatSec() { return streamout_float_sec; }; 00084 00088 double getPlayoutSec() { return playout_sec; }; 00089 00092 long getBWfromStreamoutSec(u32 sec); 00093 00096 long getBWfromPlayoutSec(u32 sec); 00097 00099 u32 getNumStreamoutSecs(); 00100 00102 double getBufferFillLevelInSecs() const { return buf_ahead_sec; }; 00103 00104 00105 //DIRECT ACCESS TO STATISTICS! ONLY USE THEM IF YOU KNOW WHAT YOU DO! 00106 00107 void setFirstPacketTS(u32 ts) { first_packet_ts = ts; }; 00108 u32 getFirstPacketTS() { return first_packet_ts; }; 00109 00110 void setHighestPacketTS(u32 ts) { highest_packet_ts = ts; }; 00111 u32 getHighestPacketTS() { return highest_packet_ts; }; 00112 00113 void setStreamoutFullSec(u32 sec) { streamout_sec = sec; }; 00114 u32 getStreamoutFullSec() { return streamout_sec; }; 00115 00116 void setStreamoutFloatSec(double sec) { streamout_float_sec = sec; }; 00117 //moved up to public methods 00118 // double getStreamoutFloatSec() { return streamout_float_sec; }; 00119 00120 void setPlayoutSec(double sec) { playout_sec = sec; }; 00121 //moved up to public methods 00122 // double getPlayoutSec() { return playout_sec; }; 00123 00124 void setBufAheadSec(double sec) { buf_ahead_sec = sec; }; 00125 double getBufAheadSec() { return buf_ahead_sec; }; 00126 00127 void setClientPreQMaxSize(u32 size) { client_preQ_max_size = size; }; 00128 u32 getClientPreQMaxSize() { return client_preQ_max_size; }; 00129 00130 void setStillToPrefetchSecs(double secs){ stillToPrefetchSecs = secs; }; 00131 double getStillToPrefetchSecs() { return stillToPrefetchSecs; }; 00132 00133 void setPrefetchedSecs(double secs){ prefetched_secs = secs; }; 00134 double getPrefetchedSecs() { return prefetched_secs; }; 00135 00136 void setFirstPacketTime(double time) { first_packet_dtime = time; }; 00137 double getFirstPacketTime() { return first_packet_dtime; }; 00138 00139 void setLastPacketTime(double time) { last_packet_dtime = time; }; 00140 double getLastPacketTime() { return last_packet_dtime; }; 00141 00142 /* will be averaged by an alpha */ 00143 int setAvgRTT(int rtt); 00144 int getAvgRTT() { return avg_rtt; }; 00145 00146 /* will be averaged by an alpha */ 00147 int setAvgInterarrivalTime(int msecs); 00148 int getAvgInterarrivalTime() { return avg_interarrival_time; }; 00149 00150 /* estimated bandwidth to stream one second in best quality, quasi-static 00151 * (normally, a little more than avg bw) */ 00152 void setStreamBW(int bw) { stream_bw = bw; }; 00153 int getStreamBW() { return stream_bw; }; 00154 00155 /* the start-streamBW of the very first stream (not affected by switching) */ 00156 void setBaseStreamBW(int bw) { base_stream_bw = bw; }; 00157 int getBaseStreamBW() { return base_stream_bw; }; 00158 00159 void setAdaptRate(int rate) { adapt_rate = rate; }; 00160 int getAdaptRate() { return adapt_rate; }; 00161 00162 void setAdaptSecs(double secs) { adapt_secs = secs; }; 00163 double getAdaptSecs() { return adapt_secs; }; 00164 00165 00166 #define IN_PLAYOUT_ARR (sec) {if (sec < MAX(0,(int)floor((double)getHighestPacketTS() / es->getMediaTimeScale() - RTP_STAT_SECS))) return false;} 00167 #define IN_STREAMOUT_ARR (sec) {if (sec < MAX(0,(int)getStreamoutFullSec() - RTP_STAT_SECS)) return false;} 00168 #define RET_OK {return true;} 00169 00170 //METHODS FOR STAT ARRAYS 00171 //PLAYOUT STATS 00172 00178 bool checkForNewPlayoutSec(int this_frame_sec, int highest_ts_sec); 00179 00180 /* writePlayoutStats will be called if a new playoutSec occurs to the Adaptors (ergo real viewing) */ 00181 void writePlayoutSecStats(int this_frame_sec); 00182 00183 void setVOPTimeIncrement(int incr) { es->setVOPTimeIncrement(incr); }; 00184 00185 /* returns the original framerate from the ESInfo */ 00186 float getOriginalFPS() { return (double)es->getMediaTimeScale() / (double)es->getVOPTimeIncrement(); }; 00187 00188 /* increases the FPS, which arrived thru network/file for the given sec (used by IO class) 00189 * they might not be displayed because of the ESSychronizer adaptor or decoding errors 00190 */ 00191 bool incPlayoutSecNetFPS(int sec) { playsec_stat[sec % RTP_STAT_SECS].net_fps++; RET_OK }; 00192 bool decPlayoutSecNetFPS(int sec) { playsec_stat[sec % RTP_STAT_SECS].net_fps--; RET_OK }; 00193 int getPlayoutSecNetFPS(int sec) { return playsec_stat[sec % RTP_STAT_SECS].net_fps; }; 00194 00195 /* increases the FPS which was _really_ displayed 00196 * after ESSync adaptor and after decoding errors (eg. missing I-VOPs make B-VOPs undecodable */ 00197 bool incPlayoutSecFPS(int sec) { playsec_stat[sec % RTP_STAT_SECS].fps++; RET_OK }; 00198 bool decPlayoutSecFPS(int sec) { playsec_stat[sec % RTP_STAT_SECS].fps--; RET_OK }; 00199 int getPlayoutSecFPS(int sec) { return playsec_stat[sec % RTP_STAT_SECS].fps; }; 00200 00201 bool incPlayoutSecIFrame(int sec) { playsec_stat[sec % RTP_STAT_SECS].iframes++; RET_OK }; 00202 bool decPlayoutSecIFrame(int sec) { playsec_stat[sec % RTP_STAT_SECS].iframes--; RET_OK }; 00203 int getPlayoutSecIFrame(int sec) { return playsec_stat[sec % RTP_STAT_SECS].iframes; }; 00204 00205 bool incPlayoutSecPFrame(int sec) { playsec_stat[sec % RTP_STAT_SECS].pframes++; RET_OK }; 00206 bool decPlayoutSecPFrame(int sec) { playsec_stat[sec % RTP_STAT_SECS].pframes--; RET_OK }; 00207 int getPlayoutSecPFrame(int sec) { return playsec_stat[sec % RTP_STAT_SECS].pframes; }; 00208 00209 bool incPlayoutSecBFrame(int sec) { playsec_stat[sec % RTP_STAT_SECS].bframes++; RET_OK }; 00210 bool decPlayoutSecBFrame(int sec) { playsec_stat[sec % RTP_STAT_SECS].bframes--; RET_OK }; 00211 int getPlayoutSecBFrame(int sec) { return playsec_stat[sec % RTP_STAT_SECS].bframes; }; 00212 00213 bool incPlayoutSecPSNR(int sec, double psnr); 00214 double getPlayoutSecPSNR(int sec); 00215 00216 bool incPlayoutSecDataPkts(int sec) { playsec_stat[sec % RTP_STAT_SECS].num_data_pkts++; RET_OK }; 00217 bool decPlayoutSecDataPkts(int sec) { playsec_stat[sec % RTP_STAT_SECS].num_data_pkts--; RET_OK }; 00218 int getPlayoutSecDataPkts(int sec) { return playsec_stat[sec % RTP_STAT_SECS].num_data_pkts; }; 00219 00220 bool incPlayoutSecRtxPkts(int sec) { playsec_stat[sec % RTP_STAT_SECS].num_rtx_pkts++; RET_OK }; 00221 int getPlayoutSecRtxPkts(int sec) { return playsec_stat[sec % RTP_STAT_SECS].num_rtx_pkts; }; 00222 00223 bool incPlayoutSecDataBW(int sec, int bw) { playsec_stat[sec % RTP_STAT_SECS].data_bw += bw; RET_OK }; 00224 bool decPlayoutSecDataBW(int sec, int bw) { playsec_stat[sec % RTP_STAT_SECS].data_bw -= bw; RET_OK }; 00225 int getPlayoutSecDataBW(int sec) { return playsec_stat[sec % RTP_STAT_SECS].data_bw; }; 00226 00227 bool incPlayoutSecRtxBW(int sec, int bw) { playsec_stat[sec % RTP_STAT_SECS].rtx_bw += bw; RET_OK }; 00228 int getPlayoutSecRtxBW(int sec) { return playsec_stat[sec % RTP_STAT_SECS].rtx_bw; }; 00229 00230 bool incPlayoutSecNackedBW(int sec, int bw) { playsec_stat[sec % RTP_STAT_SECS].nacked_bw += bw; RET_OK }; 00231 int getPlayoutSecNackedBW(int sec) { return playsec_stat[sec % RTP_STAT_SECS].nacked_bw; }; 00232 00233 00234 //STREAMOUT STATS 00240 bool checkForNewStreamoutSec(double now_dtime); 00241 /* writeClientStats will be called if a new StreamoutSec occurs to RTP */ 00242 void writeStreamoutSecClientStats(long preQsize); 00243 /* writeClientStats will be called if a new StreamoutSec occurs to RTP, 00244 * after all Adapt adjustments happened */ 00245 void writeStreamoutSecServerStats(); 00246 00247 /* @returns the percentage of lost packets */ 00248 float getStreamoutSecLossPercent(int sec); 00249 00250 bool incStreamoutSecDataPkts(int sec) { streamsec_stat[sec % RTP_STAT_SECS].num_data_pkts++; RET_OK }; 00251 bool decStreamoutSecDataPkts(int sec) { streamsec_stat[sec % RTP_STAT_SECS].num_data_pkts--; RET_OK }; 00252 int getStreamoutSecDataPkts(int sec) { return streamsec_stat[sec % RTP_STAT_SECS].num_data_pkts; }; 00253 00254 bool incStreamoutSecRtxPkts(int sec) { streamsec_stat[sec % RTP_STAT_SECS].num_rtx_pkts++; RET_OK }; 00255 int getStreamoutSecRtxPkts(int sec) { return streamsec_stat[sec % RTP_STAT_SECS].num_rtx_pkts; }; 00256 00257 bool incStreamoutSecDataBW(int sec, int bw) { streamsec_stat[sec % RTP_STAT_SECS].data_bw += bw; RET_OK }; 00258 bool decStreamoutSecDataBW(int sec, int bw) { streamsec_stat[sec % RTP_STAT_SECS].data_bw -= bw; RET_OK }; 00259 int getStreamoutSecDataBW(int sec) { return streamsec_stat[sec % RTP_STAT_SECS].data_bw; }; 00260 00261 bool incStreamoutSecRtxBW(int sec, int bw) { streamsec_stat[sec % RTP_STAT_SECS].rtx_bw += bw; RET_OK }; 00262 int getStreamoutSecRtxBW(int sec) { return streamsec_stat[sec % RTP_STAT_SECS].rtx_bw; }; 00263 00264 bool incStreamoutSecNackedBW(int sec, int bw) { streamsec_stat[sec % RTP_STAT_SECS].nacked_bw += bw; RET_OK }; 00265 int getStreamoutSecNackedBW(int sec) { return streamsec_stat[sec % RTP_STAT_SECS].nacked_bw; }; 00266 00267 bool setStreamoutSecNetBW(int sec, int bw) { streamsec_stat[sec % RTP_STAT_SECS].net_bw = bw; RET_OK }; 00268 int getStreamoutSecNetBW(int sec) { return streamsec_stat[sec % RTP_STAT_SECS].net_bw; }; 00269 00270 bool setStreamoutSecClientBufFill(int sec, int size) { streamsec_stat[sec % RTP_STAT_SECS].client_buf_fill = size; RET_OK }; 00271 bool incStreamoutSecClientBufFill(int sec, int size) { streamsec_stat[sec % RTP_STAT_SECS].client_buf_fill += size; RET_OK }; 00272 int getStreamoutSecClientBufFill(int sec) { return streamsec_stat[sec % RTP_STAT_SECS].client_buf_fill; }; 00273 00274 bool setStreamoutSecPlayoutSec(int sec, double plSec) { streamsec_stat[sec % RTP_STAT_SECS].playout_sec = plSec; RET_OK }; 00275 double getStreamoutSecPlayoutSec(int sec) { return streamsec_stat[sec % RTP_STAT_SECS].playout_sec; }; 00276 00277 bool setStreamoutSecBufAhead(int sec, double time) { streamsec_stat[sec % RTP_STAT_SECS].buf_ahead = time; RET_OK }; 00278 double getStreamoutSecBufAhead(int sec) { return streamsec_stat[sec % RTP_STAT_SECS].buf_ahead; }; 00279 00280 bool incStreamoutSecNumBKeepChecks(int sec) { streamsec_stat[sec % RTP_STAT_SECS].num_bkeep_checks++; RET_OK }; 00281 int getStreamoutSecNumBKeepChecks(int sec) { return streamsec_stat[sec % RTP_STAT_SECS].num_bkeep_checks; }; 00282 00283 private: 00284 00285 /* stats for one playout second 00286 * all values are directly mapped to the according playout sec 00287 * eg. bw is the exact bytes count for the playout sec, this might be far away from 00288 * avg. BW and streamout rate 00289 * fps and sum_psnr are set from within the according adaptors (ESSynchronizer and PSNR) 00290 */ 00291 typedef struct { 00292 int num_data_pkts; // overall num sent/recv'd 00293 int num_rtx_pkts; // subset of rtx sent/recv'd 00294 int data_bw; // how much real data was sent/recv'd? 00295 // (including rtp packet header sizes) 00296 int rtx_bw; // how many bytes were retransmissions? 00297 int net_fps; // available full frames (rate) from network 00298 int fps; // available full frames (rate) at PlayoutTime 00299 // (according to their TS) 00300 int iframes; // number of I frames within this playout second 00301 int pframes; // number of P frames within this playout second 00302 int bframes; // number of B frames within this playout second 00303 double sum_psnr; // the sum psnr for this playout second, has to 00304 // be DIV num_psnr! 00305 double num_psnr; // the num psnr for this playout second 00306 00307 //SERVER ONLY: 00308 int nacked_bw; // how many bytes lost? (client doesn't know 00309 // how many bytes were missing...) 00310 int stream_bw; // the streamBW of the current stream 00311 bool stream_switched; // indicates if in this sec, a new ES was set ( == stream switched) 00312 } OnePlayoutSecStat; 00313 00314 /* stats for one streamout second 00315 *all values are measured in this streamout sec and stored to that statistics 00316 * eg. bw is the exact bytes count for this streamout sec and should equal the 00317 * requested streamout rate 00318 */ 00319 typedef struct { 00320 int num_data_pkts; // overall num sent/recv'd 00321 int num_rtx_pkts; // subset of rtx sent/recv'd 00322 int data_bw; // how much real data was sent/recv'd? 00323 // (including rtp packet header sizes) 00324 int rtx_bw; // how many bytes were retransmissions? 00325 int net_bw; // how many bytes _should_ be streamed? 00326 double playout_sec; // where is actual playout 00327 u32 client_buf_fill;// estimation on bytes in client buffer 00328 double buf_ahead; // estimated, how far is the buffer ahead to playout sec 00329 00330 //SERVER ONLY: 00331 int nacked_bw; // how many bytes lost? (client doesn't know 00332 // how many bytes were missing...) 00333 int num_bkeep_checks; // num of tried RTCP bookkeeping 00334 int stream_bw; // the streamBW of the current stream 00335 bool stream_switched; // indicates if in this sec, a new ES was set ( == stream switched) 00336 } OneStreamoutSecStat; 00337 00338 //GENERIC STATISTICS 00339 double first_packet_dtime; 00340 double last_packet_dtime; 00341 u32 first_packet_ts; 00342 u32 highest_packet_ts; 00343 double playout_sec; // estimated client playout sec 00344 OnePlayoutSecStat playsec_stat[RTP_STAT_SECS]; //tracks the buffer stats 00345 // of the last few secs 00346 00347 //NETWORK RELATED STUFF 00348 u32 streamout_sec; // relative to thread_start_dtime 00349 double streamout_float_sec; // relative to thread_start_dtime 00350 int avg_interarrival_time; // msecs 00351 int avg_rtt; // msecs server: calcs from NACK 00352 // RTT is very unexact, since NACKs are recognized 00353 // only after an arrived pkt! 00354 int stream_bw; // estimated bandwidth to stream one second in best quality 00355 // (normally, a little more than avg bw) 00356 int base_stream_bw; // initial streamBW, not affected by switching 00357 OneStreamoutSecStat streamsec_stat[RTP_STAT_SECS]; //tracks the avg BW of 00358 // the last few secs 00359 00360 //BUFFER RELATED STUFF 00361 u32 client_preQ_max_size; //maxium size of client-side preQ 00362 double buf_ahead_sec; // estimated, how far is the buffer ahead to playout sec 00363 double prefetched_secs; // how many secs were already spent in prefetching? 00364 // (at least RTP_PREFETCH_SECS at init) 00365 double stillToPrefetchSecs;// how many secs still have to be prefetched... 00366 // (at least RTP_PREFETCH_SECS at init) 00367 00368 //ADAPTATION RELATED STUFF 00369 double adapt_secs; //normally 1.0, more or less to fill up/drain the 00370 // client buffer in adaptPreQ 00371 int adapt_rate; // 100% if no adaptation... should be in the range of 70 - 100% 00372 00373 //OTHER STAT STUFF 00374 ESInfo *es; 00375 FILE *streamout_stat_fp; 00376 FILE *playout_stat_fp; 00377 00378 }; 00379 00380 00381 #endif