#include <pjsua-lib/pjsua.h>
#include <pjsua-lib/pjsua_internal.h>
#include <pjmedia/port.h>
#include <pjmedia/errno.h>
#include <pj/assert.h>
#include <pj/pool.h>
#include <pj/string.h>
#define SIGNATURE PJMEDIA_SIG_CLASS_PORT_AUD('C','B')
struct callback_port {
pjmedia_port base;
};
extern void C_put_frame(int, void*, pj_size_t);
extern pj_status_t C_get_frame(int, void*, pj_size_t);
static void init_conference() {
pjsua_var.media_cfg.clock_rate = 48000;
pjsua_var.mconf_cfg.channel_count = 2;
pjsua_var.mconf_cfg.bits_per_sample = 16;
pjsua_var.mconf_cfg.samples_per_frame = pjsua_var.media_cfg.clock_rate * pjsua_var.mconf_cfg.channel_count * pjsua_var.media_cfg.audio_frame_ptime / 1000;
unsigned opt = 0;
opt = PJMEDIA_CONF_NO_DEVICE;
if (pjsua_var.media_cfg.quality >= 3 && pjsua_var.media_cfg.quality <= 4) {
opt |= PJMEDIA_CONF_SMALL_FILTER;
} else if (pjsua_var.media_cfg.quality < 3) {
opt |= PJMEDIA_CONF_USE_LINEAR;
}
pj_status_t status = pjmedia_conf_create(pjsua_var.pool,
pjsua_var.media_cfg.max_media_ports,
pjsua_var.media_cfg.clock_rate,
pjsua_var.mconf_cfg.channel_count,
pjsua_var.mconf_cfg.samples_per_frame,
pjsua_var.mconf_cfg.bits_per_sample,
opt, &pjsua_var.mconf);
}
static pj_status_t callback_port_put_frame(pjmedia_port *this_port, pjmedia_frame *frame) {
const struct callback_port *port;
PJ_ASSERT_RETURN(this_port->info.signature == SIGNATURE, PJ_EINVALIDOP);
port = (struct callback_port*) this_port;
if (frame->type == PJMEDIA_FRAME_TYPE_AUDIO) {
C_put_frame(0, frame->buf, frame->size);
}
return PJ_SUCCESS;
}
static pj_status_t callback_port_get_frame(pjmedia_port *this_port, pjmedia_frame *frame) {
PJ_ASSERT_RETURN(this_port->info.signature == SIGNATURE, PJ_EINVALIDOP);
// TODO
return PJ_SUCCESS;
}
static pj_status_t callback_port_on_destroy(pjmedia_port *this_port) {
PJ_ASSERT_RETURN(this_port->info.signature == SIGNATURE, PJ_EINVALIDOP);
this_port->info.signature = 0;
return PJ_SUCCESS;
}
static int callback_audio_device_create(unsigned *rrec_id, unsigned *rslot) {
if (pjsua_var.rec_cnt >= PJ_ARRAY_SIZE(pjsua_var.recorder)) {
return PJ_ETOOMANY;
}
unsigned rec_id, slot;
PJSUA_LOCK();
for (rec_id = 0; rec_id < PJ_ARRAY_SIZE(pjsua_var.recorder); ++rec_id) {
if (pjsua_var.recorder[rec_id].port == NULL) {
break;
}
}
pj_pool_t *pool = pjsua_pool_create("callback-audio", 512, 512);
if (!pool) {
PJSUA_UNLOCK();
return PJ_ENOMEM;
}
struct callback_port *port;
port = PJ_POOL_ZALLOC_T(pool, struct callback_port);
if (port == NULL) {
PJSUA_UNLOCK();
return PJ_ENOMEM;
}
const pj_str_t name = pj_str("callback-port");
pjmedia_port_info_init(
&port->base.info,
&name,
SIGNATURE,
pjsua_var.media_cfg.clock_rate,
pjsua_var.mconf_cfg.channel_count,
pjsua_var.mconf_cfg.samples_per_frame,
pjsua_var.mconf_cfg.bits_per_sample
);
port->base.on_destroy = &callback_port_on_destroy;
port->base.put_frame = &callback_port_put_frame;
port->base.get_frame = &callback_port_get_frame;
pj_status_t status = pjmedia_conf_add_port(pjsua_var.mconf, pool, &port->base, &name, &slot); // <- SIGFPE
if (status != PJ_SUCCESS) {
pjmedia_port_destroy(&port->base);
PJSUA_UNLOCK();
return status;
}
pjsua_var.recorder[rec_id].port = &port->base;
pjsua_var.recorder[rec_id].slot = slot;
pjsua_var.recorder[rec_id].pool = pool;
pjsua_var.rec_cnt++;
PJSUA_UNLOCK();
*rrec_id = rec_id;
*rslot = slot;
return PJ_SUCCESS;
}
static void callback_audio_device_destroy(unsigned id) {
PJSUA_LOCK();
if (pjsua_var.recorder[id].port) {
pjsua_conf_remove_port(pjsua_var.recorder[id].slot);
pjmedia_port_destroy(pjsua_var.recorder[id].port);
pjsua_var.recorder[id].port = NULL;
pjsua_var.recorder[id].slot = 0xFFFF;
pj_pool_release(pjsua_var.recorder[id].pool);
pjsua_var.recorder[id].pool = NULL;
pjsua_var.rec_cnt--;
}
PJSUA_UNLOCK();
}
随叫随到pjmedia_conf_add_port
_fatal error: unexpected signal during runtime execution
[signal SIGFPE: floating-point exception code=0x1 addr=0x7f466bd37f32 pc=0x7f466bd37f32]
当我尝试将采样率设置为高于 16kHz 和/或超过 1 个通道时,就会发生这种情况。
我需要使用具有 48kHz 采样率和 2 个通道的回调从呼叫中发送/接收 PCM 数据。
我究竟做错了什么?GDB 显示:
Thread 22 "call_bot" received signal SIGFPE, Arithmetic exception.
[Switching to Thread 0x7fffd0ff9700 (LWP 39156)]
0x00007ffff7b98f32 in ?? () from /usr/lib/libpjmedia.so.2
(gdb) bt
#0 0x00007ffff7b98f32 in ?? () from /usr/lib/libpjmedia.so.2
#1 0x00007ffff7b9a62e in pjmedia_conf_add_port () from /usr/lib/libpjmedia.so.2
#2 0x000000000083e931 in callback_audio_device_create (rslot=0xc000308b94, rrec_id=0xc000308b90) at /home/zabqer/0/sip/callback_audio_device.c:121
#3 _cgo_eb4dc7f96a71_Cfunc_callback_audio_device_create (v=0xc00042dcd8) at cgo-gcc-prolog:54