主要用到位于 pjsua.h 中的2个回调函数来获取
on_aud_prev_play_frame
on_aud_prev_rec_frame
//pjsua.h
...
/**
* Optional callback for audio frame preview right before queued to
* the speaker.
* Notes:
* - application MUST NOT block or perform long operation in the callback
* as the callback may be executed in sound device thread
* - when using software echo cancellation, application MUST NOT modify
* the audio data from within the callback, otherwise the echo canceller
* will not work properly.
*/
void (*on_aud_prev_play_frame)(pjmedia_frame *frame);
/**
* Optional callback for audio frame preview recorded from the microphone
* before being processed by any media component such as software echo
* canceller.
* Notes:
* - application MUST NOT block or perform long operation in the callback
* as the callback may be executed in sound device thread
* - when using software echo cancellation, application MUST NOT modify
* the audio data from within the callback, otherwise the echo canceller
* will not work properly.
*/
void (*on_aud_prev_rec_frame)(pjmedia_frame *frame);
在初始化之前设定好pjsua_media_config 的这2个回调函数
media_cfg.on_aud_prev_play_frame = &play_frame;//对方说话音频
media_cfg.on_aud_prev_rec_frame = &rec_frame;//自己说话音频
// pj create
pj_status_t status;
pjsua_config ua_cfg;
pjsua_media_config media_cfg;
pjsua_transport_config cfg;
// Must create pjsua before anything else!
status = pjsua_create();
if (status != PJ_SUCCESS)
{
LOG_FUNC_QUIT(LOG_SYS);
return;
}
LoggerCio::notice(LoggerCio::LOG_SYS,"*** sip pjsua_create() success!");
// Initialize configs with default settings.
pjsua_config_default(&ua_cfg);
pjsua_media_config_default(&media_cfg);
CString userAgent;
userAgent.Format(_T("%s/%s"), _T("CioSIP"), _T("1.0.0"));
ua_cfg.user_agent = StrToPjStr(userAgent);
//设置回调函数
ua_cfg.cb.on_reg_state2=&on_reg_state2;
ua_cfg.cb.on_call_state=&on_call_state;
ua_cfg.cb.on_call_media_state = &on_call_media_state;
ua_cfg.cb.on_incoming_call = &on_incoming_call;
//ua_cfg.cb.on_nat_detect= &on_nat_detect;
ua_cfg.cb.on_buddy_state = &on_buddy_state; //订阅分机状态
//ua_cfg.cb.on_pager = &on_pager;
//ua_cfg.cb.on_pager_status = &on_pager_status;
//ua_cfg.cb.on_call_transfer_request2 = &on_call_transfer_request2;
//ua_cfg.cb.on_call_transfer_status = &on_call_transfer_status;
ua_cfg.srtp_secure_signaling=0;
media_cfg.enable_ice = PJ_FALSE;
media_cfg.no_vad = /*accountSettings.vad ? PJ_FALSE :*/ PJ_TRUE;
media_cfg.ec_tail_len = /*accountSettings.ec ? PJSUA_DEFAULT_EC_TAIL_LEN :*/ 0;
media_cfg.clock_rate=44100;
media_cfg.channel_count=2;
// add [2019-2-23 By Pafey]
media_cfg.on_aud_prev_play_frame = &play_frame;//对方说话音频
media_cfg.on_aud_prev_rec_frame = &rec_frame;//自己说话音频
status = pjsua_init(&ua_cfg, NULL, &media_cfg);
定义回调函数来接收2路音频,再去做后续处理。
//对方说话音频
static void play_frame(pjmedia_frame *frame)
{
if( PJMEDIA_FRAME_TYPE_AUDIO == frame->type || PJMEDIA_FRAME_TYPE_EXTENDED == frame->type)
{
//CString str;
//str.Format(_T("speaker frame size:%d\n"),frame->size);
//OutputDebugStringW(str);
mainDlg->sendSpeakAudioData(frame->size,(LPBYTE)frame->buf);
}
}
//自己说话音频
static void rec_frame(pjmedia_frame *frame)
{
if( PJMEDIA_FRAME_TYPE_AUDIO == frame->type || PJMEDIA_FRAME_TYPE_EXTENDED == frame->type)
{
//CString str;
//str.Format(_T("microphone frame size:%d\n"),frame->size);
//OutputDebugStringW(str);
mainDlg->onCaptureData(frame->size,(LPARAM)frame->buf);
}
}