/// <summary> /// Extract a Int16 from the next bytes in a BufferChunk. /// </summary> /// <param name="bc"></param> /// <returns></returns> private static Int16 NextInt16(BufferChunk bc) { Int16 i = (Int16)bc.NextByte(); i += (Int16)(bc.NextByte() << 8); return(i); }
/// <summary> /// Extract a Int32 from the next bytes in a BufferChunk. /// </summary> /// <param name="bc"></param> /// <returns></returns> private static Int32 NextInt32(BufferChunk bc) { Int32 i = (Int32)bc.NextByte(); i += (Int32)(bc.NextByte() << 8); i += (Int32)(bc.NextByte() << 16); i += (Int32)(bc.NextByte() << 24); return(i); }
/// <summary> /// Converts 3 bytes into a big-endian integer /// </summary> /// <param name="data"></param> /// <returns>Big-endian formatted integer</returns> private static int ThreeBytesToInt(BufferChunk data) { int ret = 0; ret += data.NextByte(); ret += (data.NextByte() << 8); ret += (data.NextByte() << 16); if (((byte)(ret >> 16) & 0x80) == 0x80) { ret += 0xFF; } return(ret); }
/// <summary> /// Deserializes the provided buffer into this object /// </summary> /// <param name="buffer"></param> public void ReadDataFromBuffer(BufferChunk buffer) { Rtcp.SDESType type; while ((type = (Rtcp.SDESType)buffer.NextByte()) != Rtcp.SDESType.END) { switch (type) { case Rtcp.SDESType.CNAME: case Rtcp.SDESType.EMAIL: case Rtcp.SDESType.LOC: case Rtcp.SDESType.NAME: case Rtcp.SDESType.NOTE: case Rtcp.SDESType.PHONE: case Rtcp.SDESType.TOOL: ReadPropertyFromBuffer((int)type, buffer); break; case Rtcp.SDESType.PRIV: ReadPrivatePropertyFromBuffer(buffer); break; default: throw new ApplicationException(string.Format(CultureInfo.CurrentCulture, Strings.UnexpectedSDESType, type)); } } }
/// <summary> /// Converts 3 bytes into a big-endian integer /// </summary> /// <param name="data"></param> /// <returns>Big-endian formatted integer</returns> private static int ThreeBytesToInt(BufferChunk data) { int ret = 0; ret += (data.NextByte() << 1 * 8); ret += (data.NextByte() << 2 * 8); ret += (data.NextByte() << 3 * 8); // If the 8th bit of the second byte (what will be the 24th bit) // is turned on, the value is signed, so sign extend our integer if (((byte)(ret >> 1 * 8) & 0x80) == 0x80) { ret += 0xFF; } return(ret); }
private void ReadPrivatePropertyFromBuffer(BufferChunk buffer) { byte totalLength = buffer.NextByte(); byte prefixLength = buffer.NextByte(); int dataLength = totalLength - prefixLength - 1; // The cast to byte[] does a copy byte[] prefix = (byte[])buffer.NextBufferChunk(prefixLength); byte[] data = null; if (dataLength > 0) { // The cast to byte[] does a copy data = (byte[])buffer.NextBufferChunk(dataLength); } privs[prefix] = data; }
public void ReadDataFromBuffer(BufferChunk buffer) { SSRC = buffer.NextUInt32(); FractionLost = buffer.NextByte(); PacketsLost = ThreeBytesToInt(buffer.NextBufferChunk(3)); ExtendedHighestSequence = buffer.NextUInt32(); Jitter = buffer.NextUInt32(); LastSenderReport = buffer.NextUInt32(); DelaySinceLastSenderReport = buffer.NextUInt32(); }
private void ReadPropertyFromBuffer(int type, BufferChunk buffer) { int dataLength = buffer.NextByte(); if (dataLength != 0) { data[type] = (byte[])buffer.NextBufferChunk(dataLength); } else // Clear value { data[type] = null; } }
/// <summary> /// Fill in the audio-specific parts of the MediaType from the data in the BufferChunk. /// Also return the compression data which is the remaining bytes at the end of the byte[]. /// </summary> /// <param name="mt"></param> /// <param name="bc"></param> /// <param name="compressionData"></param> public static void ReconstituteAudioFormat(MediaTypeWaveFormatEx mt, BufferChunk bc, out byte[] compressionData) { mt.WaveFormatEx.FormatTag = (ushort)NextInt16(bc); mt.WaveFormatEx.Channels = (ushort)NextInt16(bc); mt.WaveFormatEx.SamplesPerSec = (uint)NextInt32(bc); mt.WaveFormatEx.AvgBytesPerSec = (uint)NextInt32(bc); mt.WaveFormatEx.BlockAlign = (ushort)NextInt16(bc); mt.WaveFormatEx.BitsPerSample = (ushort)NextInt16(bc); mt.WaveFormatEx.Size = (ushort)NextInt16(bc); compressionData = new byte[mt.WaveFormatEx.Size]; for (int i = 0; i < mt.WaveFormatEx.Size; i++) { compressionData[i] = bc.NextByte(); } }
/// <summary> /// Fill in the video-specific parts of the MediaType from the data in the BufferChunk. /// Also return the compression data which is the remaining bytes at the end of the byte[]. /// </summary> /// <param name="mt"></param> /// <param name="bc"></param> /// <param name="compressionData"></param> public static void ReconstituteVideoFormat(MediaTypeVideoInfo mt, BufferChunk bc, out byte[] compressionData) { VIDEOINFOHEADER vi; RECT s; s.left = NextInt32(bc); s.top = NextInt32(bc); s.right = NextInt32(bc); s.bottom = NextInt32(bc); vi.Source = s; RECT t; t.left = NextInt32(bc); t.top = NextInt32(bc); t.right = NextInt32(bc); t.bottom = NextInt32(bc); vi.Target = t; vi.BitRate = (uint)NextInt32(bc); vi.BitErrorRate = (uint)NextInt32(bc); vi.AvgTimePerFrame = bc.NextUInt64(); BITMAPINFOHEADER bih; bih.Size = (uint)NextInt32(bc); bih.Width = NextInt32(bc); bih.Height = NextInt32(bc); bih.Planes = (ushort)NextInt16(bc); bih.BitCount = (ushort)NextInt16(bc); bih.Compression = (uint)NextInt32(bc); bih.SizeImage = (uint)NextInt32(bc); bih.XPelsPerMeter = NextInt32(bc); bih.YPelsPerMeter = NextInt32(bc); bih.ClrUsed = (uint)NextInt32(bc); bih.ClrImportant = (uint)NextInt32(bc); vi.BitmapInfo = bih; mt.VideoInfo = vi; compressionData = new byte[bc.Length]; for (int i = 0; i < compressionData.Length; i++) { compressionData[i] = bc.NextByte(); } }
/// <summary> /// Deserializes the provided buffer into this object /// </summary> /// <param name="buffer"></param> public override void ReadDataFromBuffer(BufferChunk buffer) { SDESType type; while ((type = (SDESType)buffer.NextByte()) != SDESType.END) { switch (type) { case SDESType.CNAME: case SDESType.EMAIL: case SDESType.LOC: case SDESType.NAME: case SDESType.NOTE: case SDESType.PHONE: case SDESType.TOOL: ReadPropertyFromBuffer((int)type, buffer); break; case SDESType.PRIV: ReadPrivatePropertyFromBuffer(buffer); break; default: throw new ApplicationException(string.Format(CultureInfo.CurrentCulture, Strings.UnexpectedSDESType, type)); } } }
private void HandleInvalidPacket(BufferChunk packet, IPEndPoint src, string exception) { rtpSession.RaiseInvalidPacketEvent(string.Format("First byte: {0}, Source IP: {1}, " + "Exception: {2}", packet.NextByte(), src, exception)); }
/// <summary> /// Converts buffer into member data /// </summary> /// <param name="packet"></param> public override void ReadDataFromBuffer(BufferChunk buffer) { // Read SSRCs for(int i = 0; i < Header.ItemCount; i++) { ssrcs.Add(buffer.NextUInt32()); } // Determine if there is a reason... // SSRCs are 32 bits each, Length is number of 32 bit words in packet data if(Header.Length > Header.ItemCount) { reason = (byte[])buffer.NextBufferChunk(buffer.NextByte()); } }
private void ReadPrivatePropertyFromBuffer(BufferChunk buffer) { byte totalLength = buffer.NextByte(); byte prefixLength = buffer.NextByte(); int dataLength = totalLength - prefixLength - 1; // The cast to byte[] does a copy byte[] prefix = (byte[])buffer.NextBufferChunk(prefixLength); byte[] data = null; if(dataLength > 0) { // The cast to byte[] does a copy data = (byte[])buffer.NextBufferChunk(dataLength); } privs[prefix] = data; }
private void ReadPropertyFromBuffer(int type, BufferChunk buffer) { int dataLength = buffer.NextByte(); if(dataLength != 0) { data[type] = (byte[])buffer.NextBufferChunk(dataLength); } else // Clear value { data[type] = null; } }
/// <summary> /// Deserializes the provided buffer into this object /// </summary> /// <param name="buffer"></param> public void ReadDataFromBuffer(BufferChunk buffer) { Rtcp.SDESType type; while((type = (Rtcp.SDESType)buffer.NextByte()) != Rtcp.SDESType.END) { switch(type) { case Rtcp.SDESType.CNAME: case Rtcp.SDESType.EMAIL: case Rtcp.SDESType.LOC: case Rtcp.SDESType.NAME: case Rtcp.SDESType.NOTE: case Rtcp.SDESType.PHONE: case Rtcp.SDESType.TOOL: ReadPropertyFromBuffer((int)type, buffer); break; case Rtcp.SDESType.PRIV: ReadPrivatePropertyFromBuffer(buffer); break; default: throw new ApplicationException("Unexpected SDES type: " + type); } } }
/// <summary> /// Converts 3 bytes into a big-endian integer /// </summary> /// <param name="data"></param> /// <returns>Big-endian formatted integer</returns> private static int ThreeBytesToInt(BufferChunk data) { int ret = 0; ret += (data.NextByte() << 1 * 8); ret += (data.NextByte() << 2 * 8); ret += (data.NextByte() << 3 * 8); // If the 8th bit of the second byte (what will be the 24th bit) // is turned on, the value is signed, so sign extend our integer if(((byte)(ret >> 1 * 8) & 0x80) == 0x80) { ret += 0xFF; } return ret; }
/// <summary> /// Converts 3 bytes into a big-endian integer /// </summary> /// <param name="data"></param> /// <returns>Big-endian formatted integer</returns> private static int ThreeBytesToInt(BufferChunk data) { int ret = 0; ret += data.NextByte(); ret += (data.NextByte() << 8); ret += (data.NextByte() << 16); if(((byte)(ret >> 16) & 0x80) == 0x80) { ret += 0xFF; } return ret; }
/// <summary> /// Read the next sample at the given timestamp (or within the FUDGE_FACTOR range.) /// Return zero if there is no sample available for this timestamp. /// </summary> /// <param name="bitsPerSample"></param> /// <returns></returns> public long ReadSample(int bytesPerSample, long timestamp) { if ((buffer == null) || (buffer.Length < bytesPerSample)) { if ((buffer != null) && (buffer.Length > 0)) { //Debug.WriteLine("."); Debug.WriteLine("Warning: An audio chunk appeared to contain a fractional part of a sample which will be discarded."); } FillBuffer(); } if (exhausted) { return(0); } bool convertToStereo = false; bool convertToMono = false; if (currentChannels != targetChannels) { if (targetChannels == 2) { convertToStereo = true; } else { convertToMono = true; } } long sampleAsLong = 0; if (Math.Abs(nextTimestamp - timestamp) < FUDGE_FACTOR) { nextTimestamp += this.ticksPerSample; if ((convertToStereo) && (sampleCounter % 2 == 1)) { sampleAsLong = previousSample; } else { switch (bytesPerSample) { case 1: sampleAsLong = buffer.NextByte(); if (convertToMono) { sampleAsLong += buffer.NextByte(); sampleAsLong = sampleAsLong / 2; } break; case 2: sampleAsLong = BitConverter.ToInt16(buffer.Buffer, buffer.Index); //Note that NextInt16, NextInt32 assume the wrong byte order. We just use them to //update the BufferChunk.Index and Length. buffer.NextInt16(); if (convertToMono) { sampleAsLong += BitConverter.ToInt16(buffer.Buffer, buffer.Index); buffer.NextInt16(); sampleAsLong = sampleAsLong / 2; } break; case 4: sampleAsLong = BitConverter.ToInt32(buffer.Buffer, buffer.Index); buffer.NextInt32(); if (convertToMono) { sampleAsLong += BitConverter.ToInt32(buffer.Buffer, buffer.Index); buffer.NextInt32(); sampleAsLong = sampleAsLong / 2; } break; default: break; } } } this.previousSample = sampleAsLong; this.sampleCounter++; return(sampleAsLong); }
private void HandleInvalidPacket(BufferChunk packet, IPEndPoint src, string exception) { rtpSession.RaiseInvalidPacketEvent(string.Format(CultureInfo.CurrentCulture, "First byte: {0}, Source IP: {1}, Exception: {2}", packet.NextByte(), src, exception)); }
override public void Run() { BufferChunk bc = new BufferChunk(7); short s = 25000; int i = 545434; byte b = 56; bc += s; bc += i; bc += b; if (bc.NextInt16() != s) throw new TestCaseException("Short failed for " + s); if (bc.NextInt32() != i) throw new TestCaseException("Int failed for " + i); if (bc.NextByte() != b) throw new TestCaseException("Byte failed for " + b); bc.Reset(); s = short.MaxValue; i = int.MaxValue; b = byte.MaxValue; bc += s; bc += i; bc += b; if (bc.NextInt16() != s) throw new TestCaseException("Short failed for " + s); if (bc.NextInt32() != i) throw new TestCaseException("Int failed for " + i); if (bc.NextByte() != b) throw new TestCaseException("Byte failed for " + b); bc.Reset(); s = short.MinValue; i = int.MinValue; b = byte.MinValue; bc += s; bc += i; bc += b; if (bc.NextInt16() != s) throw new TestCaseException("Short failed for " + s); if (bc.NextInt32() != i) throw new TestCaseException("Int failed for " + i); if (bc.NextByte() != b) throw new TestCaseException("Byte failed for " + b); }
override public void Run() { BufferChunk bc = new BufferChunk(7); short s = 25000; int i = 545434; byte b = 56; bc += s; bc += i; bc += b; if (bc.NextInt16() != s) { throw new TestCaseException("Short failed for " + s); } if (bc.NextInt32() != i) { throw new TestCaseException("Int failed for " + i); } if (bc.NextByte() != b) { throw new TestCaseException("Byte failed for " + b); } bc.Reset(); s = short.MaxValue; i = int.MaxValue; b = byte.MaxValue; bc += s; bc += i; bc += b; if (bc.NextInt16() != s) { throw new TestCaseException("Short failed for " + s); } if (bc.NextInt32() != i) { throw new TestCaseException("Int failed for " + i); } if (bc.NextByte() != b) { throw new TestCaseException("Byte failed for " + b); } bc.Reset(); s = short.MinValue; i = int.MinValue; b = byte.MinValue; bc += s; bc += i; bc += b; if (bc.NextInt16() != s) { throw new TestCaseException("Short failed for " + s); } if (bc.NextInt32() != i) { throw new TestCaseException("Int failed for " + i); } if (bc.NextByte() != b) { throw new TestCaseException("Byte failed for " + b); } }