VideoDecodeWorker.js 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094
  1. let SDKModule;
  2. const VIDEO_FRAME_SUB_TYPE_I = 0; //I帧
  3. const VIDEO_FRAME_SUB_TYPE_P = 1; //P帧
  4. const VIDEO_FRAME_SUB_TYPE_B = 2; //B帧
  5. const VIDEO_FRAME_SUB_TYPE_SMART_I = 18; //智能I帧
  6. const VIDEO_FRAME_SUB_TYPE_SMART_P = 19; //智能P帧
  7. const VIDEO_FRAME_SUB_TYPE_SMART_I_NORENDER = 20; //智能I帧,但不显示
  8. const ENCODE_TYPE_VIDEO_HI_H264 = 2; //海思H.264编码格式
  9. const ENCODE_TYPE_VIDEO_MY_H264 = 4; //公司H.264编码格式
  10. const ENCODE_TYPE_VIDEO_STD_H264 = 8; //标准H.264编码格式
  11. const ENCODE_TYPE_VIDEO_H265 = 12; //H.265编码格式
  12. const DATA_RECORD_MP4 = 5; //录制MP4格式
  13. const SP_STREAM_TYPE_DHSTD = 8; //dav编码格式
  14. const STREAM_TYPE_SVC = 13; //H.264 SVC编码格式
  15. const SP_STREAM_TYPE_FLV = 18; //flv编码格式
  16. const ENCRYPT_UNKOWN = 0; //未知加密类型
  17. const ENCRYPT_AES = 1; //AES加密类型,16进制数组格式
  18. const ENCRYPT_AES256 = 2; //AES256加密类型,16进制数组格式
  19. const ENCRYPT_AES_STRING_FORMAT = 3; //AES加密类型,字符串格式
  20. const CACHE_MODE_OFF = 0; //关闭实时流自适应缓冲模式
  21. const ADAPTIVE_CACHE = 1; //自适应缓冲
  22. const REALTIME_FIRST = 2; //实时优先
  23. const FLUENCY_FIRST = 3; //流畅优先
  24. const FRAME_SCENE_POINTS_INFOR_SIZE = 144; // 景物点信息单组信息长度
  25. /* IVS类型 */
  26. var IVS_TYPE =
  27. {
  28. IVSINFOTYPE_PRESETPOS : 1,
  29. IVSINFOTYPE_MOTINTRKS : 2,
  30. IVSINFOTYPE_MOTINTRKS_EX : 3,
  31. IVSINFOTYPE_LIGHT : 4, // 光照
  32. IVSINFOTYPE_RAWDATA : 5, // jason数据
  33. IVSINFOTYPE_TRACK : 6, // 智能分析信息
  34. IVSINFOTYPE_TRACK_EX_B0 : 7, // 智能结构化数据信息
  35. IVSINFOTYPE_MOTIONFRAME : 9,
  36. IVSINFOTYPE_VIDEO_CONCENTRATION : 10,
  37. IVSINFOTYPE_OVERLAY_PIC : 11, // 叠加图片帧
  38. IVSINFOTYPE_OSD_INFO : 12, // OSD辅助帧
  39. IVSINFOTYPE_GPS_INFO : 13, // GPS辅助帧
  40. IVSINFOTYPE_TAGGING_INFO : 14, // 景物点信息标注帧,辅助帧(0x13)
  41. IVSINFOTYPE_TRACK_A1 : 15, // NVR浓缩信息轨迹点
  42. IVSINFOTYPE_DATA_WITH_LARGE_AMOUNT : 16,
  43. IVSINFOTYPE_TRACK_A1_EX : 17, // NVR浓缩信息轨迹点(扩展)
  44. IVSINFOTYPE_DATA_WITH_WATER_LEVEL_MONITOR : 18, //水位检测水位尺信息帧(0x17)
  45. IVSINFOTYPE_INTELFLOW : 19, // 智能客流量
  46. IVSINFOTYPE_DATA_WITH_SOUND_DECIBEL : 20, //声音警报分贝值信息帧(0x18)
  47. IVSINFOTYPE_DATA_WITH_SMART_MOTION : 21, //智能动检信息帧(0x19)
  48. IVSINFOTYPE_DHOP_SMART : 22, //开放平台智能帧(0x14)
  49. IVSINFOTYPE_TRAFFIC_LIGHT : 23, //交通信号灯(红绿灯)辅助帧(0x1D)
  50. IVSINFOTYPE_PTZ_LOCATION : 24, //云台位置帧(0x21)
  51. };
  52. var DRAW_TYPE =
  53. {
  54. DRAW_JSON : 0,
  55. DRAW_TRACK : 1,
  56. DRAW_ALARM : 2,
  57. DRAW_RULE : 3,
  58. DRAW_MOVE_CHECK : 7,
  59. DRAW_TEST : 9,
  60. DRAW_WEB_RULE : 11,
  61. DRAW_WEB_ALARM : 12,
  62. DRAW_FLOW_INFO : 13,
  63. DRAW_TRACKEX2 : 14,
  64. DRAW_WUXI235_TRACKEX2 : 15,
  65. DRAW_TRACKEXA1 : 16,
  66. DRAW_TRACKEX2_TYPE_HUMAN : 17,
  67. DRAW_TRACKEX2_TYPE_VEHICLE : 18,
  68. DRAW_TRACKEX2_TYPE_NONMOTOR : 19,
  69. DRAW_TRACKEX2_TYPE_SHOPPRESENCE : 20,
  70. DRAW_TRACKEX2_TYPE_FLOWBUSINESS : 21,
  71. DRAW_INTELFLOW : 22,
  72. DRAW_SMARTMOTION : 23,
  73. DRAW_DHOPSMART : 24,
  74. DRAW_DATA_WITH_LARGE_AMOUNT : 25,//大数据量帧
  75. DRAW_TRACKEX2_TYPE_BAG : 26,
  76. DRAW_RULE_HIGHWAY_LANES : 27, //高速车道线
  77. DRAW_WATER_LEVEL_MONITOR : 28, //水位尺
  78. DRAW_END : 29
  79. };
  80. //DHOP元素类型
  81. var IVS_DHOP_ElEMENT_TYPE =
  82. {
  83. EM_DHOP_CIRCLE : 1,
  84. EM_DHOP_BrokenLine : 2,
  85. EM_DHOP_POLYGON : 3,
  86. EM_DHOP_TEXT : 4
  87. };
  88. importScripts('libplay.js');
  89. addEventListener('message', receiveMessage, false);
  90. Module.onRuntimeInitialized = function(){
  91. m_bLoadSuccess = true;
  92. var msgType = 'LoadSuccess';
  93. sendMessage(m_nPlayPort, msgType, null);
  94. }
  95. var m_bPlayback = 0;
  96. var m_bSupportH264MSE = false;
  97. var m_bSupportH265MSE = false;
  98. var m_nCanvasWidth = 1920;
  99. var m_nCanvasHeight = 1080;
  100. var m_nPlayPort = 0;
  101. var jsInputData = null;
  102. var jsInputDataAry = null;
  103. var jsFrameBuf = null;
  104. var jsFrameInfo = null;
  105. let dataView = null;
  106. var jsBuf = null;
  107. var jsFrameBodyData = null;
  108. var jsBufY = null;
  109. var jsBufU = null;
  110. var jsBufV = null;
  111. var jsYuvDataY = null;
  112. var jsYuvDataU = null;
  113. var jsYuvDataV = null;
  114. var jsRecordFrameBuf = null;
  115. var jsRecordFrameInfo = null;
  116. var dataViewRecord = null;
  117. let ivsBuf = null;
  118. let ivsDataArray = null;
  119. let ivsDataView = null;
  120. var m_nWidth = 0;
  121. var m_nHeight = 0;
  122. var m_nPreWidth = 0;
  123. var m_nPreHeight = 0;
  124. var m_bSmartEncode = 0;
  125. var m_nVideoEncodeType = 0;
  126. var m_bLoadSuccess = false;
  127. var m_bDecryptionResult = false;
  128. var m_nTotalStreamLength = 0;
  129. function receiveMessage(event)
  130. {
  131. if (!m_bLoadSuccess)
  132. {
  133. return;
  134. }
  135. var message = event.data;
  136. switch (message.nType)
  137. {
  138. //初始化
  139. case 'Init':
  140. m_bPlayback = message.option.bPlayback;
  141. m_bSupportH264MSE = message.option.bSupportH264MSE;
  142. m_bSupportH265MSE = message.option.bSupportH265MSE;
  143. m_nCanvasWidth = message.option.nCanvasWidth;
  144. m_nCanvasHeight = message.option.nCanvasHeight;
  145. Init();
  146. break;
  147. //送流
  148. case 'InputData':
  149. InputData(message.pData);
  150. break;
  151. //打开智能绘制
  152. case 'OpenIVSDraw':
  153. OpenIVSDraw();
  154. break;
  155. //关闭智能绘制
  156. case 'CloseIVSDraw':
  157. CloseIVSDraw();
  158. break;
  159. //开始码流录制
  160. case 'StartRecord':
  161. StartRecord(message.nRecordType);
  162. break;
  163. //停止码流录制
  164. case 'StopRecord':
  165. StopRecord();
  166. break;
  167. //设置播放速度
  168. case 'SetPlaySpeed':
  169. SetPlaySpeed(message.nSpeed);
  170. break;
  171. case 'GetOriginalKeyCallBack':
  172. GetOriginalKey(message.playToken, message.playTokenKey, message.deviceID);
  173. break;
  174. case 'SetWebSecurityKey':
  175. SetWebSecurityKey(message.nDecryptType, message.nFrameType, message.strKey, message.stStreamInfo);
  176. break;
  177. //设置解密秘钥
  178. case 'SetSecurityKey':
  179. SetSecurityKey(message.nEncryptType, message.szKey, message.nKeyLen, message.szKeyId, message.nKeyIdLen);
  180. break;
  181. //设置是否支持硬解码标记
  182. case 'SetSupportWebMSE':
  183. m_bSupportH264MSE = message.bSupportH264MSE;
  184. m_bSupportH265MSE = message.bSupportH265MSE;
  185. SetSupportWebMSE(m_bSupportH264MSE, m_bSupportH265MSE);
  186. //暂停播放
  187. case 'Pause':
  188. Pause(message.bPause);
  189. break;
  190. //抓图
  191. case 'CatchPic':
  192. CatchPic();
  193. break;
  194. //停止播放
  195. case 'Stop':
  196. Stop();
  197. break;
  198. case 'setPrintLogLevel':
  199. SetPrintLogLevel(message.nLogLevel);
  200. break;
  201. default:
  202. break;
  203. }
  204. }
  205. function Init()
  206. {
  207. //获取PlaySDK空闲端口号
  208. var jsPort = Module._malloc(1);
  209. var jsPortAry = new Uint8Array(Module.HEAPU8.buffer, jsPort, 1);
  210. Module._PLAY_GetFreePort(jsPortAry.byteOffset);
  211. m_nPlayPort = jsPortAry[0];
  212. jsPortAry = null;
  213. Module._free(jsPort);
  214. //设置播放窗口宽高属性
  215. Module._PLAY_ViewResolutionChanged(m_nPlayPort, m_nCanvasWidth, m_nCanvasHeight, 0);
  216. //设置实时流模式
  217. var nRet = Module._PLAY_SetStreamOpenMode(m_nPlayPort, m_bPlayback);
  218. nRet = Module._PLAY_OpenStream(m_nPlayPort, 0, 0, 10*1024*1024);
  219. nRet = Module._PLAY_SetSupportWebMSE(m_nPlayPort, m_bSupportH264MSE, m_bSupportH265MSE);
  220. nRet = Module._PLAY_Play(m_nPlayPort, 1);
  221. if (nRet)
  222. {
  223. //向C++层申请一块wasm内存,用于接收码流
  224. jsInputData = Module._malloc(5*1024*1024);
  225. jsInputDataAry = new Uint8Array(Module.HEAPU8.buffer, jsInputData, 5*1024*1024);
  226. var msgType = 'InitSuccess';
  227. sendMessage(m_nPlayPort, msgType, null);
  228. }
  229. }
  230. function InputData(data)
  231. {
  232. m_nTotalStreamLength += data.length;
  233. if(jsInputDataAry)
  234. {
  235. jsInputDataAry.set(data);
  236. var nRet = Module._PLAY_InputData(m_nPlayPort, jsInputDataAry.byteOffset, data.length);
  237. var i = 0;
  238. }
  239. }
  240. function OpenIVSDraw()
  241. {
  242. Module._PLAY_RenderPrivateData(m_nPlayPort, 1, 0);
  243. }
  244. function CloseIVSDraw()
  245. {
  246. Module._PLAY_RenderPrivateData(m_nPlayPort, 0, 0);
  247. }
  248. function StartRecord(nRecordType)
  249. {
  250. Module._PLAY_StartDataRecord(m_nPlayPort, 0, nRecordType);
  251. }
  252. function StopRecord()
  253. {
  254. Module._PLAY_StopDataRecord(m_nPlayPort);
  255. }
  256. function SetPlaySpeed(nSpeed)
  257. {
  258. Module._PLAY_SetPlaySpeed(m_nPlayPort, nSpeed);
  259. }
  260. function GetOriginalKey(playToken, playTokenKey, deviceID)
  261. {
  262. var arrPlayToken = Module.intArrayFromString(playToken).concat(0);//add '\0'
  263. var playTokenPtr = Module._malloc(arrPlayToken.length);//采用声明的c函数 _malloc
  264. Module.HEAPU8.set(arrPlayToken, playTokenPtr);//复制字符串内容
  265. var arrPlayTokenKey = Module.intArrayFromString(playTokenKey).concat(0);
  266. var playTokenKeyPtr = Module._malloc(arrPlayTokenKey.length);
  267. Module.HEAPU8.set(arrPlayTokenKey, playTokenKeyPtr);
  268. var arrDeviceID = Module.intArrayFromString(deviceID).concat(0);
  269. var deviceIDPtr = Module._malloc(arrDeviceID.length);
  270. Module.HEAPU8.set(arrDeviceID, deviceIDPtr);
  271. var outKeyPtr = Module._malloc(256);
  272. var outKeyLengthPtr = Module._malloc(4);
  273. var nRet = Module._PLAY_GetOriginalKey(m_nPlayPort, playTokenPtr, playTokenKeyPtr, deviceIDPtr, outKeyPtr, outKeyLengthPtr);
  274. var outKeyLength = Module.HEAP32[outKeyLengthPtr >>2];
  275. var outKeyTmp = "";
  276. if ((1 == nRet) && (outKeyLength <= 256))
  277. {
  278. var jsKeyBuf = new ArrayBuffer(outKeyLength);
  279. var jsKeyData = new Uint8Array(jsKeyBuf);
  280. jsKeyData.set(Module.HEAPU8.subarray(outKeyPtr, outKeyPtr + outKeyLength));
  281. outKeyTmp = ArrayBufferToString(jsKeyBuf);
  282. }
  283. Module._free(playTokenPtr);//释放内存
  284. Module._free(playTokenKeyPtr);
  285. Module._free(deviceIDPtr);
  286. Module._free(outKeyPtr);
  287. Module._free(outKeyLengthPtr);
  288. var outKeyParam =
  289. {
  290. nRet: nRet,
  291. outKey: outKeyTmp,
  292. };
  293. var msgType = 'GetOriginalKeyCallBack';
  294. var msgData =
  295. {
  296. nRet: nRet,
  297. outKey: outKeyTmp,
  298. }
  299. sendMessage(m_nPlayPort, msgType, msgData);
  300. }
  301. function SetWebSecurityKey(nDecryptType, nFrameType, strKey, stStreamInfo)
  302. {
  303. var arrStrKey = Module.intArrayFromString(strKey).concat(0);
  304. var strKeyPtr = Module._malloc(arrStrKey.length);
  305. Module.HEAPU8.set(arrStrKey, strKeyPtr);
  306. var arrSdpInfo = Module.intArrayFromString(stStreamInfo.sdpInfo).concat(0);
  307. var sdpInfoPtr = Module._malloc(arrSdpInfo.length);
  308. Module.HEAPU8.set(arrSdpInfo, sdpInfoPtr);
  309. var arrUserName = Module.intArrayFromString(stStreamInfo.strUserName).concat(0);
  310. var userNamePtr = Module._malloc(arrUserName.length);
  311. Module.HEAPU8.set(arrUserName, userNamePtr);
  312. var arrPassWord = Module.intArrayFromString(stStreamInfo.strPassWord).concat(0);
  313. var passWordPtr = Module._malloc(arrPassWord.length);
  314. Module.HEAPU8.set(arrPassWord, passWordPtr);
  315. const stStreamInfoPtr = Module._malloc(16);//4:uint32的字节大小
  316. Module.HEAP32[stStreamInfoPtr/4 + 0] = sdpInfoPtr;
  317. Module.HEAP32[stStreamInfoPtr/4 + 1] = userNamePtr;
  318. Module.HEAP32[stStreamInfoPtr/4 + 2] = passWordPtr;
  319. Module.HEAP32[stStreamInfoPtr/4 + 3] = stStreamInfo.nSsrc;
  320. Module._PLAY_SetWebSecurityKey(m_nPlayPort, nDecryptType, nFrameType, strKeyPtr, stStreamInfoPtr);
  321. Module._free(strKeyPtr);//释放内存
  322. Module._free(sdpInfoPtr);
  323. Module._free(userNamePtr);
  324. Module._free(passWordPtr);
  325. Module._free(stStreamInfoPtr);
  326. }
  327. function SetSecurityKey(nEncryptType, szKey, nKeyLen, szKeyId, nKeyIdLen)
  328. {
  329. var nRet = 1;
  330. var strKey = Module._malloc(49);
  331. var arrayKey = new Uint8Array(Module.HEAPU8.buffer);
  332. var nSequence = 0;
  333. if (ENCRYPT_AES == nEncryptType)
  334. {
  335. //逐字节的形式去内存中设置值,直接修改wasm内存数据
  336. szKey.forEach((value, nIndex) => {
  337. arrayKey[(strKey + nSequence) >> 0] = value;
  338. nSequence++;
  339. });
  340. }
  341. else if(ENCRYPT_AES256 == nEncryptType)
  342. {
  343. var szKeyIdTmp = new Uint8Array(16); ;
  344. //协议规定ENCRYPT_AES256对应的枚举值为1
  345. arrayKey[(strKey + nSequence) >> 0] = 1;
  346. nSequence++;
  347. if (0 == nKeyIdLen)
  348. {
  349. for(var i = 0; i < 16; i++)
  350. {
  351. szKeyIdTmp[i] = 0x00;
  352. }
  353. nKeyIdLen = 16;
  354. szKeyId = szKeyIdTmp;
  355. }
  356. //拼接上key ID,逐字节的形式去内存中设置值,直接修改wasm内存数据
  357. szKeyId.forEach((value, nIndex) => {
  358. arrayKey[(strKey + nSequence) >> 0] = value;
  359. nSequence++;
  360. });
  361. //拼接上key,逐字节的形式去内存中设置值,直接修改wasm内存数据
  362. szKey.forEach((value, nIndex) => {
  363. arrayKey[strKey + nSequence] = value;
  364. nSequence++;
  365. });
  366. nKeyLen = 1 + nKeyLen + nKeyIdLen;
  367. szKeyIdTmp = null;
  368. }
  369. else if(ENCRYPT_AES_STRING_FORMAT == nEncryptType)
  370. {
  371. szKey.split('').forEach((char, nIndex) => {
  372. arrayKey[(strKey + nSequence) >> 0] = char.charCodeAt(0);
  373. nSequence++;
  374. });
  375. }
  376. nRet = Module._PLAY_SetSecurityKey(m_nPlayPort, strKey, nKeyLen);
  377. Module._free(strKey);
  378. return nRet;
  379. }
  380. function SetSupportWebMSE(bSupportH264MSE, bSupportH265MSE)
  381. {
  382. Module._PLAY_SetSupportWebMSE(m_nPlayPort, bSupportH264MSE, bSupportH265MSE);
  383. }
  384. function Pause(bPause)
  385. {
  386. Module._PLAY_Pause(m_nPlayPort, bPause);
  387. }
  388. function CatchPic()
  389. {
  390. var nSize = m_nWidth * m_nHeight * 3/2;
  391. var pJpegBuf = Module._malloc(nSize);
  392. var pJpegBufArr = new Uint8Array(Module.HEAPU8.buffer, pJpegBuf, nSize);
  393. var pJpegSize = Module._malloc(4);
  394. var pJpegSizeArr = new Uint8Array(Module.HEAPU8.buffer, pJpegSize, 4);
  395. //获取当前图像编码后的jpeg图片数据
  396. Module._PLAY_GetPicJPEG(m_nPlayPort, pJpegBufArr.byteOffset, nSize, pJpegSizeArr.byteOffset, 100);
  397. //C++内存数据拷贝至JS内存
  398. var nDataSize = (pJpegSizeArr[3] << 24) + (pJpegSizeArr[2] << 16) + (pJpegSizeArr[1] << 8) + pJpegSizeArr[0];
  399. var pOutJpegBuf = new ArrayBuffer(nDataSize);
  400. var pOutJpegBufArr = new Uint8Array(pOutJpegBuf);
  401. pOutJpegBufArr.set(Module.HEAPU8.subarray(pJpegBufArr.byteOffset, pJpegBufArr.byteOffset + nDataSize));
  402. var msgType = 'CatchPicCallBack';
  403. var msgData =
  404. {
  405. buffer: pOutJpegBufArr
  406. }
  407. sendMessage(m_nPlayPort, msgType, msgData);
  408. Module._free(pJpegBuf);
  409. Module._free(pJpegSize);
  410. pJpegBufArr = null;
  411. pJpegSizeArr = null;
  412. pOutJpegBuf= null;
  413. pOutJpegBufArr = null;
  414. }
  415. function Stop()
  416. {
  417. var nRet = Module._PLAY_Stop(m_nPlayPort);
  418. if (0 == nRet)
  419. {
  420. return;
  421. }
  422. nRet = Module._PLAY_CloseStream(m_nPlayPort);
  423. jsInputDataAry = null;
  424. Module._free(jsInputData);
  425. jsFrameBuf = null;
  426. jsFrameInfo = null;
  427. dataView = null;
  428. jsBufY = null;
  429. jsBufU = null;
  430. jsBufV = null;
  431. jsYuvDataY = null;
  432. jsYuvDataU = null;
  433. jsYuvDataV = null;
  434. jsRecordFrameBuf = null;
  435. jsRecordFrameInfo = null;
  436. dataViewRecord = null;
  437. m_nTotalStreamLength = 0;
  438. }
  439. function SetPrintLogLevel(nLogLevel)
  440. {
  441. Module._PLAY_SetPrintLogLevel(nLogLevel);
  442. }
  443. function cPlusVisibleDecCallBack(nPort, pBufY, pBufU, pBufV, nSize, pFrameInfo)
  444. {
  445. var stuFrameInfo = {};
  446. stuFrameInfo.nTotalStreamLength = m_nTotalStreamLength;
  447. if(!jsFrameInfo)
  448. {
  449. jsFrameBuf = new ArrayBuffer(292);//通过二进制对象分配一块连续内存
  450. jsFrameInfo = new Uint8Array(jsFrameBuf);//二进制对象绑定到视图,通过视图对内存进行读写操作
  451. dataView = new DataView(jsFrameBuf);
  452. }
  453. jsFrameInfo.set(Module.HEAPU8.subarray(pFrameInfo, pFrameInfo + 292));//c中的内存拷贝到刚分配的js内存中
  454. //帧类型
  455. stuFrameInfo.nFrameType = dataView.getInt32(0, true);
  456. //帧序号
  457. stuFrameInfo.nFrameID = dataView.getInt32(4, true);
  458. //帧子类型
  459. stuFrameInfo.nFrameSubType = dataView.getInt32(56, true);
  460. //帧时间
  461. stuFrameInfo.nYear = dataView.getUint16(40, true);
  462. stuFrameInfo.nMonth = dataView.getUint16(42, true);
  463. stuFrameInfo.nDay = dataView.getUint16(46, true);
  464. stuFrameInfo.nHour = dataView.getUint16(48, true);
  465. stuFrameInfo.nMinute = dataView.getUint16(50, true);
  466. stuFrameInfo.nSecond = dataView.getUint16(52, true);
  467. var msgData = {};
  468. //视频
  469. if (1 == stuFrameInfo.nFrameType)
  470. {
  471. //剩余缓冲数据量
  472. stuFrameInfo.nRemainData = dataView.getInt32(36, true);
  473. //抽帧标记
  474. stuFrameInfo.bThrowFrame = dataView.getUint8(120, true);
  475. if (0 == stuFrameInfo.bThrowFrame)
  476. {
  477. //编码类型
  478. stuFrameInfo.nEncodeType = dataView.getInt32(108, true);
  479. //码流类型
  480. stuFrameInfo.nStreamType = dataView.getInt32(112, true);
  481. //时间戳
  482. stuFrameInfo.nTimeStamp = dataView.getUint32(8, true);
  483. //图像宽度
  484. stuFrameInfo.nWidth = dataView.getInt32(12, true);
  485. m_nWidth = stuFrameInfo.nWidth;
  486. //图像高度
  487. stuFrameInfo.nHeight = dataView.getInt32(16, true);
  488. m_nHeight = stuFrameInfo.nHeight;
  489. //视频帧率
  490. stuFrameInfo.nFrameRate = dataView.getInt32(20, true);
  491. //图像跨距
  492. stuFrameInfo.nStride = dataView.getInt32(116, true);
  493. if ((ENCODE_TYPE_VIDEO_HI_H264 == stuFrameInfo.nEncodeType) || (ENCODE_TYPE_VIDEO_MY_H264 == stuFrameInfo.nEncodeType) || (ENCODE_TYPE_VIDEO_STD_H264 == stuFrameInfo.nEncodeType))
  494. {
  495. //H.264编码类型
  496. m_nVideoEncodeType = 1;
  497. }
  498. else if(12 == stuFrameInfo.nEncodeType)
  499. {
  500. //H.265编码类型
  501. m_nVideoEncodeType = 2;
  502. }
  503. //智能I/P帧
  504. if ((VIDEO_FRAME_SUB_TYPE_SMART_I == stuFrameInfo.nFrameSubType)
  505. || (VIDEO_FRAME_SUB_TYPE_SMART_P == stuFrameInfo.nFrameSubType)
  506. || (VIDEO_FRAME_SUB_TYPE_SMART_I_NORENDER == stuFrameInfo.nFrameSubType))
  507. {
  508. //Smart H.264或者Smart H.265
  509. m_bSmartEncode = 1;
  510. }
  511. else if(0 == stuFrameInfo.nFrameSubType)
  512. {
  513. m_bSmartEncode = 0;
  514. }
  515. //非Smart H.264/H.265码流,若浏览器支持MSE硬解码则采用硬解码
  516. //SVC码流不支持硬解码
  517. if ((((1 == m_nVideoEncodeType) && (true == m_bSupportH264MSE))
  518. || ((2 == m_nVideoEncodeType) && (true == m_bSupportH265MSE)))
  519. && !m_bSmartEncode
  520. && (STREAM_TYPE_SVC != stuFrameInfo.nStreamType))
  521. {
  522. //读取码流裸数据
  523. jsBuf = new ArrayBuffer(nSize);//通过二进制对象分配一块连续内存
  524. jsFrameBodyData = new Uint8Array(jsBuf);//二进制对象绑定到视图,通过视图对内存进行读写操作
  525. jsFrameBodyData.set(Module.HEAPU8.subarray(pBufY, pBufY + nSize));//c中的内存拷贝到刚分配的js内存中
  526. msgData =
  527. {
  528. pBufY: jsFrameBodyData,
  529. pBufU: null,
  530. pBufV: null,
  531. nSize: nSize,
  532. stuFrameInfo: stuFrameInfo,
  533. }
  534. }
  535. else
  536. {
  537. if((0 == pBufY) || (0 == pBufU) || (0 == pBufV))
  538. {
  539. return;
  540. }
  541. if (m_nWidth != m_nPreWidth || m_nHeight != m_nPreHeight)
  542. {
  543. m_nPreWidth = m_nWidth;
  544. m_nPreHeight = m_nHeight;
  545. jsBufY = null;
  546. jsBufU = null;
  547. jsBufV = null;
  548. jsYuvDataY = null;
  549. jsYuvDataU = null;
  550. jsYuvDataV = null;
  551. jsBufY = new ArrayBuffer(m_nWidth * m_nHeight);//通过二进制对象分配一块连续内存
  552. jsYuvDataY = new Uint8Array(jsBufY);//二进制对象绑定到视图,通过视图对内存进行读写操作
  553. jsBufU = new ArrayBuffer(m_nWidth * m_nHeight / 4);
  554. jsYuvDataU = new Uint8Array(jsBufU);
  555. jsBufV = new ArrayBuffer(m_nWidth * m_nHeight / 4);
  556. jsYuvDataV = new Uint8Array(jsBufV);
  557. }
  558. var h = 0;
  559. //将C++层YUV解码数据Y分量数据拷贝至JS层内存中
  560. for(h = 0; h < stuFrameInfo.nHeight; h++)
  561. {
  562. jsYuvDataY.set(Module.HEAPU8.subarray((pBufY + h * stuFrameInfo.nStride), (pBufY + h * stuFrameInfo.nStride) + stuFrameInfo.nWidth), h * stuFrameInfo.nWidth);//c中的内存拷贝到刚分配的js内存中
  563. }
  564. //将C++层YUV解码数据U分量数据拷贝至JS层内存中
  565. for(h = 0; h < stuFrameInfo.nHeight / 2; h++)
  566. {
  567. jsYuvDataU.set(Module.HEAPU8.subarray((pBufU + h * stuFrameInfo.nStride/2), (pBufU + h * stuFrameInfo.nStride/2) + stuFrameInfo.nWidth/2), h * stuFrameInfo.nWidth/2);//c中的内存拷贝到刚分配的js内存中
  568. }
  569. //将C++层YUV解码数据V分量数据拷贝至JS层内存中
  570. for(h = 0; h < stuFrameInfo.nHeight / 2; h++)
  571. {
  572. jsYuvDataV.set(Module.HEAPU8.subarray((pBufV + h * stuFrameInfo.nStride/2), (pBufV + h * stuFrameInfo.nStride/2) + stuFrameInfo.nWidth/2), h * stuFrameInfo.nWidth/2);//c中的内存拷贝到刚分配的js内存中
  573. }
  574. msgData =
  575. {
  576. pBufY: jsYuvDataY,
  577. pBufU: jsYuvDataU,
  578. pBufV: jsYuvDataV,
  579. nSize: nSize,
  580. stuFrameInfo: stuFrameInfo,
  581. }
  582. }
  583. }
  584. else
  585. {
  586. msgData =
  587. {
  588. pBufY: null,
  589. pBufU: null,
  590. pBufV: null,
  591. nSize: 0,
  592. stuFrameInfo: stuFrameInfo,
  593. }
  594. }
  595. }
  596. else if(2 == stuFrameInfo.nFrameType)//音频帧
  597. {
  598. //总通道数
  599. stuFrameInfo.nTotalChannel = dataView.getInt32(68, true);
  600. //当前通道
  601. stuFrameInfo.nCurChannel = dataView.getInt32(72, true);
  602. //暂不支持双通道音频播放
  603. if (stuFrameInfo.nCurChannel > 0)
  604. {
  605. return;
  606. }
  607. //采样位数
  608. stuFrameInfo.nBits = dataView.getInt32(28, true);
  609. //采样率
  610. stuFrameInfo.nSamples = dataView.getInt32(32, true);
  611. //声道数
  612. stuFrameInfo.nAudioChnNum = dataView.getInt32(24, true);
  613. var AudioBuf = new ArrayBuffer(nSize);
  614. var UI8AudioData = new Uint8Array(AudioBuf);
  615. //将C++层解码后的pcm音频数据拷贝至JS层内存
  616. UI8AudioData.set(Module.HEAPU8.subarray(pBufY, pBufY + nSize));
  617. msgData =
  618. {
  619. pBufY: UI8AudioData,
  620. pBufU: null,
  621. pBufV: null,
  622. nSize: nSize,
  623. stuFrameInfo: stuFrameInfo,
  624. }
  625. }
  626. var msgType = 'VisibleDecCallBack';
  627. sendMessage(nPort, msgType, msgData);
  628. jsBuf = null;
  629. jsFrameBodyData = null;
  630. }
  631. /*
  632. * C++层AES解密回调。
  633. *
  634. * @param[in] nPort 端口号
  635. * @param[in] nFrameID 视频帧序号
  636. * @param[in] bSuccess 是否解密成功
  637. */
  638. function cDigitalSignCallBack(nPort, nFrameID, bSuccess)
  639. {
  640. m_bDecryptionResult = bSuccess;
  641. var msgType = 'DecryptionResultCallBack';
  642. var msgData =
  643. {
  644. bSuccess: bSuccess
  645. }
  646. sendMessage(nPort, msgType, msgData);
  647. }
  648. /*
  649. * C++层码流录制回调,回调至JS层进行数据存储
  650. *
  651. * @param[in] nPort 端口号
  652. * @param[in] pData 码流数据
  653. * @param[in] nDataLen 数据长度
  654. * @param[in] nOffset 偏移量
  655. * @param[in] pFrameInfo 码流信息
  656. */
  657. function cRecordDataCallBack(nPort, pData, nDataLen, nOffset, pFrameInfo)
  658. {
  659. var stuFrameInfo = {};
  660. if (!jsRecordFrameInfo)
  661. {
  662. jsRecordFrameBuf = new ArrayBuffer(292); //通过二进制对象分配一块连续内存
  663. jsRecordFrameInfo = new Uint8Array(jsRecordFrameBuf); //二进制对象绑定到视图,通过视图对内存进行读写操作
  664. dataViewRecord = new DataView(jsRecordFrameBuf);
  665. }
  666. jsRecordFrameInfo.set(Module.HEAPU8.subarray(pFrameInfo, pFrameInfo + 292)); //c中的内存拷贝到刚分配的js内存中
  667. //帧类型
  668. stuFrameInfo.nFrameType = dataViewRecord.getInt32(0, true);
  669. //帧序号
  670. stuFrameInfo.nFrameID = dataViewRecord.getInt32(4, true);
  671. //帧子类型
  672. stuFrameInfo.nFrameSubType = dataViewRecord.getInt32(56, true);
  673. //视频帧
  674. if (1 == stuFrameInfo.nFrameType)
  675. {
  676. //编码类型
  677. stuFrameInfo.nEncodeType = dataViewRecord.getInt32(68, true);
  678. //码流类型
  679. stuFrameInfo.nStreamType = dataViewRecord.getInt32(72, true);
  680. //时间戳
  681. stuFrameInfo.nTimeStamp = dataViewRecord.getUint32(8, true);
  682. //帧时间
  683. stuFrameInfo.nYear = dataViewRecord.getUint16(40, true);
  684. stuFrameInfo.nMonth = dataViewRecord.getUint16(42, true);
  685. stuFrameInfo.nDay = dataViewRecord.getUint16(46, true);
  686. stuFrameInfo.nHour = dataViewRecord.getUint16(48, true);
  687. stuFrameInfo.nMinute = dataViewRecord.getUint16(50, true);
  688. stuFrameInfo.nSecond = dataViewRecord.getUint16(52, true);
  689. }
  690. var bufRecord = new ArrayBuffer(nDataLen);
  691. var arrayRecord = new Uint8Array(bufRecord);
  692. arrayRecord.set(Module.HEAPU8.subarray(pData, pData + nDataLen));
  693. var msgType = 'RecordDataCallBack';
  694. var msgData =
  695. {
  696. pRecordData: arrayRecord,
  697. nLen: nDataLen,
  698. Offset: nOffset,
  699. stuFrameInfo: stuFrameInfo,
  700. }
  701. sendMessage(nPort, msgType, msgData);
  702. bufRecord = null;
  703. arrayRecord = null;
  704. }
  705. function cIVSDrawDataCallBack(nPort, pBuf, nType, nLen, nReallen)
  706. {
  707. //帧序号为-1时不绘制
  708. if(-1 == nReallen)
  709. {
  710. return;
  711. }
  712. var pParseredBuf = null;
  713. ivsBuf = new ArrayBuffer(nLen);//通过二进制对象分配一块连续内存
  714. ivsDataArray = new Uint8Array(ivsBuf);//二进制对象绑定到视图,通过视图对内存进行读写操作
  715. ivsDataArray.set(Module.HEAPU8.subarray(pBuf, pBuf + nLen));
  716. ivsDataView = new DataView(ivsDataArray.buffer);
  717. //DHOP开放平台智能帧
  718. if (IVS_TYPE.IVSINFOTYPE_DHOP_SMART == nType)
  719. {
  720. var stuObjDHOP = {};
  721. stuObjDHOP.nId = ivsDataView.getUint32(0, true);//对象ID
  722. stuObjDHOP.wCustom = ivsDataView.getUint16(4, true);//自定义值
  723. stuObjDHOP.chState = ivsDataView.getUint8(6, true);//对象状态
  724. stuObjDHOP.chCount = ivsDataView.getUint8(7, true);//元素个数
  725. //解析DHOP元素
  726. var pElement = ivsDataView.getUint32(8, true);
  727. let elementBuf = new ArrayBuffer(12);
  728. let elementDataArray = new Uint8Array(elementBuf);
  729. let elementDataView = new DataView(elementBuf);
  730. stuObjDHOP.pElement = new Array(stuObjDHOP.chCount);
  731. for (var i = 0; i < stuObjDHOP.chCount; i++)
  732. {
  733. elementDataArray.set(Module.HEAPU8.subarray(pElement + i * 12, pElement + i * 12 + 12));
  734. //解析DHOP元素类型
  735. stuObjDHOP.pElement[i] = {};
  736. stuObjDHOP.pElement[i].nStructType = elementDataView.getUint32(0, true);
  737. stuObjDHOP.pElement[i].nStructLength = elementDataView.getUint32(4, true);
  738. var pStruct = elementDataView.getUint32(8, true);
  739. let structBuf = new ArrayBuffer(stuObjDHOP.pElement[i].nStructLength);
  740. let structArray = new Uint8Array(structBuf);
  741. let structDataView = new DataView(structBuf);
  742. structArray.set(Module.HEAPU8.subarray(pStruct, pStruct + stuObjDHOP.pElement[i].nStructLength));
  743. stuObjDHOP.pElement[i].pStruct = {};
  744. if (IVS_DHOP_ElEMENT_TYPE.EM_DHOP_CIRCLE == stuObjDHOP.pElement[i].nStructType)
  745. {
  746. stuObjDHOP.pElement[i].pStruct.chType = structDataView.getUint8(0, true);//子类型0x3
  747. stuObjDHOP.pElement[i].pStruct.chWidth = structDataView.getUint8(1, true);//线宽,单位px
  748. stuObjDHOP.pElement[i].pStruct.chStyle = structDataView.getUint8(2, true);//样式
  749. stuObjDHOP.pElement[i].pStruct.wRadius = structDataView.getUint16(4, true);//半径
  750. stuObjDHOP.pElement[i].pStruct.positionCircle = {};//圆心坐标
  751. stuObjDHOP.pElement[i].pStruct.positionCircle.x = structDataView.getUint16(8, true);
  752. stuObjDHOP.pElement[i].pStruct.positionCircle.y = structDataView.getUint16(10, true);
  753. stuObjDHOP.pElement[i].pStruct.chLineA = structDataView.getUint8(12, true);//边框线条颜色(ARGB)
  754. stuObjDHOP.pElement[i].pStruct.chLineR = structDataView.getUint8(13, true);
  755. stuObjDHOP.pElement[i].pStruct.chLineG = structDataView.getUint8(14, true);
  756. stuObjDHOP.pElement[i].pStruct.chLineB = structDataView.getUint8(15, true);
  757. stuObjDHOP.pElement[i].pStruct.chRegA = structDataView.getUint8(16, true);//区域填充颜色(ARGB)
  758. stuObjDHOP.pElement[i].pStruct.chRegR = structDataView.getUint8(17, true);
  759. stuObjDHOP.pElement[i].pStruct.chRegG = structDataView.getUint8(18, true);
  760. stuObjDHOP.pElement[i].pStruct.chRegB = structDataView.getUint8(19, true);
  761. }
  762. else if(IVS_DHOP_ElEMENT_TYPE.EM_DHOP_BrokenLine == stuObjDHOP.pElement[i].nStructType)
  763. {
  764. stuObjDHOP.pElement[i].pStruct.chType = structDataView.getUint8(0, true);//子类型0x2
  765. stuObjDHOP.pElement[i].pStruct.chCount = structDataView.getUint8(1, true);//端点个数
  766. stuObjDHOP.pElement[i].pStruct.chWidth = structDataView.getUint8(2, true);//线宽,单位px
  767. stuObjDHOP.pElement[i].pStruct.chStyle = structDataView.getUint8(3, true);//样式
  768. stuObjDHOP.pElement[i].pStruct.chLineA = structDataView.getUint8(4, true);//边框线条颜色(ARGB)
  769. stuObjDHOP.pElement[i].pStruct.chLineR = structDataView.getUint8(5, true);
  770. stuObjDHOP.pElement[i].pStruct.chLineG = structDataView.getUint8(6, true);
  771. stuObjDHOP.pElement[i].pStruct.chLineB = structDataView.getUint8(7, true);
  772. //端点坐标
  773. var pPoints = null;
  774. let pointsBuf = null;
  775. let pointsDataArray = null;
  776. let pointsDataView = null;
  777. if (stuObjDHOP.pElement[i].pStruct.chCount > 0)
  778. {
  779. stuObjDHOP.pElement[i].pStruct.pPoints = new Array(stuObjDHOP.pElement[i].pStruct.chCount);
  780. pPoints = structDataView.getUint32(8, true);
  781. pointsBuf = new ArrayBuffer(4);
  782. pointsDataArray = new Uint8Array(pointsBuf);
  783. pointsDataView = new DataView(pointsBuf);
  784. }
  785. for(var j = 0; j < stuObjDHOP.pElement[i].pStruct.chCount; j++)
  786. {
  787. pointsDataArray.set(Module.HEAPU8.subarray(pPoints + j*4, pPoints + j*4 + 4));
  788. stuObjDHOP.pElement[i].pStruct.pPoints[j] = {};
  789. stuObjDHOP.pElement[i].pStruct.pPoints[j].x = pointsDataView.getUint16(0, true);
  790. stuObjDHOP.pElement[i].pStruct.pPoints[j].y = pointsDataView.getUint16(2, true);
  791. }
  792. }
  793. else if(IVS_DHOP_ElEMENT_TYPE.EM_DHOP_POLYGON == stuObjDHOP.pElement[i].nStructType)
  794. {
  795. stuObjDHOP.pElement[i].pStruct.chType = structDataView.getUint8(0, true);//子类型0x3
  796. stuObjDHOP.pElement[i].pStruct.chCount = structDataView.getUint8(1, true);//端点个数
  797. stuObjDHOP.pElement[i].pStruct.chWidth = structDataView.getUint8(2, true);//线宽,单位px
  798. stuObjDHOP.pElement[i].pStruct.chStyle = structDataView.getUint8(3, true);//样式
  799. stuObjDHOP.pElement[i].pStruct.chLineA = structDataView.getUint8(4, true);//边框线条颜色(ARGB)
  800. stuObjDHOP.pElement[i].pStruct.chLineR = structDataView.getUint8(5, true);
  801. stuObjDHOP.pElement[i].pStruct.chLineG = structDataView.getUint8(6, true);
  802. stuObjDHOP.pElement[i].pStruct.chLineB = structDataView.getUint8(7, true);
  803. stuObjDHOP.pElement[i].pStruct.chRegA = structDataView.getUint8(8, true);//区域填充颜色(ARGB)
  804. stuObjDHOP.pElement[i].pStruct.chRegR = structDataView.getUint8(9, true);
  805. stuObjDHOP.pElement[i].pStruct.chRegG = structDataView.getUint8(10, true);
  806. stuObjDHOP.pElement[i].pStruct.chRegB = structDataView.getUint8(11, true);
  807. //端点坐标
  808. var pPoints = null;
  809. let pointsBuf = null;
  810. let pointsDataArray = null;
  811. let pointsDataView = null;
  812. if (stuObjDHOP.pElement[i].pStruct.chCount > 0)
  813. {
  814. stuObjDHOP.pElement[i].pStruct.pPoints = new Array(stuObjDHOP.pElement[i].pStruct.chCount);
  815. pPoints = structDataView.getUint32(12, true);
  816. pointsBuf = new ArrayBuffer(4);
  817. pointsDataArray = new Uint8Array(pointsBuf);
  818. pointsDataView = new DataView(pointsBuf);
  819. }
  820. for(var j = 0; j < stuObjDHOP.pElement[i].pStruct.chCount; j++)
  821. {
  822. pointsDataArray.set(Module.HEAPU8.subarray(pPoints + j*4, pPoints + j*4 + 4));
  823. stuObjDHOP.pElement[i].pStruct.pPoints[j] = {};
  824. stuObjDHOP.pElement[i].pStruct.pPoints[j].x = pointsDataView.getUint16(0, true);
  825. stuObjDHOP.pElement[i].pStruct.pPoints[j].y = pointsDataView.getUint16(2, true);
  826. }
  827. }
  828. else if(IVS_DHOP_ElEMENT_TYPE.EM_DHOP_TEXT == stuObjDHOP.pElement[i].nStructType)
  829. {
  830. stuObjDHOP.pElement[i].pStruct.chType = structDataView.getUint8(0, true);//子类型0x4
  831. stuObjDHOP.pElement[i].pStruct.chCharset = structDataView.getUint8(1, true);//编码方式
  832. stuObjDHOP.pElement[i].pStruct.stringPos = {};//字符坐标
  833. stuObjDHOP.pElement[i].pStruct.stringPos.x = structDataView.getUint16(4, true);
  834. stuObjDHOP.pElement[i].pStruct.stringPos.y = structDataView.getUint16(6, true);
  835. stuObjDHOP.pElement[i].pStruct.chLineA = structDataView.getUint8(8, true);//字体颜色(ARGB)
  836. stuObjDHOP.pElement[i].pStruct.chLineR = structDataView.getUint8(9, true);
  837. stuObjDHOP.pElement[i].pStruct.chLineG = structDataView.getUint8(10, true);
  838. stuObjDHOP.pElement[i].pStruct.chLineB = structDataView.getUint8(11, true);
  839. stuObjDHOP.pElement[i].pStruct.chFontSize = structDataView.getUint8(12, true);//字体大小,单位px
  840. stuObjDHOP.pElement[i].pStruct.chFontAlign = structDataView.getUint8(13, true);//对齐方式
  841. stuObjDHOP.pElement[i].pStruct.wTxtLen = structDataView.getUint16(14, true);//字符长度
  842. var pString = structDataView.getUint32(16, true);
  843. var stringBuf = new ArrayBuffer(stuObjDHOP.pElement[i].pStruct.wTxtLen);
  844. var stringDataArray = new Uint8Array(stringBuf);
  845. var stringDataView = new DataView(stringBuf);
  846. stringDataArray.set(Module.HEAPU8.subarray(pString, pString + stuObjDHOP.pElement[i].pStruct.wTxtLen));
  847. stuObjDHOP.pElement[i].pStruct.stringDataArray = stringDataArray;
  848. }
  849. }
  850. //解析DHOP信息内容
  851. stuObjDHOP.nInfoLen = ivsDataView.getUint16(12, true);//信息长度
  852. if (stuObjDHOP.nInfoLen > 0)
  853. {
  854. var pInfo = ivsDataView.getUint32(16, true);
  855. let infoBuf = new ArrayBuffer(nInfoLen);
  856. let infoDataArray = new Uint8Array(infoBuf);
  857. infoDataArray.set(Module.HEAPU8.subarray(pInfo, pInfo + nInfoLen));
  858. stuObjDHOP.pInfo = infoDataArray;
  859. }
  860. pParseredBuf = stuObjDHOP;
  861. }
  862. else if (IVS_TYPE.IVSINFOTYPE_TAGGING_INFO == nType)//景物点信息标注帧
  863. {
  864. let dataView = new DataView(ivsBuf);
  865. let tagInfoNum = nLen/FRAME_SCENE_POINTS_INFOR_SIZE;
  866. let tagInfos = [];
  867. for (let tagInfoIndex = 0; tagInfoIndex < tagInfoNum; tagInfoIndex++)
  868. {
  869. var tagInfo = {};
  870. let Stride = FRAME_SCENE_POINTS_INFOR_SIZE * tagInfoIndex;
  871. //编号
  872. tagInfo.nIndex = dataView.getInt32(Stride + 0, true);
  873. //景物点x坐标
  874. tagInfo.xPoint = dataView.getUint16(Stride + 4, true);
  875. //景物点y坐标
  876. tagInfo.yPoint = dataView.getUint16(Stride + 6, true);
  877. //一级名称
  878. var jsNameBuf = new ArrayBuffer(64);
  879. jsNameBuf = ivsBuf.slice(Stride + 8);
  880. tagInfo.strName = ArrayBufferToStringAutoClip(jsNameBuf);
  881. //使能标记
  882. tagInfo.enable = dataView.getInt8(Stride + 72, true);
  883. //标签类型
  884. tagInfo.titleType = dataView.getInt8(Stride + 73, true);
  885. //标签属性
  886. tagInfo.titleAttribute = dataView.getInt8(Stride + 74, true);
  887. tagInfo.sharpType = dataView.getInt8(Stride + 75, true);
  888. tagInfo.polygonNum = dataView.getInt8(Stride + 76, true);
  889. tagInfo.polygon = [];
  890. //与上一个中间空了三字节
  891. for(let i = 0;i< tagInfo.polygonNum*2;i+=2)
  892. {
  893. tagInfo.polygon[i] ={x: dataView.getInt8(Stride + 79 + 2*i, true),
  894. y: dataView.getInt8(Stride + 79 + 2*(i+1), true)};
  895. }
  896. tagInfos[tagInfoIndex] = tagInfo;
  897. jsNameBuf = null;
  898. }
  899. var msgType = 'ARTagInfoCallback';
  900. var msgData =
  901. {
  902. tagInfo: tagInfos,
  903. }
  904. sendMessage(nPort, msgType, msgData);
  905. pParseredBuf = ivsDataArray;
  906. dataView = null;
  907. }
  908. else
  909. {
  910. pParseredBuf = ivsDataArray;
  911. }
  912. var msgType = 'IVSDataCallBack';
  913. var msgData =
  914. {
  915. pBuf: pParseredBuf,
  916. nType: nType,
  917. nLen: nLen,
  918. nReallen: nReallen,
  919. }
  920. sendMessage(nPort, msgType, msgData);
  921. }
  922. function sendMessage(nPort, msgType, msgData)
  923. {
  924. var event =
  925. {
  926. nPort: nPort,
  927. msgType: msgType,
  928. msgData: msgData,
  929. };
  930. postMessage(event);
  931. }
  932. function ArrayBufferToString(buffer, encoding = 'utf-8')
  933. {
  934. const decoder = new TextDecoder(encoding);
  935. return decoder.decode(buffer);
  936. }
  937. function ArrayBufferToStringAutoClip(buffer, encoding = 'utf-8')
  938. {
  939. const decoder = new TextDecoder(encoding);
  940. const uint8Array = new Uint8Array(buffer);
  941. let i = 0;
  942. while (i < uint8Array.length) {
  943. if (uint8Array[i] === 0) {
  944. break;
  945. }
  946. i++;
  947. }
  948. return decoder.decode(buffer.slice(0,i));
  949. }