2015-05-21 103 views
1

我想寫一個概念驗證,以顯示第三方硬件設備與「可視電話「功能可以在同一局域網上調用Web應用程序。在設備製造商的建議下,我使用linphone。從第三方設備(具有「可視電話」功能)向Linphone(桌面)呼叫時顯示視頻,同時呼叫Linphone(瀏覽器)不

首先,Linphone for Windows完美地工作(在視頻編解碼器下啓用H263後)因此,爲了澄清,第三方設備使用H263視頻編解碼器。

Linphone 爲瀏覽器使用我的概念驗證,顯示從linphone調用的視頻爲窗口,但不是從第三部分設備調用時顯示。

第一個問題

後有的通過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(使用'local:///test.linphonerc'格式的URI到文件);這並沒有導致錯誤,但創建了新文件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 for windows和使用來自第三方設備的linphone瀏覽器調用概念驗證的區別。

    4。1當Linphone(瀏覽器)回覆「100 Trying」時,Linphone(Windows)以「101 Dialog Establishment」回覆SIP Invite

    4.2當按下「answer call」按鈕時,Linphone包括SDP媒體描述的「200 OK」「Media Description,name and address(m):video 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」沒有視頻媒體屬性。

因爲有人想看代碼。

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中當視頻顯示C將我使用Linphone作爲瀏覽器的概念證明分開了?

這是我的第一個問題https://stackoverflow.com/如果您有任何關於改善此問題的指示,請讓我知道。

回答

0

今天早上我發佈了與linphone開發者郵件列表相同的問題。我收到了一個答覆,在實施時解決了我的問題。

鏈接到郵件列表的答覆。http://lists.gnu.org/archive/html/linphone-developers/2015-05/msg00086.html

基本上,現在插件已經支持H263,我必須啓用編解碼器。

在我的概念驗證中啓用H263編解碼器。

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