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


static pj_status_t create_conf_port( pj_pool_t *parent_pool,pjmedia_conf *conf, pjmedia_port *port,const pj_str_t *name, struct conf_port **p_conf_port)
{
    struct conf_port *conf_port = NULL;
    pj_pool_t *pool = NULL;
    char pname[PJ_MAX_OBJ_NAME];
    pj_status_t status = PJ_SUCCESS;

    /* Make sure pool name is NULL terminated */
    pj_assert(name);
    pj_ansi_strxcpy2(pname, name, sizeof(pname));

    /* Create own pool */
    pool = pj_pool_create(parent_pool->factory, pname, 500, 500, NULL);
    if (!pool)
        return PJ_ENOMEM;

    /* Create port. */
    conf_port = PJ_POOL_ZALLOC_T(pool, struct conf_port);
    PJ_ASSERT_ON_FAIL(conf_port, {pj_pool_release(pool); return PJ_ENOMEM;});
    conf_port->pool = pool;

    /* Increment port ref count to avoid premature destroy due to
     * asynchronous port removal.
     */
    if (port) {
        if (!port->grp_lock) {
            /* Create group lock if it does not have one */
            pjmedia_port_init_grp_lock(port, pool, NULL);
        }

        pj_grp_lock_add_ref(port->grp_lock);

        /* Pool may be used for creating port's group lock and the group lock
         * may be used by app, so pool destroy must be done via handler.
         */
        status = pj_grp_lock_add_handler(port->grp_lock, NULL, conf_port,
                                         &conf_port_on_destroy);
    }

    /* Set name */
    pj_strdup_with_null(pool, &conf_port->name, name);

    /* Default has tx and rx enabled. */
    conf_port->rx_setting = PJMEDIA_PORT_ENABLE;
    conf_port->tx_setting = PJMEDIA_PORT_ENABLE;

    /* Default level adjustment is 128 (which means no adjustment) */
    conf_port->tx_adj_level = NORMAL_LEVEL;
    conf_port->rx_adj_level = NORMAL_LEVEL;

    /* Create transmit flag array */
    conf_port->listener_slots = (SLOT_TYPE*) pj_pool_zalloc(pool, 
                                          conf->max_ports * sizeof(SLOT_TYPE));
    PJ_ASSERT_ON_FAIL(conf_port->listener_slots,
                      {status = PJ_ENOMEM; goto on_return;});

    /* Create adjustment level array */
    conf_port->listener_adj_level = (unsigned *) pj_pool_zalloc(pool, 
                                       conf->max_ports * sizeof(unsigned));
    PJ_ASSERT_ON_FAIL(conf_port->listener_adj_level,
                      {status = PJ_ENOMEM; goto on_return;});

printf("%s(%d) port=%p\n",__FUNCTION__,__LINE__,port);
    /* Save some port's infos, for convenience. */
    if (port) {
        pjmedia_audio_format_detail *afd;

        afd = pjmedia_format_get_audio_format_detail(&port->info.fmt, 1);
        conf_port->port = port;
        conf_port->clock_rate = afd->clock_rate;
        conf_port->samples_per_frame = PJMEDIA_AFD_SPF(afd);
        conf_port->channel_count = afd->channel_count;
        printf("%s(%d) clock_rate=%u samples_per_frame=%u channel_count=%u\n",__FUNCTION__,__LINE__,afd->clock_rate,PJMEDIA_AFD_SPF(afd),afd->channel_count);
#ifndef MY_CODE
        conf->clock_rate = conf_port->clock_rate;
        conf->channel_count = conf_port->channel_count;
        conf->samples_per_frame = conf_port->samples_per_frame;
#endif
    } else {
        conf_port->port = NULL;
        conf_port->clock_rate = conf->clock_rate;
        conf_port->samples_per_frame = conf->samples_per_frame;
        conf_port->channel_count = conf->channel_count;
    }

    /* Create adjustment level buffer. */
    conf_port->adj_level_buf = (pj_int16_t*) pj_pool_zalloc(pool, 
                               conf->samples_per_frame * sizeof(pj_int16_t));
    PJ_ASSERT_ON_FAIL(conf_port->adj_level_buf,
                      {status = PJ_ENOMEM; goto on_return;});

    /* If port's clock rate is different than conference's clock rate,
     * create a resample sessions.
     */
    if (conf_port->clock_rate != conf->clock_rate) {

        pj_bool_t high_quality;
        pj_bool_t large_filter;

        high_quality = ((conf->options & PJMEDIA_CONF_USE_LINEAR)==0);
        large_filter = ((conf->options & PJMEDIA_CONF_SMALL_FILTER)==0);

#ifndef MY_CODE
        //high_quality = 0;
        //large_filter = 0;
        printf("%s(%d) high_quality=%d large_filter=%d Rate_in:%u Rate_out:%u samples_per_frame=%u\n",__FUNCTION__,__LINE__,high_quality,large_filter,conf_port->clock_rate,conf->clock_rate,conf->samples_per_frame * conf_port->clock_rate /conf->clock_rate);
#endif
        /* Create resample for rx buffer. */
        status = pjmedia_resample_create( pool, 
                                          high_quality,
                                          large_filter,
                                          conf->channel_count,
                                          conf_port->clock_rate,/* Rate in */
                                          conf->clock_rate, /* Rate out */
                                          conf->samples_per_frame * 
                                            conf_port->clock_rate /
                                            conf->clock_rate,
                                          &conf_port->rx_resample);
        if (status != PJ_SUCCESS)
            goto on_return;


        /* Create resample for tx buffer. */
        status = pjmedia_resample_create(pool,
                                         high_quality,
                                         large_filter,
                                         conf->channel_count,
                                         conf->clock_rate,  /* Rate in */
                                         conf_port->clock_rate, /* Rate out */
                                         conf->samples_per_frame,
                                         &conf_port->tx_resample);
        if (status != PJ_SUCCESS)
            goto on_return;
    }

    /*
     * Initialize rx and tx buffer, only when port's samples per frame or 
     * port's clock rate or channel number is different then the conference
     * bridge settings.
     */
    printf("%s(%d) conf_port(IN):\n",__FUNCTION__,__LINE__);
    printf("clock_rate=%u channel_count=%u samples_per_frame=%u\n",conf_port->clock_rate,conf_port->channel_count,conf_port->samples_per_frame);
    printf("%s(%d) conf(OUT):\n",__FUNCTION__,__LINE__);
    printf("clock_rate=%u channel_count=%u samples_per_frame=%u\n",conf->clock_rate,conf->channel_count,conf->samples_per_frame);
    if (conf_port->clock_rate != conf->clock_rate ||
        conf_port->channel_count != conf->channel_count ||
        conf_port->samples_per_frame != conf->samples_per_frame)
    {
        unsigned port_ptime, conf_ptime, buff_ptime;

        port_ptime = conf_port->samples_per_frame / conf_port->channel_count *
            1000 / conf_port->clock_rate;
        conf_ptime = conf->samples_per_frame / conf->channel_count *
            1000 / conf->clock_rate;

        /* Check compatibility of sample rate and ptime.
         * Some combinations result in a fractional number of samples per frame
         * which we do not support.
         * One such case would be for example 10ms @ 22050Hz which would yield
         * 220.5 samples per frame.
         */
        if (0 != (port_ptime * conf_port->clock_rate *
                  conf_port->channel_count % 1000))
        {
            PJ_LOG(3,(THIS_FILE,
                   "Cannot create conf port: incompatible sample rate/ptime"));
            status = PJMEDIA_ENOTCOMPATIBLE;
            goto on_return;
        }


        /* Calculate the size (in ptime) for the port buffer according to
         * this formula:
         *   - if either ptime is an exact multiple of the other, then use
         *     the larger ptime (e.g. 20ms and 40ms, use 40ms).
         *   - if not, then the ptime is sum of both ptimes (e.g. 20ms
         *     and 30ms, use 50ms)
         */
        if (port_ptime > conf_ptime) {
            buff_ptime = port_ptime;
            if (port_ptime % conf_ptime)
                buff_ptime += conf_ptime;
        } else {
            buff_ptime = conf_ptime;
            if (conf_ptime % port_ptime)
                buff_ptime += port_ptime;
        }

        /* Create RX buffer. */
        //conf_port->rx_buf_cap = (unsigned)(conf_port->samples_per_frame +
        //                                 conf->samples_per_frame * 
        //                                 conf_port->clock_rate * 1.0 /
        //                                 conf->clock_rate + 0.5);
        conf_port->rx_buf_cap = conf_port->clock_rate * buff_ptime / 1000;
        if (conf_port->channel_count > conf->channel_count)
            conf_port->rx_buf_cap *= conf_port->channel_count;
        else
            conf_port->rx_buf_cap *= conf->channel_count;

        conf_port->rx_buf_count = 0;
        conf_port->rx_buf = (pj_int16_t*)
                            pj_pool_alloc(pool, conf_port->rx_buf_cap *
                                                sizeof(conf_port->rx_buf[0]));
        PJ_ASSERT_ON_FAIL(conf_port->rx_buf,
                          {status = PJ_ENOMEM; goto on_return;});

        /* Create TX buffer. */
        conf_port->tx_buf_cap = conf_port->rx_buf_cap;
        conf_port->tx_buf_count = 0;
        conf_port->tx_buf = (pj_int16_t*)
                            pj_pool_alloc(pool, conf_port->tx_buf_cap *
                                                sizeof(conf_port->tx_buf[0]));
        PJ_ASSERT_ON_FAIL(conf_port->tx_buf,
                          {status = PJ_ENOMEM; goto on_return;});
    }


    /* Create mix buffer. */
    conf_port->mix_buf = (pj_int32_t*)
                         pj_pool_zalloc(pool, conf->samples_per_frame *
                                              sizeof(conf_port->mix_buf[0]));
    PJ_ASSERT_ON_FAIL(conf_port->mix_buf,
                      {status = PJ_ENOMEM; goto on_return;});
    conf_port->last_mix_adj = NORMAL_LEVEL;


    /* Done */
    *p_conf_port = conf_port;

on_return:
    if (status != PJ_SUCCESS) {
        /* Destroy resample if this conf port has it. */
        if (conf_port && conf_port->rx_resample)
            pjmedia_resample_destroy(conf_port->rx_resample);

        if (conf_port && conf_port->tx_resample)
            pjmedia_resample_destroy(conf_port->tx_resample);

        if (port && port->grp_lock) {
            pj_grp_lock_dec_ref(port->grp_lock);
        } else if (pool) {
            pj_pool_release(pool);
        }
    }

    return status;
}