📄 streamutil.c
字号:
pjmedia_codec_mgr_get_codec_info( pjmedia_endpt_get_codec_mgr(med_endpt),
0, &codec_info);
}
/* Create stream based on program arguments */
status = create_stream(pool, med_endpt, codec_info, dir, local_port,
&remote_addr, &stream);
if (status != PJ_SUCCESS)
goto on_exit;
/* Get the port interface of the stream */
status = pjmedia_stream_get_port( stream, &stream_port);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
if (play_file) {
unsigned wav_ptime;
wav_ptime = stream_port->info.samples_per_frame * 1000 /
stream_port->info.clock_rate;
status = pjmedia_wav_player_port_create(pool, play_file, wav_ptime,
0, -1, &play_file_port);
if (status != PJ_SUCCESS) {
app_perror(THIS_FILE, "Unable to use file", status);
goto on_exit;
}
status = pjmedia_master_port_create(pool, play_file_port, stream_port,
0, &master_port);
if (status != PJ_SUCCESS) {
app_perror(THIS_FILE, "Unable to create master port", status);
goto on_exit;
}
status = pjmedia_master_port_start(master_port);
if (status != PJ_SUCCESS) {
app_perror(THIS_FILE, "Error starting master port", status);
goto on_exit;
}
printf("Playing from WAV file %s..\n", play_file);
} else if (rec_file) {
status = pjmedia_wav_writer_port_create(pool, rec_file,
stream_port->info.clock_rate,
stream_port->info.channel_count,
stream_port->info.samples_per_frame,
stream_port->info.bits_per_sample,
0, 0, &rec_file_port);
if (status != PJ_SUCCESS) {
app_perror(THIS_FILE, "Unable to use file", status);
goto on_exit;
}
status = pjmedia_master_port_create(pool, stream_port, rec_file_port,
0, &master_port);
if (status != PJ_SUCCESS) {
app_perror(THIS_FILE, "Unable to create master port", status);
goto on_exit;
}
status = pjmedia_master_port_start(master_port);
if (status != PJ_SUCCESS) {
app_perror(THIS_FILE, "Error starting master port", status);
goto on_exit;
}
printf("Recording to WAV file %s..\n", rec_file);
} else {
/* Create sound device port. */
if (dir == PJMEDIA_DIR_ENCODING_DECODING)
status = pjmedia_snd_port_create(pool, -1, -1,
stream_port->info.clock_rate,
stream_port->info.channel_count,
stream_port->info.samples_per_frame,
stream_port->info.bits_per_sample,
0, &snd_port);
else if (dir == PJMEDIA_DIR_ENCODING)
status = pjmedia_snd_port_create_rec(pool, -1,
stream_port->info.clock_rate,
stream_port->info.channel_count,
stream_port->info.samples_per_frame,
stream_port->info.bits_per_sample,
0, &snd_port);
else
status = pjmedia_snd_port_create_player(pool, -1,
stream_port->info.clock_rate,
stream_port->info.channel_count,
stream_port->info.samples_per_frame,
stream_port->info.bits_per_sample,
0, &snd_port);
if (status != PJ_SUCCESS) {
app_perror(THIS_FILE, "Unable to create sound port", status);
goto on_exit;
}
/* Connect sound port to stream */
status = pjmedia_snd_port_connect( snd_port, stream_port );
PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
}
/* Start streaming */
pjmedia_stream_start(stream);
/* Done */
if (dir == PJMEDIA_DIR_DECODING)
printf("Stream is active, dir is recv-only, local port is %d\n",
local_port);
else if (dir == PJMEDIA_DIR_ENCODING)
printf("Stream is active, dir is send-only, sending to %s:%d\n",
pj_inet_ntoa(remote_addr.sin_addr),
pj_ntohs(remote_addr.sin_port));
else
printf("Stream is active, send/recv, local port is %d, "
"sending to %s:%d\n",
local_port,
pj_inet_ntoa(remote_addr.sin_addr),
pj_ntohs(remote_addr.sin_port));
for (;;) {
puts("");
puts("Commands:");
puts(" s Display media statistics");
puts(" q Quit");
puts("");
printf("Command: "); fflush(stdout);
fgets(tmp, sizeof(tmp), stdin);
if (tmp[0] == 's')
print_stream_stat(stream);
else if (tmp[0] == 'q')
break;
}
/* Start deinitialization: */
on_exit:
/* Destroy sound device */
if (snd_port) {
pjmedia_snd_port_destroy( snd_port );
PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
}
/* If there is master port, then we just need to destroy master port
* (it will recursively destroy upstream and downstream ports, which
* in this case are file_port and stream_port).
*/
if (master_port) {
pjmedia_master_port_destroy(master_port, PJ_TRUE);
play_file_port = NULL;
stream = NULL;
}
/* Destroy stream */
if (stream) {
pjmedia_transport *tp;
tp = pjmedia_stream_get_transport(stream);
pjmedia_stream_destroy(stream);
pjmedia_transport_udp_close(tp);
}
/* Destroy file ports */
if (play_file_port)
pjmedia_port_destroy( play_file_port );
if (rec_file_port)
pjmedia_port_destroy( rec_file_port );
/* 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();
return (status == PJ_SUCCESS) ? 0 : 1;
}
static const char *good_number(char *buf, pj_int32_t val)
{
if (val < 1000) {
pj_ansi_sprintf(buf, "%d", val);
} else if (val < 1000000) {
pj_ansi_sprintf(buf, "%d.%dK",
val / 1000,
(val % 1000) / 100);
} else {
pj_ansi_sprintf(buf, "%d.%02dM",
val / 1000000,
(val % 1000000) / 10000);
}
return buf;
}
/*
* Print stream statistics
*/
static void print_stream_stat(pjmedia_stream *stream)
{
char duration[80], last_update[80];
char bps[16], ipbps[16], packets[16], bytes[16], ipbytes[16];
pjmedia_port *port;
pjmedia_rtcp_stat stat;
pj_time_val now;
pj_gettimeofday(&now);
pjmedia_stream_get_stat(stream, &stat);
pjmedia_stream_get_port(stream, &port);
puts("Stream statistics:");
/* Print duration */
PJ_TIME_VAL_SUB(now, stat.start);
sprintf(duration, " Duration: %02ld:%02ld:%02ld.%03ld",
now.sec / 3600,
(now.sec % 3600) / 60,
(now.sec % 60),
now.msec);
printf(" Info: audio %.*s@%dHz, %dms/frame, %sB/s (%sB/s +IP hdr)\n",
(int)port->info.encoding_name.slen,
port->info.encoding_name.ptr,
port->info.clock_rate,
port->info.samples_per_frame * 1000 / port->info.clock_rate,
good_number(bps, port->info.bytes_per_frame * port->info.clock_rate /
port->info.samples_per_frame),
good_number(ipbps, (port->info.bytes_per_frame+32) *
port->info.clock_rate / port->info.clock_rate));
if (stat.rx.update_cnt == 0)
strcpy(last_update, "never");
else {
pj_gettimeofday(&now);
PJ_TIME_VAL_SUB(now, stat.rx.update);
sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago",
now.sec / 3600,
(now.sec % 3600) / 60,
now.sec % 60,
now.msec);
}
printf(" RX stat last update: %s\n"
" total %s packets %sB received (%sB +IP hdr)%s\n"
" pkt loss=%d (%3.1f%%), dup=%d (%3.1f%%), reorder=%d (%3.1f%%)%s\n"
" (msec) min avg max last\n"
" loss period: %7.3f %7.3f %7.3f %7.3f%s\n"
" jitter : %7.3f %7.3f %7.3f %7.3f%s\n",
last_update,
good_number(packets, stat.rx.pkt),
good_number(bytes, stat.rx.bytes),
good_number(ipbytes, stat.rx.bytes + stat.rx.pkt * 32),
"",
stat.rx.loss,
stat.rx.loss * 100.0 / (stat.rx.pkt + stat.rx.loss),
stat.rx.dup,
stat.rx.dup * 100.0 / (stat.rx.pkt + stat.rx.loss),
stat.rx.reorder,
stat.rx.reorder * 100.0 / (stat.rx.pkt + stat.rx.loss),
"",
stat.rx.loss_period.min / 1000.0,
stat.rx.loss_period.avg / 1000.0,
stat.rx.loss_period.max / 1000.0,
stat.rx.loss_period.last / 1000.0,
"",
stat.rx.jitter.min / 1000.0,
stat.rx.jitter.avg / 1000.0,
stat.rx.jitter.max / 1000.0,
stat.rx.jitter.last / 1000.0,
""
);
if (stat.tx.update_cnt == 0)
strcpy(last_update, "never");
else {
pj_gettimeofday(&now);
PJ_TIME_VAL_SUB(now, stat.tx.update);
sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago",
now.sec / 3600,
(now.sec % 3600) / 60,
now.sec % 60,
now.msec);
}
printf(" TX stat last update: %s\n"
" total %s packets %sB sent (%sB +IP hdr)%s\n"
" pkt loss=%d (%3.1f%%), dup=%d (%3.1f%%), reorder=%d (%3.1f%%)%s\n"
" (msec) min avg max last\n"
" loss period: %7.3f %7.3f %7.3f %7.3f%s\n"
" jitter : %7.3f %7.3f %7.3f %7.3f%s\n",
last_update,
good_number(packets, stat.tx.pkt),
good_number(bytes, stat.tx.bytes),
good_number(ipbytes, stat.tx.bytes + stat.tx.pkt * 32),
"",
stat.tx.loss,
stat.tx.loss * 100.0 / (stat.tx.pkt + stat.tx.loss),
stat.tx.dup,
stat.tx.dup * 100.0 / (stat.tx.pkt + stat.tx.loss),
stat.tx.reorder,
stat.tx.reorder * 100.0 / (stat.tx.pkt + stat.tx.loss),
"",
stat.tx.loss_period.min / 1000.0,
stat.tx.loss_period.avg / 1000.0,
stat.tx.loss_period.max / 1000.0,
stat.tx.loss_period.last / 1000.0,
"",
stat.tx.jitter.min / 1000.0,
stat.tx.jitter.avg / 1000.0,
stat.tx.jitter.max / 1000.0,
stat.tx.jitter.last / 1000.0,
""
);
printf(" RTT delay : %7.3f %7.3f %7.3f %7.3f%s\n",
stat.rtt.min / 1000.0,
stat.rtt.avg / 1000.0,
stat.rtt.max / 1000.0,
stat.rtt.last / 1000.0,
""
);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -