我想寫一個概念驗證,以顯示第三方硬件設備與「可視電話「功能可以在同一局域網上調用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」作爲編解碼器之一返回。此時,當我從第三方設備撥打我的概念證明時,仍然沒有視頻。
其他的事情我已經試過:
- 操縱Linphone中的核心參數。 (videoPort,videoPolicy,...)
- 以不同的方式接受呼叫。使用acceptCall,acceptCallWithParams,acceptEarlyMedia然後acceptCall。
我注意到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 \
查看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/如果您有任何關於改善此問題的指示,請讓我知道。