2025-12-30 13:38:34 +08:00

1439 lines
46 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
const ENCRYPT_AES256 = 2;
const ENCRYPT_AES256_GDPR2 = 3;
const ENCRYPT_AES_STRING_FORMAT = 16;
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;
let m_arrayDemuxBuf = null;
let m_uintDemuxInfo = null;
let m_dvDemuxInfo = 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;
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, message.nFileSize, message.bSegment);
break;
//停止码流录制
case 'StopRecord':
case 'CancelRecord':
StopRecord();
break;
//设置播放速度
case 'SetPlaySpeed':
SetPlaySpeed(message.nSpeed);
break;
//设置OSD叠加
case 'SetYUVOSDInfoEx':
SetYUVOSDInfoEx(message.OSDInfo);
break;
case 'GetOriginalKeyCallBack':
GetOriginalKey(message.playToken, message.playTokenKey, message.deviceID);
case 'SetPlayTokenToDecrypt':
SetPlayTokenToDecrypt(message.playToken, message.keySalt, 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 'SetSecurityKeyEx':
SetSecurityKeyEx(message.nEncryptType, message.stDecryptKey);
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;
case 'SetInt32':
SetInt32(message.nSetType, message.nValue);
break;
case 'InputAudioData':
InputAudioData(message.audioData);
break;
case 'SetPrivacyRecover':
SetPrivacyRecover(message.bRecover);
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)
{
if(jsInputDataAry)
{
jsInputDataAry.set(data);
var nRet = Module._PLAY_InputData(m_nPlayPort, jsInputDataAry.byteOffset, data.length);
var i = 0;
}
var msgType = 'WorkerReceivedData';
var msgData =
{
nLength: data.length
}
sendMessage(m_nPlayPort, msgType, msgData);
}
function OpenIVSDraw()
{
Module._PLAY_RenderPrivateData(m_nPlayPort, 1, 0);
}
function CloseIVSDraw()
{
Module._PLAY_RenderPrivateData(m_nPlayPort, 0, 0);
}
function StartRecord(nRecordType, nFileSize, bSegment)
{
if (bSegment)
{
Module._PLAY_SetSegmentRecordData(m_nPlayPort, nFileSize, null, null);
}
Module._PLAY_StartDataRecord(m_nPlayPort, 0, nRecordType);
}
function StopRecord()
{
Module._PLAY_StopDataRecord(m_nPlayPort);
}
function SetPlaySpeed(nSpeed)
{
Module._PLAY_SetPlaySpeed(m_nPlayPort, nSpeed);
}
function SetYUVOSDInfoEx(OSDInfo)
{
if (0 == m_nCanvasWidth || 0 == m_nCanvasHeight)
{
return;
}
let nOsdCount = OSDInfo.osdCount;
let nStuOsdInfoSize = 18376;//单个YUV_OSD_INFO_EX结构体18376字节
const OsdDataInfoPtr = Module._malloc(nStuOsdInfoSize);
let arrayFormat = new Uint8Array(Module.HEAPU8.buffer);
for (let i = 0; i < nStuOsdInfoSize; i ++)
{
arrayFormat[OsdDataInfoPtr + i] = 0;
}
Module.HEAPU8[OsdDataInfoPtr + 0] = 1;//是否是私有字体
let strFontPath = "Font.bin";
let nSequence = 0;
strFontPath.split('').forEach((char, nIndex) =>
{
let nValue = char.charCodeAt(0);
arrayFormat[OsdDataInfoPtr + nSequence + 1] = nValue;
nSequence++;
});
Module.HEAP32[OsdDataInfoPtr/4 + 65] = nOsdCount;
for (let i = 0; i < nOsdCount; i ++)
{
let nPointX = OSDInfo.osdList[i].pointX / m_nCanvasWidth * m_nWidth;
let nPointY = OSDInfo.osdList[i].pointY / m_nCanvasHeight * m_nHeight;
Module.HEAP32[OsdDataInfoPtr/4 + 66 + 564/4 * i] = nPointX;// 旋转点像素x位置
Module.HEAP32[OsdDataInfoPtr/4 + 67 + 564/4 * i] = nPointY;// 旋转点像素y位置
Module.HEAP32[OsdDataInfoPtr/4 + 68 + 564/4 * i] = OSDInfo.osdList[i].colorR;// osd叠加颜色r范围0-255
Module.HEAP32[OsdDataInfoPtr/4 + 69 + 564/4 * i] = OSDInfo.osdList[i].colorG;// osd叠加颜色g范围0-255
Module.HEAP32[OsdDataInfoPtr/4 + 70 + 564/4 * i] = OSDInfo.osdList[i].colorB;// osd叠加颜色b范围0-255
Module.HEAP32[OsdDataInfoPtr/4 + 71 + 564/4 * i] = OSDInfo.osdList[i].colorA;// osd叠加透明度范围0-255
nSequence = 0;
//JS默认采用UTF-16编码需要先转为UTF-8编码
let UTF8Array = UTF16ToUTF8(OSDInfo.osdList[i].strOsdData);
for(let j = 0; j < UTF8Array.length; j++)
{
arrayFormat[(OsdDataInfoPtr + nSequence + 288 + 564 * i) >> 0] = UTF8Array[j];// osd数据使用utf-8编码
nSequence++;
}
Module.HEAP32[OsdDataInfoPtr/4 + 200 + 564/4 * i] = OSDInfo.osdList[i].fontX;// 字体宽度, 使用私有字体时无效
Module.HEAP32[OsdDataInfoPtr/4 + 201 + 564/4 * i] = OSDInfo.osdList[i].fontY;// 字体高度, 最大512
Module.HEAP32[OsdDataInfoPtr/4 + 202 + 564/4 * i] = OSDInfo.osdList[i].rotateAngle;// 旋转角度范围0-359度
Module.HEAPU8[OsdDataInfoPtr + 812 + 564 * i] = OSDInfo.osdList[i].coordinate8192;// 8192坐标系, 0表示像素坐标x,y基于码流分辨率, 1表示基于8192坐标系
}
Module._PLAY_SetYUVOSDInfoEx(m_nPlayPort, OsdDataInfoPtr);
Module._free(OsdDataInfoPtr);
}
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 SetPlayTokenToDecrypt(playToken, keySalt, deviceID)
{
var arrPlayToken = Module.intArrayFromString(playToken).concat(0);
var playTokenPtr = Module._malloc(arrPlayToken.length);
Module.HEAPU8.set(arrPlayToken, playTokenPtr);
var arrKeySalt = Module.intArrayFromString(keySalt).concat(0);
var keySaltPtr = Module._malloc(arrKeySalt.length);
Module.HEAPU8.set(arrKeySalt, keySaltPtr);
var arrDeviceID = Module.intArrayFromString(deviceID).concat(0);
var deviceIDPtr = Module._malloc(arrDeviceID.length);
Module.HEAPU8.set(arrDeviceID, deviceIDPtr);
var nRet = Module._PLAY_SetPlayTokenToDecrypt(m_nPlayPort, playTokenPtr, keySaltPtr, deviceIDPtr);
Module._free(playTokenPtr);
Module._free(keySaltPtr);
Module._free(deviceIDPtr);
var msgType = 'PlayTokenDecryptResult';
var msgData = nRet;
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 SetSecurityKeyEx(nEncryptType, stDecryptKey)
{
var nRet = 1;
const stDecryptKeyPtr = Module._malloc(96);
var nSequence = 0;
const keyPtr = Module._malloc(stDecryptKey.KeyLen);
var arrayKey = new Uint8Array(Module.HEAPU8.buffer);
stDecryptKey.Key.split('').forEach((char, nIndex) => {
arrayKey[(keyPtr + nSequence) >> 0] = char.charCodeAt(0);
nSequence++;
});
nSequence = 0;
const keyIdPtr = Module._malloc(stDecryptKey.KeyIdLen);
stDecryptKey.KeyId.split('').forEach((char, nIndex) => {
arrayKey[(keyIdPtr + nSequence) >> 0] = char.charCodeAt(0);
nSequence++;
});
Module.HEAP32[stDecryptKeyPtr/4 + 0] = keyPtr;
Module.HEAP32[stDecryptKeyPtr/4 + 1] = stDecryptKey.KeyLen;
Module.HEAP32[stDecryptKeyPtr/4 + 2] = keyIdPtr;
Module.HEAP32[stDecryptKeyPtr/4 + 3] = stDecryptKey.KeyIdLen;
nRet = Module._PLAY_SetSecurityKeyEx(m_nPlayPort, nEncryptType, stDecryptKeyPtr, stDecryptKey.KeyLen);
Module._free(keyPtr);
Module._free(keyIdPtr);
Module._free(stDecryptKeyPtr);
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;
}
function SetPrintLogLevel(nLogLevel)
{
Module._PLAY_SetPrintLogLevel(nLogLevel);
}
function SetInt32(nSetType, nValue)
{
Module._PLAY_SetInt32(m_nPlayPort, nSetType, nValue);
}
function InputAudioData(audioData)
{
var jsAudioData = Module._malloc(audioData.length);
var jsAudioDataAry = new Uint8Array(Module.HEAPU8.buffer, jsAudioData, audioData.length);
jsAudioDataAry.set(audioData);
Module._PLAY_InputAudioData(m_nPlayPort, jsAudioDataAry.byteOffset, audioData.length, 16, 8000);
Module._free(jsAudioData);
}
function SetPrivacyRecover(bRecover)
{
Module._PLAY_SetPrivacyRecover(m_nPlayPort, bRecover);
}
function cPlusVisibleDecCallBack(nPort, pBufY, pBufU, pBufV, nSize, pFrameInfo)
{
var stuFrameInfo = {};
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);
//旋转角度类型
stuFrameInfo.nRotateType = dataView.getUint8(122, true);
//vui句法中视频三原色
stuFrameInfo.nColorPrimaries = dataView.getUint8(124, true);
//vui句法中视频信号转换函数
stuFrameInfo.nColorTransfer = dataView.getUint8(125, true);
//vui中视频颜色空间
stuFrameInfo.nColorSpace = dataView.getUint8(126, true);
//颜色范围 0:yuv范围16-235,对应 TV; 1:yuv范围0-255, 对应 PC
stuFrameInfo.bColorFull = dataView.getUint8(127, 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;
}
//SVC码流不支持硬解码
if ((((1 == m_nVideoEncodeType) && (true == m_bSupportH264MSE))
|| ((2 == m_nVideoEncodeType) && (true == m_bSupportH265MSE)))
&& (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);
if (IVS_TYPE.IVSINFOTYPE_INTELFLOW == nType)
{//智能客流量
var stuIntelflowInfo = {};
stuIntelflowInfo.NumberStat = ivsDataView.getUint16(0, true);//大类业务方案
stuIntelflowInfo.nIntelFlowPlanNum = ivsDataView.getUint16(2, true);//智能客流规则数量(最大不会超过32个)
var pIntelFlowPlan = ivsDataView.getUint32(4, true);
let IntelFlowPlanBuf = new ArrayBuffer(12);
let IntelFlowPlanArray = new Uint8Array(IntelFlowPlanBuf);
let IntelFlowPlanView = new DataView(IntelFlowPlanBuf);
stuIntelflowInfo.pIntelFlowPlan = new Array(stuIntelflowInfo.nIntelFlowPlanNum);
for (let i = 0; i < stuIntelflowInfo.nIntelFlowPlanNum; i++)
{
IntelFlowPlanArray.set(Module.HEAPU8.subarray(pIntelFlowPlan + i * 12, pIntelFlowPlan + i * 12 + 12));
//解析智能客流规则
stuIntelflowInfo.pIntelFlowPlan[i] = {};
stuIntelflowInfo.pIntelFlowPlan[i].PlanId = IntelFlowPlanView.getUint16(0, true);//规则ID
stuIntelflowInfo.pIntelFlowPlan[i].RuleType = IntelFlowPlanView.getUint16(2, true);//规则类型
stuIntelflowInfo.pIntelFlowPlan[i].RegionNum = IntelFlowPlanView.getUint16(8, true);//区域数目
var pRegion = IntelFlowPlanView.getUint32(4, true);
let RegionBuf = new ArrayBuffer(12);
let RegionArray = new Uint8Array(RegionBuf);
let RegionView = new DataView(RegionBuf);
stuIntelflowInfo.pIntelFlowPlan[i].pRegion = new Array(stuIntelflowInfo.pIntelFlowPlan[i].RegionNum);
for (let j = 0; j < stuIntelflowInfo.pIntelFlowPlan[i].RegionNum; j++)
{
RegionArray.set(Module.HEAPU8.subarray(pRegion + j * 12, pRegion + j * 12 + 12));
stuIntelflowInfo.pIntelFlowPlan[i].pRegion[j] = {};
stuIntelflowInfo.pIntelFlowPlan[i].pRegion[j].RegionId = RegionView.getUint16(0, true);//区域ID
stuIntelflowInfo.pIntelFlowPlan[i].pRegion[j].State = RegionView.getUint16(2, true);//状态:离开or进入
stuIntelflowInfo.pIntelFlowPlan[i].pRegion[j].PeopleNum = RegionView.getUint32(4, true);//人数
}
}
pParseredBuf = stuIntelflowInfo;
}
else if (IVS_TYPE.IVSINFOTYPE_DHOP_SMART == nType)
{//DHOP开放平台智能帧
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);
var nBufLength = stuObjDHOP.pElement[i].nStructLength;
if (IVS_DHOP_ElEMENT_TYPE.EM_DHOP_TEXT === stuObjDHOP.pElement[i].nStructType)
{
nBufLength = 20;
}
let structBuf = new ArrayBuffer(nBufLength);
let structArray = new Uint8Array(structBuf);
let structDataView = new DataView(structBuf);
structArray.set(Module.HEAPU8.subarray(pStruct, pStruct + nBufLength));
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);//字符长度
if (stuObjDHOP.pElement[i].pStruct.wTxtLen > 0)
{
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(stuObjDHOP.nInfoLen);
let infoDataArray = new Uint8Array(infoBuf);
infoDataArray.set(Module.HEAPU8.subarray(pInfo, pInfo + stuObjDHOP.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 = tagInfos;
dataView = null;
}
else if (IVS_TYPE.IVSINFOTYPE_GPS_INFO == nType)//GPS信息帧
{
let nUtcLen = (nLen == 136) ? 8:4;//协议中utc类型为ulong
let ivsGPSBuf = new ArrayBuffer(nLen - nUtcLen);//通过二进制对象分配一块连续内存
let ivsGPSDataArray = new Uint8Array(ivsGPSBuf);//二进制对象绑定到视图,通过视图对内存进行读写操作
ivsGPSDataArray.set(Module.HEAPU8.subarray(pBuf + nUtcLen, pBuf + nLen));
let ivsGPSDataView = new DataView(ivsGPSDataArray.buffer);
let GPSInfos = [];
GPSInfos.longitude = ivsGPSDataView.getInt32(0, true) / 1000.0 / 3600.0;
GPSInfos.latitude = ivsGPSDataView.getInt32(4, true) /1000.0 / 3600.0;
GPSInfos.yaw = ivsGPSDataView.getFloat32(20, true);
GPSInfos.pitch = ivsGPSDataView.getFloat32(24, true);
GPSInfos.roll = ivsGPSDataView.getFloat32(28, true);
GPSInfos.absoluteAltitude = ivsGPSDataView.getFloat32(32, true);
GPSInfos.zoom = ivsGPSDataView.getFloat32(36, true);
var msgType = 'GPSInfoCallback';
var msgData =
{
GPSInfos: GPSInfos,
}
sendMessage(nPort, msgType, msgData);
ivsGPSDataView = null;
pParseredBuf = GPSInfos;
}
else
{
pParseredBuf = ivsDataArray;
}
var msgType = 'IVSDataCallBack';
var msgData =
{
pBuf: pParseredBuf,
nType: nType,
nLen: nLen,
nReallen: nReallen,
}
sendMessage(nPort, msgType, msgData);
}
function cDemuxDecCBFun(nPort, pBuf, nSize, pMutexInfo)
{
var stuDemuxInfo = {};
if(!m_uintDemuxInfo)
{
m_arrayDemuxBuf = new ArrayBuffer(72);//通过二进制对象分配一块连续内存
m_uintDemuxInfo = new Uint8Array(m_arrayDemuxBuf);//二进制对象绑定到视图,通过视图对内存进行读写操作
m_dvDemuxInfo = new DataView(m_arrayDemuxBuf);
}
m_uintDemuxInfo.set(Module.HEAPU8.subarray(pMutexInfo, pMutexInfo + 72));//c中的内存拷贝到刚分配的js内存中
//帧类型
stuDemuxInfo.nFrameType = m_dvDemuxInfo.getInt32(0, true);
//帧子类型
stuDemuxInfo.nFrameSubType = m_dvDemuxInfo.getInt32(4, true);
//编码类型
stuDemuxInfo.nEncodeType = m_dvDemuxInfo.getInt32(8, true);
//帧序号
stuDemuxInfo.nFrameID = m_dvDemuxInfo.getInt32(12, true);
//图像宽度
stuDemuxInfo.nWidth = m_dvDemuxInfo.getInt32(16, true);
//图像高度
stuDemuxInfo.nHeight = m_dvDemuxInfo.getInt32(20, true);
//视频帧率
stuDemuxInfo.nFrameRate = m_dvDemuxInfo.getInt32(24, true);
//帧时间
stuDemuxInfo.nYear = m_dvDemuxInfo.getUint16(28, true);
stuDemuxInfo.nMonth = m_dvDemuxInfo.getUint16(32, true);
stuDemuxInfo.nDay = m_dvDemuxInfo.getUint16(36, true);
stuDemuxInfo.nHour = m_dvDemuxInfo.getUint16(40, true);
stuDemuxInfo.nMinute = m_dvDemuxInfo.getUint16(44, true);
stuDemuxInfo.nSecond = m_dvDemuxInfo.getUint16(48, true);
//时间戳
stuDemuxInfo.nTimeStamp = m_dvDemuxInfo.getUint32(52, true);
//总通道数
stuDemuxInfo.nTotalChannel = m_dvDemuxInfo.getInt32(56, true);
//采样深度
stuDemuxInfo.nBits = m_dvDemuxInfo.getInt32(60, true);
//采样率
stuDemuxInfo.nSamples = m_dvDemuxInfo.getInt32(64, true);
//绝对时间毫秒
stuDemuxInfo.nMillisecond = m_dvDemuxInfo.getInt32(68, true);
var msgType = 'DemuxdataCallBack';
var msgData =
{
pBuf: pBuf,
nSize: nSize,
pMutexInfo: stuDemuxInfo,
}
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));
}
function UTF16ToUTF8(UTF16Str)
{
var UTF8Arr = [];
var byteSize = 0;
for (var i = 0; i < UTF16Str.length; i++)
{
//获取字符Unicode码值
var code = UTF16Str.charCodeAt(i);
//如果码值是1个字节的范围则直接写入
if (code >= 0x00 && code <= 0x7f)
{
byteSize += 1;
UTF8Arr.push(code);
//如果码值是2个字节以上的范围则按规则进行填充补码转换
}
else if (code >= 0x80 && code <= 0x7ff)
{
byteSize += 2;
UTF8Arr.push((192 | (31 & (code >> 6))));
UTF8Arr.push((128 | (63 & code)))
}
else if ((code >= 0x800 && code <= 0xd7ff) || (code >= 0xe000 && code <= 0xffff))
{
byteSize += 3;
UTF8Arr.push((224 | (15 & (code >> 12))));
UTF8Arr.push((128 | (63 & (code >> 6))));
UTF8Arr.push((128 | (63 & code)))
}
else if(code >= 0x10000 && code <= 0x10ffff)
{
byteSize += 4;
UTF8Arr.push((240 | (7 & (code >> 18))));
UTF8Arr.push((128 | (63 & (code >> 12))));
UTF8Arr.push((128 | (63 & (code >> 6))));
UTF8Arr.push((128 | (63 & code)))
}
}
return UTF8Arr
}