0c39e6ff by David LaPalomento

Add values for delivered segment bitrate

When a segment begins arriving, record its bitrate. Add a second y-axis to the timeline and plot segment bitrates on it.
1 parent 04fd771a
...@@ -84,7 +84,11 @@ ...@@ -84,7 +84,11 @@
84 84
85 // run the simulation 85 // run the simulation
86 runSimulation = function(options, done) { 86 runSimulation = function(options, done) {
87 var results = [], 87 var results = {
88 bandwidth: [],
89 playlists: [],
90 options: options
91 },
88 bandwidths = options.bandwidths, 92 bandwidths = options.bandwidths,
89 fixture = document.getElementById('fixture'), 93 fixture = document.getElementById('fixture'),
90 94
...@@ -101,7 +105,6 @@ ...@@ -101,7 +105,6 @@
101 player.dispose(); 105 player.dispose();
102 }; 106 };
103 107
104
105 // mock out the environment 108 // mock out the environment
106 clock = sinon.useFakeTimers(); 109 clock = sinon.useFakeTimers();
107 fakeXhr = sinon.useFakeXMLHttpRequest(); 110 fakeXhr = sinon.useFakeXMLHttpRequest();
...@@ -159,7 +162,7 @@ ...@@ -159,7 +162,7 @@
159 while (bandwidths[i + 1] && bandwidths[i + 1].time <= t) { 162 while (bandwidths[i + 1] && bandwidths[i + 1].time <= t) {
160 i++; 163 i++;
161 } 164 }
162 results.push({ 165 results.bandwidth.push({
163 time: t, 166 time: t,
164 bandwidth: bandwidths[i].bandwidth 167 bandwidth: bandwidths[i].bandwidth
165 }); 168 });
...@@ -168,11 +171,10 @@ ...@@ -168,11 +171,10 @@
168 requests = requests.reduce(function(remaining, request) { 171 requests = requests.reduce(function(remaining, request) {
169 var arrival = request.startTime + propagationDelay, 172 var arrival = request.startTime + propagationDelay,
170 delivered = Math.max(0, bandwidths[i].bandwidth * (t - arrival)), 173 delivered = Math.max(0, bandwidths[i].bandwidth * (t - arrival)),
171 playlist = /playlist-\d+$/.test(request.url),
172 segmentSize = +request.url.match(/(\d+)-\d+$/)[1] * segmentDuration; 174 segmentSize = +request.url.match(/(\d+)-\d+$/)[1] * segmentDuration;
173 175
174 // playlist responses 176 // playlist responses
175 if (playlist) { 177 if (/playlist-\d+$/.test(request.url)) {
176 // playlist responses have no trasmission time 178 // playlist responses have no trasmission time
177 if (t === arrival) { 179 if (t === arrival) {
178 request.respond(200, null, playlistResponse(+requests[0].url.match(/\d+$/))); 180 request.respond(200, null, playlistResponse(+requests[0].url.match(/\d+$/)));
...@@ -194,6 +196,11 @@ ...@@ -194,6 +196,11 @@
194 } else { 196 } else {
195 if (t === arrival) { 197 if (t === arrival) {
196 // segment response headers arrive after the propogation delay 198 // segment response headers arrive after the propogation delay
199
200 results.playlists.push({
201 time: t,
202 bitrate: +request.url.match(/(\d+)-\d+$/)[1]
203 });
197 request.setResponseHeaders({ 204 request.setResponseHeaders({
198 'Content-Type': 'video/mp2t' 205 'Content-Type': 'video/mp2t'
199 }); 206 });
...@@ -244,39 +251,43 @@ ...@@ -244,39 +251,43 @@
244 .append('g') 251 .append('g')
245 .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); 252 .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
246 253
247 displayTimeline = function(error, bandwidth) { 254 displayTimeline = function(error, data) {
248 var x = d3.scale.linear().range([0, width]), 255 var x = d3.scale.linear().range([0, width]),
249 y = d3.scale.linear().range([height, 0]), 256 y0 = d3.scale.linear().range([height, 0]),
257 y1 = d3.scale.ordinal().rangeRoundBands([height, 0], 0.1),
250 258
251 xAxis = d3.svg.axis().scale(x).orient('bottom'), 259 timeAxis = d3.svg.axis().scale(x).orient('bottom'),
252 yAxis = d3.svg.axis().scale(y).orient('left'), 260 bandwidthAxis = d3.svg.axis().scale(y0).orient('left'),
261 segmentBitrateAxis = d3.svg.axis().scale(y1).orient('right'),
253 262
254 line = d3.svg.line() 263 bandwidthLine = d3.svg.line()
255 .interpolate('basis') 264 .interpolate('basis')
256 .x(function(data) { 265 .x(function(data) {
257 return x(data.time); 266 return x(data.time);
258 }) 267 })
259 .y(function(data) { 268 .y(function(data) {
260 return y(data.bandwidth); 269 return y0(data.bandwidth);
261 }); 270 });
262 271
263 x.domain(d3.extent(bandwidth, function(data) { 272 x.domain(d3.extent(data.bandwidth, function(data) {
264 return data.time; 273 return data.time;
265 })); 274 }));
266 y.domain([0, d3.max(bandwidth, function(data) { 275 y0.domain([0, d3.max(data.bandwidth, function(data) {
267 return data.bandwidth; 276 return data.bandwidth;
268 })]); 277 })]);
278 y1.domain(data.options.playlists);
269 279
270 // draw the new timeline 280 // time axis
271 svg.selectAll('.axis').remove(); 281 svg.selectAll('.axis').remove();
272 svg.append('g') 282 svg.append('g')
273 .attr('class', 'x axis') 283 .attr('class', 'x axis')
274 .attr('transform', 'translate(0,' + height + ')') 284 .attr('transform', 'translate(0,' + height + ')')
275 .call(xAxis); 285 .call(timeAxis);
276 286
287 // bandwidth axis
277 svg.append('g') 288 svg.append('g')
278 .attr('class', 'y axis') 289 .attr('class', 'y axis')
279 .call(yAxis) 290 .call(bandwidthAxis)
280 .append('text') 291 .append('text')
281 .attr('transform', 'rotate(-90)') 292 .attr('transform', 'rotate(-90)')
282 .attr('y', 6) 293 .attr('y', 6)
...@@ -284,11 +295,38 @@ ...@@ -284,11 +295,38 @@
284 .style('text-anchor', 'end') 295 .style('text-anchor', 'end')
285 .text('Bandwidth (b/s)'); 296 .text('Bandwidth (b/s)');
286 297
298 // segment bitrate axis
299 svg.append('g')
300 .attr('class', 'y axis')
301 .attr('transform', 'translate(' + width + ', 0)')
302 .call(segmentBitrateAxis)
303 .append('text')
304 .attr('transform', 'rotate(-90)')
305 .attr('y', 6)
306 .attr('dy', '-.71em')
307 .style('text-anchor', 'end')
308 .text('Bitrate (b/s)');
309
310 // bandwidth line
287 svg.selectAll('.bandwidth').remove(); 311 svg.selectAll('.bandwidth').remove();
288 svg.append('path') 312 svg.append('path')
289 .datum(bandwidth) 313 .datum(data.bandwidth)
290 .attr('class', 'line bandwidth') 314 .attr('class', 'line bandwidth')
291 .attr('d', line); 315 .attr('d', bandwidthLine);
316
317 // segment bitrate dots
318 svg.selectAll('.segment-bitrate').remove();
319 svg.selectAll('.segment-bitrate')
320 .data(data.playlists)
321 .enter().append('circle')
322 .attr('class', 'dot segment-bitrate')
323 .attr('r', 3.5)
324 .attr('cx', function(playlist) {
325 return x(playlist.time);
326 })
327 .attr('cy', function(playlist) {
328 return y1(playlist.bitrate) + (y1.rangeBand() / 2);
329 });
292 }; 330 };
293 })(); 331 })();
294 332
......