Browse Source

增加离屏渲染功能

worker
langhuihui 4 years ago
parent
commit
60c050ee67
  1. 31
      .vuepress/components/renderer.js
  2. 22
      .vuepress/public/ff.js
  3. 2
      .vuepress/public/ff_wasm.js
  4. BIN
      .vuepress/public/ff_wasm.wasm
  5. 18
      .vuepress/public/libhevc_aac.js
  6. 2
      .vuepress/public/libhevc_aac_wasm.js
  7. BIN
      .vuepress/public/libhevc_aac_wasm.wasm
  8. 53
      Jessibuca.cpp
  9. 159
      Jessibuca.js
  10. 3
      make.py
  11. 19
      public/264_aac.js
  12. 1
      public/264_aac_wasm.js
  13. BIN
      public/264_aac_wasm.wasm
  14. 17
      public/264_mp3.js
  15. 1
      public/264_mp3_wasm.js
  16. BIN
      public/264_mp3_wasm.wasm
  17. 535
      public/ajax.js
  18. 16
      public/avc.js
  19. 20
      public/cocos.js
  20. 1
      public/ff.js
  21. BIN
      public/ff.wasm
  22. 200
      public/ff_aac.html
  23. 28
      public/ff_aac.js
  24. 1
      public/ff_aac_wasm.js
  25. BIN
      public/ff_aac_wasm.wasm
  26. 200
      public/ff_mp3.html
  27. 26
      public/ff_mp3.js
  28. 1
      public/ff_mp3_wasm.js
  29. BIN
      public/ff_mp3_wasm.wasm
  30. 1
      public/ff_wasm.js
  31. BIN
      public/ff_wasm.wasm
  32. 1
      public/flash.html
  33. 20
      public/hevc.js
  34. 199
      public/hevc_aac.html
  35. 22
      public/hevc_aac.js
  36. 21
      public/hevc_mp3.js
  37. 239
      public/index.html
  38. 23
      public/libde265_aac.js
  39. 20
      public/libde265_mp3.js
  40. BIN
      public/live_test.swf
  41. 1709
      public/renderer.js

31
.vuepress/components/renderer.js

@ -55,7 +55,7 @@
this._opt.keepScreenOn = opt.keepScreenOn === true;
this._opt.rotate = typeof opt.rotate === 'number' ? opt.rotate : 0;
if (!opt.forceNoGL) this._initContextGL();
if (!opt.forceNoGL && !this.supportOffscreen()) this._initContextGL();
this._audioContext = new (window.AudioContext || window.webkitAudioContext)();
this._gainNode = this._audioContext.createGain();
this._audioEnabled(true);
@ -414,6 +414,7 @@
switch (msg.cmd) {
case "init":
_this._opt.isDebug && console.log("decoder worker init")
_this.setBufferTime(_this._opt.videoBuffer);
if (!_this._hasLoaded) {
_this._opt.isDebug && console.log("has loaded");
@ -427,7 +428,11 @@
_this._canvasElement.height = msg.h;
_this.onInitSize();
_this.resize();
_this._trigger('videoInfo', {w: msg.w, h: msg.h});
_this._trigger('videoInfo', { w: msg.w, h: msg.h });
if (_this.supportOffscreen()) {
const offscreen = _this._canvasElement.transferControlToOffscreen();
this.postMessage({ cmd: "init", canvas: offscreen }, [offscreen])
}
if (_this.isWebGL()) {
} else {
@ -441,16 +446,17 @@
_this._opt.isDebug && console.log("clear check loading timeout");
_this._clearCheckLoading();
}
if (_this.playing) {
if (_this.playing && !_this.supportOffscreen()) {
if (_this.isWebGL()) {
_this._drawNextOutputPictureGL(msg.output);
} else {
_this._drawNextOutputPictureRGBA(msg.buffer);
}
}
// _this._decoderWorker.postMessage({ cmd: "setBuffer", buffer: msg.output }, msg.output.map(x => x.buffer))
_this._trigger('timeUpdate', msg.ts);
_this.onTimeUpdate(msg.ts);
_this._updateStats({bps: msg.bps, ts: msg.ts});
_this._updateStats({ bps: msg.bps, ts: msg.ts });
_this._checkHeart();
break
case "initAudio":
@ -797,7 +803,7 @@
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], 'file', {type});
return new File([u8arr], 'file', { type });
}
function _downloadImg(content, fileName) {
@ -969,8 +975,11 @@
* Returns true if the canvas supports WebGL
*/
Jessibuca.prototype.isWebGL = function () {
return !!this._contextGL;
return this.supportOffscreen() || !!this._contextGL;
};
Jessibuca.prototype.supportOffscreen = function () {
return typeof this._canvasElement.transferControlToOffscreen == 'function'
}
/**
* set timeout
* @param time
@ -1016,7 +1025,7 @@
var contextName = validContextNames[nameIndex];
try {
var contextOptions = {preserveDrawingBuffer: true};
var contextOptions = { preserveDrawingBuffer: true };
if (this._opt.contextOptions) {
contextOptions = Object.assign(contextOptions, this._opt.contextOptions);
}
@ -1269,7 +1278,7 @@
this._audioPlayBuffers = [];
this._audioPlaying = false;
delete this._playAudio;
this._decoderWorker.postMessage({cmd: "close"})
this._decoderWorker.postMessage({ cmd: "close" })
if (this._wakeLock) {
this._wakeLock.release();
@ -1355,10 +1364,10 @@
if (needDelay) {
var _this = this;
setTimeout(function () {
_this._decoderWorker.postMessage({cmd: "play", url: _this.playUrl, isWebGL: _this.isWebGL()})
_this._decoderWorker.postMessage({ cmd: "play", url: _this.playUrl, isWebGL: _this.isWebGL() })
}, 300);
} else {
this._decoderWorker.postMessage({cmd: "play", url: this.playUrl, isWebGL: this.isWebGL()})
this._decoderWorker.postMessage({ cmd: "play", url: this.playUrl, isWebGL: this.isWebGL() })
}
};
/**
@ -1549,7 +1558,7 @@
*/
Jessibuca.prototype.changeBuffer = function (buffer) {
this._stats.buf = Number(buffer) * 1000;
this._decoderWorker.postMessage({cmd: "setVideoBuffer", time: Number(buffer)});
this._decoderWorker.postMessage({ cmd: "setVideoBuffer", time: Number(buffer) });
};
/**
* 设置最大缓冲时长单位秒播放器会自动消除延迟

22
.vuepress/public/ff.js
File diff suppressed because it is too large
View File

2
.vuepress/public/ff_wasm.js
File diff suppressed because it is too large
View File

BIN
.vuepress/public/ff_wasm.wasm

18
.vuepress/public/libhevc_aac.js
File diff suppressed because it is too large
View File

2
.vuepress/public/libhevc_aac_wasm.js
File diff suppressed because it is too large
View File

BIN
.vuepress/public/libhevc_aac_wasm.wasm

53
Jessibuca.cpp

@ -41,7 +41,7 @@ struct Jessica
clock_t lastVideoTimeStamp = 0;
clock_t firstVideoTimeStamp = 0;
clock_t firstTimeStamp = 0;
bool dropping = false; //是否正在丢帧
int idr_count = 0; //是否正在丢帧
int bytesCount = 0;
PROP(isPlaying, bool)
PROP(flvMode, bool)
@ -118,7 +118,7 @@ struct Jessica
auto now = clock();
if (now > lastDataTime)
{
bps = bytesCount * 1000.0 / (now - lastDataTime);
bps = bytesCount * 1000000.0 / (now - lastDataTime);
lastDataTime = now;
bytesCount = 0;
}
@ -274,7 +274,7 @@ struct Jessica
{
if (videoDecoder.isAVCSequence(data))
{
call<void>("firstVideo", u32(_timestamp));
call<void>("firstVideo", int(_timestamp));
videoDecoder.decode(data);
waitFirstVideo = false;
emscripten_log(0, "video info set! video buffer: %dms", videoBuffer);
@ -286,8 +286,9 @@ struct Jessica
return;
if (videoBuffer == 0)
{
if (call<u32>("getDelay", _timestamp) > 1000)
if (call<int>("getDelay", int(_timestamp)) > 5000)
{
emscripten_log(0, "delay: %dms", call<int>("getDelay", int(_timestamp)));
return;
}
videoDecoder.timestamp = _timestamp;
@ -296,6 +297,10 @@ struct Jessica
else
{
videoBuffers.emplace(_timestamp, data);
if (videoDecoder.isAVCSequence(data))
{
idr_count++;
}
auto &v = videoBuffers.front();
if (lastVideoTimeStamp - v.timestamp > videoBuffer)
{
@ -309,34 +314,40 @@ struct Jessica
}
lastVideoTimeStamp = _timestamp;
}
void popVBuffer()
{
if (videoDecoder.isAVCSequence(videoBuffers.front().data))
{
idr_count--;
}
videoBuffers.pop();
}
void decodeVideoBuffer()
{
if (videoBuffers.size() > 1)
{
auto &v = videoBuffers.front();
if (lastVideoTimeStamp - v.timestamp > videoBuffer)
videoDecoder.timestamp = v.timestamp;
auto start = clock();
videoDecoder.decode(v.data);
auto cost = clock() - start;
popVBuffer();
auto timeout = videoBuffers.front().timestamp - v.timestamp;
if (timeout > cost)
{
timeout = timeout - cost * 1000;
}
if (idr_count > 10)
{
videoBuffers.pop();
while (videoBuffers.size() > 0 && !videoDecoder.isAVCSequence(videoBuffers.front().data))
{
videoBuffers.pop();
popVBuffer();
}
if (videoBuffers.size()==0)
{
bufferIsPlaying = false;
return;
}
v = videoBuffers.front();
}
videoDecoder.timestamp = v.timestamp;
videoBuffers.pop();
if (videoBuffers.size() > 1)
{
auto timeout = videoBuffers.front().timestamp - v.timestamp;
val::global("setTimeout")(bind("decodeVideoBuffer"), timeout);
decodeVideoBuffer();
return;
}
videoDecoder.decode(v.data);
val::global("setTimeout")(bind("decodeVideoBuffer"), timeout);
return;
}
bufferIsPlaying = false;
}

159
Jessibuca.js

@ -26,6 +26,120 @@ mergeInto(LibraryManager.library, {
postMessage({ cmd: "init" })
}
Module.Jessibuca = Module.Jessica.extend("Jessibuca", {
_initProgram: function () {
var gl = this._contextGL;
var vertexShaderScript = [
'attribute vec4 vertexPos;',
'attribute vec4 texturePos;',
'varying vec2 textureCoord;',
'void main()',
'{',
'gl_Position = vertexPos;',
'textureCoord = texturePos.xy;',
'}'
].join('\n');
var fragmentShaderScript = [
'precision highp float;',
'varying highp vec2 textureCoord;',
'uniform sampler2D ySampler;',
'uniform sampler2D uSampler;',
'uniform sampler2D vSampler;',
'const mat4 YUV2RGB = mat4',
'(',
'1.1643828125, 0, 1.59602734375, -.87078515625,',
'1.1643828125, -.39176171875, -.81296875, .52959375,',
'1.1643828125, 2.017234375, 0, -1.081390625,',
'0, 0, 0, 1',
');',
'void main(void) {',
'highp float y = texture2D(ySampler, textureCoord).r;',
'highp float u = texture2D(uSampler, textureCoord).r;',
'highp float v = texture2D(vSampler, textureCoord).r;',
'gl_FragColor = vec4(y, u, v, 1) * YUV2RGB;',
'}'
].join('\n');
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderScript);
gl.compileShader(vertexShader);
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
console.log('Vertex shader failed to compile: ' + gl.getShaderInfoLog(vertexShader));
}
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderScript);
gl.compileShader(fragmentShader);
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
console.log('Fragment shader failed to compile: ' + gl.getShaderInfoLog(fragmentShader));
}
var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.log('Program failed to compile: ' + gl.getProgramInfoLog(program));
}
gl.useProgram(program);
this._shaderProgram = program;
}, _initBuffers: function () {
var gl = this._contextGL;
var program = this._shaderProgram;
var vertexPosBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 1, -1, 1, 1, -1, -1, -1]), gl.STATIC_DRAW);
var vertexPosRef = gl.getAttribLocation(program, 'vertexPos');
gl.enableVertexAttribArray(vertexPosRef);
gl.vertexAttribPointer(vertexPosRef, 2, gl.FLOAT, false, 0, 0);
var texturePosBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, texturePosBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 0, 0, 0, 1, 1, 0, 1]), gl.STATIC_DRAW);
var texturePosRef = gl.getAttribLocation(program, 'texturePos');
gl.enableVertexAttribArray(texturePosRef);
gl.vertexAttribPointer(texturePosRef, 2, gl.FLOAT, false, 0, 0);
this._texturePosBuffer = texturePosBuffer;
}, _initTexture: function () {
var gl = this._contextGL;
var textureRef = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, textureRef);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.bindTexture(gl.TEXTURE_2D, null);
return textureRef;
}, _initTextures: function () {
var gl = this._contextGL;
var program = this._shaderProgram;
var yTextureRef = this._initTexture();
var ySamplerRef = gl.getUniformLocation(program, 'ySampler');
gl.uniform1i(ySamplerRef, 0);
this._yTextureRef = yTextureRef;
var uTextureRef = this._initTexture();
var uSamplerRef = gl.getUniformLocation(program, 'uSampler');
gl.uniform1i(uSamplerRef, 1);
this._uTextureRef = uTextureRef;
var vTextureRef = this._initTexture();
var vSamplerRef = gl.getUniformLocation(program, 'vSampler');
gl.uniform1i(vSamplerRef, 2);
this._vTextureRef = vTextureRef;
},
__construct: function () {
this.__parent.__construct.call(this, this);
this.audioCache = []
@ -178,16 +292,41 @@ mergeInto(LibraryManager.library, {
postMessage({ cmd: "initSize", w: w, h: h })
this.buffers = [[], [], []]
var size = w * h
var qsize = size >> 2
//this.sharedBuffer = new SharedArrayBuffer(size * 3 >> 1);
if (this.isWebGL) {
this.draw = function (compositionTime, ts) {
var gl = this._contextGL
var y = HEAPU32[dataPtr];
var u = HEAPU32[dataPtr + 1];
var v = HEAPU32[dataPtr + 2];
// console.log(y, u, v);
var outputArray = [HEAPU8.subarray(y, y + size), HEAPU8.subarray(u, u + (size >> 2)), HEAPU8.subarray(v, v + (size >> 2))];
var outputArray = [HEAPU8.subarray(y, y + size), HEAPU8.subarray(u, u + qsize), HEAPU8.subarray(v, v + (qsize))];
//arrayBufferCopy(HEAPU8.subarray(y, y + size), this.sharedBuffer, 0, size)
//arrayBufferCopy(HEAPU8.subarray(u, u + (qsize)), this.sharedBuffer, size, qsize)
//arrayBufferCopy(HEAPU8.subarray(v, v + (qsize)), this.sharedBuffer, size + qsize, qsize)
this.setBuffer(outputArray)
// var outputArray = [new Uint8Array(this.buffer, 0, size), new Uint8Array(this.buffer, size, size >> 2), new Uint8Array(this.buffer, size + (size >> 2), size >> 2)]
postMessage({ cmd: "render", output: outputArray, compositionTime: compositionTime, ts: ts, bps: this.bps }, [outputArray[0].buffer, outputArray[1].buffer, outputArray[2].buffer])
//var outputArray = [new Uint8Array(this.sharedBuffer, 0, size), new Uint8Array(this.sharedBuffer, size, qsize), new Uint8Array(this.sharedBuffer, size + (qsize), qsize)]
if (gl) {
var yTextureRef = this._yTextureRef;
var uTextureRef = this._uTextureRef;
var vTextureRef = this._vTextureRef;
gl.viewport(0, 0, w, h);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, yTextureRef);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, w, h, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, HEAPU8.subarray(y, y + size));
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, uTextureRef);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, w / 2, h / 2, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, HEAPU8.subarray(u, u + qsize));
gl.activeTexture(gl.TEXTURE2);
gl.bindTexture(gl.TEXTURE_2D, vTextureRef);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, w / 2, h / 2, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, HEAPU8.subarray(v, v + (qsize)));
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
postMessage({ cmd: "render", compositionTime: compositionTime, ts: ts, bps: this.bps, delay: this.delay })
} else {
postMessage({ cmd: "render", compositionTime: compositionTime, ts: ts, bps: this.bps, delay: this.delay, output: outputArray }, outputArray.map(x => x.buffer))
}
};
} else {
var outputArray = HEAPU8.subarray(dataPtr, dataPtr + (w * h << 2));
@ -202,13 +341,25 @@ mergeInto(LibraryManager.library, {
this.firstTimestamp = Date.now()
},
getDelay: function (timestamp) {
return this.delay = (timestamp - this.firstVideoTimestamp) - (Date.now() - this.firstTimestamp)
this.delay = (timestamp - this.firstVideoTimestamp) - (Date.now() - this.firstTimestamp)
return this.delay
},
init: function (msg) {
var canvas = msg.canvas
var gl = canvas.getContext("webgl");
this._contextGL = gl
this._initProgram();
this._initBuffers();
this._initTextures();
}
});
var decoder = new Module.Jessibuca()
self.onmessage = function (event) {
var msg = event.data
switch (msg.cmd) {
case "init":
decoder.init(msg)
break
case "getProp":
postMessage({ cmd: "getProp", value: decoder[msg.prop] })
break

3
make.py

@ -27,7 +27,8 @@ sargs = {
'ASSERTIONS': 0,
'NO_EXIT_RUNTIME': 1,
'ERROR_ON_UNDEFINED_SYMBOLS': 0,
'DISABLE_EXCEPTION_CATCHING': 1
'DISABLE_EXCEPTION_CATCHING': 1,
'ALLOW_MEMORY_GROWTH':1
# 'INVOKE_RUN':1
# 'DEMANGLE_SUPPORT':1
}

19
public/264_aac.js
File diff suppressed because it is too large
View File

1
public/264_aac_wasm.js
File diff suppressed because it is too large
View File

BIN
public/264_aac_wasm.wasm

17
public/264_mp3.js
File diff suppressed because it is too large
View File

1
public/264_mp3_wasm.js
File diff suppressed because it is too large
View File

BIN
public/264_mp3_wasm.wasm

535
public/ajax.js

@ -1,535 +0,0 @@
// a simple ajax
!(function () {
var jsonType = 'application/json';
var htmlType = 'text/html';
var xmlTypeRE = /^(?:text|application)\/xml/i;
var blankRE = /^\s*$/; // \s
/*
* default setting
* */
var _settings = {
type: "GET",
beforeSend: noop,
success: noop,
error: noop,
complete: noop,
context: null,
xhr: function () {
return new window.XMLHttpRequest();
},
accepts: {
json: jsonType,
xml: 'application/xml, text/xml',
html: htmlType,
text: 'text/plain'
},
crossDomain: false,
timeout: 0,
username: null,
password: null,
processData: true,
promise: noop
};
function noop() {
}
var ajax = function (options) {
//
var settings = extend({}, options || {});
//
for (var key in _settings) {
if (settings[key] === undefined) {
settings[key] = _settings[key];
}
}
//
try {
var q = {};
var promise = new Promise(function (resolve, reject) {
q.resolve = resolve;
q.reject = reject;
});
promise.resolve = q.resolve;
promise.reject = q.reject;
settings.promise = promise;
}
catch (e) {
//
settings.promise = {
resolve: noop,
reject: noop
};
}
//
if (!settings.crossDomain) {
settings.crossDomain = /^([\w-]+:)?\/\/([^\/]+)/.test(settings.url) && RegExp.$2 !== window.location.href;
}
var dataType = settings.dataType;
// jsonp
if (dataType === 'jsonp') {
//
var hasPlaceholder = /=\?/.test(settings.url);
if (!hasPlaceholder) {
var jsonpCallback = (settings.jsonp || 'callback') + '=?';
settings.url = appendQuery(settings.url, jsonpCallback)
}
return JSONP(settings);
}
// url
if (!settings.url) {
settings.url = window.location.toString();
}
//
serializeData(settings);
var mime = settings.accepts[dataType]; // mime
var baseHeader = {}; // header
var protocol = /^([\w-]+:)\/\//.test(settings.url) ? RegExp.$1 : window.location.protocol; // protocol
var xhr = _settings.xhr();
var abortTimeout;
// X-Requested-With header
// For cross-domain requests, seeing as conditions for a preflight are
// akin to a jigsaw puzzle, we simply never set it to be sure.
// (it can always be set on a per-request basis or even using ajaxSetup)
// For same-domain requests, won't change header if already provided.
if (!settings.crossDomain && !baseHeader['X-Requested-With']) {
baseHeader['X-Requested-With'] = 'XMLHttpRequest';
}
// mime
if (mime) {
//
baseHeader['Accept'] = mime;
if (mime.indexOf(',') > -1) {
mime = mime.split(',', 2)[0]
}
//
xhr.overrideMimeType && xhr.overrideMimeType(mime);
}
// contentType
if (settings.contentType || (settings.data && settings.type.toUpperCase() !== 'GET')) {
baseHeader['Content-Type'] = (settings.contentType || 'application/x-www-form-urlencoded; charset=UTF-8');
}
// headers
settings.headers = extend(baseHeader, settings.headers || {});
// on ready state change
xhr.onreadystatechange = function () {
// readystate
if (xhr.readyState === 4) {
clearTimeout(abortTimeout);
var result;
var error = false;
//
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
dataType = dataType || mimeToDataType(xhr.getResponseHeader('content-type'));
result = xhr.responseText;
try {
// xml
if (dataType === 'xml') {
result = xhr.responseXML;
}
// json
else if (dataType === 'json') {
result = blankRE.test(result) ? null : JSON.parse(result);
}
}
catch (e) {
error = e;
}
if (error) {
ajaxError(error, 'parseerror', xhr, settings);
}
else {
ajaxSuccess(result, xhr, settings);
}
}
else {
ajaxError(null, 'error', xhr, settings);
}
}
};
// async
var async = 'async' in settings ? settings.async : true;
// open
xhr.open(settings.type, settings.url, async, settings.username, settings.password);
// xhrFields
if (settings.xhrFields) {
for (var name in settings.xhrFields) {
xhr[name] = settings.xhrFields[name];
}
}
// Override mime type if needed
if (settings.mimeType && xhr.overrideMimeType) {
xhr.overrideMimeType(settings.mimeType);
}
// set request header
for (var name in settings.headers) {
// Support: IE<9
// IE's ActiveXObject throws a 'Type Mismatch' exception when setting
// request header to a null-value.
//
// To keep consistent with other XHR implementations, cast the value
// to string and ignore `undefined`.
if (settings.headers[name] !== undefined) {
xhr.setRequestHeader(name, settings.headers[name] + "");
}
}
// before send
if (ajaxBeforeSend(xhr, settings) === false) {
xhr.abort();
return false;
}
// timeout
if (settings.timeout > 0) {
abortTimeout = window.setTimeout(function () {
xhr.onreadystatechange = noop;
xhr.abort();
ajaxError(null, 'timeout', xhr, settings);
}, settings.timeout);
}
// send
xhr.send(settings.data ? settings.data : null);
return settings.promise;
};
/*
* method get
* */
ajax.get = function (url, data, success, dataType) {
if (isFunction(data)) {
dataType = dataType || success;
success = data;
data = undefined;
}
return ajax({
url: url,
data: data,
success: success,
dataType: dataType
});
};
/*
* method post
*
* dataType:
* */
ajax.post = function (url, data, success, dataType) {
if (isFunction(data)) {
dataType = dataType || success;
success = data;
data = undefined;
}
return ajax({
type: 'POST',
url: url,
data: data,
success: success,
dataType: dataType
})
};
/*
* method getJSON
* */
ajax.getJSON = function (url, data, success) {
if (isFunction(data)) {
success = data;
data = undefined;
}
return ajax({
url: url,
data: data,
success: success,
dataType: 'json'
})
};
/*
* method ajaxSetup
* */
ajax.ajaxSetup = function (target, settings) {
return settings ? extend(extend(target, _settings), settings) : extend(_settings, target);
};
/*
* utils
*
* */
// triggers and extra global event ajaxBeforeSend that's like ajaxSend but cancelable
function ajaxBeforeSend(xhr, settings) {
var context = settings.context;
//
if (settings.beforeSend.call(context, xhr, settings) === false) {
return false;
}
}
// ajax success
function ajaxSuccess(data, xhr, settings) {
var context = settings.context;
var status = 'success';
settings.success.call(context, data, status, xhr);
settings.promise.resolve(data, status, xhr);
ajaxComplete(status, xhr, settings);
}
// status: "success", "notmodified", "error", "timeout", "abort", "parsererror"
function ajaxComplete(status, xhr, settings) {
var context = settings.context;
settings.complete.call(context, xhr, status);
}
// type: "timeout", "error", "abort", "parsererror"
function ajaxError(error, type, xhr, settings) {
var context = settings.context;
settings.error.call(context, xhr, type, error);
settings.promise.reject(xhr, type, error);
ajaxComplete(type, xhr, settings);
}
// jsonp
/*
* tks: https://www.cnblogs.com/rubylouvre/archive/2011/02/13/1953087.html
* */
function JSONP(options) {
//
var callbackName = options.jsonpCallback || 'jsonp' + (new Date().getTime());
var script = window.document.createElement('script');
var abort = function () {
// 设置 window.xxx = noop
if (callbackName in window) {
window[callbackName] = noop;
}
};
var xhr = {abort: abort};
var abortTimeout;
var head = window.document.getElementsByTagName('head')[0] || window.document.documentElement;
// ie8+
script.onerror = function (error) {
_error(error);
};
function _error(error) {
window.clearTimeout(abortTimeout);
xhr.abort();
ajaxError(error.type, xhr, error.type, options);
_removeScript();
}
window[callbackName] = function (data) {
window.clearTimeout(abortTimeout);
ajaxSuccess(data, xhr, options);
_removeScript();
};
//
serializeData(options);
script.src = options.url.replace(/=\?/, '=' + callbackName);
//
script.src = appendQuery(script.src, '_=' + (new Date()).getTime());
//
script.async = true;
// script charset
if (options.scriptCharset) {
script.charset = options.scriptCharset;
}
//
head.insertBefore(script, head.firstChild);
//
if (options.timeout > 0) {
abortTimeout = window.setTimeout(function () {
xhr.abort();
ajaxError('timeout', xhr, 'timeout', options);
_removeScript();
}, options.timeout);
}
// remove script
function _removeScript() {
if (script.clearAttributes) {
script.clearAttributes();
} else {
script.onload = script.onreadystatechange = script.onerror = null;
}
if (script.parentNode) {
script.parentNode.removeChild(script);
}
//
script = null;
delete window[callbackName];
}
return options.promise;
}
// mime to data type
function mimeToDataType(mime) {
return mime && (mime === htmlType ? 'html' : mime === jsonType ? 'json' : xmlTypeRE.test(mime) && 'xml') || 'text'
}
// append query
function appendQuery(url, query) {
return (url + '&' + query).replace(/[&?]{1,2}/, '?');
}
// serialize data
function serializeData(options) {
// formData
if (isObject(options) && !isFormData(options.data) && options.processData) {
options.data = param(options.data);
}
if (options.data && (!options.type || options.type.toUpperCase() === 'GET')) {
options.url = appendQuery(options.url, options.data);
}
}
// serialize
function serialize(params, obj, traditional, scope) {
var _isArray = isArray(obj);
for (var key in obj) {
var value = obj[key];
if (scope) {
key = traditional ? scope : scope + '[' + (_isArray ? '' : key) + ']';
}
// handle data in serializeArray format
if (!scope && _isArray) {
params.add(value.name, value.value);
}
else if (traditional ? _isArray(value) : isObject(value)) {
serialize(params, value, traditional, key);
}
else {
params.add(key, value);
}
}
}
// param
function param(obj, traditional) {
var params = [];
//
params.add = function (k, v) {
this.push(encodeURIComponent(k) + '=' + encodeURIComponent(v));
};
serialize(params, obj, traditional);
return params.join('&').replace('%20', '+');
}
// extend
function extend(target) {
var slice = Array.prototype.slice;
var args = slice.call(arguments, 1);
//
for (var i = 0, length = args.length; i < length; i++) {
var source = args[i] || {};
for (var key in source) {
if (source.hasOwnProperty(key) && source[key] !== undefined) {
target[key] = source[key];
}
}
}
return target;
}
// is object
function isObject(obj) {
var type = typeof obj;
return type === 'function' || type === 'object' && !!obj;
}
// is formData
function isFormData(obj) {
return obj instanceof FormData;
}
// is array
function isArray(value) {
return Object.prototype.toString.call(value) === "[object Array]";
}
// is function
function isFunction(value) {
return typeof value === "function";
}
// browser
window.ajax = ajax;
})();

16
public/avc.js
File diff suppressed because it is too large
View File

20
public/cocos.js
File diff suppressed because it is too large
View File

1
public/ff.js
File diff suppressed because it is too large
View File

BIN
public/ff.wasm

200
public/ff_aac.html

@ -1,200 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Jessibuca 1.0</title>
<meta charset="utf-8" />
<style>
.btn {
display: inline-block;
line-height: 1;
white-space: nowrap;
cursor: pointer;
-webkit-appearance: none;
text-align: center;
box-sizing: border-box;
outline: none;
margin: 0;
transition: .1s;
font-weight: 500;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
padding: 12px 20px;
font-size: 14px;
border-radius: 4px;
color: #fff;
background-color: #409eff;
border-color: #409eff;
width: 100%;
}
.btn-danger {
color: #fff;
background-color: #f56c6c;
border-color: #f56c6c;
}
.btn-success {
color: #fff;
background-color: #67c23a;
border-color: #67c23a;
}
.player-wrapper {
width: 900px;
height: 500px;
/*overflow-y: auto;*/
margin: 0 auto;
text-align: center;
}
.btn-wrapper {
width: 900px;
height: 50px;
margin: 0 auto;
margin-top: 10px;
}
.player-wrapper canvas {
width: 100%;
height: 100%;
}
.logs {
border: 1px solid #333;
width: 900px;
height: 300px;
margin: 0 auto;
overflow-y: auto;
padding: 5px;
}
</style>
</head>
<body>
<div class="player-wrapper">
<canvas id="canvas" style="background-color: #0D0E1B"></canvas>
</div>
<div class="btn-wrapper">
<div id="playDom">
<button class="btn" id="play">播放</button>
</div>
<div id="stopDom" style="display: none">
<button class="btn btn-danger" id="stop">结束</button>
</div>
</div>
<div id="logout" class="logs">
</div>
<script src="./ajax.js"></script>
<script>
onerror = handleErr;
var txt = "";
var h5lc = null;
var $play = document.getElementById('play');
var $stop = document.getElementById('stop');
var $playDom = document.getElementById('playDom');
var $stopDom = document.getElementById('stopDom');
var canvas = document.getElementById("canvas");
var isPlaying = false;
disabledMouseWheel(canvas);
$play.addEventListener('click', function () {
if (isPlaying) {
return;
}
isPlaying = true;
play();
$playDom.style.display = 'none';
$stopDom.style.display = 'block';
});
$stop.addEventListener('click', function () {
if (!isPlaying) {
return;
}
isPlaying = false;
stop();
$playDom.style.display = 'block';
$stopDom.style.display = 'none';
});
function play() {
// h5lc.play("ws://10.24.13.58:8088/live/user1.flv", canvas)
//h5lc.play("ws://3.1.39.135:8080/live/3458", canvas)
h5lc.play("ws://localhost/live/user1",canvas)
// h5lc.play("ws://119.9.118.39:8080/live/user1", canvas)
// h5lc.play("ws://test.qihaipi.com/gnddragon/test.flv", canvas)
}
function stop() {
h5lc.close()
}
function disabledMouseWheel(ele) {
if (ele.addEventListener) {
ele.addEventListener('DOMMouseScroll', scrollFunc, false);
} //W3C
ele.onmousewheel = scrollFunc; //IE/Opera/Chrome
}
function scrollFunc(evt) {
evt = evt || window.event;
if (evt.preventDefault) {
// Firefox
evt.preventDefault();
evt.stopPropagation();
} else {
// IE
evt.cancelBubble = true;
evt.returnValue = false;
}
return false;
}
function handleErr(msg, url, l) {
txt = "There was an error on this page.\n\n";
txt += "Error: " + msg + "\n";
txt += "URL: " + url + "\n";
txt += "Line: " + l + "\n\n";
document.getElementById("logout").innerHTML += txt + "<br>";
return true;
}
var Module = {
print: (function () {
return function (text) {
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
document.getElementById("logout").innerHTML += text + "<br>";
// These replacements are necessary if you render to raw HTML
//text = text.replace(/&/g, "&amp;");
//text = text.replace(/</g, "&lt;");
//text = text.replace(/>/g, "&gt;");
//text = text.replace('\n', '<br>', 'g');
console.log(text);
};
})(),
printErr: function (text) {
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
document.getElementById("logout").innerHTML += text + "<br>";
if (0) { // XXX disabled for safety typeof dump == 'function') {
dump(text + '\n'); // fast, straight to the real console
} else {
console.error(text);
}
},
postRun: function () {
h5lc = new Jessibuca();
h5lc.videoBuffer = 1;
}
};
</script>
<script src="./ff_aac.js"></script>
</body>
</html>

28
public/ff_aac.js
File diff suppressed because it is too large
View File

1
public/ff_aac_wasm.js
File diff suppressed because it is too large
View File

BIN
public/ff_aac_wasm.wasm

200
public/ff_mp3.html

@ -1,200 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>H5LiveClient 1.0</title>
<meta charset="utf-8" />
<style>
.btn {
display: inline-block;
line-height: 1;
white-space: nowrap;
cursor: pointer;
-webkit-appearance: none;
text-align: center;
box-sizing: border-box;
outline: none;
margin: 0;
transition: .1s;
font-weight: 500;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
padding: 12px 20px;
font-size: 14px;
border-radius: 4px;
color: #fff;
background-color: #409eff;
border-color: #409eff;
width: 100%;
}
.btn-danger {
color: #fff;
background-color: #f56c6c;
border-color: #f56c6c;
}
.btn-success {
color: #fff;
background-color: #67c23a;
border-color: #67c23a;
}
.player-wrapper {
width: 900px;
height: 500px;
/*overflow-y: auto;*/
margin: 0 auto;
text-align: center;
}
.btn-wrapper {
width: 900px;
height: 50px;
margin: 0 auto;
margin-top: 10px;
}
/*
.player-wrapper canvas {
width: 100%;
height: 100%;
} */
.logs {
border: 1px solid #333;
width: 900px;
height: 300px;
margin: 0 auto;
overflow-y: auto;
padding: 5px;
}
</style>
</head>
<body>
<div class="player-wrapper">
<canvas id="canvas" style="background-color: #0D0E1B" width="900" height="500"></canvas>
</div>
<div class="btn-wrapper">
<div id="playDom">
<button class="btn" id="play">播放</button>
</div>
<div id="stopDom" style="display: none">
<button class="btn btn-danger" id="stop">结束</button>
</div>
</div>
<div id="logout" class="logs">
</div>
<script src="./ajax.js"></script>
<script>
onerror = handleErr;
var txt = "";
var h5lc = null;
var $play = document.getElementById('play');
var $stop = document.getElementById('stop');
var $playDom = document.getElementById('playDom');
var $stopDom = document.getElementById('stopDom');
var canvas = document.getElementById("canvas");
var isPlaying = false;
disabledMouseWheel(canvas);
$play.addEventListener('click', function () {
if (isPlaying) {
return;
}
isPlaying = true;
play();
$playDom.style.display = 'none';
$stopDom.style.display = 'block';
});
$stop.addEventListener('click', function () {
if (!isPlaying) {
return;
}
isPlaying = false;
stop();
$playDom.style.display = 'block';
$stopDom.style.display = 'none';
});
function play() {
h5lc.play("ws://3.1.39.135:8080/live/345.flv", canvas)
// h5lc.play("ws://localhost:8080/live/user1", canvas)
// h5lc.play("ws://119.9.118.39:8080/live/user1", canvas)
// h5lc.play("ws://test.qihaipi.com/gnddragon/test.flv", canvas)
}
function stop() {
h5lc.close()
}
function disabledMouseWheel(ele) {
if (ele.addEventListener) {
ele.addEventListener('DOMMouseScroll', scrollFunc, false);
} //W3C
ele.onmousewheel = scrollFunc; //IE/Opera/Chrome
}
function scrollFunc(evt) {
evt = evt || window.event;
if (evt.preventDefault) {
// Firefox
evt.preventDefault();
evt.stopPropagation();
} else {
// IE
evt.cancelBubble = true;
evt.returnValue = false;
}
return false;
}
function handleErr(msg, url, l) {
txt = "There was an error on this page.\n\n";
txt += "Error: " + msg + "\n";
txt += "URL: " + url + "\n";
txt += "Line: " + l + "\n\n";
document.getElementById("logout").innerHTML += txt + "<br>";
return true;
}
var Module = {
print: (function () {
return function (text) {
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
document.getElementById("logout").innerHTML += text + "<br>";
// These replacements are necessary if you render to raw HTML
//text = text.replace(/&/g, "&amp;");
//text = text.replace(/</g, "&lt;");
//text = text.replace(/>/g, "&gt;");
//text = text.replace('\n', '<br>', 'g');
console.log(text);
};
})(),
printErr: function (text) {
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
document.getElementById("logout").innerHTML += text + "<br>";
if (0) { // XXX disabled for safety typeof dump == 'function') {
dump(text + '\n'); // fast, straight to the real console
} else {
console.error(text);
}
},
postRun: function () {
h5lc = new H5LiveClient();
h5lc.videoBuffer = 1;
}
};
</script>
<script src="./ff_mp3.js"></script>
</body>
</html>

26
public/ff_mp3.js
File diff suppressed because it is too large
View File

1
public/ff_mp3_wasm.js
File diff suppressed because it is too large
View File

BIN
public/ff_mp3_wasm.wasm

1
public/ff_wasm.js
File diff suppressed because it is too large
View File

BIN
public/ff_wasm.wasm

1
public/flash.html

@ -1 +0,0 @@
<embed src="live_test.swf" width="1024" height="768"></embed>

20
public/hevc.js
File diff suppressed because it is too large
View File

199
public/hevc_aac.html

@ -1,199 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>H5LiveClient 1.0</title>
<meta charset="utf-8" />
<style>
.btn {
display: inline-block;
line-height: 1;
white-space: nowrap;
cursor: pointer;
-webkit-appearance: none;
text-align: center;
box-sizing: border-box;
outline: none;
margin: 0;
transition: .1s;
font-weight: 500;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
padding: 12px 20px;
font-size: 14px;
border-radius: 4px;
color: #fff;
background-color: #409eff;
border-color: #409eff;
width: 100%;
}
.btn-danger {
color: #fff;
background-color: #f56c6c;
border-color: #f56c6c;
}
.btn-success {
color: #fff;
background-color: #67c23a;
border-color: #67c23a;
}
.player-wrapper {
width: 900px;
height: 500px;
/*overflow-y: auto;*/
margin: 0 auto;
text-align: center;
}
.btn-wrapper {
width: 900px;
height: 50px;
margin: 0 auto;
margin-top: 10px;
}
.player-wrapper canvas {
width: 100%;
height: 100%;
}
.logs {
border: 1px solid #333;
width: 900px;
height: 300px;
margin: 0 auto;
overflow-y: auto;
padding: 5px;
}
</style>
</head>
<body>
<div class="player-wrapper">
<canvas id="canvas" style="background-color: #0D0E1B"></canvas>
</div>
<div class="btn-wrapper">
<div id="playDom">
<button class="btn" id="play">播放</button>
</div>
<div id="stopDom" style="display: none">
<button class="btn btn-danger" id="stop">结束</button>
</div>
</div>
<div id="logout" class="logs">
</div>
<script src="./ajax.js"></script>
<script>
onerror = handleErr;
var txt = "";
var h5lc = null;
var $play = document.getElementById('play');
var $stop = document.getElementById('stop');
var $playDom = document.getElementById('playDom');
var $stopDom = document.getElementById('stopDom');
var canvas = document.getElementById("canvas");
var isPlaying = false;
disabledMouseWheel(canvas);
$play.addEventListener('click', function () {
if (isPlaying) {
return;
}
isPlaying = true;
play();
$playDom.style.display = 'none';
$stopDom.style.display = 'block';
});
$stop.addEventListener('click', function () {
if (!isPlaying) {
return;
}
isPlaying = false;
stop();
$playDom.style.display = 'block';
$stopDom.style.display = 'none';
});
function play() {
h5lc.play("ws://3.1.39.135:8080/live/345.flv", canvas)
// h5lc.play("ws://localhost:8080/live/user1", canvas)
// h5lc.play("ws://119.9.118.39:8080/live/user1", canvas)
// h5lc.play("ws://test.qihaipi.com/gnddragon/test.flv", canvas)
}
function stop() {
h5lc.close()
}
function disabledMouseWheel(ele) {
if (ele.addEventListener) {
ele.addEventListener('DOMMouseScroll', scrollFunc, false);
} //W3C
ele.onmousewheel = scrollFunc; //IE/Opera/Chrome
}
function scrollFunc(evt) {
evt = evt || window.event;
if (evt.preventDefault) {
// Firefox
evt.preventDefault();
evt.stopPropagation();
} else {
// IE
evt.cancelBubble = true;
evt.returnValue = false;
}
return false;
}
function handleErr(msg, url, l) {
txt = "There was an error on this page.\n\n";
txt += "Error: " + msg + "\n";
txt += "URL: " + url + "\n";
txt += "Line: " + l + "\n\n";
document.getElementById("logout").innerHTML += txt + "<br>";
return true;
}
var Module = {
print: (function () {
return function (text) {
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
document.getElementById("logout").innerHTML += text + "<br>";
// These replacements are necessary if you render to raw HTML
//text = text.replace(/&/g, "&amp;");
//text = text.replace(/</g, "&lt;");
//text = text.replace(/>/g, "&gt;");
//text = text.replace('\n', '<br>', 'g');
console.log(text);
};
})(),
printErr: function (text) {
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
document.getElementById("logout").innerHTML += text + "<br>";
if (0) { // XXX disabled for safety typeof dump == 'function') {
dump(text + '\n'); // fast, straight to the real console
} else {
console.error(text);
}
},
postRun: function () {
h5lc = new H5LiveClient();
h5lc.videoBuffer = 1;
}
};
</script>
<script src="./hevc_aac.js"></script>
</body>
</html>

22
public/hevc_aac.js
File diff suppressed because it is too large
View File

21
public/hevc_mp3.js
File diff suppressed because it is too large
View File

239
public/index.html

@ -1,239 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Jessibuca 1.0</title>
<meta charset="utf-8" />
<style>
.btn {
display: inline-block;
line-height: 1;
white-space: nowrap;
cursor: pointer;
-webkit-appearance: none;
text-align: center;
box-sizing: border-box;
outline: none;
margin: 0;
transition: .1s;
font-weight: 500;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
padding: 12px 20px;
font-size: 14px;
border-radius: 4px;
color: #fff;
background-color: #409eff;
border-color: #409eff;
width: 100%;
}
.btn-danger {
color: #fff;
background-color: #f56c6c;
border-color: #f56c6c;
}
.btn-success {
color: #fff;
background-color: #67c23a;
border-color: #67c23a;
}
.player-wrapper {
width: 900px;
height: 500px;
/*overflow-y: auto;*/
margin: 0 auto;
text-align: center;
}
.btn-wrapper {
width: 900px;
height: 50px;
margin: 0 auto;
margin-top: 10px;
}
/*.player-wrapper canvas {*/
/* width: 100%;*/
/* height: 100%;*/
/*}*/
.logs {
border: 1px solid #333;
width: 900px;
height: 300px;
margin: 0 auto;
overflow-y: auto;
padding: 5px;
}
</style>
</head>
<body>
<div class="player-wrapper" id="container" style="background-color: #0D0E1B;width:900px;height:500px">
</div>
<div class="btn-wrapper" id="playDom">
<button class="btn" id="play">播放</button>
</div>
<div class="btn-wrapper btn-wrapper2" id="stopDom" style="display: none">
<div style="margin-top: 5px">
<button class="btn btn-danger" id="stop">结束</button>
</div>
</div>
<button class="btn" onclick="h5lc.fullscreen=true">全屏</button>
<div id="logout" class="logs">
</div>
<script src="./ajax.js"></script>
<script src="./renderer.js"></script>
<script>
onerror = handleErr;
var txt = "";
window.onkeydown = function () {
h5lc.fullscreen = false
}
var $play = document.getElementById('play');
var $stop = document.getElementById('stop');
var $playDom = document.getElementById('playDom');
var $stopDom = document.getElementById('stopDom');
var container = document.getElementById("container");
var isPlaying = false;
disabledMouseWheel(container);
let stream = queryParam('stream') || 'user1';
let decoder = queryParam('decoder') || 'ff';
let source = queryParam('source') || 'localhost';
var h5lc = new Jessibuca({ container, decoder: decoder + ".js", videoBuffer: 0 });
h5lc.onLoad = function () {
//this.play("wss://pulls.1234326.cn/live/L01.flv")
//this.play("ws://localhost:8080/live/rtc.flv")
//this.play("ws://" + source + ":8080/live/" + stream)
//this.play("ws://pull3.afb1188.com/live/" + stream + ".flv")
//this.play("ws://pull2.afb1188.com/live/" + stream + ".flv")
}
h5lc.onPlay = function () {
isPlaying = true;
$playDom.style.display = 'none';
$stopDom.style.display = 'block';
}
$play.addEventListener('click', function () {
if (isPlaying) {
return;
}
isPlaying = true;
play();
$playDom.style.display = 'none';
$stopDom.style.display = 'block';
}, false);
$stop.addEventListener('click', function () {
if (!isPlaying) {
return;
}
isPlaying = false;
stop();
$playDom.style.display = 'block';
$stopDom.style.display = 'none';
}, false);
function play(firstResponseIp) {
//h5lc.play("ws://" + (firstResponseIp || source) + ":8080/live/" + stream)
//h5lc.play("ws://pull2.afb1188.com/live/" + stream + ".flv")
h5lc.play("ws://localhost:8080/live/" + stream)
// h5lc.play("ws://119.9.118.39:8080/live/user1", canvas)
// h5lc.play("ws://test.qihaipi.com/gnddragon/test.flv", canvas)
}
function getFastCdnFromList(ipList) {
ipList = ipList || [];
var firstResponseIp = '';
for (var i = 0, len = ipList.length; i < len; i++) {
var tempIp = ipList[i].name;
var reqHref = 'http://' + tempIp + '/test';
var request = _ajax.get(reqHref);
request.then(function (data) {
if (!firstResponseIp) {
firstResponseIp = tempIp;
// 直接可以播放了。
play(firstResponseIp);
}
})
}
}
function stop() {
h5lc.close()
}
function queryParam(name, url) {
var search = window.location.search;
var qArr = '';
var key = {};
if (url) {
qArr = url.split("?")[1].split("&")
} else {
if (!window.location.search) {
return
}
qArr = search.substr(1).split("&")
}
for (var i = 0; i < qArr.length; i++) {
var firstPos = qArr[i].indexOf('=');
key[qArr[i].slice(0, firstPos)] = qArr[i].slice(firstPos + 1)
}
if (name) {
return key[name]
} else {
if (url) {
return key[name]
} else {
return key
}
}
}
function disabledMouseWheel(ele) {
if (ele.addEventListener) {
ele.addEventListener('DOMMouseScroll', scrollFunc, false);
} //W3C
ele.onmousewheel = scrollFunc; //IE/Opera/Chrome
}
function scrollFunc(evt) {
evt = evt || window.event;
if (evt.preventDefault) {
// Firefox
evt.preventDefault();
evt.stopPropagation();
} else {
// IE
evt.cancelBubble = true;
evt.returnValue = false;
}
return false;
}
function handleErr(msg, url, l) {
txt = "There was an error on this page.\n\n";
txt += "Error: " + msg + "\n";
txt += "URL: " + url + "\n";
txt += "Line: " + l + "\n\n";
document.getElementById("logout").innerHTML += txt + "<br>";
return true;
}
</script>
</body>
</html>

23
public/libde265_aac.js
File diff suppressed because it is too large
View File

20
public/libde265_mp3.js
File diff suppressed because it is too large
View File

BIN
public/live_test.swf

1709
public/renderer.js
File diff suppressed because it is too large
View File

Loading…
Cancel
Save