pjsip功能很强,做sip rtp语音通话库首选。在2.0之后,也支持视频。不过,它的视频功能缺省是从视频设备采集,然后进行编译,再发送出去的。假设,我们已经有了视频源,比如IP摄像机,不需要采集和编码这个过程,怎么处理呢?假设我们采用pjsip附带的pjsua为例。

通常的方法:
1 把视频源当然文件来处理,sample有。不过这种方法用的不多。
2 修改vid_stream.c,在put_frame和get_frame里,换上我们自己的视频源。这种方法使用的最多,很多人在1.x版本里支持视频,就用这种方法。
3 本文采用的:重新构造sdp,自己创建rtp通道。

前两个方法思路直接,代码量都不小,尤其是第二种,需要修改pj底层代码。
如果基于pjsua做一个简单的视频通信,可以采用本文中的方法。其实代码量也不小,不过sample提供了参考,实现起来也比较容易。下面简单说明:

1 关键点在sdp上,pjsua_call_make_call这个函数非常方便,直接呼叫对方。不过它在底层做了太多工作,比如启动了声卡。而不用这个函数,直接用比较底层的pjsip_inv_send_msg,自己处理的工作相对比较多(但不难,不过这样就不需要pjsua这个现成的程序了,所以我们继续用pjsua_call_make_call)。
不过还好,pj库提供了大量的回调,其中一个:on_call_sdp_created,就是在创建sdp后回调上来,由我们自己再修改。比如我们自己定义rtp的端口g_local_port。

void on_call_sdp_created(pjsua_call_id call_id,
                                   pjmedia_sdp_session *sdp,
                                   pj_pool_t *pool,
                                   const pjmedia_sdp_session *rem_sdp)
{
int nPort;
if (sdp != NULL)
{

pjmedia_sdp_media *m = sdp->media[sdp->media_count-1];
m->desc.port = g_local_port;

pjmedia_sdp_conn *c = sdp->conn;
char* addr;
if (c)
addr= c->addr.ptr;
else
{

const pj_str_t *hostname;
pj_sockaddr_in tmp_addr;
char *addr;

hostname = pj_gethostname();
pj_sockaddr_in_init(&tmp_addr, hostname, 0);
addr = pj_inet_ntoa(tmp_addr.sin_addr);
sdp->conn = (pjmedia_sdp_conn *)pj_pool_zalloc (pool, sizeof(pjmedia_sdp_conn));
sdp->conn->net_type = pj_str("IN");
sdp->conn->addr_type = pj_str("IP4");
sdp->conn->addr = pj_str(addr);
}

sdp->origin.addr = *pj_gethostname();
}
}

同样,这里还可以修改payload type等。

这是发起呼叫时的,接收方收到后的回应之后,也会触发这个回调,自己设定RTP端口,payload type就可以了。


呼叫成功后,双方建立起连接关系,这时需要传rtp数据了。pjsua把这些工作都放在底层了,不做任何修改,只需要在发送和接收时,自己做一些处理就行。
先说接收方(参考siprtp.c源码):
pj_status_t init_local_rtp()
{
if (m_bInitMedia)
{
destroy_media();
}

//g_local_port = local_port;

pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
    pool = pj_pool_create(&(cp.factory), "test", 1000, 512, NULL);

int status;

//status = pjmedia_endpt_create(&cp.factory,  pjsip_endpt_get_ioqueue(pjsua_get_pjsip_endpt()), 0, &med_endpt);

status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);

status = pjmedia_rtp_session_init(&video.out_sess, 97, pj_rand());
status = pjmedia_rtp_session_init(&video.in_sess, 97, 0);

status = pjmedia_transport_udp_create(med_endpt, NULL, g_local_port,  0, &video.transport);

m_bInitMedia = true;
video.active = true;
return 0;
}

这段代码是本地启动rtp一个端口用来接收视频数据。
然后,从sdp得到对方发送的ip和端口,调用pjmedia_transport_attach,建立关联就可以了。

发送方同样调用上面函数,初始化本地端口,但不需要pjmedia_transport_attach。(假定视频传输是单方向的)
发送动作就比较简单了,先把要发的数据分包,大小不超过1400,然后pjmedia_rtp_encode_rtp,再pjmedia_transport_send_rtp。

上面还没有讲接收方是怎么接数据的,这里也用到了pj提供的回调机制:
status = pjmedia_transport_attach(video.transport, &video, 
//&info.rem_addr, 
&remote_addr,
NULL, 
sizeof(pj_sockaddr_in),
&on_rx_rtp,
NULL);

这里面的on_rx_rtp就是接收RTP的回调。

video.transport等定义:

struct media_stream
{
    /* Static: */
    unsigned call_index;    /* Call owner. */
    unsigned media_index;    /* Media index in call. */
    pjmedia_transport   *transport;    /* To send/recv RTP/RTCP */

/* Active? */
    pj_bool_t active;    /* Non-zero if is in call. */

/* Current stream info: */
    pjmedia_stream_info si;    /* Current stream info. */

/* More info: */
    unsigned clock_rate;    /* clock rate */
    unsigned samples_per_frame; /* samples per frame */
    unsigned bytes_per_frame;   /* frame size. */

/* RTP session: */
    pjmedia_rtp_session out_sess;    /* outgoing RTP session */
    pjmedia_rtp_session in_sess;    /* incoming RTP session */

/* RTCP stats: */
    pjmedia_rtcp_session rtcp;    /* incoming RTCP session. */

/* Thread: */
    pj_bool_t thread_quit_flag;  /* Stop media thread. */
    pj_thread_t *thread;    /* Media thread. */
};

struct media_stream video;

源码在:https://github.com/sxcong/pjsipvideo_demo
视频源RTSP,可以直接使用IPCAM,比如海康摄像机。
SIP SERVER是开源的resiprocate,编译出来可直接使用。
DEMO程序是vc2008写的,包括SIP的登录,发送请求,发送和接收视频并解码播放。可在同一台机器上运行两个实例测试。
不过毕竟是DEMO,只是演示怎么使用,细节还有很多问题需要修改。

使用pjsip传输已经编码的视频,源码在github相关推荐

  1. 自学者福利!知乎上已获千赞,原理+实战+视频+源码

    前言 不清楚你是不是知道,咱们中国有相当大的一部分软件公司,他们的软件开发团队都小的可怜,甚至只有1-3个人,连一个项目小组都算不上,而这样的团队却要承担一个软件公司所有的软件开发任务,在软件上线和开 ...

  2. 一对一交友源码,仿抖音短视频源码,搭建的秘密你了解多少?

    一对一交友源码,仿抖音短视频源码,搭建的秘密你了解多少? 5G技术马上到来,现在直播遇到的一些问题,比如延迟.卡顿.掉线等,很有可能这些情况就不复存在了.而且,其他的一些高科技产品会运用到直播过程中, ...

  3. 直播视频源码开发技术之平台测试之软件测试侧重点介绍

    随着移动互联网技术日新月异的发展,视频直播市场发生了巨大的变化,直播用户消费内容和交互方式也在不断升级,"全民直播"的开启使得越来越多的互联网创业者或者成熟企业进入视频直播源码开发 ...

  4. 长短视频之争,长视频平台和短视频源码谁主沉浮?

    文/布谷安妮 来源/山东布谷鸟网络 飞速飙升的用户流量,让以抖音和快手为代表的短视频收割了大量的关注度,从个体用户到媒体,短视频源码在短短时间内成为互联网行业最炙手可热的话题.腾讯重新启用微视,百度推 ...

  5. 直播源码和短视频源码,相亲相爱的一家人

    直播源码和短视频源码,相亲相爱的一家人 从直播的百播大战,到如今的趋于稳定:从短视频的兴起,到如今的竞争发展.直播和短视频两条线,开始相交,直播里面添加短视频功能,短视频里面也添加了直播. 在直播里面 ...

  6. 【开学季限时免费】下载19880元大数据开发全链路教程(视频+源码)

    随着大数据.云计算.物联网.人工智能这些行业的发展崛起,对于大数据人才的需求越来越大,而大数据人才的培养发展周期相对较长,导致了大数据人才短缺,市场供不应求.所以也就出现了大数据开发工程师.数仓工程师 ...

  7. 快餐文化短视频源码行业竞争激烈,短视频发展任重道远

    随着移动互联技术的兴起,形式多样的短视频源码软件为受众开辟了短视频时代,赋予视频以新的时代内涵.梨视频.美拍.快手.抖音等 APP充斥了人们的生活,因此不少人群对视频软件产生了依赖感.短视频源码APP ...

  8. php+api抖音随机播放视频源码

    简介: php+api抖音随机播放视频源码,前端纯静态html+css,数据采用php+API接口调用第三方数据,不需要配置环境,上传即用. 源码体积小,视频采集自网络,无视频资源,内置多条播放线路. ...

  9. 短视频源码,仿抖音源码,助您在短视频行业开辟出一条新路

    短视频源码,仿抖音源码,助您在短视频行业开辟出一条新路 复制代码 在短视频行业,抖音当之无愧的T0阶层.致使腾讯老大也眼红这块蛋糕,打压抖音,重启自己的短视频--微视来进行竞争.短视频的火爆事宜得益于 ...

  10. 类似抖音的短视频app开发难度大吗?短视频源码让你事半功倍

    "短视频"--在2018年视频直播行业的发展趋于稳定后,短视频app成为了主角.抖音短视频app的火爆,引来互联网大佬们的强势入局.看似简洁的抖音短视频app,实则在开发过程中会存 ...

最新文章

  1. MySQL删除表数据
  2. SQL Server中的重要观点
  3. 通过ddmlib杀死某个android进程的方法
  4. python批量做线性规划(每次的约束条件参数有变换)
  5. TortoiseSVN Launch Failed Error:系统找不到指定路径
  6. iOS 集合的深复制与浅复制
  7. 前端学习(3043):vue+element今日头条管理-组件目录和组件名
  8. IAR 的精确延时程序(转)
  9. php server(),php的$_SERVER参数详解(附实例)
  10. 设备密码的设置以及遗忘重设置
  11. uniapp 移动端上传文件_移动端上传头像并裁剪 - Clipic.js
  12. C语言中fp=fopen NULL,c – “FILE * fp,* fopen();”是什么?
  13. ASP.NET Web程序设计 第一章 ASP.NET Web应用程序基础笔记
  14. mysql 插入数据 特殊符号_使用特殊字符将数据插入mysql数据库
  15. 行列式与矩阵树定理入门
  16. activiti自定义流程之整合(六):获取我的申请任务
  17. BIOS功能调用表格
  18. RockChip Android平台抓取android trace的windows环境搭建
  19. 如何读取PHD实时数据
  20. 高考|考大学不是唯一出路!

热门文章

  1. QT表格的宽度自适应调整方法void setStretchLastSection ( bool stretch ) 转帖
  2. 盗版牢骚? or 学而不思?
  3. 根据判断浏览器类型屏幕分辨率自动调用不同CSS的代码
  4. Spring Boot + Spring Data JPA项目配置多数据源
  5. hadoop 开发环境设置以及可运行jar包生成
  6. Vue.js 系列教程 5:动画
  7. java.sql.SQLException: Field 'id' doesn't have a default value解决方法
  8. 吴恩达机器学习作业(1)
  9. 一个简单的js作用域题目(原创)
  10. redis系列二: linux下安装redis