importScripts('libSystemTransform.js');
const RECORDRTP = 0;  //录制一份未经过转封装的码流原始数据，用于定位问题
let dataType = 1;
    
// 字母字符串转byte数组
function stringToBytes (str) {
  var ch;
  var st;
  var re = [];
  for (var i = 0; i < str.length; i++) {
    ch = str.charCodeAt(i);  // get char
    st = [];                 // set up "stack"
    do {
      st.push(ch & 0xFF);    // push byte to stack
      ch = ch >> 8;          // shift value down by 1 byte
    }
    while (ch);
    // add stack contents to result
    // done because chars have "wrong" endianness
    re = re.concat(st.reverse());
  }
  // return an array of bytes
  return re;
}

// 转封装库回调函数
self.STCallBack = function (fileIndex, indexLen, data, dataLen) {
  //stFrameInfo的类型见DETAIL_FRAME_INFO
  let stFrameInfo = Module._GetDetialFrameInfo();
  let nIsMp4Index = stFrameInfo.nIsMp4Index;
		
  //console.log("FrameType is " , stFrameInfo);
  //console.log("nIsMp4Index is " + nIsMp4Index);
  //debugger
  var pData = null;
  pData = new Uint8Array(dataLen);
  pData.set(Module.HEAPU8.subarray(data, data + dataLen));
  if (dataType === 1) {
    postMessage({ type: "outputData",
      buf: pData.buffer,
      dType: 1,
      frameInfo: stFrameInfo }, [pData.buffer]);
    dataType = 2;
  } else {
    if (nIsMp4Index) {
      postMessage({ type: "outputData",
        buf: pData.buffer,
        dType: 6,
        frameInfo: stFrameInfo }, [pData.buffer]); //6：索引类型
    } else {
      postMessage({ type: "outputData",
        buf: pData.buffer,
        dType: 2,
        frameInfo: stFrameInfo }, [pData.buffer]); //2:码流
    }
  }

  //stFrameInfo的类型见DETAIL_FRAME_INFO
  //let stFrameInfo = Module._GetDetialFrameInfo();
  //let stFrameType = stFrameInfo.nFrameType;
  //let nFrameNum = stFrameInfo.nFrameNum;
  //let nTimeStamp = stFrameInfo.nTimeStamp;
  //let nIsMp4Index = stFrameInfo.nIsMp4Index;
		
  //console.log("FrameType is " + stFrameType);
  //console.log("nIsMp4Index is " + nIsMp4Index);
};

// self.Module = { memoryInitializerRequest: loadMemInitFile(), TOTAL_MEMORY: 128*1024*1024 };
// importScripts('SystemTransform.js');

self.Module['onRuntimeInitialized'] = function () {
  postMessage({type: "loaded"});
};
onmessage = function (e) {
  var data = e.data;
  if ("create" === data.type) {
    if (RECORDRTP) {
      postMessage({ type: "created" });
      postMessage({ type: "outputData",
        buf: data.buf,
        dType: 1 }, [data.buf]);
    } else {
      var iHeadLen = data.len;
      var pHead = Module._malloc(iHeadLen);
      if (pHead === null) {
        console.log("inputdata malloc failed!!!");
        return -1;
      }
      var iTransType = data.packType;//目标格式
      var iRet = 0;
      var buf = new Uint8Array(data.buf);
      //PS流(只有ps支持探测)，并且编码格式异常（正常是265和264，11位和10位 不可能全是0，全0 并且是ps就探测策略）的情况下，使用探测策略
      if (buf[9] === 0 && buf[8] === 2 && buf[11] === 0 && buf[10] === 0) {
        iRet = Module._CreatHandle(0, iTransType, iHeadLen); //用探测的策略
      } else {
        self.writeArrayToMemory(buf, pHead);
        iRet = Module._CreatHandle(pHead, iTransType, iHeadLen);
        //-2147483645代表的是参数错误，此种情况，大概率发生在头信息错误，例如大华设备的情况，此时用 无头探测的策略
        //其他情况 按海康标准处理流程，不要做任何特殊处理
        if (iRet == -2147483645) {
          iRet = Module._CreatHandle(0, iTransType, iHeadLen); //失败了，用探测的策略再试一次
        }
      }
      if (iRet != 0) {
        if (iRet == -2147483647) {
          postMessage({ type: "outputData",
            dType: 1501 }); //标记为格式不支持
        } else {
          postMessage({ type: "outputData",
            dType: 1501 }); //转封装创建失败，也同样提示码流格式不支持，如果后续要细化再区分
        }
        console.log("_CreatHandle failed!" + iRet);
      } else {
        if (data.options && typeof data.options.pKeyData !== "undefined" && data.options.pKeyData !== null) {
          if ((2 === iTransType && "" === data.options.pKeyData)) {
            //转ps的时候，如果密码是空是允许的，即使码流加密了，导出加密后的码流就行
            //此时不要设置密码否则反而会提示密码错误
          } else {
            var secretInfo = data.options;
            var keyLen = secretInfo.nKeyLen;
            var pKeyData = Module._malloc(keyLen);
            if (pKeyData === null) {
              console.log("setEncryptKey malloc failed!!!");
              return -1;
            }
            var nKeySize = secretInfo.pKeyData.length;
            var bufData = stringToBytes(secretInfo.pKeyData);
                  
            let inputData = new Uint8Array(bufData);
            Module.writeArrayToMemory(inputData, pKeyData);
            inputData = null;
                      
            iRet = Module._SysTransSetEncryptKey(secretInfo.nKeyType, pKeyData, keyLen, nKeySize);
            if (iRet != 0) {
              console.log("_SysTransSetEncryptKey failed!");
            }
            if (pKeyData != null) {
              Module._free(pKeyData);
              pKeyData = null;
            }
          }
        }
        //带samplingParam参数，代表需要 用到 音频替换功能
        if (data.options && typeof data.options.samplingParam !== "undefined") {
          var oParam = data.options.samplingParam;
          var nCapacityType = 1;                                //写死1 代表 剔除音频
          var nType = 3;                                        //写死3 代表 修改输出目标的海康头配置，内部包含视频参数、音频参数
          var nAudioEnable = 1;                                 //音频参数修改使能开关，0=不启用，1=启用
          var nAudioFormat = oParam.iAudioType;                 //音频编码类型 对应关系参考海康媒体头规范，PCM 0x7001  G711_U 0x7110  G711_A 0x7111 AAC 0x2001
          var nAudioChannels = oParam.iChannel;                 //音频通道数直接设置为
          var nAudioBitsPerSample = oParam.iAudioBitWidth;      //音频位样率
          var nAudioSamplesrate = oParam.iAudioSamplingRate;    //音频采样率
          var nAudioBitrate = oParam.iAudioBitRate;             //音频比特率
          iRet = Module._SysTransConfig(nCapacityType, nType, nAudioEnable, nAudioFormat,
            nAudioChannels, nAudioBitsPerSample, nAudioSamplesrate, nAudioBitrate);
          if (iRet != 0) {
            console.log("_SysTransConfig Failed:" + iRet);
          }
        } else {
          iRet = Module._SysTransConfig(128, 0, 0, 0, 0, 0, 0, 0);  //nCapacityType = 0x00000080 代表开启私有信息回调 解决转mp4后，私有信息丢失问题
          if (iRet != 0) {
            console.log("_SysTransConfig Failed:" + iRet);
          }
        }
        iRet = Module._SysTransRegisterDataCallBack();
        if (iRet != 0) {
          console.log("_SysTransRegisterDataCallBack Failed:" + iRet);
        }

        iRet = Module._SysTransStart(null, null);
        if (iRet != 0) {
          console.log("_SysTransStart Failed:" + iRet);
        }
        postMessage({type: "created"});
      }
      if (pHead != null) {
        Module._free(pHead);
        pHead = null;
      }
    }
  } else if ("inputData" === data.type) {
    if (RECORDRTP) {
      var aFileData = new Uint8Array(data.buf);  // 拷贝一份
      var iBufferLen = aFileData.length;
      var szBufferLen = iBufferLen.toString(16);
      if (szBufferLen.length === 1) {
        szBufferLen = "000" + szBufferLen;
      } else if (szBufferLen.length === 2) {
        szBufferLen = "00" + szBufferLen;
      } else if (szBufferLen.length === 3) {
        szBufferLen = "0" + szBufferLen;
      }
      var aData = [0, 0, parseInt(szBufferLen.substring(0, 2), 16), parseInt(szBufferLen.substring(2, 4), 16)];
      for (var iIndex = 0, iDataLength = aFileData.length; iIndex < iDataLength; iIndex++) {
        aData[iIndex + 4] = aFileData[iIndex];
      }
      var dataUint8 = new Uint8Array(aData);
      postMessage({type: "outputData",
        buf: dataUint8.buffer,
        dType: 2});
    } else {
      let inputMode = 0; //代表输入原始数据
      if (data.samplingParam) {
        iRet = Module._SysTransInputAudioPara(5, data.samplingParam.iChannel, data.samplingParam.iAudioBitWidth,
          data.samplingParam.iAudioSamplingRate, data.samplingParam.iTimeStamp, data.samplingParam.iAudioBitRate);            //参数含义和_SysTransConfig类似
        if (iRet != 0) {
          console.log("_SysTransInputAudioPara Failed:" + iRet);
        }
        inputMode = 2; //输入替换的音频
      }
      var pInputDataBuf = Module._malloc(data.len);
      var idataLen = data.len;
      self.writeArrayToMemory(new Uint8Array(data.buf), pInputDataBuf);
      // 输入数据，每次最多2m
      let pp = Module._SysTransInputData(inputMode, pInputDataBuf, idataLen);
      if (pp == -2147483627) {
        //-2147483627 对应十六进制的80000015
        postMessage({ type: "outputData",
          dType: 1500 }); //标记为密码错误
      } else if (pp == -2147483647) {
        postMessage({ type: "outputData",
          dType: 1501 }); //标记为格式不支持
      } else if (pp != 0) {
        console.log("InputData Failed:" + pp);
      }
      Module._free(pInputDataBuf);
    }
  } else if ("release" === data.type) {
    var iRet = Module._SysTransStop();
    if (iRet != 0) {
      console.log("_SysTransStop failed!");
    }
    Module._SysTransRelease();
    if (iRet != 0) {
      console.log("_SysTransRelease failed!");
    }
    close();
  }
};