public void DecodeChunk(ByteStream frame, ushort remoteSsrcId) { var blocks = _chunkHelper.ParseChunk(frame, remoteSsrcId); foreach (var block in blocks) { _decodedFrame.ProcessBlock(block); _frameBlockPool.Recycle(block); } }
public void DoReset() { List <AbstractPathNode> tmp = new List <AbstractPathNode>(); foreach (AbstractPathNode pathNode in Nodes) { tmp.Add(pathNode); } foreach (AbstractPathNode node in tmp) { pool.Recycle(node); } o = Vector3.zero; way = Way.Forward; targetOrigin.SetTransform(target); D.Value = 0; resetEvent.Invoke(); }
IEnumerator WaitForRecycle() { yield return(new WaitForSeconds(duration)); if (pool != null) { pool.Recycle(this); } this.gameObject.SetActive(false); }
public void InsertBlock(FrameBlock newBlock, int index) { frameBlockPool.Recycle(FrameBlocks[index]); newBlock.ReferenceCount++; FrameBlocks[index] = newBlock; }
// private double _doubleReadCounter; // private int _doubleReadFloor; #endregion #region Methods /// <returns>Length *in shorts* of the decoded data</returns> public int ReadSamples(short[] outputBuffer) { int length = 0; bool isSilent = false; lock (_queue) { // If there are too many frames in the queue, pull them out one by one and decode them (so the speex buffer stays OK), // but don't bother playing them. This is a case where downsampling would be helpful, but we'll ignore it for now. while (_queue.Count > queuedFramesTargetMax) { _logger.LogQueueFull(); var entry = _queue.Dequeue(); AudioDecoder = _codecFactory.GetAudioDecoder(entry.AudioCodecType); AudioDecoder.Decode(entry.Frame, 0, entry.DataLength, outputBuffer, length, entry.IsSilent); _entryPool.Recycle(entry); _videoQualityController.LogGlitch(1); } // If we haven't lost any frames since the last check, pull one frame out of the queue to reduce latency. // This is a case where downsampling would be helpful, but we'll ignore it for now. if (++_framesSinceLastCheck > _framesBetweenChecks && _firstPacketReceived) { // Keep a record of the queue size, so that we can know how "bad" it is when we miss a packet. // It's not a big deal to miss a read when the queue size is stable at < 4 frames, // but it's a pretty big deal when the queue size is jumping around between 0 and 50. while (_queueSizes.Count > maxQueueSizeEntries) { _queueSizes.RemoveAt(0); } _queueSizes.Add(_queue.Count); if (_framesLostSinceLastCheck == 0 && _queue.Count > queuedFramesTargetMin) { var entry = _queue.Dequeue(); AudioDecoder = _codecFactory.GetAudioDecoder(entry.AudioCodecType); AudioDecoder.Decode(entry.Frame, 0, entry.DataLength, outputBuffer, length, entry.IsSilent); _entryPool.Recycle(entry); if (_framesBetweenChecks > framesBetweenChecksMin) { _framesBetweenChecks -= goodTrafficAdjustment; // Speed up (slightly) the rate at which we can decrease the queue size. } _logger.LogQueueReduced(); } _framesLostSinceLastCheck = 0; _framesSinceLastCheck = 0; } // Calculate the number of packets we should retrieve. // Here's the logic. Let's say that we're only reading packets every 23.3 milliseconds instead of every 20 milliseconds. // This means that for about 3.3/20 = 16.5% of the reads, we actually need to request *two* packets. // So each time we read, we add .165 to a counter, and then take its floor. As soon as the counter floor // rolls over to a new integer, we know that we need to read a second packet. // Unfortunately, dammit, it doesn't look like this works. We'll need to create a better approach, // presumably using a resampler. //_doubleReadCounter += _logger.OverageRatio; //int packetsToRead = 1; //var newDoubleReadFloor = (int)Math.Floor(_doubleReadCounter); //if (newDoubleReadFloor > _doubleReadFloor) //{ // packetsToRead += newDoubleReadFloor - _doubleReadFloor; // _doubleReadFloor = newDoubleReadFloor; // _logger.LogMultipleRead(); //} //for (int i = 0; i < packetsToRead; i++) { if (_queue.Count > 0) { // If we have anything in the queue, fulfill the request. var entry = _queue.Dequeue(); isSilent = entry.IsSilent; _lastSequenceNumberRead = entry.SequenceNumber; AudioDecoder = _codecFactory.GetAudioDecoder(entry.AudioCodecType); length += AudioDecoder.Decode(entry.Frame, 0, entry.DataLength, outputBuffer, length, entry.IsSilent); _entryPool.Recycle(entry); _firstPacketReceived = true; } else { // Record the fact that we missed a read, so the rest of the system can adjust. _logger.LogQueueEmpty(); if (_firstPacketReceived) { double stdDev = DspHelper.GetStandardDeviation(_queueSizes); _videoQualityController.LogGlitch((int)Math.Floor(stdDev) + 1); } // If the frame hasn't arrived yet, let the last audio codec interpolate the missing packet. // Most likely, the additional frames will arrive in a bunch by the time the next read happens. // We may want to investigate our own upsampling algorithm at some point. length += AudioDecoder.Decode(null, 0, 0, outputBuffer, length, true); if (_framesBetweenChecks < framesBetweenChecksMax && _firstPacketReceived) { _framesBetweenChecks += badTrafficAdjustment; // Slow down (substantially) the rate at which we decrease the queue size. } } } } _logger.LogRead(_queue, _framesBetweenChecks, isSilent); return(length); }
public bool GetNextChunkFromQueue(Queue <FrameBlock> queue, ByteStream buffer) { byte blocks = 0; buffer.CurrentOffset = ChunkHeaderLength; short jpegQuality = 0; // Pull blocks from the queue and insert them into the buffer until the buffer is full or the block queue is empty. FrameBlock block = null; while (buffer.CurrentOffset < _maxChunkSize) { // See if there's room left in the current chunk for the next block. lock (queue) { // Stop pulling blocks from the queue if there are no more blocks. if (queue.Count == 0) { break; } // Stop pulling blocks from the queue if there's no more room in the chunk. var peek = queue.Peek(); if ((buffer.CurrentOffset + BlockHeaderLength + peek.EncodedStream.Length) > _maxChunkSize && buffer.CurrentOffset > ChunkHeaderLength) { break; } // Stop pulling blocks from the queue if the jpegQuality has changed. if ((jpegQuality > 0 && peek.JpegQuality != jpegQuality)) { break; } block = queue.Dequeue(); } blocks++; jpegQuality = block.JpegQuality; // Set the x,y position of the block. buffer.WriteByte(block.BlockX); buffer.WriteByte(block.BlockY); // Set the type of the block. buffer.WriteByte((byte)block.BlockType); // Set the size of the block. var streamLength = (short)block.EncodedStream.Length; Debug.Assert(streamLength > 0, "The length of the encoded stream must be greater than 0"); buffer.WriteInt16(streamLength); // Set the actual block data. block.EncodedStream.Position = 0; block.EncodedStream.Read(buffer.Data, buffer.CurrentOffset, streamLength); buffer.CurrentOffset += streamLength; _frameBlockPool.Recycle(block); } // If we've retrieved at least one block, go back to the beginning of the buffer // and set the chunk header information if (block != null) { buffer.Data[0] = blocks; buffer.Data[1] = (byte)_videoQualityController.CommandedVideoQuality; buffer.Data[2] = (byte)_videoQualityController.ProposedVideoQuality; buffer.Data[3] = (byte)jpegQuality; buffer.DataLength = buffer.CurrentOffset; buffer.ResetCurrentOffset(); return(true); } return(false); }