Загрузка данных


/*
 * Establish unidirectional media flow from souce to sink, with signal
 * level adjustment.
 */
PJ_DEF(pj_status_t) pjsua_conf_connect2( pjsua_conf_port_id source,
                                         pjsua_conf_port_id sink,
                                         const pjsua_conf_connect_param *prm)
{
    pj_status_t status = PJ_SUCCESS;

    PJ_LOG(4,(THIS_FILE, "%s connect: %d --> %d",
              (pjsua_var.is_mswitch ? "Switch" : "Conf"),
              source, sink));

    PJ_ASSERT_RETURN(source >= 0 && sink >= 0, PJ_EINVAL);

    pj_log_push_indent();

    PJSUA_LOCK();

    /* If sound device idle timer is active, cancel it first. */
    if (pjsua_var.snd_idle_timer.id) {
        pjsip_endpt_cancel_timer(pjsua_var.endpt, &pjsua_var.snd_idle_timer);
        pjsua_var.snd_idle_timer.id = PJ_FALSE;
    }


    /* For audio switchboard (i.e. APS-Direct):
     * Check if sound device need to be reopened, i.e: its attributes
     * (format, clock rate, channel count) must match to peer's.
     * Note that sound device can be reopened only if it doesn't have
     * any connection.
     */
    if (pjsua_var.is_mswitch) {
        pjmedia_conf_port_info port0_info;
        pjmedia_conf_port_info peer_info;
        unsigned peer_id;
        pj_bool_t need_reopen = PJ_FALSE;

        peer_id = (source!=0)? source : sink;
        status = pjmedia_conf_get_port_info(pjsua_var.mconf, peer_id,
                                            &peer_info);
        pj_assert(status == PJ_SUCCESS);

        status = pjmedia_conf_get_port_info(pjsua_var.mconf, 0, &port0_info);
        pj_assert(status == PJ_SUCCESS);

        /* Check if sound device is instantiated. */
        need_reopen = (pjsua_var.snd_port==NULL && pjsua_var.null_snd==NULL &&
                      !pjsua_var.no_snd);

        /* Check if sound device need to reopen because it needs to modify
         * settings to match its peer. Sound device must be idle in this case
         * though.
         */
        if (!need_reopen &&
            port0_info.listener_cnt==0 && port0_info.transmitter_cnt==0)
        {
            need_reopen = (peer_info.format.id != port0_info.format.id ||
                           peer_info.format.det.aud.avg_bps !=
                                   port0_info.format.det.aud.avg_bps ||
                           peer_info.clock_rate != port0_info.clock_rate ||
                           peer_info.channel_count!=port0_info.channel_count);
        }

        if (need_reopen) {
            if (pjsua_var.cap_dev != PJSUA_SND_NULL_DEV) {
                pjmedia_snd_port_param param;

                pjmedia_snd_port_param_default(&param);
                param.ec_options = pjsua_var.media_cfg.ec_options;

                /* Create parameter based on peer info */
                status = create_aud_param(&param.base, pjsua_var.cap_dev,
                                          pjsua_var.play_dev,
                                          peer_info.clock_rate,
                                          peer_info.channel_count,
                                          peer_info.samples_per_frame,
                                          peer_info.bits_per_sample,
                                          PJ_FALSE);
                if (status != PJ_SUCCESS) {
                    pjsua_perror(THIS_FILE, "Error opening sound device",
                                 status);
                    goto on_return;
                }

                /* And peer format */
                if (peer_info.format.id != PJMEDIA_FORMAT_PCM) {
                    param.base.flags |= PJMEDIA_AUD_DEV_CAP_EXT_FORMAT;
                    param.base.ext_fmt = peer_info.format;
                }

                param.options = 0;
                status = open_snd_dev(&param);
                if (status != PJ_SUCCESS) {
                    pjsua_perror(THIS_FILE, "Error opening sound device",
                                 status);
                    goto on_return;
                }
            } else {
                /* Null-audio */
                status = pjsua_set_snd_dev(pjsua_var.cap_dev,
                                           pjsua_var.play_dev);
                if (status != PJ_SUCCESS) {
                    pjsua_perror(THIS_FILE, "Error opening sound device",
                                 status);
                    goto on_return;
                }
            }
        } else if (pjsua_var.no_snd) {
            if (!pjsua_var.snd_is_on) {
                pjsua_var.snd_is_on = PJ_TRUE;
                /* Notify app */
                if (pjsua_var.ua_cfg.cb.on_snd_dev_operation) {
                    (*pjsua_var.ua_cfg.cb.on_snd_dev_operation)(1);
                }
            }
        }

    } else {
        /* The bridge version */

        /* Create sound port if none is instantiated */
        if (pjsua_var.snd_port==NULL && pjsua_var.null_snd==NULL &&
            !pjsua_var.no_snd)
        {
            status = pjsua_set_snd_dev(pjsua_var.cap_dev, pjsua_var.play_dev);
            if (status != PJ_SUCCESS) {
                pjsua_perror(THIS_FILE, "Error opening sound device", status);
                goto on_return;
            }
        } else if (pjsua_var.no_snd && !pjsua_var.snd_is_on) {
            pjsua_var.snd_is_on = PJ_TRUE;
            /* Notify app */
            if (pjsua_var.ua_cfg.cb.on_snd_dev_operation) {
                (*pjsua_var.ua_cfg.cb.on_snd_dev_operation)(1);
            }
        }
    }

on_return:
    PJSUA_UNLOCK();

    if (status == PJ_SUCCESS) {
        pjsua_conf_connect_param cc_param;
        
        if (!prm)
            pjsua_conf_connect_param_default(&cc_param);
        else
            pj_memcpy(&cc_param, prm, sizeof(cc_param));
        status = pjmedia_conf_connect_port(pjsua_var.mconf, source, sink, 
                                           (int)((cc_param.level-1) * 128));
    }

    pj_log_pop_indent();
    return status;
}

можно ли вызвать эту функцию в функции on_call_media_state(после согласования кодеков) только в том случае, если создан port0 и его параметры отличаются от peer(например clock_rate) - тогда выполнится код для need_reopen - переоткроется sound_device с нужными нам параметрами? Или в случае, если мы звоним удалённому абоненту, эту функцию нельзя вызывать?