WARNING: The online documentation has moved to https://docs.pjsip.org.

Visit the new documentation at https://docs.pjsip.org:

BLOG | DOCUMENTATION | GITHUB

Home --> Documentations --> PJMEDIA Reference

Samples: Benchmarking Conference Bridge

Benchmarking pjmedia (conference bridge+resample). For my use only, and it only works in Win32.

This file is pjsip-apps/src/samples/confbench.c

1/*
2 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
3 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20
33#include <pjmedia.h>
34#include <pjlib-util.h> /* pj_getopt */
35#include <pjlib.h>
36#include <stdlib.h> /* atoi() */
37#include <stdio.h>
38#include <windows.h>
39
40/* For logging purpose. */
41#define THIS_FILE "confsample.c"
42
43
44/* Configurable:
45 * LARGE_SET will create in total of about 232 ports.
46 * HAS_RESAMPLE will activate resampling on about half
47 * the port.
48 */
49#define TEST_SET LARGE_SET
50#define HAS_RESAMPLE 0
51
52
53#define SMALL_SET 16
54#define LARGE_SET 100
55
56
57#define PORT_COUNT 254
58#define CLOCK_RATE 16000
59#define SAMPLES_PER_FRAME (CLOCK_RATE/100)
60#if HAS_RESAMPLE
61# define SINE_CLOCK 32000
62#else
63# define SINE_CLOCK CLOCK_RATE
64#endif
65#define SINE_PTIME 20
66#define DURATION 10
67
68#define SINE_COUNT TEST_SET
69#define NULL_COUNT TEST_SET
70#define IDLE_COUNT 32
71
72
73static void app_perror(const char *sender, const char *title, pj_status_t status)
74{
75 char errmsg[PJ_ERR_MSG_SIZE];
76
77 pj_strerror(status, errmsg, sizeof(errmsg));
78 PJ_LOG(1,(sender, "%s: %s", title, errmsg));
79}
80
81
82struct Times
83{
84 FILETIME kernel_time;
85 ULARGE_INTEGER u_kernel_time;
86 FILETIME user_time;
87 ULARGE_INTEGER u_user_time;
88 ULARGE_INTEGER u_total;
89};
90
91static void process(struct Times *t)
92{
93 pj_memcpy(&t->u_kernel_time, &t->kernel_time, sizeof(FILETIME));
94 pj_memcpy(&t->u_user_time, &t->user_time, sizeof(FILETIME));
95 t->u_total.QuadPart = t->u_kernel_time.QuadPart + t->u_user_time.QuadPart;
96}
97
98static void benchmark(void)
99{
100 FILETIME creation_time, exit_time;
101 struct Times start, end;
102 DWORD ts, te;
103 LARGE_INTEGER elapsed;
104 BOOL rc;
105 int i;
106 double pct;
107
108 puts("Test started!"); fflush(stdout);
109
110 ts = GetTickCount();
111 rc = GetProcessTimes(GetCurrentProcess(), &creation_time, &exit_time,
112 &start.kernel_time, &start.user_time);
113 for (i=DURATION; i>0; --i) {
114 printf("\r%d ", i); fflush(stdout);
115 pj_thread_sleep(1000);
116 }
117 rc = GetProcessTimes(GetCurrentProcess(), &creation_time, &exit_time,
118 &end.kernel_time, &end.user_time);
119 te = GetTickCount();
120
121 process(&start);
122 process(&end);
123
124 elapsed.QuadPart = end.u_total.QuadPart - start.u_total.QuadPart;
125
126 pct = elapsed.QuadPart * 100.0 / ((te-ts)*10000.0);
127
128 printf("CPU usage=%6.4f%%\n", pct); fflush(stdout);
129}
130
131
132
133/* Struct attached to sine generator */
134typedef struct
135{
136 pj_int16_t *samples; /* Sine samples. */
137} port_data;
138
139
140/* This callback is called to feed more samples */
141static pj_status_t sine_get_frame( pjmedia_port *port,
142 pjmedia_frame *frame)
143{
144 port_data *sine = port->port_data.pdata;
145 pj_int16_t *samples = frame->buf;
146 unsigned i, left, right;
147 pj_size_t count;
148
149 /* Get number of samples */
150 count = frame->size / 2 / PJMEDIA_PIA_CCNT(&port->info);
151
152 left = 0;
153 right = 0;
154
155 for (i=0; i<count; ++i) {
156 *samples++ = sine->samples[left];
157 ++left;
158
159 if (PJMEDIA_PIA_CCNT(&port->info) == 2) {
160 *samples++ = sine->samples[right];
161 right += 2; /* higher pitch so we can distinguish left and right. */
162 if (right >= count)
163 right = 0;
164 }
165 }
166
167 /* Must set frame->type correctly, otherwise the sound device
168 * will refuse to play.
169 */
171
172 return PJ_SUCCESS;
173}
174
175#ifndef M_PI
176#define M_PI (3.14159265)
177#endif
178
179/*
180 * Create a media port to generate sine wave samples.
181 */
182static pj_status_t create_sine_port(pj_pool_t *pool,
183 unsigned sampling_rate,
184 unsigned channel_count,
185 pjmedia_port **p_port)
186{
187 pjmedia_port *port;
188 unsigned i;
189 unsigned count;
190 pj_str_t port_name;
191 port_data *sine;
192
193 PJ_ASSERT_RETURN(pool && channel_count > 0 && channel_count <= 2,
194 PJ_EINVAL);
195
196 port = pj_pool_zalloc(pool, sizeof(pjmedia_port));
197 PJ_ASSERT_RETURN(port != NULL, PJ_ENOMEM);
198
199 /* Fill in port info. */
200 port_name = pj_str("sine generator");
201 pjmedia_port_info_init(&port->info, &port_name,
202 12345, sampling_rate, channel_count, 16,
203 sampling_rate * SINE_PTIME / 1000 * channel_count);
204
205 /* Set the function to feed frame */
206 port->get_frame = &sine_get_frame;
207
208 /* Create sine port data */
209 port->port_data.pdata = sine = pj_pool_zalloc(pool, sizeof(port_data));
210
211 /* Create samples */
212 count = PJMEDIA_PIA_SPF(&port->info) / channel_count;
213 sine->samples = pj_pool_alloc(pool, count * sizeof(pj_int16_t));
214 PJ_ASSERT_RETURN(sine->samples != NULL, PJ_ENOMEM);
215
216 /* initialise sinusoidal wavetable */
217 for( i=0; i<count; i++ )
218 {
219 sine->samples[i] = (pj_int16_t) (10000.0 *
220 sin(((double)i/(double)count) * M_PI * 8.) );
221 }
222
223 *p_port = port;
224
225 return PJ_SUCCESS;
226}
227
228int main()
229{
231 pjmedia_endpt *med_endpt;
232 pj_pool_t *pool;
233 pjmedia_conf *conf;
234 int i;
235 pjmedia_port *sine_port[SINE_COUNT], *null_port, *conf_port;
236 pjmedia_port *nulls[NULL_COUNT];
237 unsigned null_slots[NULL_COUNT];
238 pjmedia_master_port *master_port;
239 pj_status_t status;
240
241
243
244 status = pj_init();
245 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
246
248 pool = pj_pool_create( &cp.factory, /* pool factory */
249 "wav", /* pool name. */
250 4000, /* init size */
251 4000, /* increment size */
252 NULL /* callback on error */
253 );
254
255 status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
256 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
257
258
259
260 status = pjmedia_conf_create( pool,
261 PORT_COUNT,
262 CLOCK_RATE,
263 1, SAMPLES_PER_FRAME, 16,
265 &conf);
266 if (status != PJ_SUCCESS) {
267 app_perror(THIS_FILE, "Unable to create conference bridge", status);
268 return 1;
269 }
270
271 printf("Resampling is %s\n", (HAS_RESAMPLE?"active":"disabled"));
272
273 /* Create Null ports */
274 printf("Creating %d null ports..\n", NULL_COUNT);
275 for (i=0; i<NULL_COUNT; ++i) {
276 status = pjmedia_null_port_create(pool, CLOCK_RATE, 1, SAMPLES_PER_FRAME*2, 16, &nulls[i]);
277 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
278
279 status = pjmedia_conf_add_port(conf, pool, nulls[i], NULL, &null_slots[i]);
280 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
281 }
282
283 /* Create sine ports. */
284 printf("Creating %d sine generator ports..\n", SINE_COUNT);
285 for (i=0; i<SINE_COUNT; ++i) {
286 unsigned j, slot;
287
288 /* Load the WAV file to file port. */
289 status = create_sine_port(pool, SINE_CLOCK, 1, &sine_port[i]);
290 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
291
292 /* Add the file port to conference bridge */
293 status = pjmedia_conf_add_port( conf, /* The bridge */
294 pool, /* pool */
295 sine_port[i], /* port to connect */
296 NULL, /* Use port's name */
297 &slot /* ptr for slot # */
298 );
299 if (status != PJ_SUCCESS) {
300 app_perror(THIS_FILE, "Unable to add conference port", status);
301 return 1;
302 }
303
304 status = pjmedia_conf_connect_port(conf, slot, 0, 0);
305 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
306
307 for (j=0; j<NULL_COUNT; ++j) {
308 status = pjmedia_conf_connect_port(conf, slot, null_slots[j], 0);
309 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
310 }
311 }
312
313 /* Create idle ports */
314 printf("Creating %d idle ports..\n", IDLE_COUNT);
315 for (i=0; i<IDLE_COUNT; ++i) {
316 pjmedia_port *dummy;
317 status = pjmedia_null_port_create(pool, CLOCK_RATE, 1, SAMPLES_PER_FRAME, 16, &dummy);
318 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
319 status = pjmedia_conf_add_port(conf, pool, dummy, NULL, NULL);
320 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
321 }
322
323 /* Create null port */
324 status = pjmedia_null_port_create(pool, CLOCK_RATE, 1, SAMPLES_PER_FRAME, 16,
325 &null_port);
326 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
327
328 conf_port = pjmedia_conf_get_master_port(conf);
329
330 /* Create master port */
331 status = pjmedia_master_port_create(pool, null_port, conf_port, 0, &master_port);
332
333
334 pjmedia_master_port_start(master_port);
335
336 puts("Waiting to settle.."); fflush(stdout);
337 pj_thread_sleep(5000);
338
339
340 benchmark();
341
342
343 /* Done. */
344 return 0;
345}
346
347
pj_status_t pjmedia_conf_connect_port(pjmedia_conf *conf, unsigned src_slot, unsigned sink_slot, int adj_level)
struct pjmedia_conf pjmedia_conf
Definition: conference.h:67
pj_status_t pjmedia_conf_add_port(pjmedia_conf *conf, pj_pool_t *pool, pjmedia_port *strm_port, const pj_str_t *name, unsigned *p_slot)
pj_status_t pjmedia_conf_create(pj_pool_t *pool, unsigned max_slots, unsigned sampling_rate, unsigned channel_count, unsigned samples_per_frame, unsigned bits_per_sample, unsigned options, pjmedia_conf **p_conf)
pjmedia_port * pjmedia_conf_get_master_port(pjmedia_conf *conf)
@ PJMEDIA_CONF_NO_DEVICE
Definition: conference.h:101
@ PJMEDIA_FRAME_TYPE_AUDIO
Definition: frame.h:45
struct pjmedia_master_port pjmedia_master_port
Definition: master_port.h:65
pj_status_t pjmedia_master_port_create(pj_pool_t *pool, pjmedia_port *u_port, pjmedia_port *d_port, unsigned options, pjmedia_master_port **p_m)
pj_status_t pjmedia_master_port_start(pjmedia_master_port *m)
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)
unsigned PJMEDIA_PIA_SPF(const pjmedia_port_info *pia)
Definition: port.h:311
unsigned PJMEDIA_PIA_CCNT(const pjmedia_port_info *pia)
Definition: port.h:270
pj_status_t pjmedia_port_info_init(pjmedia_port_info *info, const pj_str_t *name, unsigned signature, unsigned clock_rate, unsigned channel_count, unsigned bits_per_sample, unsigned samples_per_frame)
struct pjmedia_endpt pjmedia_endpt
Definition: pjmedia/types.h:186
pj_status_t pjmedia_endpt_create(pj_pool_factory *pf, pj_ioqueue_t *ioqueue, unsigned worker_cnt, pjmedia_endpt **p_endpt)
Definition: endpoint.h:127
pj_status_t pj_init(void)
short pj_int16_t
size_t pj_size_t
int pj_status_t
PJ_SUCCESS
void pj_caching_pool_init(pj_caching_pool *ch_pool, const pj_pool_factory_policy *policy, pj_size_t max_capacity)
#define PJ_LOG(level, arg)
void pj_log_set_level(int level)
pj_pool_factory_policy pj_pool_factory_default_policy
void * pj_pool_alloc(pj_pool_t *pool, pj_size_t size)
pj_pool_t * pj_pool_create(pj_pool_factory *factory, const char *name, pj_size_t initial_size, pj_size_t increment_size, pj_pool_callback *callback)
void * pj_pool_zalloc(pj_pool_t *pool, pj_size_t size)
void * pj_memcpy(void *dst, const void *src, pj_size_t size)
pj_str_t pj_str(char *str)
pj_status_t pj_thread_sleep(unsigned msec)
#define PJ_ASSERT_RETURN(expr, retval)
#define PJ_ERR_MSG_SIZE
pj_str_t pj_strerror(pj_status_t statcode, char *buf, pj_size_t bufsize)
PJMEDIA main header file.
Definition: confbench.c:83
pj_pool_factory factory
Definition: frame.h:56
pjmedia_frame_type type
Definition: frame.h:57
void * buf
Definition: frame.h:58
pj_size_t size
Definition: frame.h:59
void * pdata
Definition: port.h:385
Definition: port.h:378
pjmedia_port_info info
Definition: port.h:379
pj_status_t(* get_frame)(struct pjmedia_port *this_port, pjmedia_frame *frame)
Definition: port.h:415
Definition: confbench.c:135

 


PJMEDIA small footprint Open Source media stack
Copyright (C) 2006-2008 Teluu Inc.