Пример #1
0
 void OnItemRemoved(SmoothStreamingEvent entry)
 {
     if (ItemRemoved != null)
     {
         ItemRemoved(this, new SimpleEventArgs <SmoothStreamingEvent>(entry));
     }
 }
        void AddEvent(SmoothStreamingEvent entry)
        {
            // check for a latency alert
            if (entry.EventType == EventType.PerceivedBandwidth)
            {
                perceivedKBps = entry.Value / (8192);
            }
            else if (entry.EventType == EventType.VideoChunkDownload || entry.EventType == EventType.AudioChunkDownload)
            {
                if (entry.Value > 75)
                {
                    double dataSize           = double.Parse(entry.Data3, CultureInfo.CurrentCulture) / 1024;
                    double observedThroughput = dataSize / ((entry.Value - 75) / 1000);
                    if (observedThroughput < (perceivedKBps / Configuration.LatencyAlertThreshold))
                    {
                        if (LatencyAlert != null)
                        {
                            LatencyAlert(this, new SimpleEventArgs <SmoothStreamingEvent>(entry));
                        }
                    }
                }
            }

            // give the agents an opportunity to care about this event
            agent.ProcessEvent(entry);
            if (EventCreated != null)
            {
                EventCreated(this, new SimpleEventArgs <SmoothStreamingEvent>(entry));
            }
        }
 void OnItemRemoved(SmoothStreamingEvent entry)
 {
     if (ItemRemoved != null)
     {
         ItemRemoved(this, new SimpleEventArgs<SmoothStreamingEvent>(entry));
     }
 }
Пример #4
0
        /// <summary>
        /// Gets the total time that an event occurred by adding future timespans (the time between itself and the next event)
        /// </summary>
        /// <param name="condition">A predicate for determining which values to factor into the result</param>
        public TimeSpan GetTotalTime(Predicate <double> condition)
        {
            long   now       = DateTime.Now.Ticks;
            long   lastTime  = Math.Max(now - SlidingWindowTicks, startTicks.Value);
            double lastValue = previousEntry == null ? 0 : previousEntry.Value;
            SmoothStreamingEvent lastEntry = previousEntryOrMarker ?? new MarkerEventStart();
            long runningTotal = 0;

            foreach (SmoothStreamingEvent item in queue)
            {
                if (!(item is MarkerEventStart && lastEntry is MarkerEventStop))
                {
                    if (condition == null || condition(lastValue))
                    {
                        runningTotal += item.Ticks - lastTime;
                        if (!(item is MarkerEvent))
                        {
                            lastValue = item.Value;
                        }
                    }
                }
                lastEntry = item;
                lastTime  = item.Ticks;
            }

            if (!(lastEntry is MarkerEventStop))
            {
                if (condition == null || condition(lastValue))
                {
                    runningTotal += now - lastTime;
                }
            }

            return(TimeSpan.FromTicks(runningTotal));
        }
Пример #5
0
 static void OnReportTraceEvent(SmoothStreamingEvent e)
 {
     if (ReportTraceEvent != null)
     {
         ReportTraceEvent(e);
     }
 }
        void mediaElement_ManifestReady(object sender, EventArgs e)
        {
            startedPlay = false;    // flag used to tell us when the video actually starts playing
            SmoothStreamingEvent ssEvent = new SmoothStreamingEvent();

            ssEvent.EventType = EventType.StreamLoaded;
            ssEvent.Data1     = GetUrlWithoutQueryString(mediaElement.SmoothStreamingSource);
            SmoothStreamingSourceChanged(ssEvent.Data1);
            foreach (SegmentInfo segment in mediaElement.ManifestInfo.Segments)
            {
                foreach (StreamInfo stream in segment.AvailableStreams)
                {
                    if (stream.Type == MediaStreamType.Video)
                    {
                        ulong bitrate = 0;
                        foreach (TrackInfo track in stream.AvailableTracks)
                        {
                            if (track.Bitrate > bitrate)
                            {
                                bitrate = track.Bitrate;
                            }
                        }
                        ssEvent.Data2 = bitrate.ToString(CultureInfo.InvariantCulture);
                    }
                }
            }
            Enqueue(ssEvent);
        }
Пример #7
0
        static void RecordCpuUsage()
        {
            try
            {
                InitializeAnalytics();
                if (config.RecordCpuLoad)
                {
                    float totalLoad = analytics.AverageProcessorLoad;
                    // workaround for Silverlight 3 known issue where CPU returns 0 sometimes
                    if (totalLoad > 0)
                    {
                        float processLoad = analytics.AverageProcessLoad;
                        SmoothStreamingEvent processLoadItem = new SmoothStreamingEvent()
                        {
                            Value     = processLoad,
                            EventType = EventType.ProcessCpuLoad
                        };
                        OnReportSystemEvent(processLoadItem);

                        SmoothStreamingEvent systemLoaditem = new SmoothStreamingEvent()
                        {
                            Value     = totalLoad,
                            EventType = EventType.SystemCpuLoad
                        };
                        OnReportSystemEvent(systemLoaditem);
                    }
                }
            }
            catch
            {
                // ignore this exception, it is a known issue in Silverlight 3.
                // http://blogs.msdn.com/silverlight_sdk/archive/2009/06/05/silverlight-3-bugs.aspx
            }
        }
 void Submit(SmoothStreamingEvent entry)
 {
     if (entry != null)
     {
         if (EventCreated != null) EventCreated(this, new SimpleEventArgs<SmoothStreamingEvent>(entry));
     }
 }
 void TraceMonitor_ReportTraceEvent(SmoothStreamingEvent traceEvent)
 {
     if (mediaElementId == null || traceEvent.MediaElementId == null || traceEvent.MediaElementId == mediaElementId)
     {
         Submit(traceEvent);
     }
 }
 void ProcessQueuedEntries(SmoothStreamingEvent entry)
 {
     lock (realtimeEventQueue)
     {
         while (realtimeEventQueue.Count > 0 && (entry == null || realtimeEventQueue.Peek().Ticks < entry.Ticks))
         {
             SmoothStreamingEvent queuedEntry = realtimeEventQueue.Dequeue();
             if (queuedEntry.EventType == EventType.ClipStarted)
             {
                 CurrentClipId = queuedEntry.ClipId;
                 if (entry != null)
                 {
                     entry.ClipId = queuedEntry.ClipId;
                 }
             }
             else if (queuedEntry.EventType == EventType.StreamLoaded)
             {
                 CurrentStreamId      = TraceMonitor.GenerateStreamIdentifier();
                 queuedEntry.StreamId = CurrentStreamId;
                 if (entry != null)
                 {
                     entry.StreamId = CurrentStreamId;
                 }
             }
             else
             {
                 queuedEntry.ClipId   = CurrentClipId;
                 queuedEntry.StreamId = CurrentStreamId;
             }
             AddEvent(queuedEntry);
         }
     }
 }
        void mediaElement_MediaEnded(object sender, RoutedEventArgs e)
        {
            SmoothStreamingEvent ssEvent = new SmoothStreamingEvent();

            ssEvent.EventType = EventType.StreamEnded;
            ssEvent.Data1     = GetUrlWithoutQueryString(mediaElement.SmoothStreamingSource);
            Enqueue(ssEvent);
        }
 void Enqueue(SmoothStreamingEvent entry)
 {
     StampEvent(entry);
     lock (realtimeEventQueue)
     {
         realtimeEventQueue.Enqueue(entry);
     }
 }
 /// <summary>
 /// Accepts new entries for aggregating
 /// </summary>
 /// <param name="entry">The new smoothstreamingevent to process</param>
 public virtual void ProcessEvent(SmoothStreamingEvent entry)
 {
     if (entry is MarkerEvent)
     {
         isPlayingVideo = !(entry is MarkerEventStop);
         sampleSizeAggregator.Enqueue(entry);
     }
 }
 /// <summary>
 /// Accepts new entries for aggregating
 /// </summary>
 /// <param name="entry">The new smoothstreamingevent to process</param>
 public virtual void ProcessEvent(SmoothStreamingEvent entry)
 {
     if (entry is MarkerEvent)
     {
         isPlayingVideo = !(entry is MarkerEventStop);
         sampleSizeAggregator.Enqueue(entry);
     }
 }
        void SetPlaybackRate(long ticks, int rate)
        {
            SmoothStreamingEvent ssEvent = new SmoothStreamingEvent();

            ssEvent.Ticks     = ticks;
            ssEvent.Value     = rate;
            ssEvent.EventType = EventType.SetPlaybackRate;
            Submit(ssEvent);
        }
        void SmoothStreamingSourceChanged(string url)
        {
            Uri currentStreamUri = new Uri(url, UriKind.Absolute);

            IsEdgeServerComplete = false;
            EdgeServer           = EdgeServerDataClient.IpNA; // clear the current edge server
            ClientIP             = EdgeServerDataClient.IpNA;

            if (Configuration.EdgeServerRuleCollection != null)
            {
                EdgeServerRules addressRules = Configuration.EdgeServerRuleCollection.FirstOrDefault(ai => ai.Domain != null && currentStreamUri.Host.EndsWith(ai.Domain, StringComparison.OrdinalIgnoreCase));
                // fallback on the address rules without a domain
                if (addressRules == null)
                {
                    addressRules = Configuration.EdgeServerRuleCollection.FirstOrDefault(ai => ai.Domain == null);
                }
                try
                {
                    if (addressRules != null)
                    {
                        EdgeServerDataClient edgeServerDataClient = new EdgeServerDataClient();
                        edgeServerDataClient.GetEdgeServerCompleted += (s, e) =>
                        {
                            // warning: this can come back after we've shut down, checking for the mediaelement is a good way to ensure we're still supposed to be tracking
                            if (mediaElement != null)
                            {
                                if (e.Result != null)
                                {
                                    EdgeServer = e.Result.EdgeServer;
                                    ClientIP   = e.Result.ClientIP;
                                }
                                FinishSettingEdgeServer();

                                SmoothStreamingEvent entry = new SmoothStreamingEvent();
                                entry.EventType = EventType.AddressInfo;
                                entry.Data1     = ClientIP.ToString();
                                entry.Data2     = EdgeServer;
                                Enqueue(entry);
                            }
                        };
                        edgeServerDataClient.GetEdgeServerAsync(addressRules, currentStreamUri);
                    }
                    else
                    {
                        FinishSettingEdgeServer();
                    }
                }
                catch
                {
                    FinishSettingEdgeServer();
                }
            }
            else
            {
                FinishSettingEdgeServer();
            }
        }
 void Submit(SmoothStreamingEvent entry)
 {
     if (entry != null)
     {
         if (EventCreated != null)
         {
             EventCreated(this, new SimpleEventArgs <SmoothStreamingEvent>(entry));
         }
     }
 }
        void mediaElement_SmoothStreamingErrorOccurred(object sender, SmoothStreamingErrorEventArgs e)
        {
            SmoothStreamingEvent mediaFailedEvent = new SmoothStreamingEvent();

            mediaFailedEvent.EventType = EventType.MediaFailed;
            mediaFailedEvent.Data1     = e.ErrorMessage;
            mediaFailedEvent.Data2     = GetUrlWithoutQueryString(mediaElement.SmoothStreamingSource);
            mediaFailedEvent.Data3     = mediaElement.Position.TotalSeconds.ToString(CultureInfo.CurrentCulture);
            Enqueue(mediaFailedEvent);
        }
Пример #19
0
        public SmoothStreamingEvent DequeueAggregator()
        {
            SmoothStreamingEvent entry = queue.Dequeue();

            if (!(entry is MarkerEvent))
            {
                count--;
                total        -= entry.Value;
                previousEntry = entry;
            }
            previousEntryOrMarker = entry;
            return(entry);
        }
        public override void ProcessEvent(SmoothStreamingEvent entry)
        {
            base.ProcessEvent(entry);

            if (entry.EventType == EventType.DownloadError)
            {
                string key = entry.Data1 + "." + entry.Data2;
                if (!aggregators.ContainsKey(key))
                    AddAggregator(key);

                SampleEventAggregator agg = aggregators[key];
                agg.Enqueue(entry);
            }
        }
Пример #21
0
 public void Enqueue(SmoothStreamingEvent entry)
 {
     queue.Enqueue(entry);
     if (!(entry is MarkerEvent))
     {
         currentEntry = entry;
         count++;
         total += entry.Value;
         if (MaxEntries >= 0 && count > MaxEntries)
         {
             SmoothStreamingEvent oldestEntry = DequeueAggregator();
             OnItemRemoved(oldestEntry);
         }
     }
 }
 void mediaElement_PlaybackTrackChanged(object sender, TrackChangedEventArgs e)
 {
     if (e.NewTrack != null)
     {
         if (e.StreamType == MediaStreamType.Video && PlaybackBitrate != e.NewTrack.Bitrate)
         {
             SmoothStreamingEvent ssEvent = new SmoothStreamingEvent();
             ssEvent.Value     = e.NewTrack.Bitrate;
             ssEvent.Data1     = PlaybackBitrate.ToString(CultureInfo.InvariantCulture);
             ssEvent.EventType = EventType.BitrateChanged;
             Enqueue(ssEvent);
             // remember value
             PlaybackBitrate = e.NewTrack.Bitrate;
         }
     }
 }
        public override void ProcessEvent(SmoothStreamingEvent entry)
        {
            base.ProcessEvent(entry);

            if (entry.EventType == EventType.DownloadError)
            {
                string key = entry.Data1 + "." + entry.Data2;
                if (!aggregators.ContainsKey(key))
                {
                    AddAggregator(key);
                }

                SampleEventAggregator agg = aggregators[key];
                agg.Enqueue(entry);
            }
        }
        static SmoothStreamingEvent ConvertTraceToEvent(TraceEntry entry, EventType eventType, string regexString)
        {
            Regex regex = new Regex(regexString);

            if (regex.IsMatch(entry.Text))
            {
                SmoothStreamingEvent ssEvent = new SmoothStreamingEvent(entry);
                ssEvent.EventType      = eventType;
                ssEvent.Message        = entry.Text;
                ssEvent.MediaElementId = entry.MediaElementId;
                var matches      = regex.Matches(entry.Text);
                var valueCapture = matches[0].Groups["v"].Captures;
                if (valueCapture.Count > 0)
                {
                    double value;
                    if (double.TryParse(valueCapture[0].Value, NumberStyles.None, CultureInfo.CurrentCulture, out value))
                    {
                        ssEvent.Value = value;
                    }
                    else
                    {
                        ssEvent.Value = 0;
                    }
                }
                var data1Capture = matches[0].Groups["d1"].Captures;
                if (data1Capture.Count > 0)
                {
                    ssEvent.Data1 = data1Capture[0].Value;
                }
                var data2Capture = matches[0].Groups["d2"].Captures;
                if (data2Capture.Count > 0)
                {
                    ssEvent.Data2 = data2Capture[0].Value;
                }
                var data3Capture = matches[0].Groups["d3"].Captures;
                if (data3Capture.Count > 0)
                {
                    ssEvent.Data3 = data3Capture[0].Value;
                }
                return(ssEvent);
            }
            else
            {
                return(null);
            }
        }
        void ProcessBufferingEngineMessage(TraceEntry entry)
        {
            if (entry.MethodName == "AddChunkToCache")
            {
                SmoothStreamingEvent ssEvent = ConvertTraceToEvent(entry, EventType.VideoBufferSize, "Added (?<d2>.*) chunk with duration (?<d1>.*) to cache. Size including active chunk (?<v>.*) ms");
                if (ssEvent != null)
                {
                    if (ssEvent.Data2 == "Audio")
                    {
                        ssEvent.EventType = EventType.AudioBufferSize;
                    }
                    Submit(ssEvent);
                }
            }
            else if (entry.MethodName == "RaiseBufferChangedEvent")
            {
                SmoothStreamingEvent ssEvent = ConvertTraceToEvent(entry, EventType.BufferingStateChanged, "Rebuffer State: (?<d1>.), (?<d2>.*)");
                if (ssEvent != null)
                {
                    switch (ssEvent.Data1)
                    {
                    case "a":
                        ssEvent.Value = 0;
                        ssEvent.Data1 = "NotRebuffering";
                        break;

                    case "b":
                        ssEvent.Value = 1;
                        ssEvent.Data1 = "RebufferingDueToSeek";
                        break;

                    case "c":
                        ssEvent.Value = 1;
                        ssEvent.Data1 = "RebufferingDueToStartPlayback";
                        break;

                    case "d":
                        ssEvent.Value = 1;
                        ssEvent.Data1 = "RebufferingDueToUnderflow";
                        break;
                    }
                    Submit(ssEvent);
                }
            }
        }
        /// <summary>
        /// Add a new entry to the proper aggregator so that it can be tracked and evaluated.
        /// </summary>
        /// <param name="entry"></param>
        public void ProcessEvent(SmoothStreamingEvent entry)
        {
            if (entry != null)
            {
                if (entry.EventType == EventType.None)
                {
                    throw (new ArgumentException("Smooth Streaming Events must have an event type"));
                }
                else if (entry.EventType == EventType.ClipStarted ||
                         entry.EventType == EventType.ClipEnded ||
                         entry.EventType == EventType.StreamLoaded ||
                         entry.EventType == EventType.StreamStarted ||
                         entry.EventType == EventType.StreamEnded ||
                         entry.EventType == EventType.Paused ||
                         entry.EventType == EventType.Playing)
                {
                    if (entry.Ticks > lastAggregateUpdateTime)
                    {
                        lastAggregateUpdateTime = entry.Ticks;
                    }
                    if (entry.EventType == EventType.StreamLoaded)
                    {
                        currentStreamUrl = entry.Data1;
                    }
                    else if (entry.EventType == EventType.StreamStarted)
                    {
                        IsEnabled = true;
                    }
                    else if (entry.EventType == EventType.Playing)
                    {
                        IsEnabled = true;
                    }
                    else if (entry.EventType == EventType.StreamEnded || entry.EventType == EventType.Paused)
                    {
                        IsEnabled = false;
                    }
                }

                // pass the events to the sub agents
                foreach (var agent in agents)
                {
                    agent.ProcessEvent(entry);
                }
            }
        }
 void mediaElement_ClipProgressUpdate(object sender, ClipPlaybackEventArgs e)
 {
     if (e.Progress == ClipProgress.Start)
     {
         SmoothStreamingEvent ssEvent = new SmoothStreamingEvent();
         ssEvent.Data1     = e.Context.ClipInformation.ClipUri.ToString();
         ssEvent.EventType = EventType.ClipStarted;
         ssEvent.ClipId    = TraceMonitor.GenerateStreamIdentifier();
         Enqueue(ssEvent);
     }
     else if (e.Progress == ClipProgress.Complete)
     {
         SmoothStreamingEvent ssEvent = new SmoothStreamingEvent();
         ssEvent.EventType = EventType.ClipEnded;
         ssEvent.Data1     = e.Context.ClipInformation.ClipUri.ToString();
         Enqueue(ssEvent);
     }
 }
        void Content_FullScreenChanged(object sender, EventArgs e)
        {
            bool isFullScreen          = Application.Current.Host.Content.IsFullScreen;
            SmoothStreamingEvent entry = new SmoothStreamingEvent();

            entry.EventType = EventType.FullScreenChanged;
            if (isFullScreen)
            {
                entry.Value = 1;
                entry.Data1 = "True";
            }
            else
            {
                entry.Value = 0;
                entry.Data1 = "False";
            }
            Enqueue(entry);
        }
Пример #29
0
        /// <summary>
        /// Gets a average of the event values weighted by their timespan.
        /// Weighted values are weighted by the timespan between itself and the next event.
        /// Time in between stop and start markers is not counted.
        /// </summary>
        public double GetAverageOverTime()
        {
            long   now       = DateTime.Now.Ticks;
            long   lastTime  = Math.Max(now - SlidingWindowTicks, startTicks.Value);
            double lastValue = previousEntry == null ? 0 : previousEntry.Value;
            SmoothStreamingEvent lastEntry = previousEntryOrMarker ?? new MarkerEventStart();
            long   aggregatedTicks         = 0;
            double aggregatedValue         = 0;
            long   elapsedTicks            = 0;

            foreach (SmoothStreamingEvent item in queue)
            {
                if (!(item is MarkerEventStart && lastEntry is MarkerEventStop))
                {
                    elapsedTicks += item.Ticks - lastTime;
                    if (!(item is MarkerEvent))
                    {
                        aggregatedValue += lastValue * elapsedTicks;
                        aggregatedTicks += elapsedTicks;
                        elapsedTicks     = 0;
                        lastValue        = item.Value;
                    }
                }
                lastEntry = item;
                lastTime  = item.Ticks;
            }

            if (!(lastEntry is MarkerEventStop))
            {
                elapsedTicks     = now - lastTime;
                aggregatedValue += lastValue * elapsedTicks;
                aggregatedTicks += elapsedTicks;
            }

            if (aggregatedTicks == 0)
            {
                return(0);
            }
            else
            {
                return(aggregatedValue / aggregatedTicks);
            }
        }
Пример #30
0
        /// <summary>
        /// Refreshes the queue by causing items that were created longer ago than the SlidingWindowTicks property to get dropped
        /// </summary>
        public void Update(long currentTicks)
        {
            if (SlidingWindowTicks < 0)
            {
                return;
            }

            if (!startTicks.HasValue)
            {
                startTicks = currentTicks;
            }
            long windowStart = currentTicks - SlidingWindowTicks;

            while (queue.Count > 0 && Peek().Ticks < windowStart)
            {
                SmoothStreamingEvent entry = DequeueAggregator();
                OnItemRemoved(entry);
            }
        }
        public override void ProcessEvent(SmoothStreamingEvent entry)
        {
            base.ProcessEvent(entry);

            if (entry is MarkerEvent)
            {
                foreach (SampleEventAggregator agg in aggregators.Values)
                {
                    agg.Enqueue(entry);
                }
            }
            else
            {
                if (aggregators.ContainsKey(entry.EventType))
                {
                    aggregators[entry.EventType].Enqueue(entry);
                }
            }
        }
        /// <summary>
        /// Add a new entry to the proper aggregator so that it can be tracked and evaluated.
        /// </summary>
        /// <param name="entry"></param>
        public void ProcessEvent(SmoothStreamingEvent entry)
        {
            if (entry != null)
            {
                if (entry.EventType == EventType.None)
                {
                    throw (new ArgumentException("Smooth Streaming Events must have an event type"));
                }
                else if (entry.EventType == EventType.ClipStarted ||
                    entry.EventType == EventType.ClipEnded ||
                    entry.EventType == EventType.StreamLoaded ||
                    entry.EventType == EventType.StreamStarted ||
                    entry.EventType == EventType.StreamEnded ||
                    entry.EventType == EventType.Paused ||
                    entry.EventType == EventType.Playing)
                {
                    if (entry.Ticks > lastAggregateUpdateTime)
                    {
                        lastAggregateUpdateTime = entry.Ticks;
                    }
                    if (entry.EventType == EventType.StreamLoaded)
                    {
                        currentStreamUrl = entry.Data1;
                    }
                    else if (entry.EventType == EventType.StreamStarted)
                    {
                        IsEnabled = true;
                    }
                    else if (entry.EventType == EventType.Playing)
                    {
                        IsEnabled = true;
                    }
                    else if (entry.EventType == EventType.StreamEnded || entry.EventType == EventType.Paused)
                    {
                        IsEnabled = false;
                    }
                }

                // pass the events to the sub agents
                foreach (var agent in agents)
                    agent.ProcessEvent(entry);
            }
        }
 static SmoothStreamingEvent ConvertTraceToEvent(TraceEntry entry, EventType eventType, string regexString)
 {
     Regex regex = new Regex(regexString);
     if (regex.IsMatch(entry.Text))
     {
         SmoothStreamingEvent ssEvent = new SmoothStreamingEvent(entry);
         ssEvent.EventType = eventType;
         ssEvent.Message = entry.Text;
         ssEvent.MediaElementId = entry.MediaElementId;
         var matches = regex.Matches(entry.Text);
         var valueCapture = matches[0].Groups["v"].Captures;
         if (valueCapture.Count > 0)
         {
             double value;
             if (double.TryParse(valueCapture[0].Value, NumberStyles.None, CultureInfo.CurrentCulture, out value))
                 ssEvent.Value = value;
             else
                 ssEvent.Value = 0;
         }
         var data1Capture = matches[0].Groups["d1"].Captures;
         if (data1Capture.Count > 0)
         {
             ssEvent.Data1 = data1Capture[0].Value;
         }
         var data2Capture = matches[0].Groups["d2"].Captures;
         if (data2Capture.Count > 0)
         {
             ssEvent.Data2 = data2Capture[0].Value;
         }
         var data3Capture = matches[0].Groups["d3"].Captures;
         if (data3Capture.Count > 0)
         {
             ssEvent.Data3 = data3Capture[0].Value;
         }
         return ssEvent;
     }
     else
     {
         return null;
     }
 }
Пример #34
0
        /// <summary>
        /// Gets the total timespan of the sample window (excluding periods of time where the video was paused or stopped)
        /// </summary>
        public TimeSpan GetWindowSize()
        {
            long now      = DateTime.Now.Ticks;
            long lastTime = Math.Max(now - SlidingWindowTicks, startTicks.Value);
            SmoothStreamingEvent lastEntry = previousEntry ?? new MarkerEventStart();
            long runningTotal = 0;

            foreach (SmoothStreamingEvent item in queue)
            {
                if (!(item is MarkerEventStart && lastEntry is MarkerEventStop))
                {
                    runningTotal += item.Ticks - lastTime;
                }
                lastEntry = item;
                lastTime  = item.Ticks;
            }

            if (!(lastEntry is MarkerEventStop))
            {
                runningTotal += now - lastTime;
            }

            return(TimeSpan.FromTicks(runningTotal));
        }
 void StampEvent(SmoothStreamingEvent entry)
 {
     entry.IsLive         = mediaElement.IsLive;
     entry.MediaElementId = mediaElementId;
 }
 void mediaElement_ManifestReady(object sender, EventArgs e)
 {
     startedPlay = false;    // flag used to tell us when the video actually starts playing
     SmoothStreamingEvent ssEvent = new SmoothStreamingEvent();
     ssEvent.EventType = EventType.StreamLoaded;
     ssEvent.Data1 = GetUrlWithoutQueryString(mediaElement.SmoothStreamingSource);
     SmoothStreamingSourceChanged(ssEvent.Data1);
     foreach (SegmentInfo segment in mediaElement.ManifestInfo.Segments)
     {
         foreach (StreamInfo stream in segment.AvailableStreams)
         {
             if (stream.Type == MediaStreamType.Video)
             {
                 ulong bitrate = 0;
                 foreach (TrackInfo track in stream.AvailableTracks)
                 {
                     if (track.Bitrate > bitrate)
                     {
                         bitrate = track.Bitrate;
                     }
                 }
                 ssEvent.Data2 = bitrate.ToString(CultureInfo.InvariantCulture);
             }
         }
     }
     Enqueue(ssEvent);
 }
 void Submit(SmoothStreamingEvent entry)
 {
     StampEvent(entry);
     ProcessQueuedEntries(entry);
     AddEvent(entry);
 }
 void ProcessQueuedEntries(SmoothStreamingEvent entry)
 {
     lock (realtimeEventQueue)
     {
         while (realtimeEventQueue.Count > 0 && (entry == null || realtimeEventQueue.Peek().Ticks < entry.Ticks))
         {
             SmoothStreamingEvent queuedEntry = realtimeEventQueue.Dequeue();
             if (queuedEntry.EventType == EventType.ClipStarted)
             {
                 CurrentClipId = queuedEntry.ClipId;
                 if (entry != null) entry.ClipId = queuedEntry.ClipId;
             }
             else if (queuedEntry.EventType == EventType.StreamLoaded)
             {
                 CurrentStreamId = TraceMonitor.GenerateStreamIdentifier();
                 queuedEntry.StreamId = CurrentStreamId;
                 if (entry != null) entry.StreamId = CurrentStreamId;
             }
             else
             {
                 queuedEntry.ClipId = CurrentClipId;
                 queuedEntry.StreamId = CurrentStreamId;
             }
             AddEvent(queuedEntry);
         }
     }
 }
 void Submit(SmoothStreamingEvent entry)
 {
     StampEvent(entry);
     ProcessQueuedEntries(entry);
     AddEvent(entry);
 }
 void StampEvent(SmoothStreamingEvent entry)
 {
     entry.IsLive = mediaElement.IsLive;
     entry.MediaElementId = mediaElementId;
 }
 void SetPlaybackRate(long ticks, int rate)
 {
     SmoothStreamingEvent ssEvent = new SmoothStreamingEvent();
     ssEvent.Ticks = ticks;
     ssEvent.Value = rate;
     ssEvent.EventType = EventType.SetPlaybackRate;
     Submit(ssEvent);
 }
 public SmoothStreamingEvent DequeueAggregator()
 {
     SmoothStreamingEvent entry = queue.Dequeue();
     if (!(entry is MarkerEvent))
     {
         count--;
         total -= entry.Value;
         previousEntry = entry;
     }
     previousEntryOrMarker = entry;
     return entry;
 }
 public void Enqueue(SmoothStreamingEvent entry)
 {
     queue.Enqueue(entry);
     if (!(entry is MarkerEvent))
     {
         currentEntry = entry;
         count++;
         total += entry.Value;
         if (MaxEntries >= 0 && count > MaxEntries)
         {
             SmoothStreamingEvent oldestEntry = DequeueAggregator();
             OnItemRemoved(oldestEntry);
         }
     }
 }
        public override void ProcessEvent(SmoothStreamingEvent entry)
        {
            base.ProcessEvent(entry);

            if (entry is MarkerEvent)
            {
                foreach (SampleEventAggregator agg in aggregators.Values)
                    agg.Enqueue(entry);
            }
            else
            {
                if (aggregators.ContainsKey(entry.EventType))
                    aggregators[entry.EventType].Enqueue(entry);
            }
        }
        /// <summary>
        /// Processes trace entries from the SSME and raises the EventCreated event for each relevant one
        /// </summary>
        /// <param name="entries">An array of SSME trace events to process</param>
        public void ParseTraceEntries(TraceEntry[] entries)
        {
            for (int i = 0; i < entries.Length; i++)
            {
                TraceEntry entry = entries[i];

                if (entry.TraceLevel == TraceLevel.Warning || entry.TraceLevel == TraceLevel.Fatal
                    || entry.TraceLevel == TraceLevel.Error || entry.TraceLevel == TraceLevel.Shutdown)
                {
                    if (entry.TraceArea == TraceArea.BufferingEngine)
                    {
                        if (entry.MethodName == "HandleDownloadError")
                        {
#if SSME_1_5_1287_0
                            SmoothStreamingEvent ssEvent = ConvertTraceToEvent(entry, EventType.DownloadError, "Download error for (?<d1>.*) chunk id (?<d2>.*) startTime (?<d3>.*) physicalStartTime (?<d4>.*) timeout = .*");
#else
                            SmoothStreamingEvent ssEvent = ConvertTraceToEvent(entry, EventType.DownloadError, "Download error for (?<d1>.*) chunk id (?<d2>.*) startTime (?<d3>.*) timeout = .*");
#endif
                            if (ssEvent != null) Submit(ssEvent);
                        }
                    }
                    else
                    {
                        SmoothStreamingEvent ssEvent = new SmoothStreamingEvent(entry);
                        ssEvent.Message = entry.Text;
                        ssEvent.Value = (int)entry.TraceLevel;
                        ssEvent.Data1 = entry.TraceLevel.ToString();
                        ssEvent.Data2 = entry.ClassName + "." + entry.MethodName;
                        ssEvent.EventType = EventType.ErrorMessage;
                        Submit(ssEvent);
                    }
                }
                else
                {
                    switch (entry.TraceArea)
                    {
                        case TraceArea.HttpWebResponse:
                            if (!entry.Text.Contains("200 OK"))
                            {
                                SmoothStreamingEvent ssEvent = ConvertTraceToEvent(entry, EventType.HttpError, "HTTP Response:  (?<v>.*) .*, NetworkingStackType: (?<d1>.*)");
                                Submit(ssEvent);
                            }
                            break;
                        case TraceArea.Heuristics:
                            if (entry.MethodName == "GetPerceivedBandwidth")
                            {
                                SmoothStreamingEvent ssEvent = ConvertTraceToEvent(entry, EventType.PerceivedBandwidth, "NetworkHeuristicsModule - Perceived bandwidth using .* sliding windows and .* method is (?<v>.*) bytes/sec \\[(?<d1>.*)\\]");
                                if (ssEvent != null) Submit(ssEvent);
                            }
                            break;
                        case TraceArea.BufferingEngine:
                            ProcessBufferingEngineMessage(entry);
                            break;
                        case TraceArea.MediaElement:
                            if (entry.MethodName == "SetPlaybackRate")
                            {
                                SmoothStreamingEvent ssEvent = ConvertTraceToEvent(entry, EventType.SetPlaybackRate, "SetPlaybackRate: (?<v>.*)");
                                if (ssEvent != null)
                                {
                                    Submit(ssEvent);
                                    SmoothStreamingEvent dvrEvent = new SmoothStreamingEvent(entry);
                                    dvrEvent.EventType = EventType.DvrOperation;
                                    dvrEvent.Message = ssEvent.Message;
                                    dvrEvent.Data1 = DvrOperationType.SetPlaybackRate.ToString();
                                    dvrEvent.Value = ssEvent.Value;
                                    Submit(dvrEvent);
                                }
                            }
                            else if (entry.MethodName == "Position_set")
                            {
                                SmoothStreamingEvent ssEvent = ConvertTraceToEvent(entry, EventType.SetPosition, "Requested position (?<v>.*) \\(SS\\)");
                                if (ssEvent != null)
                                {
                                    Submit(ssEvent);
                                    SmoothStreamingEvent dvrEvent = new SmoothStreamingEvent(entry);
                                    dvrEvent.EventType = EventType.DvrOperation;
                                    dvrEvent.Message = ssEvent.Message;
                                    dvrEvent.Data1 = DvrOperationType.SetPosition.ToString();
                                    dvrEvent.Value = ssEvent.Value;
                                    Submit(dvrEvent);
                                }
                            }
                            else if (entry.MethodName == "Pause" && entry.Text == "Pause")
                            {
                                SmoothStreamingEvent ssEvent = new SmoothStreamingEvent(entry);
                                ssEvent.EventType = EventType.SetPlaybackState;
                                ssEvent.Data1 = entry.Text;
                                Submit(ssEvent);
                                SetPlaybackRate(ssEvent.Ticks, 0);
                            }
                            else if (entry.MethodName == "Play" && entry.Text == "Play")
                            {
                                SmoothStreamingEvent ssEvent = new SmoothStreamingEvent(entry);
                                ssEvent.EventType = EventType.SetPlaybackState;
                                ssEvent.Data1 = entry.Text;
                                Submit(ssEvent);
                                SetPlaybackRate(ssEvent.Ticks, 1);
                            }
                            break;
                        case TraceArea.Test:
                            try
                            {
                                // this trace message sometimes had bad data in it
                                string[] s = entry.Text.Split(' ');
                                if (s.Length == 17 && (s[5] == "V" || s[5] == "A"))
                                {
                                    SmoothStreamingEvent ssEvent = new SmoothStreamingEvent(entry);
#if SILVERLIGHT3
                                    ssEvent.Value = TimeSpan.Parse(s[2]).TotalMilliseconds;
#else
                                    ssEvent.Value = TimeSpan.Parse(s[2], CultureInfo.CurrentCulture).TotalMilliseconds;
#endif
                                    ssEvent.Data1 = s[10];
                                    ssEvent.Data2 = s[9];
                                    ssEvent.Data3 = s[7];
                                    if (s[6] == "200")
                                    {
                                        if (s[5] == "V")
                                        {
                                            ssEvent.EventType = EventType.VideoChunkDownload;
                                        }
                                        else
                                        {
                                            ssEvent.EventType = EventType.AudioChunkDownload;
                                        }
                                    }
                                    else
                                    {
                                        ssEvent.EventType = EventType.HttpError;
                                        ssEvent.Value = int.Parse(s[6], CultureInfo.CurrentCulture);
                                    }
                                    Submit(ssEvent);
                                }
                            }
                            catch
                            {
                                // ignore this exception, must have been a bad trace message
                            }
                            break;
                    }
                }
            }
        }
 void mediaElement_SmoothStreamingErrorOccurred(object sender, SmoothStreamingErrorEventArgs e)
 {
     SmoothStreamingEvent mediaFailedEvent = new SmoothStreamingEvent();
     mediaFailedEvent.EventType = EventType.MediaFailed;
     mediaFailedEvent.Data1 = e.ErrorMessage;
     mediaFailedEvent.Data2 = GetUrlWithoutQueryString(mediaElement.SmoothStreamingSource);
     mediaFailedEvent.Data3 = mediaElement.Position.TotalSeconds.ToString(CultureInfo.CurrentCulture);
     Enqueue(mediaFailedEvent);
 }
        void SmoothStreamingSourceChanged(string url)
        {
            Uri currentStreamUri = new Uri(url, UriKind.Absolute);
            IsEdgeServerComplete = false;
            EdgeServer = EdgeServerDataClient.IpNA;  // clear the current edge server
            ClientIP = EdgeServerDataClient.IpNA;

            if (Configuration.EdgeServerRuleCollection != null)
            {
                EdgeServerRules addressRules = Configuration.EdgeServerRuleCollection.FirstOrDefault(ai => ai.Domain != null && currentStreamUri.Host.EndsWith(ai.Domain, StringComparison.OrdinalIgnoreCase));
                // fallback on the address rules without a domain
                if (addressRules == null)
                    addressRules = Configuration.EdgeServerRuleCollection.FirstOrDefault(ai => ai.Domain == null);
                try
                {
                    if (addressRules != null)
                    {
                        EdgeServerDataClient edgeServerDataClient = new EdgeServerDataClient();
                        edgeServerDataClient.GetEdgeServerCompleted += (s, e) =>
                        {
                            // warning: this can come back after we've shut down, checking for the mediaelement is a good way to ensure we're still supposed to be tracking
                            if (mediaElement != null)
                            {
                                if (e.Result != null)
                                {
                                    EdgeServer = e.Result.EdgeServer;
                                    ClientIP = e.Result.ClientIP;
                                }
                                FinishSettingEdgeServer();

                                SmoothStreamingEvent entry = new SmoothStreamingEvent();
                                entry.EventType = EventType.AddressInfo;
                                entry.Data1 = ClientIP.ToString();
                                entry.Data2 = EdgeServer;
                                Enqueue(entry);
                            }
                        };
                        edgeServerDataClient.GetEdgeServerAsync(addressRules, currentStreamUri);
                    }
                    else
                        FinishSettingEdgeServer();
                }
                catch
                {
                    FinishSettingEdgeServer();
                }
            }
            else
                FinishSettingEdgeServer();
        }
 void Content_FullScreenChanged(object sender, EventArgs e)
 {
     bool isFullScreen = Application.Current.Host.Content.IsFullScreen;
     SmoothStreamingEvent entry = new SmoothStreamingEvent();
     entry.EventType = EventType.FullScreenChanged;
     if (isFullScreen)
     {
         entry.Value = 1;
         entry.Data1 = "True";
     }
     else
     {
         entry.Value = 0;
         entry.Data1 = "False";
     }
     Enqueue(entry);
 }
 void mediaElement_PlaybackTrackChanged(object sender, TrackChangedEventArgs e)
 {
     if (e.NewTrack != null)
     {
         if (e.StreamType == MediaStreamType.Video && PlaybackBitrate != e.NewTrack.Bitrate)
         {
             SmoothStreamingEvent ssEvent = new SmoothStreamingEvent();
             ssEvent.Value = e.NewTrack.Bitrate;
             ssEvent.Data1 = PlaybackBitrate.ToString(CultureInfo.InvariantCulture);
             ssEvent.EventType = EventType.BitrateChanged;
             Enqueue(ssEvent);
             // remember value
             PlaybackBitrate = e.NewTrack.Bitrate;
         }
     }
 }
 void Enqueue(SmoothStreamingEvent entry)
 {
     StampEvent(entry);
     lock (realtimeEventQueue)
     {
         realtimeEventQueue.Enqueue(entry);
     }
 }
 void mediaElement_ClipProgressUpdate(object sender, ClipPlaybackEventArgs e)
 {
     if (e.Progress == ClipProgress.Start)
     {
         SmoothStreamingEvent ssEvent = new SmoothStreamingEvent();
         ssEvent.Data1 = e.Context.ClipInformation.ClipUri.ToString();
         ssEvent.EventType = EventType.ClipStarted;
         ssEvent.ClipId = TraceMonitor.GenerateStreamIdentifier();
         Enqueue(ssEvent);
     }
     else if (e.Progress == ClipProgress.Complete)
     {
         SmoothStreamingEvent ssEvent = new SmoothStreamingEvent();
         ssEvent.EventType = EventType.ClipEnded;
         ssEvent.Data1 = e.Context.ClipInformation.ClipUri.ToString();
         Enqueue(ssEvent);
     }
 }
        void AddEvent(SmoothStreamingEvent entry)
        {
            // check for a latency alert
            if (entry.EventType == EventType.PerceivedBandwidth)
            {
                perceivedKBps = entry.Value / (8192);
            }
            else if (entry.EventType == EventType.VideoChunkDownload || entry.EventType == EventType.AudioChunkDownload)
            {
                if (entry.Value > 75)
                {
                    double dataSize = double.Parse(entry.Data3, CultureInfo.CurrentCulture) / 1024;
                    double observedThroughput = dataSize / ((entry.Value - 75) / 1000);
                    if (observedThroughput < (perceivedKBps / Configuration.LatencyAlertThreshold))
                    {
                        if (LatencyAlert != null) LatencyAlert(this, new SimpleEventArgs<SmoothStreamingEvent>(entry));
                    }
                }
            }

            // give the agents an opportunity to care about this event
            agent.ProcessEvent(entry);
            if (EventCreated != null) EventCreated(this, new SimpleEventArgs<SmoothStreamingEvent>(entry));
        }
 void mediaElement_MediaEnded(object sender, RoutedEventArgs e)
 {
     SmoothStreamingEvent ssEvent = new SmoothStreamingEvent();
     ssEvent.EventType = EventType.StreamEnded;
     ssEvent.Data1 = GetUrlWithoutQueryString(mediaElement.SmoothStreamingSource);
     Enqueue(ssEvent);
 }
 void TraceMonitor_ReportSystemEvent(SmoothStreamingEvent traceEvent)
 {
     Enqueue(traceEvent);
 }
 void TraceMonitor_ReportTraceEvent(SmoothStreamingEvent traceEvent)
 {
     if (mediaElementId == null || traceEvent.MediaElementId == null || traceEvent.MediaElementId == mediaElementId)
         Submit(traceEvent);
 }