Play wav in call with pjsua2

1.7k Views Asked by At

I'm trying to play 16 bit PCM mono .wav files in a call with PJSUA 2.11 (also happened with 2.10). The logs don't indicate any errors, however I don't hear anything on the other side. I have disabled the system audio device to prevent usage of system audio, but it also didn't work with one enabled.

I have

  • created an endpoint
  • ep.audDevManager().setNullDev();
  • created a transport
  • ep.libStart();
  • created an account with credentials
  • created a new call using an inherited class with default params using CallOpParam prm(true);
  • while (call->isActive()) pj_thread_sleep(1000);

in my call class I'm trying to play audio like this:

    virtual void onCallMediaState(OnCallMediaStateParam &prm)
    {
        std::cerr << "received media state" << std::endl;
        CallInfo ci = getInfo();

        for (unsigned i = 0; i < ci.media.size(); i++) {
            if (ci.media[i].type == PJMEDIA_TYPE_AUDIO
                && (ci.media[i].dir == PJMEDIA_DIR_ENCODING || ci.media[i].dir == PJMEDIA_DIR_ENCODING_DECODING)
                && ci.media[i].status == PJSUA_CALL_MEDIA_ACTIVE
            ) {
                AudioMedia aud_med = getAudioMedia(i);
                AudioMediaPlayer* player = new AudioMediaPlayer();
                player->createPlayer("wav/audio.wav");
                player->startTransmit(aud_med);
                break;
            }
        }
    }

I tried a few variations of playback attempts: other than this I tried not breaking after first media or using an AudioMediaPlayer as class member that's initialized only once.

However never I could hear anything on the remote side. I have verified that the devices actually work with twinkle on the system and the call does connect.

log (right after accepting the call):

20:27:25.506      inv0x55d724e01988  ....SDP negotiation done: Success
20:27:25.506          pjsua_media.c  .....Call 0: updating media..
20:27:25.506          pjsua_media.c  ......Call 0: stream #0 (audio) unchanged.
20:27:25.506          pjsua_media.c  ......Audio updated, stream #0: G722 (sendrecv)
received media state
20:27:25.506            pjsua_aud.c  .....Creating file player: wav/audio.wav..
20:27:25.506           wav_player.c  ......File player 'wav/audio.wav' created: samp.rate=44100, ch=1, bufsize=4KB, filesize=178KB
20:27:25.506            pjsua_aud.c  ......Player created, id=2, slot=4
20:27:25.506            pjsua_aud.c  .....Conf connect: 4 --> 1
20:27:25.506           conference.c  ......Port 4 (wav/audio.wav) transmitting to port 1 (sip:<remote number>@192.168.178.1)

I was thinking this might be related to me not consuming the audio received from the remote side at all, but I don't know how I can discard it without using it. The audio file plays on local PC using the playfile sample shipped with pjsip.

1

There are 1 best solutions below

1
On

My code does play back the wav. You might miss a aud_med.start_transmit:

void MyCall::onCallMediaState(pj::OnCallMediaStateParam &prm)
{
    try {
        auto callInfo = getInfo();
        std::cout << "*** onCallMediaState state: id=" << callInfo.id << ", state="  << callInfo.stateText << std::endl;
        PJ_UNUSED_ARG(prm);

        pj::AudioMedia& play_dev_med =
            pj::Endpoint::instance().audDevManager().getPlaybackDevMedia();
        

        // Get the first audio media
        pj::AudioMedia aud_med = getAudioMedia(-1);

        if (!player_) {
            player_ = std::make_unique<pj::AudioMediaPlayer>();
            player_->createPlayer("/home/Projects/test.wav");
        }

        player_->startTransmit(aud_med);
        // And this will connect the call audio media to the sound device/speaker
        aud_med.startTransmit(play_dev_med);
   }
   catch (const pj::Error& e) {
        std::cerr << "***Exception: " << e.info() << std::endl;
   }
}