/**************************************** API: create stream *****************************************/ static pj_status_t stream_stopBDIMAD(pjmedia_aud_stream *s) { struct bd_stream *strm = (struct bd_stream*)s; pj_status_t status = PJ_SUCCESS; int i, err = 0; PJ_ASSERT_RETURN(strm != NULL, PJ_EINVAL); strm->go = 0; for (i=0; !strm->rec_thread_exited && i<100; ++i) pj_thread_sleep(10); for (i=0; !strm->play_thread_exited && i<100; ++i) pj_thread_sleep(10); pj_thread_sleep(1); PJ_LOG(5,(THIS_FILE, "Stopping stream..")); strm->play_thread_initialized = 0; strm->rec_thread_initialized = 0; PJ_LOG(5,(THIS_FILE, "Done, status=%d", err)); return status; }
static pj_status_t stream_destroyBDIMAD(pjmedia_aud_stream *s) { struct bd_stream *strm = (struct bd_stream*)s; int i = 0; PJ_ASSERT_RETURN(strm != NULL, PJ_EINVAL); stream_stopBDIMAD(s); // DeInit BDIMAD bdIMADpj_FreeAEC(&strm->bdIMADpjInstance); PJ_LOG(4, (THIS_FILE, "Free AEC")); bdIMADpj_FreeStructures(&strm->bdIMADpjSettingsPtr, &strm->bdIMADpjWarningPtr); PJ_LOG(4, (THIS_FILE, "Free AEC Structure")); strm->bdIMADpjInstance = NULL; strm->bdIMADpjSettingsPtr = NULL; strm->bdIMADpjWarningPtr = NULL; strm->quit_flag = 1; for (i=0; !strm->rec_thread_exited && i<100; ++i) { pj_thread_sleep(1); } for (i=0; !strm->play_thread_exited && i<100; ++i) { pj_thread_sleep(1); } PJ_LOG(5,(THIS_FILE, "Destroying stream..")); pj_pool_release(strm->pool); return PJ_SUCCESS; }
/* API: stop stream. */ static pj_status_t strm_stop(pjmedia_aud_stream *s) { struct pa_aud_stream *stream = (struct pa_aud_stream*)s; int i, err = 0; stream->quit_flag = 1; for (i=0; !stream->rec_thread_exited && i<100; ++i) pj_thread_sleep(10); for (i=0; !stream->play_thread_exited && i<100; ++i) pj_thread_sleep(10); pj_thread_sleep(1); PJ_LOG(5,(THIS_FILE, "Stopping stream..")); if (stream->play_strm) err = Pa_StopStream(stream->play_strm); if (stream->rec_strm && stream->rec_strm != stream->play_strm) err = Pa_StopStream(stream->rec_strm); stream->play_thread_initialized = 0; stream->rec_thread_initialized = 0; PJ_LOG(5,(THIS_FILE, "Done, status=%d", err)); return err ? PJMEDIA_AUDIODEV_ERRNO_FROM_PORTAUDIO(err) : PJ_SUCCESS; }
/* API: destroy stream. */ static pj_status_t strm_destroy(pjmedia_aud_stream *s) { struct pa_aud_stream *stream = (struct pa_aud_stream*)s; int i, err = 0; stream->quit_flag = 1; for (i=0; !stream->rec_thread_exited && i<100; ++i) { pj_thread_sleep(1); } for (i=0; !stream->play_thread_exited && i<100; ++i) { pj_thread_sleep(1); } PJ_LOG(5,(THIS_FILE, "Closing %.*s: %lu underflow, %lu overflow", (int)stream->name.slen, stream->name.ptr, stream->underflow, stream->overflow)); if (stream->play_strm) err = Pa_CloseStream(stream->play_strm); if (stream->rec_strm && stream->rec_strm != stream->play_strm) err = Pa_CloseStream(stream->rec_strm); pj_pool_release(stream->pool); return err ? PJMEDIA_AUDIODEV_ERRNO_FROM_PORTAUDIO(err) : PJ_SUCCESS; }
static int stun_destroy_test_session(struct stun_test_session *test_sess) { unsigned i; pj_stun_sock_cb stun_cb; pj_status_t status; pj_stun_sock *stun_sock[MAX_SOCK_CLIENTS]; pj_bzero(&stun_cb, sizeof(stun_cb)); stun_cb.on_status = &stun_sock_on_status; pj_event_reset(test_sess->server_event); /* Create all clients first */ for (i=0; i<MAX_SOCK_CLIENTS; ++i) { char name[10]; sprintf(name, "stun%02d", i); status = pj_stun_sock_create(&test_sess->stun_cfg, name, pj_AF_INET(), &stun_cb, NULL, test_sess, &stun_sock[i]); if (status != PJ_SUCCESS) { PJ_PERROR(1,(THIS_FILE, status, "Error creating stun socket")); return -10; } } /* Start resolution */ for (i=0; i<MAX_SOCK_CLIENTS; ++i) { pj_str_t server_ip = pj_str("127.0.0.1"); status = pj_stun_sock_start(stun_sock[i], &server_ip, (pj_uint16_t)test_sess->server_port, NULL); if (status != PJ_SUCCESS) { PJ_PERROR(1,(THIS_FILE, status, "Error starting stun socket")); return -20; } } /* settle down */ pj_thread_sleep(test_sess->param.client_sleep_after_start); /* Resume server threads */ pj_event_set(test_sess->server_event); pj_thread_sleep(test_sess->param.client_sleep_before_destroy); /* Destroy clients */ for (i=0; i<MAX_SOCK_CLIENTS; ++i) { status = pj_stun_sock_destroy(stun_sock[i]); if (status != PJ_SUCCESS) { PJ_PERROR(1,(THIS_FILE, status, "Error destroying stun socket")); } } /* Give some time to ioqueue to free sockets */ pj_thread_sleep(PJ_IOQUEUE_KEY_FREE_DELAY); return 0; }
static void benchmark(void) { FILETIME creation_time, exit_time; struct Times start, end; DWORD ts, te; LARGE_INTEGER elapsed; BOOL rc; int i; double pct; puts("Test started!"); fflush(stdout); ts = GetTickCount(); rc = GetProcessTimes(GetCurrentProcess(), &creation_time, &exit_time, &start.kernel_time, &start.user_time); for (i=DURATION; i>0; --i) { printf("\r%d ", i); fflush(stdout); pj_thread_sleep(1000); } rc = GetProcessTimes(GetCurrentProcess(), &creation_time, &exit_time, &end.kernel_time, &end.user_time); te = GetTickCount(); process(&start); process(&end); elapsed.QuadPart = end.u_total.QuadPart - start.u_total.QuadPart; pct = elapsed.QuadPart * 100.0 / ((te-ts)*10000.0); printf("CPU usage=%6.4f%%\n", pct); fflush(stdout); }
static int simple_sleep_test(void) { enum { COUNT = 10 }; int i; pj_status_t rc; PJ_LOG(3,(THIS_FILE, "..will write messages every 1 second:")); for (i=0; i<COUNT; ++i) { pj_time_val tv; pj_parsed_time pt; rc = pj_thread_sleep(1000); if (rc != PJ_SUCCESS) { app_perror("...error: pj_thread_sleep()", rc); return -10; } rc = pj_gettimeofday(&tv); if (rc != PJ_SUCCESS) { app_perror("...error: pj_gettimeofday()", rc); return -11; } pj_time_decode(&tv, &pt); PJ_LOG(3,(THIS_FILE, "...%04d-%02d-%02d %02d:%02d:%02d.%03d", pt.year, pt.mon, pt.day, pt.hour, pt.min, pt.sec, pt.msec)); } return 0; }
/* Utility: display error message and exit application (usually * because of fatal error. */ static void err_exit(const char *title, pj_status_t status) { if (status != PJ_SUCCESS) { icedemo_perror(title, status); } PJ_LOG(3,(THIS_FILE, "Shutting down..")); if (icedemo.icest) pj_ice_strans_destroy(icedemo.icest); pj_thread_sleep(500); icedemo.thread_quit_flag = PJ_TRUE; if (icedemo.thread) { pj_thread_join(icedemo.thread); pj_thread_destroy(icedemo.thread); } if (icedemo.ice_cfg.stun_cfg.ioqueue) pj_ioqueue_destroy(icedemo.ice_cfg.stun_cfg.ioqueue); if (icedemo.ice_cfg.stun_cfg.timer_heap) pj_timer_heap_destroy(icedemo.ice_cfg.stun_cfg.timer_heap); pj_caching_pool_destroy(&icedemo.cp); pj_shutdown(); if (icedemo.log_fhnd) { fclose(icedemo.log_fhnd); icedemo.log_fhnd = NULL; } exit(status != PJ_SUCCESS); }
static int timer_thread_run(void* p) { pj_time_val tick = {0, 10}; timer_running = 1; while (timer_running) { if (pj_timer_heap_count(timer) == 0) { pj_sem_wait(timer_sem); } else { pj_thread_sleep(PJ_TIME_VAL_MSEC(tick)); pj_timer_heap_poll(timer, NULL); } } pj_timer_heap_destroy(timer); timer = NULL; pj_sem_destroy(timer_sem); timer_sem = NULL; pj_pool_release(timer_pool); timer_pool = NULL; timer_initialized = 0; return 0; }
static void on_response(pj_http_req *hreq, const pj_http_resp *resp) { pj_size_t i; PJ_UNUSED_ARG(hreq); PJ_UNUSED_ARG(resp); PJ_UNUSED_ARG(i); #ifdef VERBOSE printf("%.*s, %d, %.*s\n", STR_PREC(resp->version), resp->status_code, STR_PREC(resp->reason)); for (i = 0; i < resp->headers.count; i++) { printf("%.*s : %.*s\n", STR_PREC(resp->headers.header[i].name), STR_PREC(resp->headers.header[i].value)); } #endif if (test_cancel) { /* Need to delay closing the client socket here, otherwise the * server will get SIGPIPE when sending response. */ pj_thread_sleep(100); pj_http_req_cancel(hreq, PJ_TRUE); test_cancel = PJ_FALSE; } }
static int timestamp_accuracy() { pj_timestamp freq, t1, t2; pj_time_val tv1, tv2, tvtmp; pj_uint32_t msec, tics; pj_int64_t diff; PJ_LOG(3,(THIS_FILE, "...testing frequency accuracy (pls wait)")); pj_get_timestamp_freq(&freq); /* Get the start time */ pj_gettimeofday(&tvtmp); do { pj_gettimeofday(&tv1); } while (PJ_TIME_VAL_EQ(tvtmp, tv1)); pj_get_timestamp(&t1); /* Sleep for 5 seconds */ pj_thread_sleep(10000); /* Get end time */ pj_gettimeofday(&tvtmp); do { pj_gettimeofday(&tv2); } while (PJ_TIME_VAL_EQ(tvtmp, tv2)); pj_get_timestamp(&t2); /* Get the elapsed time */ PJ_TIME_VAL_SUB(tv2, tv1); msec = PJ_TIME_VAL_MSEC(tv2); /* Check that the frequency match the elapsed time */ tics = (unsigned)(t2.u64 - t1.u64); diff = tics - (msec * freq.u64 / 1000); if (diff < 0) diff = -diff; /* Only allow 1 msec mismatch */ if (diff > (pj_int64_t)(freq.u64 / 1000)) { PJ_LOG(3,(THIS_FILE, "....error: timestamp drifted by %d usec after " "%d msec", (pj_uint32_t)(diff * 1000000 / freq.u64), msec)); return -2000; /* Otherwise just print warning if timestamp drifted by >1 usec */ } else if (diff > (pj_int64_t)(freq.u64 / 1000000)) { PJ_LOG(3,(THIS_FILE, "....warning: timestamp drifted by %d usec after " "%d msec", (pj_uint32_t)(diff * 1000000 / freq.u64), msec)); } else { PJ_LOG(3,(THIS_FILE, "....good. Timestamp is accurate down to" " nearest usec.")); } return 0; }
int echo_srv_common_loop(pj_atomic_t *bytes_counter) { pj_highprec_t last_received, avg_bw, highest_bw; pj_time_val last_print; unsigned count; const char *ioqueue_name; last_received = 0; pj_gettimeofday(&last_print); avg_bw = highest_bw = 0; count = 0; ioqueue_name = pj_ioqueue_name(); for (;;) { pj_highprec_t received, cur_received, bw; unsigned msec; pj_time_val now, duration; pj_thread_sleep(1000); received = cur_received = pj_atomic_get(bytes_counter); cur_received = cur_received - last_received; pj_gettimeofday(&now); duration = now; PJ_TIME_VAL_SUB(duration, last_print); msec = PJ_TIME_VAL_MSEC(duration); bw = cur_received; pj_highprec_mul(bw, 1000); pj_highprec_div(bw, msec); last_print = now; last_received = received; avg_bw = avg_bw + bw; count++; PJ_LOG(3,("", "%s UDP (%d threads): %u KB/s (avg=%u KB/s) %s", ioqueue_name, ECHO_SERVER_MAX_THREADS, (unsigned)(bw / 1000), (unsigned)(avg_bw / count / 1000), (count==20 ? "<ses avg>" : ""))); if (count==20) { if (avg_bw/count > highest_bw) highest_bw = avg_bw/count; count = 0; avg_bw = 0; PJ_LOG(3,("", "Highest average bandwidth=%u KB/s", (unsigned)(highest_bw/1000))); } } PJ_UNREACHED(return 0;) }
/* * Clock thread */ static int clock_thread(void *arg) { pj_timestamp now; pjmedia_clock *clock = (pjmedia_clock*) arg; /* Set thread priority to maximum unless not wanted. */ if ((clock->options & PJMEDIA_CLOCK_NO_HIGHEST_PRIO) == 0) { int max = pj_thread_get_prio_max(pj_thread_this()); if (max > 0) pj_thread_set_prio(pj_thread_this(), max); } //printf("%s:------------11--------------\n", THIS_FILE); /* Get the first tick */ pj_get_timestamp(&clock->next_tick); clock->next_tick.u64 += clock->interval.u64; while (!clock->quitting) { pj_get_timestamp(&now); /* Wait for the next tick to happen */ if (now.u64 < clock->next_tick.u64) { unsigned msec; msec = pj_elapsed_msec(&now, &clock->next_tick); pj_thread_sleep(msec); } //printf("%s:------------12--------------, 0x%02x, %d\n", THIS_FILE, clock, (int)(clock->quitting)); /* Skip if not running */ if (!clock->running) { /* Calculate next tick */ clock_calc_next_tick(clock, &now); continue; } pj_lock_acquire(clock->lock); //printf("%s:------------13--------------, 0x%02x, %d\n", THIS_FILE, clock, (int)(clock->quitting)); /* Call callback, if any */ if (clock->cb) (*clock->cb)(&clock->timestamp, clock->user_data); /* Best effort way to detect if we've been destroyed in the callback */ if (clock->quitting) break; /* Increment timestamp */ clock->timestamp.u64 += clock->timestamp_inc; //printf("%s:------------14--------------, 0x%02x, %d\n", THIS_FILE, clock, (int)(clock->quitting)); /* Calculate next tick */ clock_calc_next_tick(clock, &now); //printf("%s:------------15--------------\n", THIS_FILE); pj_lock_release(clock->lock); } return 0; }
/* * Poll the I/O Queue for completed events. */ PJ_DEF(int) pj_ioqueue_poll( pj_ioqueue_t *ioq, const pj_time_val *timeout) { /* Polling is not necessary on UWP, since each socket handles * its events already. */ PJ_UNUSED_ARG(ioq); pj_thread_sleep(PJ_TIME_VAL_MSEC(*timeout)); return 0; }
static pj_status_t wait_play(pjmedia_frame *f) { play_frm_copied = PJ_FALSE; play_frm = *f; play_frm_ready = PJ_TRUE; while (!play_frm_copied) { pj_thread_sleep(1); } play_frm_ready = PJ_FALSE; return PJ_SUCCESS; }
int do_test(void *user) { int i; pj_pool_t *pool = (pj_pool_t *)user; opool_init(&opool, 10, strlen(s)+10, pool); for (i = 0; i < 100; i++) { opool_item_t *p_item = opool_get(&opool); pj_memcpy(p_item->data, s, strlen(s)); printf("%d: %s\n", i, p_item->data); pj_thread_sleep(pj_rand()%100); opool_free(&opool, p_item); } return 0; }
/* * Handle timer and network events */ static void srv_handle_events(pj_turn_srv *srv, const pj_time_val *max_timeout) { /* timeout is 'out' var. This just to make compiler happy. */ pj_time_val timeout = { 0, 0}; unsigned net_event_count = 0; int c; /* Poll the timer. The timer heap has its own mutex for better * granularity, so we don't need to lock the server. */ timeout.sec = timeout.msec = 0; c = pj_timer_heap_poll( srv->core.timer_heap, &timeout ); /* timer_heap_poll should never ever returns negative value, or otherwise * ioqueue_poll() will block forever! */ pj_assert(timeout.sec >= 0 && timeout.msec >= 0); if (timeout.msec >= 1000) timeout.msec = 999; /* If caller specifies maximum time to wait, then compare the value with * the timeout to wait from timer, and use the minimum value. */ if (max_timeout && PJ_TIME_VAL_GT(timeout, *max_timeout)) { timeout = *max_timeout; } /* Poll ioqueue. * Repeat polling the ioqueue while we have immediate events, because * timer heap may process more than one events, so if we only process * one network events at a time (such as when IOCP backend is used), * the ioqueue may have trouble keeping up with the request rate. * * For example, for each send() request, one network event will be * reported by ioqueue for the send() completion. If we don't poll * the ioqueue often enough, the send() completion will not be * reported in timely manner. */ do { c = pj_ioqueue_poll( srv->core.ioqueue, &timeout); if (c < 0) { pj_thread_sleep(PJ_TIME_VAL_MSEC(timeout)); return; } else if (c == 0) { break; } else { net_event_count += c; timeout.sec = timeout.msec = 0; } } while (c > 0 && net_event_count < MAX_NET_EVENTS); }
void queue_enqueue(queue_t *queue, void *value) { pthread_mutex_lock(&(queue->mutex)); while (queue->size == queue->capacity) { pj_thread_sleep(2); pthread_cond_wait(&(queue->cond_full), &(queue->mutex)); } queue->buffer[queue->in] = value; ++ queue->size; ++ queue->in; queue->in %= queue->capacity; pthread_mutex_unlock(&(queue->mutex)); pthread_cond_broadcast(&(queue->cond_empty)); }
pj_status_t PJStunTurn::handle_events(unsigned max_msec, unsigned* p_count) { enum { MAX_NET_EVENTS = 1 }; pj_time_val max_timeout = {0, 0}; pj_time_val timeout = {0, 0}; unsigned count = 0, net_event_count = 0; int c; max_timeout.msec = max_msec; /* Poll the timer to run it and also to retrieve the earliest entry. */ timeout.sec = timeout.msec = 0; c = pj_timer_heap_poll(ice_cfg_.stun_cfg.timer_heap, &timeout); if (c > 0) count += c; /* timer_heap_poll should never ever returns negative value, or otherwise * ioqueue_poll() will block forever! */ pj_assert(timeout.sec >= 0 && timeout.msec >= 0); if (timeout.msec >= 1000) timeout.msec = 999; /* compare the value with the timeout to wait from timer, and use the * minimum value. */ if (PJ_TIME_VAL_GT(timeout, max_timeout)) timeout = max_timeout; /* Poll ioqueue. * Repeat polling the ioqueue while we have immediate events, because * timer heap may process more than one events, so if we only process * one network events at a time (such as when IOCP backend is used), * the ioqueue may have trouble keeping up with the request rate. * * For example, for each send() request, one network event will be * reported by ioqueue for the send() completion. If we don't poll * the ioqueue often enough, the send() completion will not be * reported in timely manner. */ do { c = pj_ioqueue_poll(ice_cfg_.stun_cfg.ioqueue, &timeout); if (c < 0) { pj_status_t err = pj_get_netos_error(); pj_thread_sleep(PJ_TIME_VAL_MSEC(timeout)); if (p_count) *p_count = count; return err; } else if (c == 0) { break; } else { net_event_count += c; timeout.sec = timeout.msec = 0; } } while (c > 0 && net_event_count < MAX_NET_EVENTS); count += net_event_count; if (p_count) *p_count = count; return PJ_SUCCESS; }
/* * Stop stream. */ PJ_DEF(pj_status_t) pjmedia_snd_stream_stop(pjmedia_snd_stream *stream) { int i, err = 0; stream->quit_flag = 1; for (i=0; !stream->rec_thread_exited && i<100; ++i) pj_thread_sleep(10); for (i=0; !stream->play_thread_exited && i<100; ++i) pj_thread_sleep(10); pj_thread_sleep(1); PJ_LOG(5,(THIS_FILE, "Stopping stream..")); if (stream->play_strm) err = Pa_StopStream(stream->play_strm); if (stream->rec_strm && stream->rec_strm != stream->play_strm) err = Pa_StopStream(stream->rec_strm); PJ_LOG(5,(THIS_FILE, "Done, status=%d", err)); return err ? PJMEDIA_ERRNO_FROM_PORTAUDIO(err) : PJ_SUCCESS; }
void *queue_dequeue(queue_t *queue) { pthread_mutex_lock(&(queue->mutex)); while (queue->size == 0) { pj_thread_sleep(2); pthread_cond_wait(&(queue->cond_empty), &(queue->mutex)); } void *value = queue->buffer[queue->out]; //printf("dequeue %d\n", *(int *)value); -- queue->size; ++ queue->out; queue->out %= queue->capacity; pthread_mutex_unlock(&(queue->mutex)); pthread_cond_broadcast(&(queue->cond_full)); return value; }
/* * Poll the clock. */ PJ_DEF(pj_bool_t) pjmedia_clock_wait( pjmedia_clock *clock, pj_bool_t wait, pj_timestamp *ts) { pj_timestamp now; pj_status_t status; PJ_ASSERT_RETURN(clock != NULL, PJ_FALSE); PJ_ASSERT_RETURN((clock->options & PJMEDIA_CLOCK_NO_ASYNC) != 0, PJ_FALSE); PJ_ASSERT_RETURN(clock->running, PJ_FALSE); status = pj_get_timestamp(&now); if (status != PJ_SUCCESS) return PJ_FALSE; /* Wait for the next tick to happen */ if (now.u64 < clock->next_tick.u64) { unsigned msec; if (!wait) return PJ_FALSE; msec = pj_elapsed_msec(&now, &clock->next_tick); pj_thread_sleep(msec); } /* Call callback, if any */ if (clock->cb) (*clock->cb)(&clock->timestamp, clock->user_data); /* Report timestamp to caller */ if (ts) ts->u64 = clock->timestamp.u64; /* Increment timestamp */ clock->timestamp.u64 += clock->samples_per_frame; /* Calculate next tick */ clock->next_tick.u64 += clock->interval.u64; /* Done */ return PJ_TRUE; }
static void ui_sleep(char menuin[]) { if (pj_ansi_strnicmp(menuin, "sleep", 5)==0) { pj_str_t tmp; int delay; tmp.ptr = menuin+6; tmp.slen = pj_ansi_strlen(menuin)-7; if (tmp.slen < 1) { puts("Usage: sleep MSEC"); return; } delay = pj_strtoul(&tmp); if (delay < 0) delay = 0; pj_thread_sleep(delay); } }
/* * Clock thread */ static int clock_thread(void *arg) { pj_timestamp now; pjmedia_clock *clock = arg; /* Get the first tick */ pj_get_timestamp(&clock->next_tick); clock->next_tick.u64 += clock->interval.u64; while (!clock->quitting) { pj_get_timestamp(&now); /* Wait for the next tick to happen */ if (now.u64 < clock->next_tick.u64) { unsigned msec; msec = pj_elapsed_msec(&now, &clock->next_tick); pj_thread_sleep(msec); } /* Skip if not running */ if (!clock->running) continue; pj_lock_acquire(clock->lock); /* Call callback, if any */ if (clock->cb) (*clock->cb)(&clock->timestamp, clock->user_data); /* Increment timestamp */ clock->timestamp.u64 += clock->samples_per_frame; /* Calculate next tick */ clock->next_tick.u64 += clock->interval.u64; pj_lock_release(clock->lock); } return 0; }
static void destroy_stack(void) { enum { WAIT_CLEAR = 5000, WAIT_INTERVAL = 500 }; unsigned i; PJ_LOG(3,(THIS_FILE, "Shutting down..")); /* Wait until all clear */ hangup_all(); for (i=0; i<WAIT_CLEAR/WAIT_INTERVAL; ++i) { unsigned j; for (j=0; j<MAX_CALLS; ++j) { call_t *call = &app.call[j]; if (call->inv && call->inv->state <= PJSIP_INV_STATE_CONFIRMED) break; } if (j==MAX_CALLS) return; pj_thread_sleep(WAIT_INTERVAL); } app.quit = PJ_TRUE; if (app.worker_thread) { pj_thread_join(app.worker_thread); app.worker_thread = NULL; } //if (app.med_endpt) //pjmedia_endpt_destroy(app.med_endpt); if (app.sip_endpt) pjsip_endpt_destroy(app.sip_endpt); if (app.pool) pj_pool_release(app.pool); dump_pool_usage(THIS_FILE, &app.cp); pj_caching_pool_destroy(&app.cp); }
static int rt_worker_thread(void *arg) { int i; pj_time_val poll_delay = { 0, 10 }; PJ_UNUSED_ARG(arg); /* Sleep to allow main threads to run. */ pj_thread_sleep(10); while (!rt_stop) { pjsip_endpt_handle_events(endpt, &poll_delay); } /* Exhaust responses. */ for (i=0; i<100; ++i) pjsip_endpt_handle_events(endpt, &poll_delay); return 0; }
int main() { pj_caching_pool cp; pj_pool_t *pool; int i; pj_thread_t *thread1; pj_log_set_level(3); CHECK(__FILE__, pj_init()); pj_srand(123765); pj_caching_pool_init(&cp, NULL, 1024); pool = pj_pool_create(&cp.factory, "objpool", 128, 128, NULL); pj_thread_create(pool, "thread1", &do_test, pool, PJ_THREAD_DEFAULT_STACK_SIZE, 0, &thread1); pj_thread_sleep(500); do_test(pool); pj_thread_join(thread1); pj_pool_release(pool); pj_caching_pool_destroy(&cp); pj_shutdown(); return 0; }
/* * main() */ int main(int argc, char *argv[]) { pj_caching_pool cp; pjmedia_endpt *med_endpt; pj_pool_t *pool; pjmedia_port *file_port; pjmedia_snd_port *snd_port; char tmp[10]; pj_status_t status; if (argc != 2) { puts("Error: filename required"); puts(desc); return 1; } /* Must init PJLIB first: */ status = pj_init(); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); /* Must create a pool factory before we can allocate any memory. */ pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0); /* * Initialize media endpoint. * This will implicitly initialize PJMEDIA too. */ status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); /* Create memory pool for our file player */ pool = pj_pool_create( &cp.factory, /* pool factory */ "wav", /* pool name. */ 4000, /* init size */ 4000, /* increment size */ NULL /* callback on error */ ); /* Create file media port from the WAV file */ status = pjmedia_wav_player_port_create( pool, /* memory pool */ argv[1], /* file to play */ 20, /* ptime. */ 0, /* flags */ 0, /* default buffer */ &file_port/* returned port */ ); if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "Unable to use WAV file", status); return 1; } /* Create sound player port. */ status = pjmedia_snd_port_create_player( pool, /* pool */ -1, /* use default dev. */ file_port->info.clock_rate, /* clock rate. */ file_port->info.channel_count, /* # of channels. */ file_port->info.samples_per_frame, /* samples per frame. */ file_port->info.bits_per_sample, /* bits per sample. */ 0, /* options */ &snd_port /* returned port */ ); if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "Unable to open sound device", status); return 1; } /* Connect file port to the sound player. * Stream playing will commence immediately. */ status = pjmedia_snd_port_connect( snd_port, file_port); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); /* * File should be playing and looping now, using sound device's thread. */ /* Sleep to allow log messages to flush */ pj_thread_sleep(100); printf("Playing %s..\n", argv[1]); puts(""); puts("Press <ENTER> to stop playing and quit"); if (fgets(tmp, sizeof(tmp), stdin) == NULL) { puts("EOF while reading stdin, will quit now.."); } /* Start deinitialization: */ /* Disconnect sound port from file port */ status = pjmedia_snd_port_disconnect(snd_port); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); /* Without this sleep, Windows/DirectSound will repeteadly * play the last frame during destroy. */ pj_thread_sleep(100); /* Destroy sound device */ status = pjmedia_snd_port_destroy( snd_port ); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); /* Destroy file port */ status = pjmedia_port_destroy( file_port ); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); /* Release application pool */ pj_pool_release( pool ); /* Destroy media endpoint. */ pjmedia_endpt_destroy( med_endpt ); /* Destroy pool factory */ pj_caching_pool_destroy( &cp ); /* Shutdown PJLIB */ pj_shutdown(); /* Done. */ return 0; }
int transport_rt_test( pjsip_transport_type_e tp_type, pjsip_transport *ref_tp, char *target_url, int *lost) { enum { THREADS = 4, INTERVAL = 10 }; int i; pj_status_t status; pj_pool_t *pool; pj_bool_t logger_enabled; pj_timestamp zero_time, total_time; unsigned usec_rt; unsigned total_sent; unsigned total_recv; PJ_UNUSED_ARG(tp_type); PJ_UNUSED_ARG(ref_tp); PJ_LOG(3,(THIS_FILE, " multithreaded round-trip test (%d threads)...", THREADS)); PJ_LOG(3,(THIS_FILE, " this will take approx %d seconds, please wait..", INTERVAL)); /* Make sure msg logger is disabled. */ logger_enabled = msg_logger_set_enabled(0); /* Register module (if not yet registered) */ if (rt_module.id == -1) { status = pjsip_endpt_register_module( endpt, &rt_module ); if (status != PJ_SUCCESS) { app_perror(" error: unable to register module", status); return -600; } } /* Create pool for this test. */ pool = pjsip_endpt_create_pool(endpt, NULL, 4000, 4000); if (!pool) return -610; /* Initialize static test data. */ pj_ansi_strcpy(rt_target_uri, target_url); rt_call_id = pj_str("RT-Call-Id/"); rt_stop = PJ_FALSE; /* Initialize thread data. */ for (i=0; i<THREADS; ++i) { char buf[1]; pj_str_t str_id; pj_strset(&str_id, buf, 1); pj_bzero(&rt_test_data[i], sizeof(rt_test_data[i])); /* Init timer entry */ rt_test_data[i].tx_timer.id = i; rt_test_data[i].tx_timer.cb = &rt_tx_timer; rt_test_data[i].timeout_timer.id = i; rt_test_data[i].timeout_timer.cb = &rt_timeout_timer; /* Generate Call-ID for each thread. */ rt_test_data[i].call_id.ptr = (char*) pj_pool_alloc(pool, rt_call_id.slen+1); pj_strcpy(&rt_test_data[i].call_id, &rt_call_id); buf[0] = '0' + (char)i; pj_strcat(&rt_test_data[i].call_id, &str_id); /* Init mutex. */ status = pj_mutex_create_recursive(pool, "rt", &rt_test_data[i].mutex); if (status != PJ_SUCCESS) { app_perror(" error: unable to create mutex", status); return -615; } /* Create thread, suspended. */ status = pj_thread_create(pool, "rttest%p", &rt_worker_thread, (void*)(long)i, 0, PJ_THREAD_SUSPENDED, &rt_test_data[i].thread); if (status != PJ_SUCCESS) { app_perror(" error: unable to create thread", status); return -620; } } /* Start threads! */ for (i=0; i<THREADS; ++i) { pj_time_val delay = {0,0}; pj_thread_resume(rt_test_data[i].thread); /* Schedule first message transmissions. */ rt_test_data[i].tx_timer.user_data = (void*)1; pjsip_endpt_schedule_timer(endpt, &rt_test_data[i].tx_timer, &delay); } /* Sleep for some time. */ pj_thread_sleep(INTERVAL * 1000); /* Signal thread to stop. */ rt_stop = PJ_TRUE; /* Wait threads to complete. */ for (i=0; i<THREADS; ++i) { pj_thread_join(rt_test_data[i].thread); pj_thread_destroy(rt_test_data[i].thread); } /* Destroy rt_test_data */ for (i=0; i<THREADS; ++i) { pj_mutex_destroy(rt_test_data[i].mutex); pjsip_endpt_cancel_timer(endpt, &rt_test_data[i].timeout_timer); } /* Gather statistics. */ pj_bzero(&total_time, sizeof(total_time)); pj_bzero(&zero_time, sizeof(zero_time)); usec_rt = total_sent = total_recv = 0; for (i=0; i<THREADS; ++i) { total_sent += rt_test_data[i].sent_request_count; total_recv += rt_test_data[i].recv_response_count; pj_add_timestamp(&total_time, &rt_test_data[i].total_rt_time); } /* Display statistics. */ if (total_recv) total_time.u64 = total_time.u64/total_recv; else total_time.u64 = 0; usec_rt = pj_elapsed_usec(&zero_time, &total_time); PJ_LOG(3,(THIS_FILE, " done.")); PJ_LOG(3,(THIS_FILE, " total %d messages sent", total_sent)); PJ_LOG(3,(THIS_FILE, " average round-trip=%d usec", usec_rt)); pjsip_endpt_release_pool(endpt, pool); *lost = total_sent-total_recv; /* Flush events. */ flush_events(500); /* Restore msg logger. */ msg_logger_set_enabled(logger_enabled); return 0; }
/* * timeslice_test() */ static int timeslice_test(void) { enum { NUM_THREADS = 4 }; pj_pool_t *pool; pj_uint32_t counter[NUM_THREADS], lowest, highest, diff; pj_thread_t *thread[NUM_THREADS]; unsigned i; pj_status_t rc; quit_flag = 0; pool = pj_pool_create(mem, NULL, 4000, 4000, NULL); if (!pool) return -10; PJ_LOG(3,(THIS_FILE, "..timeslice testing with %d threads", NUM_THREADS)); /* Create all threads in suspended mode. */ for (i=0; i<NUM_THREADS; ++i) { counter[i] = i; rc = pj_thread_create(pool, "thread", (pj_thread_proc*)&thread_proc, &counter[i], PJ_THREAD_DEFAULT_STACK_SIZE, PJ_THREAD_SUSPENDED, &thread[i]); if (rc!=PJ_SUCCESS) { app_perror("...ERROR in pj_thread_create()", rc); return -20; } } /* Sleep for 1 second. * The purpose of this is to test whether all threads are suspended. */ TRACE__((THIS_FILE, " Main thread waiting..")); pj_thread_sleep(1000); TRACE__((THIS_FILE, " Main thread resuming..")); /* Check that all counters are still zero. */ for (i=0; i<NUM_THREADS; ++i) { if (counter[i] > i) { PJ_LOG(3,(THIS_FILE, "....ERROR! Thread %d-th is not suspended!", i)); return -30; } } /* Now resume all threads. */ for (i=0; i<NUM_THREADS; ++i) { TRACE__((THIS_FILE, " Resuming thread %d [%p]..", i, thread[i])); rc = pj_thread_resume(thread[i]); if (rc != PJ_SUCCESS) { app_perror("...ERROR in pj_thread_resume()", rc); return -40; } } /* Main thread sleeps for some time to allow threads to run. * The longer we sleep, the more accurate the calculation will be, * but it'll make user waits for longer for the test to finish. */ TRACE__((THIS_FILE, " Main thread waiting (5s)..")); pj_thread_sleep(5000); TRACE__((THIS_FILE, " Main thread resuming..")); /* Signal all threads to quit. */ quit_flag = 1; /* Wait until all threads quit, then destroy. */ for (i=0; i<NUM_THREADS; ++i) { TRACE__((THIS_FILE, " Main thread joining thread %d [%p]..", i, thread[i])); rc = pj_thread_join(thread[i]); if (rc != PJ_SUCCESS) { app_perror("...ERROR in pj_thread_join()", rc); return -50; } TRACE__((THIS_FILE, " Destroying thread %d [%p]..", i, thread[i])); rc = pj_thread_destroy(thread[i]); if (rc != PJ_SUCCESS) { app_perror("...ERROR in pj_thread_destroy()", rc); return -60; } } TRACE__((THIS_FILE, " Main thread calculating time slices..")); /* Now examine the value of the counters. * Check that all threads had equal proportion of processing. */ lowest = 0xFFFFFFFF; highest = 0; for (i=0; i<NUM_THREADS; ++i) { if (counter[i] < lowest) lowest = counter[i]; if (counter[i] > highest) highest = counter[i]; } /* Check that all threads are running. */ if (lowest < 2) { PJ_LOG(3,(THIS_FILE, "...ERROR: not all threads were running!")); return -70; } /* The difference between lowest and higest should be lower than 50%. */ diff = (highest-lowest)*100 / ((highest+lowest)/2); if ( diff >= 50) { PJ_LOG(3,(THIS_FILE, "...ERROR: thread didn't have equal timeslice!")); PJ_LOG(3,(THIS_FILE, ".....lowest counter=%u, highest counter=%u, diff=%u%%", lowest, highest, diff)); return -80; } else { PJ_LOG(3,(THIS_FILE, "...info: timeslice diff between lowest & highest=%u%%", diff)); } pj_pool_release(pool); return 0; }