diff --git a/lib/abr/ewma.js b/lib/abr/ewma.js index c3aa337132..7d3977625c 100644 --- a/lib/abr/ewma.js +++ b/lib/abr/ewma.js @@ -54,8 +54,12 @@ shaka.abr.Ewma = function(halfLife) { */ shaka.abr.Ewma.prototype.sample = function(weight, value) { var adjAlpha = Math.pow(this.alpha_, weight); - this.estimate_ = value * (1 - adjAlpha) + adjAlpha * this.estimate_; - this.totalWeight_ += weight; + var newEstimate = value * (1 - adjAlpha) + adjAlpha * this.estimate_; + + if (!isNaN(newEstimate)) { + this.estimate_ = newEstimate; + this.totalWeight_ += weight; + } }; diff --git a/test/abr/simple_abr_manager_unit.js b/test/abr/simple_abr_manager_unit.js index f13c6521b0..c71422fb7c 100644 --- a/test/abr/simple_abr_manager_unit.js +++ b/test/abr/simple_abr_manager_unit.js @@ -182,6 +182,29 @@ describe('SimpleAbrManager', function() { }); }); + it('can handle 0 duration segments', function() { + var audioBandwidth = 5e5; + var videoBandwidth = 2e6; + var bytesPerSecond = + sufficientBWMultiplier * (audioBandwidth + videoBandwidth) / 8.0; + + abrManager.chooseStreams(streamSetsByType); + + // 0 duration segment shouldn't cause us to get stuck on the lowest variant + abrManager.segmentDownloaded(1000, 1000, bytesPerSecond); + abrManager.segmentDownloaded(2000, 3000, bytesPerSecond); + + abrManager.enable(); + + abrManager.segmentDownloaded(4000, 5000, bytesPerSecond); + + expect(switchCallback).toHaveBeenCalled(); + expect(switchCallback.calls.argsFor(0)[0]).toEqual({ + 'audio': jasmine.objectContaining({bandwidth: audioBandwidth}), + 'video': jasmine.objectContaining({bandwidth: videoBandwidth}) + }); + }); + it('picks lowest audio Stream when there is insufficient bandwidth', function() { // The lowest audio track will only be chosen if needed to fit the