/// <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);
            }
        }
Пример #2
0
        /// <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();
                }
            }
        }
Пример #3
0
 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);
         }
     }
 }
Пример #4
0
        /// <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);
            }
        }
Пример #5
0
        /// <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);
            }
        }
Пример #6
0
        /// <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();
                }
            }
        }
Пример #7
0
        /// <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);
            }
        }