Support for WebRTC data tracks in the player
This commit is contained in:
parent
ebe783666f
commit
72bc25cef0
4 changed files with 140 additions and 9 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -677,7 +677,13 @@ function MistVideo(streamName,options) {
|
||||||
listeners: {},
|
listeners: {},
|
||||||
init: function(){
|
init: function(){
|
||||||
var me = this;
|
var me = this;
|
||||||
this.socket = new WebSocket(MistUtil.http.url.addParam(MistVideo.urlappend(json_source.url),{rate:1}));
|
if (MistVideo.player.api.metaTrackSocket) {
|
||||||
|
this.socket = new MistVideo.player.api.metaTrackSocket();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.socket = new WebSocket(MistUtil.http.url.addParam(MistVideo.urlappend(json_source.url),{rate:1}));
|
||||||
|
}
|
||||||
|
|
||||||
me.send_queue = [];
|
me.send_queue = [];
|
||||||
me.checktimer = null;
|
me.checktimer = null;
|
||||||
me.s = function(obj){
|
me.s = function(obj){
|
||||||
|
@ -711,11 +717,16 @@ function MistVideo(streamName,options) {
|
||||||
if (!message) { MistVideo.log("Subtitle websocket received invalid message."); return; }
|
if (!message) { MistVideo.log("Subtitle websocket received invalid message."); return; }
|
||||||
|
|
||||||
if (("time" in message) && ("track" in message) && ("data" in message)) {
|
if (("time" in message) && ("track" in message) && ("data" in message)) {
|
||||||
|
var pushed = false;
|
||||||
|
if ("all" in me.subscriptions) {
|
||||||
|
me.subscriptions.all.buffer.push(message);
|
||||||
|
pushed = true;
|
||||||
|
}
|
||||||
if (message.track in me.subscriptions) {
|
if (message.track in me.subscriptions) {
|
||||||
//console.warn("received:",message.track,message.data);
|
me.subscriptions[message.track].buffer.push(message);
|
||||||
me.subscriptions[message.track].buffer.push(message);
|
pushed = true;
|
||||||
console.warn("received:",message.track,message.time*1e-3,"currentTime:",MistVideo.player.api.currentTime,"latency",Math.round(MistVideo.player.api.currentTime-message.time*1e-3),"bufferlength:",me.subscriptions[message.track].buffer.length,"timer:",!!me.checktimer);
|
}
|
||||||
|
if (pushed) {
|
||||||
if (!me.checktimer) {
|
if (!me.checktimer) {
|
||||||
me.check();
|
me.check();
|
||||||
}
|
}
|
||||||
|
@ -860,6 +871,10 @@ function MistVideo(streamName,options) {
|
||||||
this.listeners = {};
|
this.listeners = {};
|
||||||
},
|
},
|
||||||
add: function (trackid,callback) {
|
add: function (trackid,callback) {
|
||||||
|
if ((typeof trackid == "function") && (!callback)) {
|
||||||
|
callback = trackid;
|
||||||
|
trackid = "all";
|
||||||
|
}
|
||||||
if (typeof callback != "function") { return; }
|
if (typeof callback != "function") { return; }
|
||||||
|
|
||||||
if (!(trackid in this.subscriptions)) {
|
if (!(trackid in this.subscriptions)) {
|
||||||
|
@ -897,6 +912,9 @@ function MistVideo(streamName,options) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
if (typeof options.subscribeToMetaTrack == "function") {
|
||||||
|
options.subscribeToMetaTrack = [["all",options.subscribeToMetaTrack]];
|
||||||
|
}
|
||||||
if (options.subscribeToMetaTrack.length) {
|
if (options.subscribeToMetaTrack.length) {
|
||||||
if (typeof options.subscribeToMetaTrack[0] != "object") {
|
if (typeof options.subscribeToMetaTrack[0] != "object") {
|
||||||
options.subscribeToMetaTrack = [options.subscribeToMetaTrack];
|
options.subscribeToMetaTrack = [options.subscribeToMetaTrack];
|
||||||
|
|
|
@ -193,6 +193,7 @@ p.prototype.build = function (MistVideo,callback) {
|
||||||
//track type not found, this should not happen
|
//track type not found, this should not happen
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (type == "subtitle") { continue; }
|
||||||
|
|
||||||
//create an event to pass this to the skin
|
//create an event to pass this to the skin
|
||||||
MistUtil.event.send("playerUpdate_trackChanged",{
|
MistUtil.event.send("playerUpdate_trackChanged",{
|
||||||
|
@ -209,7 +210,7 @@ p.prototype.build = function (MistVideo,callback) {
|
||||||
MistVideo.reporting.stats.d.tracks = ev.tracks.join(",");
|
MistVideo.reporting.stats.d.tracks = ev.tracks.join(",");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
on_seek: function(e){
|
seek: function(e){
|
||||||
var thisPlayer = this;
|
var thisPlayer = this;
|
||||||
MistUtil.event.send("seeked",seekoffset,video);
|
MistUtil.event.send("seeked",seekoffset,video);
|
||||||
|
|
||||||
|
@ -231,7 +232,7 @@ p.prototype.build = function (MistVideo,callback) {
|
||||||
}
|
}
|
||||||
else { video.play(); }
|
else { video.play(); }
|
||||||
},
|
},
|
||||||
on_speed: function(e){
|
set_speed: function(e){
|
||||||
this.webrtc.play_rate = e.play_rate_curr;
|
this.webrtc.play_rate = e.play_rate_curr;
|
||||||
MistUtil.event.send("ratechange",e,video);
|
MistUtil.event.send("ratechange",e,video);
|
||||||
},
|
},
|
||||||
|
@ -271,6 +272,11 @@ p.prototype.build = function (MistVideo,callback) {
|
||||||
thisWebRTCPlayer.isConnected = false;
|
thisWebRTCPlayer.isConnected = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "on_error": {
|
||||||
|
MistVideo.showError("WebRTC error: "+MistUtil.format.ucFirst(ev.message));
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (ev.type in me.listeners) {
|
if (ev.type in me.listeners) {
|
||||||
return me.listeners[ev.type].call(me,("data" in ev)?ev.data:ev);
|
return me.listeners[ev.type].call(me,("data" in ev)?ev.data:ev);
|
||||||
|
@ -323,10 +329,15 @@ p.prototype.build = function (MistVideo,callback) {
|
||||||
opts.iceServers = MistVideo.source.RTCIceServers;
|
opts.iceServers = MistVideo.source.RTCIceServers;
|
||||||
}
|
}
|
||||||
thisWebRTCPlayer.peerConn = new RTCPeerConnection(opts);
|
thisWebRTCPlayer.peerConn = new RTCPeerConnection(opts);
|
||||||
|
thisWebRTCPlayer.MetaDataTrack = thisWebRTCPlayer.peerConn.createDataChannel("*",{protocol:"JSON"});
|
||||||
|
|
||||||
thisWebRTCPlayer.peerConn.ontrack = function(ev) {
|
thisWebRTCPlayer.peerConn.ontrack = function(ev) {
|
||||||
video.srcObject = ev.streams[0];
|
video.srcObject = ev.streams[0];
|
||||||
if (callback) { callback(); }
|
if (callback) { callback(); }
|
||||||
};
|
};
|
||||||
|
thisWebRTCPlayer.peerConn.ondatachannel = function(){
|
||||||
|
console.warn("ondatachannel",arguments);
|
||||||
|
};
|
||||||
thisWebRTCPlayer.peerConn.onconnectionstatechange = function(e){
|
thisWebRTCPlayer.peerConn.onconnectionstatechange = function(e){
|
||||||
if (MistVideo.destroyed) { return; } //the player doesn't exist any more
|
if (MistVideo.destroyed) { return; } //the player doesn't exist any more
|
||||||
switch (this.connectionState) {
|
switch (this.connectionState) {
|
||||||
|
@ -368,6 +379,8 @@ p.prototype.build = function (MistVideo,callback) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
MistUtil.event.send("webrtc_ready",null,video);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -393,6 +406,7 @@ p.prototype.build = function (MistVideo,callback) {
|
||||||
|
|
||||||
this.stop = function(){
|
this.stop = function(){
|
||||||
if (!this.isConnected) { throw "Not connected, cannot stop." }
|
if (!this.isConnected) { throw "Not connected, cannot stop." }
|
||||||
|
n_
|
||||||
this.signaling.send({type: "stop"});
|
this.signaling.send({type: "stop"});
|
||||||
};
|
};
|
||||||
this.seek = function(seekTime){
|
this.seek = function(seekTime){
|
||||||
|
@ -747,6 +761,105 @@ p.prototype.build = function (MistVideo,callback) {
|
||||||
track.onload = correctSubtitleSync;
|
track.onload = correctSubtitleSync;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
me.api.metaTrackSocket = function(){
|
||||||
|
//console.warn("new metaTrackSocket");
|
||||||
|
|
||||||
|
this.origin = {};
|
||||||
|
this.CONNECTING = 0;
|
||||||
|
this.OPEN = 1;
|
||||||
|
this.CLOSING = 2;
|
||||||
|
this.CLOSED = 3;
|
||||||
|
|
||||||
|
this.readyState = 0;
|
||||||
|
//follow readystate of origin, except when self is asked to close, then pretend to close and remove event listeners.
|
||||||
|
|
||||||
|
this.listeners = [];
|
||||||
|
var me = this;
|
||||||
|
|
||||||
|
MistUtil.event.addListener(MistVideo.video,"webrtc_ready",function(){
|
||||||
|
me.init();
|
||||||
|
});
|
||||||
|
this.init = function(){
|
||||||
|
this.origin = MistVideo.player.webrtc && MistVideo.player.webrtc.MetaDataTrack ? MistVideo.player.webrtc.MetaDataTrack : {};
|
||||||
|
|
||||||
|
//console.warn("init",this.origin);
|
||||||
|
if ("readyState" in this.origin) {
|
||||||
|
//console.warn("origin readystate",this.origin.readyState);
|
||||||
|
function onopen() {
|
||||||
|
me.readyState = me.OPEN;
|
||||||
|
me.onopen();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.origin.addEventListener("open",onopen);
|
||||||
|
this.origin.onmessage = function(e){
|
||||||
|
//console.warn("metadata message",e);
|
||||||
|
};
|
||||||
|
this.origin.addEventListener("close",function(){
|
||||||
|
me.readyState = me.CLOSED;
|
||||||
|
me.onclose();
|
||||||
|
});
|
||||||
|
if (this.origin.readyState == "open") { onopen(); }
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.open = function(){
|
||||||
|
//should be open once webrtc is active
|
||||||
|
|
||||||
|
if (this.readyState == this.OPEN) return; //already open
|
||||||
|
|
||||||
|
switch (this.origin.readyState) {
|
||||||
|
case "connecting": { this.readyState = this.CONNECTING; break; }
|
||||||
|
case "open": { this.readyState = this.OPEN; break; }
|
||||||
|
case "closing": { this.readyState = this.CLOSING; break; }
|
||||||
|
case "closed": { this.readyState = this.CLOSED; break; }
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i in this.listeners) {
|
||||||
|
this.origin.addEventListener.apply(this.origin,this.listeners[i]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.close = function(){
|
||||||
|
//don't actually close, but pretend
|
||||||
|
if (this.readyState >= this.CLOSING) return; //already closed
|
||||||
|
|
||||||
|
this.readyState = this.CLOSED;
|
||||||
|
|
||||||
|
//remove listeners
|
||||||
|
for (var i in this.listeners) {
|
||||||
|
this.removeEventListener.apply(this,this.listeners[i]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.send = function(){
|
||||||
|
if (this.origin.readyState == "open") return this.origin.send.apply(this,arguments);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
this.onopen = function(){};
|
||||||
|
this.onclose = function(){};
|
||||||
|
this.addEventListener = function(){
|
||||||
|
this.listeners.push(arguments);
|
||||||
|
return this.origin.addEventListener.apply(this.origin,arguments);
|
||||||
|
};
|
||||||
|
this.removeEventListener = function(name,func){
|
||||||
|
//remove them from the listeners array and the origin
|
||||||
|
for (var i = this.listeners.length-1; i >= 0; i--) {
|
||||||
|
if ((name == this.listeners[i][0]) && (func == this.listeners[i][1])) {
|
||||||
|
this.listeners.splice(i,1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.origin.removeEventListener.apply(this.origin,arguments);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.init();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
//loop
|
//loop
|
||||||
MistUtil.event.addListener(video,"ended",function(){
|
MistUtil.event.addListener(video,"ended",function(){
|
||||||
|
|
Loading…
Add table
Reference in a new issue