예제 #1
0
        internal bool PreparePacket(ReadOnlySpan <byte> pcm, out byte[] target, out int length)
        {
            target = null;
            length = 0;

            if (this.IsDisposed)
            {
                return(false);
            }

            var audioFormat = this.AudioFormat;

            var packetArray = ArrayPool <byte> .Shared.Rent(this.Rtp.CalculatePacketSize(audioFormat.SampleCountToSampleSize(audioFormat.CalculateMaximumFrameSize()), this.SelectedEncryptionMode));

            var packet = packetArray.AsSpan();

            this.Rtp.EncodeHeader(this.Sequence, this.Timestamp, this.SSRC, packet);
            var opus = packet.Slice(Rtp.HeaderSize, pcm.Length);

            this.Opus.Encode(pcm, ref opus);

            this.Sequence++;
            this.Timestamp += (uint)audioFormat.CalculateFrameSize(audioFormat.CalculateSampleDuration(pcm.Length));

            Span <byte> nonce = stackalloc byte[Sodium.NonceSize];

            switch (this.SelectedEncryptionMode)
            {
            case EncryptionMode.XSalsa20_Poly1305:
                this.Sodium.GenerateNonce(packet.Slice(0, Rtp.HeaderSize), nonce);
                break;

            case EncryptionMode.XSalsa20_Poly1305_Suffix:
                this.Sodium.GenerateNonce(nonce);
                break;

            case EncryptionMode.XSalsa20_Poly1305_Lite:
                this.Sodium.GenerateNonce(this.Nonce++, nonce);
                break;

            default:
                ArrayPool <byte> .Shared.Return(packetArray);

                throw new Exception("Unsupported encryption mode.");
            }

            Span <byte> encrypted = stackalloc byte[Sodium.CalculateTargetSize(opus)];

            this.Sodium.Encrypt(opus, encrypted, nonce);
            encrypted.CopyTo(packet.Slice(Rtp.HeaderSize));
            packet = packet.Slice(0, this.Rtp.CalculatePacketSize(encrypted.Length, this.SelectedEncryptionMode));
            this.Sodium.AppendNonce(nonce, packet, this.SelectedEncryptionMode);

            target = packetArray;
            length = packet.Length;
            return(true);
        }
예제 #2
0
        internal void PreparePacket(ReadOnlySpan <byte> pcm, ref Memory <byte> target)
        {
            var audioFormat = AudioFormat;

            var packetArray = ArrayPool <byte> .Shared.Rent(Rtp.CalculatePacketSize(audioFormat.SampleCountToSampleSize(audioFormat.CalculateMaximumFrameSize()), SelectedEncryptionMode));

            var packet = packetArray.AsSpan();

            Rtp.EncodeHeader(Sequence, Timestamp, SSRC, packet);
            var opus = packet.Slice(Rtp.HeaderSize, pcm.Length);

            Opus.Encode(pcm, ref opus);

            Sequence++;
            Timestamp += (uint)audioFormat.CalculateFrameSize(audioFormat.CalculateSampleDuration(pcm.Length));

            Span <byte> nonce = new byte[Sodium.NonceSize];

            switch (SelectedEncryptionMode)
            {
            case EncryptionMode.XSalsa20_Poly1305:
                Sodium.GenerateNonce(packet.Slice(0, Rtp.HeaderSize), nonce);
                break;

            case EncryptionMode.XSalsa20_Poly1305_Suffix:
                Sodium.GenerateNonce(nonce);
                break;

            case EncryptionMode.XSalsa20_Poly1305_Lite:
                Sodium.GenerateNonce(Nonce++, nonce);
                break;

            default:
                ArrayPool <byte> .Shared.Return(packetArray);

                throw new Exception("Unsupported encryption mode.");
            }

            Span <byte> encrypted = new byte[Sodium.CalculateTargetSize(opus)];

            Sodium.Encrypt(opus, encrypted, nonce);
            encrypted.CopyTo(packet.Slice(Rtp.HeaderSize));
            packet = packet.Slice(0, Rtp.CalculatePacketSize(encrypted.Length, SelectedEncryptionMode));
            Sodium.AppendNonce(nonce, packet, SelectedEncryptionMode);

            target = target.Slice(0, packet.Length);
            packet.CopyTo(target.Span);
            ArrayPool <byte> .Shared.Return(packetArray);
        }