要了解pjsip的使用,simple_pjsua.c是一个很好的例子,虽然代码只有短短的172行,却展示了pjsua-lib层的完整使用流程、注册流程和基本呼叫流程。

下面是学习过程中整理的simple_pjsua.c中的main函数主要流程:

先来看看pjsip-apps/src/samples/simple_pjsua.c的main函数

[cpp] view plaincopy
  1. /*
  2. * main()
  3. *
  4. * argv[1] may contain URL to call.
  5. */
  6. int main(int argc, char *argv[])
  7. {
  8. pjsua_acc_id acc_id;
  9. pj_status_t status;
  10. //  创建PJSIP
  11. /* Create pjsua first! */
  12. status = pjsua_create();
  13. if (status != PJ_SUCCESS) error_exit("Error in pjsua_create()", status);
  14. //  校验被叫SIP地址是否正确
  15. /* If argument is specified, it's got to be a valid SIP URL */
  16. if (argc > 1) {
  17. status = pjsua_verify_url(argv[1]);
  18. if (status != PJ_SUCCESS) error_exit("Invalid URL in argv", status);
  19. }
  20. //    初始化PJSUA,设置回调函数
  21. /* Init pjsua */
  22. {
  23. pjsua_config cfg;
  24. pjsua_logging_config log_cfg;
  25. pjsua_config_default(&cfg);
  26. cfg.cb.on_incoming_call = &on_incoming_call;
  27. cfg.cb.on_call_media_state = &on_call_media_state;
  28. cfg.cb.on_call_state = &on_call_state;
  29. pjsua_logging_config_default(&log_cfg);
  30. log_cfg.console_level = 4;
  31. status = pjsua_init(&cfg, &log_cfg, NULL);
  32. if (status != PJ_SUCCESS) error_exit("Error in pjsua_init()", status);
  33. }
  34. //    创建PJSIP的传输端口
  35. /* Add UDP transport. */
  36. {
  37. pjsua_transport_config cfg;
  38. pjsua_transport_config_default(&cfg);
  39. cfg.port = 5060;
  40. status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &cfg, NULL);
  41. if (status != PJ_SUCCESS) error_exit("Error creating transport", status);
  42. }
  43. //    启动PJSIP
  44. /* Initialization is done, now start pjsua */
  45. status = pjsua_start();
  46. if (status != PJ_SUCCESS) error_exit("Error starting pjsua", status);
  47. //    设置SIP用户帐号
  48. /* Register to SIP server by creating SIP account. */
  49. {
  50. pjsua_acc_config cfg;
  51. pjsua_acc_config_default(&cfg);
  52. cfg.id = pj_str("sip:" SIP_USER "@" SIP_DOMAIN);
  53. cfg.reg_uri = pj_str("sip:" SIP_DOMAIN);
  54. cfg.cred_count = 1;
  55. cfg.cred_info[0].realm = pj_str(SIP_DOMAIN);
  56. cfg.cred_info[0].scheme = pj_str("digest");
  57. cfg.cred_info[0].username = pj_str(SIP_USER);
  58. cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
  59. cfg.cred_info[0].data = pj_str(SIP_PASSWD);
  60. status = pjsua_acc_add(&cfg, PJ_TRUE, &acc_id);
  61. if (status != PJ_SUCCESS) error_exit("Error adding account", status);
  62. }
  63. //    发起一个呼叫
  64. /* If URL is specified, make call to the URL. */
  65. if (argc > 1) {
  66. pj_str_t uri = pj_str(argv[1]);
  67. status = pjsua_call_make_call(acc_id, &uri, 0, NULL, NULL, NULL);
  68. if (status != PJ_SUCCESS) error_exit("Error making call", status);
  69. }
  70. //    循环等待
  71. /* Wait until user press "q" to quit. */
  72. for (;;) {
  73. char option[10];
  74. puts("Press 'h' to hangup all calls, 'q' to quit");
  75. if (fgets(option, sizeof(option), stdin) == NULL) {
  76. puts("EOF while reading stdin, will quit now..");
  77. break;
  78. }
  79. if (option[0] == 'q')
  80. break;
  81. if (option[0] == 'h')
  82. pjsua_call_hangup_all();
  83. }
  84. /* Destroy pjsua */
  85. pjsua_destroy();
  86. return 0;
  87. }

来电的回调函数

[cpp] view plaincopy
  1. //来电回调函数
  2. /* Callback called by the library upon receiving incoming call */
  3. static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
  4. pjsip_rx_data *rdata)
  5. {
  6. pjsua_call_info ci;
  7. PJ_UNUSED_ARG(acc_id);
  8. PJ_UNUSED_ARG(rdata);
  9. //    获得呼叫信息
  10. pjsua_call_get_info(call_id, &ci);
  11. PJ_LOG(3,(THIS_FILE, "Incoming call from %.*s!!",
  12. (int)ci.remote_info.slen,
  13. ci.remote_info.ptr));
  14. //    自动应答呼叫
  15. /* Automatically answer incoming calls with 200/OK */
  16. pjsua_call_answer(call_id, 200, NULL, NULL);
  17. }

呼叫状态改变的回调函数,没有做实质性的操作:

[cpp] view plaincopy
  1. //呼叫状态改变的回调函数
  2. /* Callback called by the library when call's state has changed */
  3. static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
  4. {
  5. pjsua_call_info ci;
  6. PJ_UNUSED_ARG(e);
  7. pjsua_call_get_info(call_id, &ci);
  8. PJ_LOG(3,(THIS_FILE, "Call %d state=%.*s", call_id,
  9. (int)ci.state_text.slen,
  10. ci.state_text.ptr));
  11. }

媒体状态改变的回调函数:

[cpp] view plaincopy
  1. //媒体状态改变的回调函数
  2. /* Callback called by the library when call's media state has changed */
  3. static void on_call_media_state(pjsua_call_id call_id)
  4. {
  5. pjsua_call_info ci;
  6. pjsua_call_get_info(call_id, &ci);
  7. //    当媒体为激活时,连接呼叫和声音设备
  8. if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
  9. // When media is active, connect call to sound device.
  10. pjsua_conf_connect(ci.conf_slot, 0);
  11. pjsua_conf_connect(0, ci.conf_slot);
  12. }
  13. }

PJSIP学习笔记——从simple_pjsua.c示例程序了解PJSUA-LIB的基本使用流程相关推荐

  1. Windows 8 Directx 开发学习笔记(四)示例程序小结

    VS2012的示例程序包括了最基本的DirectX流程,涉及许多知识,所以看完代码之后还是感觉没有头绪,打算对整个过程再整理一下,方便进一步的学习. 正方体在空间中可以用它的8个顶点定义,而每个顶点可 ...

  2. PJSIP学习笔记——PJSUA层发起呼叫的主要流程

    在上一篇学习笔记 从simple_pjsua.c示例程序了解PJSUA-LIB的基本使用流程中,使用了PJSUA层的 pjsua_call_make_call来发起一个呼叫,那么这个发起呼叫的流程是怎 ...

  3. mybatis学习笔记(1)-对原生jdbc程序中的问题总结

    2019独角兽企业重金招聘Python工程师标准>>> mybatis学习笔记(1)-对原生jdbc程序中的问题总结 标签:mybatis [TOC] 本文总结jdbc编程的一般步骤 ...

  4. C#.NET学习笔记2---C#.第一个C#程序

    C#.NET学习笔记2---C#.第一个C#程序 技术qq交流群:JavaDream:251572072  教程下载,在线交流:创梦IT社区:__________以前的网站现在不弄了,抱歉 6.第一个 ...

  5. MyBatis学习笔记2 ——第一个MyBatis程序

    MyBatis学习笔记2 --第一个MyBatis程序 参考教程B站狂神https://www.bilibili.com/video/BV1NE411Q7Nx 环境搭建 建立一个mybatis数据库用 ...

  6. Spark学习笔记1——第一个Spark程序:单词数统计

    Spark学习笔记1--第一个Spark程序:单词数统计 笔记摘抄自 [美] Holden Karau 等著的<Spark快速大数据分析> 添加依赖 通过 Maven 添加 Spark-c ...

  7. C++学习笔记(B站黑马程序员C++教程)

    C++学习笔记(B站黑马程序员C++教程) 简介 视频链接https://www.bilibili.com/video/BV1kV411U7Ub?spm_id_from=333.999.0.0 建议用 ...

  8. Java Web--HTML、CSS、JavaScript详细学习笔记(内含丰富示例代码)

    ** Java Web–HTML.CSS.JavaScript学习笔记 ** HTML(Hyper Text Markup Language超文本标记语言):控制的是页面的内容,是由标签组成的语言,能 ...

  9. 【前端学习笔记】移动web-黑马程序员学习笔记

    移动web-黑马程序员学习笔记 1 字体图标 2 平面转换 2.1 绝对定位元素居中: 2.2 双开门效果 2.3 旋转效果 2.4* 转换原点 2.5 多重转换效果 2.6 缩放 3* 渐变 4 空 ...

最新文章

  1. python同步赋值原理,Python直接赋值及深浅拷贝原理详解
  2. 热点快评:德国强化AI战略,系统、技术等“多轮并行”
  3. 【采用】人工智能如何帮助银行反欺诈:银行智能欺诈风险预测模型研究
  4. AIX 磁盘和文件系统
  5. ESD二极管 DW12P4N3-S 电压12V 封装DFN2020-3L
  6. 专注力 化繁为简的惊人力量
  7. 微软同步框架入门开篇(附SnapShot快照Demo)
  8. 工作30:加入git版本库
  9. Python自制微信机器人:群发消息、自动接收好友
  10. Python学习6 字典基础知识和常用函数
  11. tomcat 5 comcat 6 区别
  12. 几个RTP工具的使用 rtptools_1.18【原创】
  13. 在 Linux 的应用中测试中的延时和丢包模拟
  14. 2018-2019-2 20165234 《网络对抗技术》 Exp1 PC平台逆向破解
  15. 《图解HTTP》阅读笔记--第六章--HTTP首部
  16. java 获取 jsp 内容_JAVA记录-JSP内容
  17. 光储直流微电网能量管理。 系统主要由光伏发电模块、mppt控制模块、混合储能系统模块、直流负载模块、改进前的soc限值管理控制模块
  18. VML标记与通用属性
  19. js日期减一个月_正正正国庆!折上再减!三亚/香格里拉/稻城/拈花湾,最低499元…...
  20. 彻底搞懂内存屏障(上)

热门文章

  1. 物理与计算机信息工程学院,泉州师范学院物理与信息工程学院
  2. 分页查询插件PageHelper 5.x版本
  3. Idea创建web项目,配置tomcat服务器
  4. 商务计算机的购置方案,电子采购方案的实施.ppt
  5. linux安装数据库依赖包,Linux下安装DB2的包依赖
  6. python建db文件_临时数据库之python用sqlite3模块操作sqlite
  7. hihocoder1477 闰秒
  8. BZOJ4122 : [Baltic2015]File paths
  9. 一个DataGridView辅助类
  10. uva11991 Easy Problem from Rujia Liu?