源码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://vnzmi.com/img/in-post/webrtc_architecture.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. 其他需要补充的