0
#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
4

0 回答 0