1%
2%  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3%
4%  Use of this source code is governed by a BSD-style license
5%  that can be found in the LICENSE file in the root of the source
6%  tree. An additional intellectual property rights grant can be found
7%  in the file PATENTS.  All contributing project authors may
8%  be found in the AUTHORS file in the root of the source tree.
9%
10
11function outStruct = parse_delay_file(file)
12
13fid = fopen(file, 'rb');
14if fid == -1
15    error('Cannot open file %s', file);
16end
17
18textline = fgetl(fid);
19if ~strncmp(textline, '#!NetEQ_Delay_Logging', 21)
20    error('Wrong file format');
21end
22
23ver = sscanf(textline, '#!NetEQ_Delay_Logging%d.%d');
24if ~all(ver == [2; 0])
25    error('Wrong version of delay logging function')
26end
27
28
29start_pos = ftell(fid);
30fseek(fid, -12, 'eof');
31textline = fgetl(fid);
32if ~strncmp(textline, 'End of file', 21)
33    error('File ending is not correct. Seems like the simulation ended abnormally.');
34end
35
36fseek(fid,-12-4, 'eof');
37Npackets = fread(fid, 1, 'int32');
38fseek(fid, start_pos, 'bof');
39
40rtpts = zeros(Npackets, 1);
41seqno = zeros(Npackets, 1);
42pt = zeros(Npackets, 1);
43plen = zeros(Npackets, 1);
44recin_t = nan*ones(Npackets, 1);
45decode_t = nan*ones(Npackets, 1);
46playout_delay = zeros(Npackets, 1);
47optbuf = zeros(Npackets, 1);
48
49fs_ix = 1;
50clock = 0;
51ts_ix = 1;
52ended = 0;
53late_packets = 0;
54fs_now = 8000;
55last_decode_k = 0;
56tot_expand = 0;
57tot_accelerate = 0;
58tot_preemptive = 0;
59
60while not(ended)
61    signal = fread(fid, 1, '*int32');
62
63    switch signal
64        case 3 % NETEQ_DELAY_LOGGING_SIGNAL_CLOCK
65            clock = fread(fid, 1, '*float32');
66
67            % keep on reading batches of M until the signal is no longer "3"
68            % read int32 + float32 in one go
69            % this is to save execution time
70            temp = [3; 0];
71            M = 120;
72            while all(temp(1,:) == 3)
73                fp = ftell(fid);
74                temp = fread(fid, [2 M], '*int32');
75            end
76
77            % back up to last clock event
78            fseek(fid, fp - ftell(fid) + ...
79                (find(temp(1,:) ~= 3, 1 ) - 2) * 2 * 4 + 4, 'cof');
80            % read the last clock value
81            clock = fread(fid, 1, '*float32');
82
83        case 1 % NETEQ_DELAY_LOGGING_SIGNAL_RECIN
84            temp_ts = fread(fid, 1, 'uint32');
85
86            if late_packets > 0
87                temp_ix = ts_ix - 1;
88                while (temp_ix >= 1) && (rtpts(temp_ix) ~= temp_ts)
89                    % TODO(hlundin): use matlab vector search instead?
90                    temp_ix = temp_ix - 1;
91                end
92
93                if temp_ix >= 1
94                    % the ts was found in the vector
95                    late_packets = late_packets - 1;
96                else
97                    temp_ix = ts_ix;
98                    ts_ix = ts_ix + 1;
99                end
100            else
101                temp_ix = ts_ix;
102                ts_ix = ts_ix + 1;
103            end
104
105            rtpts(temp_ix) = temp_ts;
106            seqno(temp_ix) = fread(fid, 1, 'uint16');
107            pt(temp_ix) = fread(fid, 1, 'int32');
108            plen(temp_ix) = fread(fid, 1, 'int16');
109            recin_t(temp_ix) = clock;
110
111        case 2 % NETEQ_DELAY_LOGGING_SIGNAL_FLUSH
112            % do nothing
113
114        case 4 % NETEQ_DELAY_LOGGING_SIGNAL_EOF
115            ended = 1;
116
117        case 5 % NETEQ_DELAY_LOGGING_SIGNAL_DECODE
118            last_decode_ts = fread(fid, 1, 'uint32');
119            temp_delay = fread(fid, 1, 'uint16');
120
121            k = find(rtpts(1:(ts_ix - 1))==last_decode_ts,1,'last');
122            if ~isempty(k)
123                decode_t(k) = clock;
124                playout_delay(k) = temp_delay + ...
125                    5 *  fs_now / 8000; % add overlap length
126                last_decode_k = k;
127            end
128
129        case 6 % NETEQ_DELAY_LOGGING_SIGNAL_CHANGE_FS
130            fsvec(fs_ix) = fread(fid, 1, 'uint16');
131            fschange_ts(fs_ix) = last_decode_ts;
132            fs_now = fsvec(fs_ix);
133            fs_ix = fs_ix + 1;
134
135        case 7 % NETEQ_DELAY_LOGGING_SIGNAL_MERGE_INFO
136            playout_delay(last_decode_k) = playout_delay(last_decode_k) ...
137                + fread(fid, 1, 'int32');
138
139        case 8 % NETEQ_DELAY_LOGGING_SIGNAL_EXPAND_INFO
140            temp = fread(fid, 1, 'int32');
141            if last_decode_k ~= 0
142                tot_expand = tot_expand + temp / (fs_now / 1000);
143            end
144
145        case 9 % NETEQ_DELAY_LOGGING_SIGNAL_ACCELERATE_INFO
146            temp = fread(fid, 1, 'int32');
147            if last_decode_k ~= 0
148                tot_accelerate = tot_accelerate + temp / (fs_now / 1000);
149            end
150
151        case 10 % NETEQ_DELAY_LOGGING_SIGNAL_PREEMPTIVE_INFO
152            temp = fread(fid, 1, 'int32');
153            if last_decode_k ~= 0
154                tot_preemptive = tot_preemptive + temp / (fs_now / 1000);
155            end
156
157        case 11 % NETEQ_DELAY_LOGGING_SIGNAL_OPTBUF
158            optbuf(last_decode_k) = fread(fid, 1, 'int32');
159
160        case 12 % NETEQ_DELAY_LOGGING_SIGNAL_DECODE_ONE_DESC
161            last_decode_ts = fread(fid, 1, 'uint32');
162            k = ts_ix - 1;
163
164            while (k >= 1) && (rtpts(k) ~= last_decode_ts)
165                % TODO(hlundin): use matlab vector search instead?
166                k = k - 1;
167            end
168
169            if k < 1
170                % packet not received yet
171                k = ts_ix;
172                rtpts(ts_ix) = last_decode_ts;
173                late_packets = late_packets + 1;
174            end
175
176            decode_t(k) = clock;
177            playout_delay(k) = fread(fid, 1, 'uint16') + ...
178                5 *  fs_now / 8000; % add overlap length
179            last_decode_k = k;
180
181    end
182
183end
184
185
186fclose(fid);
187
188outStruct = struct(...
189    'ts', rtpts, ...
190    'sn', seqno, ...
191    'pt', pt,...
192    'plen', plen,...
193    'arrival', recin_t,...
194    'decode', decode_t,...
195    'fs', fsvec(:),...
196    'fschange_ts', fschange_ts(:),...
197    'playout_delay', playout_delay,...
198    'tot_expand', tot_expand,...
199    'tot_accelerate', tot_accelerate,...
200    'tot_preemptive', tot_preemptive,...
201    'optbuf', optbuf);
202