当没有音频硬件设备时,如何从PJSIP获取音频流
我想使用PJSIP的C API将传入的音频记录到一个没有硬件声音设备的机器上的文件中 我不确定具体细节,但PJSIP的稀疏文档表明应该这样做 可以通过调用当没有音频硬件设备时,如何从PJSIP获取音频流,sip,audio-streaming,pjsip,Sip,Audio Streaming,Pjsip,我想使用PJSIP的C API将传入的音频记录到一个没有硬件声音设备的机器上的文件中 我不确定具体细节,但PJSIP的稀疏文档表明应该这样做 可以通过调用pjsua\u set\u null\u snd\u dev() 在下面的完全功能(Windows偏向)示例中,调用pjmedia_aud_dev_default_param(pjmedia_aud_default_CAPTURE_dev,¶m)返回状态为pjmedia_aud_INVALID_dev 当Linux(Ubuntu14)和
pjsua\u set\u null\u snd\u dev()
在下面的完全功能(Windows偏向)示例中,调用pjmedia_aud_dev_default_param(pjmedia_aud_default_CAPTURE_dev,¶m)
返回状态为pjmedia_aud_INVALID_dev
当Linux(Ubuntu14)和Windows10上没有硬件音频设备时,代码会产生相同的错误。
如果安装了硬件音频设备驱动程序,则在两个操作系统上都可以使用完全相同的代码
我在编译PJSIP库时启用了PJMEDIA\u AUDIO\u DEV\u NULL\u AUDIO
。
在Linux上,模块snd dummy
的存在没有帮助
调用pjsua\u set\u null\u snd\u dev()
后,如何从SIP调用访问音频数据流
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int main(int,char**)
{
//首先创建pjsua!
pj_status_t status=pjsua_create();
如果(状态!=PJ_成功)
{
fprintf(stderr,“pjsua_创建错误”);
返回-1;
}
//Init pjsua
pjsua_配置cfg;
pjsua_日志记录_配置日志_cfg;
pjsua_配置_默认值(&cfg);
pjsua\u日志记录\u配置\u默认值(&log\u cfg);
log_cfg.console_level=4;
status=pjsua_init(&cfg,&log_cfg,NULL);
如果(状态!=PJ_成功)
{
fprintf(stderr,“pjsua_init error\n”);
返回-1;
}
//主动列出已知的音频设备,以便我们确定没有
pjmedia_aud_dev_info[64];
未签名信息计数=64;
pjsua_enum_aud_devs(信息和信息计数);
fprintf(stderr,“列出已知的声音设备,总计[%u]\n”,信息计数);
for(无符号i=0;iinfo);
param.samples_per_frame=PJMEDIA_PIA_SPF(&wav->info);
param.channel_count=PJMEDIA_PIA_CCNT(&wav->info);
param.bits_per_sample=PJMEDIA_PIA_bits(&wav->info);
状态=pjmedia_aud_stream_create(¶m,&test_rec_cb,&test_play_cb,wav,&strm);
如果(状态!=PJ_成功)
{
fprintf(stderr,“打开声音流时出错”);
返回-1;
}
状态=pjmedia_aud_stream_start(strm);
如果(状态!=PJ_成功)
{
fprintf(标准“启动声音设备时出错”);
返回-1;
}
//花一些时间让被叫方接收并继续录音
睡眠(10000);//睡眠10秒
//清除代码省略
返回0;
}
<> P.>通过加载ALSA模块解决了这个问题。 C++。
查看/lib/modules/YOUR_KERNEL\u VERSION/modules.dep
,如果有提及
如果有,则使用modprobe snd dummy
否则,请重新编译内核,将其作为一个模块包含,或者按照上面链接中的安装进行操作。pjsua\u set\u null\u snd\u dev()用于断开pjsip中的音频流。它必须在结束通话时使用。我不久前解决了这个问题,如果您急需答案,请告诉我,我会发布。@JimmyNJ如果您可以发布答案,我对这个问题的解决方案感兴趣。不,对不起,这不起作用,我尝试了模块问题。并且无法重新编译内核。编译库时是否启用了Alsa支持?我在PJMEDIA/include/PJMEDIA audiodev/config.h
和pjlib/include/pj/config\u site\u sample.h
中设置了#define PJMEDIA_AUDIO_DEV_HAS_ALSA
为1,我的自动功能选项还包括--enable sound。资料来源:我不久前解决了这个问题,如果您迫切需要答案,请告诉我,我会发布它JimmyNJ 7月30日1:11我也解决了这个问题,并在这里发布了我是如何解决的。我以为你没有解决它,因为这里没有答案?!
#include <pjlib.h>
#include <pjlib-util.h>
#include <pjnath.h>
#include <pjsip.h>
#include <pjsip_ua.h>
#include <pjsip_simple.h>
#include <pjsua-lib/pjsua.h>
#include <pjmedia.h>
#include <pjmedia-codec.h>
#include <pj/log.h>
#include <pj/os.h>
int main(int, char **)
{
// Create pjsua first!
pj_status_t status = pjsua_create();
if (status != PJ_SUCCESS)
{
fprintf(stderr,"pjsua_create error\n");
return -1;
}
// Init pjsua
pjsua_config cfg;
pjsua_logging_config log_cfg;
pjsua_config_default(&cfg);
pjsua_logging_config_default(&log_cfg);
log_cfg.console_level = 4;
status = pjsua_init(&cfg, &log_cfg, NULL);
if (status != PJ_SUCCESS)
{
fprintf(stderr,"pjsua_init error\n");
return -1;
}
// Proactively list known audio devices so we are sure there are NONE
pjmedia_aud_dev_info info[64];
unsigned info_count = 64;
pjsua_enum_aud_devs(info, &info_count);
fprintf(stderr,"Listing known sound devices, total of [%u]\n", info_count);
for (unsigned i = 0; i<info_count; ++i)
{
fprintf(stderr,"Name [%s]", info[i].name);
}
// Add transport
pjsua_transport_config tcfg;
pjsua_transport_id trans_id;
pjsua_transport_config_default(&tcfg);
tcfg.port = 5060;
status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &tcfg, &trans_id);
if (status != PJ_SUCCESS)
{
fprintf(stderr, "pjsua_transport_create error\n");
return -1;
}
// Initialization is done, now start pjsua
status = pjsua_start();
if (status != PJ_SUCCESS)
{
fprintf(stderr, "pjsua_start error\n");
return -1;
}
// Set NULL sound
status = pjsua_set_null_snd_dev();
if (status != PJ_SUCCESS)
{
fprintf(stderr, "pjsua_set_null_snd_dev error");
return -1;
}
// Register to a SIP server by creating SIP account, I happen use use Asterisk
pjsua_acc_id acc_id;
fprintf(stderr, "Setting up SIP server registration\n");
{
pjsua_acc_config cfg;
pjsua_acc_config_default(&cfg);
cfg.id = pj_str("sip:6001@10.0.0.21");
cfg.reg_uri = cfg.id; // same as ID
cfg.cred_count = 1;
cfg.cred_info[0].realm = pj_str("*");
cfg.cred_info[0].scheme = pj_str("digest");
cfg.cred_info[0].username = pj_str("6001");
cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
cfg.cred_info[0].data = pj_str("teddy");
status = pjsua_acc_add(&cfg, PJ_TRUE, &acc_id);
if (status != PJ_SUCCESS)
{
fprintf(stderr, "pjsua_acc_add error\n");
return -1;
}
}
fprintf(stderr, "Waiting for SIP server registration to complete....\n");
Sleep(2000); // sleep 2 seconds
// Call extension 9 on my Asterisk server at 10.0.0.21:5060
pj_str_t sip_target(pj_str("sip:9@10.0.0.21"));
fprintf(stderr, "Making call to [%s]\n", sip_target.ptr);
pjsua_call_id call_id;
status = pjsua_call_make_call(acc_id, &sip_target, 0, NULL, NULL, &call_id);
if (status != PJ_SUCCESS)
{
fprintf(stderr, "pjsua_call_make_call error\n");
return -1;
}
pj_pool_t * pool = nullptr;
pjmedia_port * wav = nullptr;
pjmedia_aud_stream *strm = nullptr;
pool = pj_pool_create(pjmedia_aud_subsys_get_pool_factory(), "wav-audio", 1000, 1000, NULL);
if (nullptr == pool)
{
fprintf(stderr,"Pool creation failed\n");
return -1;
}
// 8kHz, single channel 16bit MS WAV format file
status = pjmedia_wav_writer_port_create(pool, "test.wav", 8000, 1, 320, 16, PJMEDIA_FILE_WRITE_PCM, 0, &wav);
if (status != PJ_SUCCESS)
{
fprintf(stderr, "Error creating WAV file\n");
return -1;
}
pjmedia_aud_param param;
//////////////////////////////////////////////////////
// FAILURE HERE : This is the function call which returns PJMEDIA_AUD_INVALID_DEV
//////////////////////////////////////////////////////
status = pjmedia_aud_dev_default_param(PJMEDIA_AUD_DEFAULT_CAPTURE_DEV, ¶m);
if (status != PJ_SUCCESS)
{
fprintf(stderr, "pjmedia_aud_dev_default_param()");
return -1;
}
param.dir = PJMEDIA_DIR_CAPTURE;
param.clock_rate = PJMEDIA_PIA_SRATE(&wav->info);
param.samples_per_frame = PJMEDIA_PIA_SPF(&wav->info);
param.channel_count = PJMEDIA_PIA_CCNT(&wav->info);
param.bits_per_sample = PJMEDIA_PIA_BITS(&wav->info);
status = pjmedia_aud_stream_create(¶m, &test_rec_cb, &test_play_cb, wav, &strm);
if (status != PJ_SUCCESS)
{
fprintf(stderr, "Error opening the sound stream");
return -1;
}
status = pjmedia_aud_stream_start(strm);
if (status != PJ_SUCCESS)
{
fprintf(stderr, "Error starting the sound device");
return -1;
}
// Spend some time allowing the called party to pick up and recording to proceed
Sleep(10000); // sleep 10 seconds
// Clean up code omitted
return 0;
}