public void ShouldGenerateSimpleCompositeManifestVersion1WithAdOpportunities()
        {
            string expectedManifest;

            using (var manifestStream = new FileStream(@".\Content\SimpleCompositeSampleManifest_version1_ads.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);
            manifestInfo.AdsDataStreamName = "NBC-AD";
            manifestInfo.AddAdOpportunity(new Guid("36eb977c-d018-41c9-b565-e2ad2c4fa04f"), "A", TimeSpan.FromSeconds(38745.816).Ticks);

            var manifestWriter = new SmoothStreamingManifestWriter();

            string output = manifestWriter.GenerateCompositeManifest(manifestInfo, false);

            XDocument expectedDocument = XDocument.Parse(expectedManifest);
            XDocument outputDocument   = XDocument.Parse(output);

            Assert.AreEqual(expectedDocument.ToString(), outputDocument.ToString());
        }
        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 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);
            }
        }