Skip to content

Commit 47d77af

Browse files
yairansDan Ziv
authored andcommitted
fix(FEC-7207): listen to shaka buffering event (#31)
1 parent 59e041b commit 47d77af

File tree

2 files changed

+137
-0
lines changed

2 files changed

+137
-0
lines changed

src/dash-adapter.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ export default class DashAdapter extends BaseMediaSourceAdapter {
5959
* @private
6060
*/
6161
_loadPromise: ?Promise<Object>;
62+
/**
63+
* The buffering state flag
64+
* @member {boolean} - _buffering
65+
* @type {boolean}
66+
* @private
67+
*/
68+
_buffering: boolean = false;
6269

6370
/**
6471
* Factory method to create media source adapter.
@@ -182,6 +189,9 @@ export default class DashAdapter extends BaseMediaSourceAdapter {
182189
_addBindings(): void {
183190
this._shaka.addEventListener('adaptation', this._onAdaptation.bind(this));
184191
this._shaka.addEventListener('error', this._onError.bind(this));
192+
this._shaka.addEventListener('buffering', this._onBuffering.bind(this));
193+
//TODO use events enum when available
194+
this._videoElement.addEventListener('playing', this._onPlaying.bind(this));
185195
}
186196

187197
/**
@@ -193,6 +203,9 @@ export default class DashAdapter extends BaseMediaSourceAdapter {
193203
_removeBindings(): void {
194204
this._shaka.removeEventListener('adaptation', this._onAdaptation);
195205
this._shaka.removeEventListener('error', this._onError);
206+
this._shaka.removeEventListener('buffering', this._onBuffering.bind(this));
207+
//TODO use events enum when available
208+
this._videoElement.removeEventListener('playing', this._onPlaying.bind(this));
196209
}
197210

198211
/**
@@ -231,6 +244,7 @@ export default class DashAdapter extends BaseMediaSourceAdapter {
231244
super.destroy();
232245
this._loadPromise = null;
233246
this._sourceObj = null;
247+
this._buffering = false;
234248
if (this._shaka) {
235249
this._removeBindings();
236250
this._shaka.destroy();
@@ -508,6 +522,36 @@ export default class DashAdapter extends BaseMediaSourceAdapter {
508522
DashAdapter._logger.error(error);
509523
}
510524

525+
/**
526+
* An handler to shaka buffering event
527+
* @function _onBuffering
528+
* @param {any} event - the buffering event
529+
* @returns {void}
530+
* @private
531+
*/
532+
_onBuffering(event: any): void {
533+
this._buffering = event.buffering;
534+
if (this._buffering) { //the player enters the buffering state.
535+
//TODO use events enum when available
536+
this._videoElement.dispatchEvent(new window.Event('waiting'));
537+
} else if (!this._videoElement.paused) { //the player leaves the buffering state.
538+
this._videoElement.dispatchEvent(new window.Event('playing'));
539+
}
540+
}
541+
542+
/**
543+
* An handler to HTMLVideoElement playing event
544+
* @function _onPlaying
545+
* @returns {void}
546+
* @private
547+
*/
548+
_onPlaying(): void {
549+
if (this._buffering) { //the player is in buffering state.
550+
//TODO use events enum when available
551+
this._videoElement.dispatchEvent(new window.Event('waiting'));
552+
}
553+
}
554+
511555
/**
512556
* Getter for the src that the adapter plays on the video element.
513557
* In case the adapter preformed a load it will return the manifest url.

test/src/dash-adapter.spec.js

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,10 +213,12 @@ describe('DashAdapter: destroy', () => {
213213
dashInstance._loadPromise.should.be.exist;
214214
dashInstance._sourceObj.should.be.exist;
215215
dashInstance._config.should.be.exist;
216+
dashInstance._buffering = true;
216217
dashInstance.destroy();
217218
(!dashInstance._loadPromise).should.be.true;
218219
(!dashInstance._sourceObj).should.be.true;
219220
(!dashInstance._config).should.be.true;
221+
dashInstance._buffering.should.be.false;
220222
done();
221223
});
222224
});
@@ -878,5 +880,96 @@ describe('DashAdapter: get duration', () => {
878880
});
879881
});
880882

883+
describe('DashAdapter: _onBuffering', () => {
884+
let video, dashInstance, config;
885+
886+
beforeEach(() => {
887+
video = document.createElement("video");
888+
config = {playback: {options: {html5: {dash: {}}}}};
889+
});
890+
891+
afterEach(() => {
892+
dashInstance.destroy();
893+
dashInstance = null;
894+
});
895+
896+
after(() => {
897+
TestUtils.removeVideoElementsFromTestPage();
898+
});
899+
900+
it('should dispatch waiting event when buffering is true', (done) => {
901+
dashInstance = DashAdapter.createAdapter(video, vodSource, config);
902+
dashInstance._videoElement.addEventListener('waiting', () => {
903+
done();
904+
});
905+
dashInstance._onBuffering({buffering: true});
906+
});
907+
908+
it('should dispatch playing event when buffering is false and video is playing', (done) => {
909+
dashInstance = DashAdapter.createAdapter(video, vodSource, config);
910+
let hasPlaying = false;
911+
let onPlaying = () => {
912+
if (hasPlaying) {
913+
dashInstance._videoElement.removeEventListener('playing', onPlaying);
914+
done();
915+
} else {
916+
hasPlaying = true;
917+
dashInstance._onBuffering({buffering: false});
918+
}
919+
};
920+
dashInstance._videoElement.addEventListener('playing', onPlaying);
921+
dashInstance.load().then(() => {
922+
dashInstance._videoElement.play();
923+
});
924+
});
925+
926+
it('should not dispatch playing event when buffering is false but video is paused', (done) => {
927+
dashInstance = DashAdapter.createAdapter(video, vodSource, config);
928+
let t = setTimeout(done, 0);
929+
dashInstance._videoElement.addEventListener('playing', () => {
930+
done(new Error("test fail"));
931+
clearTimeout(t);
932+
});
933+
dashInstance._onBuffering({buffering: false});
934+
});
935+
});
936+
937+
describe('DashAdapter: _onPlaying', () => {
938+
let video, dashInstance, config;
939+
940+
beforeEach(() => {
941+
video = document.createElement("video");
942+
config = {playback: {options: {html5: {dash: {}}}}};
943+
});
944+
945+
afterEach(() => {
946+
dashInstance.destroy();
947+
dashInstance = null;
948+
});
949+
950+
after(() => {
951+
TestUtils.removeVideoElementsFromTestPage();
952+
});
953+
954+
it('should dispatch waiting event when buffering is true', (done) => {
955+
dashInstance = DashAdapter.createAdapter(video, vodSource, config);
956+
dashInstance._videoElement.addEventListener('waiting', () => {
957+
done();
958+
});
959+
dashInstance._buffering = true;
960+
dashInstance._onPlaying();
961+
});
962+
963+
it('should not dispatch waiting event when buffering is false', (done) => {
964+
dashInstance = DashAdapter.createAdapter(video, vodSource, config);
965+
let t = setTimeout(done, 0);
966+
dashInstance._videoElement.addEventListener('waiting', () => {
967+
done(new Error("test fail"));
968+
clearTimeout(t);
969+
});
970+
dashInstance._onPlaying();
971+
});
972+
});
973+
881974

882975

0 commit comments

Comments
 (0)