PJSIP-PJMEDIA【使用pjmedia 播放wav格式的音乐】

为更好交流学习,本文介绍PJSIP中PJMEDIA的使用。首先阐述了环境搭建与调试方法,包括在工具和项目属性中加入包含文件、库文件及库名,还说明了编译报错的解决办法。此外,给出播放wav文件的实例及出处。
部署运行你感兴趣的模型镜像

应宝哥建议以及更好的交流学习,这篇开始使用中文,英语就先放一放吧!

要使用PJSIP中的PJMEDIA首先我们需要搭建好它所需要的环境。

【环境搭建与调试】

1 在 工具 加入pjmedia所需要的包含文件以及库文件

2 在 项目属性 中的加入包含文件以及库文件和具体使用到的库名

3 编译过程中出现无法解析外部符号时,自习观察报错的提示,(如关键字可能为srtp,可以去工程文件下的third_party中去添加相关库或者包含文件)。

【实例功能】

播放一个wav格式的文件。

实例出处:http://www.pjsip.org/docs/latest/pjmedia/docs/html/page_pjmedia_samples_playfile_c.htm

 1 //PJMEDIA  play a wav file
 2 //heat nan 
 3 //改编自官网实例
 4 #include<pjlib.h>
 5 #include<pjlib-util.h>
 6 #include<stdlib.h>
 7 #include<pjmedia.h>
 8 #include<stdio.h>
 9 int main()
10 {
11     pj_status_t status;
12     char filename[50]="windows.wav";// the file's name which you are want to play
13     pj_caching_pool cp;
14     pjmedia_endpt *med_endpt;
15     pj_pool_t *pool;
16     pjmedia_port *file_port;
17     pjmedia_snd_port *snd_port;
18     int i;
19     //if you want to use the pjlib lib, you must init it first
20     status=pj_init();
21     if(status==PJ_SUCCESS)
22     {
23         printf("pj_init success!\n");
24     }
25     //在我们分配内存前需要首先建立一个pool factory
26     pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
27     
28     //创建一个媒体实例的endpoint
29     status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
30     if(status!=PJ_SUCCESS)
31     {
32             PJ_LOG(3,("pjmedia create","failed"));
33     }
34     //为我们的文件播放器创建内存池
35     pool=pj_pool_create(&cp.factory,"wav",4000,4000,NULL);
36     //创建一个媒体端口从wav文件中播放
37     status=pjmedia_wav_player_port_create(pool,&filename,20,0,0,&file_port);
38     if(status!=PJ_SUCCESS)
39     {
40         PJ_LOG(3,("pjmedia port","Unable to use WAV file"));
41     }
42     //创建一个单向的音频设备端口来播放制定参数相关的音频流
43     status=pjmedia_snd_port_create_player(pool,-1,PJMEDIA_PIA_SRATE(&file_port->info),PJMEDIA_PIA_CCNT(&file_port->info), PJMEDIA_PIA_SPF(&file_port->info), PJMEDIA_PIA_BITS(&file_port->info),0, &snd_port);
44     if(status!=PJ_SUCCESS)
45     {
46         PJ_LOG(3,("pjmedia","create player failed"));
47     }
48     //连接文件端口和音频设备端口
49     status=pjmedia_snd_port_connect(snd_port,file_port);
50     if(status!=PJ_SUCCESS)
51     {
52         PJ_LOG(3,("connect","failed"));
53     }
54 
55     //如果成功,音乐已经开始响起
56     /*
57     for(i=0;i<100;++i)
58     {
59          pj_int16_t framebuf[640];
60          pjmedia_frame frm;
61          pj_int32_t level32;
62          unsigned ms;
63          int level;
64 
65          frm.buf=framebuf;
66          frm.size=sizeof(framebuf);
67 
68          pjmedia_port_get_frame(file_port,&frm);
69 
70          level32=pjmedia_calc_avg_signal(framebuf,PJMEDIA_PIA_SPF(&file_port->info));
71          level=pjmedia_linear2ulaw(level32)^0xFF;
72          ms=i*1000*PJMEDIA_PIA_SPF(&file_port->info)/PJMEDIA_PIA_SRATE(&file_port->info);
73          printf("%03d.%03d\t%07d\t%7d\n",ms/1000,ms%1000,level,level32);
74     }
75 
76 */
77     //提示
78      printf("Press<ENTER>to stop the music!\n");
79     
80 getchar();
81 
82     return 0;
83 
84 
85 }

 

 

 

转载于:https://www.cnblogs.com/heat-man/p/3647416.html

您可能感兴趣的与本文相关的镜像

Anything-LLM

Anything-LLM

AI应用

AnythingLLM是一个全栈应用程序,可以使用商用或开源的LLM/嵌入器/语义向量数据库模型,帮助用户在本地或云端搭建个性化的聊天机器人系统,且无需复杂设置

已知static void on_call_state(pjsua_call_id call_id, pjsip_event *e) { pjsua_call_info call_info; /*ycw-pjsip*/ # if 0 PJ_UNUSED_ARG(e); # else # if 0 pjsip_transaction* tsx = e->body.tsx_state.tsx; # endif # endif pjsua_call_get_info(call_id, &call_info); if (call_info.state == PJSIP_INV_STATE_DISCONNECTED) { /* Stop all ringback for this call */ /*ycw-pjsip--delete conference*/ /*stop ring*/ #if 0 ring_stop(call_id); #endif /* Cancel duration timer, if any */ if (app_config.call_data[call_id].timer.id != PJSUA_INVALID_ID) { struct call_data *cd = &app_config.call_data[call_id]; pjsip_endpoint *endpt = pjsua_get_pjsip_endpt(); cd->timer.id = PJSUA_INVALID_ID; pjsip_endpt_cancel_timer(endpt, &cd->timer); } /* Rewind play file when hangup automatically, * since file is not looped */ /*ycw-pjsip--delete wave file*/ #if 0 if (app_config.auto_play_hangup) pjsua_player_set_pos(app_config.wav_id, 0); #endif PJ_LOG(3,(THIS_FILE, "Call %d is DISCONNECTED [reason=%d (%s)]", call_id, call_info.last_status, call_info.last_status_text.ptr)); #if defined(INCLUDE_ROBIN_DNS) || defined(INCLUDE_VOIP_ROBIN_DNS) /* The server block us , so we should try another server for register. */ if (call_info.last_status == PJSIP_SC_REQUEST_TIMEOUT) { pjsua_acc_try_next_ip(call_info.acc_id, 1); } #endif /* INCLUDE_ROBIN_DNS || INCLUDE_VOIP_ROBIN_DNS */ if (call_id == current_call) { find_next_call(); } FILE *fp = fopen("/proc/voip_port", "w"); if (fp) { if (fprintf(fp, "0") > 0) { } else { PJ_LOG(1, (THIS_FILE, "write fail")); } fclose(fp); } else { PJ_LOG(1, (THIS_FILE, "open /proc/voip_port fail")); } /* Dump media state upon disconnected */ if (1) { PJ_LOG(5,(THIS_FILE, "Call %d disconnected, dumping media stats..", call_id)); log_call_dump(call_id); } } else { if (app_config.duration!=NO_LIMIT && call_info.state == PJSIP_INV_STATE_CONFIRMED) { /* Schedule timer to hangup call after the specified duration */ struct call_data *cd = &app_config.call_data[call_id]; pjsip_endpoint *endpt = pjsua_get_pjsip_endpt(); pj_time_val delay; cd->timer.id = call_id; delay.sec = app_config.duration; delay.msec = 0; pjsip_endpt_schedule_timer(endpt, &cd->timer, &delay); } if (call_info.state == PJSIP_INV_STATE_EARLY) { int code; pjsip_msg *msg; /* This can only occur because of TX or RX message */ pj_assert(e->type == PJSIP_EVENT_TSX_STATE); if (e->body.tsx_state.type == PJSIP_EVENT_RX_MSG) { msg = e->body.tsx_state.src.rdata->msg_info.msg; } else { msg = e->body.tsx_state.src.tdata->msg; } code = msg->line.status.code; /* Start ringback for 180 for UAC unless there's SDP in 180 */ if (call_info.role==PJSIP_ROLE_UAC && code==180 && msg->body == NULL && call_info.media_status==PJSUA_CALL_MEDIA_NONE) { /*ycw-pjsip--delete conference bridge*/ /*begin to ring back*/ #if 0 ringback_start(call_id); #endif } PJ_LOG(3,(THIS_FILE, "Call %d state changed to %s (%d %.*s)", call_id, call_info.state_text.ptr, code, (int)msg->line.status.reason.slen, msg->line.status.reason.ptr)); } else { PJ_LOG(3,(THIS_FILE, "Call %d state changed to %s", call_id, call_info.state_text.ptr)); } if (current_call==PJSUA_INVALID_ID) current_call = call_id; } }我在挂机时会通知内核写0,那么我要在拨通或者接收发送invite时向内核通知我的接收端口号应该加在什么地方
最新发布
10-29
### 音视频功能实现指南 PJSIP 是一个开源的多媒体通信库,其核心模块 pjmedia 提供了强大的音视频处理能力。开发者可以利用 pjmedia 实现音视频采集、编码解码、传输等功能。 #### 初始化 pjmedia使用 pjmedia 之前,需要先初始化 PJSIP 核心库和 pjmedia 模块。以下是一个简单的初始化示例: ```c #include <pjsua2/pjsua2.hpp> using namespace pj; class MyEndpoint : public Endpoint { public: virtual void onRegState(OnRegStateParam &prm) { PJ_LOG(3,(__FILE__, "Registration state changed: %s", prm.evt->type)); } }; int main() { MyEndpoint ep; ep.libCreate(); // 初始化配置 EpConfig ep_cfg; ep_cfg.logConfig.level = 4; // 设置日志级别 // 启动库 ep.libInit(ep_cfg); // 创建 UDP 传输 TransportConfig tcfg; tcfg.port = 5060; ep.transportCreate(PJSIP_TRANSPORT_UDP, tcfg); // 启动库的主循环 ep.libStart(); // 主线程等待退出 cin.get(); // 清理资源 ep.libDestroy(); return 0; } ``` #### 音视频设备管理 pjmedia 支持多种音视频设备的管理和操作。可以通过 `AudioMediaPlayer` 和 `VideoPlayer` 类来实现音频和视频的播放。 ```c // 播放音频文件 AudioMediaPlayer player; player.createPlayer("test.wav"); player.startPlayer(); // 停止播放 player.stopPlayer(); player.destroyPlayer(); ``` 对于视频播放,可以使用 `VideoWindow` 来显示视频内容: ```c // 创建视频窗口 VideoWindow video_win; video_win.createWin(640, 480); // 显示视频帧 video_win.displayFrame(frame); ``` #### 编码与解码 pjmedia 提供了多种编解码器的支持,包括 G.711、G.722、H.264 等。可以通过 `CodecFactory` 获取编解码器实例,并进行编码和解码操作。 ```c // 获取编码器 Codec *encoder = CodecFactory::instance().getEncoder("G711"); // 编码音频数据 unsigned char encoded_data[1024]; int encoded_len = encoder->encode(raw_data, raw_len, encoded_data, sizeof(encoded_data)); // 获取解码器 Codec *decoder = CodecFactory::instance().getDecoder("G711"); // 解码音频数据 unsigned char decoded_data[1024]; int decoded_len = decoder->decode(encoded_data, encoded_len, decoded_data, sizeof(decoded_data)); ``` #### 网络传输 pjmedia 支持多种网络传输协议,如 RTP/RTCP。可以通过 `RtpSession` 类来管理 RTP 会话,并发送和接收音视频数据。 ```c // 创建 RTP 会话 RtpSession rtp_sess; rtp_sess.createSession(addr, port); // 发送 RTP 数据包 rtp_sess.sendPacket(data, len); // 接收 RTP 数据包 unsigned char recv_data[1500]; int recv_len = rtp_sess.recvPacket(recv_data, sizeof(recv_data)); ``` #### 示例:实现简单的音视频通话 以下是一个简单的音视频通话实现示例: ```c #include <pjsua2/pjsua2.hpp> using namespace pj; class MyCall : public Call { public: MyCall(Account &acc, int call_id) : Call(acc, call_id) {} virtual void onCallState(OnCallStateParam &prm) { CallInfo ci = getInfo(); if (ci.state == PJSIP_INV_STATE_CONFIRMED) { // 通话已建立 AudioMedia aud_med; getAudioMedia(aud_med); // 获取音频播放设备 AudDevManager &aud_mgr = Endpoint::instance().audDevManager(); AudioMedia *play_dev = aud_mgr.getPlaybackDeviceMedia(); // 连接音频媒体到播放设备 aud_med.startTransmit(*play_dev); // 获取麦克风输入设备 AudioMedia *capture_dev = aud_mgr.getCaptureDeviceMedia(); // 连接麦克风输入设备到音频媒体 capture_dev->startTransmit(aud_med); } } }; ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值