/// <summary> /// Adds a block to the playback blocks by converting the given frame. /// If there are no more blocks in the pool, the oldest block is returned to the pool /// and reused for the new block. The source frame is automatically disposed. /// </summary> /// <param name="source">The source.</param> /// <param name="container">The container.</param> /// <returns>The filled block.</returns> public MediaBlock Add(MediaFrame source, MediaContainer container) { lock (SyncRoot) { // Check if we already have a block at the given time if (IsInRange(source.StartTime)) { var reapeatedBlock = PlaybackBlocks.FirstOrDefault(f => f.StartTime.Ticks == source.StartTime.Ticks); if (reapeatedBlock != null) { PlaybackBlocks.Remove(reapeatedBlock); PoolBlocks.Enqueue(reapeatedBlock); } } // if there are no available blocks, make room! if (PoolBlocks.Count <= 0) { var firstBlock = PlaybackBlocks[0]; PlaybackBlocks.RemoveAt(0); PoolBlocks.Enqueue(firstBlock); } // Get a block reference from the pool and convert it! var targetBlock = PoolBlocks.Dequeue(); container.Convert(source, ref targetBlock, true); // Add the converted block to the playback list and sort it. PlaybackBlocks.Add(targetBlock); PlaybackBlocks.Sort(); return(targetBlock); } }
/// <summary> /// Adds a block to the playback blocks by converting the given frame. /// If there are no more blocks in the pool, the oldest block is returned to the pool /// and reused for the new block. The source frame is automatically disposed. /// </summary> /// <param name="source">The source.</param> /// <param name="container">The container.</param> /// <returns>The filled block.</returns> internal MediaBlock Add(MediaFrame source, MediaContainer container) { if (source == null) { return(null); } lock (SyncLock) { try { // Check if we already have a block at the given time if (IsInRange(source.StartTime) && source.HasValidStartTime) { var repeatedBlock = PlaybackBlocks.FirstOrDefault(f => f.StartTime.Ticks == source.StartTime.Ticks); if (repeatedBlock != null) { PlaybackBlocks.Remove(repeatedBlock); PoolBlocks.Enqueue(repeatedBlock); } } // if there are no available blocks, make room! if (PoolBlocks.Count <= 0) { // Remove the first block from playback var firstBlock = PlaybackBlocks[0]; PlaybackBlocks.RemoveAt(0); PoolBlocks.Enqueue(firstBlock); } // Get a block reference from the pool and convert it! var targetBlock = PoolBlocks.Dequeue(); var lastBlock = PlaybackBlocks.Count > 0 ? PlaybackBlocks[PlaybackBlocks.Count - 1] : null; if (container.Convert(source, ref targetBlock, true, lastBlock) == false) { // return the converted block to the pool PoolBlocks.Enqueue(targetBlock); return(null); } // Add the target block to the playback blocks PlaybackBlocks.Add(targetBlock); // return the new target block return(targetBlock); } finally { // update collection-wide properties UpdateCollectionProperties(); } } }
private static void HandleDecoding(List <MediaFrame> decodedFrames) { foreach (var frame in decodedFrames) { var frameResult = Outputs[frame.MediaType]; Container.Convert(frame, ref frameResult, true); if (IsBenchmarking == false) { HandleFrame(frameResult); } } }
/// <summary> /// Adds a block to the playback blocks by converting the given frame. /// If there are no more blocks in the pool, the oldest block is returned to the pool /// and reused for the new block. The source frame is automatically disposed. /// </summary> /// <param name="source">The source.</param> /// <param name="container">The container.</param> /// <returns>The filled block.</returns> internal MediaBlock Add(MediaFrame source, MediaContainer container) { using (Locker.AcquireWriterLock()) { // Check if we already have a block at the given time if (IsInRange(source.StartTime) && source.HasValidStartTime) { var reapeatedBlock = PlaybackBlocks.FirstOrDefault(f => f.StartTime.Ticks == source.StartTime.Ticks); if (reapeatedBlock != null) { PlaybackBlocks.Remove(reapeatedBlock); PoolBlocks.Enqueue(reapeatedBlock); } } // if there are no available blocks, make room! if (PoolBlocks.Count <= 0) { var firstBlock = PlaybackBlocks[0]; PlaybackBlocks.RemoveAt(0); PoolBlocks.Enqueue(firstBlock); } // Get a block reference from the pool and convert it! var targetBlock = PoolBlocks.Dequeue(); if (container.Convert(source, ref targetBlock, PlaybackBlocks, true) == false) { // return the converted block to the pool PoolBlocks.Enqueue(targetBlock); return(null); } // Discard video frames with incorrect timing if (MediaType == MediaType.Video && targetBlock.IsStartTimeGuessed && IsMonotonic && PlaybackBlocks.Count > 1 && targetBlock.Duration != PlaybackBlocks.Last().Duration) { // return the converted block to the pool PoolBlocks.Enqueue(targetBlock); return(null); } // Add the converted block to the playback list and sort it. PlaybackBlocks.Add(targetBlock); PlaybackBlocks.Sort(); LifetimeBlockDuration = TimeSpan.FromTicks(LifetimeBlockDuration.Ticks + targetBlock.Duration.Ticks); // return the new target block return(targetBlock); } }
/// <summary> /// Adds a block to the playback blocks by converting the given frame. /// If there are no more blocks in the pool, the oldest block is returned to the pool /// and reused for the new block. The source frame is automatically disposed. /// </summary> /// <param name="source">The source.</param> /// <param name="container">The container.</param> /// <returns>The filled block.</returns> public MediaBlock Add(MediaFrame source, MediaContainer container) { lock (SyncRoot) { // Check if we already have a block at the given time if (IsInRange(source.StartTime)) { var reapeatedBlock = PlaybackBlocks.FirstOrDefault(f => f.StartTime.Ticks == source.StartTime.Ticks); if (reapeatedBlock != null) { PlaybackBlocks.Remove(reapeatedBlock); PoolBlocks.Enqueue(reapeatedBlock); } } // if there are no available blocks, make room! if (PoolBlocks.Count <= 0) { var firstBlock = PlaybackBlocks[0]; PlaybackBlocks.RemoveAt(0); PoolBlocks.Enqueue(firstBlock); } // Get a block reference from the pool and convert it! var targetBlock = PoolBlocks.Dequeue(); container.Convert(source, ref targetBlock, PlaybackBlocks, true); // Discard a frame with incorrect timing if (targetBlock.IsStartTimeGuessed && IsMonotonic && PlaybackBlocks.Count > 1 && targetBlock.Duration != PlaybackBlocks.Last().Duration) { // return the converted block to the pool PoolBlocks.Enqueue(targetBlock); return(null); } else { // Add the converted block to the playback list and sort it. PlaybackBlocks.Add(targetBlock); PlaybackBlocks.Sort(); } return(targetBlock); } }
/// <summary> /// Adds a block to the playback blocks by converting the given frame. /// If there are no more blocks in the pool, the oldest block is returned to the pool /// and reused for the new block. The source frame is automatically disposed. /// </summary> /// <param name="source">The source.</param> /// <param name="container">The container.</param> /// <returns>The filled block.</returns> public MediaBlock Add(MediaFrame source, MediaContainer container) { if (source == null) { return(null); } lock (SyncLock) { try { // if there are no available blocks, make room! if (PoolBlocks.Count <= 0) { // Remove the first block from playback var firstBlock = PlaybackBlocks[0]; PlaybackBlocks.RemoveAt(0); PoolBlocks.Enqueue(firstBlock); } // Get a block reference from the pool and convert it! var targetBlock = PoolBlocks.Dequeue(); var lastBlock = PlaybackBlocks.Count > 0 ? PlaybackBlocks[PlaybackBlocks.Count - 1] : null; if (container.Convert(source, ref targetBlock) == false) { // return the converted block to the pool PoolBlocks.Enqueue(targetBlock); return(null); } // Add the target block to the playback blocks PlaybackBlocks.Add(targetBlock); // return the new target block return(targetBlock); } finally { // update collection-wide properties UpdateCollectionProperties(); } } }
/// <summary> /// Adds a block to the playback blocks by converting the given frame. /// If there are no more blocks in the pool, the oldest block is returned to the pool /// and reused for the new block. The source frame is automatically disposed. /// </summary> /// <param name="source">The source.</param> /// <param name="container">The container.</param> /// <returns>The filled block.</returns> internal MediaBlock Add(MediaFrame source, MediaContainer container) { if (source == null) { return(null); } lock (SyncLock) { try { // Check if we already have a block at the given time if (IsInRange(source.StartTime) && source.HasValidStartTime) { var reapeatedBlock = PlaybackBlocks.FirstOrDefault(f => f.StartTime.Ticks == source.StartTime.Ticks); if (reapeatedBlock != null) { PlaybackBlocks.Remove(reapeatedBlock); PoolBlocks.Enqueue(reapeatedBlock); } } // if there are no available blocks, make room! if (PoolBlocks.Count <= 0) { var firstBlock = PlaybackBlocks[0]; PlaybackBlocks.RemoveAt(0); PoolBlocks.Enqueue(firstBlock); } // Get a block reference from the pool and convert it! var targetBlock = PoolBlocks.Dequeue(); if (container.Convert(source, ref targetBlock, PlaybackBlocks, true) == false) { // return the converted block to the pool PoolBlocks.Enqueue(targetBlock); return(null); } // Add the converted block to the playback list and sort it if we have to. var lastBlock = PlaybackBlocks.Count > 0 ? PlaybackBlocks[PlaybackBlocks.Count - 1] : null; var requiresSorting = lastBlock != null && targetBlock.StartTime < lastBlock.StartTime; PlaybackBlocks.Add(targetBlock); var maxBlockIndex = PlaybackBlocks.Count - 1; // Perform the sorting and assignment of Previous and Next blocks if (requiresSorting) { PlaybackBlocks.Sort(); PlaybackBlocks[0].Index = 0; PlaybackBlocks[0].Previous = null; PlaybackBlocks[0].Next = maxBlockIndex > 0 ? PlaybackBlocks[1] : null; for (var blockIndex = 1; blockIndex <= maxBlockIndex; blockIndex++) { PlaybackBlocks[blockIndex].Index = blockIndex; PlaybackBlocks[blockIndex].Previous = PlaybackBlocks[blockIndex - 1]; PlaybackBlocks[blockIndex].Next = blockIndex + 1 <= maxBlockIndex ? PlaybackBlocks[blockIndex + 1] : null; } } else { targetBlock.Previous = maxBlockIndex >= 1 ? PlaybackBlocks[maxBlockIndex - 1] : null; targetBlock.Next = null; targetBlock.Index = PlaybackBlocks.Count - 1; if (targetBlock.Previous != null) { targetBlock.Previous.Next = targetBlock; } } // return the new target block return(targetBlock); } catch { throw; } finally { UpdateCollectionProperties(); } } }
/// <summary> /// Adds a block to the playback blocks by converting the given frame. /// If there are no more blocks in the pool, the oldest block is returned to the pool /// and reused for the new block. The source frame is automatically disposed. /// </summary> /// <param name="source">The source.</param> /// <param name="container">The container.</param> /// <returns>The filled block.</returns> internal MediaBlock Add(MediaFrame source, MediaContainer container) { if (source == null) { return(null); } using (Locker.AcquireWriterLock()) { // Check if we already have a block at the given time if (IsInRange(source.StartTime) && source.HasValidStartTime) { var reapeatedBlock = PlaybackBlocks.FirstOrDefault(f => f.StartTime.Ticks == source.StartTime.Ticks); if (reapeatedBlock != null) { PlaybackBlocks.Remove(reapeatedBlock); PoolBlocks.Enqueue(reapeatedBlock); } } // if there are no available blocks, make room! if (PoolBlocks.Count <= 0) { var firstBlock = PlaybackBlocks[0]; PlaybackBlocks.RemoveAt(0); PoolBlocks.Enqueue(firstBlock); } // Get a block reference from the pool and convert it! var targetBlock = PoolBlocks.Dequeue(); if (container.Convert(source, ref targetBlock, PlaybackBlocks, true) == false) { // return the converted block to the pool PoolBlocks.Enqueue(targetBlock); return(null); } // Discard video frames with incorrect timing if (MediaType == MediaType.Video && targetBlock.IsStartTimeGuessed && IsMonotonic && PlaybackBlocks.Count > 1 && targetBlock.Duration != PlaybackBlocks.Last().Duration) { // return the converted block to the pool PoolBlocks.Enqueue(targetBlock); return(null); } // Add the converted block to the playback list and sort it if we have to. var requiresSorting = targetBlock.StartTime < RangeEndTime; PlaybackBlocks.Add(targetBlock); var maxBlockIndex = PlaybackBlocks.Count - 1; LifetimeBlockDuration = TimeSpan.FromTicks(LifetimeBlockDuration.Ticks + targetBlock.Duration.Ticks); // Perform the sorting if (requiresSorting) { PlaybackBlocks.Sort(); PlaybackBlocks[0].Previous = null; PlaybackBlocks[maxBlockIndex].Next = null; for (var blockIndex = 1; blockIndex <= maxBlockIndex; blockIndex++) { PlaybackBlocks[blockIndex].Previous = PlaybackBlocks[blockIndex - 1]; PlaybackBlocks[blockIndex].Next = blockIndex + 1 <= maxBlockIndex ? PlaybackBlocks[blockIndex + 1] : null; } } else { targetBlock.Previous = maxBlockIndex >= 1 ? PlaybackBlocks[maxBlockIndex - 1] : null; targetBlock.Next = null; if (targetBlock.Previous != null) { targetBlock.Previous.Next = targetBlock; } } // return the new target block return(targetBlock); } }