public static TimeSpan ReturnTimeSpanOnGOP(ManifestTimingData data, TimeSpan ts) { var retVal = ts; ulong timestamp = (ulong)(ts.TotalSeconds * data.TimeScale); int i = 0; foreach (var t in data.TimestampList) { if (t < timestamp && i < (data.TimestampList.Count - 1) && timestamp < data.TimestampList[i + 1]) { retVal = TimeSpan.FromSeconds((double)t / (double)data.TimeScale); break; } i++; } return(retVal); }
public static ManifestTimingData GetManifestTimingData(IAsset asset, TraceWriter log) { ManifestTimingData response = new ManifestTimingData() { IsLive = false, Error = false, TimestampOffset = 0, TimestampList = new List <ulong>() }; try { ILocator mytemplocator = null; Uri myuri = FaceHelper.GetValidOnDemandURI(asset); if (myuri == null) { mytemplocator = CreatedTemporaryOnDemandLocator(asset); myuri = FaceHelper.GetValidOnDemandURI(asset); } if (myuri != null) { XDocument manifest = XDocument.Load(myuri.ToString()); var smoothmedia = manifest.Element("SmoothStreamingMedia"); var videotrack = smoothmedia.Elements("StreamIndex").Where(a => a.Attribute("Type").Value == "video"); string timescalefrommanifest = smoothmedia.Attribute("TimeScale").Value; if (videotrack.FirstOrDefault().Attribute("TimeScale") != null) // there is timescale value in the video track. Let's take this one. { timescalefrommanifest = videotrack.FirstOrDefault().Attribute("TimeScale").Value; } ulong timescale = ulong.Parse(timescalefrommanifest); response.TimeScale = (ulong?)timescale; if (videotrack.FirstOrDefault().Element("c").Attribute("t") != null) { response.TimestampOffset = ulong.Parse(videotrack.FirstOrDefault().Element("c").Attribute("t").Value); } else { response.TimestampOffset = 0; // no timestamp, so it should be 0 } ulong totalduration = 0; ulong durationpreviouschunk = 0; ulong durationchunk; int repeatchunk; foreach (var chunk in videotrack.Elements("c")) { durationchunk = chunk.Attribute("d") != null?ulong.Parse(chunk.Attribute("d").Value) : 0; repeatchunk = chunk.Attribute("r") != null?int.Parse(chunk.Attribute("r").Value) : 1; totalduration += durationchunk * (ulong)repeatchunk; if (chunk.Attribute("t") != null) { //totalduration = ulong.Parse(chunk.Attribute("t").Value) - response.TimestampOffset; // new timestamp, perhaps gap in live stream.... response.TimestampList.Add(ulong.Parse(chunk.Attribute("t").Value)); } else { response.TimestampList.Add(response.TimestampList[response.TimestampList.Count() - 1] + durationpreviouschunk); } for (int i = 1; i < repeatchunk; i++) { response.TimestampList.Add(response.TimestampList[response.TimestampList.Count() - 1] + durationchunk); } durationpreviouschunk = durationchunk; } response.TimestampEndLastChunk = response.TimestampList[response.TimestampList.Count() - 1] + durationpreviouschunk; if (smoothmedia.Attribute("IsLive") != null && smoothmedia.Attribute("IsLive").Value == "TRUE") { // Live asset.... No duration to read (but we can read scaling and compute duration if no gap) response.IsLive = true; response.AssetDuration = TimeSpan.FromSeconds((double)totalduration / ((double)timescale)); } else { totalduration = ulong.Parse(smoothmedia.Attribute("Duration").Value); response.AssetDuration = TimeSpan.FromSeconds((double)totalduration / ((double)timescale)); } } else { response.Error = true; } if (mytemplocator != null) { mytemplocator.Delete(); } } catch (Exception) { response.Error = true; } return(response); }