Bootstrap

Pjsip 视频拉取实现方案

视频拉取,指的是P1拉取P2的摄像头的视频,但是P2是不知道的。

使用Pjsip实现端到端的视频拉取,指的是P1通过拨打视频电话方式和P2通信,但是P2并没有通话的提示,也不用接听动作,P1就可以查看P2摄像头录像的视频,而且只能P1查看P2摄像头的视频和声音,P2是无法查看和听到P1的视频和声音的,说白了就是视频和声音是P2--->P1的单项传输。不过怎么区别普通的视频通话和拉取视频通话呢?这就是下面要说明的。

  • 在sip头加入Pll字段,说明是否是视频拉取
  • 修改sdp中传输方向

1.    Java层


1.1    定义视频拉取通话接口


       在PjsipCall中定义视频拉取接口public boolean makePullVideoCall(String buddyAccount)。
接口实现时,相比普通视频通话需要增加下面的参数定义:
      1)    呼叫参数CallSetting中增加一个Flag定义,参数为64,csetting.setFlag(64);这个flag是c层pjsua_call_make_call函数中pjsua_call_setting参数的flag。
       2)    增加sip协议头中Pll的定义:Pll为Pull的缩写,值为1说明是视频拉取
              sipHeader.setHName("Pll");
              sipHeader.setHValue("1");


1.2    定义音频拉取通话接口


       在PjsipCall中定义视频拉取接口public boolean makePullAudioCall (String buddyAccount)。
接口实现时,相比普通视频通话需要增加下面的参数定义:
       1)    呼叫参数CallSetting中增加一个Flag定义,参数为64,csetting.setFlag(64);这个flag是c层pjsua_call_make_call函数中pjsua_call_setting参数的flag。
        2)    增加sip协议头中Pll的定义:Pll为Pull的缩写,值为1说明是视频拉取
               sipHeader.setHName("Pll");
               sipHeader.setHValue("1");


2.    C层


2.1    pjsua_call结构体中添加isPull定义


        修改位置:pjsip/include/pjsua-lib/pjsua_internal.h
        在struct pjsua_call结构体中新增isPull成员变量,变量类型pj_bool_t类型


2.2    修改pjsua_media_channel_create_sdp函数


         函数位置:pjsip/src/pjsua-lib/pjsua_media.c
         修改函数中pjmedia_endpt_create_audio_sdp和pjmedia_endpt_create_video_sdp这两个函数的调用。把call->opt.flag参数传入,原始调用中,option参数只传0。

2.3    修改pjmedia_endpt_create_audio_sdp


      函数位置:pjmedia/src/pjmedia/endpoint.c
      在文件头中增加static const pj_str_t STR_RECVONLY = { "recvonly", 8 }; //added by dengfei的定义
      把函数中status = init_sdp_media(m, pool, &STR_AUDIO, si);的调用,修改成:status = init_sdp_media_with_flag(m, pool, options, &STR_AUDIO, si);的调用。init_sdp_media_with_flag的实现后面


2.4    修改pjmedia_endpt_create_video_sdp


      函数位置:pjmedia/src/pjmedia/endpoint.c
      在文件头中增加static const pj_str_t STR_RECVONLY = { "recvonly", 8 }; //added by dengfei的定义(前面已经增加,就可以不用再增加了)
      把函数中status = init_sdp_media(m, pool, &STR_AUDIO, si);的调用,修改成:status = init_sdp_media_with_flag(m, pool, options, &STR_AUDIO, si);的调用。init_sdp_media_with_flag的实现后面


2.5    新增函数定义init_sdp_media_with_flag


     函数位置:pjmedia/src/pjmedia/endpoint.c
     函数的实现,基本等同于init_sdp_media,只是在attr->name赋值时,需要根据option的值,判断是否是视频拉取。Option的值,就是java层中CallSetting定义的64的值。
     修改如下:
      if (flg & 64/*PJSUA_CALL_PULL_MEDIA*/) {
        attr->name = STR_RECVONLY;
      } else {
        attr->name = STR_SENDRECV;
      }


2.6    新增函数定义verify_pull_mode_incoming_request


      函数位置:pjsip/src/pjsua-lib/pjsua_call.c
      该函数用于在pjsua_call_on_incoming函数中,判断sip协议头是否携带Pll的定义,和取值,并修改pjsua_call结构体中isPull的取值。


2.7    call.hpp增加pullState值


      在call.hpp的CallInfo中,增加pullState的定义。


2.8    pjsua_call_info增加isPull定义


     修改位置:pjsip/include/pjsua-lib/pjsua.h
在pjsua.h的pjsua_call_info中,增加isPull的定义,代码如下:
      /** is pull vide or audio call */
     pj_bool_t           isPull;


2.9     call.cpp增加pullState的赋值


       在call.cpp的void CallInfo::fromPj(const pjsua_call_info &pci)中,增加pullState           = PJ2BOOL(pci.isPull);赋值,这样java层就的callInfo就可以正常的获取到值。


2.10     pjsua_call_get_info函数中isPull的赋值


      在pjsua_call.c的pjsua_call_get_info函数增加如下代码:
      /*is pull video or audio call*/
      info->isPull = call->isPull;


3.    修改默认视频的分辨率


    1)    修改pjmedia/src/pjmedia-videodev/android_dev.c中的
            #define DEFAULT_WIDTH           640//352
            #define DEFAULT_HEIGHT          480//288
     2)    修改pjmedia/src/pjmedia-codec/openh264.cpp中
            #  define DEFAULT_WIDTH         640//352
            #  define DEFAULT_HEIGHT        480//288
      注意:这个了两个文件要同时修改才能生效


4.    SDP中direction的协商


      代码位置:pjmedia/src/pjmedia/sdp_neg.c
      函数:update_media_direction
      如果remote的direction为recvonly,local的direction就更改为sendonly
 

;