00001 /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */ 00002 /* 00003 * Copyright (c) Xerox Corporation 1997. All rights reserved. 00004 * 00005 * This program is free software; you can redistribute it and/or modify it 00006 * under the terms of the GNU General Public License as published by the 00007 * Free Software Foundation; either version 2 of the License, or (at your 00008 * option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, but 00011 * WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License along 00016 * with this program; if not, write to the Free Software Foundation, Inc., 00017 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00018 * 00019 * Linking this file statically or dynamically with other modules is making 00020 * a combined work based on this file. Thus, the terms and conditions of 00021 * the GNU General Public License cover the whole combination. 00022 * 00023 * In addition, as a special exception, the copyright holders of this file 00024 * give you permission to combine this file with free software programs or 00025 * libraries that are released under the GNU LGPL and with code included in 00026 * the standard release of ns-2 under the Apache 2.0 license or under 00027 * otherwise-compatible licenses with advertising requirements (or modified 00028 * versions of such code, with unchanged license). You may copy and 00029 * distribute such a system following the terms of the GNU GPL for this 00030 * file and the licenses of the other code concerned, provided that you 00031 * include the source code of that other code when and as the GNU GPL 00032 * requires distribution of source code. 00033 * 00034 * Note that people who make modified versions of this file are not 00035 * obligated to grant this special exception for their modified versions; 00036 * it is their choice whether to do so. The GNU General Public License 00037 * gives permission to release a modified version without this exception; 00038 * this exception also makes it possible to release a modified version 00039 * which carries forward this exception. 00040 */ 00041 00042 /* 00043 * Copyright (c) 1995 The Regents of the University of California. 00044 * All rights reserved. 00045 * 00046 * Redistribution and use in source and binary forms, with or without 00047 * modification, are permitted provided that the following conditions 00048 * are met: 00049 * 1. Redistributions of source code must retain the above copyright 00050 * notice, this list of conditions and the following disclaimer. 00051 * 2. Redistributions in binary form must reproduce the above copyright 00052 * notice, this list of conditions and the following disclaimer in the 00053 * documentation and/or other materials provided with the distribution. 00054 * 3. All advertising materials mentioning features or use of this software 00055 * must display the following acknowledgement: 00056 * This product includes software developed by the Network Research 00057 * Group at Lawrence Berkeley National Laboratory. 00058 * 4. Neither the name of the University nor of the Laboratory may be used 00059 * to endorse or promote products derived from this software without 00060 * specific prior written permission. 00061 * 00062 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 00063 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00064 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00065 */ 00066 00067 #ifndef lint 00068 static const char rcsid[] = 00069 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/apps/vatrcvr.cc,v 1.7 2005/08/26 05:05:28 tomh Exp $"; 00070 #endif 00071 00072 #ifndef WIN32 00073 #include <sys/time.h> 00074 #endif 00075 #include "agent.h" 00076 #include "rtp.h" 00077 #include "adaptive-receiver.h" 00078 #include "vat.h" 00079 00080 //Most of this code is taken from the decoder.cc file of the publicly available 00081 //vat code with some minor midifications. 00082 00083 class VatRcvr : public AdaptiveRcvr { 00084 public: 00085 VatRcvr(); 00086 protected: 00087 int adapt(Packet *pkt, u_int32_t time); 00088 void count(int statno); 00089 u_int32_t hostoffset_; 00090 int32_t var_; //variance in this host's interarrival time 00091 u_int32_t playout_; // playout delay (in media units) 00092 int maxdel_; 00093 int block_size_; 00094 int lecture_mode_; 00095 u_int32_t lastrecv_; 00096 u_int32_t predicted_drop_; 00097 int delvar_; 00098 /*XXX*/ 00099 #define MAXSTAT 16 00100 struct statcntr { 00101 const char* name; 00102 u_int cnt; 00103 } stat_[MAXSTAT]; 00104 int nstat_; 00105 }; 00106 00107 00108 inline void VatRcvr::count(int statno) 00109 { 00110 ++stat_[statno].cnt; 00111 } 00112 00113 00114 inline int absdiff(int x, int y) 00115 { 00116 register int r = y - x; 00117 return (r < 0? -r : r); 00118 } 00119 00120 static inline int newoffset( 00121 int nvar, 00122 int playout, 00123 int maxdel, int mindel, int lecture) 00124 { 00125 register int offset = nvar; 00126 if (offset > maxdel) 00127 offset = maxdel; 00128 register int diff = playout - offset; 00129 00130 if (diff > 0) { 00131 // offset going down: in LectureMode, drop at most 00132 // one frametime per talkspurt. In ConferenceMode, 00133 // drop at most 1/2 of difference. 00134 if (lecture) { 00135 if (diff > FRAMESIZE) { 00136 if (playout > (maxdel * 3) / 4 && 00137 diff > 10 * FRAMESIZE) 00138 diff = 5 * FRAMESIZE; 00139 else 00140 diff = FRAMESIZE; 00141 } 00142 } else 00143 diff >>= 1; 00144 offset = playout - diff; 00145 } else if (-diff > maxdel) { 00146 // offset going way up: only allow 3/4 of max. 00147 offset = (maxdel * 3) / 4; 00148 } 00149 if (offset > (maxdel * 7) / 8) 00150 offset = (maxdel * 7) / 8; 00151 else if (offset < mindel) 00152 offset = mindel; 00153 return (offset); 00154 } 00155 00156 00157 00158 int VatRcvr::adapt(Packet *pkt, u_int32_t local_clock) 00159 { 00160 hdr_cmn* ch = hdr_cmn::access(pkt); 00161 register u_int32_t tstamp = (int)ch->timestamp(); 00162 register int hoff = (int)hostoffset_; 00163 register int offset = (tstamp + hoff - local_clock) &~ 3; 00164 hdr_rtp *rh = hdr_rtp::access(pkt); 00165 int new_ts = rh->flags() & RTP_M ; 00166 00167 //struct timeval tv; 00168 //static long int last; 00169 00170 /* printf("%1d %10d %10d\n", new_ts ? 1: 0, tstamp, local_clock);*/ 00171 00172 /* printf("%u\n", tstamp); */ 00173 00174 //gettimeofday(&tv, NULL); 00175 //last = tv.tv_usec - last; 00176 //if (last < 0) 00177 // last += 1000000; 00178 /* 00179 printf("%u %u %u ==> %d\n", tstamp, hoff, local_clock, offset); 00180 printf("%u %d\n", tv.tv_usec, last); 00181 */ 00182 //last = tv.tv_usec; 00183 /* printf("%u ==> %d\n", local_clock, offset); */ 00184 00185 if (hoff == 0 || new_ts) { 00186 /* if (hoff == 0) { */ 00187 00188 /* printf("TS: var = %d playback = %d", var_ >> (VAR_FILTER + 3), 00189 playout_ >> (PLAYO_FILTER + 3)); */ 00190 /* 00191 * start of new talk spurt -- 00192 * use accumulated variance to compute new offset if 00193 * this would make a significant change. We change if 00194 * - the variance is currently 'small', or 00195 * - the change would be a least a packet time 00196 */ 00197 register int nvar = var_ >> (VAR_FILTER - VAR_MULT); 00198 offset = playout_ >> PLAYO_FILTER; 00199 if (nvar < 3*FRAMESIZE || absdiff(nvar, offset) >= FRAMESIZE) { 00200 offset = newoffset(nvar, offset, maxdel_, 00201 block_size_, lecture_mode_); 00202 /* 00203 * assume that a talk spurt starts with TALK_LEAD 00204 * samples of history & subtract them off if possible. 00205 */ 00206 00207 /* CHANGED THIS PART OF VAT CODE AS WELL */ 00208 if (new_ts) { 00209 offset -= 4 * FRAMESIZE; 00210 if (offset < block_size_) 00211 offset = block_size_; 00212 00213 } 00214 } 00215 hostoffset_ = local_clock - tstamp + offset; 00216 /* printf(" new playback = %d\n", offset >> 3); */ 00217 } else if (offset < 0 || offset > maxdel_) { 00218 /* printf("LP: late by %d var = %d playback = %d", (0 - (offset >> 3)), 00219 var_ >> (VAR_FILTER + 3), playout_ >> (PLAYO_FILTER + 3)); */ 00220 /* 00221 * packet out of range -- if last packet also out of 00222 * range or if the delay would increase, resync. 00223 */ 00224 if (offset < 0 || predicted_drop_ == tstamp) { 00225 offset = newoffset(var_ >> (VAR_FILTER - VAR_MULT), 00226 playout_ >> PLAYO_FILTER, 00227 maxdel_, block_size_, 00228 lecture_mode_); 00229 hostoffset_ = local_clock - tstamp + offset; 00230 } else { 00231 /* printf("late packet\n"); */ 00232 predicted_drop_ = tstamp + block_size_; 00233 lastrecv_ = tstamp - local_clock; 00234 count(STAT_LATE); 00235 return (-1); 00236 } 00237 /* printf(" new playback = %d\n", offset >> 3); */ 00238 } else { 00239 // packet in range, update interarrival var. est. 00240 register int nvar = var_; 00241 register int off = tstamp - local_clock - lastrecv_; 00242 /* printf("offset = %3d", off >> 3); */ 00243 if (off < 0) 00244 off = -off; 00245 off -= (nvar >> VAR_FILTER); 00246 var_ = nvar + off; 00247 /* printf(" var = %3d", var_ >> 8); */ 00248 } 00249 lastrecv_ = tstamp - local_clock; 00250 register u_int avgplay = playout_; 00251 playout_ = avgplay + (offset - (avgplay >> PLAYO_FILTER)); 00252 /* printf(" offset = %3d avg playout = %3d", offset >> 3, playout_ >> 8); */ 00253 offset &= ~3; 00254 delvar_ = var_ >> VAR_FILTER; 00255 /* printf("\n"); */ 00256 return (offset); 00257 00258 } 00259 00260 00261 00262 static class VatRcvrClass : public TclClass { 00263 public: 00264 VatRcvrClass() : TclClass("Agent/VatRcvr") {} 00265 TclObject* create(int, const char*const*) { 00266 return (new VatRcvr()); 00267 00268 } 00269 } class_vat_rcvr; 00270 00271 00272 VatRcvr::VatRcvr() : 00273 hostoffset_(0), 00274 var_(INITIAL_OFFSET << (VAR_FILTER - VAR_MULT)), 00275 playout_(INITIAL_OFFSET << PLAYO_FILTER), 00276 maxdel_(8000*6), 00277 block_size_(FRAMESIZE), 00278 lecture_mode_(0), 00279 lastrecv_(0), 00280 predicted_drop_(~0), 00281 nstat_(0) 00282 { 00283 00284 for (int i = 0; i < MAXSTAT; ++i) { 00285 stat_[i].name = 0; 00286 stat_[i].cnt = 0; 00287 } 00288 stat_[STAT_LATE].name = "Late-Pkts"; 00289 nstat_ = 1; 00290 }
1.4.6