ios pjsip - 在 sip 通话期间播放声音

标签 ios sip pjsip audiotoolbox

当我在 sip 通话时,有时我想发送 dtmf 数字。
为此,我创建了一个自定义拨号盘,当按下某个键时应该播放该键的声音,但它不会在 sip 通话期间播放该声音(当没有通话时,会播放声音)。
这些声音是使用 AudioToolbox.h 库 (AudioServicesPlaySystemSound(soundID)) 中的函数播放的。

是否需要在 pjsip (pjsua) 或 AudioToolbox 库中设置一些属性,以便在 sip 通话期间播放声音?
我知道这是可能的(Bria 有这个,Groundwire 也不确定他们是否使用 pjsip 来实现 sip)。

最佳答案

这个答案是来自这两个链接的代码片段的组合:PJSUA-API Media ManipulationpjsipDll_PlayWav.cpp .

当 pjsua 进行调用时,它正在使用端口( session 端口)将媒体从调用目的地传输到您的设备扬声器。 您可以同时打开多个端口

所以我们要播放我们的键盘按钮点击声音的方法是再打开一个端口并播放声音(在这种情况下它是一个 wav 文件,你可以注意到还有一个用于流式传输的 pjsua 函数avi 文件)。
为此,我们将使用此功能:

 pj_status_t    pjsua_conf_connect (pjsua_conf_port_id source, pjsua_conf_port_id sink)

我们的接收器端口是我们的设备扬声器端口,在这种情况下(而且大多数情况下)它是 0。

以下所有函数都添加到 pjsua_app.c 文件中。 在 Objective-C 类中使用它们的地方之前,您必须添加如下一行:

pj_status_t play_sound_during_call(pj_str_t sound_file);

这里要播放声音的是函数:

pj_status_t play_sound_during_call(pj_str_t sound_file)
{
    pjsua_player_id player_id;
    pj_status_t status;
    status = pjsua_player_create(&sound_file, 0, &player_id);
    if (status != PJ_SUCCESS)
        return status;

    pjmedia_port *player_media_port;

    status = pjsua_player_get_port(player_id, &player_media_port);
    if (status != PJ_SUCCESS)
    {
        return status;
    }

    pj_pool_t *pool = pjsua_pool_create("my_eof_data", 512, 512);
    struct pjsua_player_eof_data *eof_data = PJ_POOL_ZALLOC_T(pool, struct pjsua_player_eof_data);
    eof_data->pool = pool;
    eof_data->player_id = player_id;

    pjmedia_wav_player_set_eof_cb(player_media_port, eof_data, &on_pjsua_wav_file_end_callback);

    status = pjsua_conf_connect(pjsua_player_get_conf_port(player_id), 0);

    if (status != PJ_SUCCESS)
    {
        return status;
    }        

    return status;
}

这里是当你的 wav 文件读取(播放)结束时监听的回调函数:

struct pjsua_player_eof_data
{
    pj_pool_t          *pool;
    pjsua_player_id player_id;
};

static PJ_DEF(pj_status_t) on_pjsua_wav_file_end_callback(pjmedia_port* media_port, void* args)
{
    pj_status_t status;

    struct pjsua_player_eof_data *eof_data = (struct pjsua_player_eof_data *)args;

    status = pjsua_player_destroy(eof_data->player_id);

    PJ_LOG(3,(THIS_FILE, "End of Wav File, media_port: %d", media_port));

    if (status == PJ_SUCCESS)
    {
        return -1;// Here it is important to return a value other than PJ_SUCCESS
                  //Check link below
    }

    return PJ_SUCCESS;
}

pjmedia_wav_player_set_eof_cb 回调函数应该返回 PJ_SUCCESS 以外的值的原因是因为此处的文档 pjmedia_wav_player_set_eof_cb说:

请注意,如果应用程序在回调中破坏了文件端口,则必须在此处返回非 PJ_SUCCESS。

关于ios pjsip - 在 sip 通话期间播放声音,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19047771/

相关文章:

iphone - 使用适用于 iOS 的 OpenGL ES 绘制正方形

iphone - 当CGPointMake遇到大数目时

ios - Swift:访问通过post请求收到的JSON

audio - 如何将 PJSIP 与 VOIP 聊天框示例应用程序 Windows Phone 8 集成

ios - 突出显示要按下的按钮,并取消突出显示未按下的按钮SWIFT

Android SIP API : Shows supported, 但错误 'not supported'

android - Android 中使用 openfire 的 VoIP 和 SIP 客户端应用程序

java - 高性能 rtsp 服务器

android - 切换android Activity 时的致命信号6(SIGABRT)

c++ - PJSUA2 - 将通话音频录制到 wav 文件