Working with AsterNET.ARI I am able to expose audio stream from asterisk, using ExternalMedia.
Scenario:
- Call is started and
Stasis
App is invoked - Create
ExternalMediaChannel
that sends stream to aRTP
server I created listening from allIP
s in Port:7777
. - Create
bridge
typemixing
and add both channels in it
The goal is to send back this stream to this channel that normally should be heared in the originator channel since both channels are in the same bridge.
It looks like the RTP is sent back and received by asterisk but however I'm not able to hear it.
ARI ExternMediaChannel:
{"UNICASTRTP_LOCAL_PORT":"15672","UNICASTRTP_LOCAL_ADDRESS":"172.18.33.220"}
Asterisk
Got RTP packet from 10.114.0.234:55874 (type 111, seq 031742, ts 3934092822, len 000069)
Sent RTP packet to 172.18.33.220:7777 (type 118, seq 029097, ts 1090576, len 000640)
Got RTP packet from 10.114.0.234:55874 (type 111, seq 031743, ts 3934093782, len 000071)
Sent RTP packet to 172.18.33.220:7777 (type 118, seq 029098, ts 1090896, len 000640)
RTP Server
Sending To: 172.18.33.220:15672
Received From: 172.18.33.220:15672
Sending To: 172.18.33.220:15672
Received From: 172.18.33.220:15672
I can actually print the byte codes received and I know it's the audio because I have saved the byte codes to file and played the file successfully.
How I am receiving and trying to send the stream back (RTP Server):
public class UDPListener
{
private const int ListenPort = 7777;
public static void StartListener()
{
UdpClient server = new UdpClient(ListenPort);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, ListenPort);
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
try
{
Console.WriteLine("Listening to: " + ListenPort);
while (true)
{
byte[] bytes = server.Receive(ref groupEP);
// PRINTS THE BYTE CODES
// Console.WriteLine($" {Encoding.ASCII.GetString(bytes, 0, bytes.Length)}");
RtpPacket rcvpacket;
bool parsedRCV = RtpPacket.TryParse(bytes, out rcvpacket);
if(parsedRCV){
Console.WriteLine($"Received From: {groupEP.Address}:{groupEP.Port}");
}
RtpPacket packet;
bool parsed = RtpPacket.TryParse(bytes, out packet);
if(parsed){
Console.WriteLine($"Sending To: {groupEP.Address}:{groupEP.Port}");
client.SendTo(packet.PayloadSegment, groupEP);
}
}
}
}
}
RtpPacket is a C#
class that represents the definition of a RTP
packet.
struct RtpPacket
{
public const int RtpHeaderSize = 12;
public const int RtpProtocolVersion = 2;
public int ProtocolVersion { get; private set; }
public bool PaddingFlag { get; private set; }
public bool ExtensionFlag { get; private set; }
public int CsrcCount { get; private set; }
public bool MarkerBit { get; private set; }
public int PayloadType { get; private set; }
public ushort SeqNumber { get; private set; }
public uint Timestamp { get; private set; }
public uint SyncSourceId { get; private set; }
public int ExtensionHeaderId { get; private set; }
public ArraySegment<byte> PayloadSegment { get; set; }
internal RtpPacket(ushort seqNumber, ArraySegment<byte> payloadSegment)
{
ProtocolVersion = 1;
PaddingFlag = false;
ExtensionFlag = false;
CsrcCount = 0;
MarkerBit = false;
PayloadType = 0;
SeqNumber = 0;
Timestamp = 0;
SyncSourceId = 0;
ExtensionHeaderId = 0;
SeqNumber = seqNumber;
PayloadSegment = payloadSegment;
}
public static bool TryParse(ArraySegment<byte> byteSegment, out RtpPacket rtpPacket)
{
rtpPacket = new RtpPacket();
Debug.Assert(byteSegment.Array != null, "byteSegment.Array != null");
if (byteSegment.Count < RtpHeaderSize)
return false;
int offset = byteSegment.Offset;
rtpPacket.ProtocolVersion = byteSegment.Array[offset] >> 6;
if (rtpPacket.ProtocolVersion != RtpProtocolVersion)
return false;
rtpPacket.PaddingFlag = (byteSegment.Array[offset] >> 5 & 1) != 0;
rtpPacket.ExtensionFlag = (byteSegment.Array[offset] >> 4 & 1) != 0;
rtpPacket.CsrcCount = byteSegment.Array[offset++] & 0xF;
rtpPacket.MarkerBit = byteSegment.Array[offset] >> 7 != 0;
rtpPacket.PayloadType = byteSegment.Array[offset++] & 0x7F;
rtpPacket.SeqNumber = (ushort)BigEndianConverter.ReadUInt16(byteSegment.Array, offset);
offset += 2;
rtpPacket.Timestamp = BigEndianConverter.ReadUInt32(byteSegment.Array, offset);
offset += 4;
rtpPacket.SyncSourceId = BigEndianConverter.ReadUInt32(byteSegment.Array, offset);
offset += 4 + 4 * rtpPacket.CsrcCount;
if (rtpPacket.ExtensionFlag)
{
rtpPacket.ExtensionHeaderId = BigEndianConverter.ReadUInt16(byteSegment.Array, offset);
offset += 2;
int extensionHeaderLength = BigEndianConverter.ReadUInt16(byteSegment.Array, offset) * 4;
offset += 2 + extensionHeaderLength;
}
int payloadSize = byteSegment.Offset + byteSegment.Count - offset;
if (rtpPacket.PaddingFlag)
{
int paddingBytes = byteSegment.Array[byteSegment.Offset + byteSegment.Count - 1];
payloadSize -= paddingBytes;
}
rtpPacket.PayloadSegment = new ArraySegment<byte>(byteSegment.Array, offset, payloadSize);
return true;
}
}
public static class BigEndianConverter
{
public static uint ReadUInt32(byte[] buffer, int offset)
{
return (uint)(buffer[offset] << 24 |
buffer[offset + 1] << 16 |
buffer[offset + 2] << 8 |
buffer[offset + 3]);
}
public static int ReadUInt24(byte[] buffer, int offset)
{
return buffer[offset] << 16 |
buffer[offset + 1] << 8 |
buffer[offset + 2];
}
public static int ReadUInt16(byte[] buffer, int offset)
{
return (buffer[offset] << 8) | buffer[offset + 1];
}
}
Any idea why I am not able to hear the stream back ?