| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094 |
- let SDKModule;
- const VIDEO_FRAME_SUB_TYPE_I = 0; //I帧
- const VIDEO_FRAME_SUB_TYPE_P = 1; //P帧
- const VIDEO_FRAME_SUB_TYPE_B = 2; //B帧
- const VIDEO_FRAME_SUB_TYPE_SMART_I = 18; //智能I帧
- const VIDEO_FRAME_SUB_TYPE_SMART_P = 19; //智能P帧
- const VIDEO_FRAME_SUB_TYPE_SMART_I_NORENDER = 20; //智能I帧,但不显示
- const ENCODE_TYPE_VIDEO_HI_H264 = 2; //海思H.264编码格式
- const ENCODE_TYPE_VIDEO_MY_H264 = 4; //公司H.264编码格式
- const ENCODE_TYPE_VIDEO_STD_H264 = 8; //标准H.264编码格式
- const ENCODE_TYPE_VIDEO_H265 = 12; //H.265编码格式
- const DATA_RECORD_MP4 = 5; //录制MP4格式
- const SP_STREAM_TYPE_DHSTD = 8; //dav编码格式
- const STREAM_TYPE_SVC = 13; //H.264 SVC编码格式
- const SP_STREAM_TYPE_FLV = 18; //flv编码格式
- const ENCRYPT_UNKOWN = 0; //未知加密类型
- const ENCRYPT_AES = 1; //AES加密类型,16进制数组格式
- const ENCRYPT_AES256 = 2; //AES256加密类型,16进制数组格式
- const ENCRYPT_AES_STRING_FORMAT = 3; //AES加密类型,字符串格式
- const CACHE_MODE_OFF = 0; //关闭实时流自适应缓冲模式
- const ADAPTIVE_CACHE = 1; //自适应缓冲
- const REALTIME_FIRST = 2; //实时优先
- const FLUENCY_FIRST = 3; //流畅优先
- const FRAME_SCENE_POINTS_INFOR_SIZE = 144; // 景物点信息单组信息长度
- /* IVS类型 */
- var IVS_TYPE =
- {
- IVSINFOTYPE_PRESETPOS : 1,
- IVSINFOTYPE_MOTINTRKS : 2,
- IVSINFOTYPE_MOTINTRKS_EX : 3,
- IVSINFOTYPE_LIGHT : 4, // 光照
- IVSINFOTYPE_RAWDATA : 5, // jason数据
- IVSINFOTYPE_TRACK : 6, // 智能分析信息
- IVSINFOTYPE_TRACK_EX_B0 : 7, // 智能结构化数据信息
- IVSINFOTYPE_MOTIONFRAME : 9,
- IVSINFOTYPE_VIDEO_CONCENTRATION : 10,
- IVSINFOTYPE_OVERLAY_PIC : 11, // 叠加图片帧
- IVSINFOTYPE_OSD_INFO : 12, // OSD辅助帧
- IVSINFOTYPE_GPS_INFO : 13, // GPS辅助帧
- IVSINFOTYPE_TAGGING_INFO : 14, // 景物点信息标注帧,辅助帧(0x13)
- IVSINFOTYPE_TRACK_A1 : 15, // NVR浓缩信息轨迹点
- IVSINFOTYPE_DATA_WITH_LARGE_AMOUNT : 16,
- IVSINFOTYPE_TRACK_A1_EX : 17, // NVR浓缩信息轨迹点(扩展)
- IVSINFOTYPE_DATA_WITH_WATER_LEVEL_MONITOR : 18, //水位检测水位尺信息帧(0x17)
- IVSINFOTYPE_INTELFLOW : 19, // 智能客流量
- IVSINFOTYPE_DATA_WITH_SOUND_DECIBEL : 20, //声音警报分贝值信息帧(0x18)
- IVSINFOTYPE_DATA_WITH_SMART_MOTION : 21, //智能动检信息帧(0x19)
- IVSINFOTYPE_DHOP_SMART : 22, //开放平台智能帧(0x14)
- IVSINFOTYPE_TRAFFIC_LIGHT : 23, //交通信号灯(红绿灯)辅助帧(0x1D)
- IVSINFOTYPE_PTZ_LOCATION : 24, //云台位置帧(0x21)
- };
- var DRAW_TYPE =
- {
- DRAW_JSON : 0,
- DRAW_TRACK : 1,
- DRAW_ALARM : 2,
- DRAW_RULE : 3,
- DRAW_MOVE_CHECK : 7,
- DRAW_TEST : 9,
- DRAW_WEB_RULE : 11,
- DRAW_WEB_ALARM : 12,
- DRAW_FLOW_INFO : 13,
- DRAW_TRACKEX2 : 14,
- DRAW_WUXI235_TRACKEX2 : 15,
- DRAW_TRACKEXA1 : 16,
- DRAW_TRACKEX2_TYPE_HUMAN : 17,
- DRAW_TRACKEX2_TYPE_VEHICLE : 18,
- DRAW_TRACKEX2_TYPE_NONMOTOR : 19,
- DRAW_TRACKEX2_TYPE_SHOPPRESENCE : 20,
- DRAW_TRACKEX2_TYPE_FLOWBUSINESS : 21,
- DRAW_INTELFLOW : 22,
- DRAW_SMARTMOTION : 23,
- DRAW_DHOPSMART : 24,
- DRAW_DATA_WITH_LARGE_AMOUNT : 25,//大数据量帧
- DRAW_TRACKEX2_TYPE_BAG : 26,
- DRAW_RULE_HIGHWAY_LANES : 27, //高速车道线
- DRAW_WATER_LEVEL_MONITOR : 28, //水位尺
- DRAW_END : 29
- };
- //DHOP元素类型
- var IVS_DHOP_ElEMENT_TYPE =
- {
- EM_DHOP_CIRCLE : 1,
- EM_DHOP_BrokenLine : 2,
- EM_DHOP_POLYGON : 3,
- EM_DHOP_TEXT : 4
- };
- importScripts('libplay.js');
- addEventListener('message', receiveMessage, false);
- Module.onRuntimeInitialized = function(){
- m_bLoadSuccess = true;
- var msgType = 'LoadSuccess';
- sendMessage(m_nPlayPort, msgType, null);
- }
- var m_bPlayback = 0;
- var m_bSupportH264MSE = false;
- var m_bSupportH265MSE = false;
- var m_nCanvasWidth = 1920;
- var m_nCanvasHeight = 1080;
- var m_nPlayPort = 0;
- var jsInputData = null;
- var jsInputDataAry = null;
- var jsFrameBuf = null;
- var jsFrameInfo = null;
- let dataView = null;
- var jsBuf = null;
- var jsFrameBodyData = null;
- var jsBufY = null;
- var jsBufU = null;
- var jsBufV = null;
- var jsYuvDataY = null;
- var jsYuvDataU = null;
- var jsYuvDataV = null;
- var jsRecordFrameBuf = null;
- var jsRecordFrameInfo = null;
- var dataViewRecord = null;
- let ivsBuf = null;
- let ivsDataArray = null;
- let ivsDataView = null;
- var m_nWidth = 0;
- var m_nHeight = 0;
- var m_nPreWidth = 0;
- var m_nPreHeight = 0;
- var m_bSmartEncode = 0;
- var m_nVideoEncodeType = 0;
- var m_bLoadSuccess = false;
- var m_bDecryptionResult = false;
- var m_nTotalStreamLength = 0;
- function receiveMessage(event)
- {
- if (!m_bLoadSuccess)
- {
- return;
- }
- var message = event.data;
- switch (message.nType)
- {
- //初始化
- case 'Init':
- m_bPlayback = message.option.bPlayback;
- m_bSupportH264MSE = message.option.bSupportH264MSE;
- m_bSupportH265MSE = message.option.bSupportH265MSE;
- m_nCanvasWidth = message.option.nCanvasWidth;
- m_nCanvasHeight = message.option.nCanvasHeight;
- Init();
- break;
- //送流
- case 'InputData':
- InputData(message.pData);
- break;
- //打开智能绘制
- case 'OpenIVSDraw':
- OpenIVSDraw();
- break;
- //关闭智能绘制
- case 'CloseIVSDraw':
- CloseIVSDraw();
- break;
- //开始码流录制
- case 'StartRecord':
- StartRecord(message.nRecordType);
- break;
- //停止码流录制
- case 'StopRecord':
- StopRecord();
- break;
- //设置播放速度
- case 'SetPlaySpeed':
- SetPlaySpeed(message.nSpeed);
- break;
- case 'GetOriginalKeyCallBack':
- GetOriginalKey(message.playToken, message.playTokenKey, message.deviceID);
- break;
- case 'SetWebSecurityKey':
- SetWebSecurityKey(message.nDecryptType, message.nFrameType, message.strKey, message.stStreamInfo);
- break;
- //设置解密秘钥
- case 'SetSecurityKey':
- SetSecurityKey(message.nEncryptType, message.szKey, message.nKeyLen, message.szKeyId, message.nKeyIdLen);
- break;
- //设置是否支持硬解码标记
- case 'SetSupportWebMSE':
- m_bSupportH264MSE = message.bSupportH264MSE;
- m_bSupportH265MSE = message.bSupportH265MSE;
- SetSupportWebMSE(m_bSupportH264MSE, m_bSupportH265MSE);
- //暂停播放
- case 'Pause':
- Pause(message.bPause);
- break;
- //抓图
- case 'CatchPic':
- CatchPic();
- break;
- //停止播放
- case 'Stop':
- Stop();
- break;
- case 'setPrintLogLevel':
- SetPrintLogLevel(message.nLogLevel);
- break;
- default:
- break;
- }
- }
- function Init()
- {
- //获取PlaySDK空闲端口号
- var jsPort = Module._malloc(1);
- var jsPortAry = new Uint8Array(Module.HEAPU8.buffer, jsPort, 1);
- Module._PLAY_GetFreePort(jsPortAry.byteOffset);
- m_nPlayPort = jsPortAry[0];
- jsPortAry = null;
- Module._free(jsPort);
-
- //设置播放窗口宽高属性
- Module._PLAY_ViewResolutionChanged(m_nPlayPort, m_nCanvasWidth, m_nCanvasHeight, 0);
-
- //设置实时流模式
- var nRet = Module._PLAY_SetStreamOpenMode(m_nPlayPort, m_bPlayback);
- nRet = Module._PLAY_OpenStream(m_nPlayPort, 0, 0, 10*1024*1024);
-
- nRet = Module._PLAY_SetSupportWebMSE(m_nPlayPort, m_bSupportH264MSE, m_bSupportH265MSE);
-
- nRet = Module._PLAY_Play(m_nPlayPort, 1);
- if (nRet)
- {
- //向C++层申请一块wasm内存,用于接收码流
- jsInputData = Module._malloc(5*1024*1024);
- jsInputDataAry = new Uint8Array(Module.HEAPU8.buffer, jsInputData, 5*1024*1024);
-
- var msgType = 'InitSuccess';
- sendMessage(m_nPlayPort, msgType, null);
- }
- }
- function InputData(data)
- {
- m_nTotalStreamLength += data.length;
-
- if(jsInputDataAry)
- {
- jsInputDataAry.set(data);
- var nRet = Module._PLAY_InputData(m_nPlayPort, jsInputDataAry.byteOffset, data.length);
- var i = 0;
- }
- }
- function OpenIVSDraw()
- {
- Module._PLAY_RenderPrivateData(m_nPlayPort, 1, 0);
- }
- function CloseIVSDraw()
- {
- Module._PLAY_RenderPrivateData(m_nPlayPort, 0, 0);
- }
- function StartRecord(nRecordType)
- {
- Module._PLAY_StartDataRecord(m_nPlayPort, 0, nRecordType);
- }
- function StopRecord()
- {
- Module._PLAY_StopDataRecord(m_nPlayPort);
- }
- function SetPlaySpeed(nSpeed)
- {
- Module._PLAY_SetPlaySpeed(m_nPlayPort, nSpeed);
- }
- function GetOriginalKey(playToken, playTokenKey, deviceID)
- {
- var arrPlayToken = Module.intArrayFromString(playToken).concat(0);//add '\0'
- var playTokenPtr = Module._malloc(arrPlayToken.length);//采用声明的c函数 _malloc
- Module.HEAPU8.set(arrPlayToken, playTokenPtr);//复制字符串内容
-
- var arrPlayTokenKey = Module.intArrayFromString(playTokenKey).concat(0);
- var playTokenKeyPtr = Module._malloc(arrPlayTokenKey.length);
- Module.HEAPU8.set(arrPlayTokenKey, playTokenKeyPtr);
-
- var arrDeviceID = Module.intArrayFromString(deviceID).concat(0);
- var deviceIDPtr = Module._malloc(arrDeviceID.length);
- Module.HEAPU8.set(arrDeviceID, deviceIDPtr);
- var outKeyPtr = Module._malloc(256);
- var outKeyLengthPtr = Module._malloc(4);
- var nRet = Module._PLAY_GetOriginalKey(m_nPlayPort, playTokenPtr, playTokenKeyPtr, deviceIDPtr, outKeyPtr, outKeyLengthPtr);
-
- var outKeyLength = Module.HEAP32[outKeyLengthPtr >>2];
- var outKeyTmp = "";
-
- if ((1 == nRet) && (outKeyLength <= 256))
- {
- var jsKeyBuf = new ArrayBuffer(outKeyLength);
- var jsKeyData = new Uint8Array(jsKeyBuf);
- jsKeyData.set(Module.HEAPU8.subarray(outKeyPtr, outKeyPtr + outKeyLength));
- outKeyTmp = ArrayBufferToString(jsKeyBuf);
- }
-
- Module._free(playTokenPtr);//释放内存
- Module._free(playTokenKeyPtr);
- Module._free(deviceIDPtr);
- Module._free(outKeyPtr);
- Module._free(outKeyLengthPtr);
-
- var outKeyParam =
- {
- nRet: nRet,
- outKey: outKeyTmp,
- };
-
- var msgType = 'GetOriginalKeyCallBack';
- var msgData =
- {
- nRet: nRet,
- outKey: outKeyTmp,
- }
-
- sendMessage(m_nPlayPort, msgType, msgData);
- }
- function SetWebSecurityKey(nDecryptType, nFrameType, strKey, stStreamInfo)
- {
- var arrStrKey = Module.intArrayFromString(strKey).concat(0);
- var strKeyPtr = Module._malloc(arrStrKey.length);
- Module.HEAPU8.set(arrStrKey, strKeyPtr);
-
- var arrSdpInfo = Module.intArrayFromString(stStreamInfo.sdpInfo).concat(0);
- var sdpInfoPtr = Module._malloc(arrSdpInfo.length);
- Module.HEAPU8.set(arrSdpInfo, sdpInfoPtr);
- var arrUserName = Module.intArrayFromString(stStreamInfo.strUserName).concat(0);
- var userNamePtr = Module._malloc(arrUserName.length);
- Module.HEAPU8.set(arrUserName, userNamePtr);
- var arrPassWord = Module.intArrayFromString(stStreamInfo.strPassWord).concat(0);
- var passWordPtr = Module._malloc(arrPassWord.length);
- Module.HEAPU8.set(arrPassWord, passWordPtr);
- const stStreamInfoPtr = Module._malloc(16);//4:uint32的字节大小
- Module.HEAP32[stStreamInfoPtr/4 + 0] = sdpInfoPtr;
- Module.HEAP32[stStreamInfoPtr/4 + 1] = userNamePtr;
- Module.HEAP32[stStreamInfoPtr/4 + 2] = passWordPtr;
- Module.HEAP32[stStreamInfoPtr/4 + 3] = stStreamInfo.nSsrc;
-
- Module._PLAY_SetWebSecurityKey(m_nPlayPort, nDecryptType, nFrameType, strKeyPtr, stStreamInfoPtr);
-
- Module._free(strKeyPtr);//释放内存
- Module._free(sdpInfoPtr);
- Module._free(userNamePtr);
- Module._free(passWordPtr);
- Module._free(stStreamInfoPtr);
- }
- function SetSecurityKey(nEncryptType, szKey, nKeyLen, szKeyId, nKeyIdLen)
- {
- var nRet = 1;
-
- var strKey = Module._malloc(49);
- var arrayKey = new Uint8Array(Module.HEAPU8.buffer);
- var nSequence = 0;
-
- if (ENCRYPT_AES == nEncryptType)
- {
- //逐字节的形式去内存中设置值,直接修改wasm内存数据
- szKey.forEach((value, nIndex) => {
- arrayKey[(strKey + nSequence) >> 0] = value;
- nSequence++;
- });
- }
- else if(ENCRYPT_AES256 == nEncryptType)
- {
- var szKeyIdTmp = new Uint8Array(16); ;
- //协议规定ENCRYPT_AES256对应的枚举值为1
- arrayKey[(strKey + nSequence) >> 0] = 1;
- nSequence++;
- if (0 == nKeyIdLen)
- {
- for(var i = 0; i < 16; i++)
- {
- szKeyIdTmp[i] = 0x00;
- }
- nKeyIdLen = 16;
- szKeyId = szKeyIdTmp;
- }
-
- //拼接上key ID,逐字节的形式去内存中设置值,直接修改wasm内存数据
- szKeyId.forEach((value, nIndex) => {
- arrayKey[(strKey + nSequence) >> 0] = value;
- nSequence++;
- });
-
- //拼接上key,逐字节的形式去内存中设置值,直接修改wasm内存数据
- szKey.forEach((value, nIndex) => {
- arrayKey[strKey + nSequence] = value;
- nSequence++;
- });
-
- nKeyLen = 1 + nKeyLen + nKeyIdLen;
- szKeyIdTmp = null;
- }
- else if(ENCRYPT_AES_STRING_FORMAT == nEncryptType)
- {
- szKey.split('').forEach((char, nIndex) => {
- arrayKey[(strKey + nSequence) >> 0] = char.charCodeAt(0);
- nSequence++;
- });
- }
- nRet = Module._PLAY_SetSecurityKey(m_nPlayPort, strKey, nKeyLen);
-
- Module._free(strKey);
-
- return nRet;
- }
- function SetSupportWebMSE(bSupportH264MSE, bSupportH265MSE)
- {
- Module._PLAY_SetSupportWebMSE(m_nPlayPort, bSupportH264MSE, bSupportH265MSE);
- }
- function Pause(bPause)
- {
- Module._PLAY_Pause(m_nPlayPort, bPause);
- }
- function CatchPic()
- {
- var nSize = m_nWidth * m_nHeight * 3/2;
- var pJpegBuf = Module._malloc(nSize);
- var pJpegBufArr = new Uint8Array(Module.HEAPU8.buffer, pJpegBuf, nSize);
-
- var pJpegSize = Module._malloc(4);
- var pJpegSizeArr = new Uint8Array(Module.HEAPU8.buffer, pJpegSize, 4);
-
- //获取当前图像编码后的jpeg图片数据
- Module._PLAY_GetPicJPEG(m_nPlayPort, pJpegBufArr.byteOffset, nSize, pJpegSizeArr.byteOffset, 100);
-
- //C++内存数据拷贝至JS内存
- var nDataSize = (pJpegSizeArr[3] << 24) + (pJpegSizeArr[2] << 16) + (pJpegSizeArr[1] << 8) + pJpegSizeArr[0];
- var pOutJpegBuf = new ArrayBuffer(nDataSize);
- var pOutJpegBufArr = new Uint8Array(pOutJpegBuf);
- pOutJpegBufArr.set(Module.HEAPU8.subarray(pJpegBufArr.byteOffset, pJpegBufArr.byteOffset + nDataSize));
-
- var msgType = 'CatchPicCallBack';
- var msgData =
- {
- buffer: pOutJpegBufArr
- }
- sendMessage(m_nPlayPort, msgType, msgData);
-
- Module._free(pJpegBuf);
- Module._free(pJpegSize);
- pJpegBufArr = null;
- pJpegSizeArr = null;
- pOutJpegBuf= null;
- pOutJpegBufArr = null;
-
- }
- function Stop()
- {
- var nRet = Module._PLAY_Stop(m_nPlayPort);
- if (0 == nRet)
- {
- return;
- }
- nRet = Module._PLAY_CloseStream(m_nPlayPort);
-
- jsInputDataAry = null;
- Module._free(jsInputData);
-
- jsFrameBuf = null;
- jsFrameInfo = null;
- dataView = null;
-
- jsBufY = null;
- jsBufU = null;
- jsBufV = null;
- jsYuvDataY = null;
- jsYuvDataU = null;
- jsYuvDataV = null;
-
- jsRecordFrameBuf = null;
- jsRecordFrameInfo = null;
- dataViewRecord = null;
-
- m_nTotalStreamLength = 0;
- }
- function SetPrintLogLevel(nLogLevel)
- {
- Module._PLAY_SetPrintLogLevel(nLogLevel);
- }
- function cPlusVisibleDecCallBack(nPort, pBufY, pBufU, pBufV, nSize, pFrameInfo)
- {
- var stuFrameInfo = {};
-
- stuFrameInfo.nTotalStreamLength = m_nTotalStreamLength;
-
- if(!jsFrameInfo)
- {
- jsFrameBuf = new ArrayBuffer(292);//通过二进制对象分配一块连续内存
- jsFrameInfo = new Uint8Array(jsFrameBuf);//二进制对象绑定到视图,通过视图对内存进行读写操作
- dataView = new DataView(jsFrameBuf);
- }
- jsFrameInfo.set(Module.HEAPU8.subarray(pFrameInfo, pFrameInfo + 292));//c中的内存拷贝到刚分配的js内存中
- //帧类型
- stuFrameInfo.nFrameType = dataView.getInt32(0, true);
- //帧序号
- stuFrameInfo.nFrameID = dataView.getInt32(4, true);
- //帧子类型
- stuFrameInfo.nFrameSubType = dataView.getInt32(56, true);
-
- //帧时间
- stuFrameInfo.nYear = dataView.getUint16(40, true);
- stuFrameInfo.nMonth = dataView.getUint16(42, true);
- stuFrameInfo.nDay = dataView.getUint16(46, true);
- stuFrameInfo.nHour = dataView.getUint16(48, true);
- stuFrameInfo.nMinute = dataView.getUint16(50, true);
- stuFrameInfo.nSecond = dataView.getUint16(52, true);
-
- var msgData = {};
- //视频
- if (1 == stuFrameInfo.nFrameType)
- {
- //剩余缓冲数据量
- stuFrameInfo.nRemainData = dataView.getInt32(36, true);
- //抽帧标记
- stuFrameInfo.bThrowFrame = dataView.getUint8(120, true);
- if (0 == stuFrameInfo.bThrowFrame)
- {
- //编码类型
- stuFrameInfo.nEncodeType = dataView.getInt32(108, true);
- //码流类型
- stuFrameInfo.nStreamType = dataView.getInt32(112, true);
- //时间戳
- stuFrameInfo.nTimeStamp = dataView.getUint32(8, true);
- //图像宽度
- stuFrameInfo.nWidth = dataView.getInt32(12, true);
- m_nWidth = stuFrameInfo.nWidth;
- //图像高度
- stuFrameInfo.nHeight = dataView.getInt32(16, true);
- m_nHeight = stuFrameInfo.nHeight;
- //视频帧率
- stuFrameInfo.nFrameRate = dataView.getInt32(20, true);
- //图像跨距
- stuFrameInfo.nStride = dataView.getInt32(116, true);
-
- if ((ENCODE_TYPE_VIDEO_HI_H264 == stuFrameInfo.nEncodeType) || (ENCODE_TYPE_VIDEO_MY_H264 == stuFrameInfo.nEncodeType) || (ENCODE_TYPE_VIDEO_STD_H264 == stuFrameInfo.nEncodeType))
- {
- //H.264编码类型
- m_nVideoEncodeType = 1;
- }
- else if(12 == stuFrameInfo.nEncodeType)
- {
- //H.265编码类型
- m_nVideoEncodeType = 2;
- }
-
- //智能I/P帧
- if ((VIDEO_FRAME_SUB_TYPE_SMART_I == stuFrameInfo.nFrameSubType)
- || (VIDEO_FRAME_SUB_TYPE_SMART_P == stuFrameInfo.nFrameSubType)
- || (VIDEO_FRAME_SUB_TYPE_SMART_I_NORENDER == stuFrameInfo.nFrameSubType))
- {
- //Smart H.264或者Smart H.265
- m_bSmartEncode = 1;
- }
- else if(0 == stuFrameInfo.nFrameSubType)
- {
- m_bSmartEncode = 0;
- }
-
- //非Smart H.264/H.265码流,若浏览器支持MSE硬解码则采用硬解码
- //SVC码流不支持硬解码
- if ((((1 == m_nVideoEncodeType) && (true == m_bSupportH264MSE))
- || ((2 == m_nVideoEncodeType) && (true == m_bSupportH265MSE)))
- && !m_bSmartEncode
- && (STREAM_TYPE_SVC != stuFrameInfo.nStreamType))
- {
- //读取码流裸数据
- jsBuf = new ArrayBuffer(nSize);//通过二进制对象分配一块连续内存
- jsFrameBodyData = new Uint8Array(jsBuf);//二进制对象绑定到视图,通过视图对内存进行读写操作
- jsFrameBodyData.set(Module.HEAPU8.subarray(pBufY, pBufY + nSize));//c中的内存拷贝到刚分配的js内存中
-
- msgData =
- {
- pBufY: jsFrameBodyData,
- pBufU: null,
- pBufV: null,
- nSize: nSize,
- stuFrameInfo: stuFrameInfo,
- }
- }
- else
- {
- if((0 == pBufY) || (0 == pBufU) || (0 == pBufV))
- {
- return;
- }
-
- if (m_nWidth != m_nPreWidth || m_nHeight != m_nPreHeight)
- {
- m_nPreWidth = m_nWidth;
- m_nPreHeight = m_nHeight;
-
- jsBufY = null;
- jsBufU = null;
- jsBufV = null;
- jsYuvDataY = null;
- jsYuvDataU = null;
- jsYuvDataV = null;
-
- jsBufY = new ArrayBuffer(m_nWidth * m_nHeight);//通过二进制对象分配一块连续内存
- jsYuvDataY = new Uint8Array(jsBufY);//二进制对象绑定到视图,通过视图对内存进行读写操作
-
- jsBufU = new ArrayBuffer(m_nWidth * m_nHeight / 4);
- jsYuvDataU = new Uint8Array(jsBufU);
-
- jsBufV = new ArrayBuffer(m_nWidth * m_nHeight / 4);
- jsYuvDataV = new Uint8Array(jsBufV);
- }
-
- var h = 0;
- //将C++层YUV解码数据Y分量数据拷贝至JS层内存中
- for(h = 0; h < stuFrameInfo.nHeight; h++)
- {
- jsYuvDataY.set(Module.HEAPU8.subarray((pBufY + h * stuFrameInfo.nStride), (pBufY + h * stuFrameInfo.nStride) + stuFrameInfo.nWidth), h * stuFrameInfo.nWidth);//c中的内存拷贝到刚分配的js内存中
- }
- //将C++层YUV解码数据U分量数据拷贝至JS层内存中
- for(h = 0; h < stuFrameInfo.nHeight / 2; h++)
- {
- jsYuvDataU.set(Module.HEAPU8.subarray((pBufU + h * stuFrameInfo.nStride/2), (pBufU + h * stuFrameInfo.nStride/2) + stuFrameInfo.nWidth/2), h * stuFrameInfo.nWidth/2);//c中的内存拷贝到刚分配的js内存中
- }
- //将C++层YUV解码数据V分量数据拷贝至JS层内存中
- for(h = 0; h < stuFrameInfo.nHeight / 2; h++)
- {
- jsYuvDataV.set(Module.HEAPU8.subarray((pBufV + h * stuFrameInfo.nStride/2), (pBufV + h * stuFrameInfo.nStride/2) + stuFrameInfo.nWidth/2), h * stuFrameInfo.nWidth/2);//c中的内存拷贝到刚分配的js内存中
- }
-
- msgData =
- {
- pBufY: jsYuvDataY,
- pBufU: jsYuvDataU,
- pBufV: jsYuvDataV,
- nSize: nSize,
- stuFrameInfo: stuFrameInfo,
- }
- }
- }
- else
- {
- msgData =
- {
- pBufY: null,
- pBufU: null,
- pBufV: null,
- nSize: 0,
- stuFrameInfo: stuFrameInfo,
- }
- }
- }
- else if(2 == stuFrameInfo.nFrameType)//音频帧
- {
- //总通道数
- stuFrameInfo.nTotalChannel = dataView.getInt32(68, true);
- //当前通道
- stuFrameInfo.nCurChannel = dataView.getInt32(72, true);
- //暂不支持双通道音频播放
- if (stuFrameInfo.nCurChannel > 0)
- {
- return;
- }
- //采样位数
- stuFrameInfo.nBits = dataView.getInt32(28, true);
- //采样率
- stuFrameInfo.nSamples = dataView.getInt32(32, true);
- //声道数
- stuFrameInfo.nAudioChnNum = dataView.getInt32(24, true);
-
- var AudioBuf = new ArrayBuffer(nSize);
- var UI8AudioData = new Uint8Array(AudioBuf);
- //将C++层解码后的pcm音频数据拷贝至JS层内存
- UI8AudioData.set(Module.HEAPU8.subarray(pBufY, pBufY + nSize));
-
- msgData =
- {
- pBufY: UI8AudioData,
- pBufU: null,
- pBufV: null,
- nSize: nSize,
- stuFrameInfo: stuFrameInfo,
- }
- }
-
- var msgType = 'VisibleDecCallBack';
-
- sendMessage(nPort, msgType, msgData);
-
- jsBuf = null;
- jsFrameBodyData = null;
- }
- /*
- * C++层AES解密回调。
- *
- * @param[in] nPort 端口号
- * @param[in] nFrameID 视频帧序号
- * @param[in] bSuccess 是否解密成功
- */
- function cDigitalSignCallBack(nPort, nFrameID, bSuccess)
- {
- m_bDecryptionResult = bSuccess;
- var msgType = 'DecryptionResultCallBack';
- var msgData =
- {
- bSuccess: bSuccess
- }
-
- sendMessage(nPort, msgType, msgData);
- }
- /*
- * C++层码流录制回调,回调至JS层进行数据存储
- *
- * @param[in] nPort 端口号
- * @param[in] pData 码流数据
- * @param[in] nDataLen 数据长度
- * @param[in] nOffset 偏移量
- * @param[in] pFrameInfo 码流信息
- */
- function cRecordDataCallBack(nPort, pData, nDataLen, nOffset, pFrameInfo)
- {
- var stuFrameInfo = {};
- if (!jsRecordFrameInfo)
- {
- jsRecordFrameBuf = new ArrayBuffer(292); //通过二进制对象分配一块连续内存
- jsRecordFrameInfo = new Uint8Array(jsRecordFrameBuf); //二进制对象绑定到视图,通过视图对内存进行读写操作
- dataViewRecord = new DataView(jsRecordFrameBuf);
- }
- jsRecordFrameInfo.set(Module.HEAPU8.subarray(pFrameInfo, pFrameInfo + 292)); //c中的内存拷贝到刚分配的js内存中
-
- //帧类型
- stuFrameInfo.nFrameType = dataViewRecord.getInt32(0, true);
- //帧序号
- stuFrameInfo.nFrameID = dataViewRecord.getInt32(4, true);
- //帧子类型
- stuFrameInfo.nFrameSubType = dataViewRecord.getInt32(56, true);
-
- //视频帧
- if (1 == stuFrameInfo.nFrameType)
- {
- //编码类型
- stuFrameInfo.nEncodeType = dataViewRecord.getInt32(68, true);
- //码流类型
- stuFrameInfo.nStreamType = dataViewRecord.getInt32(72, true);
-
- //时间戳
- stuFrameInfo.nTimeStamp = dataViewRecord.getUint32(8, true);
- //帧时间
- stuFrameInfo.nYear = dataViewRecord.getUint16(40, true);
- stuFrameInfo.nMonth = dataViewRecord.getUint16(42, true);
- stuFrameInfo.nDay = dataViewRecord.getUint16(46, true);
- stuFrameInfo.nHour = dataViewRecord.getUint16(48, true);
- stuFrameInfo.nMinute = dataViewRecord.getUint16(50, true);
- stuFrameInfo.nSecond = dataViewRecord.getUint16(52, true);
- }
-
- var bufRecord = new ArrayBuffer(nDataLen);
- var arrayRecord = new Uint8Array(bufRecord);
- arrayRecord.set(Module.HEAPU8.subarray(pData, pData + nDataLen));
-
- var msgType = 'RecordDataCallBack';
- var msgData =
- {
- pRecordData: arrayRecord,
- nLen: nDataLen,
- Offset: nOffset,
- stuFrameInfo: stuFrameInfo,
- }
- sendMessage(nPort, msgType, msgData);
-
- bufRecord = null;
- arrayRecord = null;
- }
- function cIVSDrawDataCallBack(nPort, pBuf, nType, nLen, nReallen)
- {
- //帧序号为-1时不绘制
- if(-1 == nReallen)
- {
- return;
- }
-
- var pParseredBuf = null;
-
- ivsBuf = new ArrayBuffer(nLen);//通过二进制对象分配一块连续内存
- ivsDataArray = new Uint8Array(ivsBuf);//二进制对象绑定到视图,通过视图对内存进行读写操作
- ivsDataArray.set(Module.HEAPU8.subarray(pBuf, pBuf + nLen));
- ivsDataView = new DataView(ivsDataArray.buffer);
-
- //DHOP开放平台智能帧
- if (IVS_TYPE.IVSINFOTYPE_DHOP_SMART == nType)
- {
- var stuObjDHOP = {};
- stuObjDHOP.nId = ivsDataView.getUint32(0, true);//对象ID
- stuObjDHOP.wCustom = ivsDataView.getUint16(4, true);//自定义值
- stuObjDHOP.chState = ivsDataView.getUint8(6, true);//对象状态
- stuObjDHOP.chCount = ivsDataView.getUint8(7, true);//元素个数
-
- //解析DHOP元素
- var pElement = ivsDataView.getUint32(8, true);
- let elementBuf = new ArrayBuffer(12);
- let elementDataArray = new Uint8Array(elementBuf);
- let elementDataView = new DataView(elementBuf);
-
- stuObjDHOP.pElement = new Array(stuObjDHOP.chCount);
- for (var i = 0; i < stuObjDHOP.chCount; i++)
- {
- elementDataArray.set(Module.HEAPU8.subarray(pElement + i * 12, pElement + i * 12 + 12));
- //解析DHOP元素类型
- stuObjDHOP.pElement[i] = {};
- stuObjDHOP.pElement[i].nStructType = elementDataView.getUint32(0, true);
- stuObjDHOP.pElement[i].nStructLength = elementDataView.getUint32(4, true);
- var pStruct = elementDataView.getUint32(8, true);
-
- let structBuf = new ArrayBuffer(stuObjDHOP.pElement[i].nStructLength);
- let structArray = new Uint8Array(structBuf);
- let structDataView = new DataView(structBuf);
- structArray.set(Module.HEAPU8.subarray(pStruct, pStruct + stuObjDHOP.pElement[i].nStructLength));
-
- stuObjDHOP.pElement[i].pStruct = {};
- if (IVS_DHOP_ElEMENT_TYPE.EM_DHOP_CIRCLE == stuObjDHOP.pElement[i].nStructType)
- {
- stuObjDHOP.pElement[i].pStruct.chType = structDataView.getUint8(0, true);//子类型0x3
- stuObjDHOP.pElement[i].pStruct.chWidth = structDataView.getUint8(1, true);//线宽,单位px
- stuObjDHOP.pElement[i].pStruct.chStyle = structDataView.getUint8(2, true);//样式
-
- stuObjDHOP.pElement[i].pStruct.wRadius = structDataView.getUint16(4, true);//半径
- stuObjDHOP.pElement[i].pStruct.positionCircle = {};//圆心坐标
- stuObjDHOP.pElement[i].pStruct.positionCircle.x = structDataView.getUint16(8, true);
- stuObjDHOP.pElement[i].pStruct.positionCircle.y = structDataView.getUint16(10, true);
-
- stuObjDHOP.pElement[i].pStruct.chLineA = structDataView.getUint8(12, true);//边框线条颜色(ARGB)
- stuObjDHOP.pElement[i].pStruct.chLineR = structDataView.getUint8(13, true);
- stuObjDHOP.pElement[i].pStruct.chLineG = structDataView.getUint8(14, true);
- stuObjDHOP.pElement[i].pStruct.chLineB = structDataView.getUint8(15, true);
- stuObjDHOP.pElement[i].pStruct.chRegA = structDataView.getUint8(16, true);//区域填充颜色(ARGB)
- stuObjDHOP.pElement[i].pStruct.chRegR = structDataView.getUint8(17, true);
- stuObjDHOP.pElement[i].pStruct.chRegG = structDataView.getUint8(18, true);
- stuObjDHOP.pElement[i].pStruct.chRegB = structDataView.getUint8(19, true);
-
- }
- else if(IVS_DHOP_ElEMENT_TYPE.EM_DHOP_BrokenLine == stuObjDHOP.pElement[i].nStructType)
- {
- stuObjDHOP.pElement[i].pStruct.chType = structDataView.getUint8(0, true);//子类型0x2
- stuObjDHOP.pElement[i].pStruct.chCount = structDataView.getUint8(1, true);//端点个数
- stuObjDHOP.pElement[i].pStruct.chWidth = structDataView.getUint8(2, true);//线宽,单位px
- stuObjDHOP.pElement[i].pStruct.chStyle = structDataView.getUint8(3, true);//样式
- stuObjDHOP.pElement[i].pStruct.chLineA = structDataView.getUint8(4, true);//边框线条颜色(ARGB)
- stuObjDHOP.pElement[i].pStruct.chLineR = structDataView.getUint8(5, true);
- stuObjDHOP.pElement[i].pStruct.chLineG = structDataView.getUint8(6, true);
- stuObjDHOP.pElement[i].pStruct.chLineB = structDataView.getUint8(7, true);
- //端点坐标
- var pPoints = null;
- let pointsBuf = null;
- let pointsDataArray = null;
- let pointsDataView = null;
-
- if (stuObjDHOP.pElement[i].pStruct.chCount > 0)
- {
- stuObjDHOP.pElement[i].pStruct.pPoints = new Array(stuObjDHOP.pElement[i].pStruct.chCount);
- pPoints = structDataView.getUint32(8, true);
- pointsBuf = new ArrayBuffer(4);
- pointsDataArray = new Uint8Array(pointsBuf);
- pointsDataView = new DataView(pointsBuf);
- }
-
- for(var j = 0; j < stuObjDHOP.pElement[i].pStruct.chCount; j++)
- {
- pointsDataArray.set(Module.HEAPU8.subarray(pPoints + j*4, pPoints + j*4 + 4));
- stuObjDHOP.pElement[i].pStruct.pPoints[j] = {};
- stuObjDHOP.pElement[i].pStruct.pPoints[j].x = pointsDataView.getUint16(0, true);
- stuObjDHOP.pElement[i].pStruct.pPoints[j].y = pointsDataView.getUint16(2, true);
- }
- }
- else if(IVS_DHOP_ElEMENT_TYPE.EM_DHOP_POLYGON == stuObjDHOP.pElement[i].nStructType)
- {
- stuObjDHOP.pElement[i].pStruct.chType = structDataView.getUint8(0, true);//子类型0x3
- stuObjDHOP.pElement[i].pStruct.chCount = structDataView.getUint8(1, true);//端点个数
- stuObjDHOP.pElement[i].pStruct.chWidth = structDataView.getUint8(2, true);//线宽,单位px
- stuObjDHOP.pElement[i].pStruct.chStyle = structDataView.getUint8(3, true);//样式
- stuObjDHOP.pElement[i].pStruct.chLineA = structDataView.getUint8(4, true);//边框线条颜色(ARGB)
- stuObjDHOP.pElement[i].pStruct.chLineR = structDataView.getUint8(5, true);
- stuObjDHOP.pElement[i].pStruct.chLineG = structDataView.getUint8(6, true);
- stuObjDHOP.pElement[i].pStruct.chLineB = structDataView.getUint8(7, true);
- stuObjDHOP.pElement[i].pStruct.chRegA = structDataView.getUint8(8, true);//区域填充颜色(ARGB)
- stuObjDHOP.pElement[i].pStruct.chRegR = structDataView.getUint8(9, true);
- stuObjDHOP.pElement[i].pStruct.chRegG = structDataView.getUint8(10, true);
- stuObjDHOP.pElement[i].pStruct.chRegB = structDataView.getUint8(11, true);
- //端点坐标
- var pPoints = null;
- let pointsBuf = null;
- let pointsDataArray = null;
- let pointsDataView = null;
-
- if (stuObjDHOP.pElement[i].pStruct.chCount > 0)
- {
- stuObjDHOP.pElement[i].pStruct.pPoints = new Array(stuObjDHOP.pElement[i].pStruct.chCount);
- pPoints = structDataView.getUint32(12, true);
- pointsBuf = new ArrayBuffer(4);
- pointsDataArray = new Uint8Array(pointsBuf);
- pointsDataView = new DataView(pointsBuf);
- }
-
- for(var j = 0; j < stuObjDHOP.pElement[i].pStruct.chCount; j++)
- {
- pointsDataArray.set(Module.HEAPU8.subarray(pPoints + j*4, pPoints + j*4 + 4));
- stuObjDHOP.pElement[i].pStruct.pPoints[j] = {};
- stuObjDHOP.pElement[i].pStruct.pPoints[j].x = pointsDataView.getUint16(0, true);
- stuObjDHOP.pElement[i].pStruct.pPoints[j].y = pointsDataView.getUint16(2, true);
- }
- }
- else if(IVS_DHOP_ElEMENT_TYPE.EM_DHOP_TEXT == stuObjDHOP.pElement[i].nStructType)
- {
- stuObjDHOP.pElement[i].pStruct.chType = structDataView.getUint8(0, true);//子类型0x4
- stuObjDHOP.pElement[i].pStruct.chCharset = structDataView.getUint8(1, true);//编码方式
- stuObjDHOP.pElement[i].pStruct.stringPos = {};//字符坐标
- stuObjDHOP.pElement[i].pStruct.stringPos.x = structDataView.getUint16(4, true);
- stuObjDHOP.pElement[i].pStruct.stringPos.y = structDataView.getUint16(6, true);
- stuObjDHOP.pElement[i].pStruct.chLineA = structDataView.getUint8(8, true);//字体颜色(ARGB)
- stuObjDHOP.pElement[i].pStruct.chLineR = structDataView.getUint8(9, true);
- stuObjDHOP.pElement[i].pStruct.chLineG = structDataView.getUint8(10, true);
- stuObjDHOP.pElement[i].pStruct.chLineB = structDataView.getUint8(11, true);
- stuObjDHOP.pElement[i].pStruct.chFontSize = structDataView.getUint8(12, true);//字体大小,单位px
- stuObjDHOP.pElement[i].pStruct.chFontAlign = structDataView.getUint8(13, true);//对齐方式
- stuObjDHOP.pElement[i].pStruct.wTxtLen = structDataView.getUint16(14, true);//字符长度
-
- var pString = structDataView.getUint32(16, true);
- var stringBuf = new ArrayBuffer(stuObjDHOP.pElement[i].pStruct.wTxtLen);
- var stringDataArray = new Uint8Array(stringBuf);
- var stringDataView = new DataView(stringBuf);
- stringDataArray.set(Module.HEAPU8.subarray(pString, pString + stuObjDHOP.pElement[i].pStruct.wTxtLen));
- stuObjDHOP.pElement[i].pStruct.stringDataArray = stringDataArray;
- }
- }
-
- //解析DHOP信息内容
- stuObjDHOP.nInfoLen = ivsDataView.getUint16(12, true);//信息长度
- if (stuObjDHOP.nInfoLen > 0)
- {
- var pInfo = ivsDataView.getUint32(16, true);
- let infoBuf = new ArrayBuffer(nInfoLen);
- let infoDataArray = new Uint8Array(infoBuf);
- infoDataArray.set(Module.HEAPU8.subarray(pInfo, pInfo + nInfoLen));
- stuObjDHOP.pInfo = infoDataArray;
- }
-
- pParseredBuf = stuObjDHOP;
- }
- else if (IVS_TYPE.IVSINFOTYPE_TAGGING_INFO == nType)//景物点信息标注帧
- {
- let dataView = new DataView(ivsBuf);
- let tagInfoNum = nLen/FRAME_SCENE_POINTS_INFOR_SIZE;
- let tagInfos = [];
- for (let tagInfoIndex = 0; tagInfoIndex < tagInfoNum; tagInfoIndex++)
- {
- var tagInfo = {};
- let Stride = FRAME_SCENE_POINTS_INFOR_SIZE * tagInfoIndex;
- //编号
- tagInfo.nIndex = dataView.getInt32(Stride + 0, true);
- //景物点x坐标
- tagInfo.xPoint = dataView.getUint16(Stride + 4, true);
- //景物点y坐标
- tagInfo.yPoint = dataView.getUint16(Stride + 6, true);
-
- //一级名称
- var jsNameBuf = new ArrayBuffer(64);
- jsNameBuf = ivsBuf.slice(Stride + 8);
- tagInfo.strName = ArrayBufferToStringAutoClip(jsNameBuf);
-
- //使能标记
- tagInfo.enable = dataView.getInt8(Stride + 72, true);
- //标签类型
- tagInfo.titleType = dataView.getInt8(Stride + 73, true);
- //标签属性
- tagInfo.titleAttribute = dataView.getInt8(Stride + 74, true);
- tagInfo.sharpType = dataView.getInt8(Stride + 75, true);
- tagInfo.polygonNum = dataView.getInt8(Stride + 76, true);
- tagInfo.polygon = [];
- //与上一个中间空了三字节
- for(let i = 0;i< tagInfo.polygonNum*2;i+=2)
- {
- tagInfo.polygon[i] ={x: dataView.getInt8(Stride + 79 + 2*i, true),
- y: dataView.getInt8(Stride + 79 + 2*(i+1), true)};
- }
- tagInfos[tagInfoIndex] = tagInfo;
- jsNameBuf = null;
- }
-
- var msgType = 'ARTagInfoCallback';
- var msgData =
- {
- tagInfo: tagInfos,
- }
-
- sendMessage(nPort, msgType, msgData);
-
- pParseredBuf = ivsDataArray;
- dataView = null;
- }
- else
- {
- pParseredBuf = ivsDataArray;
- }
-
- var msgType = 'IVSDataCallBack';
- var msgData =
- {
- pBuf: pParseredBuf,
- nType: nType,
- nLen: nLen,
- nReallen: nReallen,
- }
-
- sendMessage(nPort, msgType, msgData);
- }
- function sendMessage(nPort, msgType, msgData)
- {
- var event =
- {
- nPort: nPort,
- msgType: msgType,
- msgData: msgData,
- };
- postMessage(event);
- }
- function ArrayBufferToString(buffer, encoding = 'utf-8')
- {
- const decoder = new TextDecoder(encoding);
- return decoder.decode(buffer);
- }
- function ArrayBufferToStringAutoClip(buffer, encoding = 'utf-8')
- {
- const decoder = new TextDecoder(encoding);
- const uint8Array = new Uint8Array(buffer);
-
- let i = 0;
-
- while (i < uint8Array.length) {
- if (uint8Array[i] === 0) {
- break;
- }
- i++;
- }
-
- return decoder.decode(buffer.slice(0,i));
- }
|