简体   繁体   English

pjsip 捕获和播放 pcm 数据

[英]pjsip capture and play pcm data

I have some embedded Devices that have no audio device by default.我有一些默认情况下没有音频设备的嵌入式设备。 They communicate with each other via a FPGA.它们通过 FPGA 相互通信。 So my question is, how do I capture/play back audio from pjsip in pcm in order to send/receive it with the FPGA?所以我的问题是,如何从 pcm 中的 pjsip 捕获/播放音频,以便使用 FPGA 发送/接收它?

I know that there is pjmedia_mem_player_create() and pjmedia_mem_capture_create() but I can't seem to find any good info towards using these functions.我知道有pjmedia_mem_player_create()pjmedia_mem_capture_create()但我似乎找不到任何关于使用这些函数的好信息。

I tried the following piece of code, but an assertion failed cause one of the function's parameter is "empty".我尝试了下面的一段代码,但断言失败,因为函数的参数之一是“空”。

Error:错误:

pjmedia_mem_capture_create: Assertion `pool && buffer && size && clock_rate && channel_count && samples_per_frame && bits_per_sample && p_port' failed. pjmedia_mem_capture_create:断言`pool && buffer && size && clock_rate && channel_count && samples_per_frame && bits_per_sample && p_port'失败。

Note : I'm mainly using pjsua2 for everything else like registrations, transports etc. Also the default audio is set to null with ep.audDevManager().setNullDev();注意:我主要将 pjsua2 用于其他所有内容,例如注册、传输等。此外,使用ep.audDevManager().setNullDev();将默认音频设置为 null as without this, making/receiving a call would simply fail?!如果没有这个,拨打/接听电话就会失败?!

void MyCall::onCallMediaState(OnCallMediaStateParam &prm){
CallInfo ci = getInfo();

pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
pj_pool_t *pool = pj_pool_create(&cp.factory, "POOLNAME", 2000, 2000, NULL);

void *buffer;
pjmedia_port *prt;

#define CLOCK_RATE 8000
#define CHANELS 1
#define SAMPLES_PER_FRAME 480
#define BITS_PER_SAMPLE 16

pjmedia_mem_capture_create( pool, //Pool
                            buffer, //Buffer
                            2000, //Buffer Size
                            CLOCK_RATE, 
                            CHANELS, 
                            SAMPLES_PER_FRAME, 
                            BITS_PER_SAMPLE, 
                            0, //Options
                            &prt); //The return port}

UPDATE更新

The assertion failed cause the buffer variable doesn't have any memory allocated to it.断言失败导致缓冲区变量没有分配任何内存。 Allocate with twice the amount of samples per frame to have sufficient memory.每帧分配两倍的样本量以获得足够的内存。

 buffer = pj_pool_zalloc(pool, 960);

Also a callback needs to be registered with pjmedia_mem_capture_set_eof_cb2() (The two at the end is necessary for PJSIP 2.10 or later) Apparently from there the buffer can be used.还需要使用pjmedia_mem_capture_set_eof_cb2()注册回调pjmedia_mem_capture_set_eof_cb2() PJSIP 2.10 或更高版本需要末尾的两个)显然可以使用缓冲区。 Just that my implementation atm doesn't execute the callback.只是我的实现 atm 不执行回调。

Looks like I found the solution, I have modified your code and wrote a simple code in C with pjsua API to dump every frame to file.看起来我找到了解决方案,我修改了您的代码并使用 pjsua API 在 C 中编写了一个简单的代码,以将每一帧转储到文件中。 Sorry for mess, I'm not proficient in C:对不起,我不精通C:

pjsua_call_info ci;
pjsua_call_get_info(call_id, &ci);
pjsua_conf_port_info cpi;
pjsua_conf_get_port_info(ci.conf_slot, &cpi);

pj_pool_t *pool = pjsua_pool_create("POOLNAME", 2000, 2000);
pjmedia_port *prt;
uint buf_size = cpi.bits_per_sample*cpi.samples_per_frame/8;
void *buffer = pj_pool_zalloc(pool, buf_size);
pjsua_conf_port_id port_id;

pjmedia_mem_capture_create( pool,
                            buffer,
                            buf_size,
                            cpi.clock_rate,
                            cpi.channel_count,
                            cpi.samples_per_frame,
                            cpi.bits_per_sample,
                            0,
                            &prt);
pjmedia_mem_capture_set_eof_cb(prt, buffer, dump_incoming_frames);
pjsua_conf_add_port(pool, prt, &port_id);
pjsua_conf_connect(ci.conf_slot, port_id); //connect port with conference

///////dumping frames///
static pj_status_t dump_incoming_frames(pjmedia_port * port, void * usr_data){
   pj_size_t buf_size = pjmedia_mem_capture_get_size(port);
   char * data = usr_data;
   ...
   fwrite(data,sizeof(data[0]),buf_size,fptr);
   ...
}

Documenation says pjmedia_mem_capture_set_eof_cb is deprecated but I couldn't make work pjmedia_mem_capture_set_eof_cb2 , buf_size is 0 for every call of dump_incoming_frames so just left with deprecated function. Documenation说pjmedia_mem_capture_set_eof_cb已被弃用,但我不能让工作pjmedia_mem_capture_set_eof_cb2buf_size是0的每一个电话dump_incoming_frames所以只留下了不推荐使用的功能。 I also succeed the same result with creating custom port .我也通过创建自定义端口获得了相同的结果。

I hope you can modify it easily to your C++/pjsua2 code我希望您可以轻松地将其修改为您的 C++/pjsua2 代码

UPD: I have modified the PJSIP and packed audio in-out streaming into proper PJSUA2/Media classes so it can be called from Python. UPD:我已经修改了 PJSIP 并将音频输入输出流打包到适当的 PJSUA2/Media 类中,以便可以从 Python 调用它。 Full code is here .完整代码在这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM