Пример #1
0
        public static byte[] SetHeaderChecksum(byte[] bytes)
        {
            ushort dataOffset = BigEndianConverter.ReadUInt16(bytes, 6);
            ushort checksum   = CheckSum(bytes, dataOffset - 2, 0);

            return(Utils.ReplaceRange(bytes, BigEndianConverter.GetBytes((ushort)(checksum)), dataOffset - 2));
        }
        private void ParseMTAP(ArraySegment <byte> byteSegment, int tsOffsetFieldSize,
                               bool markerBit)
        {
            Debug.Assert(byteSegment.Array != null, "byteSegment.Array != null");

            int startOffset = byteSegment.Offset;
            int endOffset   = byteSegment.Offset + byteSegment.Count;

            startOffset += 1 + DecodingOrderNumberFieldSize;

            if (startOffset >= endOffset)
            {
#if DEBUG
                Console.WriteLine($"[H264VideoPayloadParser] No data to write for MTAP packet.");
#endif
            }

            while (startOffset < endOffset)
            {
                int nalUnitSize = BigEndianConverter.ReadUInt16(byteSegment.Array, startOffset);

                startOffset += 2 + DondFieldSize + tsOffsetFieldSize;

                var nalUnitSegment = new ArraySegment <byte>(byteSegment.Array, startOffset, nalUnitSize);

                startOffset += nalUnitSize;

                _h264Parser.Parse(nalUnitSegment, markerBit && startOffset >= endOffset);
            }
        }
Пример #3
0
        public static IEnumerable <RtcpPacket> Parse(ArraySegment <byte> byteSegment)
        {
            Debug.Assert(byteSegment.Array != null, "byteSegment.Array != null");

            int offset      = byteSegment.Offset;
            int totalLength = byteSegment.Count;

            while (totalLength > 0)
            {
                int value       = byteSegment.Array[offset++];
                int version     = value >> 6;
                int padding     = (value >> 5) & 1;
                int sourceCount = value & 0x1F;

                int payloadType = byteSegment.Array[offset++];
                int dwordLength = BigEndianConverter.ReadUInt16(byteSegment.Array, offset);
                offset += 2;

                int payloadLength = dwordLength * 4;

                if (payloadLength > totalLength - 4)
                {
                    throw new ArgumentException(
                              "Invalid RTCP packet size. It seems that data segment contains bad data", nameof(byteSegment));
                }

                RtcpPacket packet;

                if (payloadType == 200)
                {
                    packet = new RtcpSenderReportPacket();
                }
                else if (payloadType == 203)
                {
                    packet = new RtcpByePacket();
                }
                else
                {
                    offset      += payloadLength;
                    totalLength -= 4 + payloadLength;
                    continue;
                }

                packet.ProtocolVersion = version;
                packet.PaddingFlag     = padding != 0;
                packet.SourceCount     = sourceCount;
                packet.PayloadType     = payloadType;
                packet.DwordLength     = dwordLength;
                packet.Length          = (dwordLength + 1) * 4;

                var segment = new ArraySegment <byte>(byteSegment.Array, offset, payloadLength);
                packet.FillFromByteSegment(segment);

                yield return(packet);

                offset      += payloadLength;
                totalLength -= 4 + payloadLength;
            }
        }
Пример #4
0
        public static bool TryParse(ArraySegment <byte> byteSegment, out RtpPacket rtpPacket)
        {
            rtpPacket = new RtpPacket();

            Debug.Assert(byteSegment.Array != null, "byteSegment.Array != null");

            if (byteSegment.Count < RtpHeaderSize)
            {
                return(false);
            }

            int offset = byteSegment.Offset;

            rtpPacket.ProtocolVersion = byteSegment.Array[offset] >> 6;

            if (rtpPacket.ProtocolVersion != RtpProtocolVersion)
            {
                return(false);
            }

            rtpPacket.PaddingFlag   = (byteSegment.Array[offset] >> 5 & 1) != 0;
            rtpPacket.ExtensionFlag = (byteSegment.Array[offset] >> 4 & 1) != 0;
            rtpPacket.CsrcCount     = byteSegment.Array[offset++] & 0xF;

            rtpPacket.MarkerBit   = byteSegment.Array[offset] >> 7 != 0;
            rtpPacket.PayloadType = byteSegment.Array[offset++] & 0x7F;

            rtpPacket.SeqNumber = (ushort)BigEndianConverter.ReadUInt16(byteSegment.Array, offset);
            offset += 2;

            rtpPacket.Timestamp = BigEndianConverter.ReadUInt32(byteSegment.Array, offset);
            offset += 4;

            //Debug.WriteLine(rtpPacket.Timestamp);

            rtpPacket.SyncSourceId = BigEndianConverter.ReadUInt32(byteSegment.Array, offset);
            offset += 4 + 4 * rtpPacket.CsrcCount;

            if (rtpPacket.ExtensionFlag)
            {
                rtpPacket.ExtensionHeaderId = BigEndianConverter.ReadUInt16(byteSegment.Array, offset);
                offset += 2;

                int extensionHeaderLength = BigEndianConverter.ReadUInt16(byteSegment.Array, offset) * 4;
                offset += 2 + extensionHeaderLength;
            }

            int payloadSize = byteSegment.Offset + byteSegment.Count - offset;

            if (rtpPacket.PaddingFlag)
            {
                int paddingBytes = byteSegment.Array[byteSegment.Offset + byteSegment.Count - 1];
                payloadSize -= paddingBytes;
            }

            rtpPacket.PayloadSegment = new ArraySegment <byte>(byteSegment.Array, offset, payloadSize);
            return(true);
        }
        public void ReadUInt16_TestBuffer_ReturnsCorrectInt()
        {
            int expected = 0x33 << 8 | 0x44;
            var buffer   = new byte[] { 0x33, 0x44 };

            int result = BigEndianConverter.ReadUInt16(buffer, 0);

            Assert.AreEqual(expected, result);
        }
Пример #6
0
        public async Task <TpktPayload> ReadAsync()
        {
            int nextTpktPositon = await FindNextPacketAsync();

            int usefulDataSize = _nonParsedDataSize - nextTpktPositon;

            if (nextTpktPositon != 0)
            {
                Buffer.BlockCopy(_readBuffer, nextTpktPositon, _readBuffer, 0, usefulDataSize);
            }

            int readCount = TpktHeader.Size - usefulDataSize;

            if (readCount > 0)
            {
                await _stream.ReadExactAsync(_readBuffer, usefulDataSize, readCount);

                usefulDataSize = 0;
            }
            else
            {
                usefulDataSize = -readCount;
            }

            int channel     = _readBuffer[1];
            int payloadSize = BigEndianConverter.ReadUInt16(_readBuffer, 2);
            int totalSize   = TpktHeader.Size + payloadSize;

            if (_readBuffer.Length < totalSize)
            {
                int alignedTotalSize = SystemMemory.RoundToPageAlignmentSize(totalSize);
                Array.Resize(ref _readBuffer, alignedTotalSize);
            }

            readCount = payloadSize - usefulDataSize;

            if (readCount > 0)
            {
                await _stream.ReadExactAsync(_readBuffer, TpktHeader.Size + usefulDataSize, readCount);

                _nonParsedDataSize = 0;
            }
            else
            {
                _nonParsedDataSize   = -readCount;
                _nonParsedDataOffset = totalSize;
            }

            var payloadSegment = new ArraySegment <byte>(_readBuffer, TpktHeader.Size, payloadSize);

            return(new TpktPayload(channel, payloadSegment));
        }
        public override void Parse(TimeSpan timeOffset, ArraySegment <byte> byteSegment, bool markerBit)
        {
            int auHeadersBitLength   = BigEndianConverter.ReadUInt16(byteSegment.Array, byteSegment.Offset);
            int auHeadersLengthBytes = (auHeadersBitLength + 7) / 8;

            int headerBitSize  = _codecInfo.SizeLength + _codecInfo.IndexLength;
            int audioBitsAvail = auHeadersBitLength - headerBitSize;

            if (audioBitsAvail < 0 || headerBitSize <= 0)
            {
                return;
            }

            int framesCount = 1 + audioBitsAvail / (_codecInfo.SizeLength + _codecInfo.IndexDeltaLength);

            _bitStreamReader.ReInitialize(byteSegment.SubSegment(2));

            int offset = byteSegment.Offset + auHeadersLengthBytes;

            for (int i = 0; i < framesCount; ++i)
            {
                int frameSize = _bitStreamReader.ReadBits(_codecInfo.SizeLength);

                if (i == 0)
                {
                    _bitStreamReader.ReadBits(_codecInfo.IndexLength);
                }
                else if (_codecInfo.IndexDeltaLength != 0)
                {
                    _bitStreamReader.ReadBits(_codecInfo.IndexDeltaLength);
                }

                Debug.Assert(byteSegment.Array != null, "byteSegment.Array != null");
                var frameBytes = new ArraySegment <byte>(byteSegment.Array, offset, frameSize);

                DateTime timestamp = GetFrameTimestamp(timeOffset);

                var aacFrame = new RawAACFrame(timestamp, frameBytes,
                                               new ArraySegment <byte>(_codecInfo.ConfigBytes));

                OnFrameGenerated(aacFrame);
                offset += frameSize;
            }
        }
Пример #8
0
        public HcaMetadata(byte[] hcaBytes)
        {
            Channels     = 0;
            SampleRate   = 0;
            BlockCount   = 0;
            LoopStart    = 0;
            LoopEnd      = 0;
            Loop_r01     = 0;
            Loop_r02     = 0;
            HasLoopData  = false;
            ValidHcaFile = false;

            if (hcaBytes != null)
            {
                if (BitConverter.ToInt32(hcaBytes, 0) != HCA_SIGNATURE)
                {
                    return;
                }

                ValidHcaFile = true;
                int dataOffset = BigEndianConverter.ReadUInt16(hcaBytes, 6);
                int fmtOffset  = hcaBytes.IndexOfValue(FMT_SIGNATURE, 0, dataOffset, false);
                int loopOffset = hcaBytes.IndexOfValue(LOOP_SIGNATURE, 0, dataOffset, false);

                //Load fmt
                if (hcaBytes.Length > fmtOffset + 16 && fmtOffset != -1)
                {
                    Channels   = hcaBytes[fmtOffset + 4];
                    SampleRate = BigEndianConverter.ReadUInt16(hcaBytes, fmtOffset + 6);
                    BlockCount = BigEndianConverter.ReadInt32(hcaBytes, fmtOffset + 8);
                }

                //Load loop
                if (hcaBytes.Length > loopOffset + 16 && loopOffset != -1)
                {
                    HasLoopData = true;
                    LoopStart   = BigEndianConverter.ReadUInt32(hcaBytes, loopOffset + 4);
                    LoopEnd     = BigEndianConverter.ReadUInt32(hcaBytes, loopOffset + 8);
                    Loop_r01    = BigEndianConverter.ReadUInt16(hcaBytes, loopOffset + 12);
                    Loop_r02    = BigEndianConverter.ReadUInt16(hcaBytes, loopOffset + 14);
                }
            }
        }
        private void ParseSTAP(ArraySegment <byte> byteSegment, int donFieldSize,
                               bool markerBit)
        {
            Debug.Assert(byteSegment.Array != null, "byteSegment.Array != null");

            int startOffset = byteSegment.Offset + 1 + donFieldSize;
            int endOffset   = byteSegment.Offset + byteSegment.Count;

            while (startOffset < endOffset)
            {
                int nalUnitSize = BigEndianConverter.ReadUInt16(byteSegment.Array, startOffset);

                startOffset += 2;

                var nalUnitSegment = new ArraySegment <byte>(byteSegment.Array, startOffset, nalUnitSize);

                startOffset += nalUnitSize;

                _h264Parser.Parse(nalUnitSegment, true, markerBit && startOffset >= endOffset);
            }
        }
        private void ParseMTAP(ArraySegment <byte> byteSegment, int tsOffsetFieldSize,
                               bool markerBit)
        {
            Debug.Assert(byteSegment.Array != null, "byteSegment.Array != null");

            int startOffset = byteSegment.Offset;
            int endOffset   = byteSegment.Offset + byteSegment.Count;

            startOffset += 1 + DecodingOrderNumberFieldSize;

            while (startOffset < endOffset)
            {
                int nalUnitSize = BigEndianConverter.ReadUInt16(byteSegment.Array, startOffset);

                startOffset += 2 + DondFieldSize + tsOffsetFieldSize;

                var nalUnitSegment = new ArraySegment <byte>(byteSegment.Array, startOffset, nalUnitSize);

                startOffset += nalUnitSize;

                _h264Parser.Parse(nalUnitSegment, true, markerBit && startOffset >= endOffset);
            }
        }
Пример #11
0
        public TrackMetadata(byte[] bytes)
        {
            IsValidAudioFile = false;
            Channels         = 0;
            SampleRate       = 0;
            NumSamples       = 0;

            try
            {
                if (BitConverter.ToUInt16(bytes, 0) == ADX_SIGNATURE)
                {
                    //Is ADX
                    IsValidAudioFile = true;
                    Channels         = bytes[7];
                    SampleRate       = BigEndianConverter.ReadUInt32(bytes, 8);
                    NumSamples       = BigEndianConverter.ReadUInt32(bytes, 12);
                }
                else if (BitConverter.ToInt32(bytes, 0) == HCA_SIGNATURE)
                {
                    IsValidAudioFile = true;
                    int dataOffset = BigEndianConverter.ReadUInt16(bytes, 6);
                    int fmtOffset  = bytes.IndexOfValue(FMT_SIGNATURE, 0, dataOffset, false);

                    if (fmtOffset != -1)
                    {
                        Channels   = bytes[fmtOffset + 4];
                        SampleRate = BigEndianConverter.ReadUInt16(bytes, fmtOffset + 6);
                        int blockCount = BigEndianConverter.ReadInt32(bytes, fmtOffset + 8);
                        NumSamples = (uint)(blockCount * 1024);
                    }
                }
                else
                {
                    //DSP, which has no signature... thanks nintendo!
                    NumSamples = BigEndianConverter.ReadUInt32(bytes, 0);
                    SampleRate = BigEndianConverter.ReadUInt32(bytes, 8);
                    Channels   = (byte)BigEndianConverter.ReadUInt16(bytes, 74);

                    if (Channels == 0)
                    {
                        Channels = 1;
                    }
                }
            }
            catch
            {
                IsValidAudioFile = false;
                Channels         = 0;
                SampleRate       = 0;
                NumSamples       = 0;
            }

            if (Channels > 10 || SampleRate < 0 || NumSamples < 0)
            {
                //Values make no sense
                IsValidAudioFile = false;
                Channels         = 0;
                SampleRate       = 0;
                NumSamples       = 0;
            }
        }
        public override void Parse(TimeSpan timeOffset, ArraySegment <byte> byteSegment, bool markerBit)
        {
            Debug.Assert(byteSegment.Array != null, "byteSegment.Array != null");

            if (byteSegment.Count < JpegHeaderSize)
            {
                throw new MediaPayloadParserException("Input data size is smaller than JPEG header size");
            }

            int offset = byteSegment.Offset + 1;

            int fragmentOffset = BigEndianConverter.ReadUInt24(byteSegment.Array, offset);

            offset += 3;

            int type   = byteSegment.Array[offset++];
            int q      = byteSegment.Array[offset++];
            int width  = byteSegment.Array[offset++] * 8;
            int height = byteSegment.Array[offset++] * 8;
            int dri    = 0;

            if (type > 63)
            {
                dri     = BigEndianConverter.ReadUInt16(byteSegment.Array, offset);
                offset += 4;
            }

            if (fragmentOffset == 0)
            {
                if (_frameBuffer.CountData != 0)
                {
                    GenerateFrame(timeOffset);
                }

                bool quantizationTablesChanged = false;

                if (q > 127)
                {
                    int mbz = byteSegment.Array[offset];

                    if (mbz == 0)
                    {
                        _hasExternalQuantizationTable = true;

                        int quantizationTablesLength = BigEndianConverter.ReadUInt16(byteSegment.Array, offset + 2);
                        offset += 4;

                        if (!ArrayUtils.IsBytesEquals(byteSegment.Array, offset, quantizationTablesLength,
                                                      _quantizationTables, 0, _quantizationTablesLength))
                        {
                            if (_quantizationTables.Length < quantizationTablesLength)
                            {
                                _quantizationTables = new byte[quantizationTablesLength];
                            }

                            Buffer.BlockCopy(byteSegment.Array, offset, _quantizationTables, 0,
                                             quantizationTablesLength);
                            _quantizationTablesLength = quantizationTablesLength;
                            quantizationTablesChanged = true;
                        }

                        offset += quantizationTablesLength;
                    }
                }

                if (quantizationTablesChanged || _currentType != type || _currentQ != q ||
                    _currentFrameWidth != width || _currentFrameHeight != height || _currentDri != dri)
                {
                    _currentType        = type;
                    _currentQ           = q;
                    _currentFrameWidth  = width;
                    _currentFrameHeight = height;
                    _currentDri         = dri;

                    ReInitializeJpegHeader();
                }

                _frameBuffer.AddBytes(_jpegHeaderBytesSegment);
            }

            if (fragmentOffset != 0 && _frameBuffer.CountData == 0)
            {
                return;
            }

            int dataSize = byteSegment.Offset + byteSegment.Count - offset;

            if (dataSize < 0)
            {
                throw new MediaPayloadParserException($"Invalid payload size: {dataSize}");
            }

            _frameBuffer.AddBytes(new ArraySegment <byte>(byteSegment.Array, offset, dataSize));
        }
Пример #13
0
        /// <summary>
        /// Set or remove a HCA loop.
        /// </summary>
        /// <param name="hcaBytes">The hca file.</param>
        /// <param name="loop">If false, any loop data in the hca file will be removed. If none exists then nothing will happen.</param>
        /// <param name="loopStart">The start of the desired loop, in seconds.</param>
        /// <param name="loopEnd">The end of the loop, in seconds.</param>
        /// <param name="numLoops">The number of loops. (The game seems to ignore this... so just use 0)</param>
        /// <returns></returns>
        public static byte[] SetLoop(byte[] hcaBytes, bool loop, double loopStart, double loopEnd, int numLoops = 0)
        {
            if (loopStart > loopEnd || numLoops < 0)
            {
                return(hcaBytes);
            }
            if (loopStart < 0.0)
            {
                loopStart = 0.0;
            }

            HcaMetadata metadata = new HcaMetadata(hcaBytes);

            if (!metadata.ValidHcaFile)
            {
                throw new InvalidOperationException("SetLoop: the provided file is not a valid HCA file.");
            }

            ushort dataOffset = BigEndianConverter.ReadUInt16(hcaBytes, 6);
            int    loopIndex  = hcaBytes.IndexOfValue(LOOP_SIGNATURE, 0, dataOffset, false);

            if (!loop)
            {
                if (loopIndex == -1)
                {
                    return(hcaBytes);
                }

                //Remove loop and return
                List <byte> bytes = hcaBytes.ToList();
                bytes.RemoveRange(loopIndex, 16);

                //Adjust dataOffset
                dataOffset -= 16;

                hcaBytes = bytes.ToArray();
            }
            else
            {
                uint loopStartBlocks = SecondsToBlocks(loopStart, metadata.SampleRate);
                uint loopEndBlocks   = SecondsToBlocks(loopEnd, metadata.SampleRate);

                if (loopEndBlocks >= metadata.BlockCount || loopEnd < 0)
                {
                    loopEndBlocks = (uint)(metadata.BlockCount - 1);
                }
                if (loopStartBlocks < 0 || loopStartBlocks > metadata.BlockCount)
                {
                    loopStartBlocks = 0;
                }

                int loopCount = (numLoops == 0 && numLoops < 0x80) ? 0x80 : numLoops;

                List <byte> newLoop = new List <byte>();
                newLoop.AddRange(BitConverter.GetBytes(LOOP_SIGNATURE));
                newLoop.AddRange(BigEndianConverter.GetBytes(loopStartBlocks));
                newLoop.AddRange(BigEndianConverter.GetBytes(loopEndBlocks));
                newLoop.AddRange(BigEndianConverter.GetBytes((ushort)loopCount));
                newLoop.AddRange(BigEndianConverter.GetBytes((ushort)0x400));


                if (loopIndex != -1)
                {
                    hcaBytes = Utils.ReplaceRange(hcaBytes, newLoop.ToArray(), loopIndex);
                }
                else
                {
                    List <byte> bytes = hcaBytes.ToList();
                    bytes.InsertRange(IndexOfLoopBlock(hcaBytes, dataOffset), newLoop);
                    hcaBytes = bytes.ToArray();

                    //Adjust dataOffset
                    dataOffset += 16;
                }
            }

            //Update header size
            hcaBytes = Utils.ReplaceRange(hcaBytes, BigEndianConverter.GetBytes((ushort)(dataOffset)), 6);

            //Set checksum
            hcaBytes = SetHeaderChecksum(hcaBytes);

            return(hcaBytes);
        }