public AudioListener(IRtspReceiver receiver, string sessionId, ushort cport, ushort dport, CodecLibrariesConfig clConfig, DumpConfig dConfig) : base(cport, dport) { _receiver = receiver ?? throw new ArgumentNullException(nameof(receiver)); _sessionId = sessionId ?? throw new ArgumentNullException(nameof(sessionId)); _clConfig = clConfig ?? throw new ArgumentNullException(nameof(clConfig)); _dConfig = dConfig ?? throw new ArgumentNullException(nameof(dConfig)); _raopBuffer = RaopBufferInit(); _aesCbcDecrypt = CipherUtilities.GetCipher("AES/CBC/NoPadding"); }
private void RaopBufferFlush(RaopBuffer raop_buffer, int next_seq) { int i; for (i = 0; i < RAOP_BUFFER_LENGTH; i++) { raop_buffer.Entries[i].Available = false; raop_buffer.Entries[i].AudioBufferLen = 0; } if (next_seq < 0 || next_seq > 0xffff) { raop_buffer.IsEmpty = true; } else { raop_buffer.FirstSeqNum = (ushort)next_seq; raop_buffer.LastSeqNum = (ushort)(next_seq - 1); } }
private RaopBuffer RaopBufferInit() { var audio_buffer_size = 480 * 4; var raop_buffer = new RaopBuffer(); raop_buffer.BufferSize = audio_buffer_size * RAOP_BUFFER_LENGTH; raop_buffer.Buffer = new byte[raop_buffer.BufferSize]; for (int i = 0; i < RAOP_BUFFER_LENGTH; i++) { var entry = raop_buffer.Entries[i]; entry.AudioBufferSize = audio_buffer_size; entry.AudioBufferLen = 0; entry.AudioBuffer = (byte[])raop_buffer.Buffer.Skip(i).Take(audio_buffer_size).ToArray(); raop_buffer.Entries[i] = entry; } raop_buffer.IsEmpty = true; return(raop_buffer); }
private void RaopBufferHandleResends(RaopBuffer raop_buffer, Socket cSocket, ushort control_seqnum) { RaopBufferEntry entry; if (Utilities.SeqNumCmp(raop_buffer.FirstSeqNum, raop_buffer.LastSeqNum) < 0) { int seqnum, count; for (seqnum = raop_buffer.FirstSeqNum; Utilities.SeqNumCmp(seqnum, raop_buffer.LastSeqNum) < 0; seqnum++) { entry = raop_buffer.Entries[seqnum % RAOP_BUFFER_LENGTH]; if (entry.Available) { break; } } if (Utilities.SeqNumCmp(seqnum, raop_buffer.FirstSeqNum) == 0) { return; } count = Utilities.SeqNumCmp(seqnum, raop_buffer.FirstSeqNum); RaopRtpResendCallback(cSocket, control_seqnum, raop_buffer.FirstSeqNum, (ushort)count); } }
public byte[] RaopBufferDequeue(RaopBuffer raop_buffer, ref int length, ref uint pts, bool noResend) { short buflen; RaopBufferEntry entry; /* Calculate number of entries in the current buffer */ buflen = (short)(raop_buffer.LastSeqNum - raop_buffer.FirstSeqNum + 1); /* Cannot dequeue from empty buffer */ if (raop_buffer.IsEmpty || buflen <= 0) { return(null); } /* Get the first buffer entry for inspection */ entry = raop_buffer.Entries[raop_buffer.FirstSeqNum % RAOP_BUFFER_LENGTH]; if (noResend) { /* If we do no resends, always return the first entry */ entry.Available = false; /* Return entry audio buffer */ length = entry.AudioBufferLen; pts = entry.TimeStamp; entry.AudioBufferLen = 0; raop_buffer.Entries[raop_buffer.FirstSeqNum % RAOP_BUFFER_LENGTH] = entry; raop_buffer.FirstSeqNum += 1; return(entry.AudioBuffer); } else if (!entry.Available) { /* Check how much we have space left in the buffer */ if (buflen < RAOP_BUFFER_LENGTH) { /* Return nothing and hope resend gets on time */ length = entry.AudioBufferSize; Array.Fill <byte>(entry.AudioBuffer, 0, 0, length); return(entry.AudioBuffer); } /* Risk of buffer overrun, return empty buffer */ return(Array.Empty <byte>()); } /* Update buffer and validate entry */ if (!entry.Available) { /* Return an empty audio buffer to skip audio */ length = entry.AudioBufferSize; Array.Fill <byte>(entry.AudioBuffer, 0, 0, length); return(entry.AudioBuffer); } entry.Available = false; /* Return entry audio buffer */ length = entry.AudioBufferLen; pts = entry.TimeStamp; entry.AudioBufferLen = 0; raop_buffer.Entries[raop_buffer.FirstSeqNum % RAOP_BUFFER_LENGTH] = entry; raop_buffer.FirstSeqNum += 1; return(entry.AudioBuffer.Take(length).ToArray()); }
public int RaopBufferQueue(RaopBuffer raop_buffer, byte[] data, ushort datalen, Session session) { int encryptedlen; RaopBufferEntry entry; /* Check packet data length is valid */ if (datalen < 12 || datalen > RAOP_PACKET_LENGTH) { return(-1); } var seqnum = (ushort)((data[2] << 8) | data[3]); if (datalen == 16 && data[12] == 0x0 && data[13] == 0x68 && data[14] == 0x34 && data[15] == 0x0) { return(0); } // Ignore, old if (!raop_buffer.IsEmpty && seqnum < raop_buffer.FirstSeqNum && seqnum != 0) { return(0); } /* Check that there is always space in the buffer, otherwise flush */ if (raop_buffer.FirstSeqNum + RAOP_BUFFER_LENGTH < seqnum || seqnum == 0) { RaopBufferFlush(raop_buffer, seqnum); } entry = raop_buffer.Entries[seqnum % RAOP_BUFFER_LENGTH]; if (entry.Available && entry.SeqNum == seqnum) { /* Packet resent, we can safely ignore */ return(0); } entry.Flags = data[0]; entry.Type = data[1]; entry.SeqNum = seqnum; entry.TimeStamp = (uint)((data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7]); entry.SSrc = (uint)((data[8] << 24) | (data[9] << 16) | (data[10] << 8) | data[11]); entry.Available = true; int payloadsize = datalen - 12; var raw = new byte[payloadsize]; encryptedlen = payloadsize / 16 * 16; if (encryptedlen > 0) { _aesCbcDecrypt.ProcessBytes(data, 12, encryptedlen, data, 12); Array.Copy(data, 12, raw, 0, encryptedlen); } Array.Copy(data, 12 + encryptedlen, raw, encryptedlen, payloadsize - encryptedlen); #if DUMP /* RAW -> DUMP */ var fPath = Path.Combine(_dConfig.Path, "frames/"); File.WriteAllBytes($"{fPath}raw_{seqnum}", raw); #endif /* RAW -> PCM */ var length = _decoder.GetOutputStreamLength(); var output = new byte[length]; var res = _decoder.DecodeFrame(raw, ref output, length); if (res != 0) { output = new byte[length]; Console.WriteLine($"Decoding error. Decoder: {_decoder.Type} Code: {res}"); } #if DUMP var pPath = Path.Combine(_dConfig.Path, "pcm/"); Console.WriteLine($"RES: {res}"); Console.WriteLine($"PCM: {output.Length}"); Console.WriteLine($"LNG: {length}"); File.WriteAllBytes($"{pPath}raw_{seqnum}", output); #endif Array.Copy(output, 0, entry.AudioBuffer, 0, output.Length); entry.AudioBufferLen = output.Length; /* Update the raop_buffer seqnums */ if (raop_buffer.IsEmpty) { raop_buffer.FirstSeqNum = seqnum; raop_buffer.LastSeqNum = seqnum; raop_buffer.IsEmpty = false; } if (raop_buffer.LastSeqNum < seqnum) { raop_buffer.LastSeqNum = seqnum; } // Update entries raop_buffer.Entries[seqnum % RAOP_BUFFER_LENGTH] = entry; return(1); }