瀏覽代碼

第一次上传

xsh 1 年之前
當前提交
9a59ed9256
共有 100 個文件被更改,包括 2775 次插入0 次删除
  1. 24 0
      .gitignore
  2. 7 0
      README.md
  3. 13 0
      index.html
  4. 1 0
      nkApp/assets/Ai-0aba0dcf.css
  5. 1 0
      nkApp/assets/Ai-0c5f1be6.js
  6. 1 0
      nkApp/assets/ChartDrink-eec63ef4.js
  7. 1 0
      nkApp/assets/ChartTemp-739236cb.js
  8. 1 0
      nkApp/assets/Daily-2393572e.css
  9. 1 0
      nkApp/assets/Daily-e095d0ad.js
  10. 1 0
      nkApp/assets/DailyDetail-0d54de28.js
  11. 1 0
      nkApp/assets/DailyDetail-c94068de.css
  12. 1 0
      nkApp/assets/Energy-8cfee6e0.js
  13. 1 0
      nkApp/assets/Energy-aeeabcb8.css
  14. 1 0
      nkApp/assets/Env-0b01c9cb.js
  15. 1 0
      nkApp/assets/Env-5d9b444d.css
  16. 1 0
      nkApp/assets/Feed-1e58ee44.css
  17. 1 0
      nkApp/assets/Feed-7f1eafa0.js
  18. 1 0
      nkApp/assets/FeedDetail-7fad8eb0.js
  19. 1 0
      nkApp/assets/FeedDetail-e581bb1d.css
  20. 1 0
      nkApp/assets/History-8aeca408.css
  21. 1 0
      nkApp/assets/History-d6f51ac2.js
  22. 1 0
      nkApp/assets/Home-15311072.js
  23. 1 0
      nkApp/assets/Home-c5757787.css
  24. 1 0
      nkApp/assets/Login-98a43231.css
  25. 1 0
      nkApp/assets/Login-e3a69f73.js
  26. 1 0
      nkApp/assets/MainLayout-1b566c2c.css
  27. 1 0
      nkApp/assets/MainLayout-c0974419.js
  28. 1 0
      nkApp/assets/Mine-6fb78fd0.css
  29. 1 0
      nkApp/assets/Mine-8f5d2e81.js
  30. 二進制
      nkApp/assets/OPPOSans_M_2-44c41d8a.ttf
  31. 2 0
      nkApp/assets/Production-7a5d98aa.js
  32. 1 0
      nkApp/assets/Production-f86f016f.css
  33. 1 0
      nkApp/assets/Task-165a963a.css
  34. 1 0
      nkApp/assets/Task-ce888d97.js
  35. 1 0
      nkApp/assets/TaskDetail-289b457f.css
  36. 1 0
      nkApp/assets/TaskDetail-2e9d35d4.js
  37. 1 0
      nkApp/assets/Video-2b35466f.css
  38. 1 0
      nkApp/assets/Video-d9ec973a.js
  39. 1 0
      nkApp/assets/Warn-749de039.css
  40. 1 0
      nkApp/assets/Warn-e753a0e2.js
  41. 1 0
      nkApp/assets/XLine-4e3d5a57.js
  42. 1 0
      nkApp/assets/XLine-7c694dc2.css
  43. 3 0
      nkApp/assets/api-e0b7dcb1.js
  44. 二進制
      nkApp/assets/bu-51b51b77.png
  45. 二進制
      nkApp/assets/bu_select-487ffc90.png
  46. 二進制
      nkApp/assets/chuang-5f27ee71.png
  47. 二進制
      nkApp/assets/chuang_select-e567e3fb.png
  48. 二進制
      nkApp/assets/dai-16fd8df2.png
  49. 二進制
      nkApp/assets/duan-021c30c7.png
  50. 二進制
      nkApp/assets/ele-d409646e.png
  51. 二進制
      nkApp/assets/fan-68373b79.png
  52. 二進制
      nkApp/assets/fan_select-42dcdba7.png
  53. 二進制
      nkApp/assets/feed-f909dd30.png
  54. 二進制
      nkApp/assets/fen-bb027340.png
  55. 二進制
      nkApp/assets/hum-6abf524e.png
  56. 二進制
      nkApp/assets/icon1-69693894.png
  57. 二進制
      nkApp/assets/icon2-09711966.png
  58. 二進制
      nkApp/assets/icon3-f9f5586b.png
  59. 二進制
      nkApp/assets/icon4-a6b48a9f.png
  60. 二進制
      nkApp/assets/icon6-ba419753.png
  61. 二進制
      nkApp/assets/iconfont.1686788249013-749fb6d4.woff
  62. 二進制
      nkApp/assets/iconfont.1686788249013-eabee844.ttf
  63. 1 0
      nkApp/assets/index-4e65cdb1.css
  64. 1 0
      nkApp/assets/index-56daa4e6.js
  65. 1 0
      nkApp/assets/index-6290f871.js
  66. 1 0
      nkApp/assets/index-6860a79a.js
  67. 1 0
      nkApp/assets/index-6cf74614.js
  68. 1 0
      nkApp/assets/index-a7615baa.js
  69. 1 0
      nkApp/assets/index-c9653467.js
  70. 79 0
      nkApp/assets/index-ee85f8a3.js
  71. 二進制
      nkApp/assets/lian-de280e5a.png
  72. 二進制
      nkApp/assets/lian_select-69e49b5b.png
  73. 二進制
      nkApp/assets/liao-ec3287dc.png
  74. 二進制
      nkApp/assets/menu-07a35cb0.png
  75. 二進制
      nkApp/assets/menuSelect-fcb96348.png
  76. 二進制
      nkApp/assets/mine-40bcc01a.png
  77. 二進制
      nkApp/assets/mineSelect-7cfdecd9.png
  78. 1 0
      nkApp/assets/on-popup-reopen-28b79f93.js
  79. 二進制
      nkApp/assets/production-97996914.png
  80. 二進制
      nkApp/assets/productionSelect-0667278d.png
  81. 二進制
      nkApp/assets/ren-1f3edec0.png
  82. 二進制
      nkApp/assets/tai-11b7a56e.png
  83. 二進制
      nkApp/assets/temp-9a5e8fb1.png
  84. 1 0
      nkApp/assets/use-route-c6e6fb0f.js
  85. 二進制
      nkApp/assets/video-767c79cb.png
  86. 二進制
      nkApp/assets/warn-eb1379d5.png
  87. 二進制
      nkApp/assets/warnOrgin-e2d069be.png
  88. 二進制
      nkApp/assets/warnSelect-900585ef.png
  89. 二進制
      nkApp/assets/water-be833077.png
  90. 二進制
      nkApp/assets/water1-51a1f941.png
  91. 二進制
      nkApp/assets/zhen-0deafb75.png
  92. 15 0
      nkApp/index.html
  93. 二進制
      nkApp/static/h265/image/siagn.png
  94. 284 0
      nkApp/static/h265/index.html
  95. 1153 0
      nkApp/static/h265/src/Decoder.js
  96. 二進制
      nkApp/static/h265/src/Decoder.wasm
  97. 180 0
      nkApp/static/h265/src/H2642.js
  98. 387 0
      nkApp/static/h265/src/H264SPSParser.js
  99. 582 0
      nkApp/static/h265/src/H264Session.js
  100. 0 0
      nkApp/static/h265/src/H265.js

+ 24 - 0
.gitignore

@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?

+ 7 - 0
README.md

@@ -0,0 +1,7 @@
+# Vue 3 + Vite
+
+This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
+
+## Recommended IDE Setup
+
+- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).

+ 13 - 0
index.html

@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
+    <title>农科院</title>
+  </head>
+  <body>
+    <div id="app"></div>
+    <script type="module" src="/src/main.js"></script>
+  </body>
+</html>

文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/Ai-0aba0dcf.css


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/Ai-0c5f1be6.js


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/ChartDrink-eec63ef4.js


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/ChartTemp-739236cb.js


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/Daily-2393572e.css


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/Daily-e095d0ad.js


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/DailyDetail-0d54de28.js


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/DailyDetail-c94068de.css


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/Energy-8cfee6e0.js


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/Energy-aeeabcb8.css


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/Env-0b01c9cb.js


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/Env-5d9b444d.css


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/Feed-1e58ee44.css


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/Feed-7f1eafa0.js


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/FeedDetail-7fad8eb0.js


+ 1 - 0
nkApp/assets/FeedDetail-e581bb1d.css

@@ -0,0 +1 @@
+.monitor[data-v-5f80fd6c]{box-sizing:border-box;padding:0 .26667rem;border-radius:.26667rem;margin-bottom:.26667rem;position:relative}.padding[data-v-5f80fd6c]{padding:0 .26667rem}.monitor_box[data-v-5f80fd6c]{box-sizing:border-box;padding:.26667rem;border-radius:.26667rem;margin-bottom:.26667rem;position:relative;background:white}.chart_content[data-v-5f80fd6c]{width:100%;height:8rem}

文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/History-8aeca408.css


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/History-d6f51ac2.js


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/Home-15311072.js


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/Home-c5757787.css


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/Login-98a43231.css


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/Login-e3a69f73.js


+ 1 - 0
nkApp/assets/MainLayout-1b566c2c.css

@@ -0,0 +1 @@
+.main[data-v-0c2f4fca]{width:100%;height:100%}.main_header[data-v-0c2f4fca]{width:100%}.arrow_back[data-v-0c2f4fca]{font-size:.42667rem;color:#1998fa}.main_content[data-v-0c2f4fca]{width:100%;box-sizing:border-box;overflow:auto}.main_tab[data-v-0c2f4fca]{height:calc(100% - 2.61333rem)}.main_no_tab[data-v-0c2f4fca]{height:calc(100% - 1.22667rem)}.main_footer[data-v-0c2f4fca]{width:100%}

文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/MainLayout-c0974419.js


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/Mine-6fb78fd0.css


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/Mine-8f5d2e81.js


二進制
nkApp/assets/OPPOSans_M_2-44c41d8a.ttf


文件差異過大導致無法顯示
+ 2 - 0
nkApp/assets/Production-7a5d98aa.js


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/Production-f86f016f.css


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/Task-165a963a.css


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/Task-ce888d97.js


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/TaskDetail-289b457f.css


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/TaskDetail-2e9d35d4.js


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/Video-2b35466f.css


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/Video-d9ec973a.js


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/Warn-749de039.css


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/Warn-e753a0e2.js


+ 1 - 0
nkApp/assets/XLine-4e3d5a57.js

@@ -0,0 +1 @@
+import{_ as t,t as _,i as s,U as a}from"./index-ee85f8a3.js";const n={class:"text"},c={name:"XLine"},o=Object.assign(c,{props:{text:{type:String,default:()=>""}},setup(e){return(i,p)=>(_(),s("div",n,a(e.text),1))}}),d=t(o,[["__scopeId","data-v-ee3ad296"]]);export{d as X};

+ 1 - 0
nkApp/assets/XLine-7c694dc2.css

@@ -0,0 +1 @@
+.text[data-v-ee3ad296]{width:100%;height:.66667rem;line-height:.66667rem;box-sizing:border-box;padding-left:.53333rem;position:relative}.text[data-v-ee3ad296]:before{content:"";position:absolute;width:.13333rem;height:.42667rem;background-color:#6c3;border-radius:.13333rem;top:.13333rem;left:.13333rem}

文件差異過大導致無法顯示
+ 3 - 0
nkApp/assets/api-e0b7dcb1.js


二進制
nkApp/assets/bu-51b51b77.png


二進制
nkApp/assets/bu_select-487ffc90.png


二進制
nkApp/assets/chuang-5f27ee71.png


二進制
nkApp/assets/chuang_select-e567e3fb.png


二進制
nkApp/assets/dai-16fd8df2.png


二進制
nkApp/assets/duan-021c30c7.png


二進制
nkApp/assets/ele-d409646e.png


二進制
nkApp/assets/fan-68373b79.png


二進制
nkApp/assets/fan_select-42dcdba7.png


二進制
nkApp/assets/feed-f909dd30.png


二進制
nkApp/assets/fen-bb027340.png


二進制
nkApp/assets/hum-6abf524e.png


二進制
nkApp/assets/icon1-69693894.png


二進制
nkApp/assets/icon2-09711966.png


二進制
nkApp/assets/icon3-f9f5586b.png


二進制
nkApp/assets/icon4-a6b48a9f.png


二進制
nkApp/assets/icon6-ba419753.png


二進制
nkApp/assets/iconfont.1686788249013-749fb6d4.woff


二進制
nkApp/assets/iconfont.1686788249013-eabee844.ttf


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/index-4e65cdb1.css


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/index-56daa4e6.js


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/index-6290f871.js


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/index-6860a79a.js


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/index-6cf74614.js


文件差異過大導致無法顯示
+ 1 - 0
nkApp/assets/index-a7615baa.js


+ 1 - 0
nkApp/assets/index-c9653467.js

@@ -0,0 +1 @@
+import{a0 as r}from"./index-ee85f8a3.js";const o=r("keep",{state:()=>({keepAlive:[]}),getters:{},actions:{SET_KEEPALIVE(e){this.$patch(t=>{t.keepAlive=e})}}});export{o as u};

文件差異過大導致無法顯示
+ 79 - 0
nkApp/assets/index-ee85f8a3.js


二進制
nkApp/assets/lian-de280e5a.png


二進制
nkApp/assets/lian_select-69e49b5b.png


二進制
nkApp/assets/liao-ec3287dc.png


二進制
nkApp/assets/menu-07a35cb0.png


二進制
nkApp/assets/menuSelect-fcb96348.png


二進制
nkApp/assets/mine-40bcc01a.png


二進制
nkApp/assets/mineSelect-7cfdecd9.png


+ 1 - 0
nkApp/assets/on-popup-reopen-28b79f93.js

@@ -0,0 +1 @@
+import{P as T,R as c}from"./index-a7615baa.js";import{Y as f,w as l}from"./index-ee85f8a3.js";const i="van-hairline",E=`${i}--bottom`,R=`${i}--top-bottom`,_="van-haptics-feedback",r=500,m=5;function u(s,{args:t=[],done:o,canceled:a}){if(s){const n=s.apply(null,t);T(n)?n.then(p=>{p?o():a&&a()}).catch(c):n?o():a&&a()}else o()}const O=Symbol();function B(s){const t=f(O,null);t&&l(t,o=>{o&&s()})}export{E as B,_ as H,r as L,O as P,m as T,R as a,u as c,B as o};

二進制
nkApp/assets/production-97996914.png


二進制
nkApp/assets/productionSelect-0667278d.png


二進制
nkApp/assets/ren-1f3edec0.png


二進制
nkApp/assets/tai-11b7a56e.png


二進制
nkApp/assets/temp-9a5e8fb1.png


+ 1 - 0
nkApp/assets/use-route-c6e6fb0f.js

@@ -0,0 +1 @@
+import{g as n}from"./index-ee85f8a3.js";const c={to:[String,Object],url:String,replace:Boolean};function a({to:e,url:o,replace:t,$router:r}){e&&r?r[t?"replace":"push"](e):o&&(t?location.replace(o):location.href=o)}function i(){const e=n().proxy;return()=>a(e)}export{a,c as r,i as u};

二進制
nkApp/assets/video-767c79cb.png


二進制
nkApp/assets/warn-eb1379d5.png


二進制
nkApp/assets/warnOrgin-e2d069be.png


二進制
nkApp/assets/warnSelect-900585ef.png


二進制
nkApp/assets/water-be833077.png


二進制
nkApp/assets/water1-51a1f941.png


二進制
nkApp/assets/zhen-0deafb75.png


+ 15 - 0
nkApp/index.html

@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <link rel="icon" type="image/svg+xml" href="./vite.svg" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
+    <title>农科院</title>
+    <script type="module" crossorigin src="./assets/index-ee85f8a3.js"></script>
+    <link rel="stylesheet" href="./assets/index-4e65cdb1.css">
+  </head>
+  <body>
+    <div id="app"></div>
+    
+  </body>
+</html>

二進制
nkApp/static/h265/image/siagn.png


+ 284 - 0
nkApp/static/h265/index.html

@@ -0,0 +1,284 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>player</title>
+    <script type="text/javascript" src="./src/SuperRender_20.js"></script>
+    <style>
+        .container {
+            position: absolute;
+            top: 0;
+            left: 0;
+        }
+
+        #canvas {
+            position: absolute;
+        }
+        .sk-chase {
+        width: 40px;
+        height: 40px;
+        position: absolute;
+        top: 50%;
+        left: 50%;
+        transform: translate(-50%, -50%);
+        display: block;
+        animation: sk-chase 2.5s infinite linear both;
+      }
+
+      .sk-chase-dot {
+        width: 100%;
+        height: 100%;
+        position: absolute;
+        left: 0;
+        top: 0;
+        animation: sk-chase-dot 2.0s infinite ease-in-out both;
+      }
+
+      .sk-chase-dot:before {
+        content: '';
+        display: block;
+        width: 25%;
+        height: 25%;
+        background-color: #8cc5ff;
+        border-radius: 100%;
+        animation: sk-chase-dot-before 2.0s infinite ease-in-out both;
+      }
+
+      .sk-chase-dot:nth-child(1) { animation-delay: -1.1s; }
+      .sk-chase-dot:nth-child(2) { animation-delay: -1.0s; }
+      .sk-chase-dot:nth-child(3) { animation-delay: -0.9s; }
+      .sk-chase-dot:nth-child(4) { animation-delay: -0.8s; }
+      .sk-chase-dot:nth-child(5) { animation-delay: -0.7s; }
+      .sk-chase-dot:nth-child(6) { animation-delay: -0.6s; }
+      .sk-chase-dot:nth-child(1):before { animation-delay: -1.1s; }
+      .sk-chase-dot:nth-child(2):before { animation-delay: -1.0s; }
+      .sk-chase-dot:nth-child(3):before { animation-delay: -0.9s; }
+      .sk-chase-dot:nth-child(4):before { animation-delay: -0.8s; }
+      .sk-chase-dot:nth-child(5):before { animation-delay: -0.7s; }
+      .sk-chase-dot:nth-child(6):before { animation-delay: -0.6s; }
+
+      @keyframes sk-chase {
+        100% { transform: rotate(360deg); }
+      }
+
+      @keyframes sk-chase-dot {
+        80%, 100% { transform: rotate(360deg); }
+      }
+
+      @keyframes sk-chase-dot-before {
+        50% {
+          transform: scale(0.4);
+        } 100%, 0% {
+            transform: scale(1.0);
+          }
+      }
+      #error_text {
+          width: 170px;
+          height: 170px;
+          background: url("./image/siagn.png") no-repeat;
+          background-size: 100%;
+          position: absolute;
+          top: 50%;
+          left: 50%;
+          transform: translate(-50%, -50%);
+          display: none;
+      }
+      body::-webkit-scrollbar {
+          display: none;
+      }
+    </style>
+</head>
+<body style="margin: 0; padding: 0; width: 100%; height: 100%; z-index:999; background-color: transparent; overflow: hidden">
+    <video id="video"></video>
+    <div class="container">
+        <canvas id="canvas"></canvas>
+        <canvas id="videoCanvas"></canvas>
+    </div>
+    <canvas id="draw" ></canvas>
+    <div class="sk-chase" id="sk-chase">
+        <div class="sk-chase-dot"></div>
+        <div class="sk-chase-dot"></div>
+        <div class="sk-chase-dot"></div>
+        <div class="sk-chase-dot"></div>
+        <div class="sk-chase-dot"></div>
+        <div class="sk-chase-dot"></div>
+    </div>
+    <div id="error_text"></div>
+</body>
+<!-- <script src="./node_modules/file-saver/FileSaver.js"/> -->
+<script src="./src/md5.js" type="text/javascript"></script>
+<script type="module">
+    import Player from "./src/player.js";
+
+    var clickTimeId;
+    let str  = location.href;
+    let num = str.indexOf('?');
+    str = str.substr(num+1);
+    let data = str.split(',');
+    console.log(data);
+
+    // 下标0 wsUrl, 1 rtspUrl, 2 canvas 宽度, 3 canvas高度
+
+    let video = document.getElementById('video');
+    let height = video.clientHeight;
+    video.dblclick = function () {
+    };
+    // function onDocumentClick(event) {
+    //     // 取消上次延时未执行的方法
+    //     clearTimeout(clickTimeId);
+    //     //执行延时
+    //     clickTimeId = setTimeout(function() {
+    //         //此处为单击事件要执行的代码
+    //         console.log("鼠标单击");
+    //     }, 250);
+    // }
+
+    // 设置高度宽度
+    document.getElementById('canvas').width = data[2];
+    document.getElementById('canvas').height = data[3];
+    document.getElementById('videoCanvas').width = data[2];
+    document.getElementById('videoCanvas').height = data[3];
+
+    const options = {
+        video: document.getElementById('video'),
+        canvas: document.getElementById('canvas'),
+        drawer: document.getElementById('draw'),
+        wsUrl: '',
+        rtspUrl: '',
+        user: '',
+        pwd: ''
+    }
+
+    options.wsUrl = data[0];
+    options.rtspUrl = data[1];
+
+    let player = new Player(options);
+    player.init();
+    player.on('error', function () {
+        console.log('连接失败')
+        let er = document.getElementById('error_text');
+        er.style.display = 'block';
+
+        let sk = document.getElementById('sk-chase');
+        sk.style.display = 'none';
+    });
+    player.on('noStream', function () {
+        console.log('noStream');
+        player.close();
+        player = null;
+        player = new Player(options);
+        player.init();
+        player.connect();
+    });
+
+    player.on('canplay', function () {
+        console.log('首次播放')
+        //player.close();
+    });
+
+    player.on('initialCompleted', function () {
+        let data = [[
+            {x: 2861, y: 4395},
+            {x: 6403, y: 4013},
+            {x: 3260, y: 7986},
+            {x: 640, y: 6252}
+        ]];
+        console.log('initialCompleted')
+        player.setROI(data);
+    });
+
+    player.on('ROIFinished', function () {
+       console.log('ROIFinished');
+    });
+
+    player.connect();
+
+    let sk = document.getElementById('sk-chase');
+    sk.style.display = 'none';
+
+    // document.getElementById('close').onclick = ()=>{
+    //     player.close();
+    // };
+
+    // document.getElementById('ROIreset').onclick = () =>{
+    //     player.resetROI();
+    // };
+    //
+    // document.getElementById('ROIset').onclick = () =>{
+    //     let data = [[
+    //         {x: 2861, y: 4395},
+    //         {x: 6403, y: 4013},
+    //         {x: 3260, y: 7986},
+    //         {x: 640, y: 6252}
+    //     ]];
+    //     player.setROI(data);
+    // };
+    //
+    // document.getElementById('ROIdata').onclick = () =>{
+    //     let result = player.getROIData();
+    //     console.log(result)
+    // };
+    //
+    // document.getElementById('ROIsetNum').onclick = ()=> {
+    //     let num = document.getElementById('ROINum').value;
+    //     player.setPolygonNum(num);
+    // }
+
+    function onDocumenDblClick(event) {
+       show = !show;
+       let width = window.screen.width;
+       let height = window.screen.height;
+       let canvas = document.getElementById('canvas');
+       if(show) {
+         if (document.body.requestFullscreen) { //解决兼容性问题
+           document.body.requestFullscreen();
+         } else if (document.body.webkitRequestFullScreen) { //兼容谷歌 /Edge
+           document.body.webkitRequestFullScreen();
+         } else if (document.body.mozRequestFullScreen) { //Firefox
+           document.body.mozRequestFullScreen();
+         }else if(document.body.msRequestFullscreen){//ie
+           document.body.msRequestFullscreen();
+         }
+         canvas.style.position = 'fixed';
+         canvas.style.top = 0;
+         canvas.style.left = 0;
+         document.getElementById('canvas').width = width;
+         document.getElementById('canvas').height = height;
+         document.getElementById('videoCanvas').width = width;
+         document.getElementById('videoCanvas').height = height;
+       } else {
+         if(document.exitFullscreen) {
+           document.exitFullscreen();
+         } else if(document.mozCancelFullScreen) {
+           document.mozCancelFullScreen();
+         } else if(document.webkitExitFullscreen) {
+           document.webkitExitFullscreen();
+         }else if(document.msExitFullscreen) {
+           document.msExitFullscreen();
+         }
+         document.getElementById('canvas').width = data[2];
+         document.getElementById('canvas').height = data[3];
+         document.getElementById('videoCanvas').width = data[2];
+         document.getElementById('videoCanvas').height = data[3];
+       }
+
+
+
+    }
+
+    let cloc = 0;
+    let show = false;
+    document.getElementById('canvas').onclick = function (e) {
+      e.preventDefault();
+      cloc++;
+      setTimeout(() => {
+        cloc = 0;
+      }, 500)
+      if(cloc == 2) {
+        onDocumenDblClick()
+      }
+    }
+
+
+</script>
+</html>

文件差異過大導致無法顯示
+ 1153 - 0
nkApp/static/h265/src/Decoder.js


二進制
nkApp/static/h265/src/Decoder.wasm


+ 180 - 0
nkApp/static/h265/src/H2642.js

@@ -0,0 +1,180 @@
+
+importScripts('./jsFFMPEG.js');
+let initDecoder = null;
+let decoderContext = null;
+let decodeByFFMPEG = null;
+let getWidth = null;
+let getHeight = null;
+let closeContext = null;
+let context = null;
+let outpic = null;
+let outpicptr = null;
+let ID = 264;
+let initialized = false;
+let firstIFrame = true;
+
+class H264Decoder {
+    constructor() {
+
+
+
+       //Module.onRuntimeInitialized = () => {
+            console.log('h264 decoder init')
+
+            initDecoder = Module.cwrap('init_jsFFmpeg', 'void', []);
+            decoderContext = Module.cwrap('context_jsFFmpeg', 'number', ['number']);
+            decodeByFFMPEG = Module.cwrap('decode_video_jsFFmpeg', 'number', ['number', 'array', 'number', 'number']);
+            getWidth = Module.cwrap('get_width', 'number', ['number']);
+            getHeight = Module.cwrap('get_height', 'number', ['number']);
+            closeContext = Module.cwrap('close_jsFFmpeg', 'number', ['number']);
+        initDecoder();
+            this.init();
+            initialized = true;
+        //};
+    }
+    init() {
+        if (context !== null) {
+            closeContext(context);
+            context = null;
+        }
+        context = decoderContext(ID);
+    }
+
+    setOutputSize(size) {
+        console.log("H264 Decoder setOutputSize");
+        let outpicsize = size * 1.5;
+        outpicptr = Module._malloc(outpicsize);
+        outpic = new Uint8Array(Module.HEAPU8.buffer, outpicptr, outpicsize);
+    }
+
+    decode(data) {
+        if(!initialized) {
+            console.log('未初始化完成')
+            return null;
+        }
+        console.log(data.subarray(0, 100))
+        let frameType = ((data[4] & 0x1f) === 7 || (data[4] & 0x1f) === 5) ? 'I' : 'P';
+    //console.log(data[4] & 0x1f)
+        if(frameType === 'I' && initialized) {
+            firstIFrame = true;
+        }
+        if(!firstIFrame) {
+            console.log('非 firstIFrame')
+            return null;
+        }
+        let beforeDecoding = null;
+        let decodingTime = null;
+        let frameData = null;
+        let bufferIdx = null;
+        var dataHeap = null;
+
+        beforeDecoding = Date.now();
+
+        decodeByFFMPEG(context, data, data.length, outpic.byteOffset);
+        decodingTime = Date.now() - beforeDecoding;
+
+
+
+        let width = getWidth(context);
+        let height = getHeight(context);
+
+        console.log(width, height)
+        if (width > 0 && height > 0) {
+            let copyOutput = new Uint8Array(outpic);
+
+            frameData = {
+                'data': copyOutput,
+                'bufferIdx': bufferIdx,
+                'width': width,
+                'height': height,
+                'codecType': 'h264',
+                'decodingTime': decodingTime,
+                'frameType': frameType,
+            };
+            console.log(frameData)
+
+            return frameData;
+        }
+
+        // if(decodeby) {
+        //     //avcodec_decode_video2(context, outpicptr, size, data);
+        //     //console.log(Module.HEAP8.subarray(outpicptr, outpicptr+20))
+        //
+        //     //
+        //     var memoryData = Module._malloc(data.byteLength);
+        //     Module.HEAPU8.set(data, memoryData);
+        //     var ptr = Module._video_decode_frame(video_decoder_ctx, memoryData, data.byteLength);
+        //     Module._free(memoryData);
+        //     if(ptr === 0) {
+        //         console.error("[ERROR] no Frame Data!");
+        //         return null;
+        //     }else {
+        //     }
+        // }else {
+        //     try {
+        //         //outpic = Module.HEAPU8.length - data.length - 1000;
+        //         Module.HEAPU8.set(data, outpic);
+        //         console.log(data.length, data.subarray(0, 30), outpic,  Module.HEAPU8.subarray(outpic))
+        //         //let result = avcodec_decode_video2(context, outpic, size/8, data);
+        //         console.log(h264_decode_frame(context, data, data.length, outpic));
+        //         //dataHeap = new Uint8Array(Module.HEAPU8.buffer, outpic, size);
+        //         //dataHeap.set(data);
+        //         //outpic.set(data);
+        //         //console.log(data.length, data.subarray(0, 30), outpic.byteOffset, outpic.subarray(0, 30), Module.HEAPU8.subarray(outpic.byteOffset))
+        //         //let result = avcodec_decode_video2(context, outpic.byteOffset, 0, data);
+        //         //console.log('result: ', result)
+        //     } catch (e) {
+        //         console.log(e)
+        //     }
+        //
+        // }
+
+
+        // if (!Constructor.prototype.isFirstFrame()) {
+        //     Constructor.prototype.setIsFirstFrame(true);
+        //     frameData = {
+        //         'firstFrame': true,
+        //     };
+        //     return frameData;
+        // }
+        // draw picture in canvas.
+        //console.log(outpic)
+
+        //console.log(width, height)
+        // if (width > 0 && height > 0) {
+        let copyOutput;
+        // if(decodeby) {
+        //     var width = Module.HEAPU32[ptr / 4],
+        //         height = Module.HEAPU32[ptr / 4 + 1],
+        //         YimgBufferPtr = Module.HEAPU32[ptr / 4 + 2],
+        //         UimgBufferPtr = Module.HEAPU32[ptr / 4 + 3],
+        //         VimgBufferPtr = Module.HEAPU32[ptr / 4 + 4],
+        //         YimageBuffer = Module.HEAPU8.subarray(YimgBufferPtr, YimgBufferPtr + width * height),
+        //         UimageBuffer = Module.HEAPU8.subarray(UimgBufferPtr, UimgBufferPtr + width * height / 4),
+        //         VimageBuffer = Module.HEAPU8.subarray(VimgBufferPtr, VimgBufferPtr + width * height / 4);
+        //
+        //     var ydata = new Uint8Array(YimageBuffer);
+        //     var udata = new Uint8Array(UimageBuffer);
+        //     var vdata = new Uint8Array(VimageBuffer);
+        //
+        //     frameData = {
+        //         'bufferIdx': bufferIdx,
+        //         'width': width,
+        //         'height': height,
+        //         'codecType': 'h264',
+        //         'decodingTime': decodingTime,
+        //         'frameType': frameType,
+        //         YData:ydata.buffer,
+        //         UData:udata.buffer,
+        //         VData:vdata.buffer,
+        //     };
+        //
+        //     return frameData;
+        // } else {
+        //     //console.log(outpic)
+        //     copyOutput = new Uint8Array(Module.HEAPU8.buffer, outpic, data.size);
+        //     //console.log(outpic)
+        //
+        // }
+    }
+}

+ 387 - 0
nkApp/static/h265/src/H264SPSParser.js

@@ -0,0 +1,387 @@
+//import Map from './Map.js';
+
+let BITWISE0x00000007 = 0x00000007;
+let BITWISE0x7 = 0x7;
+let BITWISE2 = 2;
+let BITWISE3 = 3;
+let BITWISE4 = 4;
+let BITWISE5 = 5;
+let BITWISE6 = 6;
+let BITWISE8 = 8;
+let BITWISE12 = 12;
+let BITWISE15 = 15;
+let BITWISE16 = 16;
+let BITWISE32 = 32;
+let BITWISE64 = 64;
+let BITWISE255 = 255;
+let BITWISE256 = 256;
+
+function H264SPSParser() {
+    let vBitCount = 0;
+    let spsMap = null;
+    let fps = null;
+
+
+    function constructor() {
+        spsMap = new Map();
+    }
+
+    constructor.prototype = {
+        parse (pSPSBytes) {
+            //console.log("=========================SPS START=========================");
+            vBitCount = 0;
+            spsMap.clear();
+
+            // forbidden_zero_bit, nal_ref_idc, nal_unit_type
+            spsMap.set("forbidden_zero_bit", readBits(pSPSBytes, 1));
+            spsMap.set("nal_ref_idc", readBits(pSPSBytes, BITWISE2));
+            spsMap.set("nal_unit_type", readBits(pSPSBytes, BITWISE5));
+
+            // profile_idc
+            spsMap.set("profile_idc", readBits(pSPSBytes, BITWISE8));
+            spsMap.set("profile_compatibility", readBits(pSPSBytes, BITWISE8));
+
+            // spsMap.set("constrained_set0_flag", readBits(pSPSBytes, 1));
+            // spsMap.set("constrained_set1_flag", readBits(pSPSBytes, 1));
+            // spsMap.set("constrained_set2_flag", readBits(pSPSBytes, 1));
+            // spsMap.set("constrained_set3_flag", readBits(pSPSBytes, 1));
+            // spsMap.set("constrained_set4_flag", readBits(pSPSBytes, 1));
+            // spsMap.set("constrained_set5_flag", readBits(pSPSBytes, 1));
+            // spsMap.set("reserved_zero_2bits", readBits(pSPSBytes, 2));
+
+            // level_idc
+            spsMap.set("level_idc", readBits(pSPSBytes, BITWISE8));
+            spsMap.set("seq_parameter_set_id", ue(pSPSBytes, 0));
+
+            let profileIdc = spsMap.get("profile_idc");
+            let BITWISE100 = 100;
+            let BITWISE110 = 110;
+            let BITWISE122 = 122;
+            let BITWISE244 = 244;
+            let BITWISE44 = 44;
+            let BITWISE83 = 83;
+            let BITWISE86 = 86;
+            let BITWISE118 = 118;
+            let BITWISE128 = 128;
+            let BITWISE138 = 138;
+            let BITWISE139 = 139;
+            let BITWISE134 = 134;
+
+            if ((profileIdc === BITWISE100) || (profileIdc === BITWISE110) ||
+                (profileIdc === BITWISE122) || (profileIdc === BITWISE244) ||
+                (profileIdc === BITWISE44) || (profileIdc === BITWISE83) ||
+                (profileIdc === BITWISE86) || (profileIdc === BITWISE118) ||
+                (profileIdc === BITWISE128) || (profileIdc === BITWISE138) ||
+                (profileIdc === BITWISE139) || (profileIdc === BITWISE134)) {
+                spsMap.set("chroma_format_idc", ue(pSPSBytes, 0));
+                if (spsMap.get("chroma_format_idc") === BITWISE3) {
+                    spsMap.set("separate_colour_plane_flag", readBits(pSPSBytes, 1));
+                }
+
+                spsMap.set("bit_depth_luma_minus8", ue(pSPSBytes, 0));
+                spsMap.set("bit_depth_chroma_minus8", ue(pSPSBytes, 0));
+                spsMap.set("qpprime_y_zero_transform_bypass_flag", readBits(pSPSBytes, 1));
+                spsMap.set("seq_scaling_matrix_present_flag", readBits(pSPSBytes, 1));
+
+                if (spsMap.get("seq_scaling_matrix_present_flag")) {
+                    let num = spsMap.get("chroma_format_idc") !== BITWISE3 ? BITWISE8 : BITWISE12;
+                    let seqScalingListPresentFlag = new Array(num);
+                    for (let i = 0; i < num; i++) {
+                        seqScalingListPresentFlag[i] = readBits(pSPSBytes, 1);
+
+                        if (seqScalingListPresentFlag[i]) {
+                            let slNumber = i < BITWISE6 ? BITWISE16 : BITWISE64;
+                            let lastScale = 8;
+                            let nextScale = 8;
+                            let deltaScale = 0;
+
+                            for (let j = 0; j < slNumber; j++) {
+                                if (nextScale) {
+                                    deltaScale = se(pSPSBytes, 0);
+                                    nextScale = (lastScale + deltaScale + BITWISE256) % BITWISE256;
+                                }
+                                lastScale = (nextScale === 0) ? lastScale : nextScale;
+                            }
+                        }
+                    }
+                    spsMap.set("seq_scaling_list_present_flag", seqScalingListPresentFlag);
+                }
+            }
+            spsMap.set("log2_max_frame_num_minus4", ue(pSPSBytes, 0));
+            spsMap.set("pic_order_cnt_type", ue(pSPSBytes, 0));
+
+            if (spsMap.get("pic_order_cnt_type") === 0) {
+                spsMap.set("log2_max_pic_order_cnt_lsb_minus4", ue(pSPSBytes, 0));
+            } else if (spsMap.get("pic_order_cnt_type") === 1) {
+                spsMap.set("delta_pic_order_always_zero_flag", readBits(pSPSBytes, 1));
+                spsMap.set("offset_for_non_ref_pic", se(pSPSBytes, 0));
+                spsMap.set("offset_for_top_to_bottom_field", se(pSPSBytes, 0));
+                spsMap.set("num_ref_frames_in_pic_order_cnt_cycle", ue(pSPSBytes, 0));
+                for (let numR = 0; numR < spsMap.get("num_ref_frames_in_pic_order_cnt_cycle"); numR++) {
+                    spsMap.set("num_ref_frames_in_pic_order_cnt_cycle", se(pSPSBytes, 0));
+                }
+            }
+            spsMap.set("num_ref_frames", ue(pSPSBytes, 0));
+            spsMap.set("gaps_in_frame_num_value_allowed_flag", readBits(pSPSBytes, 1));
+            spsMap.set("pic_width_in_mbs_minus1", ue(pSPSBytes, 0));
+            spsMap.set("pic_height_in_map_units_minus1", ue(pSPSBytes, 0));
+            spsMap.set("frame_mbs_only_flag", readBits(pSPSBytes, 1));
+
+            if (spsMap.get("frame_mbs_only_flag") === 0) {
+                spsMap.set("mb_adaptive_frame_field_flag", readBits(pSPSBytes, 1));
+            }
+            spsMap.set("direct_8x8_interence_flag", readBits(pSPSBytes, 1));
+            spsMap.set("frame_cropping_flag", readBits(pSPSBytes, 1));
+            if (spsMap.get("frame_cropping_flag") === 1) {
+                spsMap.set("frame_cropping_rect_left_offset", ue(pSPSBytes, 0));
+                spsMap.set("frame_cropping_rect_right_offset", ue(pSPSBytes, 0));
+                spsMap.set("frame_cropping_rect_top_offset", ue(pSPSBytes, 0));
+                spsMap.set("frame_cropping_rect_bottom_offset", ue(pSPSBytes, 0));
+            }
+
+            //vui parameters
+            spsMap.set("vui_parameters_present_flag", readBits(pSPSBytes, 1));
+            if (spsMap.get("vui_parameters_present_flag")) {
+                vuiParameters(pSPSBytes);
+            }
+
+            //console.log("=========================SPS END=========================");
+
+
+            return true;
+        },
+        getSizeInfo () {
+            let SubWidthC = 0;
+            let SubHeightC = 0;
+
+            if (spsMap.get("chroma_format_idc") === 0) { //monochrome
+                SubWidthC = SubHeightC = 0;
+            } else if (spsMap.get("chroma_format_idc") === 1) { //4:2:0
+                SubWidthC = SubHeightC = BITWISE2;
+            } else if (spsMap.get("chroma_format_idc") === BITWISE2) { //4:2:2
+                SubWidthC = BITWISE2;
+                SubHeightC = 1;
+            } else if (spsMap.get("chroma_format_idc") === BITWISE3) { //4:4:4
+                if (spsMap.get("separate_colour_plane_flag") === 0) {
+                    SubWidthC = SubHeightC = 1;
+                } else if (spsMap.get("separate_colour_plane_flag") === 1) {
+                    SubWidthC = SubHeightC = 0;
+                }
+            }
+
+            let PicWidthInMbs = spsMap.get("pic_width_in_mbs_minus1") + 1;
+
+            let PicHeightInMapUnits = spsMap.get("pic_height_in_map_units_minus1") + 1;
+            let FrameHeightInMbs = (BITWISE2 - spsMap.get("frame_mbs_only_flag")) * PicHeightInMapUnits;
+
+            let cropLeft = 0;
+            let cropRight = 0;
+            let cropTop = 0;
+            let cropBottom = 0;
+
+            if (spsMap.get("frame_cropping_flag") === 1) {
+                cropLeft = spsMap.get("frame_cropping_rect_left_offset");
+                cropRight = spsMap.get("frame_cropping_rect_right_offset");
+                cropTop = spsMap.get("frame_cropping_rect_top_offset");
+                cropBottom = spsMap.get("frame_cropping_rect_bottom_offset");
+            }
+            let decodeSize = (PicWidthInMbs * BITWISE16) * (FrameHeightInMbs * BITWISE16);
+            let width = (PicWidthInMbs * BITWISE16) - (SubWidthC * (cropLeft + cropRight));
+            let height = (FrameHeightInMbs * BITWISE16) -
+                (SubHeightC * (BITWISE2 - spsMap.get("frame_mbs_only_flag")) * (cropTop + cropBottom));
+
+            let sizeInfo = {
+                'width': width,
+                'height': height,
+                'decodeSize': decodeSize,
+            };
+
+            return sizeInfo;
+        },
+        getSpsValue (key) {
+            return spsMap.get(key);
+        },
+        getCodecInfo () {
+            let profileIdc = spsMap.get("profile_idc").toString(BITWISE16);
+            let profileCompatibility = spsMap.get("profile_compatibility") < BITWISE15 ?
+                "0" + spsMap.get("profile_compatibility").toString(BITWISE16) :
+                spsMap.get("profile_compatibility").toString(BITWISE16);
+
+            let levelIdc = spsMap.get("level_idc").toString(BITWISE16);
+
+            //console.log("getCodecInfo = " + (profile_idc + profile_compatibility + level_idc));
+            return profileIdc + profileCompatibility + levelIdc;
+
+        },
+
+        getSpsMap() {
+            return spsMap;
+        },
+
+        getFPS() {
+            return fps;
+        }
+    }
+
+    return new constructor();
+
+    function getBit(base, offset) {
+        let offsetData = offset;
+        let vCurBytes = (vBitCount + offsetData) >> BITWISE3;
+        offsetData = (vBitCount + offset) & BITWISE0x00000007;
+        return (((base[(vCurBytes)])) >> (BITWISE0x7 - (offsetData & BITWISE0x7))) & 0x1;
+    }
+
+    function readBits(pBuf, vReadBits) {
+        let vOffset = 0;
+        let vTmp = 0,
+            vTmp2 = 0;
+
+        if (vReadBits === 1) {
+            vTmp = getBit(pBuf, vOffset);
+        } else {
+            for (let i = 0; i < vReadBits; i++) {
+                vTmp2 = getBit(pBuf, i);
+                vTmp = (vTmp << 1) + vTmp2;
+            }
+        }
+
+        vBitCount += vReadBits;
+        return vTmp;
+    }
+
+    function ue(base, offset) {
+        let zeros = 0,
+            vTmp = 0,
+            vReturn = 0;
+        let vIdx = offset;
+        do {
+            vTmp = getBit(base, vIdx++);
+            if (vTmp === 0) {
+                zeros++;
+            }
+        } while (0 === vTmp);
+
+        if (zeros === 0) {
+            vBitCount += 1;
+            return 0;
+        }
+
+        vReturn = 1 << zeros;
+
+        for (let i = zeros - 1; i >= 0; i--, vIdx++) {
+            vTmp = getBit(base, vIdx);
+            vReturn |= vTmp << i;
+        }
+
+        let addBitCount = (zeros * BITWISE2) + 1;
+        vBitCount += addBitCount;
+
+        return (vReturn - 1);
+    }
+
+    function se(base, offset) {
+        let vReturn = ue(base, offset);
+
+        if (vReturn & 0x1) {
+            return (vReturn + 1) / BITWISE2;
+        } else {
+            return -vReturn / BITWISE2;
+        }
+    }
+
+    function hrdParameters(pSPSBytes) {
+        spsMap.set("cpb_cnt_minus1", ue(pSPSBytes, 0));
+        spsMap.set("bit_rate_scale", readBits(pSPSBytes, BITWISE4));
+        spsMap.set("cpb_size_scale", readBits(pSPSBytes, BITWISE4));
+        let cpdCntMinus1 = spsMap.get("cpb_cnt_minus1");
+        let bitRateValueMinus1 = new Array(cpdCntMinus1);
+        let cpbSizeValueMinus1 = new Array(cpdCntMinus1);
+        let cbrFlag = new Array(cpdCntMinus1);
+        //Todo: 原本为i <= cpdCntMinus1,运行到此处时直接停住,原因不明,改为<后正常
+        for (let i = 0; i < cpdCntMinus1; i++) {
+            bitRateValueMinus1[i] = ue(pSPSBytes, 0);
+            cpbSizeValueMinus1[i] = ue(pSPSBytes, 0);
+            cbrFlag[i] = readBits(pSPSBytes, 1);
+        }
+        spsMap.set("bit_rate_value_minus1", bitRateValueMinus1);
+        spsMap.set("cpb_size_value_minus1", cpbSizeValueMinus1);
+        spsMap.set("cbr_flag", cbrFlag);
+
+        spsMap.set("initial_cpb_removal_delay_length_minus1", readBits(pSPSBytes, BITWISE4));
+        spsMap.set("cpb_removal_delay_length_minus1", readBits(pSPSBytes, BITWISE4));
+        spsMap.set("dpb_output_delay_length_minus1", readBits(pSPSBytes, BITWISE4));
+        spsMap.set("time_offset_length", readBits(pSPSBytes, BITWISE4));
+    }
+
+    function vuiParameters(pSPSBytes) {
+        spsMap.set("aspect_ratio_info_present_flag", readBits(pSPSBytes, 1));
+        if (spsMap.get("aspect_ratio_info_present_flag")) {
+            spsMap.set("aspect_ratio_idc", readBits(pSPSBytes, BITWISE8));
+            //Extended_SAR
+            if (spsMap.get("aspect_ratio_idc") === BITWISE255) {
+                spsMap.set("sar_width", readBits(pSPSBytes, BITWISE16));
+                spsMap.set("sar_height", readBits(pSPSBytes, BITWISE16));
+            }
+        }
+
+        spsMap.set("overscan_info_present_flag", readBits(pSPSBytes, 1));
+        if (spsMap.get("overscan_info_present_flag")) {
+            spsMap.set("overscan_appropriate_flag", readBits(pSPSBytes, 1));
+        }
+        spsMap.set("video_signal_type_present_flag", readBits(pSPSBytes, 1));
+        if (spsMap.get("video_signal_type_present_flag")) {
+            spsMap.set("video_format", readBits(pSPSBytes, BITWISE3));
+            spsMap.set("video_full_range_flag", readBits(pSPSBytes, 1));
+            spsMap.set("colour_description_present_flag", readBits(pSPSBytes, 1));
+            if (spsMap.get("colour_description_present_flag")) {
+                spsMap.set("colour_primaries", readBits(pSPSBytes, BITWISE8));
+                spsMap.set("transfer_characteristics", readBits(pSPSBytes, BITWISE8));
+                spsMap.set("matrix_coefficients", readBits(pSPSBytes, BITWISE8));
+            }
+        }
+        spsMap.set("chroma_loc_info_present_flag", readBits(pSPSBytes, 1));
+        if (spsMap.get("chroma_loc_info_present_flag")) {
+            spsMap.set("chroma_sample_loc_type_top_field", ue(pSPSBytes, 0));
+            spsMap.set("chroma_sample_loc_type_bottom_field", ue(pSPSBytes, 0));
+        }
+        spsMap.set("timing_info_present_flag", readBits(pSPSBytes, 1));
+        if (spsMap.get("timing_info_present_flag")) {
+            spsMap.set("num_units_in_tick", readBits(pSPSBytes, BITWISE32));
+            spsMap.set("time_scale", readBits(pSPSBytes, BITWISE32));
+            spsMap.set("fixed_frame_rate_flag", readBits(pSPSBytes, 1));
+
+            fps =  spsMap.get("time_scale") / spsMap.get("num_units_in_tick");
+            if(spsMap.get("fixed_frame_rate_flag")) {
+                fps = fps / 2;
+            }
+        }
+        spsMap.set("nal_hrd_parameters_present_flag", readBits(pSPSBytes, 1));
+        if (spsMap.get("nal_hrd_parameters_present_flag")) {
+            hrdParameters(pSPSBytes);
+        }
+        spsMap.set("vcl_hrd_parameters_present_flag", readBits(pSPSBytes, 1));
+        if (spsMap.get("vcl_hrd_parameters_present_flag")) {
+            hrdParameters(pSPSBytes);
+        }
+        if (spsMap.get("nal_hrd_parameters_present_flag") ||
+            spsMap.get("vcl_hrd_parameters_present_flag")) {
+            spsMap.set("low_delay_hrd_flag", readBits(pSPSBytes, 1));
+        }
+        spsMap.set("pic_struct_present_flag", readBits(pSPSBytes, 1));
+        spsMap.set("bitstream_restriction_flag", readBits(pSPSBytes, 1));
+        if (spsMap.get("bitstream_restriction_flag")) {
+            spsMap.set("motion_vectors_over_pic_boundaries_flag", readBits(pSPSBytes, 1));
+            spsMap.set("max_bytes_per_pic_denom", ue(pSPSBytes, 0));
+            spsMap.set("max_bits_per_mb_denom", ue(pSPSBytes, 0));
+            spsMap.set("log2_max_mv_length_horizontal", ue(pSPSBytes, 0));
+            spsMap.set("log2_max_mv_length_vertical", ue(pSPSBytes, 0));
+            spsMap.set("max_num_reorder_frames", ue(pSPSBytes, 0));
+            spsMap.set("max_dec_frame_buffering", ue(pSPSBytes, 0));
+        }
+    }
+}
+
+
+
+//export default H264SPSParser;

+ 582 - 0
nkApp/static/h265/src/H264Session.js

@@ -0,0 +1,582 @@
+function H264Session() {
+    let rtpTimeStamp = 0;
+    let size1M = 1048576; //1024 * 1024
+    let inputBuffer = new Uint8Array(size1M);
+    let spsSegment = null;
+    let ppsSegment = null;
+
+    let SPSParser = null;
+
+    let width = 0;
+    let height = 0;
+    let inputLength = 0;
+
+    let initalSegmentFlag = true; //用于确定是否是initSegment
+    let initalMediaFrameFlag = true;
+
+    let frameRate = null; //根据SDP或者SPS设置
+    let preSample = null; //上一个Sample
+
+    let inputSegBufferSub = null;
+
+    //MSE使用的数据以及相关配置,顺序codecInfo -> initSegmentData -> mediaSample -> frameData
+    //时间戳用于绘制人脸框
+    let decodedData = {
+        frameData: null, //视频数据
+        timeStamp: null, //时间戳
+        initSegmentData: null, //MP4配置,用于initsegment
+        mediaSample: null, //使用duration控制每一帧的播放时间
+        codecInfo: "", //MSE init时传入,用于创建mediasource
+    };
+    let FRAMETYPE = {
+        1: 'P',
+        5: 'I',
+        6: 'SEI',
+        7: 'I'
+    };
+    let frameType = '';
+    let decodeMode = 'canvas';
+    let outputSize = 0;
+    let curSize = 0;
+
+    const PREFIX = new Uint8Array(['0x00', '0x00', '0x00', '0x01']);
+
+    let firstIframe = false;
+
+    let SEIInfo = {
+        ivs: null,
+        timestamp:null,
+    };
+
+    let preWidth = null,
+        preHeight = null;
+    let resetTimeCount = 0;
+    let lastTimeStamp = 0;
+    //const RESETTIME = 162000000;
+    const RESETTIME = 4320000;
+    let SEIBuffer = null;
+    let lastTime =0;
+    let decoder = null;
+    function constructor() {
+
+    }
+
+    constructor.prototype = {
+        init() {
+            SPSParser = new H264SPSParser();
+            decoder = new H264Decoder();
+            this.resolutionChangedCallback = ()=>{};
+        },
+
+        remuxRTPData(rtspInterleaved, rtpHeader, rtpPayload) {
+            //console.log(rtspInterleaved)
+            //console.log(rtpHeader)
+            let PaddingSize = 0;
+            let extensionHeaderLen = 0; //如果RtpHeader.X=1,则在RTP报头后跟有一个扩展报头
+            let PAYLOAD = null;
+//console.log(rtpHeader)
+//console.log(rtspInterleaved, rtpHeader, rtpPayload.subarray(0,5))
+            let RtpHeader = {
+                V: rtpHeader[0] >>> 6,
+                P: rtpHeader[0] & 0x20,
+                X: rtpHeader[0] & 0x10,
+                CC: rtpHeader[0] & 0x0F,
+                M: (rtpHeader[1] & 0x80) >> 7,
+                PT: rtpHeader[1] & 127,
+                SN: (rtpHeader[2] << 8) + rtpHeader[3],
+                timeStamp: (rtpHeader[4] << 24) + (rtpHeader[5] << 16) + (rtpHeader[6] << 8) + rtpHeader[7],
+                SSRC: (rtpHeader[8] << 24) + (rtpHeader[9] << 16) + (rtpHeader[10] << 8) + rtpHeader[11],
+            };
+            if (RtpHeader.P) { //填充
+                PaddingSize = rtpPayload[rtpPayload.length - 1];
+                //console.log("Padding - " + PaddingSize);
+            }
+
+            if (RtpHeader.X) { //扩展
+                extensionHeaderLen = (((rtpPayload[2] << 8) | rtpPayload[3]) * 4) + 4;
+                console.log('X: ' + rtpPayload[0])
+            }
+//console.log('extensionHeaderLen: '+ extensionHeaderLen)
+            PAYLOAD = rtpPayload.subarray(extensionHeaderLen, rtpPayload.length - PaddingSize);
+            rtpTimeStamp = RtpHeader.timeStamp;
+
+            //console.log(rtpTimeStamp, rtpHeader[4], rtpHeader[5], rtpHeader[6] , rtpHeader[7], PAYLOAD[0] & 0x1f)
+            /* 载荷结构(https://blog.csdn.net/davebobo/article/details/52994596)
+            +---------------+
+            |0|1|2|3|4|5|6|7|
+            +-+-+-+-+-+-+-+-+
+            |F|NRI|  Type   |
+            +---------------+
+            Type = 1-23 单个NAL单元包
+            Type = 24,25, 26, 27聚合包
+            Type = 28,29, 分片单元
+            */
+            //console.log(rtspInterleaved,rtpHeader, PAYLOAD[0]);
+            let nalType = (PAYLOAD[0] & 0x1f);
+            //console.log(PAYLOAD[0] + ' nalType: ' + nalType);
+
+//console.log('rtpPayload.length: ' + rtpPayload.length)
+//console.log(nalType, PAYLOAD[0])
+//console.log('nalType: ' + nalType, RtpHeader.M, rtpTimeStamp)
+            //console.log('nalType: ', nalType, ' timestamp: ', rtpTimeStamp);
+            switch (nalType) {
+                case 6: //SEI
+                    //console.log(PAYLOAD, String.fromCharCode.apply(null, PAYLOAD))
+                    if(SEIParse(PAYLOAD) === null) {
+                        return;
+                    }
+                    inputBuffer = setBuffer(inputBuffer, PREFIX);
+                    inputBuffer = setBuffer(inputBuffer, PAYLOAD);
+                    break;
+                case 7: //SPS
+                    //console.log('SPS');
+                    SPSParser.parse(removeH264or5EmulationBytes(PAYLOAD));
+                    let sizeInfo = SPSParser.getSizeInfo();
+                    //console.log(SPSParser.getSpsMap())
+                    width = sizeInfo.width;
+                    height = sizeInfo.height;
+
+                    if(preWidth !== width || preHeight !== height) {
+                        console.log('resolution changed!');
+                        console.log('preWidth: ', preWidth, ' preHeight: ', preHeight, ' width: ', width, ' height: ', height);
+                        preWidth = width;
+                        preHeight = height;
+                    }
+                    inputBuffer = setBuffer(inputBuffer, PREFIX);
+                    inputBuffer = setBuffer(inputBuffer, PAYLOAD);
+                    spsSegment = PAYLOAD;
+                    //console.log('width: ',width, 'height: ', height)
+                    curSize = sizeInfo.decodeSize;
+                    firstIframe = true;
+//console.log(spsSegment)
+                    if (frameRate === null) {
+                        frameRate = SPSParser.getFPS();
+                    }
+                    break;
+                case 8: //PPS
+                    //console.log('PPS')
+                    inputBuffer = setBuffer(inputBuffer, PREFIX);
+                    inputBuffer = setBuffer(inputBuffer, PAYLOAD);
+                    ppsSegment = PAYLOAD;
+//console.log(ppsSegment)
+                    break;
+                case 28: //FU
+                    //console.log('FU');
+                    let startBit = ((PAYLOAD[1] & 0x80) === 0x80),
+                        endBit = ((PAYLOAD[1] & 0x40) === 0x40),
+                        fuType = PAYLOAD[1] & 0x1f,
+                        payloadStartIndex = 2;
+                    //console.log('startBit: ' + startBit + ' endBit: ' + endBit)
+                    //console.log('fuType: ' + fuType)
+                    if (startBit === true && endBit === false) {
+                        let newNalHeader = new Uint8Array(1);
+                        newNalHeader[0] = ((PAYLOAD[0] & 0xe0) | fuType);
+                        //console.log('newNalHeader: ', newNalHeader[0])
+                        //console.log('fuType: ' + fuType)
+                        //console.log((PAYLOAD[2] << 8) + PAYLOAD[3])
+//console.log(new Uint8Array(PAYLOAD.subarray(0, 100)));
+                        if (false) { //赛兰摄像头,SPS,PPS,I帧打在一个RTP包中
+                            PAYLOAD[1] = newNalHeader[0];
+                            SPSParser.parse(removeH264or5EmulationBytes(PAYLOAD.subarray(1, 27)));
+                            let sizeInfo = SPSParser.getSizeInfo();
+//console.log(sizeInfo, SPSParser.getSpsMap())
+                            //SPS
+                            width = sizeInfo.width;
+                            height = sizeInfo.height;
+                            inputBuffer = setBuffer(inputBuffer, PREFIX);
+                            inputBuffer = setBuffer(inputBuffer, PAYLOAD.subarray(1, 27));
+                            spsSegment = PAYLOAD.subarray(1, 27);
+                            //console.log('width: ',width, 'height: ', height)
+                            curSize = sizeInfo.decodeSize;
+                            firstIframe = true;
+
+                            //PPS
+                            inputBuffer = setBuffer(inputBuffer, PREFIX);
+                            inputBuffer = setBuffer(inputBuffer, PAYLOAD.subarray(30, 34));
+                            ppsSegment = PAYLOAD.subarray(30, 34);
+
+                            //I
+                            inputBuffer = setBuffer(inputBuffer, PREFIX);
+                            inputBuffer = setBuffer(inputBuffer, PAYLOAD.subarray(38, PAYLOAD.length));
+
+                        } else {
+                            //console.log(newNalHeader[0] & 0x1f)
+                            inputBuffer = setBuffer(inputBuffer, PREFIX);
+                            inputBuffer = setBuffer(inputBuffer, newNalHeader);
+                            inputBuffer = setBuffer(inputBuffer, PAYLOAD.subarray(payloadStartIndex, PAYLOAD.length));
+                        }
+
+                    } else {
+                        //console.log(startBit, endBit, 'endBit')
+                        inputBuffer = setBuffer(inputBuffer,
+                            PAYLOAD.subarray(payloadStartIndex, PAYLOAD.length));
+                    }
+//console.log(startBit,endBit)
+                    // if(endBit === true) {
+                    //     end = true;
+                    // }
+                    break;
+                case 1:
+                    inputBuffer = setBuffer(inputBuffer, PREFIX);
+                    inputBuffer = setBuffer(inputBuffer, PAYLOAD);
+                    break;
+                default:
+                    //console.log('nalType: ' + nalType);
+                    //console.log(PAYLOAD)
+                    break;
+            }
+
+            //console.log('ppsSegment: ', ppsSegment)
+            //console.log('nalType: ' + nalType);
+//console.log('M: ' + RtpHeader.M + ' ' + (rtpHeader[1] & 0x80))
+            //console.log(RtpHeader)
+
+
+//console.log('RtpHeader.M: ', RtpHeader.M)
+            //check marker bit
+            if (RtpHeader.M) {
+                if (!firstIframe) {
+                    inputLength = 0;
+                    return;
+                }
+                let inputBufferSub = inputBuffer.subarray(0, inputLength);
+                frameType = FRAMETYPE[inputBufferSub[4] & 0x1f];
+
+                //只根据视频帧计算resetTimeCount
+                if(frameType !== 'SEI') {
+                    // rtp时间戳周期为RESETTIME,如果单向递增,设为0
+                    if(lastTimeStamp - rtpTimeStamp > (RESETTIME / 2)) { //判断lastTimeStamp远大于rtpTimeStamp,防止后一帧比前一帧先到的情况
+                        //console.log(lastTimeStamp - rtpTimeStamp)
+                        console.warn('时间戳重置', lastTimeStamp, rtpTimeStamp, frameType, new Date())
+                        resetTimeCount ++;
+                    }
+                    rtpTimeStamp = rtpTimeStamp + RESETTIME * resetTimeCount;
+                } else {
+                    //同一帧的SEI比视频发送慢时
+                    if (rtpTimeStamp - lastTimeStamp > (RESETTIME / 2)) {
+                        console.warn('SEI翻转', rtpTimeStamp , lastTimeStamp);
+                        rtpTimeStamp = rtpTimeStamp + RESETTIME * (resetTimeCount - 1);
+                    } else {
+                        rtpTimeStamp = rtpTimeStamp + RESETTIME * resetTimeCount;
+                    }
+                    //console.log('SEI', rtpTimeStamp, 'video', lastTimeStamp, lastTimeStamp+ RESETTIME * resetTimeCount - rtpTimeStamp)
+                    // //同一帧的SEI比视频发送快时
+                    // if(rtpTimeStamp - lastTimeStamp === 3600) {
+                    //     if(rtpTimeStamp === 0 ) {
+                    //         rtpTimeStamp = rtpTimeStamp + RESETTIME * (resetTimeCount + 1);
+                    //     } else {
+                    //         rtpTimeStamp = rtpTimeStamp + RESETTIME * resetTimeCount;
+                    //     }
+                    // }
+                }
+
+                if(frameType === 'SEI') {
+                    //SEI被分片(nal === 28)时,分片包发送完后marker为1,不会和视频帧一起
+                    SEIBuffer = inputBuffer.subarray(4, inputLength);
+                    //console.log(SEIBuffer)
+                    inputBufferSub = new Uint8Array();
+                }
+                if(SEIBuffer) {
+                    let SEI = SEIParse(SEIBuffer);
+                    if (SEI) {
+                        SEIInfo.ivs = SEI;
+                        SEIInfo.timestamp = rtpTimeStamp;
+                        //console.log('GET SEI', rtpTimeStamp)
+                        //SEI信息
+                        decodedData.SEIInfo = SEIInfo;
+
+                        if (!(rtpTimeStamp - lastTime)) {
+                            console.log('上个SET包时间和本次相等');
+                            console.log('lastTime: ', lastTime, ' rtpTimeStamp: ', rtpTimeStamp, RtpHeader.timeStamp, rtpHeader[4], rtpHeader[5], rtpHeader[6], rtpHeader[7])
+                        }
+                        if ((rtpTimeStamp - lastTime) !== 3600) {
+                            //console.log('SEI 时间差:', (rtpTimeStamp - lastTime), rtpTimeStamp, lastTime)
+                        }
+                        lastTime = rtpTimeStamp;
+                        SEIInfo = {
+                            ivs: null,
+                            timestamp: 0,
+                        };
+                    }
+                    SEIBuffer = null;
+                }
+
+                if(decodeMode === 'canvas' && (frameType !== 'SEI')) {
+                    if (outputSize !== curSize) {
+                        outputSize = curSize;
+                        decoder.setOutputSize(curSize);
+                    }
+
+                    decodedData.frameData = decoder.decode(inputBufferSub);
+                    decodedData.decodeMode = 'canvas';
+                    decodedData.timeStamp = rtpTimeStamp;
+                    decodedData.width = width;
+                    decodedData.height = height;
+                    this.handleDecodedData(decodedData)
+                } else {
+                    if (!initalSegmentFlag) {
+                        decodedData.initSegmentData = null;
+                        decodedData.codecInfo = null;
+                    } else {
+                        initalSegmentFlag = false;
+                        const info = {
+                            id: 1,
+                            width: width,
+                            height: height,
+                            type: "video",
+                            profileIdc: SPSParser.getSpsValue("profile_idc"),
+                            profileCompatibility: 0,
+                            levelIdc: SPSParser.getSpsValue("level_idc"),
+                            sps: [spsSegment],
+                            pps: [ppsSegment],
+                            timescale: 1e3,
+                            fps: frameRate
+                        };
+                        decodedData.initSegmentData = info;
+                        decodedData.codecInfo = SPSParser.getCodecInfo();
+                        //console.log(info.pps)
+                    }
+
+                    if (frameType === 'I') {
+//console.log('ppsSegment: ', ppsSegment)
+                        let h264parameterLength = spsSegment.length + ppsSegment.length + 8;
+                        inputSegBufferSub = inputBufferSub.subarray(h264parameterLength, inputBufferSub.length);
+                    } else {
+                        inputSegBufferSub = inputBufferSub.subarray(0, inputBufferSub.length);
+                    }
+
+                    let segSize = inputSegBufferSub.length - 4;
+                    //mp4 box头
+                    inputSegBufferSub[0] = (segSize & 0xFF000000) >>> 24;
+                    inputSegBufferSub[1] = (segSize & 0xFF0000) >>> 16;
+                    inputSegBufferSub[2] = (segSize & 0xFF00) >>> 8;
+                    inputSegBufferSub[3] = (segSize & 0xFF);
+
+                    decodedData.frameData = new Uint8Array(inputSegBufferSub);
+
+                    let sample = {
+                        duration: Math.round((1 / frameRate) * 1000),
+                        size: inputSegBufferSub.length,
+                        frame_time_stamp: null,
+                        frameDuration: null,
+                    };
+                    sample.frame_time_stamp = rtpTimeStamp; //Todo:暂时为null,通过帧率控制duration
+                    if (initalMediaFrameFlag) {
+                        sample.frameDuration = 0;
+                        initalMediaFrameFlag = false;
+                    } else {
+                        if(frameRate) {
+                            sample.frameDuration = Math.round(1000 / frameRate);
+                        }else {
+                            sample.frameDuration = (sample.frame_time_stamp - preSample.frame_time_stamp) / 90; // 时钟频率90000,timescale=1000
+                        }
+                    }
+                    preSample = sample;
+
+                    decodedData.mediaSample = sample;
+
+                    decodedData.timeStamp = rtpTimeStamp;
+
+                    this.handleDecodedData(decodedData);
+                }
+
+
+                inputLength = 0;
+                decodedData.SEIInfo = null;
+                inputSegBufferSub = null;
+                if(frameType !== 'SEI') {
+                    lastTimeStamp = RtpHeader.timeStamp;
+                }
+                frameType = '';
+            }
+            //console.log('xxxxxxxxxxxxxxxxxxxxxxxxx')
+        },
+
+        set rtpSessionCallback(func) {
+            this.handleDecodedData = func;
+        },
+
+        setFrameRate(fps) {
+            frameRate = fps;
+            //console.log('frameRate: ', frameRate)
+        },
+
+        setResolutionChangedCallback(callback) {
+            this.resolutionChangedCallback = callback;
+        }
+    }
+
+    return new constructor();
+
+    function setBuffer(buffer1, buffer2) {
+        let bufferTemp = buffer1;
+        if ((inputLength + buffer2.length) > buffer1.length) {
+            bufferTemp = new Uint8Array(buffer1.length + size1M);
+        }
+
+        bufferTemp.set(buffer2, inputLength);
+        inputLength += buffer2.length;
+        return bufferTemp;
+    }
+}
+
+
+
+
+/**
+ * 去除SPS中的Emulation字节
+ * @param data SPS源数据
+ * @returns {Array} 去除后Emulation字节后的SPS
+ */
+function removeH264or5EmulationBytes(data) {
+    let toSize = 0;
+    let i = 0;
+    let to = [];
+    let dataLength = data.length;
+    while (i < dataLength) {
+        if (i + 2 < dataLength && data[i] === 0 && data[i + 1] === 0 && data[i + 2] === 3) {
+            to[toSize] = to[toSize + 1] = 0;
+            toSize += 2;
+            i += 3;
+        } else {
+            to[toSize] = data[i];
+            toSize += 1;
+            i += 1;
+        }
+    }
+    return to;
+}
+
+/**
+ * 解析SEI信息
+ * @param data
+ * @return {Array}
+ */
+function SEIParse(data) {
+    //console.log(data)
+    if((data[0] & 0x1f) !== 6) {
+        //非SEI
+        return null;
+    }
+
+    if(data[1] !== 0x55 || data[2] !== 0x4C ||data[3] !== 0x53 ||data[4] !== 0x40) {
+        //ULS@开头
+        console.warn('unknown SEI type');
+        return null;
+    }
+
+    let dataLength = data.length;
+    let type = (data[5] << 8) + data[6];
+    let checkSum = (data[7] << 8) + data[8];
+    // if(dataLength !== (checkSum + 1 + 4 + 4)) {
+    //     console.log('SEI check fail!');
+    //     return null;
+    // }
+    let result;
+    data = data.subarray(9);
+    switch(type) {
+        case 0:
+            result = parseRect(data);
+            break;
+        case 1:
+            //console.log(parseBody(data))
+            result = parseBody(data);
+            break;
+        default:
+            result = null;
+            break;
+    }
+    return result;
+}
+
+function parseRect(data) {
+    //console.log(data)
+    let dataLength = data.length;
+    let contents = [];
+    while(dataLength > 0) {
+        //console.log('dataLength: ', dataLength)
+        let x0 = ((data[4] & 0x7f) << 8) + data[5],
+            y0 = ((data[6] & 0x7f) << 8) + data[7],
+            width = ((data[8] & 0x7f) << 8) + data[9] - x0,
+            height = ((data[10] & 0x7f) << 8) + data[11] - y0;
+        let content = {
+            type: 'rect',
+            id: (data[2] << 8) + data[3],
+            rect: [x0, y0, width, height],
+            state: data[1] & 0x01,
+            quality: (data[1] & 0x02) >> 1,
+        };
+        Array.prototype.push.apply(contents, [content]);
+        data = data.subarray(12);
+        dataLength = data.length;
+    }
+
+    return contents;
+}
+
+function parseBody(data) {
+    let dataLength = data.length;
+    let contents = [];
+    while(dataLength > 0) {
+        //console.log('dataLength: ', dataLength)
+        let x0 = ((data[4] & 0x7f) << 8) + data[5],
+            y0 = ((data[6] & 0x7f) << 8) + data[7],
+            width = ((data[8] & 0x7f) << 8) + data[9] - x0,
+            height = ((data[10] & 0x7f) << 8) + data[11] - y0,
+            boxConfidence = ((data[12] & 0x7f) << 8) + data[13];
+        let points = [];
+
+        for(let i = 0; i < 17; i++) {
+            let point = {
+                x: ((data[16 + i * 8] & 0x7f) << 8) + data[17 + i * 8],
+                y: ((data[18 + i * 8] & 0x7f) << 8) + data[19 + i * 8],
+                confidence: ((data[20 + i * 8] & 0x7f) << 8) + data[21 + i * 8],
+                // x: Math.random() * 8191,
+                // y: Math.random() * 8191,
+                // confidence: 1,
+            };
+            points.push(point);
+        }
+        let content = {
+            type: 'coco-pose',
+            id: (data[2] << 8) + data[3],
+            handsUp: data[1] & 0x04,
+            boundingBox: [x0, y0, width, height],
+            boxConfidence,
+            points: parseBodyToTree(points),
+            state: data[1] & 0x01,
+        };
+        Array.prototype.push.apply(contents, [content]);
+        data = data.subarray(152);
+        dataLength = data.length;
+
+    }
+    return contents;
+}
+
+/**
+ * 将智能帧中的人体姿态点转化为树结构(双亲表示法)
+ * @param points
+ */
+function parseBodyToTree(points) {
+    let newPoints = [];
+    newPoints[0] = {...points[0], parent: -1, pointColor:'#FF0002', lineColor: '#FF0002'};
+    newPoints[1] = {...points[1], parent: 0, pointColor:'#FF0002', lineColor: '#FF0002'};
+    newPoints[2] = {...points[2], parent: 0, pointColor:'#FF0002', lineColor: '#FF0002'};
+    newPoints[3] = {...points[5], parent: 17, pointColor:'#D9E34F', lineColor: '#FF0002'};
+    newPoints[4] = {...points[6], parent: 17, pointColor:'#D9E34F', lineColor: '#FF0002'};
+    newPoints[5] = {...points[3], parent: 1, pointColor:'#00FF00', lineColor: '#FF0002'};
+    newPoints[6] = {...points[4], parent: 2, pointColor:'#FFAC00', lineColor: '#FF0002'};
+    newPoints[7] = {...points[7], parent: 3, pointColor:'#00FF45', lineColor: '#'};
+    newPoints[8] = {...points[11], parent: 17, pointColor:'#EEC446', lineColor: '#'};
+    newPoints[9] = {...points[8], parent: 4, pointColor:'#43D3AF', lineColor: '#'};
+    newPoints[10] = {...points[12], parent: 17, pointColor:'#7A93E8', lineColor: '#'};
+    newPoints[11] = {...points[9], parent: 7, pointColor:'#EFB842', lineColor: '#'};
+    newPoints[12] = {...points[13], parent: 8, pointColor:'#E56C00', lineColor: '#'};
+    newPoints[13] = {...points[10], parent: 9, pointColor:'#47CD43', lineColor: '#0096FF'};
+    newPoints[14] = {...points[14], parent: 10, pointColor:'#3868D2', lineColor: '#00FF51'};
+    newPoints[15] = {...points[15], parent: 12, pointColor:'#DF4D01', lineColor: '#5100FF'};
+    newPoints[16] = {...points[16], parent: 14, pointColor:'#1E48D4', lineColor: '#00FFA0'};
+    newPoints[17] = {x: (points[5].x + points[6].x) / 2,y: (points[5].y + points[6].y) / 2, parent: -1, pointColor:'#D9E34F', lineColor: '#00FFA0'};
+    return newPoints;
+}

+ 0 - 0
nkApp/static/h265/src/H265.js


部分文件因文件數量過多而無法顯示