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)); } }
/// <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)); }
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); }
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); } }
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); }
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); } }
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); }
/// <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); } }
/// <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; } }
/// <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 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); } } }
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 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 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 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 TraceMonitor_ReportSystemEvent(SmoothStreamingEvent traceEvent) { Enqueue(traceEvent); }
void TraceMonitor_ReportTraceEvent(SmoothStreamingEvent traceEvent) { if (mediaElementId == null || traceEvent.MediaElementId == null || traceEvent.MediaElementId == mediaElementId) Submit(traceEvent); }