In the player templates for Expression Encoder 3 and 4 the “Silverlight Default” and “Smooth Streaming Graphic Player” provide a complex diagnostic graph that provides a lot of detailed information about which bitrate is being played and how well it is being played.  This UI is useful for debugging and diagnostic purposes – but has excessive technical detail for general usage.   Here a simplified UI is presented that is more suitable for general usage.  The simplified UI can be more readily adapted to application specific needs that the more complex graphing UI.
 

Step 1: Create a custom template.  In Encoder select the template you want to base your custom template on and using the command “Edit copy of template in Visual Studio”.  – See prior blog post “Making a simple appearance change to an Expression Encoder 4 template using Expression Blend”  for a more detailed checklist on how to do this step.

 

Step 2: Add custom interface required.  In Visual Studio find the “PlugInMSSCtrl” project and in that open “PlugInMSSCtrl.cs” in Visual Studio – at the bottom of the file add the following interface definition:

 

    /// <summary>

    /// Interface for providing a simplified quality UI

    /// </summary>

    public interface IPlugInMssSimpleQualityUI

    {

        /// <summary>

        /// UIElement to be inserted into the visual tree to display a simple indicator playback quality.

        /// </summary>

        UIElement SimpleQualityUI { get; }

    }

 

Step 3:  Prepare the player to use the simplified UI.   In the “MediaPlayer” project, edit the file “MediaPlayerAdaptiveSupport.cs”  -- near the bottom of the file – find a method named “StartSmoothStreamingPlayback”   In this method, find this bit of code:

 

            // Display stats graph if this template has a slot for it.

            if (this.m_gridPlugIn != null)

            {

                IPlugInMssStatisticsGraph plugInGraph = this.m_mediaElementForSmoothStreamingContent as IPlugInMssStatisticsGraph;

                if (plugInGraph != null)

                {

                    this.m_gridPlugIn.Children.Clear(); // Remove all prior plug ins

                    this.m_gridPlugIn.Children.Add(plugInGraph.StatisticsGraph);

                }

            }

 

and replace it with this:

 

            // Display stats graph if this template has a slot for it.

            if (this.m_gridPlugIn != null)

            {

                var w = this.m_gridPlugIn.ActualWidth;

                if (w > 100)

                {

                    IPlugInMssStatisticsGraph plugInGraph = this.m_mediaElementForSmoothStreamingContent as IPlugInMssStatisticsGraph;

                    if (plugInGraph != null)

                    {

                        this.m_gridPlugIn.Children.Clear(); // Remove all prior plug ins

                        this.m_gridPlugIn.Children.Add(plugInGraph.StatisticsGraph);

                    }

                }

                else

                {

                    IPlugInMssSimpleQualityUI plugInSimpleUI = this.m_mediaElementForSmoothStreamingContent as IPlugInMssSimpleQualityUI;

                    if (plugInSimpleUI != null)

                    {

                        this.m_gridPlugIn.Children.Clear(); // Remove all prior plug ins

                        this.m_gridPlugIn.Children.Add(plugInSimpleUI.SimpleQualityUI);

                    }

                }

            }

 

Step 4: Add UI place holder for the simple UI – in this example it is added to bottom of the videoWindowGrid – but it could be added wherever makes sense for your application.  It could also be easily added to the “miscControls” StackPanel.

 

<Grid x:Name="gridPlugIn" Height="32" Width="35" HorizontalAlignment="Right" VerticalAlignment="Bottom" Background="#00FFFFFF" Opacity="1" IsHitTestVisible="False" Margin="3"/>

 

 

Step 5: Rebuild the customized player.

 

Step 6: Begin Adding Simplifed UI to the Smooth Streaming plug-in.  In Visual Studio right click on the “PlugInMSSCtrl” project and select “Open Folder In Windows Explorer”  -- in Explorer 1st navigate up on level to the “templates” directory – then navigate down into the “SmoothStreamingMediaElement” directory.  In that directory, find the “SmoothStreamingMediaElement.SLN” file and open it in Visual Studio.   Do a “find in files” search for  “IPlugInMssStatisticsGraph”  -- there should be four matches – in two of those matches:

 

replace this line:

 

    public partial class SmoothStreamingMediaElementShim : MediaElementShim, IPlugInMssStatisticsGraph

 

with this line:

 

    public partial class SmoothStreamingMediaElementShim : MediaElementShim, IPlugInMssStatisticsGraph, IPlugInMssSimpleQualityUI

 

Step 7: Do a “find in files” search for  “UIElement StatisticsGraph” – in the match contained within “SmoothStreamingMediaElementShim,cs”  add the following code below the body of the StatisticsGraph property

 

        private UIElement m_plugInSimpleQualityUI;

        public UIElement SimpleQualityUI

        {

            get

            {

                // Initialize plugin UI

                if (m_plugInSimpleQualityUI == null)

                {

                    m_plugInSimpleQualityUI = new SimplfiedQualityUI(this);

                }

                return m_plugInSimpleQualityUI;

            }

        }

 

Step 8: Add actual simplfied UI.   In Visual Studio,  Right-Click on the “SmoothStreamingMediaElement” project and select “Add->Class” – Select “Silverlight User Control” and then type “SimplfiedQualityUI” as the name.  In SimplifiedQualityUI.XAML modify the XAML to this:

 

<UserControl x:Class="SmoothStreaming.SimplfiedQualityUI"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    mc:Ignorable="d">

 

    <Grid x:Name="LayoutRoot" Background="Transparent" HorizontalAlignment="Center" VerticalAlignment="Center" MinWidth="32" MinHeight="32">

        <TextBlock x:Name="qualityText" Text="" FontSize="10" Foreground="#55FFDDFF" VerticalAlignment="Center" HorizontalAlignment="Center"/>

    </Grid>

</UserControl>

 

Step 9:  Add the simplified UI code into SimplifiedQualityUI.XAML.cs

 

namespace SmoothStreaming

{

    using System;

    using System.Collections;

    using System.Collections.Generic;

    using System.Diagnostics;

    using System.Globalization;

    using System.Windows;

    using System.Windows.Controls;

    using System.Windows.Input;

    using System.Windows.Media;

    using System.Windows.Media.Animation;

    using System.Windows.Shapes;

    using System.Windows.Threading;

    using Microsoft.Expression.Encoder.PlugInMssCtrl;

    using Microsoft.Web.Media.SmoothStreaming;

 

    public partial class SimplfiedQualityUI : UserControl

    {

        private SimplfiedQualityUI()

        {

            InitializeComponent();

        }

 

        /// <summary>

        /// The actual streaming source object.

        /// </summary>

        private SmoothStreamingMediaElement m_ssme;

 

        /// <summary>

        /// The shim object to access helper methods

        /// </summary>

        private SmoothStreamingMediaElementShim m_shim;

 

        /// <summary>

        /// The current playing bitrate.

        /// </summary>

        private ulong m_nowPlayingBitrate;

        private uint m_nowPlayingBitrateHeight;

 

        /// <summary>

        /// Table of bitrates to vertical resolution

        /// </summary>

        private Dictionary<ulong, uint> m_trackHeights;

 

        /// <summary>

        /// A timer which tracks the stats of the media element

        /// </summary>

        private DispatcherTimer m_timerUIThread;

 

        /// <summary>

        /// Initializes a new instance of the SmoothStreamingUI class.

        /// </summary>

        /// <param name="source">The smooth streaming source.</param>

        internal SimplfiedQualityUI(SmoothStreamingMediaElementShim shim)

        {

            InitializeComponent();

 

            if (shim != null)

            {

                this.m_shim = shim;

                this.m_ssme = shim.ActualMediaElement;

                if (this.m_ssme != null)

                {

                    this.m_ssme.MediaOpened += new RoutedEventHandler(OnMediaElementMediaOpened);

                    this.m_ssme.PlaybackTrackChanged += new EventHandler<TrackChangedEventArgs>(OnPlayBitrateChange);

                }

            }

        }

 

        /// <summary>

        /// Callback for the play bitrate changed event.

        /// </summary>

        /// <param name="sender">The object that sent this event</param>

        /// <param name="e">Event args for this event</param>

        public void OnPlayBitrateChange(object sender, TrackChangedEventArgs e)

        {

            if (e.StreamType == MediaStreamType.Video)

            {

                this.m_nowPlayingBitrate = e.NewTrack.Bitrate;

                uint tmp;

                if (this.m_trackHeights.TryGetValue(m_nowPlayingBitrate, out tmp))

                {

                    this.m_nowPlayingBitrateHeight = tmp;

                }

                this.qualityText.Text = GetQualityText(this.m_nowPlayingBitrateHeight);

            }

        }

 

        /// <summary>

        /// Initialize bitrate graph labels

        /// </summary>

        private void InitBitrates()

        {

            this.m_trackHeights = new Dictionary<ulong, uint>();

            if (this.m_ssme != null)

            {

                foreach (var segment in this.m_ssme.ManifestInfo.Segments)

                {

                    foreach (var stream in segment.AvailableStreams)

                    {

                        if (stream.Type == MediaStreamType.Video)

                        {

                            foreach (var track in stream.AvailableTracks)

                            {

                                uint trackHeight = CPUHeuristic.GetTrackHeight(track);

                                this.m_trackHeights.Add(track.Bitrate, trackHeight);

                            }

                        }

                    }

                }

            }

        }

 

        private static string GetQualityText(uint height)

        {

            string qualityText = string.Empty;

            if (height >= 1080)

            {

                qualityText = "1080P";

            }

            else if (height > 720)

            {

                qualityText = "720P+";

            }

            else if (height == 720)

            {

                qualityText = "720P";

            }

            else if (height >= 480)

            {

                qualityText = "SD";

            }

            else

            {

                qualityText = "LD";

            }

            return qualityText;

        }

 

        /// <summary>

        /// Event handler for the media opened event from the media element.

        /// </summary>

        /// <param name="sender">Source of the event.</param>

        /// <param name="e">Event args.</param>

        private void OnMediaElementMediaOpened(object sender, RoutedEventArgs e)

        {

            InitBitrates();

        }

    }

}

 Step 10:  Rebuild the “SmoothStreamingMediaElement” solution.   Once it rebuilds correctly – right click on the “SmoothStreamingMediaElement” in the Visual Studio “Solution Explorer” and “Open Folder in Windows Explorer”  -- in Explorer find the rebuild “SmoothStreaming.XAP” and copy to the template directory for the customized template – replacing the older version of”SmoothStreaming.XAP” lurking there.

 Step 11: Use in Expression Encoder 4 

This information is provided "AS IS" with no warrantee and confers no rights.