vquality_g711.pl
上传用户:wzkunzhan
上传日期:2022-04-23
资源大小:2618k
文件大小:13k
源码类别:

模拟服务器

开发平台:

Visual C++

  1. # File: vquality_g711.pl
  2. #
  3. # Modified OpenPhone based Voice Evaluation Tool (MOBVET) Version 0.1
  4. # --------------------------------------------------------------------
  5. # Voice Over IP Laboratory (http://www.voip.nce.ufrj.br)
  6. # Federal University of Rio de Janeiro
  7. # Copyright (c) 2002-2004 UFRJ (Federal University of Rio de Janeiro).
  8. # The contents of this file are subject to the Mozilla Public License
  9. # Version 1.0 (the "License"); you may not use this file except in
  10. # compliance with the License. You may obtain a copy of the License at
  11. # http://www.mozilla.org/MPL/
  12. # Versao de 10/11/2003 - Leandro
  13. # Versao de 11/11/2003 - Leandro
  14. # Modificacao no codigo para considerar perda de pacotes por "buffer full" 
  15. # Versao de 12/03/2004 - Leandro
  16. # Modificado para considerar tempo de dejitter_buffer como max_time/2
  17. use Emodel;
  18. #Definindo Codec como G711
  19. VoIP::Emodel->setIe(0);
  20. VoIP::Emodel->setBpl(25.1);
  21. $CODEC = "G711";
  22. $pasta = ".";
  23. my $dir = "side?.H323";
  24. #my $dir = "sideA.H323";
  25. my $linha;
  26. print "Processing the trace files...n";
  27. chdir $pasta;
  28. open DIR, "dir /b $dir |";
  29. #open DIR, "ls $dir |";
  30. my @arqs = <DIR>;
  31. foreach $linha (@arqs) {
  32. #print "Processing file: $linha";
  33. ($nome_arq, $ext_arq) = split("H",$linha);
  34. $log_vql = $nome_arq . "vql";
  35. $log_ppl = $nome_arq . "ppl";
  36. $log_mos = $nome_arq . "mos";
  37. #print "File PPL Nanme: $log_ppln";
  38. emodel($log_ppl);
  39. markov_chain($linha);
  40. }
  41. close DIR;
  42. sub emodel {
  43. $log_ppl = shift;
  44. open(LOG_PPL, $log_ppl) or die "CAnnot open file $log_ppln";
  45. foreach $line (<LOG_PPL>) {
  46. push(@emodel_array,$line);
  47. }
  48. close(LOG_PPL);
  49. }
  50. # Recebe string no formato "mm:ss.xxxx <lixo>" ou "hh:mm:ss.xxxx <lixo>" e converte para milisegundos
  51. sub converte_para_Milisegundos
  52. {
  53.         my $arg = shift;
  54.         if ($arg =~ /(d*):(d*):(d*).(d*)/o ) {
  55.                 return ( (($1*3600)+$2*60+$3)*1000 +$4 );
  56.         } elsif ($arg =~ /(d*):(d*).(d*)/o ) {
  57.                 return ( (($1*60)+$2)*1000 +$3 );
  58.         }
  59.         printf ("Parametro Invalido: %sn", $arg);
  60. }
  61. # Recebe valor em milisegundos e converte para string no formato "mm:ss.xxxx" ou "hh:mm:ss.xxxx" 
  62. sub ms
  63. {
  64. my $arg = shift;
  65. my ($h, $r, $m, $s, $ms);
  66. $h = int ($arg / 3600000);
  67. $r = $arg % 3600000;
  68. $m = int ($r / 60000);
  69. $r = $r % 60000;
  70. $s = int ($r / 1000); 
  71. $ms = $r % 1000;
  72. if ($h > 0) {
  73. return (sprintf("%d:%02d:%02d.%03d",$h,$m,$s,$ms));
  74. } else {
  75. return (sprintf("%d:%02d.%03d",$m,$s,$ms));
  76. }
  77. }
  78. sub markov_chain {
  79. my $arquivo = shift;
  80. my $status_old;
  81. my $time_old;
  82. $e = exp(1);
  83. $pkt = 0;   # contador de pacotes recebidos
  84. $lost = 0;  # contador de pacotes perdidos
  85. $gmin = 16; # tamanho do gap m�imo, normalmente 16
  86. $c5 = 0;    # utilizaco para calcular o tempo passado desde o ultimo burst significativo de perdas 
  87. $c14 = 0;
  88. $c13 = 0;
  89. $c11 = 0;
  90. $c33 = 0;
  91. $c23 = 0;
  92. $c22 = 0;
  93. $F = 0.03; # tamanho de frame e segundos do g711 - 1 frame per packet
  94.  
  95. # #Valores para G.723.1 6.3k + VAD
  96. # $d1 = 4.25;
  97. # $d2 = 4.8;
  98. # $d3 = 12;
  99. # $d4 = 1.75;
  100. $IeCODEC = 0;
  101. $t1 = 5;
  102. $t2 = 15;
  103. $i = 0; 
  104. ($time_emodel, $rtt, $psent, $plost, $too_late, $jitter, $buffer_size) = split(" ",shift(@emodel_array));
  105. open (LOG_VQL, ">$log_vql");
  106. open(LOG_H323, $arquivo) or die "lendo arquivo $arquivo";
  107. foreach $line (<LOG_H323>) {
  108. if ($line =~ /(.*)RTP Jitter:.*Receive statistics:.*packets=(d*).*octets=(d*).*tooLate=(d*)/o ) {
  109. $status = "received";
  110. $time = ms (converte_para_Milisegundos($1));
  111. if ($status_old eq "received") {
  112.  #print "n-> PACKET RECEIVED: $time_old -----------------------------------------n";
  113.  receive_event();
  114.  
  115.  
  116. }
  117. }elsif ($line =~ /(.*)RTP Jitter:.*Droppeds(d*)s/o ){
  118. $status = "dropped";
  119. $time = ms (converte_para_Milisegundos($1));
  120. $dropped = $2;
  121. #Considera pacotes multiframe 
  122. for ($i = 0; $i < $dropped ; $i++) {
  123. #print "n-> PACKET LOST: $time ---------------------------------------------n";
  124. loss_event();
  125. }
  126. }elsif ($line =~ /(.*)Jitter buffer oldest packet.*too late/o ){
  127.  
  128.   $status = "late";
  129. $time = ms (converte_para_Milisegundos($1));
  130. if ($status_old eq "received") {
  131. #print "n-> PACKET TOO LATE: $time_old ------------------------------------------n";
  132. loss_event();
  133. }
  134. # 2:33.566      RTP Jitter:80786e0 RTP Jitter buffer full, throwing away oldest frame (31920)
  135. }elsif ($line =~ /(.*)Jitter buffer full, throwing away oldest frame/o ){
  136. $status = "late";
  137. $time = ms (converte_para_Milisegundos($1));
  138. if ($status_old eq "received") {
  139. #print "n-> BUFFER FULL: $time_old ------------------------------------------n";
  140. loss_event();
  141. }
  142. }elsif($line =~ /(.*)SentReceiverReport:s*ssrc=(d*)s*fraction=(d*)s*lost=(d*)s*last_seq=(d*)s*jitter=(d*)s*lsr=(d*)s*dlsr=(d*)/o ) {
  143. $time = ms (converte_para_Milisegundos($1));
  144. if ($time == $time_emodel) {
  145. calcula_markov();
  146. $ta = onewaydelay($rtt,$CODEC,$buffer_size);
  147. VoIP::Emodel->setTa($ta);
  148. if ($psent != 0){
  149. VoIP::Emodel->setPpl(($plost + $too_late ) / $psent);
  150. }
  151. else {
  152. #Caso nenhum pacote tenha sido enviado
  153. VoIP::Emodel->setPpl(0);
  154. }
  155. #print ("Ppl: ",VoIP::Emodel->getPpl(),"  Bpl: ",VoIP::Emodel->getBpl(), " Ie: ",VoIP::Emodel->getIe(), "n");
  156. $r_emodel = VoIP::Emodel->r();
  157. $ie_emodel = VoIP::Emodel->getIeef();
  158. $id_emodel = VoIP::Emodel->getId();
  159. $mos_emodel = VoIP::Emodel->mos(VoIP::Emodel->r());
  160. $id_emodel_ext = $id_emodel; #ler o artigo outra vez para ajustar o valor de id
  161. $r_emodel_ext = $R - $id_emodel_ext;
  162. #print "$R $r_emodel_ext $id_emodel_extn";
  163. if ($r_emodel_ext < 0 ) {
  164. #nao deixa o r do emodel extendido ficar negativo
  165. $r_emodel_ext = 0;
  166. #print LOG_VQL ($time_emodel," ",$ie_emodel," ",$id_emodel," ",$r_emodel," ",$mos_emodel," ",$IeTotal," ",$id_emodel_ext," ",$r_emodel_ext," ",VoIP::Emodel->mos($r_emodel_ext)," ",$I1," ",$I2," ",$Ieav,"n");
  167. print LOG_VQL ($time_emodel," ",$ie_emodel," ",$id_emodel," ",$r_emodel," ",$mos_emodel," ",$IeTotal," ",$id_emodel_ext," ",$r_emodel_ext," ",VoIP::Emodel->mos($r_emodel_ext),"n");
  168. ($time_emodel, $lixo, $psent, $plost, $too_late, $jitter, $buffer_size) = split(" ",shift(@emodel_array));
  169. # a variavel lixo eh utilizada para nao se atualizar o rtt
  170. # o owd eh calculado sempre em relacao ao primeiro rtt calculado
  171. # o que varia eh o tamaho do buffer de compensacao de jitter
  172. }
  173. }
  174. $status_old = $status;
  175. $time_old = $time;
  176. }
  177. # calculo do MOS final da ligacao
  178. $Ie_end = $Ieav + (0.7 * ($I1 - $Ieav)) * $e ** (-$y/30);
  179. #Verificar como adicionar Id no R final da ligacao
  180. $R = 93.36 -  $Ie_end - $IeCODEC - $id_emodel_ext;
  181. #print "###########################################################n";
  182. #print "AVALIACAO FINAL DA LIGACAOn";
  183. #print "Ie(End of call) = $Ie_endn";
  184. #print "R-Factod(End of call) = $Rn";
  185. #print "MOS(End of call)  = ", mos($R),"n";
  186. open (LOG_MOS, ">$log_mos");
  187. print LOG_MOS (VoIP::Emodel->mos($R),"n");
  188. close (LOG_MOS);
  189. close(LOG_H323);
  190. close(LOG_VQL);
  191. }
  192. sub receive_event {
  193. # evento de recepcao de pacote
  194. $pkt++;
  195. }
  196. sub loss_event {
  197. # evento de perda de pacote
  198. $c5 = $c5 + $pkt;
  199. if ($pkt >= $gmin) {
  200.                 if ($lost == 1) {
  201.                
  202.                 $c14++;
  203.                 }
  204.                 else {
  205.                
  206.                 $c13++;
  207.                 }
  208.                
  209.                 $lost = 1;
  210.                 $c11 = $c11 + $pkt;
  211.         }
  212.         else {
  213.       
  214.       
  215.                 $lost++;
  216.                 if ($lost > 8) {
  217.                 
  218.                      $c5 = 0;
  219.                 }
  220.                 if( $pkt == 0) {
  221.                 $c33++;
  222. }
  223. else {
  224.                  $c23++;
  225.                  $c22 = $c22 + $pkt;
  226. }
  227. }
  228. $pkt = 0;
  229. }
  230. sub calcula_markov {
  231. $c31 = $c13;
  232. $c32 = $c23;
  233. if ( ($c11 + $c14 + $c13) == 0 ) {
  234. $p11 = 0;
  235. $p13 = 0;
  236. }
  237. else {
  238. $p11 = ( $c11 + $c14 ) / ( $c11 + $c14 + $c13);
  239. $p13 = $c13 / ( $c11 + $c14 + $c13);
  240. }
  241. #$p13 = 1 - $p11;
  242. if ( ( $c31 + $c32 + $c33) ==0 ) {
  243. $p31 = 0;
  244. $p32 = 0;
  245. $p33 = 0;
  246. }
  247. else {
  248. $p31 = $c31 / ( $c31 + $c32 + $c33);
  249. $p32 = $c32 / ( $c31 + $c32 + $c33);
  250. #$p33 = 1 - $p31 - $p32;
  251. $p33 = $c33 / ( $c31 + $c32 + $c33);
  252. }
  253. if ( ($c22 + $c23) == 0 ) {
  254. $p22 = 0;
  255. $p23 = 0;
  256. } else {
  257. $p22 = $c22 / ( $c22 + $c23 );
  258. $p23 = $c23 / ( $c22 + $c23 );
  259. }
  260. #$p23 = 1- $p22;
  261. $d = ($p23 * $p31 + $p13 * $p32 + $p13 * $p23);
  262. if ($d == 0) {
  263. $p1 = 0;
  264. $p2 = 0;
  265. $p3 = 0;
  266. }
  267. else {
  268. $p1 = ($p31 * $p23) / $d;
  269. $p2 = ($p13 * $p32) / $d;
  270. $p3 = ($p13 * $p23) / $d;
  271. }
  272. $L = 100 * $p3; # porcentagem media da taxa de pacotes perdidos
  273. $y = $F * $c5; # tempo passado desde o ultimo burst significativo de perdas em segundos
  274. if ( $p11 == 1) { 
  275. # significa que nao apareceu burst
  276. $g = $y;
  277. }else{
  278. $g = $F / ( 1 - $p11); # tamanho do gap em segundos
  279. }
  280. if ($c11 == 0) {
  281. $Dg = 0;
  282. }
  283. else {
  284. $Dg = 100 *  $c14 / ( $c11 + $c14); #densidade de perda no gap (porcentagem)
  285. }
  286. if ( ($p1 * $p13) == 0 ) {
  287. $b = 0;
  288. }
  289. else {
  290. $b = ( $F * (1 - $p1) ) / ( $p1 * $p13); # tamanho do burst em segundos
  291. }
  292. if ( ($p23 + $p32) == 0 ) {
  293. $Db = 0;
  294. }
  295. else {
  296. $Db = 100 * $p23 / ($p23 + $p32); # densidade de perda no burs (porcentagem)
  297. }
  298. # Ao meu ver, esta forma de calcular Db estah errada
  299. #$Db = 100 * $p23;
  300. #print "Average packet loss rate = $L %n";
  301. #print "Gap Length  = $g seg.n";
  302. #print "Gap loss density = $Dg %n";
  303. #print "Burst length = $b seg.n";
  304. #print "Burst loss density = $Db %n";
  305. #print "Delay since last burst = $y seg.n";
  306. # if ($Dg < 0.5) {
  307. #
  308. # $Ieg = 0;
  309. #
  310. # }
  311. # elsif ( (0.5 < $Dg) && ($Dg < $d2) ) {
  312. #
  313. # $Ieg = $d1 * $Dg;
  314. #
  315. # }
  316. # elsif ($d2 < $Dg) {
  317. #
  318. # $Ieg = $d3 + $d4 * $Dg;
  319. #
  320. # }
  321. #
  322. # if ($Db < 0.5) {
  323. #
  324. # $Ieb = 0;
  325. #
  326. # }
  327. # elsif ( (0.5 < $Db) && ($Db < $d2) ) {
  328. #
  329. #
  330. # $Ieb = $d1 * $Db;
  331. # }
  332. # elsif ($d2 < $Db) {
  333. #
  334. #
  335. # $Ieb = $d3 + $d4 * $Db;
  336. # }
  337. #
  338. VoIP::Emodel->setPpl($Dg/100);
  339. VoIP::Emodel->r();
  340. $Ieg = VoIP::Emodel->getIeef();
  341. VoIP::Emodel->setPpl($Db/100);
  342. VoIP::Emodel->r();
  343. $Ieb = VoIP::Emodel->getIeef();
  344. #print "Dg = $Dgn";
  345. #print "Db = $Dbn";
  346. #print "Ieg = $Iegn";
  347. #print "Ieb = $Iebn";
  348. if ( (1 - $e ** (-$b/$t1 - $g/$t2)) == 0) {
  349. $I2 = 0;
  350. }
  351. else {
  352. $I2 = ( $Ieg * ( 1 - $e ** (-$g /$t2)) + $Ieb * ( 1 - $e** (-$b/$t1)) * $e ** (-$g/$t2)) / (1 - $e ** (-$b/$t1 - $g/$t2) );
  353. }
  354. #$I1 = $Ieb - ($Ieg - $I2) * $e ** (-$b/$t1);
  355. $I1 = $Ieb - ($Ieb - $I2) * $e ** (-$b/$t1); # Our considerations
  356. $Ieav = ($b * $Ieb + $g * $Ieg - $t1 * ($Ieb - $I2) * (1 - $e ** (-$b/$t1)) + $t2 * ($I1 - $Ieg) * (1 - $e ** (- $g/$t2)) ) / ($b + $g);
  357. #print "I1 = $I1n";
  358. #print "I2 = $I2n";
  359. #print "g = $gn";
  360. #print "b = $bn";
  361. #print "Ie(av) = $Ieavn";
  362. $R = 94 -  $Ieav - $IeCODEC;
  363. $IeTotal = $Ieav + $IeCODEC;
  364. if ($IeTotal > 100) {
  365. #nao deixa o ietotal ser negativo 
  366. $IeTotal = 100;
  367. }
  368. #print "R-factior = $Rn";
  369. #print "MOS = ", mos($R),"  at  $time n";
  370. }
  371. sub onewaydelay
  372. #Parametros (rtt, codec, playoutbuffer)
  373. #Calcula o On Way Delay, tambe'm chamado de Absolute Delay (Ta).
  374. #Ta = RTT/2 + tempo de codificacao (dependente do codec utilizado) + tempo de playout buffer (fixo)
  375. {
  376. my $rtt = shift;
  377. my $codec = shift;
  378. my $plbuffer = shift;
  379. my $codec_time = 0;
  380. #confirmar tempo de codificacao
  381. $plbuffer = $plbuffer/2; #codecao do dejitter_buffer como max_time/2
  382. if ($codec eq "G711") { $codec_time = 0.25}
  383. elsif ($codec eq "GSM") { $codec_time = 40}
  384. elsif ($codec eq "G729") { $codec_time = 25}
  385. elsif ($codec eq "G723") { $codec_time = 157.5} #4 frames por pacote no caso do openam # ver g.114
  386. #considerando link de alta velocidade (melhor caso)
  387. #elsif ($codec eq "G723") { $codec_time = 277.5} #4 frames por pacote no caso do openam # ver g.114
  388. #considerando link de baixa velocidade (pior caso)
  389. #$a = ($rtt/2) + $plbuffer + $codec_time;
  390. #print "rtt= $rtt, buffer= $plbuffer, codec= $codec_time, total= $an";
  391. return ($rtt/2) + $plbuffer + $codec_time;
  392. }