예제 #1
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);
        }