RecordPlayBackParse.js 9.9 KB
import ByteBuffer  from 'libs/bytebuffer.min';
import Emiter from 'Emiter';
import MessageTypes from 'MessageTypes';
import Loger from 'Loger';

import pdu from 'pdus/index';
import PduType from 'pdus/PduType';
import PduConsts from 'pdus/PduConsts';
import ApeConsts from 'apes/ApeConsts';
import ArrayBufferUtil from 'libs/ArrayBufferUtil';
import Base64 from 'base64-js';
import GlobalConfig from 'GlobalConfig';
import EngineUtils from 'EngineUtils';
import TimerCounter from "TimerCounter";


let parseBuffer;
// 日志对象
const loger = Loger.getLoger('RecordPlayBackParse');
const Default=0;//未开始
const PLAY=1;//播放中
const PAUSE=2;//暂停
const SEEK=3;//seek
const STOP=4;//停止

class RecordPlayBackParse extends Emiter {
    constructor() {
        super();
        loger.log("RecordPlayBackParse");
        parseBuffer = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN);
        parseBuffer.clear();
        console.log(parseBuffer);
        this._recordPlaybackTimestamp = 0;//回放的时间
        this._recordPlaybackMaxTime = 0;//录制回放的总时间
        this._apes = {};
        this._messages = {};
        this._timerCounter = new TimerCounter();//计时器
        this._timerCounter.addTimerCallBack(this._timerCounterUptate.bind(this), 1);
    }

    //method--------------------内部---------------------------------------------
    // 注册Ape
    registerApe(ape) {
        this._apes[ape._session_id] = ape;
    }

    // 录制回放EverSocket底层消息处理
    _everSocketMsgReceivedHandler(data) {
        let pduMsg = pdu.decode_pdu(data);
        let pduType = pduMsg.get("type");
        let pduData = pduMsg.get("data");
        //*************非常重要******************
        //客户端发送的所有125消息,MCU收到之后会痛120把消息返回给客户端,
        //所以需要把125消息type转换为120,因为MCU在录制的时候是直接录制客户端发送的消息而不是MCU转换之后的
        if (pduType == PduType.RCPDU_UNIFORM_SEND_DATA_REQUEST) {
            pduMsg.type = PduType.RCPDU_SEND_DATA_REQUEST;
            pduType = PduType.RCPDU_SEND_DATA_REQUEST;
        }
        loger.log('pduType', pduType);
        switch (pduType) {
            case PduType.RCPDU_CONNECT_PROVIDER_RESPONSE:
                //加入课堂请求返回数据处理
                let joinConfPdu = pdu['RCConferenceJoinResponsePdu'].decode(pduData);
                let pduResultCode = joinConfPdu.result;
                loger.warn('RCPDU_CONNECT_PROVIDER_RESPONSE  ->pduResultCode:' + pduResultCode);
                switch (pduResultCode) {
                    case PduConsts.RET_SUCCESS:
                        //加入成功
                        this._updateMCUConfInfoDescription(joinConfPdu.classDescription);
                        this._emit(MessageTypes.CLASS_JOIN_MCU_SUCCESS, this.classInfo);
                        break;
                    case PduConsts.RET_FULL_CAPACITY:
                        this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_FULL);
                        break;
                    default:
                        loger.warn('JoinConfPdu-未知类型-等待处理.', pduResultCode);
                        break
                }
                break;
            case PduType.RCPDU_SEND_DATA_REQUEST:
                //先判断当前消息属于哪个APE 根据 sessionId来判断
                let ape = this._apes[pduMsg.sessionId];
                let sessionLabel = ApeConsts(pduMsg.sessionId);
                if (ape) {
                    let subTypeLabel = pdu.id2type(pduMsg.subType);
                    //loger.log('MCU-SecondLayer封装消息', 'sessionId', sessionLabel, pduMsg.sessionId, 'subtype', subTypeLabel, pduMsg.subType);
                    //ape广播事件,只要ape中监听就能收到
                    ape._emit(pduMsg.subType, pduMsg.data);
                } else {
                    loger.warn(sessionLabel + '尚未注册');
                }
                break;
            default:
                loger.warn('PDU-未知类型-等待处理.', pduType);
        }
    }

    //开启计时器
    _startTimerCounter() {
        this._timerCounter.startTimer();
    }

    //停止计时器
    _stopTimerCounter() {
        this._timerCounter.stopTimer();
    }

    _timerCounterUptate() {
        this._recordPlaybackTimestamp = this._recordPlaybackTimestamp + 1;//计时
        if(this._recordPlaybackTimestamp>=this._recordPlaybackMaxTime){
            this._stopTimerCounter();
            loger.log("录制结束...当前时间->", this._recordPlaybackTimestamp," 总时间->",this._recordPlaybackMaxTime);
            this._emit(MessageTypes.RECORD_PLAYBACK_UPDATE,{"status":STOP});
            return;
        }

        loger.log("录制回放中...", this._recordPlaybackTimestamp);
        this._emit(MessageTypes.CLASS_UPDATE_TIMER, {"classTimestamp": this._recordPlaybackTimestamp});

        //根据时间查找消息数据
        this._searchMessageFromTime(this._recordPlaybackTimestamp);
    }

    //加载录制文件
    readyRecordPlay() {
        this._stopTimerCounter();
        loger.log("读取回放数据");
        //let url = `http://123.56.73.119:80/h5dev/20170306/1357644520_20170306.rec`;
        let url = `http://${ GlobalConfig.RecordServerIP}:${ GlobalConfig.RecordServerPort}/${GlobalConfig.recordFileName}`;
        console.log(url);
        fetch(url, {
            timeout: 90000 //加载文件超时时间1分30秒
        })
            .then(ret => {
                if (ret.ok) {
                    return ret.arrayBuffer();
                } else {
                    loger.error(`读取回放数据-网络异常.状态码:${ret.status}`);
                    this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_RECORD_PLAY_BACK_DATA_FAILED);
                    throw '';
                }
            })
            .then(ret => {
                if (ret) {
                    loger.log('读取回放数据-完成');
                    this._loadRecordDataSuccess(ret);
                } else {
                    loger.warn('读取回放数据-失败.');
                    this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_RECORD_PLAY_BACK_DATA_FAILED);
                }
            })
            .catch(err => {
                loger.error(`读取回放数据.状态码:${err}`);
                this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_RECORD_PLAY_BACK_DATA_FAILED);
            });
    }

    _loadRecordDataSuccess(arrayBuffer) {
        loger.log("获取录制回放数据的长度", arrayBuffer.byteLength);
        if (parseBuffer) {
            parseBuffer.clear();
            parseBuffer.append(arrayBuffer);
            //解析数据
            this.parseArrayBuf();
        }
    }

    //解析数据
    parseArrayBuf() {
        this._messages = {};
        let byteLength = parseBuffer.offset;
        parseBuffer.byteOffset = 0;
        var position = 0;
        while (position < byteLength) {
            let timestamp = parseBuffer.readUInt32(position);
            position += 4;//4字节
            let byteLen = parseBuffer.readUInt32(position);
            position += 4;//4字节
            let byteData = parseBuffer.buffer.slice(position, (position + byteLen));
            position += byteLen;
            console.log(timestamp, byteLen, byteData);

            let messageItem=this._messages[timestamp];
            if(!messageItem){
                this._messages[timestamp]=[];//数组存数据,因为有1秒内收到多个消息的情况,timestamp是按秒记录的
                messageItem=this._messages[timestamp];
            }
            messageItem.push({"timestamp": timestamp, "byteData": byteData});

            //记录最后一个数据的时间戳作为整个录制回放的总时间戳
            this._recordPlaybackMaxTime=timestamp;
        }
        this._recordPlaybackTimestamp=0;
        this._stopTimerCounter();

        GlobalConfig.recordPlaybackMaxTime=this._recordPlaybackMaxTime;
        loger.log("录制回放数据解析完成,录制回放的总时间长为->",this._recordPlaybackMaxTime);
        console.log(this._messages);
        this._emit(RecordPlayBackParse.CLASS_JOIN_RECORD_PLAYBACK_SUCCESS,{"recordPlaybackMaxTime":this._recordPlaybackMaxTime});
    }

    //根据时间查找数据
    _searchMessageFromTime(_timestamp){
        let msgDataArr=this._messages[_timestamp];
        if(!msgDataArr){
            //没有数据,需要查找当前时间点属于哪一个时间戳关键帧

        }else {
            //把时间点对应的数据发送,同一秒内有存在多个数据的情况
            for(let i=0;i<msgDataArr.length;i++){
                this._everSocketMsgReceivedHandler(msgDataArr[i].byteData);
            }
        }
    }
    //method------------外部接口-------------------------------------

    startRecordPlayback(_param) {
        this._startTimerCounter();
        return {"code": ApeConsts.RETURN_SUCCESS,"data": "ok"};
        //this._apes(MessageTypes.RECORD_PLAYBACK_UPDATE,{"status":});
    }

    stopRecordPlayback(_param) {
        this._recordPlaybackTimestamp = 0;
        this._stopTimerCounter();
        return {"code": ApeConsts.RETURN_SUCCESS,"data": "ok"};
    }

    pauseRecordPlayback(_param) {
        this._stopTimerCounter()
        return {"code": ApeConsts.RETURN_SUCCESS,"data": "ok"};
    }

    seekRecordPlayback(_param) {
        if(!_param||!_param.time){
            return {"code": ApeConsts.RETURN_FAILED,"data": "参数不正确"};
        }
        this._stopTimerCounter()
        this._recordPlaybackTimestamp = _param.time || 0;
        this._startTimerCounter();
        return {"code": ApeConsts.RETURN_SUCCESS,"data": "ok"};
    }
}

RecordPlayBackParse.prototype.CLASS_JOIN_RECORD_PLAYBACK_SUCCESS = RecordPlayBackParse.CLASS_JOIN_RECORD_PLAYBACK_SUCCESS = 'class_join_recordPlayback_success';//加入录制回放成功

export default new RecordPlayBackParse;