Newer
Older
safe_production_front / public / DispatchLib / DispatchVideoLib.js
wangxitong on 16 Aug 35 KB first commit
/************************** DispatchVideoLib ******************************/
function DispatchVideoLib() {}


 

DispatchVideoLib.VoipCallID = {};

var EleResize = {
    _handleResize: function(e) {
        var ele = e.target || e.srcElement;
        var trigger = ele.__resizeTrigger__;
        if (trigger) {
            var handlers = trigger.__z_resizeListeners;
            if (handlers) {
                var size = handlers.length;
                for (var i = 0; i < size; i++) {
                    var h = handlers[i];
                    var handler = h.handler;
                    var context = h.context;
                    handler.apply(context, [context]);
                }
            }
        }
    },
    _removeHandler: function(ele, handler, context) {
        var handlers = ele.__z_resizeListeners;
        if (handlers) {
            var size = handlers.length;
            for (var i = 0; i < size; i++) {
                var h = handlers[i];
                if (h.handler === handler && h.context === context) {
                    handlers.splice(i, 1);
                    return;
                }
            }
        }
    },
    _createResizeTrigger: function(ele) {
        var obj = document.createElement('object');
        obj.setAttribute('style',
            'display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden;opacity: 0; pointer-events: none; z-index: -1;'
            );
        obj.onload = EleResize._handleObjectLoad;
        obj.type = 'text/html';
        ele.appendChild(obj);
        obj.data = 'about:blank';
        return obj;
    },
    _handleObjectLoad: function(evt) {
        this.contentDocument.defaultView.__resizeTrigger__ = this.__resizeElement__;
        this.contentDocument.defaultView.addEventListener('resize', EleResize._handleResize);
    }
};
if (document.attachEvent) { //ie9-10
    EleResize.on = function(ele, handler, context) {
        var handlers = ele.__z_resizeListeners;
        if (!handlers) {
            handlers = [];
            ele.__z_resizeListeners = handlers;
            ele.__resizeTrigger__ = ele;
            ele.attachEvent('onresize', EleResize._handleResize);
        }
        handlers.push({
            handler: handler,
            context: context
        });
    };
    EleResize.off = function(ele, handler, context) {
        var handlers = ele.__z_resizeListeners;
        if (handlers) {
            EleResize._removeHandler(ele, handler, context);
            if (handlers.length === 0) {
                ele.detachEvent('onresize', EleResize._handleResize);
                delete ele.__z_resizeListeners;
            }
        }
    }
} else {
    EleResize.on = function(ele, handler, context) {
        var handlers = ele.__z_resizeListeners;
        if (!handlers) {
            handlers = [];
            ele.__z_resizeListeners = handlers;

            if (getComputedStyle(ele, null).position === 'static') {
                ele.style.position = 'relative';
            }
            var obj = EleResize._createResizeTrigger(ele);
            ele.__resizeTrigger__ = obj;
            obj.__resizeElement__ = ele;
        }
        handlers.push({
            handler: handler,
            context: context
        });
    };
    EleResize.off = function(ele, handler, context) {
        var handlers = ele.__z_resizeListeners;
        if (handlers) {
            EleResize._removeHandler(ele, handler, context);
            if (handlers.length === 0) {
                var trigger = ele.__resizeTrigger__;
                if (trigger) {
                    if (trigger.contentDocument) {
                        trigger.contentDocument.defaultView.removeEventListener('resize', EleResize._handleResize);
                    }
                    ele.removeChild(trigger);
                    delete ele.__resizeTrigger__;
                }
                delete ele.__z_resizeListeners;
            }
        }
    }
}

var DispatchVideoLib_Array = new Array();

var div_resize_listener = function(lib) {

    if (lib.div.clientWidth * lib.div.clientHeight == 0) {
        return;
    }

    console.log("div_resize " + lib.div.clientWidth + "x" + lib.div.clientHeight);

    //lib.video.style.width = "" + lib.div.clientWidth + "px";
    //lib.video.style.height = "" + lib.div.clientHeight + "px";
    
    if (lib.flag_rotate == 1 || lib.flag_rotate == 3) {
        lib.video.style.left = "" + Math.abs(lib.div.clientHeight-lib.div.clientWidth)/2 + "px";
        lib.video.style.top = "-" + Math.abs(lib.div.clientHeight-lib.div.clientWidth)/2 + "px";
        lib.video.style.width = "" + lib.div.clientHeight + "px";
        lib.video.style.height = "" + lib.div.clientWidth + "px";
    } else {
        lib.video.style.left = "0px";
        lib.video.style.top = "0px";
        lib.video.style.width = "" + lib.div.clientWidth + "px";
        lib.video.style.height = "" + lib.div.clientHeight + "px";
    }
    if (lib.head_div_control_div) {
        lib.head_div_control_div.style.width = lib.div.clientWidth / 5 + "px";
        lib.head_div_control_div.style.top = lib.div.clientHeight * 0.1 + "px";
        for (let item of lib.head_div_control_div.childNodes) {
            item.style.cssText = 
            `line-height:${lib.head_div_control_div.clientHeight / 3}px;display:flex;justify-content: center;`; //调节框样式
            for (let items of item.childNodes) {
                items.style.cssText = `transform:scale(${lib.div.clientHeight / 450});color:#fff;display:inline-block;opacity:0.8;white-space: nowrap;flex:1;width:50%;`; //调节框样式
            }
        }
    }
};


DispatchVideoLib.prototype.Init = function(Div,flag) {
    this.isDispatchVideoLib = true;
    var index = 0;
    for (var i = 0; i < 100; i++) {
        if (!DispatchVideoLib_Array[i]) {
            index = i;
            break;
        }
    }
    this.index = index;
    DispatchVideoLib_Array[this.index] = this;

    Div.DispatchVideoLib = this;

    this.CallID = -1;
    
    this.div = Div;

    this.video = document.createElement('video');
    this.video.id = "DispatchVideo_" + index;
    this.video.style.cssText =
        "position:absolute;background-color:black; left:0%; top:0%; width:100%; height:100%; z-index:1";
    this.video.autoplay = true;
    this.div.appendChild(this.video);

    this.textcanvas = document.createElement('canvas');
    this.textcanvas.style.cssText = "position:absolute; right:0; bottom:-7%;width:35%; height:auto; z-index:10;";
    this.textcanvas.id = "DispatchVideoText_" + index;
    this.div.appendChild(this.textcanvas);

    this.text_ctx = this.textcanvas.getContext("2d");
    this.text_ctx.clearRect(0, 0, this.video.width, this.video.height);
    this.text_ctx.font = "22px lighter bold Arial"
    //this.text_ctx.font = "30px Sans-serif"
    this.text_ctx.fillStyle = "white";
    this.text_ctx.textAlign = "right";
    this.text_ctx.textBaseline = 'top';

    this.UserText = "";

    this.video.videolib = this;

    this.rtclib = null;

    this.bFull = false;
    this.video.addEventListener('dblclick', function(e) {
        e.currentTarget.videolib.fullscreen();
    }, false);

    EleResize.on(Div, div_resize_listener, this);
    if(flag !== 1){
        this.AddControlDivNode();
    }
    console.log("DispatchVideoLib_" + this.index + " Init");
}

DispatchVideoLib.prototype.AddControlDivNode = function() {
    
    
    var self = this;
    
    this.head_div = document.createElement('div');
    this.head_div.style.cssText =
        "position:absolute;left:0%; top:0%; width:100%; height:10%; z-index:10;background:#515a6e;color:#000000;opacity:0.8";
    this.head_div.id = "DispatchVideoHeadDiv_" + this.index;
    this.head_div.style.display = "none";
    this.div.appendChild(this.head_div);
    
    
    var CreateCss = function(index, pic) {
        var cssText = "position:absolute;left:calc(100% - " + 6 * index + "%); top:6%; width:5%; height:90%; z-index:16;";
        cssText += "background-image:url(" + DispatchLibPath + "image/" + pic + ");background-color:#515a6e;display: inline-block;background-repeat: no-repeat;background-position: 2% 2%;background-size: 100% 100%"
        return cssText;
    }
    
    var a_index = 1;
    
    this.head_div_close = document.createElement('a');
    this.head_div_close.style.cssText = CreateCss(a_index, "close.png");
    this.head_div_close.id = "DispatchVideoHeadDivButton_close_" + this.index;
    this.head_div_close.DispatchFunction = "close";
    this.head_div_close.title = "关闭";
    this.head_div.appendChild(this.head_div_close);
    a_index++;
    
    if (DispatchCtrlLib.cb_forward) {
        this.head_div_forward = document.createElement('a');
        this.head_div_forward.style.cssText = CreateCss(a_index, "forward.png");
        this.head_div_forward.id = "DispatchVideoHeadDivButton_forward_" + this.index;
        this.head_div_forward.DispatchFunction = "forward";
        this.head_div_forward.title = "转发";
        this.head_div.appendChild(this.head_div_forward);
        a_index++;
    }
    
    this.head_div_mute = document.createElement('a');
    this.head_div_mute.style.cssText = CreateCss(a_index, "mute.png");
    this.head_div_mute.id = "DispatchVideoHeadDivButton_mute_" + this.index;
    this.head_div_mute.DispatchFunction = "mute";
    this.head_div_mute.title = "静音";
    this.head_div.appendChild(this.head_div_mute);
    a_index++;
    
    this.head_div_call = document.createElement('a');
    this.head_div_call.style.cssText = CreateCss(a_index, "call.png");
    this.head_div_call.id = "DispatchVideoHeadDivButton_call_" + this.index;
    this.head_div_call.DispatchFunction = "call";
    this.head_div_call.title = "语音通话";
    this.head_div.appendChild(this.head_div_call);
    a_index++;
    
    this.head_div_control = document.createElement('a');
    this.head_div_control.style.cssText = CreateCss(a_index, "control.png");
    this.head_div_control.id = "DispatchVideoHeadDivButton_control_" + this.index;
    this.head_div_control.DispatchFunction = "control";
    this.head_div_control.title = "控制";
    this.head_div.appendChild(this.head_div_control);
    a_index++;
    
    this.head_div_scale = document.createElement('a');
    this.head_div_scale.style.cssText = CreateCss(a_index, "scale.png");
    this.head_div_scale.id = "DispatchVideoHeadDivButton_scale_" + this.index;
    this.head_div_scale.DispatchFunction = "scale";
    this.head_div_scale.title = "放大/缩小";
    this.head_div.appendChild(this.head_div_scale);
    a_index++;
    
    this.head_div_rotate = document.createElement('a');
    this.head_div_rotate.style.cssText = CreateCss(a_index, "rotate.png");
    this.head_div_rotate.id = "DispatchVideoHeadDivButton_rotate_" + this.index;
    this.head_div_rotate.DispatchFunction = "rotate";
    this.head_div_rotate.title = "旋转";
    this.head_div.appendChild(this.head_div_rotate);
    a_index++;
    
    this.head_div_record = document.createElement('a');
    this.head_div_record.style.cssText = CreateCss(a_index, "record.png");
    this.head_div_record.id = "DispatchVideoHeadDivButton_record_" + this.index;
    this.head_div_record.DispatchFunction = "record";
    this.head_div_record.title = "录像";
    this.head_div.appendChild(this.head_div_record);
    a_index++;
    
    this.head_div_photo = document.createElement('a');
    this.head_div_photo.style.cssText = CreateCss(a_index, "photo.png");
    this.head_div_photo.id = "DispatchVideoHeadDivButton_photo_" + this.index;
    this.head_div_photo.DispatchFunction = "photo";
    this.head_div_photo.title = "拍照";
    this.head_div.appendChild(this.head_div_photo);
    a_index++;

    this.head_div_parameter = document.createElement('a');
    this.head_div_parameter.style.cssText = CreateCss(a_index, "parameter.png");
    this.head_div_parameter.id = "DispatchVideoHeadDivButton_parameter_" + this.index;
    this.head_div_parameter.DispatchFunction = "parameter";
    this.head_div_parameter.title = "参数";
    this.head_div.appendChild(this.head_div_parameter);
    a_index++;

    if (DispatchCtrlLib.cb_ptz) {
        this.head_div_ptz = document.createElement('a');
        this.head_div_ptz.style.cssText = CreateCss(a_index, "ptz.png");
        this.head_div_ptz.id = "DispatchVideoHeadDivButton_ptz_" + this.index;
        this.head_div_ptz.DispatchFunction = "ptz";
        this.head_div.appendChild(this.head_div_ptz);
        a_index++;
    }
    
    this.div.addEventListener('mouseover', function(e) {
        //self.head_div.style.display = "block";
        if (self.flag_bMoniterVideo) {
           self.head_div.style.display = "block";
           if (e.toElement.DispatchFunction) {
               if (e.target.DispatchFunction == "control" ||
                   e.target.DispatchFunction == "call") {
                   if (self.rtclib.target.Type == 5) {
                       return;
                   }
               } else if (e.target.DispatchFunction == "ptz") {
                   if (self.rtclib.target.Type == 1 ||
                       (self.rtclib.target.Type == 5 && self.rtclib.target.Number.length != 20)) {
                       return;
                   }
               }
               e.toElement.style.backgroundColor = "black";
           } 
        }
    }, false);
    
    this.div.addEventListener('mouseout', function(e) {
        self.head_div.style.display = "none";
    
        if (self.flag_bMoniterVideo) {
            if (e.fromElement.DispatchFunction) {
                e.fromElement.style.backgroundColor = "#515a6e";
            }
        }
    }, false);
    
    this.head_div.addEventListener('click', function(e) {
        if (e.target.DispatchFunction && self.flag_bMoniterVideo) {
        //if (e.target.DispatchFunction) {
            switch (e.target.DispatchFunction) {
                case "close": {
                    self.func_close();
                    e.target.style.backgroundColor = "black";
                    break;
                }
                case "forward": {
                    self.func_forward();
                    break;
                }
                case "mute": {
                    if (self.func_mute()) {
                        e.target.style.backgroundImage = "url(" + DispatchLibPath + "image/unmute.png)"
                    } else {
                        e.target.style.backgroundImage = "url(" + DispatchLibPath + "image/mute.png)"
                    }
                    break;
                }
                case "call": {
                    if (self.rtclib.target.Type == 5) {
                        return;
                    }
                    
                    if (self.func_call()) {
                        e.target.style.backgroundImage = "url(" + DispatchLibPath + "image/call_hangup.png)"
                    } else {
                        e.target.style.backgroundImage = "url(" + DispatchLibPath + "image/call.png)"
                    }
                    break;
                }
                case "control": {
                    if (self.rtclib.target.Type == 5) {
                        return;
                    }
                    
                    self.func_control();
                    break;
                }
                case "scale": {
                    self.func_scale();
                    break;
                }
                case "rotate": {
                    self.func_rotate();
                    break;
                }
                case "record": {
                    self.func_record();
                    break;
                }
                case "photo": {
                    self.func_photo();
                    break;
                }
                case "ptz": {
                    if (self.rtclib.target.Type == 1 ||
                        (self.rtclib.target.Type == 5 && self.rtclib.target.Number.length != 20)) {
                        return;
                    }
                    self.func_ptz();
                    break;
                }
        case "parameter":
          console.log("parameter点击了");
          self.flag_parameter = self.flag_parameter === 0 ? 1 : 0;
          break;

            }
    
        }
    }, false);
    
    this.flag_bMoniterVideo = false;//是否拉取视频 
    this.flag_mute    = 0;  //0-静音 1-放音
    this.flag_call    = 0;  //0-未呼叫 1-呼叫接入中 2-呼叫中 
    this.voip_callID  = 0;  //VOIP CALLID
    this.flag_scale   = 0;  //0-比例显示 1-拉伸
    this.flag_rotate  = 0;  //0-0° 1-90° 2-180° 3-270° 
    this.flag_record  = 0;  //0-未录制 1-录制中
    this.flag_parameter = 1; // 0-隐藏参数 1-展示
    
    
    //远控界面
    this.head_div_control_div = document.createElement('div');
    this.head_div_control_div.style.cssText = `position:absolute;left:${this.head_div_control.style.left}; top:40px;width:${this.div.style.width.split('px')[0] * 0.12}px; height:18%; z-index:10;background:#515a6e;color:#cdcdcd;opacity:0.8;font-size: 14px;line-height:${this.div.style.height.split('px')[0] * 0.18 / 3}px;`; //调节框样式
    this.head_div_control_div.id = "DispatchVideoHeadDiv_" + this.index;
    this.head_div_control_div.style.display = "none";
    this.head_div_control_div.ResolutionFlag = 0;     //分辨率 0-当前 1-QVGA 2-VGA 3-720P 4-1080P
    this.head_div_control_div.CameraFlag = 0;         //摄像头 0-当前 1-后置 2-前置
    this.head_div_control_div.videolib = this;
    this.head_div_control_div.func_close = function() {
        self.head_div_control_div.ResolutionFlag = 0;    
        self.head_div_control_div.childNodes[0].childNodes[1].text = "当前";
        self.head_div_control_div.CameraFlag = 0;
        self.head_div_control_div.childNodes[1].childNodes[1].text = "当前";
        self.head_div_control_div.style.display = "none";
    }
    
    this.div.appendChild(this.head_div_control_div);
    
    var div_node;
    div_node = document.createElement('div');
    this.head_div_control_div.appendChild(div_node);
    
    var a_node;
    a_node = document.createElement('a');
    a_node.text = "分辨率:";
    a_node.style.cssText = "display:inline-block; margin:0px 10px 0px 5px; user-select:none;color:#cdcdcd;font-size: 14px;";
    div_node.appendChild(a_node);
    
    a_node = document.createElement('a');
    a_node.text = "当前";
    a_node.style.cssText = "display:inline-block; margin:0px 10px 0px 5px; user-select:none;color:#cdcdcd;font-size: 14px;";
    div_node.appendChild(a_node);
       
    a_node.addEventListener('mouseover', function(e) {
        e.target.style.color = "white";
    }, false);
    
    a_node.addEventListener('mouseout', function(e) {
        e.target.style.color = "#cdcdcd";
    }, false);
    
    a_node.addEventListener('click', function(e) {
        var head_div_control_div = e.target.parentElement.parentElement;
        head_div_control_div.ResolutionFlag++;
    
        var text = "当前";
        switch (head_div_control_div.ResolutionFlag) {
            case 0:
                text = "当前";
                break;
            case 1:
                text = "QVGA";
                break;
            case 2:
                text = "VGA";
                break;
            case 3:
                text = "720P";
                break;
            case 4:
            default:
                text = "当前";
                head_div_control_div.ResolutionFlag = 0;
                break;
        }
        
        e.target.text = text;
        
    }, false);
    
    div_node = document.createElement('div');
    this.head_div_control_div.appendChild(div_node);
    
    var a_node;
    a_node = document.createElement('a');
    a_node.text = "摄像头:";
    a_node.style.cssText = "display:inline-block; margin:0px 10px 0px 5px; user-select:none;color:#cdcdcd;font-size: 14px;";
    div_node.appendChild(a_node);
    
    a_node = document.createElement('a');
    a_node.text = "当前";
    a_node.style.cssText = "display:inline-block; margin:0px 10px 0px 5px; user-select:none;color:#cdcdcd;font-size: 14px;";
    div_node.appendChild(a_node);
    
    a_node.addEventListener('mouseover', function(e) {
        e.target.style.color = "white";
    }, false);
    
    a_node.addEventListener('mouseout', function(e) {
        e.target.style.color = "#cdcdcd";
    }, false);
    
    a_node.addEventListener('click', function(e) {
        var head_div_control_div = e.target.parentElement.parentElement;
        head_div_control_div.CameraFlag++;
        
        var text = "当前";
        switch (head_div_control_div.CameraFlag) {
            case 0:
                text = "当前";
                break;
            case 1:
                text = "后置";
                break;
            case 2:
                text = "前置";
                break;
            default:
                text = "当前";
                head_div_control_div.CameraFlag = 0;
                break;
        }
        
        e.target.text = text;
    }, false);
    
    div_node = document.createElement('div');
    this.head_div_control_div.appendChild(div_node);
    
    var a_node;
    a_node = document.createElement('a');
    a_node.text = "确认";
    a_node.style.cssText = "display:inline-block; position:absolute; left:calc(50% - 20px); margin:0px 10px 0px 5px; user-select:none;color:#cdcdcd;font-size: 14px;";
    div_node.appendChild(a_node);
    
    a_node.addEventListener('mouseover', function(e) {
        e.target.style.color = "white";
    }, false);
    
    a_node.addEventListener('mouseout', function(e) {
        e.target.style.color = "#cdcdcd";
    }, false);
    
    a_node.addEventListener('click', function(e) {
        var head_div_control_div = e.target.parentElement.parentElement;       
        if (head_div_control_div.CameraFlag || head_div_control_div.ResolutionFlag) {
            if (head_div_control_div.videolib.rtclib &&
                head_div_control_div.videolib.rtclib.target) {
                DispatchCtrlLib.MonitorVideoRemoteControl(head_div_control_div.videolib.rtclib.target.Number, head_div_control_div.ResolutionFlag, head_div_control_div.CameraFlag)
            }            
        }
        head_div_control_div.func_close();
    }, false);
    
    
}

DispatchVideoLib.prototype.FuncRestore = function() {
    if (this.flag_mute) {
        this.func_mute();
    }
    this.flag_mute = 0; 
    
    if (this.flag_call) {
        this.func_call();
    }
    this.flag_call = 0;
      
    if (this.flag_scale) {
        this.setDisplayScale(0);
    }
    this.flag_scale   = 0; 
     
    if (this.flag_rotate) {
        this.setDisplayDegree(0);
    }     
    this.flag_rotate  = 0;  
    
    if (this.flag_record) {
        this.func_record();
    }
    this.flag_record  = 0;  
    if(this.head_div_control_div){
        this.head_div_control_div.func_close();
    }
}

DispatchVideoLib.prototype.Uninit = function() {
    EleResize.off(this.div, div_resize_listener, this);
    this.video.parentNode.removeChild(this.video);
}



DispatchVideoLib.prototype.StartDisplay = function(CallID) {
    this.CallID = CallID;
    this.video.style.objectFit = "contain";

    console.log("DispatchVideoLib_" + this.index + " msgInitPlay " + this.CallID);

    var videolib = this;

    DispatchRtcLib.DisplayVideo(CallID, this);
}

DispatchVideoLib.prototype.StopDisplay = function() {
    if (this.bFull) {
        this.fullscreen();
    }

    this.video.srcObject = null;

    this.CallID = -1;
    this.UserText = "";
    this.clear();
    this.rtclib = null;
    this.flag_bMoniterVideo = false;
    this.FuncRestore();
    if(this.head_div){
        this.head_div.style.display = "none";
    }
}

DispatchVideoLib.prototype.clear = function(msg) {
    this.text_ctx.clearRect(0, 0, this.text_ctx.canvas.width, this.text_ctx.canvas.height);
}


DispatchVideoLib.prototype.fullscreen = function() {


    if (this.bFull) {
        if (document.webkitExitFullscreen) {
            document.webkitExitFullscreen();
        } else if (document.mozCancelFullScreen) {
            document.mozCancelFullScreen();
        } else if (document.msExitFullscreen) {
            document.msExitFullscreen();
        } else {
            console.log("Exit fullscreen doesn't work");
        }
        this.bFull = false;

        this.restore_pic();
    } else {
        if (!this.video.srcObject) {
            return;
        }

        var div = this.div;

        this.save_pic();

        if (div.RequestFullScreen) {
            div.RequestFullScreen();
        } else if (div.webkitRequestFullScreen) {
            var ret = div.webkitRequestFullScreen();//.then( () => console.log("webkitRequestFullScreen done") );
        } else if (div.mozRequestFullScreen) {
            div.mozRequestFullScreen();
        } else if (div.msRequestFullscreen) {
            div.msRequestFullscreen();
        } else {
            console.log("This browser doesn't supporter fullscreen");
        }
        this.bFull = true;
    }
};

DispatchVideoLib.prototype.save_pic = function() {
    this.width_before = this.div.clientWidth;
    this.height_before = this.div.clientHeight;
    console.log("DispatchVideoLib_" + this.index + " save_pic " + this.div.clientWidth + "x" + this.div
        .clientHeight);
};

DispatchVideoLib.prototype.restore_pic = function() {
    this.video.style.width = "" + this.width_before + "px";
    this.video.style.height = "" + this.height_before + "px";
    console.log("DispatchVideoLib_" + this.index + " restore_pic " + this.width_before + "x" + this.height_before);
};

DispatchVideoLib.prototype.setUserText = function(text) {
    this.UserText = text;
};

DispatchVideoLib.prototype.setVideoText = function(codec, fps, bitrate, width, height) {
    this.codec = codec;
    this.fps = fps;
    this.bitrate = Math.round(bitrate);
    this.width = width;
    this.height = height;

    this.text_ctx.clearRect(0, 0, this.text_ctx.canvas.width, this.text_ctx.canvas.height);
    
    function strlen(str){
        var len = 0;
        for (var i=0; i<str.length; i++) { 
         var c = str.charCodeAt(i); 
        //单字节加1 
         if ((c >= 0x0001 && c <= 0x007e) || (0xff60<=c && c<=0xff9f)) { 
           len++; 
         } else { 
          len+=2; 
         } 
        } 
        return len;
    }
    
    //var line1 = "通话中 录制中(24:30)";
    var line1 = "";
    if (this.flag_call == 1) {
        line1 = line1 + "通话接入中 ";
    } else if (this.flag_call == 2) {
        line1 = line1 + "通话中 ";
    }
    
    if (this.flag_record) {
        line1 = line1 + "录制中";
    }
    
    var line2 = this.codec + " " + this.width + "x" + this.height;
    var line3 = this.fps + "fps " + this.bitrate + "kps";
    var line4 = ""
    if (this.rtclib && this.rtclib.target) {
        line4 = this.rtclib.target.Number + " " + this.rtclib.target.Name;
    }

    this.text_ctx.fillText(line1, 300, 0);
    if (this.flag_parameter === 1) {
        this.text_ctx.fillText(line2, 300, 30);
        this.text_ctx.fillText(line3, 300, 60);
    }
    this.text_ctx.fillText(line4, 300, 90);
    // this.text_ctx.fillText(this.fps + "fps " + this.bitrate + "kps", this.text_ctx.canvas.width * 0.85, this
    //     .text_ctx.canvas.height * 0.15 + 30);
    // this.text_ctx.fillText(this.UserText, this.text_ctx.canvas.width * 0.85, this.text_ctx.canvas.height * 0.15 +
    //     60);
};

//设置视频显示模式 0-按比例缩放 1-拉伸
DispatchVideoLib.prototype.setDisplayScale = function(mode) {

    //"contain"		—— 按比例缩放 全部显示 默认
    //"fill"		—— 拉伸
    //"cover" 		—— 按比例缩放 会裁剪
    //"none"		—— 不缩放
    if (mode == 0) {
        this.video.style.objectFit = "contain";
    } else {
        this.video.style.objectFit = "fill";
    }
};

//设置视频角度 0-0° 1-顺时针90° 2-顺时针180° 3-顺时针270°
DispatchVideoLib.prototype.setDisplayDegree = function(degree) {
    if (degree < 0 || degree > 3) {
        return;
    }

    var rotate = 90 * parseInt(degree);

    this.video.style.transform = "rotate(" + rotate + "deg)";
        
    if (degree == 1 || degree == 3) {
        this.video.style.left = "" + Math.abs(this.div.clientHeight-this.div.clientWidth)/2 + "px";
        this.video.style.top = "-" + Math.abs(this.div.clientHeight-this.div.clientWidth)/2 + "px";
        this.video.style.width = "" + this.div.clientHeight + "px";
        this.video.style.height = "" + this.div.clientWidth + "px";
    } else {
        this.video.style.left = "0px";
        this.video.style.top = "0px";
        this.video.style.width = "" + this.div.clientWidth + "px";
        this.video.style.height = "" + this.div.clientHeight + "px";
    }
};

DispatchVideoLib.prototype.func_close = function() {
    console.log("DispatchVideoLib_" + this.index + " func_close");
    if (this.rtclib && this.rtclib.CallID && this.flag_bMoniterVideo) {
        DispatchCtrlLib.MonitorVideoHangup(this.rtclib.CallID);
    }
}

DispatchVideoLib.prototype.func_forward = function() {
    console.log("DispatchVideoLib_" + this.index + " func_forward");
    if (!this.video.srcObject || !this.flag_bMoniterVideo) {
       return;
    }
    
    //回调
    if (DispatchCtrlLib.cb_forward) {
        DispatchCtrlLib.cb_forward(this.rtclib.target.Number, this.rtclib.target.Type, this.rtclib.CallID);
    }
}

DispatchVideoLib.prototype.func_mute = function() {
    console.log("DispatchVideoLib_" + this.index + " func_mute");
    if (!this.video.srcObject || !this.flag_bMoniterVideo) {
        return 0;
    }

    this.flag_mute = 1 - this.flag_mute;
    this.video.volume = this.flag_mute;
    
    return this.flag_mute;
}

DispatchVideoLib.prototype.func_call = function() {
    console.log("DispatchVideoLib_" + this.index + " func_call");
    if (!this.video.srcObject || !this.flag_bMoniterVideo) {
        return 0;
    }
    
    if (this.flag_call) {
        //挂断
        DispatchCtrlLib.VoipHangupCall(this.voip_callID);
        
        this.flag_call = 0;
        this.voip_callID = 0;
        DispatchVideoLib.VoipCallID[CallID] = null;
    } else {
        var CallID = DispatchCtrlLib.VoipMakeAudioCall(this.rtclib.target.Number);
        if (CallID > 0) {
            this.voip_callID = CallID;
            DispatchVideoLib.VoipCallID[CallID] = this;
        }
        
        this.flag_call = 1;
    }
    
    return this.flag_call;
}

DispatchVideoLib.func_call_onStatus = function(CallID, status) {
    if (DispatchVideoLib.VoipCallID[CallID]) {
        var videolib = DispatchVideoLib.VoipCallID[CallID];
        if (status == 2) {
            //呼叫成功
            videolib.flag_call = 2;
        } else if (status > 2) {
            //呼叫失败、挂断
            videolib.flag_call = 0;
            videolib.voip_callID = 0;
            DispatchVideoLib.VoipCallID[CallID] = null;
            videolib.head_div_call.style.backgroundImage = "url(" + DispatchLibPath + "image/call.png)"
        }
        
    }    
}

DispatchVideoLib.prototype.func_control = function() {
    console.log("DispatchVideoLib_" + this.index + " func_control");
    if (!this.video.srcObject || !this.flag_bMoniterVideo) {
      return;
    }
    
    if (this.head_div_control_div.style.display == "block") {
        this.head_div_control_div.func_close();
    } else {
        this.head_div_control_div.style.display = "block"
        this.head_div_control_div.style.width = this.div.clientWidth / 5 + "px";
        this.head_div_control_div.style.top = this.div.clientHeight * 0.1 + 'px';
        for (let item of this.head_div_control_div.childNodes) {
            item.style.cssText =
                `line-height:${this.head_div_control_div.clientHeight / 3 }px;display:flex;justify-content: center;`; //调节框样式
            for (let items of item.childNodes) {
                items.style.cssText = `transform:scale(${this.div.clientHeight / 450});color:#fff;display:inline-block;opacity:0.8;white-space: nowrap;flex:1;width:50%;`; //调节框样式
            }
        }
    }
}

DispatchVideoLib.prototype.func_scale = function() {
    console.log("DispatchVideoLib_" + this.index + " func_scale");
    if (!this.video.srcObject || !this.flag_bMoniterVideo) {
       return;
    }
    
    this.flag_scale = 1 - this.flag_scale;
    this.setDisplayScale(this.flag_scale);
}

DispatchVideoLib.prototype.func_rotate = function() {
    console.log("DispatchVideoLib_" + this.index + " func_rotate");
    if (!this.video.srcObject || !this.flag_bMoniterVideo) {
       return;
    }
    
    this.flag_rotate++;
    if (this.flag_rotate >= 4) {
        this.flag_rotate = 0;
    }
    
    this.setDisplayDegree(this.flag_rotate);
}

DispatchVideoLib.currentTime = function() {
    
    function add0(m) {
        return m < 10 ? '0' + m : m
    }
    
    var time = new Date();
    var y = time.getFullYear();
    var m = time.getMonth() + 1;
    var d = time.getDate();
    var h = time.getHours();
    var mm = time.getMinutes();
    var s = time.getSeconds();
    return y + '-' + add0(m) + '-' + add0(d) + 'T' + add0(h) + '-' + add0(mm) + '-' + add0(s);
}

DispatchVideoLib.prototype.func_record = function() {
    console.log("DispatchVideoLib_" + this.index + " func_record");
    if (!this.video.srcObject || !this.flag_bMoniterVideo) {
        return;
    }
    
    //待实现
    if (this.flag_record) {
        //结束
        DispatchRtcLib.StopRecordStream(this.rtclib.CallID);
    } else {
        //开始
        DispatchRtcLib.StartRecordStream(this.rtclib.CallID);
    }   
    this.flag_record = 1 - this.flag_record;
    
    

}

DispatchVideoLib.prototype.func_photo = function() {
    console.log("DispatchVideoLib_" + this.index + " func_photo");
    if (!this.video.srcObject || !this.flag_bMoniterVideo) {
       return;
    }
    
    //待实现
    function savePic(fileName, video_id) {
    	var fileType = "png";  // 如果文件名中没有带后缀,默认使用png
    	switch (fileName) {  // 判断保存的图片格式
    		case fileName.indexOf("png") > -1:
    			fileType = "png";
    			break;
    		case fileName.indexOf("jpg") > -1:
    			fileType = "jpg";
    			break;
    	
    		case fileName.indexOf("jpeg") > -1:
    			fileType = "jpeg";
    			break;
    		case fileName.indexOf("bmp") > -1:
    			fileType = "bmp";
    			break;
    		case fileName.indexOf("gif") > -1:
    			fileType = "gif";
    			break;
    		default:
    			fileType = "png";
    			break;

        }
        var video = document.querySelector("#"+video_id);
          // 找到需要截图的video标签
        if (!video) {
             video = interface_func.getSelectorByDiv("#"+video_id);
        }

        var canvas = window.canvas = document.createElement("canvas");
        canvas.width = video.videoWidth;
        canvas.height = video.videoHeight; 
        canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);  // 图片大小和视频分辨率一致
        var strDataURL = canvas.toDataURL("image/" + fileType);   // canvas中video中取一帧图片并转成dataURL
        var arr = strDataURL.split(','),
            mime = arr[0].match(/:(.*?);/)[1],
            bstr = atob(arr[1]),
            n = bstr.length,
            u8arr = new Uint8Array(n);
        while (n--) {
            u8arr[n] = bstr.charCodeAt(n);
        }
        var blob = new Blob([u8arr], {
            type: mime
        });
        var url = window.URL.createObjectURL(blob);
        var a = document.createElement('a');  
        a.style.display = 'none';
        a.href = url;
        a.download = fileName;
        document.body.appendChild(a);
        a.click();
        setTimeout(function () {
            document.body.removeChild(a);
            window.URL.revokeObjectURL(url);
        }, 1000);
    
    }
    
    var filename = this.rtclib.target.Number + "-[" + DispatchVideoLib.currentTime() + "].png";
    savePic(filename, this.video.id);
}

DispatchVideoLib.prototype.func_ptz = function() {
    console.log("DispatchVideoLib_" + this.index + " func_ptz");
    if (!this.video.srcObject || !this.flag_bMoniterVideo) {
       return;
    }
    
    //回调
    if (DispatchCtrlLib.cb_ptz) {
        DispatchCtrlLib.cb_ptz(this.rtclib.target.Number, this.rtclib.target.Type, this.rtclib.CallID);
    }
}