Пример #1
0
    public static VideoSenderPacketData Parse(byte[] packetBytes)
    {
        var reader = new BinaryReader(new MemoryStream(packetBytes));

        reader.BaseStream.Position = 5;

        var videoSenderPacketData = new VideoSenderPacketData();

        videoSenderPacketData.frameId     = reader.ReadInt32();
        videoSenderPacketData.packetIndex = reader.ReadInt32();
        videoSenderPacketData.packetCount = reader.ReadInt32();

        videoSenderPacketData.messageData = reader.ReadBytes(packetBytes.Length - (int)reader.BaseStream.Position);

        return(videoSenderPacketData);
    }
Пример #2
0
    private static void CollectPacket(UdpSocketPacket packet, SenderPacketCollection senderPacketCollection)
    {
        int senderSessionId         = PacketHelper.getSessionIdFromSenderPacketBytes(packet.Bytes);
        SenderPacketType packetType = PacketHelper.getPacketTypeFromSenderPacketBytes(packet.Bytes);

        if (packetType == SenderPacketType.Confirm)
        {
            senderPacketCollection.ConfirmPacketInfoList.Add(new ConfirmPacketInfo(packet.EndPoint, senderSessionId, ConfirmSenderPacketData.Parse(packet.Bytes)));
            return;
        }

        SenderPacketSet senderPacketSet;

        if (!senderPacketCollection.SenderPacketSets.TryGetValue(senderSessionId, out senderPacketSet))
        {
            return;
        }

        // Heartbeat packets turns on ReceivedAny.
        senderPacketSet.ReceivedAny = true;
        switch (packetType)
        {
        case SenderPacketType.VideoInit:
            senderPacketSet.InitPacketDataList.Add(VideoInitSenderPacketData.Parse(packet.Bytes));
            break;

        case SenderPacketType.Frame:
            senderPacketSet.VideoPacketDataList.Add(VideoSenderPacketData.Parse(packet.Bytes));
            break;

        case SenderPacketType.Parity:
            senderPacketSet.FecPacketDataList.Add(ParitySenderPacketData.Parse(packet.Bytes));
            break;

        case SenderPacketType.Audio:
            senderPacketSet.AudioPacketDataList.Add(AudioSenderPacketData.Parse(packet.Bytes));
            break;

        case SenderPacketType.Floor:
            senderPacketSet.FloorPacketDataList.Add(FloorSenderPacketData.Parse(packet.Bytes));
            break;
        }
    }
        public void Run(KinectReceiver kinectReceiver,
                        int senderSessionId,
                        ConcurrentQueue <VideoSenderPacketData> videoPacketDataQueue,
                        ConcurrentQueue <FecSenderPacketData> fecPacketDataQueue,
                        ConcurrentQueue <AudioSenderPacketData> audioPacketDataQueue)
        {
            SocketError error = SocketError.WouldBlock;

            while (true)
            {
                var packet = kinectReceiver.udpSocket.Receive(out error);
                if (packet == null)
                {
                    break;
                }

                int sessionId  = PacketHelper.getSessionIdFromSenderPacketBytes(packet);
                var packetType = PacketHelper.getPacketTypeFromSenderPacketBytes(packet);

                if (sessionId != senderSessionId)
                {
                    continue;
                }

                if (packetType == SenderPacketType.Frame)
                {
                    videoPacketDataQueue.Enqueue(VideoSenderPacketData.Parse(packet));
                }
                else if (packetType == SenderPacketType.Fec)
                {
                    fecPacketDataQueue.Enqueue(FecSenderPacketData.Parse(packet));
                }
                else if (packetType == SenderPacketType.Audio)
                {
                    audioPacketDataQueue.Enqueue(AudioSenderPacketData.Parse(packet));
                }
            }

            if (error != SocketError.WouldBlock)
            {
                UnityEngine.Debug.Log($"Error from receiving packets: {error.ToString()}");
            }
        }
    public static SenderPacketSet Receive(UdpSocket udpSocket)
    {
        var senderPacketSet = new SenderPacketSet();

        while (true)
        {
            var packet = udpSocket.Receive();
            if (packet == null)
            {
                break;
            }

            //int sessionId = PacketHelper.getSessionIdFromSenderPacketBytes(packet);
            senderPacketSet.ReceivedAny = true;
            switch (PacketHelper.getPacketTypeFromSenderPacketBytes(packet))
            {
            case SenderPacketType.Init:
                senderPacketSet.InitPacketDataList.Add(InitSenderPacketData.Parse(packet));
                break;

            case SenderPacketType.Frame:
                senderPacketSet.VideoPacketDataList.Add(VideoSenderPacketData.Parse(packet));
                break;

            case SenderPacketType.Parity:
                senderPacketSet.FecPacketDataList.Add(ParitySenderPacketData.Parse(packet));
                break;

            case SenderPacketType.Audio:
                senderPacketSet.AudioPacketDataList.Add(AudioSenderPacketData.Parse(packet));
                break;

            case SenderPacketType.Floor:
                senderPacketSet.FloorPacketDataList.Add(FloorSenderPacketData.Parse(packet));
                break;
            }
        }

        return(senderPacketSet);
    }
    public void Assemble(UdpSocket udpSocket,
                         List <VideoSenderPacketData> videoPacketDataList,
                         List <ParitySenderPacketData> parityPacketDataList,
                         int lastVideoFrameId,
                         List <Tuple <int, VideoSenderMessageData> > videoMessageList)
    {
        int?addedFrameId = null;

        // Collect the received video packets.
        foreach (var videoSenderPacketData in videoPacketDataList)
        {
            if (videoSenderPacketData.frameId <= lastVideoFrameId)
            {
                continue;
            }

            if (!videoPacketCollections.ContainsKey(videoSenderPacketData.frameId))
            {
                videoPacketCollections[videoSenderPacketData.frameId] = new VideoSenderPacketData[videoSenderPacketData.packetCount];
                // Assign the largest new frame_id.
                if (!addedFrameId.HasValue || addedFrameId < videoSenderPacketData.frameId)
                {
                    addedFrameId = videoSenderPacketData.frameId;
                }
            }

            videoPacketCollections[videoSenderPacketData.frameId][videoSenderPacketData.packetIndex] = videoSenderPacketData;
        }

        // Collect the received parity packets.
        foreach (var paritySenderPacketData in parityPacketDataList)
        {
            if (paritySenderPacketData.frameId <= lastVideoFrameId)
            {
                continue;
            }

            if (!parityPacketCollections.ContainsKey(paritySenderPacketData.frameId))
            {
                parityPacketCollections[paritySenderPacketData.frameId] = new ParitySenderPacketData[paritySenderPacketData.packetCount];
            }

            parityPacketCollections[paritySenderPacketData.frameId][paritySenderPacketData.packetIndex] = paritySenderPacketData;
        }

        if (addedFrameId.HasValue)
        {
            foreach (var videoPacketCollection in videoPacketCollections)
            {
                int frameId = videoPacketCollection.Key;
                VideoSenderPacketData[] videoPackets = videoPacketCollection.Value;

                // Skip the frame that just got added or even newer.
                if (frameId >= addedFrameId)
                {
                    continue;
                }

                // Find the parity packet collection corresponding to the video packet collection.
                // Skip if there is no parity packet collection for the video frame.
                if (!parityPacketCollections.ContainsKey(frameId))
                {
                    continue;
                }

                ParitySenderPacketData[] parityPackets = parityPacketCollections[frameId];

                // Loop per each parity packet.
                // Collect video packet indices to request.
                List <int> videoPacketIndiecsToRequest  = new List <int>();
                List <int> parityPacketIndiecsToRequest = new List <int>();

                for (int parityPacketIndex = 0; parityPacketIndex < parityPackets.Length; ++parityPacketIndex)
                {
                    // Range of the video packets that correspond to the parity packet.
                    int videoPacketStartIndex = parityPacketIndex * FEC_GROUP_SIZE;
                    // Pick the end index with the end of video packet indices in mind (i.e., prevent overflow).
                    int videoPacketEndIndex = Math.Min(videoPacketStartIndex + FEC_GROUP_SIZE, videoPackets.Length);

                    // If the parity packet is missing, request all missing video packets and skip the FEC process.
                    // Also request the parity packet if there is a relevant missing video packet.
                    if (parityPackets[parityPacketIndex] == null)
                    {
                        bool parityPacketNeeded = false;
                        for (int videoPacketIndex = videoPacketStartIndex; videoPacketIndex < videoPacketEndIndex; ++videoPacketIndex)
                        {
                            if (videoPackets[videoPacketIndex] == null)
                            {
                                videoPacketIndiecsToRequest.Add(videoPacketIndex);
                                parityPacketNeeded = true;
                            }
                        }
                        if (parityPacketNeeded)
                        {
                            parityPacketIndiecsToRequest.Add(parityPacketIndex);
                        }
                        continue;
                    }

                    // Find if there is existing video packets and missing video packet indices.
                    // Check all video packets that relates to this parity packet.
                    var existingVideoPackets      = new List <VideoSenderPacketData>();
                    var missingVideoPacketIndices = new List <int>();
                    for (int videoPacketIndex = videoPacketStartIndex; videoPacketIndex < videoPacketEndIndex; ++videoPacketIndex)
                    {
                        if (videoPackets[videoPacketIndex] != null)
                        {
                            existingVideoPackets.Add(videoPackets[videoPacketIndex]);
                        }
                        else
                        {
                            missingVideoPacketIndices.Add(videoPacketIndex);
                        }
                    }

                    // Skip if there all video packets already exist.
                    if (missingVideoPacketIndices.Count == 0)
                    {
                        continue;
                    }

                    // XOR based FEC only works for a single missing packet.
                    if (missingVideoPacketIndices.Count > 1)
                    {
                        foreach (int missingIndex in missingVideoPacketIndices)
                        {
                            // Add the missing video packet indices for the vector to request them.
                            videoPacketIndiecsToRequest.Add(missingIndex);
                        }
                        continue;
                    }

                    // The missing video packet index.
                    int missingVideoPacketIndex = missingVideoPacketIndices[0];

                    // Reconstruct the missing video packet.
                    VideoSenderPacketData fecVideoPacketData = new VideoSenderPacketData();
                    fecVideoPacketData.frameId     = frameId;
                    fecVideoPacketData.packetIndex = missingVideoPacketIndex;
                    fecVideoPacketData.packetCount = videoPackets.Length;
                    // Assign from the parity packet here since other video packets will be XOR'ed in the below loop.
                    fecVideoPacketData.messageData = parityPackets[parityPacketIndex].bytes;

                    foreach (var existingVideoPacket in existingVideoPackets)
                    {
                        for (int i = 0; i < fecVideoPacketData.messageData.Length; ++i)
                        {
                            fecVideoPacketData.messageData[i] ^= existingVideoPacket.messageData[i];
                        }
                    }

                    // Insert the reconstructed packet.
                    videoPacketCollections[frameId][missingVideoPacketIndex] = fecVideoPacketData;
                }
                // Request the video packets that FEC was not enough to fix.
                udpSocket.Send(PacketHelper.createRequestReceiverPacketBytes(sessionId, frameId, videoPacketIndiecsToRequest, parityPacketIndiecsToRequest), remoteEndPoint);
            }
        }

        // Find all full collections and their frame_ids.
        var fullFrameIds = new List <int>();

        foreach (var collectionPair in videoPacketCollections)
        {
            bool full = true;
            foreach (var packetData in collectionPair.Value)
            {
                if (packetData == null)
                {
                    full = false;
                    break;
                }
            }

            if (full)
            {
                int frameId = collectionPair.Key;
                fullFrameIds.Add(frameId);
            }
        }

        // Extract messages from the full collections.
        foreach (int fullFrameId in fullFrameIds)
        {
            var ms = new MemoryStream();
            foreach (var packetData in videoPacketCollections[fullFrameId])
            {
                ms.Write(packetData.messageData, 0, packetData.messageData.Length);
            }

            var videoMessageData = VideoSenderMessageData.Parse(ms.ToArray());
            videoMessageList.Add(new Tuple <int, VideoSenderMessageData>(fullFrameId, videoMessageData));

            videoPacketCollections.Remove(fullFrameId);
        }

        // Clean up frame_packet_collections.
        var obsoleteFrameIds = new List <int>();

        foreach (var collectionPair in videoPacketCollections)
        {
            if (collectionPair.Key <= lastVideoFrameId)
            {
                obsoleteFrameIds.Add(collectionPair.Key);
            }
        }

        foreach (int obsoleteFrameId in obsoleteFrameIds)
        {
            videoPacketCollections.Remove(obsoleteFrameId);
        }
    }
        public void Run(KinectReceiver kinectReceiver,
                        ConcurrentQueue <VideoSenderPacketData> videoPacketDataQueue,
                        ConcurrentQueue <FecSenderPacketData> fecPacketDataQueue)
        {
            // The logic for XOR FEC packets are almost the same to frame packets.
            // The operations for XOR FEC packets should happen before the frame packets
            // so that frame packet can be created with XOR FEC packets when a missing
            // frame packet is detected.
            FecSenderPacketData fecSenderPacketData;

            while (fecPacketDataQueue.TryDequeue(out fecSenderPacketData))
            {
                if (fecSenderPacketData.frameId <= kinectReceiver.lastVideoFrameId)
                {
                    continue;
                }

                if (!fecPacketCollections.ContainsKey(fecSenderPacketData.frameId))
                {
                    fecPacketCollections[fecSenderPacketData.frameId] = new FecSenderPacketData[fecSenderPacketData.packetCount];
                }

                fecPacketCollections[fecSenderPacketData.frameId][fecSenderPacketData.packetIndex] = fecSenderPacketData;
            }

            VideoSenderPacketData videoSenderPacketData;

            while (videoPacketDataQueue.TryDequeue(out videoSenderPacketData))
            {
                if (videoSenderPacketData.frameId <= kinectReceiver.lastVideoFrameId)
                {
                    continue;
                }

                // If there is a packet for a new frame, check the previous frames, and if
                // there is a frame with missing packets, try to create them using xor packets.
                // If using the xor packets fails, request the sender to retransmit the packets.
                if (!videoPacketCollections.ContainsKey(videoSenderPacketData.frameId))
                {
                    videoPacketCollections[videoSenderPacketData.frameId] = new VideoSenderPacketData[videoSenderPacketData.packetCount];

                    ///////////////////////////////////
                    // Forward Error Correction Start//
                    ///////////////////////////////////
                    // Request missing packets of the previous frames.
                    foreach (var collectionPair in videoPacketCollections)
                    {
                        if (collectionPair.Key < videoSenderPacketData.frameId)
                        {
                            int missingFrameId = collectionPair.Key;
                            //var missingPacketIndices = collectionPair.Value.GetMissingPacketIds();

                            var missingPacketIndices = new List <int>();
                            for (int i = 0; i < collectionPair.Value.Length; ++i)
                            {
                                if (collectionPair.Value[i] == null)
                                {
                                    missingPacketIndices.Add(i);
                                }
                            }

                            // Try correction using XOR FEC packets.
                            var fecFailedPacketIndices = new List <int>();
                            var fecPacketIndices       = new List <int>();

                            // missing_packet_index cannot get error corrected if there is another missing_packet_index
                            // that belongs to the same XOR FEC packet...
                            foreach (int i in missingPacketIndices)
                            {
                                bool found = false;
                                foreach (int j in missingPacketIndices)
                                {
                                    if (i == j)
                                    {
                                        continue;
                                    }

                                    if ((i / XOR_MAX_GROUP_SIZE) == (j / XOR_MAX_GROUP_SIZE))
                                    {
                                        found = true;
                                        break;
                                    }
                                }
                                if (found)
                                {
                                    fecFailedPacketIndices.Add(i);
                                }
                                else
                                {
                                    fecPacketIndices.Add(i);
                                }
                            }

                            foreach (int fecPacketIndex in fecPacketIndices)
                            {
                                // Try getting the XOR FEC packet for correction.
                                int xorPacketIndex = fecPacketIndex / XOR_MAX_GROUP_SIZE;

                                if (!fecPacketCollections.ContainsKey(missingFrameId))
                                {
                                    fecFailedPacketIndices.Add(fecPacketIndex);
                                    continue;
                                }

                                var fecPacketData = fecPacketCollections[missingFrameId][xorPacketIndex];
                                // Give up if there is no xor packet yet.
                                if (fecPacketData == null)
                                {
                                    fecFailedPacketIndices.Add(fecPacketIndex);
                                    continue;
                                }

                                var fecVideoPacketData = new VideoSenderPacketData();

                                fecVideoPacketData.frameId     = missingFrameId;
                                fecVideoPacketData.packetIndex = videoSenderPacketData.packetIndex;
                                fecVideoPacketData.packetCount = videoSenderPacketData.packetCount;
                                fecVideoPacketData.messageData = fecPacketData.bytes;

                                int beginFramePacketIndex = xorPacketIndex * XOR_MAX_GROUP_SIZE;
                                int endFramePacketIndex   = Math.Min(beginFramePacketIndex + XOR_MAX_GROUP_SIZE, collectionPair.Value.Length);

                                // Run bitwise XOR with all other packets belonging to the same XOR FEC packet.
                                for (int i = beginFramePacketIndex; i < endFramePacketIndex; ++i)
                                {
                                    if (i == fecPacketIndex)
                                    {
                                        continue;
                                    }

                                    for (int j = 0; j < fecVideoPacketData.messageData.Length; ++j)
                                    {
                                        fecVideoPacketData.messageData[j] ^= collectionPair.Value[i].messageData[j];
                                    }
                                }

                                videoPacketCollections[missingFrameId][fecPacketIndex] = fecVideoPacketData;
                            } // end of foreach (int missingPacketIndex in missingPacketIndices)

                            kinectReceiver.udpSocket.Send(PacketHelper.createRequestReceiverPacketBytes(collectionPair.Key, fecFailedPacketIndices));
                        }
                    }
                    /////////////////////////////////
                    // Forward Error Correction End//
                    /////////////////////////////////
                }
                // End of if (frame_packet_collections.find(frame_id) == frame_packet_collections.end())
                // which was for reacting to a packet for a new frame.

                videoPacketCollections[videoSenderPacketData.frameId][videoSenderPacketData.packetIndex] = videoSenderPacketData;
            }

            // Find all full collections and their frame_ids.
            var fullFrameIds = new List <int>();

            foreach (var collectionPair in videoPacketCollections)
            {
                bool full = true;
                foreach (var packetData in collectionPair.Value)
                {
                    if (packetData == null)
                    {
                        full = false;
                        break;
                    }
                }

                if (full)
                {
                    int frameId = collectionPair.Key;
                    fullFrameIds.Add(frameId);
                }
            }

            // Extract messages from the full collections.
            foreach (int fullFrameId in fullFrameIds)
            {
                var ms = new MemoryStream();
                foreach (var packetData in videoPacketCollections[fullFrameId])
                {
                    ms.Write(packetData.messageData, 0, packetData.messageData.Length);
                }

                var videoMessageData = VideoSenderMessageData.Parse(ms.ToArray());
                kinectReceiver.videoMessageQueue.Enqueue(new Tuple <int, VideoSenderMessageData>(fullFrameId, videoMessageData));

                videoPacketCollections.Remove(fullFrameId);
            }

            // Clean up frame_packet_collections.
            var obsoleteFrameIds = new List <int>();

            foreach (var collectionPair in videoPacketCollections)
            {
                if (collectionPair.Key <= kinectReceiver.lastVideoFrameId)
                {
                    obsoleteFrameIds.Add(collectionPair.Key);
                }
            }

            foreach (int obsoleteFrameId in obsoleteFrameIds)
            {
                videoPacketCollections.Remove(obsoleteFrameId);
            }
        }