diff --git a/tools/matlab/rtpAnalyze.m b/tools/matlab/rtpAnalyze.m new file mode 100644 index 0000000000..6da25f6a4d --- /dev/null +++ b/tools/matlab/rtpAnalyze.m @@ -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 +