首页 文章

从第三方设备(具有“可视电话”功能)呼叫到Linphone(桌面)显示视频,同时呼叫Linphone(浏览器)不

提问于
浏览
1

我正在尝试编写一个概念证明,以证明具有“可视电话”功能的第三方硬件设备可以在同一LAN上调用Web应用程序 . 根据设备制造商的建议,我正在使用linphone .

首先,Linphone for Windows完美运行 (After enabling H263 under video codecs) 所以为了澄清,第三方设备使用H263视频编解码器 .

Linphone for the browser 使用我的概念验证,在从linphone for windows调用时显示视频,但在从第3部分设备调用时则不显示 .

First Problem

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

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

Other things I've tried:

  • Manipulate linphone core parameters . (videoPort,videoPolicy,...)

  • Accept calls in different ways . 使用acceptCall,acceptCallWithParams,acceptEarlyMedia,然后是acceptCall .

  • 我注意到linphone for windows将其配置导出到linphonerc文件 . Tried to initialise the linphone core using the same parameters an linphone for windows

3.1尝试使用core.init('URI to file using format format:/// C:/test.linphonerc');这导致无效的URI错误 .

3.2尝试使用core.init('URI to file using the format: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 \

  • Looking at wireshark logs 看到调用linphone for windows和使用linphone浏览器从第三方设备调用概念证明之间的区别 .

4.1 Linphone(Windows)使用“101 Dialog Establishment”回复SIP Invite,而Linphone(浏览器)回复“100 Trying”

4.2按下"answer call"按钮时,Linphone(Windows)回复"200 OK",其中包含SDP媒体描述 "Media Description, name and address (m): video 9078 RTP/AVP 34" ,而Linphone(浏览器)回复 "200 OK" with a media description "Media Description, name and address (m): video 0 RTP/AVP 0"

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

有人希望看到代码 .

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;                    

}

Any idea why the video is displaying when calling Linphone for windows but not when calling my proof of concept that makes use of Linphone for browser?

这是我在https://stackoverflow.com/的第一个问题 . 如果你有任何关于改进这个问题的建议,请告诉我 .

1 回答

  • 0

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

    Link to the mailing list with the reply. http://lists.gnu.org/archive/html/linphone-developers/2015-05/msg00086.html

    Basically, now that the plugin had support for H263, I had to enable the codec.

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

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

相关问题