Skip to content

Commit

Permalink
Add various callbacks, .nextFrame() method and .paused property
Browse files Browse the repository at this point in the history
  • Loading branch information
phoboslab committed Nov 28, 2018
1 parent 8e3d87f commit 4f21d11
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 4 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ The `options` argument supports the following properties:
- `audioBufferSize` – when streaming, size in bytes for the audio decode buffer. Default 128*1024 (128kb). You may have to increase this for very high bitrates.
- `onVideoDecode(decoder, time)` – A callback that is called after each decoded and rendered video frame
- `onAudioDecode(decoder, time)` – A callback that is called after each decoded audio frame
- `onPlay(player)` – A callback that is called whenever playback starts
- `onPause(player)` – A callback that is called whenever playback paused (e.g. when .pause() is called or the source has ended)
- `onEnded(player)` – A callback that is called when playback has reached the end of the source (only called when `loop` is `false`).
- `onStalled(player)` – A callback that is called whenever there's not enough data for playback
- `onSourceEstablished(source)` – A callback that is called when source has first received data
- `onSourceCompleted(source)` – A callback that is called when the source has received all data


All options except from `canvas` can also be used with the HTML Element through `data-` attributes. E.g. to specify looping and autoplay in JavaScript:

Expand All @@ -75,9 +82,11 @@ A `JSMpeg.Player` instance supports the following methods and properties:
- `.play()` – start playback
- `.pause()` – pause playback
- `.stop()` – stop playback and seek to the beginning
- `.nextFrame()` – advance playback by one video frame. This does not decode audio. Returns `true` on success, `false` when there's not enough data.
- `.destroy()` – stops playback, disconnects the source and cleans up WebGL and WebAudio state. The player can not be used afterwards.
- `.volume` – get or set the audio volume (0-1)
- `.currentTime` – get or set the current playback position in seconds
- `.paused` – read only, wether playback is paused


## Encoding Video/Audio for JSMpeg
Expand Down
5 changes: 3 additions & 2 deletions jsmpeg.min.js

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions src/ajax-progressive.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ var AjaxProgressiveSource = function(url, options) {
this.loadStartTime = 0;
this.throttled = options.throttled !== false;
this.aborted = false;

this.onEstablishedCallback = options.onSourceEstablished;
this.onCompletedCallback = options.onSourceCompleted;
};

AjaxProgressiveSource.prototype.connect = function(destination) {
Expand Down Expand Up @@ -64,6 +67,9 @@ AjaxProgressiveSource.prototype.loadNextChunk = function() {

if (start >= this.fileSize || this.aborted) {
this.completed = true;
if (this.onCompletedCallback) {
this.onCompletedCallback(this);
}
return;
}

Expand Down Expand Up @@ -101,12 +107,18 @@ AjaxProgressiveSource.prototype.onProgress = function(ev) {
};

AjaxProgressiveSource.prototype.onChunkLoad = function(data) {
var isFirstChunk = !this.established;
this.established = true;
this.progress = 1;

this.loadedSize += data.byteLength;
this.loadFails = 0;
this.isLoading = false;

if (isFirstChunk && this.onEstablishedCallback) {
this.onEstablishedCallback(this);
}

if (this.destination) {
this.destination.write(data);
}
Expand Down
10 changes: 10 additions & 0 deletions src/ajax.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ var AjaxSource = function(url, options) {
this.completed = false;
this.established = false;
this.progress = 0;

this.onEstablishedCallback = options.onSourceEstablished;
this.onCompletedCallback = options.onSourceCompleted;
};

AjaxSource.prototype.connect = function(destination) {
Expand Down Expand Up @@ -49,6 +52,13 @@ AjaxSource.prototype.onLoad = function(data) {
this.completed = true;
this.progress = 1;

if (this.onEstablishedCallback) {
this.onEstablishedCallback(this);
}
if (this.onCompletedCallback) {
this.onCompletedCallback(this);
}

if (this.destination) {
this.destination.write(data);
}
Expand Down
38 changes: 37 additions & 1 deletion src/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ var Player = function(url, options) {

if (!options.disableWebAssembly && JSMpeg.WASMModule.IsSupported()) {
this.wasmModule = new JSMpeg.WASMModule();
options.wasmModule =this.wasmModule;
options.wasmModule = this.wasmModule;
}

if (options.video !== false) {
Expand Down Expand Up @@ -63,6 +63,7 @@ var Player = function(url, options) {
set: this.setVolume
});

this.paused = true;
this.unpauseOnShow = false;
if (options.pauseWhenHidden !== false) {
document.addEventListener('visibilitychange', this.showHide.bind(this));
Expand Down Expand Up @@ -104,21 +105,36 @@ Player.prototype.showHide = function(ev) {
};

Player.prototype.play = function(ev) {
if (this.animationId) {
return;
}

this.animationId = requestAnimationFrame(this.update.bind(this));
this.wantsToPlay = true;
this.paused = false;
};

Player.prototype.pause = function(ev) {
if (this.paused) {
return;
}

cancelAnimationFrame(this.animationId);
this.animationId = null;
this.wantsToPlay = false;
this.isPlaying = false;
this.paused = true;

if (this.audio && this.audio.canPlay) {
// Seek to the currentTime again - audio may already be enqueued a bit
// further, so we have to rewind it.
this.audioOut.stop();
this.seek(this.currentTime);
}

if (this.options.onPause) {
this.options.onPause(this);
}
};

Player.prototype.getVolume = function() {
Expand Down Expand Up @@ -186,6 +202,10 @@ Player.prototype.update = function() {
if (!this.isPlaying) {
this.isPlaying = true;
this.startTime = JSMpeg.Now() - this.currentTime;

if (this.options.onPlay) {
this.options.onPlay(this);
}
}

if (this.options.streaming) {
Expand Down Expand Up @@ -219,6 +239,13 @@ Player.prototype.updateForStreaming = function() {
}
};

Player.prototype.nextFrame = function() {
if (this.source.established && this.video) {
return this.video.decode();
}
return false;
};

Player.prototype.updateForStaticFile = function() {
var notEnoughData = false,
headroom = 0;
Expand Down Expand Up @@ -275,8 +302,17 @@ Player.prototype.updateForStaticFile = function() {
}
else {
this.pause();
if (this.options.onEnded) {
this.options.onEnded(this);
}
}
}

// If there's not enough data and the source is not completed, we have
// just stalled.
else if (notEnoughData && this.options.onStalled) {
this.options.onStalled(this);
}
};

return Player;
Expand Down
11 changes: 10 additions & 1 deletion src/websocket.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ var WSSource = function(url, options) {
this.progress = 0;

this.reconnectTimeoutId = 0;

this.onEstablishedCallback = options.onSourceEstablished;
this.onCompletedCallback = options.onSourceCompleted; // Never used
};

WSSource.prototype.connect = function(destination) {
Expand Down Expand Up @@ -49,7 +52,6 @@ WSSource.prototype.resume = function(secondsHeadroom) {

WSSource.prototype.onOpen = function() {
this.progress = 1;
this.established = true;
};

WSSource.prototype.onClose = function() {
Expand All @@ -62,6 +64,13 @@ WSSource.prototype.onClose = function() {
};

WSSource.prototype.onMessage = function(ev) {
var isFirstChunk = !this.established;
this.established = true;

if (isFirstChunk && this.onEstablishedCallback) {
this.onEstablishedCallback(this);
}

if (this.destination) {
this.destination.write(ev.data);
}
Expand Down

0 comments on commit 4f21d11

Please sign in to comment.