private FrameBlock GetBlockFromImage(byte[] image, int blockX, int blockY) { FrameBlock block = frameBlockPool.GetNext(); block.BlockX = (byte)blockX; if (stride <= 0) { block.BlockY = (byte)(verticalBlocks - blockY - 1); // Reverse the y-axis because the image is upside down. } else { block.BlockY = (byte)blockY; } int startingOffset = (blockX * BlockSizeInBytes) + (blockY * horizontalBlocks * TotalBlockSizeInBytes); for (int line = 0; line < BlockSize; line++) { int sampleLine; if (stride <= 0) { sampleLine = BlockSize - line - 1; // Reverse the y axis because the image is upside down. } else { sampleLine = line; } int sourceStartPos = startingOffset + (sampleLine * widthInBytes); int destStartPos = line * BlockSizeInBytes; Buffer.BlockCopy(image, sourceStartPos, block.RgbaRaw, destStartPos, BlockSizeInBytes); } return(block); }
public void WriteSamples(Array samples, int start, int dataLength, ushort sequenceNumber, AudioCodecType audioCodecType, bool isSilent) { // Only write the frame to the queue if it's newer than the most recently played frame. // This particular way of checking will miss some out-of-order packets if they occur right when a wrap-around // is happening, but not many. if (sequenceNumber > _lastSequenceNumberRead || _lastSequenceNumberRead < lowEndWrapAround || _lastSequenceNumberRead > highEndWrapAround || sequenceNumber < lowEndWrapAround || sequenceNumber > highEndWrapAround) { var entry = _entryPool.GetNext(); Buffer.BlockCopy(samples, start, entry.Frame, 0, dataLength); entry.DataLength = dataLength / sizeof(short); entry.SequenceNumber = sequenceNumber; entry.AudioCodecType = audioCodecType; entry.IsSilent = isSilent; lock (_queue) { _queue.Enqueue(entry); } _logger.LogWrite(); } else { _logger.LogWriteOutOfOrder(); } }
public FrameBlock[] ParseChunk(ByteStream chunk, ushort remoteSsrcId) { byte numBlocks = chunk.Data[0]; // ks 7/18/11 - This seems like an odd place to do it, but I can't think of a better one. _videoQualityController.LogReceivedVideoQuality(remoteSsrcId, (VideoQuality)chunk.Data[1], (VideoQuality)chunk.Data[2]); byte jpegQuality = chunk.Data[3]; Debug.Assert(jpegQuality > 0 && jpegQuality <= 100); chunk.CurrentOffset = ChunkHeaderLength; var blocks = new FrameBlock[numBlocks]; for (int i = 0; i < numBlocks; i++) { var block = _frameBlockPool.GetNext(); block.JpegQuality = jpegQuality; block.BlockX = chunk.ReadByte(); block.BlockY = chunk.ReadByte(); block.BlockType = (BlockType)chunk.ReadByte(); short payloadLength = chunk.ReadInt16(); Debug.Assert(payloadLength > 0, "The payloadLength must be greater than 0"); block.EncodedStream = new MemoryStream(chunk.Data, chunk.CurrentOffset, payloadLength); chunk.CurrentOffset += payloadLength; blocks[i] = block; } return(blocks); }
public static List <RtpPacketData> GetPacketsFromData(ByteStream buffer, IObjectPool <List <RtpPacketData> > rtpPacketDataListPool, IObjectPool <RtpPacketData> rtpPacketDataPool) { // Retrieve the list from an object pool (rather than creating a new one each time that has to be garbage-collected). var packets = rtpPacketDataListPool.GetNext(); while (buffer.CurrentOffset < buffer.EndOffset) { RtpPacketData packet = rtpPacketDataPool.GetNext(); RtpParseResult result = packet.ParsePacket(buffer); switch (result) { case RtpParseResult.Success: // Add the packet to the list and continue processing. packets.Add(packet); break; case RtpParseResult.DataIncomplete: // Tell the calling function that it can reuse the buffer after position <length>. // Move the data to the beginning of the buffer (so that we can get it next time) and stop parsing. Debug.Assert(buffer.CurrentOffset >= 0, "The current offset cannot be negative."); Debug.Assert(buffer.RemainingBytes >= 0, "The remaining bytes cannot be negative."); Buffer.BlockCopy(buffer.Data, buffer.CurrentOffset, buffer.Data, 0, buffer.RemainingBytes); buffer.DataLength = buffer.RemainingBytes; buffer.DataOffset = 0; buffer.CurrentOffset = 0; return(packets); case RtpParseResult.DataInvalid: // Don't add the current packet to the list, but continue processing at the current position. break; } } // If this is our exit point, tell the calling function that it can reuse the entire buffer. buffer.DataLength = 0; buffer.CurrentOffset = 0; return(packets); }