Example #1
0
        /// <summary>
        /// Renders the specified media block.
        /// </summary>
        /// <param name="mediaBlock">The media block.</param>
        /// <param name="clockPosition">The clock position.</param>
        public void Render(MediaBlock mediaBlock, TimeSpan clockPosition)
        {
            // We don't need to render anything while we are seeking. Simply drop the blocks.
            if (MediaElement.IsSeeking)
            {
                return;
            }
            if (AudioBuffer == null)
            {
                return;
            }

            // Capture Media Block Reference
            var block = mediaBlock as AudioBlock;

            if (block == null)
            {
                return;
            }

            var audioBlocks = MediaCore.Blocks[MediaType.Audio];
            var audioBlock  = mediaBlock as AudioBlock;

            while (audioBlock != null)
            {
                // Write the block if we have to, avoiding repeated blocks.
                if (AudioBuffer.WriteTag < audioBlock.StartTime)
                {
                    MediaElement.RaiseRenderingAudioEvent(audioBlock, clockPosition);
                    AudioBuffer.Write(audioBlock.Buffer, audioBlock.BufferLength, audioBlock.StartTime, true);
                }

                // Stop adding if we have too much in there.
                if (AudioBuffer.CapacityPercent >= 0.8)
                {
                    break;
                }

                // Retrieve the following block
                audioBlock = audioBlocks.Next(audioBlock) as AudioBlock;
            }
        }
Example #2
0
        /// <summary>
        /// Retrieves the block following the provided current block
        /// </summary>
        /// <param name="current">The current block.</param>
        /// <returns>The next media block</returns>
        public MediaBlock Next(MediaBlock current)
        {
            using (Locker.AcquireReaderLock())
            {
                var currentIndex = current == null && PlaybackBlocks.Count > 0 ?
                                   0 : PlaybackBlocks.IndexOf(current);

                if (currentIndex < 0)
                {
                    return(null);
                }

                if (currentIndex + 1 < PlaybackBlocks.Count)
                {
                    return(PlaybackBlocks[currentIndex + 1]);
                }

                return(null);
            }
        }
Example #3
0
        private static void PrintFrameInfo(MediaBlock e)
        {
            {
                var a = e as AudioBlock;
                if (a != null)
                {
                    $"{e.MediaType,-10} | PTS: {e.StartTime.TotalSeconds,8:0.00000} | DUR: {e.Duration.TotalSeconds,8:0.00000} | END: {e.EndTime.TotalSeconds,8:0.00000} | SMP: {a.SamplesPerChannel,6}".Trace(typeof(Program));
                    return;
                }
            }

            {
                var v = e as VideoBlock;
                if (v != null)
                {
                    $"{e.MediaType,-10} | PTS: {e.StartTime.TotalSeconds,8:0.00000} | DUR: {e.Duration.TotalSeconds,8:0.00000} | END: {e.EndTime.TotalSeconds,8:0.00000} | DIM: {v.PixelWidth}x{v.PixelHeight}".Info(typeof(Program));
                    return;
                }
            }
        }
        private int SendBlockToRenderer(MediaBlock currentBlock, TimeSpan playbackPosition)
        {
            // No blocks were rendered
            if (currentBlock == null || currentBlock.IsDisposed)
            {
                return(0);
            }

            var t = currentBlock.MediaType;
            var isAttachedPicture      = t == MediaType.Video && Container.Components[t].StreamInfo.IsAttachedPictureDisposition;
            var lastBlockStartTime     = MediaCore.LastRenderTime[t];
            var isRepeatedBlock        = lastBlockStartTime != TimeSpan.MinValue && lastBlockStartTime == currentBlock.StartTime;
            var requiresRepeatedBlocks = t == MediaType.Audio || isAttachedPicture;

            // For live streams, we don't want to display previosu blocks
            if (t == MediaType.Video && !isRepeatedBlock && !isAttachedPicture && Container.IsLiveStream)
            {
                isRepeatedBlock = lastBlockStartTime.Ticks >= currentBlock.StartTime.Ticks;
            }

            // Render by forced signal (TimeSpan.MinValue) or because simply it is time to do so
            // otherwise simply skip block rendering as we have sent the block already.
            if (isRepeatedBlock && !requiresRepeatedBlocks)
            {
                return(0);
            }

            // Process property changes coming from video blocks
            State.UpdateDynamicBlockProperties(currentBlock);

            // Capture the last render time so we don't repeat the block
            MediaCore.LastRenderTime[t] = currentBlock.StartTime;

            // Send the block to its corresponding renderer
            MediaCore.Renderers[t]?.Render(currentBlock, playbackPosition);

            // Log the block statistics for debugging
            LogRenderBlock(currentBlock, playbackPosition);

            return(1);
        }
Example #5
0
        private int SendBlockToRenderer(MediaBlock block, TimeSpan clockPosition)
        {
            // No blocks were rendered
            if (block == null)
            {
                return(0);
            }

            // Process property changes coming from video blocks
            State.UpdateDynamicBlockProperties(block, MediaCore.Blocks[block.MediaType]);

            // Send the block to its corresponding renderer
            MediaCore.Renderers[block.MediaType]?.Render(block, clockPosition);
            MediaCore.LastRenderTime[block.MediaType] = block.StartTime;

            // Log the block statistics for debugging
            LogRenderBlock(block, clockPosition, block.Index);

            // At this point, we are certain that a blocl has been
            // sent to its corresponding renderer.
            return(1);
        }
        /// <summary>
        /// Renders the specified media block.
        /// </summary>
        /// <param name="mediaBlock">The media block.</param>
        /// <param name="clockPosition">The clock position.</param>
        /// <param name="renderIndex">Index of the render.</param>
        public void Render(MediaBlock mediaBlock, TimeSpan clockPosition, int renderIndex)
        {
            SpeedRatio = MediaElement?.Clock?.SpeedRatio ?? 0d;

            if (AudioBuffer == null)
            {
                return;
            }
            var block = mediaBlock as AudioBlock;

            if (block == null)
            {
                return;
            }

            var currentIndex    = renderIndex;
            var audioBlocks     = MediaElement.Blocks[MediaType.Audio];
            var addedBlockCount = 0;
            var addedBytes      = 0;

            while (currentIndex >= 0 && currentIndex < audioBlocks.Count)
            {
                var audioBlock = audioBlocks[currentIndex] as AudioBlock;
                if (AudioBuffer.WriteTag < audioBlock.StartTime)
                {
                    AudioBuffer.Write(audioBlock.Buffer, audioBlock.BufferLength, audioBlock.StartTime, true);
                    addedBlockCount++;
                    addedBytes += audioBlock.BufferLength;
                }

                currentIndex++;

                // Stop adding if we have too much in there.
                if (AudioBuffer.CapacityPercent >= 0.8)
                {
                    break;
                }
            }
        }
Example #7
0
        /// <summary>
        /// Renders the specified media block.
        /// This needs to return immediately so the calling thread is not disturbed.
        /// </summary>
        /// <param name="mediaBlock">The media block.</param>
        /// <param name="clockPosition">The clock position.</param>
        public void Render(MediaBlock mediaBlock, TimeSpan clockPosition)
        {
            var block = mediaBlock as VideoBlock;

            if (block == null)
            {
                return;
            }
            if (IsRenderingInProgress.Value == true)
            {
                MediaElement?.MediaCore?.Log(MediaLogMessageType.Debug, $"{nameof(VideoRenderer)}: Frame skipped at {mediaBlock.StartTime}");
                return;
            }

            // Flag the start of a rendering cycle
            IsRenderingInProgress.Value = true;

            // Ensure the target bitmap can be loaded
            GuiContext.Current.EnqueueInvoke(DispatcherPriority.Render, () =>
            {
                try
                {
                    MediaElement.CaptionsView.RenderPacket(block, MediaCore);

                    var bitmapData = LockTargetBitmap(block);
                    if (bitmapData != null)
                    {
                        LoadTargetBitmapBuffer(bitmapData, block);
                        MediaElement.RaiseRenderingVideoEvent(block, bitmapData, clockPosition);
                        RenderTargetBitmap(block, bitmapData, clockPosition);
                    }
                }
                catch { /* swallow */ }
                finally
                {
                    IsRenderingInProgress.Value = false;
                }
            });
        }
Example #8
0
        public void Render(MediaBlock mediaBlock, TimeSpan clockPosition)
        {
            var block = mediaBlock as VideoBlock;

            if (block == null)
            {
                return;
            }
            //if (IsRenderingInProgress.Value == true)
            //{
            //    //MediaElement.Logger.Log(MediaLogMessageType.Debug, $"{nameof(VideoRenderer)}: Frame skipped at {mediaBlock.StartTime}");
            //    return;
            //}

            IsRenderingInProgress.Value = true;

            var size  = block.BufferLength;
            var bytes = new byte[size];

            Marshal.Copy(block.Buffer, bytes, 0, size);

            Transform(block.Buffer, bytes, block.PixelWidth, block.PixelHeight);
        }
Example #9
0
 /// <summary>
 /// Logs a block rendering operation as a Trace Message
 /// if the debugger is attached.
 /// </summary>
 /// <param name="container">The container.</param>
 /// <param name="block">The block.</param>
 /// <param name="clockPosition">The clock position.</param>
 /// <param name="renderIndex">Index of the render.</param>
 internal static void LogRenderBlock(this MediaContainer container, MediaBlock block, TimeSpan clockPosition, int renderIndex)
 {
     if (Debugger.IsAttached == false)
     {
         return;
     }
     try
     {
         var drift = TimeSpan.FromTicks(clockPosition.Ticks - block.StartTime.Ticks);
         container?.Log(MediaLogMessageType.Trace,
                        ($"{block.MediaType.ToString().Substring(0, 1)} "
                         + $"BLK: {block.StartTime.Debug()} | "
                         + $"CLK: {clockPosition.Debug()} | "
                         + $"DFT: {drift.TotalMilliseconds,4:0} | "
                         + $"IX: {renderIndex,3} | "
                         + $"PQ: {container?.Components[block.MediaType]?.PacketBufferLength / 1024d,7:0.0}k | "
                         + $"TQ: {container?.Components.PacketBufferLength / 1024d,7:0.0}k"));
     }
     catch
     {
         // swallow
     }
 }
Example #10
0
        public override void Render(MediaBlock mediaBlock, TimeSpan clockPosition)
        {
            var block = BeginRenderingCycle(mediaBlock);

            if (block == null)
            {
                return;
            }

            IDisposable blockLock = null;

            try
            {
                if (!block.TryAcquireReaderLock(out blockLock))
                {
                    return;
                }

                var bitmap = Graphics.Write(block);
                if (bitmap == null)
                {
                    return;
                }

                MediaElement?.RaiseRenderingVideoEvent(block, bitmap, clockPosition);
                UpdateTargetImage(DispatcherPriority.Loaded, true);
            }
            catch (Exception ex)
            {
                this.LogError(Aspects.VideoRenderer, $"{nameof(InteropVideoRenderer)}.{nameof(Render)} bitmap failed.", ex);
            }
            finally
            {
                blockLock?.Dispose();
                FinishRenderingCycle(block, clockPosition);
            }
        }
Example #11
0
        /// <summary>
        /// Logs a block rendering operation as a Trace Message
        /// if the debugger is attached.
        /// </summary>
        /// <param name="mediaCore">The media engine.</param>
        /// <param name="block">The block.</param>
        /// <param name="clockPosition">The clock position.</param>
        /// <param name="renderIndex">Index of the render.</param>
        internal static void LogRenderBlock(this MediaEngine mediaCore, MediaBlock block, TimeSpan clockPosition, int renderIndex)
        {
            if (MediaEngine.Platform.IsInDebugMode == false)
            {
                return;
            }

            try
            {
                var drift = TimeSpan.FromTicks(clockPosition.Ticks - block.StartTime.Ticks);
                mediaCore?.Log(MediaLogMessageType.Trace,
                               $"{block.MediaType.ToString().Substring(0, 1)} "
                               + $"BLK: {block.StartTime.Format()} | "
                               + $"CLK: {clockPosition.Format()} | "
                               + $"DFT: {drift.TotalMilliseconds,4:0} | "
                               + $"IX: {renderIndex,3} | "
                               + $"PQ: {mediaCore.Container?.Components[block.MediaType]?.BufferLength / 1024d,7:0.0}k | "
                               + $"TQ: {mediaCore.Container?.Components.BufferLength / 1024d,7:0.0}k");
            }
            catch
            {
                // swallow
            }
        }
        /// <summary>
        /// Renders the specified media block.
        /// </summary>
        /// <param name="mediaBlock">The media block.</param>
        /// <param name="clockPosition">The clock position.</param>
        public void Render(MediaBlock mediaBlock, TimeSpan clockPosition)
        {
            lock (SyncLock)
            {
                var subtitleBlock = mediaBlock as SubtitleBlock;
                if (subtitleBlock == null)
                {
                    return;
                }

                // Save the start and end times. We will need
                // them in order to make the subtitles disappear
                StartTime = subtitleBlock.StartTime;
                EndTime   = subtitleBlock.EndTime;

                // Raise the subtitles event and keep track of the text.
                BlockText = MediaElement.RaiseRenderingSubtitlesEvent(subtitleBlock, clockPosition)
                    ? string.Empty
                    : string.Join("\r\n", subtitleBlock.Text);

                // Call the selective update method
                Update(clockPosition);
            }
        }
Example #13
0
        /// <inheritdoc />
        public void Render(MediaBlock mediaBlock, TimeSpan clockPosition)
        {
            lock (SyncLock)
            {
                if (mediaBlock is SubtitleBlock == false)
                {
                    return;
                }

                // Get a reference to the subtitle block
                var subtitleBlock = (SubtitleBlock)mediaBlock;

                // Raise the subtitles event and keep track of the text.
                var cancelRender = MediaElement.RaiseRenderingSubtitlesEvent(subtitleBlock, clockPosition);

                if (cancelRender)
                {
                    BlockText = string.Empty;
                    StartTime = null;
                    EndTime   = null;
                }
                else
                {
                    // Save the block text lines to display
                    BlockText = string.Join("\r\n", subtitleBlock.Text);

                    // Save the start and end times. We will need
                    // them in order to make the subtitles disappear
                    StartTime = subtitleBlock.StartTime;
                    EndTime   = subtitleBlock.EndTime;
                }

                // Call the selective update method
                Update(clockPosition);
            }
        }
        /// <inheritdoc />
        public void Render(MediaBlock mediaBlock, TimeSpan clockPosition)
        {
            // We don't need to render anything while we are seeking. Simply drop the blocks.
            if (MediaCore.State.IsSeeking || HasFiredAudioDeviceStopped)
            {
                return;
            }

            var lockTaken = false;

            Monitor.TryEnter(SyncLock, SyncLockTimeout, ref lockTaken);
            if (lockTaken == false)
            {
                return;
            }

            try
            {
                if ((AudioDevice?.IsRunning ?? false) == false)
                {
                    if (HasFiredAudioDeviceStopped)
                    {
                        return;
                    }
                    MediaElement.RaiseAudioDeviceStoppedEvent();
                    HasFiredAudioDeviceStopped = true;

                    return;
                }

                if (AudioBuffer == null)
                {
                    return;
                }

                // Capture Media Block Reference
                if (mediaBlock is AudioBlock == false)
                {
                    return;
                }
                var audioBlock  = (AudioBlock)mediaBlock;
                var audioBlocks = MediaCore.Blocks[MediaType.Audio];

                while (audioBlock != null)
                {
                    if (audioBlock.TryAcquireReaderLock(out var readLock) == false)
                    {
                        return;
                    }

                    using (readLock)
                    {
                        // Write the block if we have to, avoiding repeated blocks.
                        if (AudioBuffer.WriteTag < audioBlock.StartTime)
                        {
                            AudioBuffer.Write(audioBlock.Buffer, audioBlock.SamplesBufferLength, audioBlock.StartTime, true);
                        }

                        // Stop adding if we have too much in there.
                        if (AudioBuffer.CapacityPercent >= 0.5)
                        {
                            break;
                        }

                        // Retrieve the following block
                        audioBlock = audioBlocks.ContinuousNext(audioBlock) as AudioBlock;
                    }
                }
            }
            catch (Exception ex)
            {
                this.LogError(Aspects.AudioRenderer, $"{nameof(AudioRenderer)}.{nameof(Read)} has faulted.", ex);
            }
            finally
            {
                Monitor.Exit(SyncLock);
            }
        }
 /// <summary>
 /// Renders the specified media block.
 /// </summary>
 /// <param name="mediaBlock">The media block.</param>
 /// <param name="clockPosition">The clock position.</param>
 /// <param name="renderIndex">Index of the render.</param>
 public void Render(MediaBlock mediaBlock, TimeSpan clockPosition, int renderIndex)
 {
     //placeholder
 }
Example #16
0
        /// <summary>
        /// Renders the specified media block.
        /// This needs to return immediately so the calling thread is not disturbed.
        /// </summary>
        /// <param name="mediaBlock">The media block.</param>
        /// <param name="clockPosition">The clock position.</param>
        public void Render(MediaBlock mediaBlock, TimeSpan clockPosition)
        {
            var block = mediaBlock as VideoBlock;

            if (block == null)
            {
                return;
            }
            if (IsRenderingInProgress)
            {
                return;
            }

            IsRenderingInProgress = true;

            Utils.UIEnqueueInvoke(
                DispatcherPriority.Render,
                new Action <VideoBlock, TimeSpan>((b, cP) =>
            {
                try
                {
                    if (TargetBitmap == null || TargetBitmap.PixelWidth != b.PixelWidth || TargetBitmap.PixelHeight != b.PixelHeight)
                    {
                        InitializeTargetBitmap(b);
                    }

                    var updateRect = new Int32Rect(0, 0, b.PixelWidth, b.PixelHeight);
                    TargetBitmap.WritePixels(updateRect, b.Buffer, b.BufferLength, b.BufferStride);
                    MediaElement.RaiseRenderingVideoEvent(TargetBitmap, MediaElement.Container.MediaInfo.Streams[b.StreamIndex], b.StartTime, b.Duration, cP);

                    var scaleTransform = MediaElement.ViewBox.LayoutTransform as ScaleTransform;

                    // Process Aspect Ratio according to block.
                    if (b.AspectWidth != b.AspectHeight)
                    {
                        var scaleX = b.AspectWidth > b.AspectHeight ? (double)b.AspectWidth / b.AspectHeight : 1d;
                        var scaleY = b.AspectHeight > b.AspectWidth ? (double)b.AspectHeight / b.AspectWidth : 1d;

                        if (scaleTransform == null)
                        {
                            scaleTransform = new ScaleTransform(scaleX, scaleY);
                            MediaElement.ViewBox.LayoutTransform = scaleTransform;
                        }

                        if (scaleTransform.ScaleX != scaleX || scaleTransform.ScaleY != scaleY)
                        {
                            scaleTransform.ScaleX = scaleX;
                            scaleTransform.ScaleY = scaleY;
                        }
                    }
                    else
                    {
                        if (scaleTransform != null && (scaleTransform.ScaleX != 1d || scaleTransform.ScaleY != 1d))
                        {
                            scaleTransform.ScaleX = 1d;
                            scaleTransform.ScaleY = 1d;
                        }
                    }
                }
                catch (Exception ex)
                {
                    Utils.Log(MediaElement, MediaLogMessageType.Error, $"{nameof(VideoRenderer)} {ex.GetType()}: {ex.Message}. Stack Trace:\r\n{ex.StackTrace}");
                }
                finally
                {
                    IsRenderingInProgress = false;
                }
            }), block,
                clockPosition);
        }
Example #17
0
        /// <summary>
        /// Renders the specified media block.
        /// This needs to return immediately so the calling thread is not disturbed.
        /// </summary>
        /// <param name="mediaBlock">The media block.</param>
        /// <param name="clockPosition">The clock position.</param>
        public void Render(MediaBlock mediaBlock, TimeSpan clockPosition)
        {
            var block = mediaBlock as VideoBlock;

            if (block == null)
            {
                return;
            }
            if (IsRenderingInProgress.Value == true)
            {
                MediaElement.Logger.Log(MediaLogMessageType.Debug, $"{nameof(VideoRenderer)}: Frame skipped at {mediaBlock.StartTime}");
                return;
            }

            IsRenderingInProgress.Value = true;

            Runner.UIEnqueueInvoke(
                DispatcherPriority.Render,
                new Action <VideoBlock, TimeSpan>((b, cP) =>
            {
                try
                {
                    // Skip rendering if Scrubbing is not enabled
                    if (MediaElement.ScrubbingEnabled == false && MediaElement.IsPlaying == false)
                    {
                        return;
                    }

                    if (TargetBitmap == null || TargetBitmap.PixelWidth != b.PixelWidth || TargetBitmap.PixelHeight != b.PixelHeight)
                    {
                        InitializeTargetBitmap(b);
                    }

                    var updateRect = new Int32Rect(0, 0, b.PixelWidth, b.PixelHeight);
                    TargetBitmap.WritePixels(updateRect, b.Buffer, b.BufferLength, b.BufferStride);
                    MediaElement.VideoSmtpeTimecode   = b.SmtpeTimecode;
                    MediaElement.VideoHardwareDecoder = (MediaElement.Container?.Components?.Video?.IsUsingHardwareDecoding ?? false) ?
                                                        MediaElement.Container?.Components?.Video?.HardwareAccelerator?.Name ?? string.Empty : string.Empty;

                    MediaElement.RaiseRenderingVideoEvent(
                        TargetBitmap,
                        MediaElement.Container.MediaInfo.Streams[b.StreamIndex],
                        b.SmtpeTimecode,
                        b.DisplayPictureNumber,
                        b.StartTime,
                        b.Duration,
                        cP);

                    ApplyScaleTransform(b);
                }
                catch (Exception ex)
                {
                    Utils.Log(MediaElement, MediaLogMessageType.Error, $"{nameof(VideoRenderer)} {ex.GetType()}: {ex.Message}. Stack Trace:\r\n{ex.StackTrace}");
                }
                finally
                {
                    IsRenderingInProgress.Value = false;
                }
            }), block,
                clockPosition);
        }
Example #18
0
        /// <summary>
        /// Renders the specified media block.
        /// </summary>
        /// <param name="mediaBlock">The media block.</param>
        /// <param name="clockPosition">The clock position.</param>
        public void Render(MediaBlock mediaBlock, TimeSpan clockPosition)
        {
            // We don't need to render anything while we are seeking. Simply drop the blocks.
            if (MediaCore.State.IsSeeking)
            {
                return;
            }

            var lockTaken = false;

            Monitor.TryEnter(SyncLock, SyncLockTimeout, ref lockTaken);
            if (lockTaken == false)
            {
                return;
            }

            try
            {
                if ((AudioDevice?.IsRunning ?? false) == false)
                {
                    // TODO: Handle this? -- see issue #93
                    return;
                }

                if (AudioBuffer == null)
                {
                    return;
                }

                // Capture Media Block Reference
                if (mediaBlock is AudioBlock == false)
                {
                    return;
                }
                var audioBlock = mediaBlock as AudioBlock;
                if (audioBlock == null)
                {
                    return;
                }
                var audioBlocks = MediaCore.Blocks[MediaType.Audio];

                while (audioBlock != null)
                {
                    if (audioBlock.TryAcquireReaderLock(out var readLock) == false)
                    {
                        return;
                    }

                    using (readLock)
                    {
                        // Write the block if we have to, avoiding repeated blocks.
                        if (AudioBuffer.WriteTag < audioBlock.StartTime)
                        {
                            MediaElement.RaiseRenderingAudioEvent(audioBlock, clockPosition);
                            AudioBuffer.Write(audioBlock.Buffer, audioBlock.SamplesBufferLength, audioBlock.StartTime, true);
                        }

                        // Stop adding if we have too much in there.
                        if (AudioBuffer.CapacityPercent >= 0.8)
                        {
                            break;
                        }

                        // Retrieve the following block
                        audioBlock = audioBlocks.Next(audioBlock) as AudioBlock;
                    }
                }
            }
            catch (Exception ex)
            {
                MediaCore?.Log(MediaLogMessageType.Error,
                               $"{ex.GetType()} in {nameof(AudioRenderer)}.{nameof(Read)}: {ex.Message}. Stack Trace:\r\n{ex.StackTrace}");
            }
            finally
            {
                Monitor.Exit(SyncLock);
            }
        }
 /// <summary>
 /// The render block callback that updates the reported media position
 /// </summary>
 /// <param name="block">The block.</param>
 /// <param name="clockPosition">The clock position.</param>
 /// <param name="renderIndex">Index of the render.</param>
 private void RenderBlock(MediaBlock block, TimeSpan clockPosition, int renderIndex)
 {
     Renderers[block.MediaType].Render(block, clockPosition, renderIndex);
     Container.LogRenderBlock(block, clockPosition, renderIndex);
 }
Example #20
0
        /// <summary>
        /// Renders the specified media block.
        /// This needs to return immediately so the calling thread is not disturbed.
        /// </summary>
        /// <param name="mediaBlock">The media block.</param>
        /// <param name="clockPosition">The clock position.</param>
        public void Render(MediaBlock mediaBlock, TimeSpan clockPosition)
        {
            var block = mediaBlock as VideoBlock;

            if (block == null)
            {
                return;
            }
            if (IsRenderingInProgress.Value == true)
            {
                MediaElement?.MediaCore?.Log(MediaLogMessageType.Debug, $"{nameof(VideoRenderer)}: Frame skipped at {mediaBlock.StartTime}");
                return;
            }

            // Flag the start of a rendering cycle
            IsRenderingInProgress.Value = true;

            // Create an action that holds GUI thread actions
            var foregroundAction = new Action(() =>
            {
                MediaElement.CaptionsView.RenderPacket(block, MediaCore);
                ApplyLayoutTransforms(block);
            });

            var canStartForegroundTask = MediaElement.VideoView.ElementDispatcher != MediaElement.Dispatcher;
            var foregroundTask         = canStartForegroundTask ?
                                         MediaElement.Dispatcher.InvokeAsync(foregroundAction) : null;

            // Ensure the target bitmap can be loaded
            MediaElement.VideoView.InvokeAsync(DispatcherPriority.Render, () =>
            {
                if (block.IsDisposed)
                {
                    IsRenderingInProgress.Value = false;
                    return;
                }

                // Run the foreground action if we could not start it.
                if (foregroundTask == null)
                {
                    foregroundAction();
                }

                try
                {
                    var bitmapData = LockTargetBitmap(block);
                    if (bitmapData != null)
                    {
                        LoadTargetBitmapBuffer(bitmapData, block);
                        MediaElement.RaiseRenderingVideoEvent(block, bitmapData, clockPosition);
                        RenderTargetBitmap(block, bitmapData, clockPosition);
                    }
                }
                catch (Exception ex)
                {
                    MediaElement?.MediaCore?.Log(
                        MediaLogMessageType.Error,
                        $"{nameof(VideoRenderer)} {ex.GetType()}: {nameof(Render)} failed. {ex.Message}.");
                }
                finally
                {
                    foregroundTask?.Wait();
                    IsRenderingInProgress.Value = false;
                }
            });
        }
Example #21
0
 public void Render(MediaBlock mediaBlock, TimeSpan clockPosition)
 {
 }
Example #22
0
        private static IEnumerable <Block> Unroll(SelectorAndBlock block)
        {
            var ret   = new List <Block>();
            var props = new List <Property>();

            foreach (var prop in block.Properties)
            {
                var media  = prop as InnerMediaProperty;
                var nested = prop as NestedBlockProperty;
                if (media == null && nested == null)
                {
                    props.Add(prop);
                    continue;
                }

                if (nested != null)
                {
                    var inner      = Unroll(nested.Block);
                    var innerMedia = inner.OfType <MediaBlock>();
                    var other      = inner.Where(i => !(i is MediaBlock)).Cast <SelectorAndBlock>();

                    props.AddRange(other.Select(s => new NestedBlockProperty(s, s.Start, s.Stop)));

                    foreach (var m in innerMedia)
                    {
                        var selBlock =
                            new SelectorAndBlock(
                                block.Selector,
                                m.Blocks.Cast <SelectorAndBlock>().Select(s => new NestedBlockProperty(s, s.Start, s.Stop)),
                                null,
                                m.Start,
                                m.Stop,
                                m.FilePath
                                );

                        var newMedia =
                            new MediaBlock(
                                m.MediaQuery,
                                new List <Block> {
                            selBlock
                        },
                                m.Start,
                                m.Stop,
                                m.FilePath
                                );

                        ret.Add(newMedia);
                    }

                    continue;
                }

                var unrolled =
                    new MediaBlock(
                        media.MediaQuery,
                        new List <Block>
                {
                    new SelectorAndBlock(
                        block.Selector,
                        media.Block.Properties,
                        null,
                        -1,
                        -1,
                        media.FilePath
                        )
                },
                        -1,
                        -1,
                        media.FilePath
                        );

                ret.Add(unrolled);
            }

            ret.Add(new SelectorAndBlock(block.Selector, props, null, block.Start, block.Stop, block.FilePath));

            return(ret);
        }
Example #23
0
        /// <summary>
        /// Invoke when manager starts new question
        /// </summary>
        /// <param name="id">Number of question</param>
        /// <param name="text">Text of question</param>
        /// <param name="secondsToAnswer">Time in seconds to answer</param>
        /// <param name="kind">Type of question</param>
        /// <param name="answers">List of answers</param>
        /// <param name="mediaPath">Path to video or picture for question</param>
        private void QuizManager_OnNewQuestion(int id, string text, string rightAnswer, int secondsToAnswer, QuestionKind kind, List <Answer> answers, Uri mediaPath, MediaAnswer mediaAnswer)
        {
            switch (kind)
            {
            case QuestionKind.WithVideo:
            {
                ShowBlacker();
                ImageAndVideoGrid.Children[0].Visibility = Visibility.Collapsed;
                MediaGrid.Visibility  = Visibility.Visible;
                MediaBorder.Padding   = new Thickness(200, 30, 200, 0);
                MediaBlock.Source     = mediaPath;
                MediaBlock.Visibility = Visibility.Visible;
                MediaBlock.Play();
                isVideoQuestion = true;
                isVideoPlay     = true;
                break;
            }

            case QuestionKind.WithImage:
            {
                ShowBlacker();
                MediaBlock.Stop();

                ImageAndVideoGrid.Children.RemoveAt(0);

                Image       image = new Image();
                BitmapImage src   = new BitmapImage();
                src.BeginInit();
                src.UriSource = mediaPath;
                src.EndInit();
                image.Source  = src;
                image.Stretch = Stretch.Uniform;

                ImageAndVideoGrid.Children.Insert(0, image);


                MediaGrid.Visibility  = Visibility.Visible;
                MediaBlock.Visibility = Visibility.Collapsed;
                isVideoQuestion       = false;


                break;
            }

            case QuestionKind.Simple:
            {
                HideBlacker();
                MediaBlock.Stop();
                MediaDockPanel.Visibility = Visibility.Collapsed;
                MediaBlock.Visibility     = Visibility.Collapsed;
                isVideoQuestion           = false;
                break;
            }
            }

            switch (mediaAnswer.Kind)
            {
            case AnswerKind.WithImage:
            {
                RightAnswerMediaGrid.Visibility = Visibility.Visible;
                RightAnswerMediaBlock.Stop();
                RightAnswerMediaBlock.Visibility = Visibility.Collapsed;

                RightMediaInnerGrid.Children.RemoveAt(0);

                Image       image = new Image();
                BitmapImage src   = new BitmapImage();
                src.BeginInit();
                src.UriSource = mediaAnswer.AnswerImagePath;
                src.EndInit();
                image.Source  = src;
                image.Stretch = Stretch.Uniform;

                RightMediaInnerGrid.Children.Insert(0, image);

                if (src.Height > SystemParameters.PrimaryScreenHeight / 2.4)
                {
                    (RightMediaInnerGrid.Children[0] as Image).Height = SystemParameters.PrimaryScreenHeight / 2.4;
                }


                RightAnswerDockPanel.Margin = new Thickness(0, 20, 0, 0);

                break;
            }

            case AnswerKind.WithVideo:
            {
                RightAnswerMediaGrid.Visibility            = Visibility.Visible;
                RightAnswerMediaBlock.Visibility           = Visibility.Visible;
                RightMediaInnerGrid.Children[0].Visibility = Visibility.Collapsed;
                RightAnswerMediaBlock.Source = mediaAnswer.AnswerVideoPath;
                RightAnswerMediaBlock.Play();

                RightAnswerDockPanel.Margin = new Thickness(0, 20, 0, 0);

                break;
            }

            case AnswerKind.Simple:
            {
                RightAnswerMediaGrid.Visibility = Visibility.Collapsed;
                RightAnswerDockPanel.Margin     = new Thickness(0, 100, 0, 0);
                break;
            }
            }

            QuestionNumberFontSize = 33 - ((int)Math.Log10(QuestionNumber) + 1) * 2;
            if (text.Count() < 93)
            {
                QuestionTextBlock.VerticalAlignment = VerticalAlignment.Center;
            }
            else if (text.Count() < 185)
            {
                QuestionTextBlock.VerticalAlignment = VerticalAlignment.Top;
            }
            else
            {
                QuestionTextBlock.VerticalAlignment = VerticalAlignment.Top;
                text = text.Substring(0, 182) + "...";
            }

            QuestionText = text;

            Regex reg = new Regex(@"\s{2,}");

            text = reg.Replace(text, " ");

            MainWindowQuestion = text;
            AnswerTimerText    = secondsToAnswer.ToString();
            _answersTime       = TimeSpan.FromSeconds(secondsToAnswer);

            QuestionNumber = id;

            RightAnswer = rightAnswer;
            RightAnswerGrid.Visibility = Visibility.Hidden;
            RightAnswerMediaBlock.Stop();

            MediaGrid.Visibility      = Visibility.Visible;
            MediaDockPanel.Visibility = Visibility.Visible;
            ShowImage();
        }
Example #24
0
        /// <inheritdoc />
        public void Render(MediaBlock mediaBlock, TimeSpan clockPosition)
        {
            if (mediaBlock is VideoBlock == false)
            {
                return;
            }

            var block = (VideoBlock)mediaBlock;

            if (IsRenderingInProgress.Value)
            {
                if (MediaCore?.State.IsPlaying ?? false)
                {
                    this.LogDebug(Aspects.VideoRenderer, $"{nameof(VideoRenderer)} frame skipped at {mediaBlock.StartTime}");
                }

                return;
            }

            // Flag the start of a rendering cycle
            IsRenderingInProgress.Value = true;

            // Send the packets to the CC renderer
            MediaElement?.CaptionsView?.SendPackets(block, MediaCore);

            // Create an action that holds GUI thread actions
            var foregroundAction = new Action(() =>
            {
                MediaElement?.CaptionsView?.Render(MediaElement.ClosedCaptionsChannel, clockPosition);
                ApplyLayoutTransforms(block);
            });

            var canStartForegroundTask = MediaElement.VideoView.ElementDispatcher != MediaElement.Dispatcher;
            var foregroundTask         = canStartForegroundTask ?
                                         MediaElement.Dispatcher.InvokeAsync(foregroundAction) : null;

            // Ensure the target bitmap can be loaded
            MediaElement?.VideoView?.InvokeAsync(DispatcherPriority.Render, () =>
            {
                if (block.IsDisposed)
                {
                    IsRenderingInProgress.Value = false;
                    return;
                }

                // Run the foreground action if we could not start it in parallel.
                if (foregroundTask == null)
                {
                    try
                    {
                        foregroundAction();
                    }
                    catch (Exception ex)
                    {
                        this.LogError(Aspects.VideoRenderer, $"{nameof(VideoRenderer)}.{nameof(Render)} layout/CC failed.", ex);
                    }
                }

                try
                {
                    // Render the bitmap data
                    var bitmapData = LockTargetBitmap(block);
                    if (bitmapData == null)
                    {
                        return;
                    }

                    LoadTargetBitmapBuffer(bitmapData, block);
                    MediaElement.RaiseRenderingVideoEvent(block, bitmapData, clockPosition);
                    RenderTargetBitmap(bitmapData);
                }
                catch (Exception ex)
                {
                    this.LogError(Aspects.VideoRenderer, $"{nameof(VideoRenderer)}.{nameof(Render)} bitmap failed.", ex);
                }
                finally
                {
                    if (foregroundTask != null)
                    {
                        try
                        {
                            foregroundTask.Wait();
                        }
                        catch (Exception ex)
                        {
                            this.LogError(Aspects.VideoRenderer, $"{nameof(VideoRenderer)}.{nameof(Render)} layout/CC failed.", ex);
                        }
                    }

                    // Always reset the rendering state
                    IsRenderingInProgress.Value = false;
                }
            });
        }
Example #25
0
        private void Window_KeyUp(object sender, KeyEventArgs e)
        {
            switch (e.Key)
            {
            case Key.P:
            {
                if (isVideoQuestion)
                {
                    if (isVideoPlay)
                    {
                        MediaBlock.Pause();
                    }
                    else
                    {
                        MediaBlock.Play();
                    }

                    isVideoPlay = !isVideoPlay;
                }

                if (isVideoRightAnswer)
                {
                    if (isRightAnswerVideoPlay)
                    {
                        RightAnswerMediaBlock.Pause();
                    }
                    else
                    {
                        RightAnswerMediaBlock.Play();
                    }

                    isRightAnswerVideoPlay = !isRightAnswerVideoPlay;
                }
                break;
            }

            case Key.R:
            {
                if (isVideoQuestion)
                {
                    MediaBlock.Stop();
                    MediaBlock.Play();
                    isVideoPlay = true;
                }

                if (isVideoRightAnswer)
                {
                    MediaBlock.Stop();
                    MediaBlock.Play();
                    isRightAnswerVideoPlay = true;
                }
                break;
            }
            }

            if (!isQuizStarted)
            {
                return;
            }

            if (e.Key == Key.Enter)
            {
                if (isAddPointsWindowOpened)
                {
                    if (ActivePlayer != null && ActivePlayer.PlayerIndex >= 0)
                    {
                        if (quizManager.AddedPoints())
                        {
                            HideBlacker();
                        }
                        else
                        {
                            ShowBlacker();
                        }


                        isAddPointsWindowOpened = false;

                        AddPointsMenu.Visibility = Visibility.Collapsed;

                        if (isAddingPointNecessary)
                        {
                            AddPoints(ActivePlayer.PlayerIndex, Convert.ToDouble(AddingPointsTextBlock.Text));
                            QuizManager_OnRightAnswer(0, true);
                            MediaGrid.Visibility       = Visibility.Hidden;
                            RightAnswerGrid.Visibility = Visibility.Visible;
                            isAddingPointNecessary     = false;
                            return;
                        }

                        HideBlacker();
                        AddPoints(ActivePlayer.PlayerIndex, Convert.ToDouble(AddingPointsTextBlock.Text));

                        isAddingPointNecessary   = false;
                        closedElement.Visibility = Visibility.Visible;
                    }
                }
            }

            if (e.Key == Key.Escape)
            {
                if (isAddPointsWindowOpened)
                {
                    if (!isAddingPointNecessary)
                    {
                        AddPointsMenu.Visibility = Visibility.Hidden;
                        closedElement.Visibility = Visibility.Visible;
                        HideBlacker();
                    }
                }
            }

            if (isAddPointsWindowOpened)
            {
                if (Char.IsDigit((char)KeyInterop.VirtualKeyFromKey(e.Key)) && e.Key != Key.Back || e.Key == Key.Space)
                {
                    if ((int)(((char)KeyInterop.VirtualKeyFromKey(e.Key)) - '0') > Players.Count || (int)(((char)KeyInterop.VirtualKeyFromKey(e.Key)) - '0') == 0)
                    {
                        return;
                    }

                    ActivePlayer = Players[(int)(((char)KeyInterop.VirtualKeyFromKey(e.Key)) - '0') - 1];
                }
                else
                {
                    return;
                }
            }

            switch (e.Key)
            {
            case Key.Y:
            {
                quizManager.RightAnswerClick();
                break;
            }

            case Key.N:
            {
                quizManager.WrongAnswerClick();
                break;
            }

            case Key.S:
            {
                quizManager.StartButtonListener(StartTimer);
                break;
            }

            case Key.C:
            {
                quizManager.Next();
                break;
            }

            case Key.Q:
            {
                ShowBlacker();
                isAddingPointNecessary   = false;
                AddPointsMenu.Visibility = Visibility.Visible;
                ActivePlayer             = null;

                if (RightAnswerGrid.Visibility == Visibility.Visible)
                {
                    closedElement = RightAnswerGrid;
                    RightAnswerGrid.Visibility = Visibility.Hidden;
                }
                else if (MediaGrid.Visibility == Visibility.Visible)
                {
                    closedElement        = MediaGrid;
                    MediaGrid.Visibility = Visibility.Hidden;
                }
                else if (MainSettingsGrid.Visibility == Visibility.Visible)
                {
                    closedElement = MainSettingsGrid;
                    MainSettingsGrid.Visibility = Visibility.Hidden;
                }

                isAddPointsWindowOpened = true;

                quizManager.StopQuiz();

                break;
            }
            }
        }