PjSIP and memory captures...

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,
as first: I'm not a professional at this topic and I'm really trying my best, but now I'm stuck and don't know what to do. I want to modify my program, which is using PjSIP to create and do a wav-file-record, to perform a memory_capture to a buffer - this requires a existing call-conference - i guess (otherwise I will get error 70004). The easy-to-use function "pjsua_recorder_create()" does all by itself and i can get in a very simple way a plain old recorder to file. After copy-and-pasting (i choosed this snippet from "pjsua_aud.c", because it needs only little modifications to work with the memory_capture) THIS code...
```
PJ_DEF(pj_status_t) pjsua_recorder_create( const pj_str_t *filename,
                       unsigned enc_type,
                       void *enc_param,
                       pj_ssize_t max_size,
                       unsigned options,
                       pjsua_recorder_id *p_id)
{
    enum Format
    {
    FMT_UNKNOWN,
    FMT_WAV,
    FMT_MP3,
    };
    unsigned slot, file_id;
    char path[PJ_MAXPATH];
    pj_str_t ext;
    int file_format;
    pj_pool_t *pool = NULL;
    pjmedia_port *port;
    pj_status_t status = PJ_SUCCESS;

    /* Filename must present */
    PJ_ASSERT_RETURN(filename != NULL, PJ_EINVAL);

    /* Don't support max_size at present */
    PJ_ASSERT_RETURN(max_size == 0 || max_size == -1, PJ_EINVAL);

    /* Don't support encoding type at present */
    PJ_ASSERT_RETURN(enc_type == 0, PJ_EINVAL);

    PJ_LOG(4,(THIS_FILE, "Creating recorder %.*s..",
          (int)filename->slen, filename->ptr));
    pj_log_push_indent();

    if (pjsua_var.rec_cnt >= PJ_ARRAY_SIZE(pjsua_var.recorder)) {
    pj_log_pop_indent();
    return PJ_ETOOMANY;
    }

    /* Determine the file format */
    ext.ptr = filename->ptr + filename->slen - 4;
    ext.slen = 4;

    if (pj_stricmp2(&ext, ".wav") == 0)
    file_format = FMT_WAV;
    else if (pj_stricmp2(&ext, ".mp3") == 0)
    file_format = FMT_MP3;
    else {
    PJ_LOG(1,(THIS_FILE, "pjsua_recorder_create() error: unable to "
                 "determine file format for %.*s",
                 (int)filename->slen, filename->ptr));
    pj_log_pop_indent();
    return PJ_ENOTSUP;
    }

    PJSUA_LOCK();

    for (file_id=0; file_id<PJ_ARRAY_SIZE(pjsua_var.recorder); ++file_id) {
    if (pjsua_var.recorder[file_id].port == NULL)
        break;
    }

    if (file_id == PJ_ARRAY_SIZE(pjsua_var.recorder)) {
    /* This is unexpected */
    pj_assert(0);
    status = PJ_EBUG;
    goto on_return;
    }

    pj_memcpy(path, filename->ptr, filename->slen);
    path[filename->slen] = '\0';

    pool = pjsua_pool_create(get_basename(path, (unsigned)filename->slen), 1000,
                 1000);
    if (!pool) {
    status = PJ_ENOMEM;
    goto on_return;
    }

    if (file_format == FMT_WAV) {
    status = pjmedia_wav_writer_port_create(pool, path,
                        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,
                        options, 0, &port);
    } else {
    PJ_UNUSED_ARG(enc_param);
    port = NULL;
    status = PJ_ENOTSUP;
    }

    if (status != PJ_SUCCESS) {
    pjsua_perror(THIS_FILE, "Unable to open file for recording", status);
    goto on_return;
    }

    status = pjmedia_conf_add_port(pjsua_var.mconf, pool,
                   port, filename, &slot);
    if (status != PJ_SUCCESS) {
    pjmedia_port_destroy(port);
    goto on_return;
    }

    pjsua_var.recorder[file_id].port = port;
    pjsua_var.recorder[file_id].slot = slot;
    pjsua_var.recorder[file_id].pool = pool;

    if (p_id) *p_id = file_id;

    ++pjsua_var.rec_cnt;

    PJSUA_UNLOCK();

    PJ_LOG(4,(THIS_FILE, "Recorder created, id=%d, slot=%d", file_id, slot));

    pj_log_pop_indent();
    return PJ_SUCCESS;

on_return:
    PJSUA_UNLOCK();
    if (pool) pj_pool_release(pool);
    pj_log_pop_indent();
    return status;
}
```
...(of the normal recorder-to-file) to my program (and modified it) - it create a 44 bytes big file and thats it. I guess my problem is, that my modified version uses a new instance of a pjmedia_conf* (createt by pjmedia_conf_create()), which is not connected with the incoming call. So my questions are: - How I can bind an existing call (e.g. with its call_info) to a new conference (conf)? - Or how can I get the default "pjsua_var.mconf" to use it inside the mem_capture or at least with this extracted code snippet? - Or has anyone a good snippet with an example of the usage of PjSIP calls with mem_capture? This here is a good example of the high-level-recorder-to-wav function: "http://binerry.de/post/29180946733/raspberry-pi-caller-and-answering-machine"; - but I would love to see a code snippet with the direct source code of the easy-to-use-function, so I can simply modify it to work with the mem_capture. - Can *anyone* explain me, how PjSIP-Conference/Media structures work (How to use ports, what are the slots - what can I get from the "normal" call_info - structures)? I've read the documentation really often, but I don't know what I'm doing wrong...

Btw this is my modified version - yeah I know it is dirty...
```
void VoIP_client::record_wav_start(string filename_out) {
    //Update call_info
    pjsua_call_get_info(this->call_id, &this->call_info);

    pj_str_t rec_file;
    pj_status_t status = PJ_ENOTFOUND;

    VoIP::voip_log->log_msg("[VoIP] [REC] Creating recorder for " + string(this->call_info.remote_info.ptr), LOG_DEBUG);

    // Create recorder for call
    //status = pjsua_recorder_create(pj_cstr(&rec_file, filename_out.c_str()), 0, NULL, 0, 0, &this->recorder_id);
    {
        const pj_str_t *filename = pj_cstr(&rec_file, filename_out.c_str());
        unsigned options = 0;
        unsigned pjsua_var_rec_cnt;
        pjmedia_port * pjsua_var_recorder_0_port;
        unsigned pjsua_var_recorder_0_slot;
        pj_pool_t * pjsua_var_recorder_0_pool;
        pjmedia_conf * pjsua_var_mconf;

        enum Format {
            FMT_UNKNOWN,
            FMT_WAV,
            FMT_MP3,
        };
        unsigned slot, file_id;
        char path[PJ_MAXPATH];
        pj_str_t ext;
        int file_format;
        pj_pool_t *pool = NULL;
        pjmedia_port *port;
        pj_status_t statust = PJ_SUCCESS;

        /* Filename must present */
        //PJ_ASSERT_RETURN(filename != NULL, PJ_EINVAL);

        /* Don't support max_size at present */
        //PJ_ASSERT_RETURN(max_size == 0 || max_size == -1, PJ_EINVAL);

        /* Don't support encoding type at present */
        //PJ_ASSERT_RETURN(enc_type == 0, PJ_EINVAL);

        PJ_LOG(4, ("", "Creating recorder %.*s..",
                (int) filename->slen, filename->ptr));
        pj_log_push_indent();

        //if (pjsua_var_rec_cnt >= PJ_ARRAY_SIZE(pjsua_var.recorder)) {
        //    pj_log_pop_indent();
        //    return PJ_ETOOMANY;
        // }

        /* Determine the file format */
        ext.ptr = filename->ptr + filename->slen - 4;
        ext.slen = 4;

        if (pj_stricmp2(&ext, ".wav") == 0)
            file_format = FMT_WAV;
        else if (pj_stricmp2(&ext, ".mp3") == 0)
            file_format = FMT_MP3;
        else {
            PJ_LOG(1, ("", "pjsua_recorder_create() error: unable to "
                    "determine file format for %.*s",
                    (int) filename->slen, filename->ptr));
            pj_log_pop_indent();
            exit(PJ_ENOTSUP);
        }

        //for (file_id = 0; file_id < PJ_ARRAY_SIZE(pjsua_var.recorder); ++file_id) {
        //    if (pjsua_var_recorder_0_port == NULL)
        //        break;
        //}

        //if (file_id == PJ_ARRAY_SIZE(pjsua_var.recorder)) {
        //    /* This is unexpected */
        //    pj_assert(0);
        //    status = PJ_EBUG;
        //    goto on_return;
        //}

        pj_memcpy(path, filename->ptr, filename->slen);
        path[filename->slen] = '\0';

        pool = pjsua_pool_create("pool1", 1000,
                1000);
        if (!pool) {
            statust = PJ_ENOMEM;
            goto on_return;
        }

        if (file_format == FMT_WAV) {
            statust = pjmedia_wav_writer_port_create(pool, path,
                    8000, //pjsua_var.media_cfg.clock_rate,
                    1, //pjsua_var.mconf_cfg.channel_count,
                    160, //pjsua_var.mconf_cfg.samples_per_frame,
                    16, //pjsua_var.mconf_cfg.bits_per_sample,
                    options, 0, &port);
        } else {
            port = NULL;
            exit(PJ_ENOTSUP);
        }

        if (statust != PJ_SUCCESS) {
            pjsua_perror("", "Unable to open file for recording", status);
            goto on_return;
        }

        status = pjmedia_conf_create(
                pool,
                1 /*Phone*/ + 1 /*Sound device*/,
                8000 /*8kHz clock rate*/,
                1 /*Channel count*/,
                160 /*samples_per_frame*/,
                16 /*bits_per_sample*/,
                PJMEDIA_CONF_NO_DEVICE /* options */,
                &pjsua_var_mconf /* result */);
        if (status != PJ_SUCCESS)
            VoIP::voip_log->log_msg("[VoIP] Error on creating conference for client " + string(this->call_info.remote_info.ptr) + ": " + to_string(status), LOG_ERROR);

        statust = pjmedia_conf_add_port(pjsua_var_mconf, pool, port, filename, &slot);
        if (statust != PJ_SUCCESS) {
            pjmedia_port_destroy(port);
            goto on_return;
        }

        pjsua_var_recorder_0_port = port;
        pjsua_var_recorder_0_slot = slot;
        pjsua_var_recorder_0_pool = pool;

        //if (p_id) *p_id = file_id;

        //++pjsua_var.rec_cnt;

        PJ_LOG(4, ("", "Recorder created, id=%d, slot=%d", file_id, slot));

        pj_log_pop_indent();
        status = PJ_SUCCESS;

on_return:
        if (pool) pj_pool_release(pool);
        pj_log_pop_indent();
        //exit(statust);
    }
    if (status != PJ_SUCCESS)
        VoIP::voip_log->log_msg("[VoIP] [REC] Error recording answer" + to_string(status), LOG_ERROR);

    //Connect recorder with a new virtual phone conference
    pjsua_conf_port_id rec_port = pjsua_recorder_get_conf_port(this->recorder_id);
    pjsua_conf_connect(this->call_info.conf_slot, rec_port);

    VoIP::voip_log->log_msg("[VoIP] [REC] Created a recorder for " + string(this->call_info.remote_info.ptr), LOG_DEBUG);

}
```

Thank to anyone who can help or at least understands waht i want and where i fail.
Simonmicro


_______________________________________________
Visit our blog: http://blog.pjsip.org

pjsip mailing list
pjsip@xxxxxxxxxxxxxxx
http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org




[Index of Archives]     [Asterisk Users]     [Asterisk App Development]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [Linux API]
  Powered by Linux