npaw-plugin-adapters
Version:
NPAW's Plugin Adapters
217 lines (196 loc) • 6.4 kB
JavaScript
export default class ChromecastAdapter {
getPlayhead() {
return this.player.getEstimatedTime || this.player.currentTime;
}
getVersion() {
return '7.0.2-chromecast-jsclass';
}
getDuration() {
return this.player.duration;
}
getBitrate() {
if (this.castPlayer && this.castPlayer.getStreamingProtocol) {
const protocol = this.castPlayer.getStreamingProtocol();
let streamCount = 0;
try {
if (protocol.getStreamCount && protocol.getStreamCount() > 0) {
streamCount = protocol.getStreamCount();
}
} catch (e) { }
for (let c = 0; c < protocol.getStreamCount(); c++) {
const streamInfo = protocol.getStreamInfo(c);
if (streamInfo.mimeType.indexOf('video/') === 0) {
const videoLevel = protocol.getQualityLevel(c);
if (streamInfo.bitrates && streamInfo.bitrates[videoLevel]) {
return streamInfo.bitrates[videoLevel];
}
}
}
}
return undefined;
}
getRendition() {
let ret;
if (this.player && this.player.videoHeight && this.player.videoWidth) {
let bitrate = this.getVideo().getBitrate();
if (bitrate <= 0) {
bitrate = this.plugin.requestBuilder.lastSent['bitrate'] || -1;
}
ret = this.getNpawUtils().buildRenditionString(this.player.videoWidth, this.player.videoHeight, bitrate);
}
return ret;
}
getResource() {
let ret;
if (!this.player.currentSrc.startsWith('blob:')) {
ret = this.player.currentSrc;
} else if (this.castPlayer) {
ret = this.castPlayer.getHost().url;
}
return ret
}
getPlayrate() {
return this.player.playbackRate;
}
getDroppedFrames() {
return this.player.webkitDroppedFrameCount;
}
getPlayerVersion() {
let ret;
if (typeof cast !== 'undefined' && cast.player && cast.player.api) {
ret = cast.player.api.VERSION;
}
return ret;
}
getPlayerName() {
return 'Chromecast';
}
registerListeners() {
this.getNpawUtils().logAllEvents(this.player);
this.monitorPlayhead(true, false, 1200);
this.references = {
loadstart: this.playListener.bind(this),
pause: this.pauseListener.bind(this),
playing: this.playingListener.bind(this),
error: this.errorListener.bind(this),
seeking: this.seekingListener.bind(this),
abort: this.endedListener.bind(this),
ended: this.endedListener.bind(this),
buffering: this.bufferingListener.bind(this)
};
this.hostReferences = {
onAutoPause: this.autoPauseListener.bind(this)
};
for (let key in this.references) {
this.player.addEventListener(key, this.references[key]);
}
if (this.castPlayer && this.castPlayer.getHost && this.castPlayer.getHost()) {
let host = this.castPlayer.getHost();
for (let key2 in this.hostReferences) {
host[key2] = this.hostReferences[key2];
}
}
this.registerModelVersion();
}
unregisterListeners() {
if (this.monitor) this.monitor.stop();
if (this.player && this.references) {
if (typeof this.player.removeEventListener === 'function') {
for (let key in this.references) {
this.player.removeEventListener(key, this.references[key]);
}
}
delete this.references;
}
if (this.castPlayer && this.castPlayer.getHost && this.castPlayer.getHost()) {
const host = this.castPlayer.getHost();
for (let key2 in this.hostReferences) {
host[key2] = undefined;
}
delete this.hostReferences;
}
}
registerModelVersion() {
// If client set model on plugin options we do not override
if (typeof this.getVideo().options['device.model'] !== 'undefined') {
return;
}
// https://developers.google.com/cast/docs/media#video_codecs
try {
const { hardwareConcurrency, userAgent } = window.navigator;
const context = cast.receiver.CastReceiverManager.getInstance();
// Chromecast with Google TV supports 'H.264 High Profile, level 5.1'
if (context.canDisplayType('video/mp4; codecs="avc1.640033')) {
this.getVideo().options['device.model'] = 'Chromecast with Google TV';
return;
}
// Android Devices with Chromecast built-in
if (userAgent.includes('Android')) {
this.getVideo().options['device.model'] = 'Chromecast Android';
return;
}
// Chromecast Ultra supports 'HEVC main profile, level 3.1'
if (context.canDisplayType('video/mp4; codecs=hev1.1.6.L93.B0')) {
this.getVideo().options['device.model'] = 'Chromecast Ultra';
return;
}
// 3rd generation Chromecast supports 'H.264 high profile, level 4.2'
if (context.canDisplayType('video/mp4; codecs=avc1.64002A')) {
this.getVideo().options['device.model'] = 'Chromecast 3';
return;
}
// 2nd and 1st generation Chromecast can be differentiated by hardwareConcurrency
if (hardwareConcurrency === 2) {
this.getVideo().options['device.model'] = 'Chromecast 2';
return;
}
if (hardwareConcurrency === 1) {
this.getVideo().options['device.model'] = 'Chromecast 1';
return;
}
} catch (e) {
// do nothing
}
this.getVideo().options['device.model'] = 'Chromecast';
}
playListener(e) {
if (this.flags.isStarted) {
this.fireStop({}, 'playListener');
}
this.fireStart({}, 'playListener');
}
pauseListener(e) {
if (!this.flags.isBuffering) {
this.firePause({}, 'pauseListener');
}
}
playingListener(e) {
this.fireResume({}, 'playingListener');
this.fireSeekEnd({}, 'playingListener');
this.fireBufferEnd({}, 'playingListener');
this.fireJoin({}, 'playingListener');
}
errorListener(e) {
this.fireError(e);
}
endedListener(e) {
this.fireStop({}, 'endedListener');
}
seekingListener(e) {
this.fireSeekBegin({}, false, 'seekingListener');
}
bufferingListener(e) {
if (this.flags.isPaused) {
this.fireResume({}, 'bufferingListener');
}
this.fireBufferBegin({}, false, 'bufferingListener');
}
autoPauseListener(e) {
if (e) {
this.fireResume({}, 'autoPauseListener');
this.fireBufferBegin({}, false, 'autoPauseListener');
} else {
this.fireBufferEnd({}, 'autoPauseListener');
}
}
}