1function [delay_struct, delayvalues] = plot_neteq_delay(delayfile, varargin) 2 3% InfoStruct = plot_neteq_delay(delayfile) 4% InfoStruct = plot_neteq_delay(delayfile, 'skipdelay', skip_seconds) 5% 6% Henrik Lundin, 2006-11-17 7% Henrik Lundin, 2011-05-17 8% 9 10try 11 s = parse_delay_file(delayfile); 12catch 13 error(lasterr); 14end 15 16delayskip=0; 17noplot=0; 18arg_ptr=1; 19delaypoints=[]; 20 21s.sn=unwrap_seqno(s.sn); 22 23while arg_ptr+1 <= nargin 24 switch lower(varargin{arg_ptr}) 25 case {'skipdelay', 'delayskip'} 26 % skip a number of seconds in the beginning when calculating delays 27 delayskip = varargin{arg_ptr+1}; 28 arg_ptr = arg_ptr + 2; 29 case 'noplot' 30 noplot=1; 31 arg_ptr = arg_ptr + 1; 32 case {'get_delay', 'getdelay'} 33 % return a vector of delay values for the points in the given vector 34 delaypoints = varargin{arg_ptr+1}; 35 arg_ptr = arg_ptr + 2; 36 otherwise 37 warning('Unknown switch %s\n', varargin{arg_ptr}); 38 arg_ptr = arg_ptr + 1; 39 end 40end 41 42% find lost frames that were covered by one-descriptor decoding 43one_desc_ix=find(isnan(s.arrival)); 44for k=1:length(one_desc_ix) 45 ix=find(s.ts==max(s.ts(s.ts(one_desc_ix(k))>s.ts))); 46 s.sn(one_desc_ix(k))=s.sn(ix)+1; 47 s.pt(one_desc_ix(k))=s.pt(ix); 48 s.arrival(one_desc_ix(k))=s.arrival(ix)+s.decode(one_desc_ix(k))-s.decode(ix); 49end 50 51% remove duplicate received frames that were never decoded (RED codec) 52if length(unique(s.ts(isfinite(s.ts)))) < length(s.ts(isfinite(s.ts))) 53 ix=find(isfinite(s.decode)); 54 s.sn=s.sn(ix); 55 s.ts=s.ts(ix); 56 s.arrival=s.arrival(ix); 57 s.playout_delay=s.playout_delay(ix); 58 s.pt=s.pt(ix); 59 s.optbuf=s.optbuf(ix); 60 plen=plen(ix); 61 s.decode=s.decode(ix); 62end 63 64% find non-unique sequence numbers 65[~,un_ix]=unique(s.sn); 66nonun_ix=setdiff(1:length(s.sn),un_ix); 67if ~isempty(nonun_ix) 68 warning('RTP sequence numbers are in error'); 69end 70 71% sort vectors 72[s.sn,sort_ix]=sort(s.sn); 73s.ts=s.ts(sort_ix); 74s.arrival=s.arrival(sort_ix); 75s.decode=s.decode(sort_ix); 76s.playout_delay=s.playout_delay(sort_ix); 77s.pt=s.pt(sort_ix); 78 79send_t=s.ts-s.ts(1); 80if length(s.fs)<1 81 warning('No info about sample rate found in file. Using default 8000.'); 82 s.fs(1)=8000; 83 s.fschange_ts(1)=min(s.ts); 84elseif s.fschange_ts(1)>min(s.ts) 85 s.fschange_ts(1)=min(s.ts); 86end 87 88end_ix=length(send_t); 89for k=length(s.fs):-1:1 90 start_ix=find(s.ts==s.fschange_ts(k)); 91 send_t(start_ix:end_ix)=send_t(start_ix:end_ix)/s.fs(k)*1000; 92 s.playout_delay(start_ix:end_ix)=s.playout_delay(start_ix:end_ix)/s.fs(k)*1000; 93 s.optbuf(start_ix:end_ix)=s.optbuf(start_ix:end_ix)/s.fs(k)*1000; 94 end_ix=start_ix-1; 95end 96 97tot_time=max(send_t)-min(send_t); 98 99seq_ix=s.sn-min(s.sn)+1; 100send_t=send_t+max(min(s.arrival-send_t),0); 101 102plot_send_t=nan*ones(max(seq_ix),1); 103plot_send_t(seq_ix)=send_t; 104plot_nw_delay=nan*ones(max(seq_ix),1); 105plot_nw_delay(seq_ix)=s.arrival-send_t; 106 107cng_ix=find(s.pt~=13); % find those packets that are not CNG/SID 108 109if noplot==0 110 h=plot(plot_send_t/1000,plot_nw_delay); 111 set(h,'color',0.75*[1 1 1]); 112 hold on 113 if any(s.optbuf~=0) 114 peak_ix=find(s.optbuf(cng_ix)<0); % peak mode is labeled with negative values 115 no_peak_ix=find(s.optbuf(cng_ix)>0); %setdiff(1:length(cng_ix),peak_ix); 116 h1=plot(send_t(cng_ix(peak_ix))/1000,... 117 s.arrival(cng_ix(peak_ix))+abs(s.optbuf(cng_ix(peak_ix)))-send_t(cng_ix(peak_ix)),... 118 'r.'); 119 h2=plot(send_t(cng_ix(no_peak_ix))/1000,... 120 s.arrival(cng_ix(no_peak_ix))+abs(s.optbuf(cng_ix(no_peak_ix)))-send_t(cng_ix(no_peak_ix)),... 121 'g.'); 122 set([h1, h2],'markersize',1) 123 end 124 %h=plot(send_t(seq_ix)/1000,s.decode+s.playout_delay-send_t(seq_ix)); 125 h=plot(send_t(cng_ix)/1000,s.decode(cng_ix)+s.playout_delay(cng_ix)-send_t(cng_ix)); 126 set(h,'linew',1.5); 127 hold off 128 ax1=axis; 129 axis tight 130 ax2=axis; 131 axis([ax2(1:3) ax1(4)]) 132end 133 134 135% calculate delays and other parameters 136 137delayskip_ix = find(send_t-send_t(1)>=delayskip*1000, 1 ); 138 139use_ix = intersect(cng_ix,... % use those that are not CNG/SID frames... 140 intersect(find(isfinite(s.decode)),... % ... that did arrive ... 141 (delayskip_ix:length(s.decode))')); % ... and are sent after delayskip seconds 142 143mean_delay = mean(s.decode(use_ix)+s.playout_delay(use_ix)-send_t(use_ix)); 144neteq_delay = mean(s.decode(use_ix)+s.playout_delay(use_ix)-s.arrival(use_ix)); 145 146Npack=max(s.sn(delayskip_ix:end))-min(s.sn(delayskip_ix:end))+1; 147nw_lossrate=(Npack-length(s.sn(delayskip_ix:end)))/Npack; 148neteq_lossrate=(length(s.sn(delayskip_ix:end))-length(use_ix))/Npack; 149 150delay_struct=struct('mean_delay',mean_delay,'neteq_delay',neteq_delay,... 151 'nw_lossrate',nw_lossrate,'neteq_lossrate',neteq_lossrate,... 152 'tot_expand',round(s.tot_expand),'tot_accelerate',round(s.tot_accelerate),... 153 'tot_preemptive',round(s.tot_preemptive),'tot_time',tot_time,... 154 'filename',delayfile,'units','ms','fs',unique(s.fs)); 155 156if not(isempty(delaypoints)) 157 delayvalues=interp1(send_t(cng_ix),... 158 s.decode(cng_ix)+s.playout_delay(cng_ix)-send_t(cng_ix),... 159 delaypoints,'nearest',NaN); 160else 161 delayvalues=[]; 162end 163 164 165 166% SUBFUNCTIONS % 167 168function y=unwrap_seqno(x) 169 170jumps=find(abs((diff(x)-1))>65000); 171 172while ~isempty(jumps) 173 n=jumps(1); 174 if x(n+1)-x(n) < 0 175 % negative jump 176 x(n+1:end)=x(n+1:end)+65536; 177 else 178 % positive jump 179 x(n+1:end)=x(n+1:end)-65536; 180 end 181 182 jumps=find(abs((diff(x(n+1:end))-1))>65000); 183end 184 185y=x; 186 187return; 188