diff --git a/sdk/demo/demo.html b/sdk/demo/demo.html index 4bdcd17033ad058f69552494e62f42565c6b2bea..f06b72259fcfd6c2b9967b436392f0b3ff2b5d99 100644 --- a/sdk/demo/demo.html +++ b/sdk/demo/demo.html @@ -16,28 +16,22 @@ Copyright 2022 Huawei Cloud Computing Technology Co., Ltd. - + h5 demo - 云手机SDK demo + - +
+ class="fullscreen-container">
+ class="broadway container" + workers="false" + render="true" + webgl="auto">
+ id="loading"> + width="50" + height="50"> 退出
+
+
+

温馨提示

+
+
+

确定退出吗?

+
+ +
+
CTRL
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
-
+
+ + + onclick="fullscreenToggle('fullscreen-container')">Fullscreen + 信任目标机器 + target="_blank" + class="play-ctr-btn" + href="">信任目标机器
+ + src="sdk/CloudApp.min.js"> diff --git a/sdk/index.html b/sdk/index.html index ad7e654c2107ccb46d48a39c78149b501949ab12..9c4391dc886c8b92c6f346511c9e5aee351f977d 100644 --- a/sdk/index.html +++ b/sdk/index.html @@ -27,14 +27,11 @@ Copyright 2022 Huawei Cloud Computing Technology Co., Ltd. margin: 0; padding: 0; } - - .container { width: 100%; height: 100%; - background: gray; + background: black; } - .loading { width: 50px; height: 50px; @@ -48,7 +45,6 @@ Copyright 2022 Huawei Cloud Computing Technology Co., Ltd. -o-animation: load-anim 2s linear infinite; animation: load-anim 2s linear infinite; } - @keyframes load-anim { from { -ms-transform: rotate(0deg); @@ -57,7 +53,6 @@ Copyright 2022 Huawei Cloud Computing Technology Co., Ltd. -o-transform: rotate(0deg); transform: rotate(0deg); } - to { -ms-transform: rotate(360deg); -moz-transform: rotate(360deg); @@ -66,7 +61,6 @@ Copyright 2022 Huawei Cloud Computing Technology Co., Ltd. transform: rotate(360deg); } } - #network-info { pointer-events: none; position: absolute; @@ -77,12 +71,10 @@ Copyright 2022 Huawei Cloud Computing Technology Co., Ltd. width: 100%; color: #fff; } - #keyboard-dialog { border: 1px solid lightblue; border-radius: 10px; } - .play-ctr-btn { display: inline-block; background: #fff; @@ -93,8 +85,7 @@ Copyright 2022 Huawei Cloud Computing Technology Co., Ltd. border-radius: 5px; font-size: 14px; } - - .message-modal { + .message-modal, .exit-modal { display: none; width: 300px; height: 200px; @@ -117,12 +108,10 @@ Copyright 2022 Huawei Cloud Computing Technology Co., Ltd. text-align: center; height: 40%; } - .footer-content { height: 20%; border-top: 1px solid #dfe1e6; } - .button-alone { width: 100%; height: 100%; @@ -130,7 +119,64 @@ Copyright 2022 Huawei Cloud Computing Technology Co., Ltd. text-align: center; background-color: #fff; } - + .control-btn { + display: none; + font-size: 14px; + line-height: 40px; + text-align: center; + width: 40px; + height: 40px; + position: fixed; + z-index: 999; + top: 15%; + left: 35%; + background-color: #fff; + border: 1px solid #dfe1e6; + border-radius: 50%; + } + .button-modal{ + display: none; + width: 255px; + height: 155px; + position: absolute; + z-index: 999; + top: 50%; + left: 50%; + background-color: rgba(0, 0, 0, 0.4); + border-radius: 5px; + transform: translate(-50%, -50%); + } + .button-network,.button-exit{ + width: 100%; + height: 25%; + margin-bottom: 10px; + } + .radio-group { + color: #ffffff; + display: flex; + justify-content: space-around; + align-items: center; + height: 35%; + } + input[type="radio"] { + transform: scale(1.5); + } + .exit-btn { + float: left; + width: 50%; + height: 100%; + border: none; + text-align: center; + background-color: #fff; + } + .cancel-btn { + float: right; + width: 50%; + height: 100%; + border: none; + text-align: center; + background-color: #fff; + } @@ -173,15 +219,46 @@ Copyright 2022 Huawei Cloud Computing Technology Co., Ltd.

温馨提示

-

hhhhhhhhhhh

+

+
+
+

温馨提示

+
+
+

确定退出吗?

+
+ +
+
CTRL
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
-
+
@@ -353,9 +430,31 @@ Copyright 2022 Huawei Cloud Computing Technology Co., Ltd. console.log(e); } - function toggleNetworkInfo() { + function toggleNetworkInfo(event) { var networkInfoElement = document.getElementById('network-info'); networkInfoElement.hidden = !networkInfoElement.hidden; + if (networkInfoElement.hidden) { + event.target.innerHTML = '显示时延数据'; + } else { + event.target.innerHTML = '关闭时延数据'; + } + } + + function showExitModal() { + const buttonModalEle = document.getElementById('buttonModal'); + const exitModalEle = document.getElementById('exitModal'); + buttonModalEle.style.display = 'none'; + exitModal.style.display = 'block'; + } + + function exitPhone() { + exit(); + closeExitModal(); + } + + function closeExitModal() { + const exitModalEle = document.getElementById('exitModal'); + exitModal.style.display = 'none'; } function exit() { @@ -455,12 +554,50 @@ Copyright 2022 Huawei Cloud Computing Technology Co., Ltd. function startsuccessCallBack(data){ const connectSuccessState = 2048; if (data.state === connectSuccessState) { + closeCtrlModal(); try { CasCallback.startSuccessCallback(); } catch (error) {} } } + function radioChange(event) { + const checkedVal = event && event.target.value; + cloudapp.setResolution(checkedVal); + } + + function closeCtrlModal() { + const ctrlEle = document.getElementById('controlBtn'); + const buttonModalEle = document.getElementById('buttonModal'); + const playContainer = document.querySelector('article'); + const playerElement = playContainer.shadowRoot.querySelector('#playCanvas') || playContainer.shadowRoot.querySelector('#phoenixVideo'); + ctrlEle.style.display = 'block'; + ctrlEle.addEventListener('click', (event) => { + if(buttonModalEle.style.display !== 'block') { + buttonModalEle.style.display = 'block'; + } else { + buttonModalEle.style.display = 'none'; + } + }); + + if (/(iPhone|iPad|iPod|iOS|Android)/i.test(navigator.userAgent)) { + playerElement.addEventListener('touchend', (event) => { + if(!buttonModalEle.contains(event.target) && !ctrlEle.contains(event.target)) { + buttonModalEle.style.display = 'none'; + } + }); + } else { + document.addEventListener('click', (event) => { + if(!buttonModalEle.contains(event.target) && !ctrlEle.contains(event.target)) { + buttonModalEle.style.display = 'none'; + } + }); + } + + buttonModalEle.addEventListener('click', (event) => { + event.stopPropagation(); + }); + } diff --git a/sdk/src/AppController.js b/sdk/src/AppController.js index 3d23f67b807fe9b4712e360d5eab19121b8f8756..40aaa091a8237135051b844d73d411ec2902c615 100644 --- a/sdk/src/AppController.js +++ b/sdk/src/AppController.js @@ -323,6 +323,14 @@ class AppController { autoRotate: this.options.autoRotate }); this.touchHandler.start(); + if(this.touchHandler.displayBox.width && this.touchHandler.displayBox.height) { + const ctrlEle = document.getElementById('controlBtn'); + const containerEle = document.getElementById('container'); + const left = (containerEle.offsetWidth - this.touchHandler.displayBox.width)/2 + 20; + const top = (containerEle.offsetHeight - this.touchHandler.displayBox.height)/2 + 125; + ctrlEle.style.top = `${top}px`; + ctrlEle.style.left = `${left}px`; + } this.listenPlayerSizeChange(); this.autoRotation = new AutoRotation(this.options.containerId, @@ -1048,13 +1056,18 @@ class AppController { if (this.isMSE) { this.player.style.setProperty('width', '100%', 'important'); this.player.style.setProperty('height', '100%', 'important'); + // 硬解时video标签会按比例填充视频,避免视频被裁减设置contain显示完整画面 + this.player.style.setProperty('object-fit', 'contain', 'important'); } else { // 解决画布居中问题 this.player.style.setProperty('margin', '0 auto', 'important'); } + // 有些手机是硬解场景,将画面覆盖整个video容器,避免出现黑边 + if (this.isMSE && this.options.isMobile) { + this.player.style.setProperty('object-fit', 'fill', 'important'); + } // 解决真机键盘弹起后,浏览器可视窗变小,video高度很小而导致video停止播放,时延增加的问题。 this.player.style.setProperty('min-height', '60px', 'important'); - this.player.style.setProperty('object-fit', 'contain', 'important'); // H5 场景下 video、canvas 的 display 属性默认值为 inline,需要主动设置为 block,以避免底部留边问题 this.player.style.setProperty('display', 'block', 'important'); @@ -1221,13 +1234,12 @@ class AppController { } // 设置画质 - setResolution(width, height) { - Logger.debug('Setting resolution:' + width + '*' + height); + setResolution(clarityVal) { + // 暂时默认h264流 + const frameType = 'H264'; - let config = { - virtual_width: width, - virtual_height: height - }; + const allMediaConfig = PROTOCOL_CONFIG[frameType]; + const config = allMediaConfig[`${mediaWidth}P`][clarityVal]; this.setMediaConfig(config); } @@ -1365,6 +1377,7 @@ class AppController { } return isMSE; + // return false; } sendDataToCloudApp(data) { diff --git a/sdk/src/AutoRotation.js b/sdk/src/AutoRotation.js index e7c2ff2990bb49072cfcb0cac1410c96b5d65cd4..11f9291370b7d3941c03bf27811f4ea07f2d3ce5 100644 --- a/sdk/src/AutoRotation.js +++ b/sdk/src/AutoRotation.js @@ -74,8 +74,7 @@ export default class AutoRotation { if (rect) { if (this.isMobile) { width = Math.max(width - Math.max(rect.left, 0), 0); - // 需要预留按钮位置 - height = Math.min(height - Math.max(rect.top, 0), rect.height); + height = Math.max(height - Math.max(rect.top, 0), 0); } else { width = Math.max(width - Math.max(rect.left * 2, 0), 0); height = Math.min(height - Math.max(rect.top * 2, 0), rect.height); diff --git a/sdk/src/CanvasPlayer.js b/sdk/src/CanvasPlayer.js index 69dbb692b3d9f60c4d87b332698bba90e4bb7798..ca1edd7ba3b3a93c06922650047e6f941456feb1 100644 --- a/sdk/src/CanvasPlayer.js +++ b/sdk/src/CanvasPlayer.js @@ -39,7 +39,7 @@ class CanvasPlayer extends BaseClass { /* javascript-obfuscator:enable */ this.videoDecoderWorker.addEventListener('message', this.eventMessageHandel.bind(this)); - // this.loadjs(); + this.loadjs(); } setCanvas () { @@ -58,6 +58,9 @@ class CanvasPlayer extends BaseClass { } loadjs(decoderType) { + if (!decoderType) { + decoderType = 'H264'; + } this.videoDecoderWorker.postMessage({ type: 'loadwasm', libPath: this.options.libPath, @@ -157,7 +160,6 @@ class CanvasPlayer extends BaseClass { } decode(data) { - console.log('流数据:', data); /*global __IS_DEBUG__*/ if (__IS_DEBUG__) { let traceId = window.delayAnalysis.shiftTraceId('receive') || ''; diff --git a/sdk/src/CloudApp.js b/sdk/src/CloudApp.js index 10dd716d3df588e141b2260567c31ffe581ffa8c..60e24569aef363915c684809affb31fe870d2d69 100644 --- a/sdk/src/CloudApp.js +++ b/sdk/src/CloudApp.js @@ -116,7 +116,7 @@ class CloudApp { const clientHeight = document.documentElement.clientHeight; fullscreenContainer.style.width = `${clientWidth}px`; // 需要给操作按钮留出空间 - fullscreenContainer.style.height = `${clientHeight - 100}px`; + fullscreenContainer.style.height = `${clientHeight}px`; } this.appController = CloudApp.setAppController.bind(this)(); @@ -363,13 +363,8 @@ class CloudApp { this.appController.off(eventName, callback); } - setResolution(resolution) { - if (typeof resolution !== 'object') { - Logger.debug('resolution should be an object'); - return; - } - - this.appController.setResolution(resolution.width, resolution.height); + setResolution(clarityVal) { + this.appController.setResolution(clarityVal); } setMediaConfig(config) { diff --git a/sdk/src/Util.js b/sdk/src/Util.js index 32b2fb209f9ce9c802138db7c9219c615ae0d08d..194e80d08d325f7973e73962329584c75beccb15 100644 --- a/sdk/src/Util.js +++ b/sdk/src/Util.js @@ -121,6 +121,9 @@ export default class Util { const parentContainer = document.getElementById('container'); let playerHeight = parentContainer && parentContainer.clientHeight; let playerWidth = playerHeight * ratio; + if (isMobile) { + playerWidth = parentContainer && parentContainer.clientWidth; + } const $ele = this.createEl('canvas'); $ele.style.display = 'block'; $ele.width = playerWidth; diff --git a/sdk/src/codec/Decode.js b/sdk/src/codec/Decode.js index c465f794e000fe245a92876659e5992633ddd7de..97ac4a492dc477cdd159bf3ba2ef6a94ffb2af96 100644 --- a/sdk/src/codec/Decode.js +++ b/sdk/src/codec/Decode.js @@ -11,7 +11,8 @@ class Decode { loadWASM(event) { let that = this; let libPath = event.data.libPath; - this.decoderType = DECODER_TYPE_MAP[event.data.decoderType]; + const decoderType = event.data.decoderType.toUpperCase(); + this.decoderType = DECODER_TYPE_MAP[decoderType]; self.Module = { locateFile: function (wasm) { return libPath + wasm; diff --git a/sdk/src/config/protocolConfig.js b/sdk/src/config/protocolConfig.js index 2bfaca694ca811e6f8bd86525f1dee0037a2fb66..de90b8b874858a7f98a0f5b972191f58ecee0c07 100644 --- a/sdk/src/config/protocolConfig.js +++ b/sdk/src/config/protocolConfig.js @@ -77,6 +77,7 @@ const PROTOCOL_CONFIG = { MEDIA_CONFIG_SUCCESS: 0x21, START_SUCCESS: 0x08, RECONNECT_FAILED: 0x0D, + CAE_MEDIA_CONFIG: 0x020, INVALID_OPERATION: 0xFF }, ACTIONS_TYPE: { @@ -110,6 +111,78 @@ const PROTOCOL_CONFIG = { height: 1920 } }, + H264: { + '720P': { + 'UHD': { + virtual_width: 720, + virtual_height: 1280, + bitrate: 2000000 + }, + 'HD': { + virtual_width: 720, + virtual_height: 1280, + bitrate: 1500000 + }, + 'SD': { + virtual_width: 544, + virtual_height: 960, + bitrate: 1100000 + }, + }, + '1280P': { + 'UHD': { + virtual_width: 1080, + virtual_height: 1920, + bitrate: 4000000 + }, + 'HD': { + virtual_width: 1080, + virtual_height: 1920, + bitrate: 3000000 + }, + 'SD': { + virtual_width: 720, + virtual_height: 1280, + bitrate: 2200000 + }, + }, + }, + H265: { + '720P': { + 'UHD': { + virtual_width: 720, + virtual_height: 1280, + bitrate: 1400000 + }, + 'HD': { + virtual_width: 720, + virtual_height: 1280, + bitrate: 1000000 + }, + 'SD': { + virtual_width: 544, + virtual_height: 960, + bitrate: 800000 + }, + }, + '1280P': { + 'UHD': { + virtual_width: 1080, + virtual_height: 1920, + bitrate: 2700000 + }, + 'HD': { + virtual_width: 1080, + virtual_height: 1920, + bitrate: 2000000 + }, + 'SD': { + virtual_width: 720, + virtual_height: 1280, + bitrate: 1500000 + }, + }, + }, DEFAULT_RESOLUTION: { width: 720, height: 1280