/* * main() */ int main(int argc, char *argv[]) { pj_caching_pool cp; pjmedia_endpt *med_endpt; pj_pool_t *pool; pjmedia_port *wav_play; pjmedia_port *wav_rec; pjmedia_port *wav_out; pj_status_t status; pjmedia_echo_state *ec; pjmedia_frame play_frame, rec_frame; unsigned opt = 0; unsigned latency_ms = 25; unsigned tail_ms = TAIL_LENGTH; pj_timestamp t0, t1; int i, repeat=1, interactive=0, c; pj_optind = 0; while ((c=pj_getopt(argc, argv, "d:l:a:r:i")) !=-1) { switch (c) { case 'd': latency_ms = atoi(pj_optarg); if (latency_ms < 25) { puts("Invalid delay"); puts(desc); } break; case 'l': tail_ms = atoi(pj_optarg); break; case 'a': { int alg = atoi(pj_optarg); switch (alg) { case 0: opt = 0; case 1: opt = PJMEDIA_ECHO_SPEEX; break; case 3: opt = PJMEDIA_ECHO_SIMPLE; break; default: puts("Invalid algorithm"); puts(desc); return 1; } } break; case 'r': repeat = atoi(pj_optarg); if (repeat < 1) { puts("Invalid repeat count"); puts(desc); return 1; } break; case 'i': interactive = 1; break; } } if (argc - pj_optind != 3) { puts("Error: missing argument(s)"); 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 */ ); /* Open wav_play */ status = pjmedia_wav_player_port_create(pool, argv[pj_optind], PTIME, PJMEDIA_FILE_NO_LOOP, 0, &wav_play); if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "Error opening playback WAV file", status); return 1; } /* Open recorded wav */ status = pjmedia_wav_player_port_create(pool, argv[pj_optind+1], PTIME, PJMEDIA_FILE_NO_LOOP, 0, &wav_rec); if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "Error opening recorded WAV file", status); return 1; } /* play and rec WAVs must have the same clock rate */ if (wav_play->info.clock_rate != wav_rec->info.clock_rate) { puts("Error: clock rate mismatch in the WAV files"); return 1; } /* .. and channel count */ if (wav_play->info.channel_count != wav_rec->info.channel_count) { puts("Error: clock rate mismatch in the WAV files"); return 1; } /* Create output wav */ status = pjmedia_wav_writer_port_create(pool, argv[pj_optind+2], wav_play->info.clock_rate, wav_play->info.channel_count, wav_play->info.samples_per_frame, wav_play->info.bits_per_sample, 0, 0, &wav_out); if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "Error opening output WAV file", status); return 1; } /* Create echo canceller */ status = pjmedia_echo_create2(pool, wav_play->info.clock_rate, wav_play->info.channel_count, wav_play->info.samples_per_frame, tail_ms, latency_ms, opt, &ec); if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "Error creating EC", status); return 1; } /* Processing loop */ play_frame.buf = pj_pool_alloc(pool, wav_play->info.samples_per_frame<<1); rec_frame.buf = pj_pool_alloc(pool, wav_play->info.samples_per_frame<<1); pj_get_timestamp(&t0); for (i=0; i < repeat; ++i) { for (;;) { play_frame.size = wav_play->info.samples_per_frame << 1; status = pjmedia_port_get_frame(wav_play, &play_frame); if (status != PJ_SUCCESS) break; status = pjmedia_echo_playback(ec, (short*)play_frame.buf); rec_frame.size = wav_play->info.samples_per_frame << 1; status = pjmedia_port_get_frame(wav_rec, &rec_frame); if (status != PJ_SUCCESS) break; status = pjmedia_echo_capture(ec, (short*)rec_frame.buf, 0); //status = pjmedia_echo_cancel(ec, (short*)rec_frame.buf, // (short*)play_frame.buf, 0, NULL); pjmedia_port_put_frame(wav_out, &rec_frame); } pjmedia_wav_player_port_set_pos(wav_play, 0); pjmedia_wav_player_port_set_pos(wav_rec, 0); } pj_get_timestamp(&t1); i = pjmedia_wav_writer_port_get_pos(wav_out) / sizeof(pj_int16_t) * 1000 / (wav_out->info.clock_rate * wav_out->info.channel_count); PJ_LOG(3,(THIS_FILE, "Processed %3d.%03ds audio", i / 1000, i % 1000)); PJ_LOG(3,(THIS_FILE, "Completed in %u msec\n", pj_elapsed_msec(&t0, &t1))); /* Destroy file port(s) */ status = pjmedia_port_destroy( wav_play ); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); status = pjmedia_port_destroy( wav_rec ); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); status = pjmedia_port_destroy( wav_out ); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); /* Destroy ec */ pjmedia_echo_destroy(ec); /* 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(); if (interactive) { char s[10], *dummy; puts("ENTER to quit"); dummy = fgets(s, sizeof(s), stdin); } /* Done. */ return 0; }
/* * main() * */ int main(int argc, char *argv[]) { pj_caching_pool cp; pj_pool_t *pool = NULL; pjsip_module mod_app = { NULL, NULL, /* prev, next. */ { "mod-app", 7 }, /* Name. */ -1, /* Id */ PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */ NULL, /* load() */ NULL, /* start() */ NULL, /* stop() */ NULL, /* unload() */ &on_rx_request, /* on_rx_request() */ NULL, /* on_rx_response() */ NULL, /* on_tx_request. */ NULL, /* on_tx_response() */ NULL, /* on_tsx_state() */ }; int c; pj_status_t status; /* Must init PJLIB first: */ status = pj_init(); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); /* Then init PJLIB-UTIL: */ status = pjlib_util_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); /* Create global endpoint: */ { /* Endpoint MUST be assigned a globally unique name. * Ideally we should put hostname or public IP address, but * we'll just use an arbitrary name here. */ /* Create the endpoint: */ status = pjsip_endpt_create(&cp.factory, "sipstateless", &sip_endpt); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); } /* Parse arguments */ pj_optind = 0; pj_list_init(&hdr_list); while ((c=pj_getopt(argc, argv , "H:")) != -1) { switch (c) { case 'H': if (pool == NULL) { pool = pj_pool_create(&cp.factory, "sipstateless", 1000, 1000, NULL); } if (pool) { char *name; name = strtok(pj_optarg, ":"); if (name == NULL) { puts("Error: invalid header format"); return 1; } else { char *val = strtok(NULL, "\r\n"); pjsip_generic_string_hdr *h; pj_str_t hname, hvalue; hname = pj_str(name); hvalue = pj_str(val); h = pjsip_generic_string_hdr_create(pool, &hname, &hvalue); pj_list_push_back(&hdr_list, h); PJ_LOG(4,(THIS_FILE, "Header %s: %s added", name, val)); } } break; default: puts("Error: invalid argument"); usage(); return 1; } } if (pj_optind != argc) { code = atoi(argv[pj_optind]); if (code < 200 || code > 699) { puts("Error: invalid status code"); usage(); return 1; } } PJ_LOG(4,(THIS_FILE, "Returning %d to incoming requests", code)); /* * Add UDP transport, with hard-coded port */ #ifdef HAS_UDP_TRANSPORT { pj_sockaddr_in addr; addr.sin_family = pj_AF_INET(); addr.sin_addr.s_addr = 0; addr.sin_port = pj_htons(5060); status = pjsip_udp_transport_start( sip_endpt, &addr, NULL, 1, NULL); if (status != PJ_SUCCESS) { PJ_LOG(3,(THIS_FILE, "Error starting UDP transport (port in use?)")); return 1; } } #endif #if HAS_TCP_TRANSPORT /* * Add UDP transport, with hard-coded port */ { pj_sockaddr_in addr; addr.sin_family = pj_AF_INET(); addr.sin_addr.s_addr = 0; addr.sin_port = pj_htons(5060); status = pjsip_tcp_transport_start(sip_endpt, &addr, 1, NULL); if (status != PJ_SUCCESS) { PJ_LOG(3,(THIS_FILE, "Error starting TCP transport (port in use?)")); return 1; } } #endif /* * Register our module to receive incoming requests. */ status = pjsip_endpt_register_module( sip_endpt, &mod_app); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); /* Done. Loop forever to handle incoming events. */ PJ_LOG(3,(THIS_FILE, "Press Ctrl-C to quit..")); for (;;) { pjsip_endpt_handle_events(sip_endpt, NULL); } }