public void ShouldGenerateServerManifest() { const string ExpectedServerManifest = "<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n<smil xmlns=\"http://www.w3.org/2001/SMIL20/Language\">\r\n <head>\r\n <meta\r\n name=\"clientManifestRelativePath\"\r\n content=\"test.ismc\" />\r\n </head>\r\n <body>\r\n <switch>\r\n <video\r\n src=\"test_4000.ismv\"\r\n systemBitrate=\"4000000\">\r\n <param\r\n name=\"trackID\"\r\n value=\"2\"\r\n valuetype=\"data\" />\r\n </video>\r\n <video\r\n src=\"test_1700.ismv\"\r\n systemBitrate=\"1700000\">\r\n <param\r\n name=\"trackID\"\r\n value=\"2\"\r\n valuetype=\"data\" />\r\n </video>\r\n <video\r\n src=\"test_900.ismv\"\r\n systemBitrate=\"900000\">\r\n <param\r\n name=\"trackID\"\r\n value=\"2\"\r\n valuetype=\"data\" />\r\n </video>\r\n <audio\r\n src=\"test_4000.ismv\"\r\n systemBitrate=\"64000\">\r\n <param\r\n name=\"trackID\"\r\n value=\"1\"\r\n valuetype=\"data\" />\r\n </audio>\r\n </switch>\r\n </body>\r\n</smil>"; var manifestWriter = new SmoothStreamingManifestWriter(); var switchs = new List <SwitchInfo> { new SwitchInfo("test_4000.ismv", 4000, FileType.Video), new SwitchInfo("test_1700.ismv", 1700, FileType.Video), new SwitchInfo("test_900.ismv", 900, FileType.Video), new SwitchInfo("test_4000.ismv", 64, FileType.Audio), }; var output = manifestWriter.GenerateServerManifest("test.ismc", switchs); Assert.AreEqual(ExpectedServerManifest, output); }
public void ShouldGenerateSmoothStreamingManifestVersion2() { var manifestStream = new FileStream(@".\Content\SampleManifest_version2.ismc", FileMode.Open, FileAccess.Read); StreamReader reader = new StreamReader(manifestStream); string input = reader.ReadToEnd(); manifestStream.Seek(0, SeekOrigin.Begin); var manifestParser = new SmoothStreamingManifestParser(manifestStream); reader.Close(); var manifestWriter = new SmoothStreamingManifestWriter(); string output = manifestWriter.GenerateClientManifest(manifestParser.ManifestInfo); Assert.AreEqual(input, output); }
public string GetSubClipManifest(Uri manifestUri, double markIn, double markOut) { string manifest = null; DownloaderManager downloaderManager = new DownloaderManager(); Stream manifestStream = downloaderManager.DownloadManifest(manifestUri, true, null); if (manifestStream != null) { SmoothStreamingManifestParser parser = new SmoothStreamingManifestParser(manifestStream); SmoothStreamingManifestWriter writer = new SmoothStreamingManifestWriter(); CompositeManifestInfo compositeManifestInfo = new CompositeManifestInfo(parser.ManifestInfo.MajorVersion, parser.ManifestInfo.MinorVersion); compositeManifestInfo.AddClip(manifestUri, (ulong)markIn, (ulong)markOut, parser.ManifestInfo); manifest = writer.GenerateCompositeManifest(compositeManifestInfo, false); } return manifest; }
public void ShouldGenerateCompositeSmoothStreamingManifestVersion1() { string expectedManifest; using (var expectedManifestStream = new FileStream(@".\Content\VideoAudioCompositeSampleManifest_version1.ismc", FileMode.Open, FileAccess.Read)) { using (StreamReader reader = new StreamReader(expectedManifestStream)) { expectedManifest = reader.ReadToEnd(); } } var manifestStream = new FileStream(@".\Content\SampleManifest_version1.ismc", FileMode.Open, FileAccess.Read); var manifestParser = new SmoothStreamingManifestParser(manifestStream); var manifestWriter = new SmoothStreamingManifestWriter(); CompositeManifestInfo manifestInfo = new CompositeManifestInfo(manifestParser.ManifestInfo.MajorVersion, manifestParser.ManifestInfo.MinorVersion); Clip clip = new Clip(this.manifestUri, 400000000, 900000000); foreach (StreamInfo streamInfo in manifestParser.ManifestInfo.Streams) { clip.Streams.Add(streamInfo); } manifestInfo.Clips.Add(clip); string output = manifestWriter.GenerateCompositeManifest(manifestInfo, true); XDocument expectedDocument = XDocument.Parse(expectedManifest); XDocument outputDocument = XDocument.Parse(output); Assert.AreEqual(expectedDocument.ToString(), outputDocument.ToString()); }
public void ShouldNotOverflowOnSourceManifestWithDuration2() { string expectedManifest; using (var expectedManifestStream = new FileStream(@".\Content\interstitial2.csm", FileMode.Open, FileAccess.Read)) { using (StreamReader reader = new StreamReader(expectedManifestStream)) { expectedManifest = reader.ReadToEnd(); } } var manifestStream = new FileStream(@".\Content\interstitial2.xml", FileMode.Open, FileAccess.Read); var manifestParser = new SmoothStreamingManifestParser(manifestStream); var manifestWriter = new SmoothStreamingManifestWriter(); CompositeManifestInfo manifestInfo = new CompositeManifestInfo(manifestParser.ManifestInfo.MajorVersion, manifestParser.ManifestInfo.MinorVersion); Clip clip = new Clip(this.manifestUri, 611540, 23391570); foreach (StreamInfo streamInfo in manifestParser.ManifestInfo.Streams) { clip.Streams.Add(streamInfo); } manifestInfo.Clips.Add(clip); string output = manifestWriter.GenerateCompositeManifest(manifestInfo, true); XDocument expectedDocument = XDocument.Parse(expectedManifest); XDocument outputDocument = XDocument.Parse(output); Assert.AreEqual(expectedDocument.ToString(), outputDocument.ToString()); }
public void ShouldMaintainFrameAccuracy2WhenGeneratingCompositeSmoothStreamingManifestVersion2() { string expectedManifest; using (var expectedManifestStream = new FileStream(@".\Content\frame2.csm", FileMode.Open, FileAccess.Read)) { using (StreamReader reader = new StreamReader(expectedManifestStream)) { expectedManifest = reader.ReadToEnd(); } } var manifestStream = new FileStream(@".\Content\frame2.xml", FileMode.Open, FileAccess.Read); var manifestParser = new SmoothStreamingManifestParser(manifestStream); var manifestWriter = new SmoothStreamingManifestWriter(); CompositeManifestInfo manifestInfo = new CompositeManifestInfo(manifestParser.ManifestInfo.MajorVersion, manifestParser.ManifestInfo.MinorVersion); Clip clip = new Clip(this.manifestUri, 394311093750, 395006410000); foreach (StreamInfo streamInfo in manifestParser.ManifestInfo.Streams) { clip.Streams.Add(streamInfo); } manifestInfo.Clips.Add(clip); string output = manifestWriter.GenerateCompositeManifest(manifestInfo, true); XDocument expectedDocument = XDocument.Parse(expectedManifest); XDocument outputDocument = XDocument.Parse(output); Assert.AreEqual(expectedDocument.ToString(), outputDocument.ToString()); }
public CreateTrainingSetResponse CreateTrainingSet(CreateTrainingSetRequest request) { var response = new CreateTrainingSetResponse(); try { var downloadManager = new DownloaderManager(); var compositeManifestInfo = new CompositeManifestInfo(2, 0); var videoRepository = serviceLocator.GetInstance <IVideoRepository>(); var catalogRepository = serviceLocator.GetInstance <ICatalogRepository>(); var templateRepository = serviceLocator.GetInstance <ITrainingSetTemplateRepository>(); var totalDuration = TimeSpan.Zero; foreach (var videoPart in request.TrainingSet.VideoParts) { var video = videoRepository.Get(videoPart.VideoId); var manifestStream = downloadManager.DownloadManifest(video.StreamUri, true, null); if (manifestStream != null) { var parser = new SmoothStreamingManifestParser(manifestStream); double startPosition = videoPart.From.TotalSeconds; double endPosition = videoPart.To.TotalSeconds; compositeManifestInfo.AddClip(video.StreamUri, (ulong)(startPosition * Timescale), (ulong)(endPosition * Timescale), parser.ManifestInfo); totalDuration = totalDuration.Add(videoPart.To.Subtract(videoPart.From)); } } var writer = new SmoothStreamingManifestWriter(); var manifest = writer.GenerateCompositeManifest(compositeManifestInfo, false, false); string csmPath = HttpContext.Current.Server.MapPath("csm"); if (!Directory.Exists(csmPath)) { Directory.CreateDirectory(csmPath); } var uniqueName = Guid.NewGuid().ToString(); string tmpFilePath = Path.Combine(csmPath, string.Format("{0}.tmpcsm", uniqueName)); string finalFilePath = Path.Combine(csmPath, string.Format("{0}.csm", uniqueName)); File.WriteAllText(tmpFilePath, manifest, Encoding.UTF8); if (File.Exists(tmpFilePath)) { if (File.Exists(finalFilePath)) { File.Delete(finalFilePath); } File.Move(tmpFilePath, finalFilePath); } var userService = serviceLocator.GetInstance <IApplicationUserService>(); var user = userService.RetrieveApplicationUser(new ApplicationUserFindCriteria() { Username = request.User }); var template = templateRepository.Get(request.TrainingSet.TrainingSetTemplateId); //var _telemetry = new List<Telemetry>(); var timer = TimeSpan.Zero; var recordingInterval = TimeSpan.FromSeconds(2); var telemetryFile = new StringBuilder().AppendLine("\"Minutes\",\"Torq(N-m)\",\"Km/h\",\"Watts\",\"Km\",\"Cadence\",\"Hrate\",\"ID\",\"Altitude(m)\""); foreach (var interval in template.Intervals) { var numberOfElements = interval.Duration.TotalSeconds / recordingInterval.TotalSeconds; for (int i = 0; i < numberOfElements; i++) { var telemetry = new Telemetry(); telemetry.PercentageThreshold = Convert.ToDouble(interval.Effort) / 100; telemetry.Watts = ((telemetry.PercentageThreshold) * user.FTP.GetValueOrDefault()); telemetry.TimePosition = timer; timer = timer.Add(recordingInterval); telemetryFile.AppendLine(telemetry.ToDelimitedString(',')); //telemetry.PercentageThreshold = Convert.ToDouble(interval.Effort); //telemetry.TimePosition = timer; //telemetryFile.AppendLine(telemetry.ToDelimitedString(',')); } } string telemetryPath = HttpContext.Current.Server.MapPath("telemetry"); if (!Directory.Exists(telemetryPath)) { Directory.CreateDirectory(telemetryPath); } string filePath = Path.Combine(telemetryPath, string.Format("{0}.csv", uniqueName)); File.WriteAllText(filePath, telemetryFile.ToString()); //var context = System.ServiceModel.OperationContext.Current; //RemoteEndpointMessageProperty property = (RemoteEndpointMessageProperty)context.IncomingMessageProperties[RemoteEndpointMessageProperty.Name]; string host = "www.indoorworx.com";// property.Address; //var host = "localhost"; //now create the video var workout = new Video(); workout.StreamUri = new Uri(string.Format("http://{0}/IndoorWorx/csm/{1}.csm", host, uniqueName), UriKind.Absolute); workout.Title = request.TrainingSet.Title; workout.Description = template.Description; workout.Duration = totalDuration; workout.TelemetryInfo.TelemetryUri = new Uri(string.Format("http://{0}/IndoorWorx/telemetry/{1}.csv", host, uniqueName), UriKind.Absolute); foreach (var text in template.VideoText) { workout.VideoText.Add(text.Clone()); } workout.Intervals = template.Intervals.Select(x => new VideoInterval(x.Duration, x.Effort, x.Sequence)).ToList(); var savedWorkout = videoRepository.Save(workout); userService.AddVideoToLibrary(new AddVideoRequest() { User = request.User, VideoId = savedWorkout.Id }); response.Status = CreateTrainingSetStatus.Success; response.TrainingSet = savedWorkout; } catch (Exception ex) { response.Status = CreateTrainingSetStatus.Error; response.Message = ex.StackTrace; //response.Message = ex.Message; } return(response); }
private void GenerateManifest() { IDictionary <Track, string> manifestByTrack = new Dictionary <Track, string>(); var tracks = this.sequenceRegistry.CurrentSequenceModel.Tracks.Where( t => (t.TrackType == TrackType.Visual || t.TrackType == TrackType.Audio) && t.Shots.Count > 0); foreach (var track in tracks) { CompositeManifestInfo compositeManifestInfo = new CompositeManifestInfo(2, 0); compositeManifestInfo.RubberBandingDataStreamName = "RubberBanding"; compositeManifestInfo.TransitionDataStreamName = "Transition"; IDictionary <TimelineElement, double> gapDurations = CalculateGapsDuration(track); foreach (TimelineElement shot in track.Shots) { if (this.streamsByUri.ContainsKey(shot.Asset.Source)) { Stream manifestStream = this.streamsByUri[shot.Asset.Source]; if (manifestStream != null) { if (!this.treatGapsAsError) { this.AddPreviousGap(gapDurations[shot], this.streamsByUri[this.gapUri], compositeManifestInfo); } AddClipToCompositeManifestInfo(shot, manifestStream, compositeManifestInfo); this.AddRubberBandingPoints(shot, compositeManifestInfo); this.AddTransitions(shot, compositeManifestInfo); } } } if (track.TrackType == TrackType.Visual) { compositeManifestInfo.OverlayDataStreamName = "Overlay"; var overlaysTrack = this.sequenceRegistry.CurrentSequenceModel.Tracks.First(t => t.TrackType == TrackType.Overlay); foreach (TimelineElement shot in overlaysTrack.Shots) { this.AddOverlay(shot, compositeManifestInfo); } } var userSettings = this.userSettingsService.GetSettings(); SmoothStreamingManifestWriter writer = new SmoothStreamingManifestWriter(); string manifest = writer.GenerateCompositeManifest( compositeManifestInfo, false, false, userSettings.MinBitrate, userSettings.MaxBitrate, userSettings.IsSingleBitrate); manifestByTrack[track] = manifest; } this.dispatcher.BeginInvoke(() => this.actionCallback(manifestByTrack)); }
private IEnumerable <string> GetManifests(string pbpDataStreamName, string adsDataStreamName, bool compressManifest, string gapUriString, string gapCmsId, string gapAzureId, int sequenceNumber) { List <string> manifests = new List <string>(); this.gapUri = new Uri(gapUriString); DownloaderManager manager = new DownloaderManager(); string manifest = string.Empty; if (this.project.Sequences != null && this.project.Sequences.Count >= 1) { Stream gapStream = manager.DownloadManifest(this.gapUri, true); byte[] gapResult = null; using (BinaryReader reader = new BinaryReader(gapStream)) { gapResult = reader.ReadBytes((int)manager.LastResponseLength); } MemoryStream gapMemoryStream = null; try { gapMemoryStream = new MemoryStream(gapResult); Sequence sequence = this.project.Sequences[0]; if (this.project.Sequences.Count > sequenceNumber) { sequence = this.project.Sequences[sequenceNumber]; } foreach ( var track in sequence.Tracks.Where( t => (t.TrackType.Equals("visual", StringComparison.InvariantCultureIgnoreCase) || t.TrackType.Equals("audio", StringComparison.InvariantCultureIgnoreCase)) && t.Shots.Count > 0)) { CompositeManifestInfo compositeManifestInfo = new CompositeManifestInfo(2, 0); compositeManifestInfo.PlayByPlayDataStreamName = pbpDataStreamName; compositeManifestInfo.AdsDataStreamName = adsDataStreamName; compositeManifestInfo.RubberBandingDataStreamName = "RubberBanding"; compositeManifestInfo.TransitionDataStreamName = "Transition"; IDictionary <Shot, double> gapDurations = CalculateGapsDuration(track); foreach (Shot shot in track.Shots) { Resource resource = shot.Source.Resources.SingleOrDefault(x => !string.IsNullOrEmpty(x.Ref)); Uri assetUri; if (resource != null && Uri.TryCreate(resource.Ref, UriKind.Absolute, out assetUri)) { Stream manifestStream = manager.DownloadManifest(assetUri, true); MemoryStream stream = new MemoryStream(); if (manifestStream != null) { byte[] buffer = ReadFully(manifestStream); if (buffer != null) { var binaryWriter = new BinaryWriter(stream); binaryWriter.Write(buffer); } stream.Seek(0, SeekOrigin.Begin); } this.AddPreviousGap(gapDurations[shot], gapMemoryStream, gapCmsId, gapAzureId, compositeManifestInfo); AddClipToCompositeManifestInfo(shot, stream, compositeManifestInfo); this.AddRubberBandingPoints(shot, compositeManifestInfo); this.AddTransitions(shot, compositeManifestInfo); stream.Close(); if (track.TrackType.Equals("visual", StringComparison.InvariantCultureIgnoreCase)) { compositeManifestInfo.OverlayDataStreamName = "Overlay"; var overlaysTrack = sequence.Tracks.First(t => t.TrackType.Equals("Overlay")); foreach (Shot s in overlaysTrack.Shots) { this.AddOverlay(s, compositeManifestInfo); } if (sequence.AdOpportunities != null) { foreach ( RCE.Services.Contracts.AdOpportunity adOpportunity in sequence.AdOpportunities) { compositeManifestInfo.AddAdOpportunity( adOpportunity.ID, adOpportunity.TemplateType, adOpportunity.Time); } } if (sequence.MarkerCollection != null) { foreach (Marker marker in sequence.MarkerCollection) { compositeManifestInfo.AddPlayByPlay(marker.ID, marker.Text, marker.Time); } } } } } SmoothStreamingManifestWriter writer = new SmoothStreamingManifestWriter(); manifest = writer.GenerateCompositeManifest(compositeManifestInfo, false, compressManifest); manifests.Add(manifest); } } finally { if (gapMemoryStream != null) { gapMemoryStream.Close(); } } } return(manifests); }
public void ShouldGenerateSimpleCompositeManifestVersion1() { string expectedManifest; using (var manifestStream = new FileStream(@".\Content\SimpleCompositeSampleManifest_version1.csm", FileMode.Open, FileAccess.Read)) { using (var reader = new StreamReader(manifestStream)) { expectedManifest = reader.ReadToEnd(); } } CompositeManifestInfo manifestInfo = new CompositeManifestInfo(1, 0); Clip clip = new Clip(new Uri("http://server/stream1.isml/Manifest"), 6400000000, 6510000000); StreamInfo streamInfo = new StreamInfo("video"); streamInfo.AddAttribute("Chunks", "0"); streamInfo.AddAttribute("Type", "video"); streamInfo.AddAttribute("SubType", "WVC1"); streamInfo.AddAttribute("Url", "QualityLevels({bitrate})/Fragments(video={start time})"); ulong[] bitrates = { 350000, 1050000, 600000, 1450000 }; int[][] sizes = { new[] { 320, 176 }, new[] { 592, 336 }, new[] { 424, 240 }, new[] { 848, 476 } }; for (int i = 0; i < bitrates.Length; i++) { QualityLevel qualityLevel = new QualityLevel(); qualityLevel.AddAttribute("Bitrate", bitrates[i].ToString()); qualityLevel.AddAttribute("FourCC", "WVC1"); qualityLevel.AddAttribute("Width", sizes[i][0].ToString()); qualityLevel.AddAttribute("Height", sizes[i][1].ToString()); qualityLevel.AddAttribute("CodecPrivateData", "250000010FCBA01270A58A12782968045080A00AE020C00000010E5A47F840"); streamInfo.QualityLevels.Add(qualityLevel); } for (int i = 0; i < 325; i++) { ulong time = ((ulong)i * 20000000) + 20000000; ulong?duration = null; if (i == 324) { duration = 17500001; } Chunk chunk = new Chunk(null, time, duration); streamInfo.Chunks.Add(chunk); } clip.Streams.Add(streamInfo); manifestInfo.Clips.Add(clip); var manifestWriter = new SmoothStreamingManifestWriter(); string output = manifestWriter.GenerateCompositeManifest(manifestInfo, true); XDocument expectedDocument = XDocument.Parse(expectedManifest); XDocument outputDocument = XDocument.Parse(output); Assert.AreEqual(expectedDocument.ToString(), outputDocument.ToString()); }
public void CreateCompositeStream(Contracts.Project project) { CompositeManifestInfo compositeManifestInfo = new CompositeManifestInfo(2, 1); compositeManifestInfo.PlayByPlayDataStreamName = "PBP"; compositeManifestInfo.AdsDataStreamName = "ADS"; DownloaderManager manager = new DownloaderManager(); const ulong Timescale = 10000000; if (project.Timeline != null) { Track track = project.Timeline.SingleOrDefault(x => x.TrackType.ToUpperInvariant() == "VISUAL"); if (track != null && track.Shots != null) { foreach (Shot shot in track.Shots) { if (shot.Source != null && shot.Source is VideoItem && shot.Source.Resources.Count > 0 && shot.SourceAnchor != null) { Resource resource = shot.Source.Resources.SingleOrDefault(x => !String.IsNullOrEmpty(x.Ref)); Uri assetUri; if (resource != null && Uri.TryCreate(resource.Ref, UriKind.Absolute, out assetUri)) { Stream manifestStream = manager.DownloadManifest(assetUri, true, null); if (manifestStream != null) { double startPosition = (shot.Source is SmoothStreamingVideoItem) ? ((SmoothStreamingVideoItem)shot.Source).StartPosition : 0; SmoothStreamingManifestParser parser = new SmoothStreamingManifestParser(manifestStream); ulong clipBegin = (ulong)((shot.SourceAnchor.MarkIn.GetValueOrDefault() * Timescale) + (startPosition * Timescale)); ulong clipEnd = (ulong)((shot.SourceAnchor.MarkOut.GetValueOrDefault() * Timescale) + (startPosition * Timescale)); compositeManifestInfo.AddClip(assetUri, clipBegin, clipEnd, parser.ManifestInfo); } } } } } } if (project.Titles != null) { foreach (var title in project.Titles) { //compositeManifestInfo } } if (project.AdOpportunities != null) { foreach (RCE.Services.Contracts.AdOpportunity adOpportunity in project.AdOpportunities) { compositeManifestInfo.AddAdOpportunity(adOpportunity.ID, adOpportunity.TemplateType, adOpportunity.Time); } } if (project.Markers != null) { foreach (Marker marker in project.Markers) { compositeManifestInfo.AddPlayByPlay(marker.ID, marker.Text, marker.Time); } } SmoothStreamingManifestWriter writer = new SmoothStreamingManifestWriter(); string manifest = writer.GenerateCompositeManifest(compositeManifestInfo, false); string csmPath = HttpContext.Current.Server.MapPath("csm"); if (!Directory.Exists(csmPath)) { Directory.CreateDirectory(csmPath); } string datetime = DateTime.Now.ToString("yyyyMMddHHmmss", CultureInfo.InvariantCulture); string tmpFilePath = Path.Combine(csmPath, string.Format(CultureInfo.InvariantCulture, "{0}-{1}.tmpcsm", project.Title.ToString(), datetime)); string finalFilePath = Path.Combine(csmPath, string.Format(CultureInfo.InvariantCulture, "{0}-{1}.csm", project.Title.ToString(), datetime)); File.WriteAllText(tmpFilePath, manifest, Encoding.UTF8); if (File.Exists(tmpFilePath)) { if (File.Exists(finalFilePath)) { File.Delete(finalFilePath); } File.Move(tmpFilePath, finalFilePath); } }