Esempio n. 1
0
        private void handleVideoFrameAckMessage(int recipientId, byte[] message)
        {
            // watch out: sender and recipient semantics are inverted!
            int  senderId = BitConverter.ToInt32(message, 1);
            byte frameId  = message[5];

            lock (outboundVideoFrameHistories) {
                Dictionary <int, OutboundVideoFrameHistory> senderHistories;
                if (!outboundVideoFrameHistories.TryGetValue(senderId, out senderHistories))
                {
                    senderHistories = new Dictionary <int, OutboundVideoFrameHistory>();
                    outboundVideoFrameHistories.Add(senderId, senderHistories);
                }
                OutboundVideoFrameHistory history;
                if (!senderHistories.TryGetValue(recipientId, out history))
                {
                    history = new OutboundVideoFrameHistory();
                    senderHistories.Add(recipientId, history);
                }
                history.ClearHistoryUntilThisFrame(frameId);
            }
        }
Esempio n. 2
0
        private void compressAndSendFrame(int senderId, int recipientId, byte[] frame)
        {
            byte oldestFrameId;

            byte[] oldestFrameData;
            lock (outboundVideoFrameHistories) {
                Dictionary <int, OutboundVideoFrameHistory> senderHistories;
                if (!outboundVideoFrameHistories.TryGetValue(senderId, out senderHistories))
                {
                    senderHistories = new Dictionary <int, OutboundVideoFrameHistory>();
                    outboundVideoFrameHistories.Add(senderId, senderHistories);
                }
                OutboundVideoFrameHistory history;
                if (!senderHistories.TryGetValue(recipientId, out history))
                {
                    history = new OutboundVideoFrameHistory();
                    senderHistories.Add(recipientId, history);
                }
                oldestFrameData = history.OldestFrameData;
                oldestFrameId   = (oldestFrameData != null ? history.OldestFrameId : (byte)0);
            }
            byte[] encodedData;
            byte   frameId;

            if (recipientId == hostingPlayerId)
            {
                // no compression needed
                encodedData = frame;
                lock (outboundVideoFrameHistories) {
                    frameId = outboundVideoFrameHistories[senderId][recipientId].AddFrame(frame);
                }
            }
            else
            {
                byte[] frameBuffer = (byte[])frame.Clone();
                unsafe
                {
                    fixed(byte *frameBufferPtr = frameBuffer)
                    {
                        byte *compressedBuffer = stackalloc byte[4096 * 3];
                        int   byteCount;

                        if (oldestFrameData == null)
                        {
                            // no reference frame
                            videoCodec.Encode((IntPtr)frameBufferPtr, (IntPtr)compressedBuffer, out byteCount);
                        }
                        else
                        {
                            // reference frame
                            fixed(byte *referenceFramePtr = oldestFrameData)
                            {
                                videoCodec.Encode((IntPtr)referenceFramePtr, (IntPtr)frameBufferPtr, (IntPtr)compressedBuffer, out byteCount);
                            }
                        }
                        encodedData = new byte[byteCount];
                        for (int i = 0; i < encodedData.Length; ++i)
                        {
                            encodedData[i] = compressedBuffer[i];
                        }
                    }
                }
                lock (outboundVideoFrameHistories) {
                    frameId = outboundVideoFrameHistories[senderId][recipientId].AddFrame(frameBuffer);
                }
            }
            using (NetworkPacket packet = new NetworkPacket(encodedData.Length + 7)) {
                packet.Write((byte)ReservedMessageType.VideoFrame);
                packet.Write((int)senderId);
                packet.Write((byte)frameId);
                packet.Write((byte)(oldestFrameData != null ? oldestFrameId : frameId));
                packet.Write(encodedData);
                // use a timeout equal to 10 times the capture period (15 times per second)
                // TODO : use measured average time between sends
                try {
                    server.SendTo(recipientId, packet, 10 * 1000 / 15, SendFlags.NoComplete | SendFlags.Coalesce | SendFlags.PriorityLow);
                } catch (Microsoft.DirectX.DirectPlay.InvalidPlayerException) { }
            }
        }
Esempio n. 3
0
        /// <summary>Connect to a server.</summary>
        /// <param name="serverName">IP address or hostname of the server.</param>
        /// <param name="serverPort">IP port on which the server is listening.</param>
        /// <remarks>The first client to connect becomes the hosting player.</remarks>
        public void Connect(string serverName, int serverPort)
        {
            Debug.Assert(status == NetworkStatus.Disconnected);

            serverIsOnSameComputer     = (serverName == "localhost");
            outboundVideoFrameHistory  = new OutboundVideoFrameHistory();
            inboundVideoFrameHistories = new Dictionary <int, InboundVideoFrameHistory>();
            soundBuffers = new Dictionary <int, Buffer3D>();

            client = new Microsoft.DirectX.DirectPlay.Client(InitializeFlags.DisableParameterValidation);
            client.ConnectComplete   += new ConnectCompleteEventHandler(onConnectComplete);
            client.Receive           += new ReceiveEventHandler(onReceive);
            client.SessionTerminated += new SessionTerminatedEventHandler(onSessionTerminated);

            status = NetworkStatus.Connecting;

            // trigger NAT traversal
            EnabledAddresses enabledAddresses = NatResolver.TestNatTraversal(serverName, serverPort);

            ApplicationDescription description = new ApplicationDescription();

            description.GuidApplication = new Guid("{920BAF09-A06C-47d8-BCE0-21B30D0C3586}");
            // try first using the host's public address
            using (Address hostAddress = (enabledAddresses == null ? new Address(serverName, serverPort) : new Address(enabledAddresses.HostPublicAddress, enabledAddresses.HostPublicPort))) {
                hostAddress.ServiceProvider = Address.ServiceProviderTcpIp;
                using (Address device = new Address()) {
                    device.ServiceProvider = Address.ServiceProviderTcpIp;
                    device.AddComponent(Address.KeyTraversalMode, Address.TraversalModeNone);
                    if (enabledAddresses != null)
                    {
                        device.AddComponent(Address.KeyPort, enabledAddresses.ClientPrivatePort);
                    }
                    using (NetworkPacket packet = new NetworkPacket()) {
                        try {
                            client.Connect(description, hostAddress, device, packet, 0);
                        } catch (Exception e) {
                            status = NetworkStatus.Disconnected;
                            ConnectionFailureCause cause =
                                (e is NoConnectionException ? ConnectionFailureCause.NoConnection :
                                 (e is NotHostException ? ConnectionFailureCause.NotHost :
                                  (e is SessionFullException ? ConnectionFailureCause.SessionFull :
                                   ConnectionFailureCause.Other)));

                            // try again using the host's private address
                            if (enabledAddresses != null)
                            {
                                using (Address hostPrivateAddress = new Address(enabledAddresses.HostPrivateAddress, enabledAddresses.HostPrivatePort)) {
                                    try {
                                        client.Connect(description, hostAddress, device, packet, 0);
                                    } catch {
                                        NetworkMessage message = new NetworkMessage(0, (byte)ReservedMessageType.ConnectionFailed, new byte[1] {
                                            (byte)cause
                                        });
                                        lock (networkMessages) {
                                            networkMessages.Enqueue(message);
                                        }
                                        return;
                                    }
                                }
                            }
                            else
                            {
                                NetworkMessage message = new NetworkMessage(0, (byte)ReservedMessageType.ConnectionFailed, new byte[1] {
                                    (byte)cause
                                });
                                lock (networkMessages) {
                                    networkMessages.Enqueue(message);
                                }
                                return;
                            }
                        }
                    }
                }
            }

            // launch a timer to monitor timeout
            timeoutTimer = new System.Threading.Timer(onTimeout, client, 4000, 0);
        }