Adding a new Matlab tool rtpAnalyze
The purpose of the tool is to analyze the output from the command line tool rtp_analyze. That is, starting with an rtpdump or pcap file, it is processed through rtp_analyze to produce a text output, which is then used as input to this new Matlab function. BUG=2692 TBR=tina.legrand@webrtc.org Review URL: https://webrtc-codereview.appspot.com/47339004 Cr-Commit-Position: refs/heads/master@{#9306}
This commit is contained in:
parent
3b187b9c0c
commit
8051832a9d
203
tools/matlab/rtpAnalyze.m
Normal file
203
tools/matlab/rtpAnalyze.m
Normal file
@ -0,0 +1,203 @@
|
||||
function rtpAnalyze( input_file )
|
||||
%RTP_ANALYZE Analyze RTP stream(s) from a txt file
|
||||
% The function takes the output from the command line tool rtp_analyze
|
||||
% and analyzes the stream(s) therein. First, process your rtpdump file
|
||||
% through rtp_analyze (from command line):
|
||||
% $ out/Debug/rtp_analyze my_file.rtp my_file.txt
|
||||
% Then load it with this function (in Matlab):
|
||||
% >> rtpAnalyze('my_file.txt')
|
||||
|
||||
% Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
|
||||
%
|
||||
% Use of this source code is governed by a BSD-style license
|
||||
% that can be found in the LICENSE file in the root of the source
|
||||
% tree. An additional intellectual property rights grant can be found
|
||||
% in the file PATENTS. All contributing project authors may
|
||||
% be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
|
||||
|
||||
[SeqNo,TimeStamp,ArrTime,Size,PT,M,SSRC] = importfile(input_file);
|
||||
|
||||
%% Find streams
|
||||
[uSSRC, ~, uix] = unique(SSRC);
|
||||
|
||||
if length(uSSRC) > 1
|
||||
for i=1:length(uSSRC)
|
||||
uPT = unique(PT(uix == i));
|
||||
fprintf('%i: %s (%d packets, pt: %i', i, uSSRC{i}, ...
|
||||
length(find(uix==i)), uPT(1));
|
||||
if length(uPT) > 1
|
||||
fprintf(', %i', uPT(2:end));
|
||||
end
|
||||
fprintf(')\n');
|
||||
end
|
||||
sel = input('Select stream number: ');
|
||||
if sel < 1 || sel > length(uSSRC)
|
||||
error('Out of range');
|
||||
end
|
||||
ix = find(uix==sel);
|
||||
SeqNo = SeqNo(ix);
|
||||
TimeStamp = TimeStamp(ix);
|
||||
ArrTime = ArrTime(ix);
|
||||
Size = Size(ix);
|
||||
PT = PT(ix);
|
||||
M = M(ix);
|
||||
SSRC = SSRC(ix);
|
||||
end
|
||||
|
||||
%% Unwrap SeqNo and TimeStamp
|
||||
SeqNoUW = maxUnwrap(SeqNo, 65535);
|
||||
TimeStampUW = maxUnwrap(TimeStamp, 4294967295);
|
||||
|
||||
%% Generate some stats for the stream
|
||||
fprintf('Statistics:\n');
|
||||
fprintf('SSRC: %s\n', SSRC{1});
|
||||
uPT = unique(PT);
|
||||
if length(uPT) > 1
|
||||
warning('This tool cannot yet handle changes in codec sample rate');
|
||||
end
|
||||
fprintf('Payload type(s): %i', uPT(1));
|
||||
if length(uPT) > 1
|
||||
fprintf(', %i', uPT(2:end));
|
||||
end
|
||||
fprintf('\n');
|
||||
fprintf('Packets: %i\n', length(SeqNo));
|
||||
fprintf('Missing sequence numbers: %i\n', ...
|
||||
length(find(diff(sort(SeqNoUW)) > 1)));
|
||||
fprintf('Reordered packets: %i\n', length(find(diff(sort(SeqNoUW)) < 1)));
|
||||
tsdiff = diff(TimeStampUW);
|
||||
tsdiff = tsdiff(diff(SeqNoUW) == 1);
|
||||
[utsdiff, ~, ixtsdiff] = unique(tsdiff);
|
||||
fprintf('Common packet sizes:\n');
|
||||
for i = 1:length(utsdiff)
|
||||
fprintf(' %i samples (%i%%)\n', ...
|
||||
utsdiff(i), ...
|
||||
round(100 * length(find(ixtsdiff==i))/length(ixtsdiff)));
|
||||
end
|
||||
|
||||
%% Trying to figure out sample rate
|
||||
fs_est = (TimeStampUW(end) - TimeStampUW(1)) / (ArrTime(end) - ArrTime(1));
|
||||
fs_vec = [8, 16, 32, 48];
|
||||
fs = 0;
|
||||
for f = fs_vec
|
||||
if abs((fs_est-f)/f) < 0.05 % 5% margin
|
||||
fs = f;
|
||||
break;
|
||||
end
|
||||
end
|
||||
if fs == 0
|
||||
fprintf('Cannot determine sample rate. I get it to %.2f kHz\n', ...
|
||||
fs_est);
|
||||
fs = input('Please, input a sample rate (in kHz): ');
|
||||
else
|
||||
fprintf('Sample rate estimated to %i kHz\n', fs);
|
||||
end
|
||||
|
||||
SendTimeMs = (TimeStampUW - TimeStampUW(1)) / fs;
|
||||
|
||||
fprintf('Stream duration at sender: %.1f seconds\n', ...
|
||||
(SendTimeMs(end) - SendTimeMs(1)) / 1000);
|
||||
|
||||
fprintf('Stream duration at receiver: %.1f seconds\n', ...
|
||||
(ArrTime(end) - ArrTime(1)) / 1000);
|
||||
|
||||
fprintf('Clock drift: %.2f%%\n', ...
|
||||
100 * ((ArrTime(end) - ArrTime(1)) / ...
|
||||
(SendTimeMs(end) - SendTimeMs(1)) - 1));
|
||||
|
||||
fprintf('Sent average bitrate: %i kbps\n', ...
|
||||
round(sum(Size) * 8 / (SendTimeMs(end)-SendTimeMs(1))));
|
||||
fprintf('Received average bitrate: %i kbps\n', ...
|
||||
round(sum(Size) * 8 / (ArrTime(end)-ArrTime(1))));
|
||||
|
||||
%% Plots
|
||||
delay = ArrTime - SendTimeMs;
|
||||
delay = delay - min(delay);
|
||||
figure
|
||||
plot(SendTimeMs / 1000, delay);
|
||||
xlabel('Send time [s]');
|
||||
ylabel('Relative transport delay [ms]');
|
||||
title(sprintf('SSRC: %s', SSRC{1}));
|
||||
|
||||
SendBitrateKbps = 8 * Size(1:end-1) ./ diff(SendTimeMs);
|
||||
figure
|
||||
plot(SendTimeMs(1:end-1)/1000, SendBitrateKbps);
|
||||
xlabel('Send time [s]');
|
||||
ylabel('Send bitrate [kbps]');
|
||||
end
|
||||
|
||||
function [SeqNo,TimeStamp,SendTime,Size,PT,M,SSRC] = ...
|
||||
importfile(filename, startRow, endRow)
|
||||
%IMPORTFILE Import numeric data from a text file as column vectors.
|
||||
% [SEQNO,TIMESTAMP,SENDTIME,SIZE,PT,M,SSRC] = IMPORTFILE(FILENAME) Reads
|
||||
% data from text file FILENAME for the default selection.
|
||||
%
|
||||
% [SEQNO,TIMESTAMP,SENDTIME,SIZE,PT,M,SSRC] = IMPORTFILE(FILENAME,
|
||||
% STARTROW, ENDROW) Reads data from rows STARTROW through ENDROW of text
|
||||
% file FILENAME.
|
||||
%
|
||||
% Example:
|
||||
% [SeqNo,TimeStamp,SendTime,Size,PT,M,SSRC] =
|
||||
% importfile('rtpdump_recv.txt',2, 123);
|
||||
%
|
||||
% See also TEXTSCAN.
|
||||
|
||||
% Auto-generated by MATLAB on 2015/05/28 09:55:50
|
||||
|
||||
%% Initialize variables.
|
||||
if nargin<=2
|
||||
startRow = 2;
|
||||
endRow = inf;
|
||||
end
|
||||
|
||||
%% Format string for each line of text:
|
||||
% column1: double (%f)
|
||||
% column2: double (%f)
|
||||
% column3: double (%f)
|
||||
% column4: double (%f)
|
||||
% column5: double (%f)
|
||||
% column6: double (%f)
|
||||
% column7: text (%s)
|
||||
% For more information, see the TEXTSCAN documentation.
|
||||
formatSpec = '%5f%11f%11f%6f%6f%3f%s%[^\n\r]';
|
||||
|
||||
%% Open the text file.
|
||||
fileID = fopen(filename,'r');
|
||||
|
||||
%% Read columns of data according to format string.
|
||||
% This call is based on the structure of the file used to generate this
|
||||
% code. If an error occurs for a different file, try regenerating the code
|
||||
% from the Import Tool.
|
||||
dataArray = textscan(fileID, formatSpec, endRow(1)-startRow(1)+1, ...
|
||||
'Delimiter', '', 'WhiteSpace', '', 'HeaderLines', startRow(1)-1, ...
|
||||
'ReturnOnError', false);
|
||||
for block=2:length(startRow)
|
||||
frewind(fileID);
|
||||
dataArrayBlock = textscan(fileID, formatSpec, ...
|
||||
endRow(block)-startRow(block)+1, 'Delimiter', '', 'WhiteSpace', ...
|
||||
'', 'HeaderLines', startRow(block)-1, 'ReturnOnError', false);
|
||||
for col=1:length(dataArray)
|
||||
dataArray{col} = [dataArray{col};dataArrayBlock{col}];
|
||||
end
|
||||
end
|
||||
|
||||
%% Close the text file.
|
||||
fclose(fileID);
|
||||
|
||||
%% Post processing for unimportable data.
|
||||
% No unimportable data rules were applied during the import, so no post
|
||||
% processing code is included. To generate code which works for
|
||||
% unimportable data, select unimportable cells in a file and regenerate the
|
||||
% script.
|
||||
|
||||
%% Allocate imported array to column variable names
|
||||
SeqNo = dataArray{:, 1};
|
||||
TimeStamp = dataArray{:, 2};
|
||||
SendTime = dataArray{:, 3};
|
||||
Size = dataArray{:, 4};
|
||||
PT = dataArray{:, 5};
|
||||
M = dataArray{:, 6};
|
||||
SSRC = dataArray{:, 7};
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user