vatrcvr.cc

Go to the documentation of this file.
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 }

Generated on Tue Mar 6 16:47:53 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6