Ejemplo n.º 1
0
static pj_status_t g729_open(pjmedia_codec *codec,
			     pjmedia_codec_param *attr )
{
    struct g729_private *priv = (struct g729_private*) codec->codec_data;
    pj_pool_t *pool;

    priv->pt = attr->info.pt;
    pool = priv->pool;

  /* PREPARING THE ENCODER */
  priv->encoder = pj_pool_zalloc(pool, g729a_enc_mem_size());
	if (!priv->encoder)
		return PJMEDIA_CODEC_EFAILED;
    if (!g729a_enc_init(priv->encoder))
    	return PJMEDIA_CODEC_EFAILED;

    /* PREPARING THE DECODER */
    priv->decoder = pj_pool_zalloc(pool, g729a_dec_mem_size());
	if (!priv->decoder)
		return PJMEDIA_CODEC_EFAILED;
    if (!g729a_dec_init(priv->decoder))
		return PJMEDIA_CODEC_EFAILED;

#if !PLC_DISABLED
    priv->plc_enabled = (attr->setting.plc != 0);
#endif
    priv->vad_enabled = (attr->setting.vad != 0);
    return PJ_SUCCESS;
}
Ejemplo n.º 2
0
/*
 * Create the ZRTP transport.
 */
PJ_DEF(pj_status_t) pjmedia_transport_zrtp_create(pjmedia_endpt *endpt,
        const char *name,
        pjmedia_transport *transport,
        pjmedia_transport **p_tp,
        pj_bool_t close_slave)
{
    pj_pool_t *pool;
    struct tp_zrtp *zrtp;
    pj_status_t rc;

    if (name == NULL)
        name = "tzrtp%p";

    /* Create the pool and initialize the adapter structure */
    pool = pjmedia_endpt_create_pool(endpt, name, 5*1024, 512);
    zrtp = PJ_POOL_ZALLOC_T(pool, struct tp_zrtp);
    zrtp->pool = pool;
    pj_ansi_strncpy(zrtp->base.name, pool->obj_name,
                    sizeof(zrtp->base.name));
    zrtp->base.type = (pjmedia_transport_type)
                      (PJMEDIA_TRANSPORT_TYPE_USER + 2);
    zrtp->base.op = &tp_zrtp_op;

#ifndef DYNAMIC_TIMER
    if (timer_pool == NULL)
    {
        timer_pool = pjmedia_endpt_create_pool(endpt, "zrtp_timer", 256, 256);
        rc = timer_initialize();
        if (rc != PJ_SUCCESS)
        {
            pj_pool_release(timer_pool);
            pj_pool_release(zrtp->pool);
            return rc;
        }
    }
#else
    zrtp->timer_heap = pjsip_endpt_get_timer_heap(pjsua_var.endpt);
#endif

    /* Create the empty wrapper */
    zrtp->zrtpCtx = zrtp_CreateWrapper();

    /* Initialize standard values */
    zrtp->clientIdString = clientId;    /* Set standard name */
    zrtp->zrtpSeq = 1;                  /* TODO: randomize */
    rc = pj_mutex_create_simple(zrtp->pool, "zrtp", &zrtp->zrtpMutex);
    zrtp->zrtpBuffer = pj_pool_zalloc(pool, MAX_ZRTP_SIZE);
    zrtp->sendBuffer = pj_pool_zalloc(pool, MAX_RTP_BUFFER_LEN);
    zrtp->sendBufferCtrl = pj_pool_zalloc(pool, MAX_RTCP_BUFFER_LEN);

    zrtp->slave_tp = transport;
    zrtp->close_slave = close_slave;
    zrtp->mitmMode = PJ_FALSE;

    /* Done */
    zrtp->refcount++;
    *p_tp = &zrtp->base;
    return PJ_SUCCESS;
}
Ejemplo n.º 3
0
/*
 * Create the splitter/combiner.
 */
PJ_DEF(pj_status_t) pjmedia_splitcomb_create( pj_pool_t *pool,
					      unsigned clock_rate,
					      unsigned channel_count,
					      unsigned samples_per_frame,
					      unsigned bits_per_sample,
					      unsigned options,
					      pjmedia_port **p_splitcomb)
{
    const pj_str_t name = pj_str("splitcomb");
    struct splitcomb *sc;

    /* Sanity check */
    PJ_ASSERT_RETURN(pool && clock_rate && channel_count &&
		     samples_per_frame && bits_per_sample &&
		     p_splitcomb, PJ_EINVAL);

    /* Only supports 16 bits per sample */
    PJ_ASSERT_RETURN(bits_per_sample == 16, PJ_EINVAL);

    *p_splitcomb = NULL;

    /* Create the splitter/combiner structure */
    sc = pj_pool_zalloc(pool, sizeof(struct splitcomb));
    PJ_ASSERT_RETURN(sc != NULL, PJ_ENOMEM);

    /* Create temporary buffers */
    sc->get_buf = pj_pool_alloc(pool, samples_per_frame * 
				      sizeof(TMP_SAMP_TYPE) /
				      channel_count);
    PJ_ASSERT_RETURN(sc->get_buf, PJ_ENOMEM);

    sc->put_buf = pj_pool_alloc(pool, samples_per_frame * 
				      sizeof(TMP_SAMP_TYPE) /
				      channel_count);
    PJ_ASSERT_RETURN(sc->put_buf, PJ_ENOMEM);


    /* Save options */
    sc->options = options;

    /* Initialize port */
    pjmedia_port_info_init(&sc->base.info, &name, SIGNATURE, clock_rate,
			   channel_count, bits_per_sample, samples_per_frame);

    sc->base.put_frame = &put_frame;
    sc->base.get_frame = &get_frame;
    sc->base.on_destroy = &on_destroy;

    /* Init ports array */
    sc->port_desc = pj_pool_zalloc(pool, channel_count*sizeof(*sc->port_desc));

    /* Done for now */
    *p_splitcomb = &sc->base;

    return PJ_SUCCESS;
}
Ejemplo n.º 4
0
/*
 * Create a media port to generate sine wave samples.
 */
static pj_status_t create_sine_port(pj_pool_t *pool,
				    unsigned sampling_rate,
				    unsigned channel_count,
				    pjmedia_port **p_port)
{
    pjmedia_port *port;
    unsigned i;
    unsigned count;
    port_data *sine;

    PJ_ASSERT_RETURN(pool && channel_count > 0 && channel_count <= 2, 
		     PJ_EINVAL);

    port = pj_pool_zalloc(pool, sizeof(pjmedia_port));
    PJ_ASSERT_RETURN(port != NULL, PJ_ENOMEM);

    /* Fill in port info. */
    port->info.bits_per_sample = 16;
    port->info.channel_count = channel_count;
    port->info.encoding_name = pj_str("pcm");
    port->info.has_info = 1;
    port->info.name = pj_str("sine generator");
    port->info.need_info = 0;
    port->info.pt = 0xFF;
    port->info.clock_rate = sampling_rate;
    port->info.samples_per_frame = sampling_rate * 20 / 1000 * channel_count;
    port->info.bytes_per_frame = port->info.samples_per_frame * 2;
    port->info.type = PJMEDIA_TYPE_AUDIO;
    
    /* Set the function to feed frame */
    port->get_frame = &sine_get_frame;

    /* Create sine port data */
    port->port_data.pdata = sine = pj_pool_zalloc(pool, sizeof(port_data));

    /* Create samples */
    count = port->info.samples_per_frame / channel_count;
    sine->samples = pj_pool_alloc(pool, count * sizeof(pj_int16_t));
    PJ_ASSERT_RETURN(sine->samples != NULL, PJ_ENOMEM);

    /* initialise sinusoidal wavetable */
    for( i=0; i<count; i++ )
    {
        sine->samples[i] = (pj_int16_t) (10000.0 * 
		sin(((double)i/(double)count) * M_PI * 8.) );
    }

    *p_port = port;

    return PJ_SUCCESS;
}
Ejemplo n.º 5
0
/*
 * Allocate a new iLBC codec instance.
 */
static pj_status_t ilbc_alloc_codec(pjmedia_codec_factory *factory, 
				    const pjmedia_codec_info *id,
				    pjmedia_codec **p_codec)
{
    pj_pool_t *pool;
    struct ilbc_codec *codec;

    PJ_ASSERT_RETURN(factory && id && p_codec, PJ_EINVAL);
    PJ_ASSERT_RETURN(factory == &ilbc_factory.base, PJ_EINVAL);

    pool = pjmedia_endpt_create_pool(ilbc_factory.endpt, "iLBC%p",
				     2000, 2000);
    PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM);

    codec = pj_pool_zalloc(pool, sizeof(struct ilbc_codec));
    codec->base.op = &ilbc_op;
    codec->base.factory = factory;
    codec->pool = pool;

    pj_ansi_snprintf(codec->obj_name,  sizeof(codec->obj_name),
		     "ilbc%p", codec);

    *p_codec = &codec->base;
    return PJ_SUCCESS;
}
Ejemplo n.º 6
0
/*
 * Create client subscription.
 */
PJ_DEF(pj_status_t) pjsip_pres_create_uac( pjsip_dialog *dlg,
					   const pjsip_evsub_user *user_cb,
					   unsigned options,
					   pjsip_evsub **p_evsub )
{
    pj_status_t status;
    pjsip_pres *pres;
    pjsip_evsub *sub;

    PJ_ASSERT_RETURN(dlg && p_evsub, PJ_EINVAL);

    pjsip_dlg_inc_lock(dlg);

    /* Create event subscription */
    status = pjsip_evsub_create_uac( dlg,  &pres_user, &STR_PRESENCE, 
				     options, &sub);
    if (status != PJ_SUCCESS)
	goto on_return;

    /* Create presence */
    pres = pj_pool_zalloc(dlg->pool, sizeof(pjsip_pres));
    pres->dlg = dlg;
    pres->sub = sub;
    if (user_cb)
	pj_memcpy(&pres->user_cb, user_cb, sizeof(pjsip_evsub_user));

    /* Attach to evsub */
    pjsip_evsub_set_mod_data(sub, mod_presence.id, pres);

    *p_evsub = sub;

on_return:
    pjsip_dlg_dec_lock(dlg);
    return status;
}
Ejemplo n.º 7
0
PJ_DEF(pj_status_t) pjmedia_silence_det_create( pj_pool_t *pool,
						unsigned clock_rate,
						unsigned samples_per_frame,
						pjmedia_silence_det **p_sd)
{
    pjmedia_silence_det *sd;

    PJ_ASSERT_RETURN(pool && p_sd, PJ_EINVAL);

    sd = pj_pool_zalloc(pool, sizeof(struct pjmedia_silence_det));

    pj_ansi_strncpy(sd->objname, THIS_FILE, PJ_MAX_OBJ_NAME);
    sd->objname[PJ_MAX_OBJ_NAME-1] = '\0';

    sd->ptime = samples_per_frame * 1000 / clock_rate;
    sd->signal_cnt = 0;
    sd->silence_cnt = 0;
    sd->weakest_signal = 0xFFFFFFFFUL;
    sd->loudest_silence = 0;
     
    /* Default settings */
    pjmedia_silence_det_set_params(sd, -1, -1, -1);

    /* Restart in fixed, silent mode */
    sd->in_talk = PJ_FALSE;
    pjmedia_silence_det_set_adaptive( sd, -1 );

    *p_sd = sd;
    return PJ_SUCCESS;
}
Ejemplo n.º 8
0
PJ_DEF(pj_status_t) pjmedia_null_port_create( pj_pool_t *pool,
					      unsigned sampling_rate,
					      unsigned channel_count,
					      unsigned samples_per_frame,
					      unsigned bits_per_sample,
					      pjmedia_port **p_port )
{
    pjmedia_port *port;
    const pj_str_t name = pj_str("null-port");

    PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL);

    port = pj_pool_zalloc(pool, sizeof(pjmedia_port));
    PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM);

    pjmedia_port_info_init(&port->info, &name, SIGNATURE, sampling_rate,
			   channel_count, bits_per_sample, samples_per_frame);

    port->get_frame = &null_get_frame;
    port->put_frame = &null_put_frame;
    port->on_destroy = &null_on_destroy;


    *p_port = port;
    
    return PJ_SUCCESS;
}
Ejemplo n.º 9
0
Archivo: xml.c Proyecto: Jopie64/pjsip
static int xml_parse_print_test(const char *doc)
{
    pj_str_t msg;
    pj_pool_t *pool;
    pj_xml_node *root;
    char *output;
    int output_len;

    pool = pj_pool_create(mem, "xml", 4096, 1024, NULL);
    pj_strdup2(pool, &msg, doc);
    root = pj_xml_parse(pool, msg.ptr, msg.slen);
    if (!root) {
	PJ_LOG(1, (THIS_FILE, "  Error: unable to parse XML"));
	return -10;
    }

    output = (char*)pj_pool_zalloc(pool, msg.slen + 512);
    output_len = pj_xml_print(root, output, msg.slen+512, PJ_TRUE);
    if (output_len < 1) {
	PJ_LOG(1, (THIS_FILE, "  Error: buffer too small to print XML file"));
	return -20;
    }
    output[output_len] = '\0';


    pj_pool_release(pool);
    return 0;
}
Ejemplo n.º 10
0
/*
 * Create. 
 */
PJ_DEF(pj_status_t) echo_supp_create( pj_pool_t *pool,
				      unsigned clock_rate,
				      unsigned samples_per_frame,
				      unsigned tail_ms,
				      unsigned latency_ms,
				      unsigned options,
				      void **p_state )
{
    echo_supp *ec;
    pj_status_t status;

    PJ_UNUSED_ARG(clock_rate);
    PJ_UNUSED_ARG(options);
    PJ_UNUSED_ARG(latency_ms);

    ec = pj_pool_zalloc(pool, sizeof(struct echo_supp));
    ec->samples_per_frame = samples_per_frame;
    ec->tail_ms = tail_ms;

    status = pjmedia_silence_det_create(pool, clock_rate, samples_per_frame,
					&ec->sd);
    if (status != PJ_SUCCESS)
	return status;

    pjmedia_silence_det_set_name(ec->sd, "ecsu%p");
    pjmedia_silence_det_set_adaptive(ec->sd, PJMEDIA_ECHO_SUPPRESS_THRESHOLD);
    pjmedia_silence_det_set_params(ec->sd, 100, 500, 3000);

    *p_state = ec;
    return PJ_SUCCESS;
}
Ejemplo n.º 11
0
/*
 * Make outgoing call.
 */
static pj_status_t make_call(const pj_str_t *dst_uri)
{
    struct call *call;
    pjsip_dialog *dlg;
    pjmedia_sdp_session *sdp;
    pjsip_tx_data *tdata;
    pj_status_t status;


    /* Create UAC dialog */
    status = pjsip_dlg_create_uac( pjsip_ua_instance(), 
				   &app.local_uri,	/* local URI	    */
				   &app.local_contact,	/* local Contact    */
				   dst_uri,		/* remote URI	    */
				   dst_uri,		/* remote target    */
				   &dlg);		/* dialog	    */
    if (status != PJ_SUCCESS) {
	return status;
    }

    /* Create call */
    call = pj_pool_zalloc(dlg->pool, sizeof(struct call));

    /* Create SDP */
    if (app.real_sdp) {
	status = pjmedia_endpt_create_sdp(app.med_endpt, dlg->pool, 1, 
					  app.skinfo, &sdp);
	if (status != PJ_SUCCESS) {
	    pjsip_dlg_terminate(dlg);
	    return status;
	}
    } else
	sdp = app.dummy_sdp;

    /* Create the INVITE session. */
    status = pjsip_inv_create_uac( dlg, sdp, 0, &call->inv);
    if (status != PJ_SUCCESS) {
	pjsip_dlg_terminate(dlg);
	return status;
    }


    /* Create initial INVITE request.
     * This INVITE request will contain a perfectly good request and 
     * an SDP body as well.
     */
    status = pjsip_inv_invite(call->inv, &tdata);
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);


    /* Send initial INVITE request. 
     * From now on, the invite session's state will be reported to us
     * via the invite session callbacks.
     */
    status = pjsip_inv_send_msg(call->inv, tdata);
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);


    return PJ_SUCCESS;
}
Ejemplo n.º 12
0
/*
 * Create PLC session. This function will select the PLC algorithm to
 * use based on the arguments.
 */
PJ_DEF(pj_status_t) pjmedia_plc_create( pj_pool_t *pool,
					unsigned clock_rate,
					unsigned samples_per_frame,
					unsigned options,
					pjmedia_plc **p_plc)
{
    pjmedia_plc *plc;

    PJ_ASSERT_RETURN(pool && clock_rate && samples_per_frame && p_plc,
		     PJ_EINVAL);
    PJ_ASSERT_RETURN(options == 0, PJ_EINVAL);

    PJ_UNUSED_ARG(options);

    plc = pj_pool_zalloc(pool, sizeof(pjmedia_plc));

    if (0)
	;
#if defined(PJMEDIA_HAS_STEVEU_PLC) && PJMEDIA_HAS_STEVEU_PLC!=0
    else if (clock_rate == 8000)
	plc->op = &plc_steveu;
#endif
    else
	plc->op = &plc_replay;

    plc->obj = plc->op->plc_create(pool, clock_rate, samples_per_frame);

    *p_plc = plc;

    return PJ_SUCCESS;
}
/*
 * Create a media port to generate sine wave samples.
 */
static pj_status_t create_sine_port(pj_pool_t *pool,
				    unsigned sampling_rate,
				    unsigned channel_count,
				    pjmedia_port **p_port)
{
    pjmedia_port *port;
    unsigned i;
    unsigned count;
    pj_str_t name;
    port_data *sine;

    PJ_ASSERT_RETURN(pool && channel_count > 0 && channel_count <= 2, 
		     PJ_EINVAL);

    port = pj_pool_zalloc(pool, sizeof(pjmedia_port));
    PJ_ASSERT_RETURN(port != NULL, PJ_ENOMEM);

    /* Fill in port info. */
    name = pj_str("sine generator");
    pjmedia_port_info_init(&port->info, &name,
                           PJMEDIA_SIG_CLASS_PORT_AUD('s', 'i'),
			   sampling_rate,
			   channel_count,
			   16, sampling_rate * 20 / 1000 * channel_count);
    
    /* Set the function to feed frame */
    port->get_frame = &sine_get_frame;

    /* Create sine port data */
    port->port_data.pdata = sine = pj_pool_zalloc(pool, sizeof(port_data));

    /* Create samples */
    count = PJMEDIA_PIA_SPF(&port->info) / channel_count;
    sine->samples = pj_pool_alloc(pool, count * sizeof(pj_int16_t));
    PJ_ASSERT_RETURN(sine->samples != NULL, PJ_ENOMEM);

    /* initialise sinusoidal wavetable */
    for( i=0; i<count; i++ )
    {
        sine->samples[i] = (pj_int16_t) (10000.0 * 
		sin(((double)i/(double)count) * M_PI * 8.) );
    }

    *p_port = port;

    return PJ_SUCCESS;
}
Ejemplo n.º 14
0
void Sdp::setTelephoneEventRtpmap(pjmedia_sdp_media *med)
{
    pjmedia_sdp_attr *attr_rtpmap = NULL;
    pjmedia_sdp_attr *attr_fmtp = NULL;

    attr_rtpmap = static_cast<pjmedia_sdp_attr *>(pj_pool_zalloc(memPool_, sizeof(pjmedia_sdp_attr)));
    attr_rtpmap->name = pj_str((char *) "rtpmap");
    attr_rtpmap->value = pj_str((char *) "101 telephone-event/8000");

    med->attr[med->attr_count++] = attr_rtpmap;

    attr_fmtp = static_cast<pjmedia_sdp_attr *>(pj_pool_zalloc(memPool_, sizeof(pjmedia_sdp_attr)));
    attr_fmtp->name = pj_str((char *) "fmtp");
    attr_fmtp->value = pj_str((char *) "101 0-15");

    med->attr[med->attr_count++] = attr_fmtp;
}
Ejemplo n.º 15
0
/*
 * Create the echo canceller.
 */
pjs_echo_canceller::pjs_echo_canceller(pj_pool_t *pool_, unsigned clock_rate,
		unsigned samples_per_frame_, unsigned tail_ms, unsigned latency_ms,
		unsigned options) {
	int sampling_rate = clock_rate;
	unsigned ptime, lat_cnt;
	unsigned delay_buf_opt = 0;

	lat_ready = PJ_FALSE;
	/* Create new pool and instantiate and init the EC */
	pool = pj_pool_create(pool_->factory, "ec%p", 256, 256, NULL);
	lock = new PPJ_SemaphoreLock(pool, NULL, 1, 1);
	samples_per_frame = samples_per_frame_;
	frm_buf = (pj_int16_t*) pj_pool_alloc(pool, samples_per_frame << 1);

    state = speex_echo_state_init(samples_per_frame,
    					clock_rate * tail_ms / 1000);

    speex_echo_ctl(state, SPEEX_ECHO_SET_SAMPLING_RATE,
		   &sampling_rate);

    preprocess = speex_preprocess_state_init(samples_per_frame,
						   clock_rate);
    tmp_frame = (pj_int16_t*) pj_pool_zalloc(pool, 2*samples_per_frame);

    speex_preprocess_ctl(preprocess, SPEEX_PREPROCESS_SET_ECHO_STATE,
 			state);

	pj_list_init(&lat_buf);
	pj_list_init(&lat_free);

	PJ_LOG(5, (THIS_FILE, "Creating echo canceler"));

	/* Create latency buffers */
	ptime = samples_per_frame * 1000 / clock_rate;
	if (latency_ms < ptime) {
		/* Give at least one frame delay to simplify programming */
		latency_ms = ptime;
	}
	lat_cnt = latency_ms / ptime;
	while (lat_cnt--) {
		struct frame *frm;

		frm = (struct frame*) pj_pool_alloc(pool,
				(samples_per_frame << 1) + sizeof(struct frame));
		pj_list_push_back(&lat_free, frm);
	}

	/* Create delay buffer to compensate drifts */
	if (options & PJMEDIA_ECHO_USE_SIMPLE_FIFO)
		delay_buf_opt |= PJMEDIA_DELAY_BUF_SIMPLE_FIFO;
	pjmedia_delay_buf_create(pool, NULL, clock_rate, samples_per_frame,
			1, (PJMEDIA_SOUND_BUFFER_COUNT + 1) * ptime, delay_buf_opt,
			&delay_buf);
	PJ_LOG(4, (THIS_FILE, "ECHO canceller created, clock_rate=%d, channel=%d, "
	"samples per frame=%d, tail length=%d ms, "
	"latency=%d ms", clock_rate, 1, samples_per_frame, tail_ms, latency_ms));
}
Ejemplo n.º 16
0
PJ_DEF(int) jitter_buffer_create(Jitter_Buffer ** jitter_buffer, pj_pool_t *pool,
    int max_number_of_frames, NACK_MODE nack_mode, 
    int low_rtt_threshold_ms, int high_rtt_threshold_ms) {
    pj_assert(low_rtt_threshold_ms <= high_rtt_threshold_ms);
    //alloc jitter buffer
    Jitter_Buffer *jitter_buffer_internal = (Jitter_Buffer*)pj_pool_zalloc(pool, sizeof(Jitter_Buffer));
    //init list alloc
    list_alloc_init(&jitter_buffer_internal->frame_alloc, pool);
    list_alloc_init(&jitter_buffer_internal->packet_alloc, pool);
    //init frame list, don't call frame_buffer_init, 
    //since the header is not used as a real frame
    pj_list_init(&jitter_buffer_internal->frameList);
    pj_list_init(&jitter_buffer_internal->decodingFrameList);
    //init frame number
    jitter_buffer_internal->max_number_of_frames = max_number_of_frames 
            < MIN_NUM_OF_FRAMES? MIN_NUM_OF_FRAMES : max_number_of_frames;
    jitter_buffer_internal->number_of_frames = 0;
    //init decode state
    decode_state_init(&jitter_buffer_internal->decode_state);
    //init jitter estimator
    jitter_estimator_init(&jitter_buffer_internal->jitter_estimator);
    //init inter_frame_delay
    inter_frame_delay_init(&jitter_buffer_internal->inter_frame_delay);
    //init rtt
    jitter_buffer_internal->rttMs = DEFAULT_RTT_MS;
    //init nack
    if(high_rtt_threshold_ms != -1) 
        jitter_buffer_internal->rttMs = 0;
    jitter_buffer_internal->nack_mode = nack_mode;
    jitter_buffer_internal->low_rtt_threshold_ms = low_rtt_threshold_ms;
    jitter_buffer_internal->high_rtt_threshold_ms = high_rtt_threshold_ms;
    jitter_buffer_internal->nack_seq_num = 0;
    //init event
    if(event_create(&jitter_buffer_internal->frame_event) != 0) {
        return -1;
    }
    if(event_create(&jitter_buffer_internal->packet_event) != 0)
        return -1;
    
    //not running
    jitter_buffer_internal->running = PJ_FALSE;
    //first packet 
    jitter_buffer_internal->first_packet = PJ_FALSE;
    //the first frame must be key frame
    jitter_buffer_internal->waiting_for_key_frame = PJ_TRUE;
    //waiting for completed frame
    jitter_buffer_internal->waiting_for_completed_frame.timestamp = 0;
    jitter_buffer_internal->waiting_for_completed_frame.frame_size = 0;
    jitter_buffer_internal->waiting_for_completed_frame.latest_packet_timestamp = -1;
    //init mutex
    if(pj_mutex_create_simple(pool, NULL, &jitter_buffer_internal->jb_mutex) != PJ_SUCCESS)
        return -1;
    //ret
    *jitter_buffer = jitter_buffer_internal;
    return 0;
    
}
Ejemplo n.º 17
0
void queue_init(queue_t *queue, int cap, int data_size, pj_pool_t *p_mempool) {
    queue->capacity = cap;
    queue->buffer = pj_pool_zalloc(p_mempool, sizeof(void *) * cap);
    queue->size = 0;
    queue->in = 0;
    queue->out = 0;

//#define QEPOOL_SIZE(queue) (5*queue->capacity)
//    qepool_init(&(queue->qepool), QEPOOL_SIZE(queue), data_size, p_mempool);
    pthread_mutex_init(&queue->mutex, NULL);
    pthread_cond_init(&queue->cond_full, NULL);
    pthread_cond_init(&queue->cond_empty, NULL);
}
Ejemplo n.º 18
0
Jt_Car::Jt_Car(pj_uint32_t id):_id(id)
{
	PJ_LOG(3, ("car.cpp", "build a car"));
	_pool = pj_pool_create(&g_cp.factory, "car", INIT_POOL_CAR_SIZE, INC_POOL_CAR_SIZE, NULL);
	
	_event_track = (jt_e_track_node*)PJ_POOL_ZALLOC_T(_pool, jt_e_track_node);
	pj_list_init(_event_track);
	
	_station_track = (jt_s_track_node*)PJ_POOL_ZALLOC_T(_pool, jt_s_track_node);
	pj_list_init(_station_track);
	_station_track->station = NULL;
	_data = pj_pool_zalloc(_pool, MAX_CAR_DATA_LEN);
}
Ejemplo n.º 19
0
/**
 * This method is to parse and add the choice type 
 * argument values to command structure.
 **/
static pj_status_t add_choice_node(pj_cli_t *cli,
				   pj_xml_node *xml_node,
				   pj_cli_arg_spec *arg,
				   pj_cli_get_dyn_choice get_choice)
{
    pj_xml_node *choice_node;
    pj_xml_node *sub_node;
    pj_cli_arg_choice_val choice_values[PJ_CLI_MAX_CHOICE_VAL];
    pj_status_t status = PJ_SUCCESS;

    sub_node = xml_node;
    arg->type = PJ_CLI_ARG_CHOICE;
    arg->get_dyn_choice = get_choice;						

    choice_node = sub_node->node_head.next;
    while (choice_node != (pj_xml_node*)&sub_node->node_head) {
	pj_xml_attr *choice_attr;
	unsigned *stat_cnt = &arg->stat_choice_cnt;
	pj_cli_arg_choice_val *choice_val = &choice_values[*stat_cnt];		     
	pj_bzero(choice_val, sizeof(*choice_val));

	choice_attr = choice_node->attr_head.next;
	while (choice_attr != &choice_node->attr_head) {
	    if (!pj_stricmp2(&choice_attr->name, "value")) {
		pj_strassign(&choice_val->value, &choice_attr->value);
	    } else if (!pj_stricmp2(&choice_attr->name, "desc")) {
		pj_strassign(&choice_val->desc, &choice_attr->value);
	    }
	    choice_attr = choice_attr->next;
	}		
	if (++(*stat_cnt) >= PJ_CLI_MAX_CHOICE_VAL)
	    break;
	choice_node = choice_node->next;
    }    
    if (arg->stat_choice_cnt > 0) {
        unsigned i;

	arg->stat_choice_val = (pj_cli_arg_choice_val *)
				pj_pool_zalloc(cli->pool, 
					       arg->stat_choice_cnt *
					       sizeof(pj_cli_arg_choice_val));

        for (i = 0; i < arg->stat_choice_cnt; i++) {
	    pj_strdup(cli->pool, &arg->stat_choice_val[i].value, 
		      &choice_values[i].value);
            pj_strdup(cli->pool, &arg->stat_choice_val[i].desc, 
		      &choice_values[i].desc);            
        }
    }
    return status;
}
Ejemplo n.º 20
0
static void* plc_replay_create(pj_pool_t *pool, unsigned clock_rate, 
			       unsigned samples_per_frame)
{
    struct replay_plc *o;

    PJ_UNUSED_ARG(clock_rate);

    o = pj_pool_alloc(pool, sizeof(struct replay_plc));
    o->size = samples_per_frame * 2;
    o->replay_cnt = 0;
    o->frame = pj_pool_zalloc(pool, o->size);

    return o;
}
Ejemplo n.º 21
0
/*!
 * \internal
 * \brief Insert the header pointers into the linked list.
 *
 * For each header in the message, allocate a list entry,
 * clone the header, then insert the entry.
 */
static int insert_headers(pj_pool_t * pool, struct hdr_list *list, pjsip_msg * msg)
{
	pjsip_hdr *hdr = msg->hdr.next;
	struct hdr_list_entry *le;

	while (hdr && hdr != &msg->hdr) {
		le = pj_pool_zalloc(pool, sizeof(struct hdr_list_entry));
		le->hdr = pjsip_hdr_clone(pool, hdr);
		AST_LIST_INSERT_TAIL(list, le, nextptr);
		hdr = hdr->next;
	}

	return 0;
}
Ejemplo n.º 22
0
pjmedia_sdp_session_clone( pj_pool_t *pool,
			   const pjmedia_sdp_session *rhs)
{
    pjmedia_sdp_session *sess;
    unsigned i;

    PJ_ASSERT_RETURN(pool && rhs, NULL);

    sess = pj_pool_zalloc(pool, sizeof(pjmedia_sdp_session));
    PJ_ASSERT_RETURN(sess != NULL, NULL);

    /* Clone origin line. */
    pj_strdup(pool, &sess->origin.user, &rhs->origin.user);
    sess->origin.id = rhs->origin.id;
    sess->origin.version = rhs->origin.version;
    pj_strdup(pool, &sess->origin.net_type, &rhs->origin.net_type);
    pj_strdup(pool, &sess->origin.addr_type, &rhs->origin.addr_type);
    pj_strdup(pool, &sess->origin.addr, &rhs->origin.addr);

    /* Clone subject line. */
    pj_strdup(pool, &sess->name, &rhs->name);

    /* Clone connection line */
    if (rhs->conn) {
	sess->conn = pjmedia_sdp_conn_clone(pool, rhs->conn);
	PJ_ASSERT_RETURN(sess->conn != NULL, NULL);
    }

    /* Clone time line. */
    sess->time.start = rhs->time.start;
    sess->time.stop = rhs->time.stop;

    /* Duplicate session attributes. */
    sess->attr_count = rhs->attr_count;
    for (i=0; i<rhs->attr_count; ++i) {
	sess->attr[i] = pjmedia_sdp_attr_clone(pool, rhs->attr[i]);
    }

    /* Duplicate media descriptors. */
    sess->media_count = rhs->media_count;
    for (i=0; i<rhs->media_count; ++i) {
	sess->media[i] = pjmedia_sdp_media_clone(pool, rhs->media[i]);
    }

    return sess;
}
Ejemplo n.º 23
0
PJ_DEF(pj_status_t) pjmedia_mem_player_create( pj_pool_t *pool,
					       const void *buffer,
					       pj_size_t size,
					       unsigned clock_rate,
					       unsigned channel_count,
					       unsigned samples_per_frame,
					       unsigned bits_per_sample,
					       unsigned options,
					       pjmedia_port **p_port )
{
    struct mem_player *port;
    pj_str_t name = pj_str("memplayer");

    /* Sanity check */
    PJ_ASSERT_RETURN(pool && buffer && size && clock_rate && channel_count &&
		     samples_per_frame && bits_per_sample && p_port,
		     PJ_EINVAL);

    /* Can only support 16bit PCM */
    PJ_ASSERT_RETURN(bits_per_sample == 16, PJ_EINVAL);


    port = pj_pool_zalloc(pool, sizeof(struct mem_player));
    PJ_ASSERT_RETURN(port != NULL, PJ_ENOMEM);

    /* Create the port */
    pjmedia_port_info_init(&port->base.info, &name, SIGNATURE, clock_rate,
			   channel_count, bits_per_sample, samples_per_frame);

    port->base.put_frame = &mem_put_frame;
    port->base.get_frame = &mem_get_frame;
    port->base.on_destroy = &mem_on_destroy;


    /* Save the buffer */
    port->buffer = port->read_pos = (char*)buffer;
    port->buf_size = size;

    /* Options */
    port->options = options;

    *p_port = &port->base;

    return PJ_SUCCESS;
}
Ejemplo n.º 24
0
static struct playlist_port *create_file_list_port(pj_pool_t *pool,
						   const pj_str_t *name)
{
    struct playlist_port *port;

    port = pj_pool_zalloc(pool, sizeof(struct playlist_port));
    if (!port)
	return NULL;

    /* Put in default values.
     * These will be overriden once the file is read.
     */
    pjmedia_port_info_init(&port->base.info, name, SIGNATURE,
			   8000, 1, 16, 80);

    port->base.get_frame = &file_list_get_frame;
    port->base.on_destroy = &file_list_on_destroy;

    return port;
}
Ejemplo n.º 25
0
PJ_DEF(pj_status_t) pjmedia_echo_port_create(pj_pool_t *pool,
					     pjmedia_port *dn_port,
					     unsigned tail_ms,
					     unsigned latency_ms,
					     unsigned options,
					     pjmedia_port **p_port )
{
    const pj_str_t AEC = { "EC", 2 };
    struct ec *ec;
    pj_status_t status;

    PJ_ASSERT_RETURN(pool && dn_port && p_port, PJ_EINVAL);
    PJ_ASSERT_RETURN(dn_port->info.bits_per_sample==16 && tail_ms, 
		     PJ_EINVAL);

    /* Create the port and the AEC itself */
    ec = pj_pool_zalloc(pool, sizeof(struct ec));
    
    pjmedia_port_info_init(&ec->base.info, &AEC, SIGNATURE,
			   dn_port->info.clock_rate, 
			   dn_port->info.channel_count, 
			   dn_port->info.bits_per_sample,
			   dn_port->info.samples_per_frame);

    status = pjmedia_echo_create(pool, dn_port->info.clock_rate, 
				 dn_port->info.samples_per_frame,
				 tail_ms, latency_ms, options, &ec->ec);
    if (status != PJ_SUCCESS)
	return status;

    /* More init */
    ec->dn_port = dn_port;
    ec->base.get_frame = &ec_get_frame;
    ec->base.put_frame = &ec_put_frame;
    ec->base.on_destroy = &ec_on_destroy;

    /* Done */
    *p_port = &ec->base;

    return PJ_SUCCESS;
}
Ejemplo n.º 26
0
/* Helper function to create "incoming" packet */
struct recv_list *create_incoming_packet( struct loop_transport *loop,
					  pjsip_tx_data *tdata )
{
    pj_pool_t *pool;
    struct recv_list *pkt;

    pool = pjsip_endpt_create_pool(loop->base.endpt, "rdata", 
				   PJSIP_POOL_RDATA_LEN, 
				   PJSIP_POOL_RDATA_INC+5);
    if (!pool)
	return NULL;

    pkt = pj_pool_zalloc(pool, sizeof(struct recv_list));

    /* Initialize rdata. */
    pkt->rdata.tp_info.pool = pool;
    pkt->rdata.tp_info.transport = &loop->base;
    
    /* Copy the packet. */
    pj_memcpy(pkt->rdata.pkt_info.packet, tdata->buf.start,
	      tdata->buf.cur - tdata->buf.start);
    pkt->rdata.pkt_info.len = tdata->buf.cur - tdata->buf.start;

    /* "Source address" info. */
    pkt->rdata.pkt_info.src_addr_len = sizeof(pj_sockaddr_in);
    if (loop->base.key.type == PJSIP_TRANSPORT_LOOP)
	pj_ansi_strcpy(pkt->rdata.pkt_info.src_name, ADDR_LOOP);
    else
	pj_ansi_strcpy(pkt->rdata.pkt_info.src_name, ADDR_LOOP_DGRAM);
    pkt->rdata.pkt_info.src_port = loop->base.local_name.port;

    /* When do we need to "deliver" this packet. */
    pj_gettimeofday(&pkt->rdata.pkt_info.timestamp);
    pkt->rdata.pkt_info.timestamp.msec += loop->recv_delay;
    pj_time_val_normalize(&pkt->rdata.pkt_info.timestamp);

    /* Done. */

    return pkt;
}
Ejemplo n.º 27
0
PJ_DECL(pj_status_t) pjmedia_plc_port_create(pj_pool_t *pool,
        pjmedia_port *dn_port, pjmedia_codec *codec, unsigned fpp,
        em_plc_mode plc_mode, pjmedia_port **p_port)
{
    const pj_str_t plc = { "plc", 3 };
    struct plc_port *plcp;
    pj_status_t status;

    PJ_ASSERT_RETURN(pool && dn_port && p_port, PJ_EINVAL);

    /* Create the port itself */
    plcp = PJ_POOL_ZALLOC_T(pool, struct plc_port);
    plcp->frame_buf = pj_pool_zalloc(pool, BUF_SIZE);

    pjmedia_port_info_init(&plcp->base.info, &plc, SIGNATURE,
			   dn_port->info.clock_rate,
			   dn_port->info.channel_count,
			   dn_port->info.bits_per_sample,
			   dn_port->info.samples_per_frame*fpp);

    /* More init */
    plcp->dn_port = dn_port;
    plcp->codec = codec;
    plcp->fpp = fpp;
    plcp->plc_mode = plc_mode;
    plcp->base.get_frame = &plc_get_frame;
    plcp->base.put_frame = &plc_put_frame;
    plcp->base.on_destroy = &plc_on_destroy;
    plcp->frame.type = PJMEDIA_FRAME_TYPE_NONE;
    plcp->frame.buf = plcp->frame_buf;
    plcp->stats.received = 0;
    plcp->stats.lost = 0;
    plcp->stats.total = 0;

    /* Done */
    *p_port = &plcp->base;

    return PJ_SUCCESS;
}
Ejemplo n.º 28
0
/*!
 * \internal
 * \brief Implements PJSIP_HEADER 'add' by inserting the specified header into thge list.
 *
 * Retrieve the header_datastore from the session or create one if it doesn't exist.
 * Create and initialize the list if needed.
 * Create the pj_strs for name and value.
 * Create pjsip_msg and hdr_list_entry.
 * Add the entry to the list.
 */
static int add_header(void *obj)
{
	struct header_data *data = obj;
	struct ast_sip_session *session = data->channel->session;
	pj_pool_t *pool = session->inv_session->dlg->pool;
	pj_str_t pj_header_name;
	pj_str_t pj_header_value;
	struct hdr_list_entry *le;
	struct hdr_list *list;

	RAII_VAR(struct ast_datastore *, datastore,
			 ast_sip_session_get_datastore(session, header_datastore.type), ao2_cleanup);

	if (!datastore) {
		if (!(datastore = ast_sip_session_alloc_datastore(&header_datastore,
														  header_datastore.type))
			|| !(datastore->data = pj_pool_alloc(pool, sizeof(struct hdr_list)))
			|| ast_sip_session_add_datastore(session, datastore)) {
			ast_log(AST_LOG_ERROR, "Unable to create datastore for header functions.\n");
			return -1;
		}
		AST_LIST_HEAD_INIT((struct hdr_list *) datastore->data);
	}

	ast_debug(1, "Adding header %s with value %s\n", data->header_name,
			  data->header_value);

	pj_cstr(&pj_header_name, data->header_name);
	pj_cstr(&pj_header_value, data->header_value);
	le = pj_pool_zalloc(pool, sizeof(struct hdr_list_entry));
	le->hdr = (pjsip_hdr *) pjsip_generic_string_hdr_create(pool, &pj_header_name,
															&pj_header_value);
	list = datastore->data;

	AST_LIST_INSERT_TAIL(list, le, nextptr);

	return 0;
}
Ejemplo n.º 29
0
/**
 * Create UDP stream transport from existing socket info.
 */
PJ_DEF(pj_status_t) pjmedia_transport_udp_attach( pjmedia_endpt *endpt,
						  const char *name,
						  const pjmedia_sock_info *si,
						  unsigned options,
						  pjmedia_transport **p_tp)
{
    struct transport_udp *tp;
    pj_pool_t *pool;
    pj_ioqueue_t *ioqueue;
    pj_ioqueue_callback rtp_cb, rtcp_cb;
    pj_ssize_t size;
    unsigned i;
    pj_status_t status;


    /* Sanity check */
    PJ_ASSERT_RETURN(endpt && si && p_tp, PJ_EINVAL);

    /* Check name */
    if (!name)
	name = "udpmedia";

    /* Get ioqueue instance */
    ioqueue = pjmedia_endpt_get_ioqueue(endpt);


    /* Create transport structure */
    pool = pjmedia_endpt_create_pool(endpt, name, 4000, 4000);
    if (!pool)
	return PJ_ENOMEM;

    tp = pj_pool_zalloc(pool, sizeof(struct transport_udp));
    tp->pool = pool;
    tp->options = options;
    pj_ansi_strcpy(tp->base.name, name);
    tp->base.op = &transport_udp_op;

    /* Copy socket infos */
    tp->rtp_sock = si->rtp_sock;
    tp->rtp_addr_name = si->rtp_addr_name;
    tp->rtcp_sock = si->rtcp_sock;
    tp->rtcp_addr_name = si->rtcp_addr_name;

    /* If address is 0.0.0.0, use host's IP address */
    if (tp->rtp_addr_name.sin_addr.s_addr == 0) {
	pj_in_addr hostip;

	status = pj_gethostip(&hostip);
	if (status != PJ_SUCCESS)
	    goto on_error;

	tp->rtp_addr_name.sin_addr = hostip;
    }

    /* Same with RTCP */
    if (tp->rtcp_addr_name.sin_addr.s_addr == 0) {
	tp->rtcp_addr_name.sin_addr.s_addr = tp->rtp_addr_name.sin_addr.s_addr;
    }

    /* Setup RTP socket with the ioqueue */
    pj_bzero(&rtp_cb, sizeof(rtp_cb));
    rtp_cb.on_read_complete = &on_rx_rtp;

    status = pj_ioqueue_register_sock(pool, ioqueue, tp->rtp_sock, tp,
				      &rtp_cb, &tp->rtp_key);
    if (status != PJ_SUCCESS)
	goto on_error;
    
    pj_ioqueue_op_key_init(&tp->rtp_read_op, sizeof(tp->rtp_read_op));
    for (i=0; i<PJ_ARRAY_SIZE(tp->rtp_pending_write); ++i)
	pj_ioqueue_op_key_init(&tp->rtp_pending_write[i].op_key, 
			       sizeof(tp->rtp_pending_write[i].op_key));

    /* Kick of pending RTP read from the ioqueue */
    tp->rtp_addrlen = sizeof(tp->rtp_src_addr);
    size = sizeof(tp->rtp_pkt);
    status = pj_ioqueue_recvfrom(tp->rtp_key, &tp->rtp_read_op,
			         tp->rtp_pkt, &size, PJ_IOQUEUE_ALWAYS_ASYNC,
				 &tp->rtp_src_addr, &tp->rtp_addrlen);
    if (status != PJ_EPENDING)
	goto on_error;


    /* Setup RTCP socket with ioqueue */
    pj_bzero(&rtcp_cb, sizeof(rtcp_cb));
    rtcp_cb.on_read_complete = &on_rx_rtcp;

    status = pj_ioqueue_register_sock(pool, ioqueue, tp->rtcp_sock, tp,
				      &rtcp_cb, &tp->rtcp_key);
    if (status != PJ_SUCCESS)
	goto on_error;

    pj_ioqueue_op_key_init(&tp->rtcp_read_op, sizeof(tp->rtcp_read_op));
    pj_ioqueue_op_key_init(&tp->rtcp_write_op, sizeof(tp->rtcp_write_op));


    /* Kick of pending RTCP read from the ioqueue */
    size = sizeof(tp->rtcp_pkt);
    tp->rtcp_addr_len = sizeof(tp->rtcp_src_addr);
    status = pj_ioqueue_recvfrom( tp->rtcp_key, &tp->rtcp_read_op,
				  tp->rtcp_pkt, &size, PJ_IOQUEUE_ALWAYS_ASYNC,
				  &tp->rtcp_src_addr, &tp->rtcp_addr_len);
    if (status != PJ_EPENDING)
	goto on_error;


    /* Done */
    *p_tp = &tp->base;
    return PJ_SUCCESS;


on_error:
    pjmedia_transport_udp_close(&tp->base);
    return status;
}
Ejemplo n.º 30
0
/* Calculate the bandwidth for the specific test configuration.
 * The test is simple:
 *  - create sockpair_cnt number of producer-consumer socket pair.
 *  - create thread_cnt number of worker threads.
 *  - each producer will send buffer_size bytes data as fast and
 *    as soon as it can.
 *  - each consumer will read buffer_size bytes of data as fast 
 *    as it could.
 *  - measure the total bytes received by all consumers during a
 *    period of time.
 */
static int perform_test(pj_bool_t allow_concur,
			int sock_type, const char *type_name,
                        unsigned thread_cnt, unsigned sockpair_cnt,
                        pj_size_t buffer_size, 
                        pj_size_t *p_bandwidth)
{
    enum { MSEC_DURATION = 5000 };
    pj_pool_t *pool;
    test_item *items;
    pj_thread_t **thread;
    pj_ioqueue_t *ioqueue;
    pj_status_t rc;
    pj_ioqueue_callback ioqueue_callback;
    pj_uint32_t total_elapsed_usec, total_received;
    pj_highprec_t bandwidth;
    pj_timestamp start, stop;
    unsigned i;

    TRACE_((THIS_FILE, "    starting test.."));

    ioqueue_callback.on_read_complete = &on_read_complete;
    ioqueue_callback.on_write_complete = &on_write_complete;

    thread_quit_flag = 0;

    pool = pj_pool_create(mem, NULL, 4096, 4096, NULL);
    if (!pool)
        return -10;

    items = (test_item*) pj_pool_alloc(pool, sockpair_cnt*sizeof(test_item));
    thread = (pj_thread_t**)
    	     pj_pool_alloc(pool, thread_cnt*sizeof(pj_thread_t*));

    TRACE_((THIS_FILE, "     creating ioqueue.."));
    rc = pj_ioqueue_create(pool, sockpair_cnt*2, &ioqueue);
    if (rc != PJ_SUCCESS) {
        app_perror("...error: unable to create ioqueue", rc);
        return -15;
    }

    rc = pj_ioqueue_set_default_concurrency(ioqueue, allow_concur);
    if (rc != PJ_SUCCESS) {
	app_perror("...error: pj_ioqueue_set_default_concurrency()", rc);
        return -16;
    }

    /* Initialize each producer-consumer pair. */
    for (i=0; i<sockpair_cnt; ++i) {
        pj_ssize_t bytes;

        items[i].ioqueue = ioqueue;
        items[i].buffer_size = buffer_size;
        items[i].outgoing_buffer = (char*) pj_pool_alloc(pool, buffer_size);
        items[i].incoming_buffer = (char*) pj_pool_alloc(pool, buffer_size);
        items[i].bytes_recv = items[i].bytes_sent = 0;

        /* randomize outgoing buffer. */
        pj_create_random_string(items[i].outgoing_buffer, buffer_size);

        /* Create socket pair. */
	TRACE_((THIS_FILE, "      calling socketpair.."));
        rc = app_socketpair(pj_AF_INET(), sock_type, 0, 
                            &items[i].server_fd, &items[i].client_fd);
        if (rc != PJ_SUCCESS) {
            app_perror("...error: unable to create socket pair", rc);
            return -20;
        }

        /* Register server socket to ioqueue. */
	TRACE_((THIS_FILE, "      register(1).."));
        rc = pj_ioqueue_register_sock(pool, ioqueue, 
                                      items[i].server_fd,
                                      &items[i], &ioqueue_callback,
                                      &items[i].server_key);
        if (rc != PJ_SUCCESS) {
            app_perror("...error: registering server socket to ioqueue", rc);
            return -60;
        }

        /* Register client socket to ioqueue. */
	TRACE_((THIS_FILE, "      register(2).."));
        rc = pj_ioqueue_register_sock(pool, ioqueue, 
                                      items[i].client_fd,
                                      &items[i],  &ioqueue_callback,
                                      &items[i].client_key);
        if (rc != PJ_SUCCESS) {
            app_perror("...error: registering server socket to ioqueue", rc);
            return -70;
        }

        /* Start reading. */
	TRACE_((THIS_FILE, "      pj_ioqueue_recv.."));
        bytes = items[i].buffer_size;
        rc = pj_ioqueue_recv(items[i].server_key, &items[i].recv_op,
                             items[i].incoming_buffer, &bytes,
			     0);
        if (rc != PJ_EPENDING) {
            app_perror("...error: pj_ioqueue_recv", rc);
            return -73;
        }

        /* Start writing. */
	TRACE_((THIS_FILE, "      pj_ioqueue_write.."));
        bytes = items[i].buffer_size;
        rc = pj_ioqueue_send(items[i].client_key, &items[i].send_op,
                             items[i].outgoing_buffer, &bytes, 0);
        if (rc != PJ_SUCCESS && rc != PJ_EPENDING) {
            app_perror("...error: pj_ioqueue_write", rc);
            return -76;
        }

        items[i].has_pending_send = (rc==PJ_EPENDING);
    }

    /* Create the threads. */
    for (i=0; i<thread_cnt; ++i) {
	struct thread_arg *arg;

	arg = (struct thread_arg*) pj_pool_zalloc(pool, sizeof(*arg));
	arg->id = i;
	arg->ioqueue = ioqueue;
	arg->counter = 0;

        rc = pj_thread_create( pool, NULL, 
                               &worker_thread, 
                               arg, 
                               PJ_THREAD_DEFAULT_STACK_SIZE, 
                               PJ_THREAD_SUSPENDED, &thread[i] );
        if (rc != PJ_SUCCESS) {
            app_perror("...error: unable to create thread", rc);
            return -80;
        }
    }

    /* Mark start time. */
    rc = pj_get_timestamp(&start);
    if (rc != PJ_SUCCESS)
        return -90;

    /* Start the thread. */
    TRACE_((THIS_FILE, "     resuming all threads.."));
    for (i=0; i<thread_cnt; ++i) {
        rc = pj_thread_resume(thread[i]);
        if (rc != 0)
            return -100;
    }

    /* Wait for MSEC_DURATION seconds. 
     * This should be as simple as pj_thread_sleep(MSEC_DURATION) actually,
     * but unfortunately it doesn't work when system doesn't employ
     * timeslicing for threads.
     */
    TRACE_((THIS_FILE, "     wait for few seconds.."));
    do {
	pj_thread_sleep(1);

	/* Mark end time. */
	rc = pj_get_timestamp(&stop);

	if (thread_quit_flag) {
	    TRACE_((THIS_FILE, "      transfer limit reached.."));
	    break;
	}

	if (pj_elapsed_usec(&start,&stop)<MSEC_DURATION * 1000) {
	    TRACE_((THIS_FILE, "      time limit reached.."));
	    break;
	}

    } while (1);

    /* Terminate all threads. */
    TRACE_((THIS_FILE, "     terminating all threads.."));
    thread_quit_flag = 1;

    for (i=0; i<thread_cnt; ++i) {
	TRACE_((THIS_FILE, "      join thread %d..", i));
        pj_thread_join(thread[i]);
    }

    /* Close all sockets. */
    TRACE_((THIS_FILE, "     closing all sockets.."));
    for (i=0; i<sockpair_cnt; ++i) {
        pj_ioqueue_unregister(items[i].server_key);
        pj_ioqueue_unregister(items[i].client_key);
    }

    /* Destroy threads */
    for (i=0; i<thread_cnt; ++i) {
        pj_thread_destroy(thread[i]);
    }

    /* Destroy ioqueue. */
    TRACE_((THIS_FILE, "     destroying ioqueue.."));
    pj_ioqueue_destroy(ioqueue);

    /* Calculate actual time in usec. */
    total_elapsed_usec = pj_elapsed_usec(&start, &stop);

    /* Calculate total bytes received. */
    total_received = 0;
    for (i=0; i<sockpair_cnt; ++i) {
        total_received = (pj_uint32_t)items[i].bytes_recv;
    }

    /* bandwidth = total_received*1000/total_elapsed_usec */
    bandwidth = total_received;
    pj_highprec_mul(bandwidth, 1000);
    pj_highprec_div(bandwidth, total_elapsed_usec);
    
    *p_bandwidth = (pj_uint32_t)bandwidth;

    PJ_LOG(3,(THIS_FILE, "   %.4s    %2d        %2d       %8d KB/s",
              type_name, thread_cnt, sockpair_cnt,
              *p_bandwidth));

    /* Done. */
    pj_pool_release(pool);

    TRACE_((THIS_FILE, "    done.."));
    return 0;
}