利用 Video Streaming 来设计视讯会议软件, 其中在技术层面不可或缺的一部份就是 RTP Protocol 的部份。RTP 也是 VoIP (Voice over IP) 相关技术所使用的通讯协议。
为了配合 Video Streaming 来设计完整的视讯会议软件, 我们势必要加入 RTP 的技术。在这方面, 我们选择使用现成的 RTP 链接库 – JRTPLIB。
与 video4linux 链接库不同的是, video4linux 在决策上我们选择自行发展, 但 JRTPLIB 则是一个很成熟的项目了, 而且仍在持续维护, 未来 JRTPLIB 还会加入 IPV6 与 multicasting 方面的完整支持, 因此使用 JRTPLIB 来发展我们的 Video Streaming 软件才是解决之道。
与 JRTPLIB 相关的计画包括 JVOIPLIB 与 JTHREAD, 这两个链接库对我们的工作是相关有帮助的, 本文则先将重心放在 JRTPLIB上面。
JRTPLIB 实作了 RTP 协议, 并且提供了简单易用的 API 供软件开发使用。JRTPLIB 也支持了 session, 并且可在底下平台执行:
MS-Windows 95,98 and NT
Linux
FreeBSD
HP-UX
Solaris
VxWorks
JRTPLIB 的官方首页为:
http://lumumba.luc.ac.be/jori/jrtplib/jrtplib.html
JRTPLIB 的第一个程序
底下我们介绍过 JRTPLIB 的设计方法后, 大家就会发觉到 JRTPLIB 实在很好上手。要利用 RTP 通讯协议传送资料, 第一步要先建立一个 session, 方法如下:
#include "rtpsession.h"
int main(void)
{
RTPSession sess;
sess.Create(5000);
return 0;
}
第一步我们要先把 rtpsession.h 给 include 进来:
#include "rtpsession.h"
接下来再产生 RTPSession 类别的对象:
RTPSession sess;
最后再建立 session 就完成最简单的初始动作了:
sess.Create(5000);
Create() 成员函数接收一个 portbase 的参数, 指定 session 的 port, 接着开始初始化 timestamp 与 packet sequence number。RTPSession::Create() 程序代码如下:
int RTPSession::Create(int localportbase,unsigned long localip)
{
int status;
if (initialized)
return ERR_RTP_SESSIONALREADYINITIALIZED;
if ((status = rtpconn.Create(localportbase,localip)) < 0)
return status;
if ((status = contribsources.CreateLocalCNAME()) < 0)
{
rtpconn.Destroy();
return status;
}
CreateNewSSRC();
localinf.CreateSessionParameters();
rtcpmodule.Initialize();
initialized = true;
return 0;
}
Create() 接着会再建立一个 SSRC:
CreateNewSSRC();
SSRC 为 local synchronization source identifier。
指定目的端
接下来再指定目的端的 IP 地址:
unsigned long addr = ntohl(inet_addr("127.0.0.1"));
sess.AddDestination(addr,5000);
这里表示我们要将封包传送到 127.0.0.1 (本地端) 的 port 5000, 只要照着套用即可。
传送 RTP 封包
sess.SendPacket("1234567890",10,0,false,10);
1234567890 是要传送的字符串, 第二个参数 (10) 表示传送字符串的长度, 第三个参数为 payload type, 第四个参数为 mark flag, 最后第五个参数则是 timestamp 的递增单位。
RTP 的封包格式
RTP 与其它 Internet 通讯协议一样, 在封包里也会有封包档头, 接着才是封包的资料。
在 RTPsession::SendPacket() 的第三个参数与第四个参数分别是 payload type 与 mark flag, 在 RTP 封包档头里, 分别是 Payload 字段与 M 字段。
Payload 字段的长度为 7 bits, M 字段的长度为 1 bits。
RTP 的 Payload type
RTP 文件头的 Payload type 指定封包资料的编码方式, 我们列出五个常用的 Audio 标准, 与三个常用的 Video 标准, 其中 JPEG/H.261/H.263 我们本文第一篇里都有做过简单的介绍。常用的 Payload type 如下表:
Payload type 编码标准 支持Audio或Video Clock Rate (Hz)
2 G.721 A 8000
4 G.723 A 8000
7 LPC A 8000
9 G.722 A 8000
15 G.728 A 8000
26 JPEG V 90000
31 H.261 V 90000
34 H.263 V 90000
Top
9 楼AntonlioX(做人要厚道)回复于 2005-07-01 00:35:29 得分 25
wgscd转摘的
RTP/RTCP(实时传输协议/实时传输控制协议)基于UDP派生出的协议,并增加了对实时传输的控制。一般用于网上传输实时视频数据,比如远程视频监控,视频点播等。有一本名叫《多媒体网络传输协议》的书上对此2个协议的结构和原理做了比较详细的介绍,好象是清华大学出版社出版的。
我去年做远程视频监控系统时,曾用基于2个协议,用Wonsock工具封装了一个网络传输动态连接库,专门用于局域网组播传输实时视频数据。以下是我针对此2个协议定义的相关C结构。
/*Current protocol version. */
#define RTP_VERSION 2
#define MIN_SEQUENTIAL 1
#define RTP_SEQ_MOD (1<<16)
#define RTP_MAX_SDES 255 /* maximum text length for SDES */
#define MID_BUFFER_NUM 2
#define MAX_DROPOUT 25
typedef enum {
RTCP_SR = 200,
RTCP_RR = 201,
RTCP_SDES = 202,
RTCP_BYE = 203,
RTCP_APP = 204
} rtcp_type_t;
typedef enum {
RTCP_SDES_END = 0,
RTCP_SDES_CNAME = 1,
RTCP_SDES_NAME = 2,
RTCP_SDES_EMAIL = 3,
RTCP_SDES_PHONE = 4,
RTCP_SDES_LOC = 5,
RTCP_SDES_TOOL = 6,
RTCP_SDES_NOTE = 7,
RTCP_SDES_PRIV = 8
} rtcp_sdes_type_t;
/*
* RTP data header
*/
typedef struct {
unsigned int version:2; /* protocol version */
unsigned int p:1; /* padding flag */
unsigned int x:1; /* header extension flag */
unsigned int cc:4; /* CSRC count */
unsigned int m:1; /* marker bit */
unsigned int pt:7; /* payload type */
u_int16 seq; /* sequence number */
u_int32 ts; /* timestamp */
u_int32 ssrc; /* synchronization source */
u_int32 csrc[1]; /* optional CSRC list */
} rtp_hdr_t;
/*
* RTCP common header word
*/
typedef struct {
unsigned int version:2; /* protocol version */
unsigned int p:1; /* padding flag */
unsigned int count:5; /* varies by packet type */
unsigned int pt:8; /* RTCP packet type */
u_int16 length; /* pkt len in words, w/o this word */
} rtcp_common_t;
/*
* Big-endian mask for version, padding bit and packet type pair
*/
#define RTCP_VALID_MASK (0xc000 | 0x2000 | 0xfe)
#define RTCP_VALID_VALUE ((RTP_VERSION << 14) | RTCP_SR)
/*
* Reception report block
*/
typedef struct {
u_int32 ssrc; /* data source being reported */
unsigned int fraction:8; /* fraction lost since last SR/RR */
int lost:24; /* cumul. no. pkts lost (signed!) */
u_int32 last_seq; /* extended last seq. no. received */
u_int32 jitter; /* interarrival jitter */
u_int32 lsr; /* last SR packet from this source */
u_int32 dlsr; /* delay since last SR packet */
} rtcp_rr_t;
/*
* SDES item
*/
typedef struct {
u_int8 type; /* type of item (rtcp_sdes_type_t) */
u_int8 length; /* length of item (in octets) */
char data[1]; /* text, not null-terminated */
} rtcp_sdes_item_t;
/*
* One RTCP packet
*/
typedef struct {
rtcp_common_t common; /* common header */
union {
/* sender report (SR) */
struct {
u_int32 ssrc; /* sender generating this report */
u_int32 ntp_sec; /* NTP timestamp */
u_int32 ntp_frac;
u_int32 rtp_ts; /* RTP timestamp */
u_int32 psent; /* packets sent */
u_int32 osent; /* octets sent */
rtcp_rr_t rr[1]; /* variable-length list */
} sr;
/* reception report (RR) */
struct {
u_int32 ssrc; /* receiver generating this report */
rtcp_rr_t rr[1]; /* variable-length list */
} rr;
/* source description (SDES) */
struct rtcp_sdes {
u_int32 src; /* first SSRC/CSRC */
rtcp_sdes_item_t item[1]; /* list of SDES items */
} sdes;
/* BYE */
struct {
u_int32 src[1]; /* list of sources */
/* can"t express trailing text for reason */
} bye;
} r;
} rtcp_t;
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/xwchen/archive/2008/04/24/2325481.aspx