Search code examples
audiosiprtp

How to send G722 encoded audio over an RTP stream?


I've got a small SIP application, which is basically the UserAgentServer example from SipSorcery. I can set-up an RTP stream with ulaw encoded audio, which is then received by my softphone without problems.

Now I've used ffmepg to create a file with g722 encoded audio using: ffmpeg -i sample.wav -ar 16000 -acodec g722 sample.g722. I can playback this audio fine via ffplay sample.g722and the file size comes out at roughly 8000 bytes per second.

I answer the invite request with:

v=0
o=- 55811 0 IN IP4 192.168.1.36
s=sipsorcery
c=IN IP4 192.168.1.36
t=0 0
m=audio 49000 RTP/AVP 9
a=rtpmap:9 G722/8000
a=sendrecv

But then something goes wrong. Because in wireshark I see that the payload of my RTP stream is 'RTPType-96' while the RTP stream of the softphone is displayed as g722. So it seems the codec type was correctly negotiated, but somehow my actual RTP stream is still missing some information.

I send bytes over my RPT stream, from my g722 encoded file, like this:

private async Task SendG722()
{
    uint timestamp = 0;
    using (StreamReader sr = new StreamReader(this.AudioFileName))
    {
        var interval = 20;
        var bytesPerSecond = 8000;
        var packetsPerSecond = 1000 / interval;
        var bufferSize = bytesPerSecond / packetsPerSecond;

        byte[] buffer = new byte[bufferSize];
        int bytesRead = sr.BaseStream.Read(buffer, 0, buffer.Length);

        while (bytesRead > 0 && !this.CancellationTokenSource.IsCancellationRequested)
        {                
            this.Session.SendAudioFrame(this.RtpSocket, this.DestinationRtpEndPoint, timestamp, buffer);
            timestamp += (uint)buffer.Length;                    

            await Task.Delay(interval, this.CancellationTokenSource.Token);
            bytesRead = sr.BaseStream.Read(buffer, 0, buffer.Length);
        }
    }
}

But while the bytes are being sent somewhere, and the RTP stream, and packets, show up in wireshark. I am unable to hear any audio from my softphone. And wireshark can't even figure out anything about the stream.


Solution

  • I suspect all you need to do is set the RTP packet payload type to match your SDP offer.

    The line below set the payload type in the RTP packet header to 0.

    var rtpSession = new RTPSession(RTPPayloadTypesEnum.PCMU, null, null);
    

    Your problem is your SDP offer tells the receiver to expect a payload type of 9 in the RTP packet header.

    The fix should be as simple as changing the ENUM to:

    public enum RTPPayloadTypesEnum
    {
        PCMU = 0,
        PCMA = 1,
        G722 = 9,
        Dynamic = 96,
    }
    

    and then

    var rtpSession = new RTPSession(RTPPayloadTypesEnum.G722, null, null);