Я сейчас начинаю работать с PJSUA2. Я хочу разработать SIP-клиент, который принимает звонки. Когда он принимает вызов, я играю WAV-файл и также записываю ввод в WAV-файл. PJSIP не определяет мои аудиоустройства по умолчанию, но это нормально, так как я все равно не хочу их использовать, поэтому я выбираю NullAudio через audDevManager (). SetNullDev ().
Вот код моего звонка:
class MyCall : public Call {
public:
AudioMediaPlayer player;
AudioMediaRecorder recorder;
AudioMediaRecorder recorderVerify;
MyCall(Account &acc, int call_id = PJSUA_INVALID_ID)
: Call(acc, call_id)
{ }
void MyCall::onCallState(OnCallStateParam &prm)
{
cout << "!!!!! onCallState is called !!!!!" << endl;
CallInfo ci = getInfo();
cout << "ci.state = " << ci.state << endl;
if (ci.state == PJSIP_INV_STATE_DISCONNECTED) {
delete this;
}
}
void MyCall::onCallMediaState(OnCallMediaStateParam &prm){
cout << "!!!!! onCallMediaState is called !!!!!" << endl;
try{
player.createPlayer("Ring02.wav", PJMEDIA_FILE_NO_LOOP);
recorder.createRecorder("in.wav");
recorderVerify.createRecorder("test.wav");
CallInfo ci = getInfo();
AudioMedia* aud_med = 0;
// Iterate all the call medias
for (unsigned i = 0; i < ci.media.size(); i++) {
cout << "Check audio " << i << endl;
if (ci.media[i].type==PJMEDIA_TYPE_AUDIO && getMedia(i)) {
aud_med = static_cast<AudioMedia*>( getMedia(i));
break;
}
}
if (aud_med != 0){
cout << "Send stuff to media" << endl;
// Connect the call audio media to sound device
AudDevManager& mgr = Endpoint::instance().audDevManager();
player.startTransmit(*aud_med);
aud_med->startTransmit(recorder);
player.startTransmit(recorderVerify);
}
} catch (Error& err) {
cout << "Error when playing: " << err.info() << endl;
}
}
};
Я уже сделал переменные члена плеера и рекордера на основе PJSUA2 — запись аудио звонка в файл wav. Теперь я могу правильно воспроизвести файл WAV для вызывающего абонента, а также записать свой собственный файл WAV через устройство записи Verify. Но звук от звонящего не записывается, а сгенерированный WAV-файл — это тишина.
Нужно ли что-то инициализировать или что я пропустил? Большое спасибо за вашу помощь!
Это просто дикая догадка.
Когда PJSUA отправляет второй запрос INVITE сразу после получения первого OK, что он делает в диалоговом режиме (это можно проверить с помощью wireshark), onCallMediaState
называется второй раз и, если по какой-то причине стороны договорились о каком-то другом кодеке, не то, что это был первый раз, может быть другой getMedia(i)
объект, и первый оригинальный может быть уничтожен. В этом случае рекордер просто прекращает запись, и вы получаете WAV одну секунду.
когда onCallMediaState
вызывается второй раз для второго запроса INVITE, вы пытаетесь
player.createPlayer("Ring02.wav", PJMEDIA_FILE_NO_LOOP);
recorder.createRecorder("in.wav");
recorderVerify.createRecorder("test.wav");
который бросит, потому что они уже созданы. Если я прав, в вашем журнале должно быть уведомление об ошибке. Таким образом, вы не получите
aud_med->startTransmit(recorder);
продолжить запись, поэтому ваш WAV содержит долю секунды длинной записи разговора, прежде чем сеанс был повторно инициализирован.
Других решений пока нет …