//Player states.
const playerStateFinish = 0;
const playerStatePlaying = 1;
const playerStatePausing = 2;
var boundary = "XHFs29zHSUTjXw"
var cms_header_format = `format:cms\r\nboundary:${boundary}\r\nts:${Date.now()}\r\ntrack:id=1,codec=alaw,rate=8000\r\n\r\n`
function Player($container) {
this.type = "video";
this.isLive = false;
this.webglPlayer = null;
this.pcmPlayer = null;
this.videoLoadFinish = false;
this.frameSize = 0;
this.canvas = null;
this.image = null;
this.playerState = playerStateFinish;
this.isGetRealSize = false;
this.videoWidth = 0;
this.videoHeight = 0;
this.yLength = 0;
this.uvLength = 0;
this.isTalking = false;
this.isListening = false;
this.pauseDownload = false;
this.isRedVideo = false;
this.flowControl = false;
this.fullscreenFlag = false;
this.DownloadFinish = false; // add by ramon
this.isReviewing = false; // add by ramon
this.videoBuffer = [];
this.audioBuffer = [];
this.imageBuffer = [];
this.currentVideots = 0;
this.currentFrameIndex = 0;
this.currentAudioIndex = 0;
this.startAudioIndex = 0;
this.videoPartHeaders = [];
this.audioPartHeaders = [];
this.diplayLastTick = 0
//this.currPart = null // del by ramon
this.displayInterval = 0; // add by ramon
this.lastDisplayTick = 0; // add by ramon
//talk
this.localAudioStream = null;
this.mediaRecorder = null
this.httpRequest = null
this.cmsTalk = null
//this.cmsTalk = new CmsTalk()
//this.talkUrl = talkUrl
//初始化元素
this.$container = $container;
this.initCMSHtml();
//初始化解析器
this.initCMSParserWorker();
this.logger = new Logger("Player");
}
Player.prototype.initCMSHtml = function () {
var self = this;
var html = `
`;
var pictureDialogHtml = ``;
this.$container.html("");
this.$container.append(html);
this.$pictureDialog = $(pictureDialogHtml);
this.$pictureDialog.appendTo($("body"));
//全屏
this.$container.find("#fullscreenBtn").click(function () {
this.fullscreenFlag = true;
this.fullscreen();
}.bind(this));
this.$container.find("#canvasBox").dblclick(function () {
if (this.fullscreenFlag) {
this.exitfullscreen();
} else {
this.fullscreen();
}
this.fullscreenFlag = !this.fullscreenFlag;
}.bind(this));
//暂停
this.$container.find("#pauseBtn").click(function () {
if (self.pauseDownload) {
$(this).attr("src", "./public/images/pause.svg");
self.resume();
} else {
$(this).attr("src", "./public/images/play.svg");
self.pause();
}
});
this.$container.find("#listenBtn").click(function () {
console.log("listenBtn clicked", self.isListening);
if (self.isListening) {
$(this).attr("src", "./public/images/mute.svg");
self.stopListen();
} else {
$(this).attr("src", "./public/images/sound.svg");
self.startListen();
}
});
this.$container.find("#talkBtn").click(function () {
console.log("talkBtn clicked", self.isTalking);
if (self.isTalking) {
$(this).attr("src", "./public/images/microphone-close.svg");
self.stopTalk()
} else {
$(this).attr("src", "./public/images/microphone.svg");
self.startTalk()
}
});
//循环红点画面
this.$container.find("#reviewBtn").click(function () {
if (self.$container.find("#alarmblock").css("display") === "block") {
if (!self.alarmTime) return;
if (!self.isReviewing) {
self.isReviewing = true;
} else {
self.isReviewing = false;
}
if (self.isReviewing) {
if (self.type === "video") {
//视频流
for (var i = 0; i < self.videoPartHeaders.length; i++) {
if ((self.startTime + self.videoPartHeaders[i].ts + 500) >= (self.alarmTime - 2000)) {
self.alarmBlockStartFrameIndex = i;
self.currentFrameIndex = i;
self.currentVideots = self.videoPartHeaders[i].ts;
break;
}
}
if (!self.alarmBlockStartFrameIndex) {
self.isReviewing = false;
return;
}
for (var i = self.alarmBlockStartFrameIndex; i < self.videoPartHeaders.length; i++) {
if ((self.startTime + self.videoPartHeaders[i].ts) >= (self.alarmTime + 2000)) {
self.alarmBlockEndFrameIndex = i;
break;
}
}
if (!self.alarmBlockEndFrameIndex) {
self.alarmBlockEndFrameIndex = self.videoPartHeaders.length;
}
//声音播放
if (self.isListening) {
self.isListeningFirst = false;
if (self.pcmPlayer) {
self.pcmPlayer.destroy();
self.pcmPlayer = null;
}
}
} else {
//图片流
for (var i = 0; i < self.imageBuffer.length; i++) {
if ((self.startTime + self.imageBuffer[i].t + 500) >= (self.alarmTime - 2000)) {
self.alarmBlockStartFrameIndex = i;
self.currentFrameIndex = i;
break;
}
}
if (!self.alarmBlockStartFrameIndex) {
self.isReviewing = false;
return;
}
for (var i = 0; i < self.imageBuffer.length; i++) {
if ((self.startTime + self.imageBuffer[i].t - 400) >= (self.alarmTime + 2000)) {
self.alarmBlockEndFrameIndex = i;
break;
}
}
if (!self.alarmBlockEndFrameIndex) {
self.alarmBlockEndFrameIndex = self.imageBuffer.length;
}
}
$(this).parent().css("background", "red");
} else {
$(this).parent().css("background", "#1C66A3");
}
}
});
//红点视频-播放声音
this.$container.find("#soundBtn").click(function () {
console.log("soundBtn click", self.isListening);
if (self.isListening) {
$(this).attr("src", "./public/images/mute.svg");
self.stopListen();
} else {
$(this).attr("src", "./public/images/sound.svg");
self.startListen();
}
});
//查看红点图片
this.$container.find("#pictureBtn").click(function () {
this.$pictureDialog.css("display", "block");
this.$pictureDialog.find("#totalPicNumber").html(this.imageBuffer.length);
var html = "";
for (var i = 0; i < this.imageBuffer.length; i++) {
var timeStr = "";
var time = (this.alarmTime - (this.startTime + this.imageBuffer[i].t)) / 1000;
if (time >= 0) {
timeStr = `触发前${time}秒`;
} else {
timeStr = `触发后${Math.abs(time)}秒`;
}
if (i === 0) {
firstTimeStr = timeStr;
}
html += `
${timeStr}
`;
}
this.$pictureDialog.find("#pictureList").html(html);
//默认显示第一张大图
this.currentPictureIndex = 0;
var firstHtml = `
${firstTimeStr}`;
this.$pictureDialog.find("#currentPictureBox").html(firstHtml);
this.$pictureDialog.find("#pictureList li").eq(0).css("border", "2px solid blue");
//切换显示当前图片
var self = this;
this.$pictureDialog.find("#pictureList li").click(function () {
self.currentPictureIndex = $(this).index();
$(this).parent().find("li").css("border", "2px solid #DDD");
$(this).css("border", "2px solid blue");
var src = $(this).find("img").attr("src");
var timeStr = $(this).find("span").html();
self.$pictureDialog.find("#currentPictureBox img").attr("src", src);
self.$pictureDialog.find("#currentPictureBox span").html(timeStr);
self.$pictureDialog.find("#currentPicNumber").html(self.currentPictureIndex + 1);
});
}.bind(this));
//上一张
this.$pictureDialog.find("#prePicBtn").click(function () {
if (this.currentPictureIndex === 0) {
return;
}
this.currentPictureIndex = this.currentPictureIndex - 1;
this.$pictureDialog.find("#pictureList li").css("border", "2px solid #DDD");
this.$pictureDialog.find("#pictureList li").eq(this.currentPictureIndex).css("border", "2px solid blue");
var src = this.$pictureDialog.find("#pictureList li").eq(this.currentPictureIndex).find("img").attr("src");
var timeStr = this.$pictureDialog.find("#pictureList li").eq(this.currentPictureIndex).find("span").html();
this.$pictureDialog.find("#currentPictureBox img").attr("src", src);
this.$pictureDialog.find("#currentPictureBox span").html(timeStr);
this.$pictureDialog.find("#currentPicNumber").html(this.currentPictureIndex + 1);
var top = this.$pictureDialog.find("#pictureList li").eq(this.currentPictureIndex).offset().top;
var height = this.$pictureDialog.find("#pictureList li").eq(this.currentPictureIndex).height();
if (top - height < 0) {
this.$pictureDialog.find("#pictureList li").eq(this.currentPictureIndex).get(0).scrollIntoView();
}
}.bind(this));
//下一张
this.$pictureDialog.find("#nextPicBtn").click(function () {
if (this.currentPictureIndex === this.imageBuffer.length - 1) {
return;
}
this.currentPictureIndex = this.currentPictureIndex + 1;
this.$pictureDialog.find("#pictureList li").css("border", "2px solid #DDD");
this.$pictureDialog.find("#pictureList li").eq(this.currentPictureIndex).css("border", "2px solid blue");
var src = this.$pictureDialog.find("#pictureList li").eq(this.currentPictureIndex).find("img").attr("src");
var timeStr = this.$pictureDialog.find("#pictureList li").eq(this.currentPictureIndex).find("span").html();
this.$pictureDialog.find("#currentPictureBox img").attr("src", src);
this.$pictureDialog.find("#currentPictureBox span").html(timeStr);
this.$pictureDialog.find("#currentPicNumber").html(this.currentPictureIndex + 1);
var top = this.$pictureDialog.find("#pictureList li").eq(this.currentPictureIndex).offset().top;
var height = this.$pictureDialog.find("#pictureList li").eq(this.currentPictureIndex).height();
var containerHeight = this.$pictureDialog.find("#pictureList").height();
if (top + height > containerHeight) {
this.$pictureDialog.find("#pictureList li").eq(this.currentPictureIndex).get(0).scrollIntoView(false);
}
}.bind(this));
//首页
this.$pictureDialog.find("#firstPicBtn").click(function () {
if (this.currentPictureIndex === 0) {
return;
}
this.currentPictureIndex = 0;
this.$pictureDialog.find("#pictureList li").css("border", "2px solid #DDD");
this.$pictureDialog.find("#pictureList li").eq(this.currentPictureIndex).css("border", "2px solid blue");
var src = this.$pictureDialog.find("#pictureList li").eq(this.currentPictureIndex).find("img").attr("src");
var timeStr = this.$pictureDialog.find("#pictureList li").eq(this.currentPictureIndex).find("span").html();
this.$pictureDialog.find("#currentPictureBox img").attr("src", src);
this.$pictureDialog.find("#currentPictureBox span").html(timeStr);
this.$pictureDialog.find("#currentPicNumber").html(this.currentPictureIndex + 1);
this.$pictureDialog.find("#pictureList li").eq(this.currentPictureIndex).get(0).scrollIntoView();
}.bind(this));
//末页
this.$pictureDialog.find("#lastPicBtn").click(function () {
if (this.currentPictureIndex === this.imageBuffer.length - 1) {
return;
}
this.currentPictureIndex = this.imageBuffer.length - 1;
this.$pictureDialog.find("#pictureList li").css("border", "2px solid #DDD");
this.$pictureDialog.find("#pictureList li").eq(this.currentPictureIndex).css("border", "2px solid blue");
var src = this.$pictureDialog.find("#pictureList li").eq(this.currentPictureIndex).find("img").attr("src");
var timeStr = this.$pictureDialog.find("#pictureList li").eq(this.currentPictureIndex).find("span").html();
this.$pictureDialog.find("#currentPictureBox img").attr("src", src);
this.$pictureDialog.find("#currentPictureBox span").html(timeStr);
this.$pictureDialog.find("#currentPicNumber").html(this.currentPictureIndex + 1);
this.$pictureDialog.find("#pictureList li").eq(this.currentPictureIndex).get(0).scrollIntoView(false);
}.bind(this));
//导出图片
this.$pictureDialog.find("#exportBtn").click(function () {
for (var i = 0; i < this.imageBuffer.length; i++) {
var time = this.startTime + this.imageBuffer[i].t;
time = moment(time).format("YYYY_MM_DD_HH_mm_ss_SSS");
var a = document.createElement('a');
a.href = this.imageBuffer[i].d;
a.download = time + ".png";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
}.bind(this));
//图片浏览-全屏
this.$pictureDialog.find("#pictureDialogFullScreenBtn").click(function () {
if (!this.pictureFullScreenFlag) {
this.pictureFullScreenFlag = true;
this.$pictureDialog.find("#pictureDialogFullScreenBtn").attr("src", "./public/images/fullscreen-exit2.svg");
} else {
this.pictureFullScreenFlag = false;
this.$pictureDialog.find("#pictureDialogFullScreenBtn").attr("src", "./public/images/fullscreen2.svg");
}
if (this.pictureFullScreenFlag) {
this.$pictureDialog.css({
width: "100%",
height: "100%",
top: 0,
left: 0
});
} else {
this.$pictureDialog.css({
width: "66%",
height: "70%",
top: "10%",
left: "17%"
});
}
}.bind(this));
//图片浏览-关闭
this.$pictureDialog.find("#pictureDialogCloseBtn").click(function () {
this.$pictureDialog.css("display", "none");
this.$pictureDialog.find("#pictureList").html("");
this.$pictureDialog.find("#currentPictureBox").html("");
}.bind(this));
this.canvas = this.$container.find("#videoscreen")[0];
this.image = this.$container.find("#imgscreen")[0];
}
Player.prototype.initCMSParserWorker = function () {
var self = this;
this.cmsParserWorker = new Worker("public/player/cmsparser.js");
this.cmsParserWorker.onmessage = function (evt) {
var objData = evt.data;
switch (objData.t) {
case kCMSHeaderRes:
self.onCMSHeaderInfo(objData.t1, objData.v, objData.a, objData.i, objData.s, objData.at);
break;
case kFinishDownload:
self.onDownloadFinish(objData.s);
break;
case kImageFrame:
self.onImageFrame(objData);
break;
case kCmsPartHeader:
self.onCmsPartHeader(objData);
break;
case kVideoFrame:
if (!self.isGetRealSize) {
self.isGetRealSize = true;
self.videoWidth = objData.w;
self.videoHeight = objData.h;
self.yLength = self.videoWidth * self.videoHeight;
self.uvLength = (self.videoWidth / 2) * (self.videoHeight / 2);
}
self.onVideoFrame(objData);
break;
case kAudioFrame:
self.onAudioFrame(objData);
break;
}
if (objData.err) {
self.$container.find("#errMsg").html(objData.err);
self.$container.find("#errMsg").css("display", "block");
}
}
};
Player.prototype.play = function (url, isLive, alarmTime, isRedVideo) {
console.log("Player.prototype.play ", url)
// window.alert("加载成功");
var ret = {
e: 0,
m: "Success"
};
if (isRedVideo) {
this.isRedVideo = isRedVideo;
}
var success = true;
if (this.playerState == playerStatePlaying) {
ret = {
e: -1,
m: "Invalid url"
};
success = false;
this.logger.logError("video is playing.");
return ret;
}
if (!url) {
ret = {
e: -2,
m: "Invalid url"
};
success = false;
this.logger.logError("[ER] playVideo error, url empty.");
return ret;
}
if (!this.cmsParserWorker) {
ret = {
e: -4,
m: "CMSParserWorker not initialized"
};
success = false;
this.logger.logError("[ER] CMSParserWorker not initialized.");
return ret;
}
this.$container.find("#videoToolBar").css("display", "flex");
this.liveUrl = url;
this.isLive = isLive;
if (alarmTime) {
if (typeof alarmTime === "string") {
this.alarmTime = Number(alarmTime);
} else {
this.alarmTime = alarmTime;
}
}
//时间进度条
if (this.isLive) {
this.$container.find("#playProgressBar").css("display", "none");
} else {
this.$container.find("#playProgressBar").css("display", "block");
}
this.cmsParserWorker.postMessage({
t: kOpenDecoderReq
});
this.displayLoop();
this.webglPlayer = new WebGLPlayer(this.canvas, {
preserveDrawingBuffer: false
});
this.cmsParserWorker.postMessage({
t: isLive ? kRequestLiveReq : kRequestHeaderReq,
u: url,
r: this.isRedVideo // add by ramon
});
if (this.isLive && !this.cmsTalk) {
this.cmsTalk = new CmsTalk()
}
return ret;
};
Player.prototype.resume = function () {
//debugger
if (this.playerState == playerStatePausing) {
this.pauseDownload = false;
this.playerState = playerStatePlaying;
if (this.isLive) {
if (this.liveUrl) {
this.cmsParserWorker.postMessage({
t: kOpenDecoderReq
});
this.cmsParserWorker.postMessage({
t: kRequestLiveReq,
u: this.liveUrl,
r: false
});
}
} else {
if (!this.isRedVideo) {
if (this.DownloadFinish) {
this.flushRate = 0;
this.currentFrameIndex = 0; //从头开始播放
this.currentVideots = 0;
this.isListeningFirst = false;
} else {
this.flowControl = false;
this.cmsParserWorker.postMessage({
t: kResumeGetUrlReq
});
}
}
}
//恢复声音播放
if (this.isListening) {
if (!this.pcmPlayer) {
this.pcmPlayer = new PCMPlayer({
encoding: "16bitInt",
channels: 1,
sampleRate: 44100,
flushingTime: 5000
});
}
this.pcmPlayer.resume();
}
}
}
Player.prototype.pause = function () {
if (this.playerState == playerStatePlaying) {
this.pauseDownload = true;
this.playerState = playerStatePausing;
if (this.isLive) {
this.cmsParserWorker.postMessage({
t: kCloseDecoderReq
});
} else {
this.cmsParserWorker.postMessage({
t: kPauseGetUrlReq
});
}
//暂停声音
this.isListeningFirst = false;
if (this.pcmPlayer) {
this.pcmPlayer.destroy();
this.pcmPlayer = null;
}
}
}
Player.prototype.skip = function (time) {
if (!this.isLive && !this.isReviewing) {
if (this.type === "video") {
for (var i = 0; i < this.videoBuffer.length; i++) {
if (this.videoBuffer[i].s == time) {
this.flushRate = 0;
this.currentFrameIndex = i;
//暂停声音
this.isListeningFirst = false;
if (this.pcmPlayer) {
this.pcmPlayer.destroy();
this.pcmPlayer = null;
}
this.pcmPlayer = new PCMPlayer({
encoding: "16bitInt",
channels: 1,
sampleRate: 44100,
flushingTime: 5000
});
this.pcmPlayer.resume();
break;
}
}
} else {
for (var i = 0; i < this.imageBuffer.length; i++) {
if (this.imageBuffer[i].t == time) {
this.flushRate = 0;
this.currentFrameIndex = i;
break;
}
}
}
}
}
Player.prototype.stop = function (flag) {
this.logger.logInfo("Stop.");
if (this.playerState == playerStateFinish) {
var ret = {
e: -1,
m: "Not playing"
};
return ret;
}
this.logger.logInfo("Closing decoder.");
this.cmsParserWorker.postMessage({
t: kCloseDecoderReq
});
//关闭worker
if (true) { // modify by ramon old:flag
this.cmsParserWorker.terminate();
this.cmsParserWorker = null;
}
this.webglPlayer = null;
if (this.pcmPlayer) {
this.pcmPlayer.destroy();
this.pcmPlayer = null;
this.logger.logInfo("Pcm player released.");
}
this.videoLoadFinish = false;
this.isListening = false;
this.pauseDownload = false;
this.frameSize = 0;
this.currentFrameIndex = 0;
this.canvas = null;
this.image = null;
this.playerState = playerStateFinish;
this.isGetRealSize = false;
this.videoWidth = 0;
this.videoHeight = 0;
this.yLength = 0;
this.uvLength = 0;
this.videoBuffer = [];
this.audioBuffer = [];
this.imageBuffer = [];
//清空容器内容
this.$container.html("");
this.$pictureDialog.remove();
if (this.cmsTalk) {
this.cmsTalk.recClose();
// delete this.cmsTalk
// this.cmsTalk = null
}
return 0;
};
Player.prototype.fullscreen = function () {
if (this.type === "video") {
if (this.webglPlayer) {
this.webglPlayer.fullscreen();
}
} else if (this.type === "image") {
this.$container.find("#imgscreen").css({
"position": "fixed",
"z-index": "10",
"top": 0,
"left": 0
});
}
};
Player.prototype.exitfullscreen = function () {
if (this.type === "video") {
if (this.webglPlayer) {
this.webglPlayer.exitfullscreen();
}
} else if (this.type === "image") {
this.$container.find("#imgscreen").css({
"position": "static",
"z-index": "auto",
"top": "auto",
"left": "auto"
});
}
};
Player.prototype.startTalk = function (callback) {
this.isTalking = true;
if (this.cmsTalk)
this.cmsTalk.startTalk(this.talkUrl, callback)
};
Player.prototype.stopTalk = function () {
this.isTalking = false;
if (this.cmsTalk)
this.cmsTalk.stopTalk()
};
Player.prototype.startListen = function () {
this.isListening = true;
if (!this.pcmPlayer) {
this.pcmPlayer = new PCMPlayer({
encoding: "16bitInt",
channels: 1,
sampleRate: 44100,
flushingTime: 5000
});
}
this.pcmPlayer.resume();
};
Player.prototype.stopListen = function () {
this.isListeningFirst = false;
this.isListening = false;
if (this.pcmPlayer) {
this.pcmPlayer.destroy();
this.pcmPlayer = null;
}
};
Player.prototype.displayLoop = function (timestamp) {
//console.log("displayLoop timestamp:",timestamp);
requestAnimationFrame(this.displayLoop.bind(this));
if (this.playerState == playerStateFinish || this.playerState == playerStatePausing) {
if (this.isLive) {
while (this.videoBuffer.length > 0) {
this.videoBuffer.shift();
}
while (this.audioBuffer.length > 0) {
this.audioBuffer.shift();
}
}
return false;
}
if (this.isLive) {
//实时视频
//视频流
if (this.videoBuffer.length > 0) {
var videoFrame = this.videoBuffer[0];
if (this.displayVideoFrame(videoFrame)) {
this.videoBuffer.shift();
}
}
//声音流
if (this.audioBuffer.length > 0) {
var audioFrame = this.audioBuffer[0];
if (this.displayAudioFrame(audioFrame)) {
this.audioBuffer.shift();
}
}
} else {
//红点视频
if (this.type === "video") {
//视频流
if (this.isRedVideo) {
//console.log("displayLoop : isRedVideo :videoPartHeaders.length:",this.videoPartHeaders.length," -- videoBuffer:",this.videoBuffer.length);
if (0 == this.displayInterval) {
this.displayInterval = Math.round(1000 / this.videoRate) - 20;
}
if ((timestamp - this.diplayLastTick) >= this.displayInterval) {
if (this.videoBuffer.length > 0) {
var frame = this.videoBuffer.shift();
if (frame) {
this.currentVideots = frame.s;
//console.log("displayVideoFrame timestamp:",timestamp ," displayInterval:",this.displayInterval);
this.displayVideoFrame(frame);
this.updateTimeTrack(frame.s, false);
}
this.diplayLastTick = timestamp;
}
}
if (this.videoBuffer.length < 20) {
while (this.currentFrameIndex < this.videoPartHeaders.length) {
var part = this.videoPartHeaders[this.currentFrameIndex];
// console.log(this.currentFrameIndex, part.type)
if (part.type == 'a') {
this.currentFrameIndex++
} else {
this.cmsParserWorker.postMessage({
t: kDecodeVideo,
index: this.currentFrameIndex++
});
break
}
}
}
//声音播放
if (this.isListening && this.audioBuffer.length > 0) {
if (!this.isListeningFirst) {
for (var i = 0; i < this.audioBuffer.length; i++) {
// console.log("audioBuffer", this.audioBuffer[i].s, this.currentVideots)
if (this.audioBuffer[i].s >= this.currentVideots - 60) {
this.currentAudioIndex = i;
if (!this.pcmPlayer) {
this.pcmPlayer = new PCMPlayer({
encoding: "16bitInt",
channels: 1,
sampleRate: 44100,
flushingTime: 5000
});
this.pcmPlayer.resume();
}
this.displayAudioFrame(this.audioBuffer[i], true);
break;
}
}
this.isListeningFirst = true;
} else {
if (this.currentAudioIndex < this.audioBuffer.length - 1) {
this.currentAudioIndex++;
this.displayAudioFrame(this.audioBuffer[this.currentAudioIndex]);
}
}
}
//播放结束
if (this.isReviewing) {
//循环播放红点画面
if (this.currentFrameIndex + 1 > this.alarmBlockEndFrameIndex) {
this.currentFrameIndex = this.alarmBlockStartFrameIndex;
this.currentVideots = this.videoBuffer[this.currentFrameIndex].s;
if (this.isListening) {
this.isListeningFirst = false;
if (this.pcmPlayer) {
this.pcmPlayer.destroy();
this.pcmPlayer = null;
}
}
}
} else {
//从头开始播放
if (this.frameSize > 0 && this.currentFrameIndex >= this.frameSize) {
this.flushRate = 0;
this.currentFrameIndex = 0;
this.currentVideots = 0;
this.isListeningFirst = false;
//重复播放不会断累积缓冲,导致延时, 没找到如何清空缓存,
if (this.pcmPlayer) {
this.pcmPlayer.destroy();
this.pcmPlayer = null;
}
}
}
} else {
//普通录像
if (this.videoPartHeaders.length > 0) {
if (0 == this.displayInterval) {
this.displayInterval = Math.round(1000 / this.videoRate) - 20;
}
if ((timestamp - this.diplayLastTick) >= this.displayInterval) {
if (this.videoBuffer.length > 0) {
var frame = this.videoBuffer.shift();
if (frame) {
this.currentVideots = frame.s;
this.displayVideoFrame(frame);
this.updateTimeTrack(frame.s, false);
}
this.diplayLastTick = timestamp;
}
}
if (this.videoBuffer.length < 20) {
while (this.currentFrameIndex < this.videoPartHeaders.length) {
var part = this.videoPartHeaders[this.currentFrameIndex];
// console.log(this.currentFrameIndex, part.type)
if (part.type == 'a') {
this.currentFrameIndex++
} else {
this.cmsParserWorker.postMessage({
t: kDecodeVideo,
index: this.currentFrameIndex++
});
break
}
}
}
/////// flowControl add by ramon
if ((this.currentFrameIndex < this.videoPartHeaders.length) && (!this.DownloadFinish)) {
var buf_count = this.videoPartHeaders.length - this.currentFrameIndex;
console.log("buf_count:", buf_count, " ", this.flowControl);
if (buf_count > 400) {
if (false == this.flowControl) {
this.flowControl = true;
this.cmsParserWorker.postMessage({
t: kPauseGetUrlReq
});
console.log("------Pause GetUrlReq---------");
}
} else if (buf_count < 200) {
if (true == this.flowControl) {
this.flowControl = false;
this.cmsParserWorker.postMessage({
t: kResumeGetUrlReq
});
console.log("------Resume GetUrlReq---------");
}
}
}
//声音播放
if (this.isListening && this.audioBuffer.length > 0) {
if (!this.isListeningFirst) {
for (var i = 0; i < this.audioBuffer.length; i++) {
// console.log("audioBuffer", this.audioBuffer[i].s, this.currentVideots)
if (this.audioBuffer[i].s >= this.currentVideots - 60) {
this.currentAudioIndex = i;
if (!this.pcmPlayer) {
this.pcmPlayer = new PCMPlayer({
encoding: "16bitInt",
channels: 1,
sampleRate: 44100,
flushingTime: 5000
});
this.pcmPlayer.resume();
}
this.displayAudioFrame(this.audioBuffer[i], true);
break;
}
}
this.isListeningFirst = true;
} else {
if (this.currentAudioIndex < this.audioBuffer.length - 1) {
this.currentAudioIndex++;
this.displayAudioFrame(this.audioBuffer[this.currentAudioIndex]);
}
}
}
if (this.frameSize > 0 && this.currentFrameIndex >= this.frameSize) {
if (this.DownloadFinish) { //播放结束
if (this.isReviewing) {
this.flushRate = 0;
this.currentFrameIndex = 0; //从头开始播放
this.currentVideots = 0;
this.isListeningFirst = false;
//重复播放不会断累积缓冲,导致延时, 没找到如何清空缓存,
if (this.pcmPlayer) {
this.pcmPlayer.destroy();
this.pcmPlayer = null;
}
} else {
if (!this.pauseDownload) {
this.$container.find("#pauseBtn").attr("src", "./public/images/play.svg");
this.pause();
}
}
}
}
}
// if (this.videoBuffer.length > 0) {
// // console.log("this.videoBuffer.length:", this.videoBuffer.length);
// var videoFrame = this.videoBuffer[0];
// if (this.displayVideoFrame(videoFrame)) {
// this.videoBuffer.shift();
// }
// if (this.videoBuffer.length > 400) {
// if (false == this.flowControl) {
// this.flowControl = true;
// this.cmsParserWorker.postMessage({
// t: kPauseGetUrlReq
// });
// //console.log("------Pause GetUrlReq---------");
// }
// } else if (this.videoBuffer.length < 200) {
// if (true == this.flowControl) {
// this.flowControl = false;
// this.cmsParserWorker.postMessage({
// t: kResumeGetUrlReq
// });
// //console.log("------Resume GetUrlReq---------");
// }
// }
// }
// //声音流
// if (this.audioBuffer.length > 0) {
// var audioFrame = this.audioBuffer[0];
// if (this.displayAudioFrame(audioFrame)) {
// this.audioBuffer.shift();
// }
// }
}
} else {
// 图片流
if (this.imageBuffer.length < 1)
return
if (this.flushRate > 0) {
this.flushRate--;
return
}
//console.log("图片流", this.imageBuffer.length, this.currentFrameIndex, this.isReviewing)
var frame = this.imageBuffer[this.currentFrameIndex];
if (frame) {
this.flushRate = Math.ceil(60 / this.imageRate);
this.image.src = this.imageBuffer[this.currentFrameIndex].d;
this.updateTimeTrack(this.imageBuffer[this.currentFrameIndex].t);
this.currentFrameIndex++;
}
//播放结束
if (this.isReviewing) {
//循环播放红点画面
if (this.currentFrameIndex + 1 > this.alarmBlockEndFrameIndex) {
this.currentFrameIndex = this.alarmBlockStartFrameIndex;
}
} else {
//从头开始播放
if (this.frameSize > 0 && this.currentFrameIndex >= this.frameSize) {
this.flushRate = 0;
this.currentFrameIndex = 0;
}
}
}
}
};
Player.prototype.displayVideoFrame = function (frame) {
if (this.playerState == playerStateFinish || this.playerState == playerStatePausing) {
return false;
}
if (this.videoBuffer.length < 2 && this.pauseDownload) {
this.pauseDownload = false;
this.cmsParserWorker.postMessage({
t: kResumeGetUrlReq
});
}
if (this.webglPlayer) {
var data = new Uint8Array(frame.d);
//console.log("displayVideoFrame:",data.length);
this.webglPlayer.renderFrame(data, this.videoWidth, this.videoHeight, this.yLength, this.uvLength);
delete data;
return true;
} else {
return false;
}
};
Player.prototype.displayAudioFrame = function (frame, flushcache) {
if (this.playerState == playerStateFinish || this.playerState == playerStatePausing || !this.isListening) {
return false;
}
if (this.audioBuffer.length < 2 && this.pauseDownload) {
this.pauseDownload = false;
this.cmsParserWorker.postMessage({
t: kResumeGetUrlReq
});
}
if (this.pcmPlayer) {
this.pcmPlayer.play(new Uint8Array(frame.d), flushcache);
return true;
} else {
return false;
}
}
Player.prototype.onCMSHeaderInfo = function (videoType, videoTrack, audioTrack, imageTrack, startTime, alarmTime) {
if (startTime && typeof startTime === "string") {
startTime = Number(startTime);
}
if (alarmTime && typeof alarmTime === "string") {
alarmTime = Number(alarmTime);
}
this.type = videoType;
this.startTime = startTime;
if (alarmTime) {
this.alarmTime = alarmTime;
}
this.playerState = playerStatePlaying;
if ((!this.isLive) && (!this.isRedVideo)) { // modify by ramon
this.cmsParserWorker.postMessage({
t: kRequestBodyReq
});
}
this.$container.find(".videoToolBarIcon").css("display", "none");
if (this.type === "video") {
this.$container.find("#imgscreen").css("display", "none");
if (this.isLive) {
this.$container.find(".liveVideo").css("display", "inline-block");
} else {
this.$container.find(".redVideo").css("display", "inline-block");
}
if (videoTrack) {
this.videoWidth = videoTrack.width;
this.videoHeight = videoTrack.height;
this.videoRate = videoTrack.rate;
this.yLength = this.videoWidth * this.videoHeight;
this.uvLength = (this.videoWidth / 2) * (this.videoHeight / 2);
this.flushRate = Math.round(60 / this.videoRate);
}
if (audioTrack) {
this.pcmPlayer = new PCMPlayer({
encoding: "16bitInt",
channels: 1,
sampleRate: 44100,
flushingTime: 5000
});
}
} else if (this.type === "image") {
this.$container.find("#imgscreen").css("display", "block");
if (this.isLive) {
this.$container.find(".liveImg").css("display", "inline-block");
} else {
this.$container.find(".redImg").css("display", "inline-block");
}
if (imageTrack) {
this.imageWidth = imageTrack.width;
this.imageHeight = imageTrack.height;
// this.imageRate = imageTrack.rate;
this.imageRate = 3;
this.flushRate = Math.ceil(60 / this.imageRate);
}
}
}
Player.prototype.onDownloadFinish = function (size) {
// if (this.type === "video") {
// this.frameSize = this.videoBuffer.length;
// } else {
this.frameSize = size;
// }
this.DownloadFinish = true;
}
Player.prototype.onImageFrame = function (frame) {
var encodeData = this.arrayBufferToBase64(frame.d);
var imageData = "data:image/jpeg;base64," + encodeData;
var data = {
d: imageData,
t: frame.s
};
this.imageBuffer.push(data);
//当前获取到流的相对时间
this.updateTimeTrack(data.t, true);
};
Player.prototype.arrayBufferToBase64 = function (buffer) {
var binary = '';
for (var i = 0; i < buffer.length; i++) {
binary += String.fromCharCode(buffer[i]);
}
// for (var i = 0; i < buffer.length; i++) {
// for (var j = 0; j < buffer[i].length; j++) {
// binary += String.fromCharCode(buffer[i][j]);
// }
// }
return window.btoa(binary);
}
Player.prototype.onCmsPartHeader = function (part) {
if (this.isLive) {
while (this.videoPartHeaders.length > 10) {
this.videoPartHeaders.shift();
}
}
this.videoPartHeaders.push(part);
if (part.type != 'a')
this.updateTimeTrack(part.ts, true);
};
Player.prototype.onVideoFrame = function (frame) {
if (this.isLive) {
while (this.videoBuffer.length > 10) {
this.videoBuffer.shift();
}
}
this.videoBuffer.push(frame);
// this.updateTimeTrack(frame.s, true);
};
Player.prototype.onAudioFrame = function (frame) {
if (this.isLive) {
while (this.audioBuffer.length > 10) {
this.audioBuffer.shift();
}
}
this.audioBuffer.push(frame);
// console.log("onAudioFrame", this.audioBuffer.length)
}
//红点视频-更新时间进度
Player.prototype.updateTimeTrack = function (currentTime, loadBuffer) {
if (this.isLive) {
return;
}
var self = this;
if (loadBuffer) {
//时间刻度
var cursorNum = this.$container.find("#videoTimeTrack").find("li").length;
if ((Math.floor(currentTime / 1000) + 1) > cursorNum) {
var time = moment(this.startTime).add(Math.floor(currentTime / 1000), "seconds").format("HH:mm:ss");
if (cursorNum === 0) {
var t = currentTime;
} else if (cursorNum === 1) {
var t = this.preCurrentTime;
} else {
var t = this.preCurrentTime2;
}
this.preCurrentTime2 = currentTime;
this.$container.find("#videoTimeTrack").append("");
this.$container.find("#timeProgress").append("");
}
var cursorNum2 = this.$container.find("#videoTimeTrack").find("li").length;
this.$container.find("#videoTimeTrack").find("li").css("width", (100 / cursorNum2) + "%");
this.$container.find("#timeProgress").find("li").css("width", (100 / cursorNum2) + "%");
this.$container.find("#timeProgress li").unbind("click").click(function () {
var t = $(this).attr("t");
self.skip(t);
});
//红点视频范围
if (this.startTime + currentTime >= this.alarmTime) {
this.$container.find("#alarmblock").css("display", "block");
var per = (4000 / currentTime) * 100;
this.$container.find("#alarmblock").css("width", per + "%");
var left = ((this.alarmTime - 2000 - this.startTime) / currentTime) * 100;
this.$container.find("#alarmblock").css("left", left + "%");
}
this.preCurrentTime = currentTime;
} else {
//播放进度条
var index2 = 0;
this.$container.find("#timeProgress li").each(function (index) {
var time = $(this).attr("t");
if (index < self.$container.find("#timeProgress li").length - 1) {
var time2 = self.$container.find("#timeProgress li").eq(index + 1).attr("t");
if (currentTime >= time && currentTime < time2) {
index2 = index;
return false;
}
} else {
if (currentTime >= time) {
index2 = index;
return false;
}
}
});
var left = this.$container.find("#videoTimeTrack").find("li").eq(index2).position().left;
if (index2 < this.$container.find("#timeProgress li").length - 1) {
this.$container.find("#timeTrack").css("left", left - 10);
} else {
var lastTimeTrack = this.$container.find("#timeProgress").find("li").eq(index2).attr("t");
if (Math.floor(currentTime / 1000) > Math.floor(lastTimeTrack / 1000)) {
var lastTimeWidth = this.$container.find("#videoTimeTrack").find("li").eq(index2).width();
this.$container.find("#timeTrack").css("left", left + lastTimeWidth - 10);
} else {
this.$container.find("#timeTrack").css("left", left - 10);
}
}
}
}