原始碼tryit-jssip/lib下是一個React編寫的使用了jssip的Demo
組態檔:settingsManager.js
穿透的iceServers得在這裏面設定,沒法在網頁
視訊:this._ua.call(uri,{裏面設定video爲true}
元件結構:
Login
Settings//設定sip設定
App
Phone //主要與SIP有關的元件
Session//通話中可暫停|恢復|掛斷
Incoming//接聽和拒接電話
Dialer //輸入號碼打電話
sounds.json//Base64格式的來電聲|等待聲|等
SIPML5 架構
2.29 編譯sip原始碼
webrtc2sip(相當於Asterisk):官方原始碼介紹//https://www.doubango.org/webrtc2sip/technical-guide-1.0.pdf
sipml5:遵循WebSocket協定作爲對談發起協定:
WebSockets-> 星號伺服器(傳遞sip信號)
WebRTC->(ICE(STUN)->UDP)-> 星號伺服器(WebRTC需要ICE)(傳遞語音等)
enable webrtc breaker勾選框的作用:作爲一個sip協定頭參數被傳到伺服器,伺服器就知道它要用breaker了
打斷點就在new websocket 的幾個監聽裏面打就好了
3.31 瀏覽器音訊視訊方案列出,核心程式碼註釋
4.31 傳輸到伺服器,伺服器怎麼對接,核心程式碼註釋
Asterisk 是第一套以開放原始碼軟體實現的 使用者交換機 (PBX) 系統,安裝FreePBX,這是基於Asterisk的發行版,它通過WebSocket支援SIP
IAX//Asterisk 內部交換協定
FreePBX == Asterisk
FusionPBX == FreeSWITCH
網路通訊服務提供商(ITSP)
PSTN//( Public Switched Telephone Network )定義:公共交換電話網路,一種常用舊式電話系統,即我們日常生活中常用的電話網
//PSTN 通過採用SIP協定作爲傳輸語音數據包的協定變成VoIP電話(因特網語音)
SSL(安全Sockets層)在標準化道路上最終成爲TLS(傳輸層安全協定) //用於在兩個通訊應用程式之間提供保密性和數據完整性。
DTLS// D即數據包, 擴充套件了TLS以支援UDP安全
SSH//安全外殼Shell協定
SRTP//:安全的-實時傳輸協定
SMTP//:簡單-郵件傳輸協定
SIP//(對談發起協定)用於建立,修改和終止包括視訊,語音,線上遊戲和虛擬現實等互動式對談。SIP是一項基於文字的信令協定
SIP(對談發起協定)和WebRTC(更安全)都是VoIP的方法,因爲它們既代表實時通訊,又希望通過IP網路(使用相同的標準/編解碼器)發送語音(和視訊)。
WebRTC:Real-Time Communication網頁即時通訊, 是一個API。
//最新的WebRTC要麼用localhost存取,如果要用IP存取,則只能用https協定進行存取, 架構:https://s3.ap-northeast-1.wasabisys.com/img.tw511.com/202008/webrtc_architecture5mh13d3xapw.png
WebSocket是WebRTC的基礎,WebSocket爲WebRTC負責用戶端到伺服器端的數據轉發,
WebSockets需要SERVER,它基於發佈/訂閱模式,可以在此模式中來回發送原始數據,預設情況下不需要任何特殊的數據處理。
WebSocket可以用來傳遞sip信令,而WebRTC用來實時傳輸語音視訊流
相比之下,WebRTC已經有許多功能可用於處理音訊/視訊流以及帶有數據通道的原始數據,WebRTC駐留在使用者的瀏覽器中,不需要其他軟體即可執行
WebRTC使用RTCPeerConnection在瀏覽器之間傳輸流數據,只負責傳輸,不負責協定(Signaling)
//可以選擇 SIP 協定(Signaling),所以WebRTC不需要使用SIP,它可以與其他協定一起使用,也可以完全不使用。
如 用SIP做Signaling 有:
1 對談控制訊息:用來初始化或者關閉通訊和報告錯誤(SDP)
RTCSessionDescription 物件是符合SDP規格的序列號二進制物件
描述了什麼樣的解碼器合解析度可以被我的瀏覽器支援和瀏覽器想要什麼樣的數據//程式碼中是Description
2 網路設定:我面向外部世界的IP地址合埠 (ICE)
ICE:互動連線建立(Interactive Connectivity Establishment ) 爲了通過對方暴露的外網埠去獲取對方的內網埠, ICE利用STUN,再不行就用TURN
STUN(Session Traversal Utilities for NAT|NAT對談穿越程式) 你想存取對方的真實埠,但是對方只暴露了外網埠,STUN告訴你對方的真實埠
//被用來在兩個同時處於NAT路由器之後的主機之間建立UDP通訊
TURN(Traversal Using Relay NAT|使用中繼進行遍歷NAT) 比STUN更好//預先得到公網地址(TURNServer上的地址)之間發到該地址
//程式碼中:Offer是應答
JSEP(JS對談建立協定): 描述了WebRTC-API 用SDP建立對談連線的offer/answer架構
SIP不需要WebRTC,它可以單獨執行,也可以通過使用其他協定(例如實時傳輸協定)
WebSocket的SIP子協定: 爲SIP實體之間的可靠傳輸機制 機製
SIP藉助:SDP(對談描述協定)來描述對談和RTP(實時傳輸協定)
SIP FSM(有限狀態機): sip狀態的流轉圖
一、SIP數位對講系統框架拓撲
因爲終端裝置大多不在一個網段,互相之間是不可見的,所以需要一個公網的中轉伺服器來轉發,這種網路結
構也叫「背靠背」網路模型,需要中轉,也就涉及到終端上報自己的資訊給伺服器,所以需要註冊的機制 機製。
SIP數位對講系統實際就是一個VoIP(Voice over IP)網路電話平臺, 因爲暫時不需要接入運營商,所以我們僅僅討論
終端的具體實現和伺服器的定製開發。
二、SIP數位對講系統終端與伺服器之間的互動
終端和伺服器之間的互動一般情況下是由信令和負載兩個通道來完成,信令負責接入和管控負載。
1. SIP協定
常用的請求方法:INVITE,ACK,BYE,CANCEL,OPTIONS,REGISTER,PRACK,SUBSCRIBE,NOTIFY,
PUBLISH,INFO,REFER,MESSAGE,UPDATE
我們的對講應用只用到了註冊,應答,掛斷,拒接和狀態更新
協定具體欄位細節可以檢視wiki
https://en.wikipedia.org/wiki/List_of_SIP_request_methods
2. SIP信令互動流程
1)註冊
Bob SIP Server
| |
| REGISTER F1 |
|------------------------------>|
| 401 Unauthorized F2 |
|<------------------------------|
| REGISTER F3 |
|------------------------------>|
| 200 OK F4 |
|<------------------------------|
| |
2)對等呼叫(同一網段不需要通過伺服器)
Alice Bob
| |
| INVITE F1 |
|----------------------->|
| 180 Ringing F2 |
|<-----------------------|
| |
| 200 OK F3 |
|<-----------------------|
| ACK F4 |
|----------------------->|
| Both Way RTP Media |
|<======================>|
| |
| BYE F5 |
|<-----------------------|
| 200 OK F6 |
|----------------------->|
| |
3)語音會議模式呼叫
User A Proxy User B
| | |
| INVITE F1 | |
|------------------>| |
| | INVITE F2 |
| (100 Trying) F3 |---------------------->|
|<------------------| |
| | 200 OK F4 |
| 200 OK F5 |<----------------------|
|<------------------| |
| | |
| ACK F6 | |
|------------------>| ACK F7 |
| |---------------------->|
| | |
| RTP Both Ways - Deposit Msg for B |
|<-m-m-m-m-m-m-m-m-m-m-m-m-m-m-m-m-m-m-m-m->|
| | |
| BYE F8 | |
|------------------>| BYE F9 |
| |---------------------->|
| | |
| | 200 OK F10 |
| |<----------------------|
| 200 OK F11 | |
|<------------------| |
| | |
備註:對等模式和語音會議模式的區別是:
會議模式的情況下,中轉伺服器會對終端裝置上傳的語音數據進行混音,而對等模式則是伺服器直接轉發。
三、SIP終端的具體實現
SIP終端應用實際是個媒體網路代理,包含了用戶端和伺服器端,
互相請求和互相提供服務。
1. 信令互動的實現
參考開源exosip2協定棧的help文件
1)註冊
libexosip2-5.1.0/tools/sip_reg.c
2)撥號
libexosip2-5.1.0/help/doxygen/ht0-initialize.dox
libexosip2-5.1.0/help/doxygen/ht1-callcontrol.dox
libexosip2-5.1.0/help/doxygen/ht2-registration.dox
2. 負載通道的實現
1)主要是全雙工6個操作回圈處理
語音採集--->語音編碼--->rtp發送
rtp接受--->語音解碼---->語音播放
2)用一個範例圖來說明更直觀
Audio Encode/Decode && conference bridge
https://trac.pjsip.org/repos/wiki/media-flow?from=groupmessage
3)rtp收發參考設計
jrtplib-3.11.1/examples/example1.c
4)綜合實現參考
intercom/src/conference.cpp
3. 對講終端應用範例
除了我們定製的intercom應用,建議嵌入式相關人員熟悉開源的pjsip二次開發,因爲這個非常完整,輕量級,
而且架構設計得非常好。
四、 SIP伺服器的定製
1. 初步應用
1)安裝freeswitch
https://freeswitch.org/confluence/display/FREESWITCH/CentOS+7
2)設定NAT
vi conf/sip_profiles/internal.xml
param name="ext-rtp-ip" value="auto-nat" #改成外網IP
param name="ext-sip-ip" value="auto-nat" #改成外網IP
通過以上步驟即可使用預設設定的服務,預設支援的編碼格式
2. 深度定製
雖然freeswitch是一個強大的SIP通訊平臺,但是其媒體處理能力有限,所以需要整合ffmpeg,webrtc之類的外
部庫來處理,整合細節可以檢視官網手冊。
1)模組定製
freeswitch/src/mod
2)通訊能力
freeswitch本身SIP通訊夠用,SIP以外的通訊協定也可以以模組的形式新增
3)媒體能力
ffmpeg是最合適的,花一些精力專研是有必要的
這裏freeswitch服務定製只是初步說明了下,具體根據需求來新增,更重要的還是通訊和媒體基礎,需要大量的
精力去偵錯。
四、基礎常識拓展
1. 媒體數據的處理(串流媒體)
1)時間戳以及時間戳的變換
一般情況下,時間戳是用來控制節奏的,靜態的數據,時間戳完全就是一個普通屬性。
a.音訊流時間戳
eg: samplerate = 8k fps = 25
每個畫素點的時間粒度 1000ms/8k = 1/8(ms)
每幀的畫素點(8bit) = 8k / 25 = 320
16 bit = 320/2 = 160
時間戳(幀間間隔) = 1000ms / 8k * 160 = 20ms
b.視訊流時間戳
eg: samplerate = 90k fps = 25
每個畫素點的時間粒度 1000ms/90k = 1/90(ms)
每幀的畫素點(32bit) = 90k / 25 = 3600
32 bit YUV/RGB raw
時間戳(幀間間隔) = 1000ms / 90k * 3600 = 40ms
位元速率 = 90k * 32bit = 2880kbit/s
c.編碼、解碼和轉碼時間戳
對於非聯動的編碼器,解碼器和轉碼器來說,時間戳只是一個屬性,一般都是一一對應的,並且不是必須的。
/* encode 1 second of video */
for (i = 0; i < 25; i++) {
fflush(stdout);
/* make sure the frame data is writable */
ret = av_frame_make_writable(frame);
if (ret < 0)
exit(1);
/* prepare a dummy image */
/* Y */
for (y = 0; y < c->height; y++) {
for (x = 0; x < c->width; x++) {
frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3;
}
}
/* Cb and Cr */
for (y = 0; y < c->height/2; y++) {
for (x = 0; x < c->width/2; x++) {
frame->data[1][y * frame->linesize[1] + x] = 128 + y + i * 2;
frame->data[2][y * frame->linesize[2] + x] = 64 + x + i * 5;
}
}
frame->pts = i;
/* encode the image */
encode(c, frame, pkt, f);
}
static void decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt,
const char *filename)
{
char buf[1024];
int ret;
ret = avcodec_send_packet(dec_ctx, pkt);
if (ret < 0) {
fprintf(stderr, "Error sending a packet for decoding\n");
exit(1);
}
while (ret >= 0) {
ret = avcodec_receive_frame(dec_ctx, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
return;
else if (ret < 0) {
fprintf(stderr, "Error during decoding\n");
exit(1);
}
printf("saving frame %3d\n", dec_ctx->frame_number);
fflush(stdout);
/* the picture is allocated by the decoder. no need to
free it */
snprintf(buf, sizeof(buf), "%s-%d", filename, dec_ctx->frame_number);
pgm_save(frame->data[0], frame->linesize[0],
frame->width, frame->height, buf);
}
}
其他情況,可以參考
ffmpeg/doc/example/encode_audio.c
ffmpeg/doc/example/encode_vedio.c
ffmpeg/doc/example/decode_audio.c
ffmpeg/doc/example/decode_vedio.c
ffmpeg/doc/example/transcoding.c
d.封裝、解封裝和轉封裝時間戳
對於非聯動封裝器、解封裝器和轉封裝器來說,時間戳也只是一個屬性,一般都是一一對應的,並且不是必須
的。
同樣參考
ffmpeg/doc/example/muxing.c
ffmpeg/doc/example/demuxing_decode.c
ffmpeg/doc/example/remuxing.c
e.網路傳輸時間戳
網路傳輸時間戳是以發送方和接收方協商來制定的,一般以採樣點或者幀間間隔作爲時間戳,幀間間隔也分不
同情況,時間粒度的差異(微秒,毫秒),間隔時間的差異(相對間隔,絕對間隔)。如果數據幀需要分包,分包時
間也有差異(同一幀數據的分包用同一時間,同一幀數據的分包間隔時間(間隔又有相對,絕對之分))
2)容器的封裝,解封裝與轉封裝
容器太多,選最常用的PS, TS, MP4 和 FLV
PS封裝
例如gb28181協定串流媒體實現爲rtp荷載ps流,將h264流打包成ps流。
1:視訊關鍵幀的封裝 RTP + PSheader + PS system header + PS system Map + PES header +h264 data
2:視訊非關鍵幀的封裝 RTP +PS header + PES header + h264 data
3:音訊幀的封裝: RTP + PES header + G711
TS封裝
ts包大小固定爲188位元組,ts層分爲三個部分:ts header、adaptation field、payload。ts header固定4個位元組;
adaptation field可能存在也可能不存在,主要作用是給不足188位元組的數據做填充;payload是pes數據。
TS Header + Adaptation Field + Payload(PES)
MP4封裝
規格書裡描述等很清晰
https://webstore.iec.ch/p-preview/info_isoiec14496-14%7Bed2.0%7Den.pdf
FLV封裝
https://www.adobe.com/content/dam/acom/en/devnet/flv/video_file_format_spec_v10_1.pdf
這些封裝格式的程式實現同樣可以參考ffmpeg自帶範例
ffmpeg/doc/example/muxing.c
ffmpeg/doc/example/demuxing_decode.c
ffmpeg/doc/example/remuxing.c
容器的更多細節需要在IEC和ISO官網查詢規格書
https://webstore.iec.ch/home
https://www.iso.org/home.html
3)媒體數據流的分包與組包
分包有各種情況
切分
切分+標識
切分+封裝
切分+標識+封裝
切分+封裝+標識
組包就是逆向操作:解標識,解封裝,解數據,合併數據
2. 串流媒體通訊協定
1)rtp/rtcp
參考
ORTP
UCL Common RTP library
Bell Labs RTP Library
jrtplib
2)rtsp
參考
live555
gst-rtsp
3)rtmp
參考
nginx
librtmp
srs-librtmp
這些協定細節描述需要在RFC官網去查規格書,非三言兩語能說清
https://www.rfc-editor.org/search/rfc_search_detail.php
3. 其他需要補充的