private void uncompressFrame(int senderId, byte[] messageData) { byte frameId = messageData[1]; byte referenceFrameId = messageData[2]; // send video frame reception notification using (NetworkPacket packet = new NetworkPacket(2)) { packet.Write((byte)ReservedMessageType.VideoFrameAck); packet.Write((int)senderId); packet.Write((byte)frameId); // use a timeout equal to 10 times the capture period (15 times per second) try { server.SendTo(senderId, packet, 10 * 1000 / 15, SendFlags.NoComplete | SendFlags.Coalesce | SendFlags.PriorityHigh); } catch (Microsoft.DirectX.DirectPlay.InvalidPlayerException) { } } // uncompress video frame InboundVideoFrameHistory history; if (!inboundVideoFrameHistories.TryGetValue(senderId, out history)) { history = new InboundVideoFrameHistory(); inboundVideoFrameHistories.Add(senderId, history); } byte[] frame = new byte[64 * 64 * 3]; if (senderId == hostingPlayerId) { // no compression needed Array.Copy(messageData, 3, frame, 0, frame.Length); } else { unsafe { fixed(byte *framePtr = frame) { fixed(byte *dataPtr = messageData) { if (frameId == referenceFrameId) { // no reference frame videoCodec.Decode((IntPtr)(dataPtr + 3), (IntPtr)framePtr); } else { // reference frame fixed(byte *referenceFramePtr = history.GetFrameData(referenceFrameId)) { videoCodec.Decode((IntPtr)referenceFramePtr, (IntPtr)(dataPtr + 3), (IntPtr)framePtr); } } } } } } if (referenceFrameId != frameId) { history.ClearHistoryUntilThisFrame(referenceFrameId); } history.AddFrame(frameId, frame); // make one compress job for each other player foreach (int playerId in server.Players) { if (playerId != senderId && playerId != serverId) { compressJobs.AddFirst(new CompressJob(senderId, playerId, frame)); } } }
/// <summary>Get all pending messages received.</summary> /// <returns>An array of NetworkMessage instances.</returns> public NetworkMessage[] RetrieveNetworkMessages() { NetworkMessage[] shallowCopy; lock (networkMessages) { shallowCopy = networkMessages.ToArray(); networkMessages.Clear(); } for (int i = shallowCopy.Length - 1; i >= 0; --i) { NetworkMessage message = shallowCopy[i]; if (message.Type == (byte)ReservedMessageType.VideoFrameReceived && message.Data != null) { byte frameId = message.Data[5]; // send video frame reception notification if (status == NetworkStatus.Connected) { using (NetworkPacket packet = new NetworkPacket(6)) { packet.Write((byte)ReservedMessageType.VideoFrameAck); packet.Write((int)message.SenderId); packet.Write((byte)frameId); // use a timeout equal to 10 times the capture period (15 times per second) client.Send(packet, 10 * 1000 / 15, SendFlags.NoComplete | SendFlags.Coalesce | SendFlags.PriorityHigh); } } // ignore earlier frames from same sender for (int j = 0; j < i; ++j) { NetworkMessage earlierMessage = shallowCopy[j]; if (earlierMessage.Type == (byte)ReservedMessageType.VideoFrameReceived && earlierMessage.SenderId == message.SenderId) { shallowCopy[j] = new NetworkMessage(earlierMessage.SenderId, earlierMessage.Type, null); } } } } for (int i = 0; i < shallowCopy.Length; ++i) { NetworkMessage message = shallowCopy[i]; if (message.Type == (byte)ReservedMessageType.VideoFrameReceived && message.Data != null) { byte frameId = message.Data[5]; byte referenceFrameId = message.Data[6]; InboundVideoFrameHistory history; if (!inboundVideoFrameHistories.TryGetValue(message.SenderId, out history)) { history = new InboundVideoFrameHistory(); inboundVideoFrameHistories.Add(message.SenderId, history); } byte[] frame = new byte[64 * 64 * 3]; if (serverIsOnSameComputer) { // no compression Array.Copy(message.Data, 7, frame, 0, frame.Length); } else { // uncompress video frame unsafe { fixed(byte *framePtr = frame) { fixed(byte *dataPtr = message.Data) { if (frameId == referenceFrameId) { // no reference frame videoCodec.Decode((IntPtr)(dataPtr + 7), (IntPtr)framePtr); } else { // reference frame fixed(byte *referenceFramePtr = history.GetFrameData(referenceFrameId)) { videoCodec.Decode((IntPtr)referenceFramePtr, (IntPtr)(dataPtr + 7), (IntPtr)framePtr); } } } } } } if (referenceFrameId != frameId) { history.ClearHistoryUntilThisFrame(referenceFrameId); } history.AddFrame(frameId, frame); shallowCopy[i] = new NetworkMessage(message.SenderId, message.Type, frame); } } return(shallowCopy); }