美文网首页
PJSIP自定义语音

PJSIP自定义语音

作者: 集韵增广 | 来源:发表于2022-03-30 11:17 被阅读0次
SIP协议架构

缩写注释:

SDP(会话描述协议): 用于两个会话实体之间的媒体协商,并达成一致,属信令语言族,采用文本(字符)描述形式;
RTP (实时传输协议):由RFC3550定义的端到端的传输实时数据协议,它包含:净荷类型识别,序列号编码,时间戳和传输控制;
RTCP(实时传输控制协议):与RTP共同定义在1996年提出的RFC 1889中,是和 RTP一起工作的控制协议。
RSVP(资源预留协议):RSVP是一种位于第三层的信令协定,它独立于各种网路媒介,使得套用能将自己的QoS要求通过信令通知给网路,网路可以对此套用预留相应的资源。
Sigcomp(信令压缩):一种压缩应用层协议(如SIP、RTSP)消息的方案。

SIP简单体系架构

SIP标准:

核心标准:RFC3261 SIP:Session Initiation Protocol

扩展标准:RFC2976 The SIP INFO Method
RFC3263 Locating SIP Servers
RFC3265 SIP-Specific Event Notification
RFC3311 UPDATE Method
RFC3326 The Reason Header Field
RFC3372 SIP for Telephones (SIP-T): Context and Architectures
RFC3398 ISUP to SIP Mapping
RFC3428 SIP Extension for Instant Messaging

pjsua拨号流程

1,初始化PJSUA

status = pjsua_create();   
if (status != PJ_SUCCESS)    {        printf("Error in pjsua_create(%d)\n", status);    }  
pjsua_config_default(&(ua_cfg));   
ua_cfg.cb.on_incoming_call = &on_incoming_call;   (接听电话回调)
ua_cfg.cb.on_call_media_state = &on_call_media_state;   (媒体事件回调)
ua_cfg.cb.on_call_state = &on_call_state;    (播出电话的回调)
ua_cfg.cb.on_pager = &on_pager;    (进来message的回调)
ua_cfg.cb.on_pager_status = &on_pager_status;    (短信发送的状态变化)
ua_cfg.cb.on_typing = &on_typing;    /* configure logging */    (对方输入消息的动作回调)
pjsua_logging_config_default(&(log_cfg));   
log_cfg.console_level = 4;    /* configure media */   
pjsua_media_config_default(&(media_cfg));   
status = pjsua_init(&ua_cfg, &log_cfg, NULL);   
if (status != PJ_SUCCESS)    {        printf("Error in pjsua_init(%d)\n", status);    }       
pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);       
pool = pjsua_pool_create("MYSOUNDPOOL", 4000, 4000);      
// pj_pool_t *pcmpool = pjsua_pool_create("PCMPOOL", 2000, 2000);    /* Add UDP transport. */    {        pjsua_transport_config_default(&trans_cfg);       
trans_cfg.port = 5060;       
status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &trans_cfg, &transport_id);       
if (status != PJ_SUCCESS)        {            printf("Error creating transport(%d)\n", status);        }    }   
pjsua_set_null_snd_dev();    /* Initialization is done, now start pjsua */   
status = pjsua_start();   
if (status != PJ_SUCCESS)    {        printf("Error starting pjsua(%d)\n", status);    }    /* Register to SIP server by creating SIP account. */    {       
pjsua_acc_config_default(&acc_cfg);       
acc_cfg.id = pj_str("sip:" SIP_USER "@" SIP_DOMAIN);       
acc_cfg.reg_uri = pj_str("sip:" SIP_DOMAIN);       
acc_cfg.cred_count = 1;       
acc_cfg.cred_info[0].realm = pj_str(SIP_DOMAIN);       
acc_cfg.cred_info[0].scheme = pj_str("digest");       
acc_cfg.cred_info[0].username = pj_str(SIP_USER);       
acc_cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;       
//    acc_cfg.cred_info[0].data = pj_str(SIP_PASSWD);       
status = pjsua_acc_add_local(transport_id, PJ_TRUE, &acc_id);       
if (status != PJ_SUCCESS)        {            printf("Error adding account(%d)\n", status);        }       
}

2,拨号

pj_str_t to = pj_str(toaddr);
status = pjsua_call_make_call(acc_id, &to, NULL, NULL, NULL, &current_call);

3,建立语音通道(对端接听通话后on_call_media_state会触发,media状态为PJSUA_CALL_MEDIA_ACTIVE)

static void on_call_media_state(pjsua_call_id call_id){   
    pjsua_call_info ci;   
    pjsua_call_get_info(call_id, &ci);   
    if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE)    {            
           pjsua_conf_get_port_info(ci.conf_slot, &cpi);
           //初始化gaudo为自定义的音频设备
           gaudo->setupmodev(cpi.bits_per_sample);       
           gaudo->setupmidev(cpi.bits_per_sample);       
           // create pcm micro media port       
           pjmedia_port *pcmport;       
           port_data *sine;       
           unsigned i;       
           unsigned count;       
           unsigned samplerate = cpi.clock_rate;       
           unsigned channel_count = 1;       
           //创建麦克风的输入port
           pcmport = (pjmedia_port *)pj_pool_zalloc(pool, sizeof(pjmedia_port));       
           pj_str_t name = pj_str("PCMAUDPORT");       
           pjmedia_port_info_init(&pcmport->info, &name, PJMEDIA_SIG_CLASS_PORT_AUD('s', 'i'), samplerate, channel_count, 16,                               samplerate * 62.5 / 1000 * channel_count);       
           pcmport->get_frame = &sine_get_frame;    //从麦克风读数据,写给输出音频         
           //创建喇叭的输出port
           pjmedia_port *prt;         
           pjsua_conf_port_id port_id, pcmport_id;       
           prt = (pjmedia_port *)pj_pool_zalloc(pool, sizeof(pjmedia_port));       
           name = pj_str("PCMAUDPORT2");       
           pjmedia_port_info_init(&prt->info, &name, PJMEDIA_SIG_CLASS_PORT_AUD('s', 'o'), samplerate, channel_count, 16,                               samplerate * 62.5 / 1000 * channel_count);       
           prt->put_frame = &sine_put_frame; //从输入音频流读数据,写给喇叭
                  
           pjsua_conf_add_port(pool, prt, &port_id);       
           pjsua_conf_add_port(pool, pcmport, &pcmport_id);       
           gport_id = port_id ;      
           gport = prt;       
           gpcmport_id = pcmport_id;       
           gpcmport = pcmport;       
           PJ_LOG(3, (THIS_FILE, "Media state conf_slot[%d] pcmport_id[%d]!!\n", ci.conf_slot, pcmport_id));       
           //麦克风的输入数据传输给通话对端
          pjsua_conf_connect(pcmport_id, ci.conf_slot);       
          //通话对端传输的数据传输给喇叭播放
          pjsua_conf_connect(ci.conf_slot, port_id);  
}}

4,本地音频处理

static pj_status_t sine_put_frame(struct pjmedia_port *port, pjmedia_frame *frame){   
    MI_S32 s32Ret = MI_SUCCESS;    MI_AUDIO_DEV AoDevId = 0;   
    MI_AO_CHN AoChn = 0;    MI_AUDIO_Frame_t stAoSendFrame;   
    if (frame->type == PJMEDIA_FRAME_TYPE_AUDIO)     {       
        if (frame->size <= 0) {          return PJ_SUCCESS;       
    }       
    memset(&stAoSendFrame, 0x0, sizeof(MI_AUDIO_Frame_t));       
    stAoSendFrame.u32Len = frame->size /  PJMEDIA_PIA_CCNT(&port->info);       
    stAoSendFrame.apVirAddr[0] = frame->buf;       
    stAoSendFrame.apVirAddr[1] = NULL;       
    do        {   
        //-1 blockmode, 0 nonblockmode           
        s32Ret = MI_AO_SendFrame(AoDevId, AoChn, &stAoSendFrame, -1);       
        } while (s32Ret == MI_AO_ERR_NOBUF);       
        if (s32Ret != MI_SUCCESS)        {            printf("[Warning]: MI_AO_SendFrame fail, error is 0x%x: \n", s32Ret);        }   
    }       
    return PJ_SUCCESS;
}
static pj_status_t sine_get_frame(pjmedia_port *port, pjmedia_frame *frame){   
    void *samples = frame->buf;   
    unsigned i, left, right;   
    if (frame->size <= 0) {        return PJ_SUCCESS;    }   
    MI_AUDIO_Frame_t stAiChFrame;   
    MI_AUDIO_AecFrame_t stAecFrame;   
    MI_S32 s32Ret;   
    MI_U32 u32ChnIndex;   
    struct timeval tv_before, tv_after;   
    MI_S64 before_us, after_us;   
    MI_AI_AedResult_t stAedResult;    MI_S32 s32Doa;    MI_U32 AiDevId = 0;   
    MI_U32 AiChn = 0;    MI_BOOL bEnableAed = false;   
    memset(&stAiChFrame, 0, sizeof(MI_AUDIO_Frame_t));   
    memset(&stAecFrame, 0, sizeof(MI_AUDIO_AecFrame_t));    //-1 blockmode, 0 nonblockmode   
    s32Ret = MI_AI_GetFrame(AiDevId, AiChn, &stAiChFrame, &stAecFrame, -1);   
    if (MI_SUCCESS == s32Ret)    {       
        memcpy(samples, stAiChFrame.apVirAddr[0], stAiChFrame.u32Len);       
        MI_AI_ReleaseFrame(AiDevId, AiChn, &stAiChFrame, NULL);  
    }   
    frame->type = PJMEDIA_FRAME_TYPE_AUDIO;   
    return PJ_SUCCESS;
}

5,挂断

status = pjsua_call_hangup(current_call, 0, NULL, NULL);

参考链接:

https://www.renrendoc.com/paper/110170462.html

相关文章

  • PJSIP自定义语音

    缩写注释: SDP(会话描述协议): 用于两个会话实体之间的媒体协商,并达成一致,属信令语言族,采用文本(字符)描...

  • 2018-08-16

    Android 语音通话模块介绍(一) PJSIP简介 PJSIP是一个开放源代码的SIP协议栈;官网地址(h...

  • pjsip

    pjsip 视频通话 语音通话基础上增加 pj_status_t status; pj_str_tdest...

  • pjsip开发——专网对讲机项目架构

      去年,由于公司项目需求,开发了一套基于pjsip的智能终端对讲机项目,主要业务是语音实时通信功能。废话不多说,...

  • libpjsua2.so.2: cannot open shar

    遇到问题: pjsip安装好之后,编译运行 pjproject-2.12.1/pjsip-apps/src/swi...

  • PJSIP开发VoIP记录3-通话的实现

    PJSIP开发VoIP记录1 - 编译与集成 PJSIP开发VoIP记录2 - 配置 开发工具:Xcode9.2开...

  • pjsip编译

    iOS之PJSIP的编译与简单使用 原创2017年02月22日 16:26:12 标签: ios/ pjsip/ ...

  • 树莓派使用PJSIP

    本文用来记录在RASPBERRY4上编译,使用PJSIP的记录 1,下载PJSIP 下载地址:https://gi...

  • PJSIP for iOS:一、PJSIP库的编译

    PJSIP is a free and open sourcemultimedia communication l...

  • iOS音视频开源框架PJSIP入门-编译

    背景 PJSIP is a free and open source multimedia communicati...

网友评论

      本文标题:PJSIP自定义语音

      本文链接:https://www.haomeiwen.com/subject/sueijrtx.html