blob: 6da25f6a4d23e9a542f1cd1e485fe2fcd753e552 [file] [log] [blame]
Henrik Lundin80518322015-05-28 12:37:46 +02001function rtpAnalyze( input_file )
2%RTP_ANALYZE Analyze RTP stream(s) from a txt file
3% The function takes the output from the command line tool rtp_analyze
4% and analyzes the stream(s) therein. First, process your rtpdump file
5% through rtp_analyze (from command line):
6% $ out/Debug/rtp_analyze my_file.rtp my_file.txt
7% Then load it with this function (in Matlab):
8% >> rtpAnalyze('my_file.txt')
9
10% Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
11%
12% Use of this source code is governed by a BSD-style license
13% that can be found in the LICENSE file in the root of the source
14% tree. An additional intellectual property rights grant can be found
15% in the file PATENTS. All contributing project authors may
16% be found in the AUTHORS file in the root of the source tree.
17
18
19
20[SeqNo,TimeStamp,ArrTime,Size,PT,M,SSRC] = importfile(input_file);
21
22%% Find streams
23[uSSRC, ~, uix] = unique(SSRC);
24
25if length(uSSRC) > 1
26 for i=1:length(uSSRC)
27 uPT = unique(PT(uix == i));
28 fprintf('%i: %s (%d packets, pt: %i', i, uSSRC{i}, ...
29 length(find(uix==i)), uPT(1));
30 if length(uPT) > 1
31 fprintf(', %i', uPT(2:end));
32 end
33 fprintf(')\n');
34 end
35 sel = input('Select stream number: ');
36 if sel < 1 || sel > length(uSSRC)
37 error('Out of range');
38 end
39 ix = find(uix==sel);
40 SeqNo = SeqNo(ix);
41 TimeStamp = TimeStamp(ix);
42 ArrTime = ArrTime(ix);
43 Size = Size(ix);
44 PT = PT(ix);
45 M = M(ix);
46 SSRC = SSRC(ix);
47end
48
49%% Unwrap SeqNo and TimeStamp
50SeqNoUW = maxUnwrap(SeqNo, 65535);
51TimeStampUW = maxUnwrap(TimeStamp, 4294967295);
52
53%% Generate some stats for the stream
54fprintf('Statistics:\n');
55fprintf('SSRC: %s\n', SSRC{1});
56uPT = unique(PT);
57if length(uPT) > 1
58 warning('This tool cannot yet handle changes in codec sample rate');
59end
60fprintf('Payload type(s): %i', uPT(1));
61if length(uPT) > 1
62 fprintf(', %i', uPT(2:end));
63end
64fprintf('\n');
65fprintf('Packets: %i\n', length(SeqNo));
66fprintf('Missing sequence numbers: %i\n', ...
67 length(find(diff(sort(SeqNoUW)) > 1)));
68fprintf('Reordered packets: %i\n', length(find(diff(sort(SeqNoUW)) < 1)));
69tsdiff = diff(TimeStampUW);
70tsdiff = tsdiff(diff(SeqNoUW) == 1);
71[utsdiff, ~, ixtsdiff] = unique(tsdiff);
72fprintf('Common packet sizes:\n');
73for i = 1:length(utsdiff)
74 fprintf(' %i samples (%i%%)\n', ...
75 utsdiff(i), ...
76 round(100 * length(find(ixtsdiff==i))/length(ixtsdiff)));
77end
78
79%% Trying to figure out sample rate
80fs_est = (TimeStampUW(end) - TimeStampUW(1)) / (ArrTime(end) - ArrTime(1));
81fs_vec = [8, 16, 32, 48];
82fs = 0;
83for f = fs_vec
84 if abs((fs_est-f)/f) < 0.05 % 5% margin
85 fs = f;
86 break;
87 end
88end
89if fs == 0
90 fprintf('Cannot determine sample rate. I get it to %.2f kHz\n', ...
91 fs_est);
92 fs = input('Please, input a sample rate (in kHz): ');
93else
94 fprintf('Sample rate estimated to %i kHz\n', fs);
95end
96
97SendTimeMs = (TimeStampUW - TimeStampUW(1)) / fs;
98
99fprintf('Stream duration at sender: %.1f seconds\n', ...
100 (SendTimeMs(end) - SendTimeMs(1)) / 1000);
101
102fprintf('Stream duration at receiver: %.1f seconds\n', ...
103 (ArrTime(end) - ArrTime(1)) / 1000);
104
105fprintf('Clock drift: %.2f%%\n', ...
106 100 * ((ArrTime(end) - ArrTime(1)) / ...
107 (SendTimeMs(end) - SendTimeMs(1)) - 1));
108
109fprintf('Sent average bitrate: %i kbps\n', ...
110 round(sum(Size) * 8 / (SendTimeMs(end)-SendTimeMs(1))));
111fprintf('Received average bitrate: %i kbps\n', ...
112 round(sum(Size) * 8 / (ArrTime(end)-ArrTime(1))));
113
114%% Plots
115delay = ArrTime - SendTimeMs;
116delay = delay - min(delay);
117figure
118plot(SendTimeMs / 1000, delay);
119xlabel('Send time [s]');
120ylabel('Relative transport delay [ms]');
121title(sprintf('SSRC: %s', SSRC{1}));
122
123SendBitrateKbps = 8 * Size(1:end-1) ./ diff(SendTimeMs);
124figure
125plot(SendTimeMs(1:end-1)/1000, SendBitrateKbps);
126xlabel('Send time [s]');
127ylabel('Send bitrate [kbps]');
128end
129
130function [SeqNo,TimeStamp,SendTime,Size,PT,M,SSRC] = ...
131 importfile(filename, startRow, endRow)
132%IMPORTFILE Import numeric data from a text file as column vectors.
133% [SEQNO,TIMESTAMP,SENDTIME,SIZE,PT,M,SSRC] = IMPORTFILE(FILENAME) Reads
134% data from text file FILENAME for the default selection.
135%
136% [SEQNO,TIMESTAMP,SENDTIME,SIZE,PT,M,SSRC] = IMPORTFILE(FILENAME,
137% STARTROW, ENDROW) Reads data from rows STARTROW through ENDROW of text
138% file FILENAME.
139%
140% Example:
141% [SeqNo,TimeStamp,SendTime,Size,PT,M,SSRC] =
142% importfile('rtpdump_recv.txt',2, 123);
143%
144% See also TEXTSCAN.
145
146% Auto-generated by MATLAB on 2015/05/28 09:55:50
147
148%% Initialize variables.
149if nargin<=2
150 startRow = 2;
151 endRow = inf;
152end
153
154%% Format string for each line of text:
155% column1: double (%f)
156% column2: double (%f)
157% column3: double (%f)
158% column4: double (%f)
159% column5: double (%f)
160% column6: double (%f)
161% column7: text (%s)
162% For more information, see the TEXTSCAN documentation.
163formatSpec = '%5f%11f%11f%6f%6f%3f%s%[^\n\r]';
164
165%% Open the text file.
166fileID = fopen(filename,'r');
167
168%% Read columns of data according to format string.
169% This call is based on the structure of the file used to generate this
170% code. If an error occurs for a different file, try regenerating the code
171% from the Import Tool.
172dataArray = textscan(fileID, formatSpec, endRow(1)-startRow(1)+1, ...
173 'Delimiter', '', 'WhiteSpace', '', 'HeaderLines', startRow(1)-1, ...
174 'ReturnOnError', false);
175for block=2:length(startRow)
176 frewind(fileID);
177 dataArrayBlock = textscan(fileID, formatSpec, ...
178 endRow(block)-startRow(block)+1, 'Delimiter', '', 'WhiteSpace', ...
179 '', 'HeaderLines', startRow(block)-1, 'ReturnOnError', false);
180 for col=1:length(dataArray)
181 dataArray{col} = [dataArray{col};dataArrayBlock{col}];
182 end
183end
184
185%% Close the text file.
186fclose(fileID);
187
188%% Post processing for unimportable data.
189% No unimportable data rules were applied during the import, so no post
190% processing code is included. To generate code which works for
191% unimportable data, select unimportable cells in a file and regenerate the
192% script.
193
194%% Allocate imported array to column variable names
195SeqNo = dataArray{:, 1};
196TimeStamp = dataArray{:, 2};
197SendTime = dataArray{:, 3};
198Size = dataArray{:, 4};
199PT = dataArray{:, 5};
200M = dataArray{:, 6};
201SSRC = dataArray{:, 7};
202end
203