从第三方设备(使用"视频电话"功能)拨打到Linphone(桌面),在拨打Linphone(浏览器)时显示视频

时间:2015-05-21 13:50:59

标签: sip voip linphone

我试图写一个概念证明来证明第三方硬件设备带有" Videophone"功能可以在同一LAN上调用Web应用程序。根据设备制造商的建议,我使用了linphone。

首先,Linphone for Windows完美运行(在视频编解码器下启用H263后)为了澄清,第三方设备使用H263视频编解码器。

Linphone 用于浏览器使用我的概念验证,在从linphone for windows调用时显示视频,但在从第3部分设备调用时则不显示。

第一个问题

经过一些挖掘https://www.linphone.org/docs/linphone-web/external-LinphoneCore.html并查看" core.videoCodecs"的结果。我注意到 返回的唯一视频编解码器是VP8。

经过多次挖掘后,x-linphone-web插件默认不包含所有编解码器。所以我重新编译了插件,支持" H263"启用。 " core.videoCodecs" 现在返回" H263"作为编解码器之一。此时,当我从第三方设备拨打我的概念证据时,仍然没有视频。

我尝过的其他事情:

  1. 操纵linphone核心参数(videoPort,videoPolicy,...)
  2. 以不同方式接听电话。使用acceptCall,acceptCallWithParams,acceptEarlyMedia,然后是acceptCall。
  3. 我注意到linphone for windows将其配置导出到linphonerc文件。 尝试使用与linphone相同的参数

    来初始化linphone核心

    3.1尝试使用core.init(' URI使用格式文件:/// C:/test.linphonerc');这导致了无效的URI错误。

    3.2尝试使用core.init(' URI使用格式' local:///test.linphonerc');这不会导致错误,但会创建新文件C:\ Users *** \ AppData \ Local \ Temp \ linphone-web \ 8d89-653a-c164-9d79 \ test.linphonerc

    3.3尝试使用newLpConfig(' local:///test.linphonerc')在代码中创建文件,然后使用core.init初始化(' local:///test.linphonerc' )。 newLpConfig写入C:\ Users *** \ AppData \ Local \ Temp \ linphone-web \中的新文件夹,init尝试从C:\ Users *** \ AppData \ Local \ Temp \中的另一个新文件夹中读取linphone-web \

  4. 查看wireshark日志,了解使用linphone调用linphone和使用第三方设备的linphone浏览器调用概念验证之间的区别。

    4.1 Linphone(Windows)使用" 101对话建立"回复SIP邀请。而Linphone(浏览器)使用" 100 Trying"

    回复

    4.2当"接听电话"按下按钮,Linphone(Windows)回复" 200 OK"其中包括SDP媒体描述"媒体描述,姓名和地址(m):视频9078 RTP / AVP 34" ,而Linphone(浏览器)回复" 200 OK"媒体描述"媒体描述,姓名和地址(m):视频0 RTP / AVP 0"

    4.3在回答时,Linphone(Windows)回复" 200 OK" ,其中包含SDP媒体属性"媒体属性(a):rtpmap: 34 H263 / 90000" ,而Linphone(浏览器)使用" 200 OK" 回复,但没有视频媒体属性。

  5. 有人希望看到代码。

    linphone.html

    <html>
    
        <head>  
            <script type="text/javascript" src="linphone.js"></script>  
        </head>
    
        <body onload="initLinphoneCore()" style="background:#000000; font-family : Arial; font-size: 12;">
    
            <object id="core" type="application/x-linphone-web" width="0" height="0">
                <param name="onload" value='initLinphoneCore()'>
            </object>
    
            <div style="width : 640px; height : 480px; position : absolute; top : 30%; left : 30%; right : 30%; background : #EEEEEE;">                         
    
                <div id="status" style="position:relative; height:30px; font-size:18px;top:0px; background:#888888; color:#FFFFFF;text-align: center;"></div>
                <div id="videoContainer1" style="position:relative; top: 25%; left:25%;" ></div>
    
                <div style="position:absolute; width : 100%; height:30px; font-size:18px; bottom:0px; text-align: right; background : #333333;">
                    <input type="button" OnClick="answerCall()" value="Answer Call">
                </div>      
    
            </div>      
    
        </body> 
    </html>
    

    linphone.js

    var CallStatusIdle = 0;
    var CallStatusIncomingReceived = 1;
    var CallStatusConnected = 6;
    var CallStatusStreamsRunning = 7;
    var CallStatusError = 12;
    var CallStatusEnd = 13;
    
    var currentCall;
    var currentCallStatus = CallStatusIdle;
    
    //-------------------------------------------------------------------------------------------------------
    // Name : addEvent
    // Desc : Register to be notified of an event.
    // param obj :
    // param name :
    // param func :
    //-------------------------------------------------------------------------------------------------------
    function addEvent(obj, name, func) 
    {
        if (obj.attachEvent) {
            obj.attachEvent("on"+name, func);
        } else {
            obj.addEventListener(name, func, false); 
        }
    }   
    
    //-------------------------------------------------------------------------------------------------------
    // Name : updateStatus
    // Desc : Function that display some text in a html element.
    // param id :
    // param value :
    // param bgColour:
    // param fgColour:
    //-------------------------------------------------------------------------------------------------------
    function updateStatus(id, value, bgColour, fgColour)
    {
        document.getElementById(id).innerHTML= value;
        document.getElementById(id).style.background = bgColour;
        document.getElementById(id).style.color = fgColour;
    }
    
    //-------------------------------------------------------------------------------------------------------
    // Name : getCore
    // Desc : Get a reference to linphone core.
    //-------------------------------------------------------------------------------------------------------
    function getCore()
    {
        return document.getElementById('core');
    }                       
    //-------------------------------------------------------------------------------------------------------
    // Title : initLinphoneCore.
    // Desc : Initialise the linphone core.
    //-------------------------------------------------------------------------------------------------------
    function initLinphoneCore()
    {       
        var core = getCore();
    
        addEvent(core, "callStateChanged", onCallStateChanged);
    
        /*
            Initial attempt was to initialise using core.init();
            Haven't managed to get that working so attempt "n" is to specify the configuration as exported using
            the windows desktop version of linphone.
        */
    
    
        var config = core.newLpConfig("local:///config.linphonerc");
        config.cleanSection("rtp");
        config.setString('rtp', 'download_ptime', "0");
        config.setString('rtp', 'audio_rtp_port', "7078");
        config.setString('rtp', 'video_rtp_port', "9078");
        config.setString('rtp', 'audio_jitt_comp', "60");
        config.setString('rtp', 'video_jitt_comp', "60");
        config.setString('rtp', 'nortp_timeout', "30");
        config.setString('rtp', 'audio_adaptive_jitt_comp_enabled', "1");
        config.setString('rtp', 'video_adaptive_jitt_comp_enabled', "1");
        config.setString('rtp', 'audio_dscp', "0x2e");
        config.setString('rtp', 'video_dscp', "0x2e");              
        config.cleanSection("sip");
        config.setString('sip', 'media_encryption', "none");
        config.setString('sip', 'default_proxy', "-1");
        config.setString('sip', 'sip_port', "5062");
        config.setString('sip', 'sip_tcp_port', "0");
        config.setString('sip', 'sip_tls_port', "0");
        config.setString('sip', 'use_info', "1");
        config.setString('sip', 'guess_hostname', "1");
        config.setString('sip', 'inc_timeout', "30");
        config.setString('sip', 'in_call_timeout', "0");
        config.setString('sip', 'delayed_timeout', "4");
        config.setString('sip', 'use_ipv6', "0");
        config.setString('sip', 'register_only_when_network_is_up', "1");
        config.setString('sip', 'register_only_when_upnp_is_ok', "1");
        config.setString('sip', 'dscp', "0x1a");
        config.cleanSection("video");
        config.setString('video', 'display', "1");
        config.setString('video', 'capture', "1");
        config.setString('video', 'automatically_initiate', "1");
        config.setString('video', 'automatically_accept', "1");
        config.setString('video', 'show_local', "0");
        config.setString('video', 'self_view', "0");
        config.setString('video', 'size', "svga");
        // config.setString('video', 'device', "Removed for SO Question");  
        config.cleanSection("net");
        config.setString('net', 'download_bw', "0");
        config.setString('net', 'upload_bw', "0");
        config.setString('net', 'adaptive_rate_control', "1");
        config.setString('net', 'firewall_policy', "0");
        config.setString('net', 'mtu', "1300");     
        config.cleanSection("sound");
        // config.setString('sound', 'playback_dev_id', "Removed for SO Question");
        // config.setString('sound', 'ringer_dev_id', "Removed for SO Question");
        // config.setString('sound', 'capture_dev_id', "Removed for SO Question");
        config.setString('sound', 'echocancellation', "0");
        config.setString('sound', 'mic_gain_db', "0.000000");
        config.setString('sound', 'local_ring', "C:\Program Files (x86)\Linphone\share\sounds\linphone\rings\oldphone.wav");
        config.setString('sound', 'playback_gain_db', "0.000000");  
        config.cleanSection("video_codec_0");
        config.setString('video_codec_0', 'mime', "H263");
        config.setString('video_codec_0', 'rate', "90000");
        config.setString('video_codec_0', 'enabled', "1");
        config.setString('video_codec_0', 'recv_fmtp', "");     
        config.cleanSection("video_codec_1");
        config.setString('video_codec_1', 'mime', "VP8");
        config.setString('video_codec_1', 'rate', "90000");
        config.setString('video_codec_1', 'enabled', "1");      
        config.cleanSection("video_codec_2");
        config.setString('video_codec_2', 'mime', "H263-1998");
        config.setString('video_codec_2', 'rate', "90000");
        config.setString('video_codec_2', 'enabled', "1");
        config.setString('video_codec_2', 'recv_fmtp', "1;QCIF=1");                     
    
        // Write configuration file:
        var configFileSynch = config.sync();
        if ( configFileSynch !== 0 ) {      
            console.log( 'Failed to write configuration file.' );
            return;     
        }
    
        // Initialise core:
        var coreInit = core.init( 'local:///config.linphonerc' );
        if ( coreInit !== 0 ) 
        {
            console.log( 'Failed to initialise core.' );
            return;
        }
    
        // Setup core logging.
        core.logHandler = function( level, message ) 
        {
            window.console.log(message);
        }   
    
        // Start main loop:
        core.iterateEnabled = true; 
    
        updateStatus ( 'status', 'Linphone Core Initialised', "#888888", '#FFFFFF');
    }
    
    //-------------------------------------------------------------------------------------------------------
    // Name : onCallStateChanged
    // Desc : On notification of call status, decide on the logic to perform.
    // param event : The event that triggered all of this.
    // param call : The call object that had its state changed.
    // param state : The new state of the call.
    // param message : A description of the call state.
    //-------------------------------------------------------------------------------------------------------
    function onCallStateChanged(event, call, state, message)
    {
        try {
    
            // Keep a reference for later use:
            currentCall = call;
            currentCallStatus = state;
    
            // Log new call state:
            window.console.log('Call state changed : ' + state);
    
            if ( CallStatusIncomingReceived === state ) 
            {           
                updateStatus('status', message, "#0000AA", '#FFFFFF');                      
                document.getElementById('videoContainer1').innerHTML=  "<object id='remoteVideo1' type='application/x-linphone-web-video' style='display: inline; width: 320px; height: 240px; position:absolute'><param name='onload' value='onLoadVideo1' /><param name='magic' value='1' /></object>";                       
            }               
            else if ( CallStatusConnected === state )
            {
                updateStatus('status', message, "#000000", '#FFFFFF');
            }       
            else if( CallStatusStreamsRunning === state )
            {       
                updateStatus('status', message, "#00AA00", '#FFFFFF');                          
            }
            else if( CallStatusEnd === state )
            {   
                updateStatus('status', message, "#000000", '#FFFFFF');      
            }
            else if( CallStatusError === state ) 
            {
                updateStatus('status', message, "#440000", '#FFFFFF');
            }                       
    
        } 
        catch (err)
        {
            var msg = "There was an error during call status change : " + err.message;
            console.log ( msg );
            updateStatus ( 'status', msg, "#000000", '#FFFFFF');
        }
    }
    
    //-------------------------------------------------------------------------------------------------------
    // Name : answerCall
    // Desc : User clicked button to answer call.
    //-------------------------------------------------------------------------------------------------------
    function answerCall() 
    {
        try {
    
            core.acceptCall ( currentCall) ;
        } 
        catch (err) 
        {
            var msg = "There was an error while answering call : " + err.message;
            console.log ( msg );
            updateStatus ( 'status', msg, "#000000", '#FFFFFF');                
        }
    }       
    
    //-------------------------------------------------------------------------------------------------------
    // Name : onLoadVideo1
    // Desc : Initialise video parameters after x-linphone-web-video injected and loaded.
    //-------------------------------------------------------------------------------------------------------       
    function onLoadVideo1() {   
        var v = document.getElementById('remoteVideo1');
        core.videoPolicy.automaticallyAccept = true;        
        core.videoDisplayEnabled = true; 
        core.nativeVideoWindowId = v.window;                    
    
    }
    

    在调用Linphone for Windows时显示视频显示的原因,而不是在调用使用Linphone浏览器的概念验证时

    这是我关于https://stackoverflow.com/的第一个问题。如果您对改进此问题有任何指示,请告诉我。

1 个答案:

答案 0 :(得分:0)

今天早上我在linphone开发者邮件列表中发布了同样的问题。我收到了回复,实施时解决了我的问题。

通过回复链接到邮件列表。 http://lists.gnu.org/archive/html/linphone-developers/2015-05/msg00086.html

基本上,既然插件支持H263,我必须启用编解码器。

在我的概念验证中启用H263编解码器。

core.enablePayloadType ( core.videoCodecs[2], true );