audio_tool.c
来自「基于sip协议的网络电话源码」· C语言 代码 · 共 410 行
C
410 行
/* $Id$ *//* * Copyright (C) 2003-2007 Benny Prijono <benny@prijono.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <pjmedia.h>#include <pjlib.h>#include <stdio.h>#define THIS_FILE "audio_tool.c"static pj_caching_pool caching_pool;static pj_pool_factory *pf;static FILE *fhnd;static pj_med_mgr_t *mm;static pjmedia_codec *codec;static pjmedia_codec_param cattr;#define WRITE_ORIGINAL_PCM 0#if WRITE_ORIGINAL_PCMstatic FILE *fhnd_pcm;#endifstatic char talker_sdp[] = "v=0\r\n" "o=- 0 0 IN IP4 127.0.0.1\r\n" "s=-\r\n" "c=IN IP4 127.0.0.1\r\n" "t=0 0\r\n" "m=audio 4002 RTP/AVP 0\r\n" "a=rtpmap:0 PCMU/8000\r\n" "a=sendonly\r\n";static char listener_sdp[] = "v=0\r\n" "o=- 0 0 IN IP4 127.0.0.1\r\n" "s=-\r\n" "c=IN IP4 127.0.0.1\r\n" "t=0 0\r\n" "m=audio 4000 RTP/AVP 0\r\n" "a=rtpmap:0 PCMU/8000\r\n" "a=recvonly\r\n";static pj_status_t play_callback(/* in */ void *user_data, /* in */ pj_uint32_t timestamp, /* out */ void *frame, /* out */ unsigned size){ char pkt[160]; struct pjmedia_frame in, out; int frmsz = cattr.avg_bps / 8 * cattr.ptime / 1000; if (fread(pkt, frmsz, 1, fhnd) != 1) { puts("EOF"); return -1; } else { in.type = PJMEDIA_FRAME_TYPE_AUDIO; in.buf = pkt; in.size = frmsz; out.buf = frame; if (codec->op->decode (codec, &in, size, &out) != 0) return -1; size = out.size; return 0; }}static pj_status_t rec_callback( /* in */ void *user_data, /* in */ pj_uint32_t timestamp, /* in */ const void *frame, /* in*/ unsigned size){ char pkt[160]; struct pjmedia_frame in, out; //int frmsz = cattr.avg_bps / 8 * cattr.ptime / 1000;#if WRITE_ORIGINAL_PCM fwrite(frame, size, 1, fhnd_pcm);#endif in.type = PJMEDIA_FRAME_TYPE_AUDIO; in.buf = (void*)frame; in.size = size; out.buf = pkt; if (codec->op->encode(codec, &in, sizeof(pkt), &out) != 0) return -1; if (fwrite(pkt, out.size, 1, fhnd) != 1) return -1; return 0;}static pj_status_t init(){ pjmedia_codec_mgr *cm; pjmedia_codec_info id; int i; pj_caching_pool_init(&caching_pool, &pj_pool_factory_default_policy, 0); pf = &caching_pool.factory; if (pj_snd_init(&caching_pool.factory)) return -1; PJ_LOG(3,(THIS_FILE, "Dumping audio devices:")); for (i=0; i<pj_snd_get_dev_count(); ++i) { const pj_snd_dev_info *info; info = pj_snd_get_dev_info(i); PJ_LOG(3,(THIS_FILE, " %d: %s\t(%d in, %d out", i, info->name, info->input_count, info->output_count)); } mm = pj_med_mgr_create (&caching_pool.factory); cm = pj_med_mgr_get_codec_mgr (mm); id.type = PJMEDIA_TYPE_AUDIO; id.pt = 0; id.encoding_name = pj_str("PCMU"); id.sample_rate = 8000; codec = pjmedia_codec_mgr_alloc_codec (cm, &id); codec->op->default_attr(codec, &cattr); codec->op->open(codec, &cattr); return 0;}static pj_status_t deinit(){ pjmedia_codec_mgr *cm; cm = pj_med_mgr_get_codec_mgr (mm); codec->op->close(codec); pjmedia_codec_mgr_dealloc_codec (cm, codec); pj_med_mgr_destroy (mm); pj_caching_pool_destroy(&caching_pool); return 0;}static pj_status_t record_file (const char *filename){ pj_snd_stream *stream; pj_snd_stream_info info; int status; char s[10]; printf("Recording to file %s...\n", filename); fhnd = fopen(filename, "wb"); if (!fhnd) return -1;#if WRITE_ORIGINAL_PCM fhnd_pcm = fopen("ORIGINAL.PCM", "wb"); if (!fhnd_pcm) return -1;#endif pj_bzero(&info, sizeof(info)); info.bits_per_sample = 16; info.bytes_per_frame = 2; info.frames_per_packet = 160; info.samples_per_frame = 1; info.samples_per_sec = 8000; stream = pj_snd_open_recorder(-1, &info, &rec_callback, NULL); if (!stream) return -1; status = pj_snd_stream_start(stream); if (status != 0) goto on_error; puts("Press <ENTER> to exit recording"); fgets(s, sizeof(s), stdin); pj_snd_stream_stop(stream); pj_snd_stream_close(stream);#if WRITE_ORIGINAL_PCM fclose(fhnd_pcm);#endif fclose(fhnd); return 0;on_error: pj_snd_stream_stop(stream); pj_snd_stream_close(stream); return -1;}static pj_status_t play_file (const char *filename){ pj_snd_stream *stream; pj_snd_stream_info info; int status; char s[10]; printf("Playing file %s...\n", filename); fhnd = fopen(filename, "rb"); if (!fhnd) return -1; pj_bzero(&info, sizeof(info)); info.bits_per_sample = 16; info.bytes_per_frame = 2; info.frames_per_packet = 160; info.samples_per_frame = 1; info.samples_per_sec = 8000; stream = pj_snd_open_player(-1, &info, &play_callback, NULL); if (!stream) return -1; status = pj_snd_stream_start(stream); if (status != 0) goto on_error; puts("Press <ENTER> to exit playing"); fgets(s, sizeof(s), stdin); pj_snd_stream_stop(stream); pj_snd_stream_close(stream); fclose(fhnd); return 0;on_error: pj_snd_stream_stop(stream); pj_snd_stream_close(stream); return -1;}static int create_ses_by_remote_sdp(int local_port, char *sdp){ pj_media_session_t *ses = NULL; pjsdp_session_desc *sdp_ses; pj_media_sock_info skinfo; pj_pool_t *pool; char s[4]; const pj_media_stream_info *info[2]; int i, count; pool = pj_pool_create(pf, "sdp", 1024, 0, NULL); if (!pool) { PJ_LOG(1,(THIS_FILE, "Unable to create pool")); return -1; } pj_bzero(&skinfo, sizeof(skinfo)); skinfo.rtp_sock = skinfo.rtcp_sock = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, 0); if (skinfo.rtp_sock == PJ_INVALID_SOCKET) { PJ_LOG(1,(THIS_FILE, "Unable to create socket")); goto on_error; } pj_sockaddr_init2(&skinfo.rtp_addr_name, "0.0.0.0", local_port); if (pj_sock_bind(skinfo.rtp_sock, (struct pj_sockaddr*)&skinfo.rtp_addr_name, sizeof(pj_sockaddr_in)) != 0) { PJ_LOG(1,(THIS_FILE, "Unable to bind socket")); goto on_error; } sdp_ses = pjsdp_parse(sdp, strlen(sdp), pool); if (!sdp_ses) { PJ_LOG(1,(THIS_FILE, "Error parsing SDP")); goto on_error; } ses = pj_media_session_create_from_sdp(mm, sdp_ses, &skinfo); if (!ses) { PJ_LOG(1,(THIS_FILE, "Unable to create session from SDP")); goto on_error; } if (pj_media_session_activate(ses) != 0) { PJ_LOG(1,(THIS_FILE, "Error activating session")); goto on_error; } count = pj_media_session_enum_streams(ses, 2, info); printf("\nDumping streams: \n"); for (i=0; i<count; ++i) { const char *dir; char *local_ip; switch (info[i]->dir) { case PJMEDIA_DIR_NONE: dir = "- NONE -"; break; case PJMEDIA_DIR_ENCODING: dir = "SENDONLY"; break; case PJMEDIA_DIR_DECODING: dir = "RECVONLY"; break; case PJMEDIA_DIR_ENCODING_DECODING: dir = "SENDRECV"; break; default: dir = "?UNKNOWN"; break; } local_ip = pj_sockaddr_get_str_addr(&info[i]->sock_info.rtp_addr_name); printf(" Stream %d: %.*s %s local=%s:%d remote=%.*s:%d\n", i, info[i]->type.slen, info[i]->type.ptr, dir, local_ip, pj_sockaddr_get_port(&info[i]->sock_info.rtp_addr_name), info[i]->rem_addr.slen, info[i]->rem_addr.ptr, info[i]->rem_port); } puts("Press <ENTER> to quit"); fgets(s, sizeof(s), stdin); pj_media_session_destroy(ses); pj_sock_close(skinfo.rtp_sock); pj_pool_release(pool); return 0;on_error: if (ses) pj_media_session_destroy(ses); if (skinfo.rtp_sock != PJ_INVALID_SOCKET) pj_sock_close(skinfo.rtp_sock); if (pool) pj_pool_release(pool); return -1;}#if WRITE_ORIGINAL_PCMstatic pj_status_t convert(const char *src, const char *dst){ char pcm[320]; char frame[160]; struct pjmedia_frame in, out; fhnd_pcm = fopen(src, "rb"); if (!fhnd_pcm) return -1; fhnd = fopen(dst, "wb"); if (!fhnd) return -1; while (fread(pcm, 320, 1, fhnd_pcm) == 1) { in.type = PJMEDIA_FRAME_TYPE_AUDIO; in.buf = pcm; in.size = 320; out.buf = frame; if (codec->op->encode(codec, &in, 160, &out) != 0) break; if (fwrite(frame, out.size, 1, fhnd) != 1) break; } fclose(fhnd); fclose(fhnd_pcm); return 0;}#endifstatic void usage(const char *exe){ printf("Usage: %s <command> <file>\n", exe); puts("where:"); puts(" <command> play|record|send|recv");}int main(int argc, char *argv[]){ if (argc < 2) { usage(argv[0]); return 1; } pj_init(); init(); if (stricmp(argv[1], "record")==0) { record_file("FILE.PCM"); } else if (stricmp(argv[1], "play")==0) { play_file("FILE.PCM"); } else if (stricmp(argv[1], "send")==0) { create_ses_by_remote_sdp(4002, listener_sdp); } else if (stricmp(argv[1], "recv")==0) { create_ses_by_remote_sdp(4000, talker_sdp); } else { usage(argv[0]); } deinit(); return 0;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?