User Manual, Developers Guide and API Documentation

VideoTelephony.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002  * This file is part of openWNS (open Wireless Network Simulator)
00003  * _____________________________________________________________________________
00004  *
00005  * Copyright (C) 2004-2007
00006  * Chair of Communication Networks (ComNets)
00007  * Kopernikusstr. 5, D-52074 Aachen, Germany
00008  * phone: ++49-241-80-27910,
00009  * fax: ++49-241-80-22242
00010  * email: info@openwns.org
00011  * www: http://www.openwns.org
00012  * _____________________________________________________________________________
00013  *
00014  * openWNS is free software; you can redistribute it and/or modify it under the
00015  * terms of the GNU Lesser General Public License version 2 as published by the
00016  * Free Software Foundation;
00017  *
00018  * openWNS is distributed in the hope that it will be useful, but WITHOUT ANY
00019  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
00020  * A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00021  * details.
00022  *
00023  * You should have received a copy of the GNU Lesser General Public License
00024  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00025  *
00026  ******************************************************************************/
00027 
00028 #include <APPLICATIONS/session/client/VideoTelephony.hpp>
00029 #include <WNS/distribution/Norm.hpp>
00030 
00031 using namespace applications::session::client;
00032 
00033 STATIC_FACTORY_REGISTER_WITH_CREATOR(applications::session::client::VideoTelephony,
00034                      applications::session::Session,
00035                      "client.VideoTelephony", wns::PyConfigViewCreator);
00036 
00037 VideoTelephony::VideoTelephony(const wns::pyconfig::View& _pyco) :
00038   Session(_pyco),
00039   i(0),
00040   j(0),
00041   limit(1000),
00042   idx (0),
00043 
00044   fracI(0.0),
00045   kI(1),
00046   pI(0.0),
00047   nI(0.0),
00048   dI(1.0),
00049   logNormValueI(0.0),
00050   meanI(0.0),
00051   varianceI(1.0),
00052   yI(0.0),
00053   mI(0.0),
00054   sqrValueI(0.0),
00055 
00056   fracB(0.0),
00057   kB(1),
00058   pB(0.0),
00059   nB(0.0),
00060   dB(1.0),
00061   logNormValueB(0.0),
00062   meanB(0.0),
00063   varianceB(1.0),
00064   yB(0.0),
00065   mB(0.0),
00066   sqrValueB(0.0),
00067 
00068   fracP(0.0),
00069   kP(1),
00070   pP(0.0),
00071   nP(0.0),
00072   dP(1.0),
00073   logNormValueP(0.0),
00074   meanP(0.0),
00075   varianceP(1.0),
00076   yP(0.0),
00077   mP(0.0),
00078   sqrValueP(0.0),
00079 
00080   mean(0.0),
00081   n(0),
00082   distribution(NULL),
00083   logNormDisI(NULL),
00084   logNormDisB(NULL),
00085   logNormDisP(NULL),
00086   distributionValue(0.0),
00087   normMean(0.0),
00088   variance(0.0),
00089 
00090   stateTransitionDistribution(NULL),
00091   cnCounter(0),
00092   bFrameCounter(1),
00093   gopCounter(1),
00094   newGOP(true)
00095 {
00096   wns::pyconfig::View sTVConfig(_pyco, "stateTransition");
00097   std::string sTVName = sTVConfig.get<std::string>("__plugin__");
00098   stateTransitionDistribution = wns::distribution::DistributionFactory::creator(sTVName)->create(sTVConfig);
00099 
00100   settlingTime = _pyco.get<wns::simulator::Time>("settlingTime");
00101 
00102   byteFlag = _pyco.get<bool>("params.byteFlag");
00103 
00104   logMeanI = _pyco.get<double>("params.meanI");
00105   logStdI = _pyco.get<double>("params.stdI");
00106   hurstI = _pyco.get<double>("params.hurstI");
00107   phiI = _pyco.get<double>("params.phiI");
00108   thetaI = _pyco.get<double>("params.thetaI");
00109 
00110   logMeanP = _pyco.get<double>("params.meanP");
00111   logStdP = _pyco.get<double>("params.stdP");
00112   hurstP = _pyco.get<double>("params.hurstP");
00113   phiP = _pyco.get<double>("params.phiP");
00114   thetaP = _pyco.get<double>("params.thetaP");
00115 
00116   logMeanB = _pyco.get<double>("params.meanB");
00117   logStdB = _pyco.get<double>("params.stdB");
00118   hurstB = _pyco.get<double>("params.hurstB");
00119   phiB = _pyco.get<double>("params.phiB");
00120   thetaB = _pyco.get<double>("params.thetaB");
00121 
00122   voicePacketIat = _pyco.get<wns::simulator::Time>("voicePacketIat");
00123   voicePacketSize = _pyco.get<Bit>("voicePacketSize");
00124   /* Packet size includes 12 bytes RTP header. */
00125   voicePacketSize = voicePacketSize + 96;
00126 
00127   comfortNoisePacketSize = _pyco.get<Bit>("comfortNoisePacketSize");
00128   /* Packet size includes 12 bytes RTP header. */
00129   comfortNoisePacketSize = comfortNoisePacketSize + 96;
00130 
00131   comfortNoise = _pyco.get<bool>("comfortNoise");
00132 
00133   MESSAGE_BEGIN(NORMAL, logger, m, "APPL: Starting new session with voiceparameters: ");
00134   m << "voicePacketSize = " << voicePacketSize;
00135   m << ", voicePacketIat = " << voicePacketIat;
00136   m << ", comfortNoisePacketSize = " << comfortNoisePacketSize;
00137   MESSAGE_END();
00138 
00139   videoFrameRate = _pyco.get<int>("params.frameRate");
00140   videoPacketIat = 1 / double(videoFrameRate);
00141 
00142   MESSAGE_BEGIN(NORMAL, logger, m, "APPL: Starting new session with videoparameters: ");
00143   m << "videoFrameRate = " << videoFrameRate;
00144   m << ", videoPacketIat = " << videoPacketIat;
00145   MESSAGE_END();
00146 
00147   calculateSLRangeDependency();
00148 
00149   state = running;
00150 
00151   /* only for probing */
00152   sessionType = videotelephony;
00153 
00154   sessionDelay = (*sessionDelayDistribution)();
00155   MESSAGE_SINGLE(NORMAL, logger, "APPL: Delay before session starts: " << sessionDelay << ".\n");
00156 
00157   setTimeout(connectiontimeout, sessionDelay);
00158   setTimeout(probetimeout, windowSize);
00159 }
00160 
00161 
00162 VideoTelephony::~VideoTelephony()
00163 {
00164   if (stateTransitionDistribution != NULL)
00165     delete stateTransitionDistribution;
00166   stateTransitionDistribution = NULL;
00167 
00168   autocorrI.clear();
00169   phiInew.clear();
00170   phiIold.clear();
00171   xI.clear();
00172 
00173   autocorrB.clear();
00174   phiBnew.clear();
00175   phiBold.clear();
00176   xB.clear();
00177 
00178   autocorrP.clear();
00179   phiPnew.clear();
00180   phiPold.clear();
00181   xP.clear();
00182 }
00183 
00184 void
00185 VideoTelephony::onData(const wns::osi::PDUPtr& _pdu)
00186 {
00187   assureType(_pdu.getPtr(), applications::session::PDU*);
00188 
00189   receivedPacketNumber = static_cast<applications::session::PDU*>(_pdu.getPtr())->getPacketNumber();
00190 
00191   MESSAGE_SINGLE(NORMAL, logger, "APPL: receivedPacketNumber = " << receivedPacketNumber << ".");
00192 
00193   applications::session::Session::incomingProbesCalculation(_pdu);
00194 
00195   if((receivedPacketNumber == 1) && (state != sessionended))
00196     {
00197       /* Voice */
00198       onTimeout(sendtimeout);
00199       voiceState = active;
00200       setTimeout(statetransitiontimeout, 0.02);
00201 
00202       /* Video */
00203       onTimeout(frametimeout);
00204 
00205       state = running;
00206     }
00207 }
00208 
00209 void
00210 VideoTelephony::onTimeout(const Timeout& _t)
00211 {
00212   /* Voice */
00213   if(_t == sendtimeout)
00214     {
00215       MESSAGE_SINGLE(NORMAL, logger, "APPL: Sending voicepacket!");
00216 
00217       applications::session::Session::iatProbesCalculation();
00218 
00219       packetSize = voicePacketSize;
00220 
00221       applications::session::PDU* applicationPDU = new applications::session::PDU(Bit(voicePacketSize), pyco);
00222       applicationPDU->setCreationTime(wns::simulator::getEventScheduler()->getTime());
00223 
00224       ++packetNumber;
00225       applicationPDU->setPacketNumber(packetNumber, packetFrom);
00226       MESSAGE_SINGLE(NORMAL, logger, "APPL: PacketNumber = " << packetNumber << ".");
00227 
00228       wns::osi::PDUPtr pdu(applicationPDU);
00229       applications::session::Session::outgoingProbesCalculation(pdu);
00230 
00231       connection->sendData(pdu);
00232     }
00233   else if(_t == receivetimeout)
00234     {
00235       /* Comfort noise packets will be send to fill the silence */
00236       MESSAGE_SINGLE(NORMAL, logger, "APPL: Sending comfort noise packet!");
00237 
00238       applications::session::Session::iatProbesCalculation();
00239 
00240       packetSize = comfortNoisePacketSize;
00241 
00242       applications::session::PDU* applicationPDU = new applications::session::PDU(Bit(comfortNoisePacketSize), pyco);
00243       applicationPDU->setCreationTime(wns::simulator::getEventScheduler()->getTime());
00244 
00245       ++packetNumber;
00246       applicationPDU->setPacketNumber(packetNumber, packetFrom);
00247       MESSAGE_SINGLE(NORMAL, logger, "APPL: PacketNumber = " << packetNumber << ".");
00248 
00249       wns::osi::PDUPtr pdu(applicationPDU);
00250       applications::session::Session::outgoingProbesCalculation(pdu);
00251 
00252       connection->sendData(pdu);
00253     }
00254   else if(_t == statetransitiontimeout)
00255     {
00256       /* Transition between active (speech) state and inactive (silent/pause) state. */
00257       double stateTransitionValue = (*stateTransitionDistribution)();
00258 
00259       MESSAGE_SINGLE(NORMAL, logger, "APPL: State transition. TransitionValue = " << stateTransitionValue << ".");
00260 
00261       if(stateTransitionValue <= 0.01 && voiceState == inactive)
00262     {
00263       cnCounter = 0;
00264       onTimeout(sendtimeout);
00265 
00266       voiceState = active;
00267     }
00268       else if(stateTransitionValue > 0.01 && voiceState == inactive)
00269     {
00270       if(cnCounter == 8)
00271         {
00272           cnCounter = 1;
00273           onTimeout(receivetimeout);
00274         }
00275       else
00276         {
00277           cnCounter += 1;
00278         }
00279     }
00280       else if(stateTransitionValue <= 0.01 && voiceState == active)
00281     {
00282       cnCounter = 1;
00283       onTimeout(receivetimeout);
00284 
00285       voiceState = inactive;
00286     }
00287       else if(stateTransitionValue > 0.01 && voiceState == active)
00288     {
00289       onTimeout(sendtimeout);
00290     }
00291 
00292       setTimeout(statetransitiontimeout, 0.02);
00293     }
00294   /* Video */
00295   else if(_t == frametimeout)
00296     {
00297       if(newGOP == false)
00298     {
00299       if(bFrameCounter <= 2)
00300         {
00301           /* B-Frame */
00302           MESSAGE_SINGLE(NORMAL, logger, "APPL: B-FRAME!");
00303 
00304           bFrameCounter += 1;
00305 
00306           setTimeout(frametimeout, videoPacketIat);
00307 
00308           logNormalProjectedFarima(xB, phiBold, yB, phiB, thetaB, mB, sqrValueB,
00309                        varianceB, kB, logMeanB, logStdB);
00310         }
00311       else
00312         {
00313           /* P-Frame */
00314           bFrameCounter = 1;
00315 
00316           if(gopCounter < 4)
00317         {
00318           MESSAGE_SINGLE(NORMAL, logger, "APPL: P-FRAME!");
00319 
00320           logNormalProjectedFarima(xP, phiPold, yP, phiP, thetaP, mP, sqrValueP,
00321                        varianceP, kP, logMeanP, logStdP);
00322 
00323           gopCounter += 1;
00324           setTimeout(frametimeout, videoPacketIat);
00325         }
00326           else
00327         {
00328           gopCounter = 1;
00329           newGOP = true;
00330           onTimeout(frametimeout);
00331         }
00332         }
00333     }
00334       else
00335     {
00336       /* I-Frame */
00337       MESSAGE_SINGLE(NORMAL, logger, "APPL: I-FRAME!");
00338 
00339       VideoTelephony::logNormalProjectedFarima(xI, phiIold, yI, phiI, thetaI, mI, sqrValueI,
00340                            varianceI, kI, logMeanI, logStdI);
00341 
00342       newGOP = false;
00343       setTimeout(frametimeout, videoPacketIat);
00344     }
00345     }
00346   else if(_t == connectiontimeout)
00347     {
00348       packetFrom = "client.VideoTelephony";
00349 
00350       /* Open connection */
00351       binding->initBinding();
00352     }
00353   else if(_t == probetimeout)
00354     {
00355       applications::session::Session::onTimeout(_t);
00356     }
00357   else if(_t == calltimeout)
00358     {
00359       /* Start with calling the server. */
00360       applications::session::PDU* applicationPDU = new applications::session::PDU(Bit(comfortNoisePacketSize), pyco);
00361       applicationPDU->setCreationTime(wns::simulator::getEventScheduler()->getTime());
00362 
00363       packetSize = comfortNoisePacketSize;
00364 
00365       packetNumber = 1;
00366       applicationPDU->setPacketNumber(packetNumber, packetFrom);
00367       MESSAGE_SINGLE(NORMAL, logger, "APPL: PacketNumber = " << packetNumber << ".");
00368 
00369       wns::osi::PDUPtr pdu(applicationPDU);
00370       applications::session::Session::outgoingProbesCalculation(pdu);
00371 
00372       connection->sendData(pdu);
00373 
00374       state = idle;
00375     }
00376   else
00377     {
00378       assure(false, "APPL: Unknown timout type =" << _t);
00379     }
00380 }
00381 
00382 
00383 void
00384 VideoTelephony::onConnectionEstablished(wns::service::tl::Connection* _connection)
00385 {
00386   /* Connection is ready, so start sending after session start delay. */
00387   connection = _connection;
00388   establishedAt = wns::simulator::getEventScheduler()->getTime();
00389 
00390   MESSAGE_SINGLE(NORMAL, logger, "APPL: Connection established!");
00391 
00392   onTimeout(calltimeout);
00393 }
00394 
00395 
00396 void
00397 VideoTelephony::calculateSLRangeDependency()
00398 {
00399   /* Callculation of the short- and longrangedependencies.
00400      For detailed discription see diplomathesis of Cem Mengi 10.07.2006:
00401      "Conception and implementation of traffic Models for VoIP and Videotelephony". */
00402   MESSAGE_SINGLE(NORMAL, logger, "APPL: Callculation of the short- and longrange dependencies!");
00403 
00404   fracI = hurstI - 0.5;
00405   fracP = hurstP - 0.5;
00406   fracB = hurstB - 0.5;
00407 
00408   autocorrI.push_back(1.0);
00409   autocorrP.push_back(1.0);
00410   autocorrB.push_back(1.0);
00411 
00412   /* This distribution is just used one time and deleted after that.
00413      Next time a new distribution is used.*/
00414   logNormDisI = new wns::distribution::Norm(meanI, varianceI);
00415   logNormValueI = (*logNormDisI)();
00416   xI.push_back(logNormValueI);
00417 
00418   logNormDisP = new wns::distribution::Norm(meanP, varianceP);
00419   logNormValueP = (*logNormDisP)();
00420   xP.push_back(logNormValueP);
00421 
00422   logNormDisB = new wns::distribution::Norm(meanB, varianceB);
00423   logNormValueB = (*logNormDisB)();
00424   xB.push_back(logNormValueB);
00425 
00426   delete logNormDisI;
00427   logNormDisI = NULL;
00428 
00429   delete logNormDisP;
00430   logNormDisP = NULL;
00431 
00432   delete logNormDisB;
00433   logNormDisB = NULL;
00434 
00435   for(i = 1; i < limit; i++)
00436     {
00437       autocorrI.push_back(autocorrI[i - 1] * ((static_cast<float>(i - 1) + fracI)/ (static_cast<float>(i) - fracI)));
00438       autocorrP.push_back(autocorrP[i - 1] * ((static_cast<float>(i - 1) + fracP)/ (static_cast<float>(i) - fracP)));
00439       autocorrB.push_back(autocorrB[i - 1] * ((static_cast<float>(i - 1) + fracB)/ (static_cast<float>(i) - fracB)));
00440 
00441       pI = 0;
00442       pP = 0;
00443       pB = 0;
00444 
00445       for(j = 1; j <= (i-1); j++)
00446     {
00447       pI = pI + phiIold[j - 1] * autocorrI[i - j];
00448       pP = pP + phiPold[j - 1] * autocorrP[i - j];
00449       pB = pB + phiBold[j - 1] * autocorrB[i - j];
00450     }
00451 
00452       dI = dI - ((nI * nI) / dI);
00453       nI = autocorrI[i] - pI;
00454       dP = dP - ((nP * nP) / dP);
00455       nP = autocorrP[i] - pP;
00456       dB = dB - ((nB * nB) / dB);
00457       nB = autocorrB[i] - pB;
00458 
00459       phiInew.push_back(nI / dI);
00460       phiPnew.push_back(nP / dP);
00461       phiBnew.push_back(nB / dB);
00462 
00463       idx = i;
00464 
00465       meanI = phiInew[0] * xI[0];
00466       meanP = phiPnew[0] * xP[0];
00467       meanB = phiBnew[0] * xB[0];
00468 
00469       for(idx = i; idx > 1; idx--)
00470     {
00471 
00472       phiInew.push_front(phiIold[idx - 2] - (phiInew[i - idx] * phiIold[i - idx]));
00473       phiPnew.push_front(phiPold[idx - 2] - (phiPnew[i - idx] * phiPold[i - idx]));
00474       phiBnew.push_front(phiBold[idx - 2] - (phiBnew[i - idx] * phiBold[i - idx]));
00475 
00476       meanI = meanI + (phiInew[0] * xI[i - idx + 1]);
00477       meanP = meanP + (phiPnew[0] * xP[i - idx + 1]);
00478       meanB = meanB + (phiBnew[0] * xB[i - idx + 1]);
00479 
00480     }
00481 
00482       varianceI = (1 - pow(phiInew[i - 1], 2)) * varianceI;
00483       varianceP = (1 - pow(phiPnew[i - 1], 2)) * varianceP;
00484       varianceB = (1 - pow(phiBnew[i - 1], 2)) * varianceB;
00485 
00486       /* This distribution is just used one time and deleted after that.
00487      Next time a new distribution is used.*/
00488       logNormDisI = new wns::distribution::Norm(meanI, varianceI);
00489       logNormValueI = (*logNormDisI)();
00490       xI.push_back(logNormValueI);
00491 
00492       logNormDisP = new wns::distribution::Norm(meanP, varianceP);
00493       logNormValueP = (*logNormDisP)();
00494       xP.push_back(logNormValueP);
00495 
00496       logNormDisB = new wns::distribution::Norm(meanB, varianceB);
00497       logNormValueB = (*logNormDisB)();
00498       xB.push_back(logNormValueB);
00499 
00500       phiIold.clear();
00501       phiPold.clear();
00502       phiBold.clear();
00503       phiIold = phiInew;
00504       phiPold = phiPnew;
00505       phiBold = phiBnew;
00506       phiInew.clear();
00507       phiPnew.clear();
00508       phiBnew.clear();
00509 
00510       delete logNormDisI;
00511       logNormDisI = NULL;
00512 
00513       delete logNormDisP;
00514       logNormDisP = NULL;
00515 
00516       delete logNormDisB;
00517       logNormDisB = NULL;
00518 
00519     }
00520 
00521   xI.pop_front();
00522   xP.pop_front();
00523   xB.pop_front();
00524 
00525   autocorrI.clear();
00526   autocorrP.clear();
00527   autocorrB.clear();
00528 }
00529 
00530 
00531 void
00532 VideoTelephony::logNormalProjectedFarima(std::deque<double> _x, std::deque<double> _phiold, double _y,
00533                      double _phi, double _theta, double _m, double _sqrValue,
00534                      double _variance, int _k, double _logMean, double _logStd)
00535 {
00536   mean = 0;
00537   n = 0;
00538   while(n < limit - 1)
00539     {
00540       mean = mean + _x[n] * _phiold[limit - n - 2];
00541 
00542       n = n + 1;
00543     }
00544   _variance = (1 - pow(_phiold[limit - 2], 2)) * _variance;
00545 
00546   distribution = new wns::distribution::Norm(mean, _variance);
00547   distributionValue = (*distribution)();
00548   _x.push_back(distributionValue);
00549 
00550   _y = _x[limit - 1];
00551 
00552   _m = _m + _y;
00553 
00554   _sqrValue = _sqrValue + pow(_y, 2);
00555 
00556   normMean = _m / static_cast<int>((float)(_k + 1));
00557 
00558   variance = (_sqrValue - (pow(_m, 2) / static_cast<int>((float)(_k + 1)))) / static_cast<int>((float)(_k));
00559 
00560   packetSize = exp(_logMean + (_logStd * ((_y - normMean) / sqrt(variance)))) + 1;
00561 
00562   if(byteFlag == true)
00563     {
00564       packetSize *= 8.0;
00565     }
00566 
00567   _x.pop_front();
00568   _k = _k + 1;
00569 
00570   delete distribution;
00571   distribution = NULL;
00572 
00573   applications::session::PDU* applicationPDU = new applications::session::PDU(Bit(packetSize), pyco);
00574   applicationPDU->setCreationTime(wns::simulator::getEventScheduler()->getTime());
00575 
00576   ++packetNumber;
00577   applicationPDU->setPacketNumber(packetNumber, packetFrom);
00578   MESSAGE_SINGLE(NORMAL, logger, "APPL: PacketNumber = " << packetNumber << ".");
00579 
00580   wns::osi::PDUPtr pdu(applicationPDU);
00581   applications::session::Session::outgoingProbesCalculation(pdu);
00582 
00583   connection->sendData(pdu);
00584 }

Generated on Sun May 27 03:32:16 2012 for openWNS by  doxygen 1.5.5