コード例 #1
0
        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");
        }
コード例 #2
0
        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);
            }
        }
コード例 #3
0
        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);
        }
コード例 #4
0
        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);
            }
        }
コード例 #5
0
        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());
        }
コード例 #6
0
        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);
        }