private void AddPreviousGap(double gapDuration, Stream gapManifestStream, CompositeManifestInfo compositeManifestInfo)
        {
            if (gapDuration == 0)
            {
                return;
            }

            const double Timescale = 10000000.0;

            SmoothStreamingManifestParser parser = new SmoothStreamingManifestParser(gapManifestStream);

            gapManifestStream.Seek(0, SeekOrigin.Begin);

            double gapVideoCount = gapDuration / (parser.ManifestInfo.ManifestDuration / Timescale);

            int    completeVideos         = (int)gapVideoCount;
            double partialVideoProportion = gapVideoCount - (int)gapVideoCount;

            ulong clipEnd          = parser.ManifestInfo.ManifestDuration;
            var   customAttributes = new Dictionary <string, string> {
                { "CMSId", this.gapCmsId }, { "AzureId", this.gapAzureId }
            };

            for (int i = 0; i < completeVideos; i++)
            {
                compositeManifestInfo.AddClip(this.gapUri, 0, clipEnd, customAttributes, true, parser.ManifestInfo);
            }

            clipEnd = (ulong)(clipEnd * partialVideoProportion);

            if (clipEnd != 0)
            {
                compositeManifestInfo.AddClip(this.gapUri, 0, clipEnd, customAttributes, true, parser.ManifestInfo);
            }
        }
Example #2
0
        private static void WritePlayByPlay(XmlWriter writer, CompositeManifestInfo manifestInfo)
        {
            if (manifestInfo.PlayByPlayEvents.Count > 0)
            {
                StreamInfo streamInfo = WriteCompositeManifestStandardStreamIndex(manifestInfo.PlayByPlayDataStreamName, manifestInfo.PlayByPlayEvents.Count);

                for (int i = 0; i < manifestInfo.PlayByPlayEvents.Count; i++)
                {
                    PlayByPlay pbp = manifestInfo.PlayByPlayEvents[i];

                    StringBuilder output = new StringBuilder();

                    XmlWriter tempWriter = CreateWriter(output, true, true);

                    if (tempWriter != null)
                    {
                        tempWriter.WriteStartElement("InStreamEnvelope");
                        tempWriter.WriteAttributeString("Id", pbp.ID.ToString());
                        tempWriter.WriteAttributeString("Action", "Add");
                        tempWriter.WriteAttributeString("TargetID", string.Empty);
                        tempWriter.WriteAttributeString("Priority", "1");
                        tempWriter.WriteStartElement("PlayByPlay");
                        tempWriter.WriteAttributeString("ID", pbp.ID.ToString());
                        tempWriter.WriteAttributeString("Time", pbp.Time.ToString(CultureInfo.InvariantCulture));
                        tempWriter.WriteAttributeString("IsTimelineMarker", "True");
                        tempWriter.WriteAttributeString("IsNavigable", "True");
                        tempWriter.WriteAttributeString("EditorialType", string.Empty);
                        tempWriter.WriteAttributeString("Type", string.Empty);
                        tempWriter.WriteCData(pbp.Text);
                        tempWriter.WriteEndElement();
                        tempWriter.Close();

                        byte[] envelopeBytes = Encoding.UTF8.GetBytes(output.ToString());

                        string encodedEnvelope = Convert.ToBase64String(envelopeBytes);

                        ulong?duration = null;

                        if (i == manifestInfo.PlayByPlayEvents.Count - 1)
                        {
                            duration = 10000000;
                        }

                        Chunk chunk = new Chunk(null, (ulong)pbp.Time, duration, encodedEnvelope);

                        streamInfo.Chunks.Add(chunk);
                    }
                }

                WriteStreamIndex(writer, streamInfo, true);
            }
        }
Example #3
0
        private static void WriteAdOpportunities(XmlWriter writer, CompositeManifestInfo manifestInfo)
        {
            if (manifestInfo.AdOpportunities.Count > 0)
            {
                StreamInfo streamInfo = WriteCompositeManifestStandardStreamIndex(manifestInfo.AdsDataStreamName, manifestInfo.AdOpportunities.Count);

                for (int i = 0; i < manifestInfo.AdOpportunities.Count; i++)
                {
                    AdOpportunity adOpportunity = manifestInfo.AdOpportunities[i];

                    StringBuilder output = new StringBuilder();

                    XmlWriter tempWriter = CreateWriter(output, true, true);

                    if (tempWriter != null)
                    {
                        tempWriter.WriteStartElement("InStreamEnvelope");
                        tempWriter.WriteAttributeString("Id", adOpportunity.ID.ToString());
                        tempWriter.WriteAttributeString("Action", "Add");
                        tempWriter.WriteAttributeString("TargetID", string.Empty);
                        tempWriter.WriteAttributeString("Priority", "1");
                        tempWriter.WriteStartElement("AdOpportunity");
                        tempWriter.WriteAttributeString("ID", adOpportunity.ID.ToString());
                        tempWriter.WriteAttributeString("Time", adOpportunity.Time.ToString(CultureInfo.InvariantCulture));
                        tempWriter.WriteAttributeString("TemplateType", adOpportunity.TemplateType);
                        tempWriter.WriteEndElement();
                        tempWriter.Close();

                        byte[] envelopeBytes = Encoding.UTF8.GetBytes(output.ToString());

                        string encodedEnvelope = Convert.ToBase64String(envelopeBytes);

                        ulong?duration = null;

                        if (i == manifestInfo.AdOpportunities.Count - 1)
                        {
                            duration = 10000000;
                        }

                        Chunk chunk = new Chunk(null, (ulong)adOpportunity.Time, duration, encodedEnvelope);

                        streamInfo.Chunks.Add(chunk);
                    }
                }

                WriteStreamIndex(writer, streamInfo, true);
            }
        }
        private void AddRubberBandingPoints(TimelineElement element, CompositeManifestInfo compositeManifestInfo)
        {
            const ulong Timescale = 10000000;

            List <Point> elementVolumeCollection = element.VolumeNodeCollection;

            foreach (Point point in elementVolumeCollection)
            {
                double volume       = 1 - point.Y;
                long   frames       = (long)point.X;
                double totalSeconds = TimeCode.FromFrames(frames, this.sequenceRegistry.CurrentSequenceModel.CurrentPosition.FrameRate).TotalSeconds + element.Position.TotalSeconds;

                long ticks = (long)(totalSeconds * Timescale);

                compositeManifestInfo.AddRubberBandingPoint(ticks, volume);
            }
        }
        private void AddTransitions(TimelineElement shot, CompositeManifestInfo compositeManifestInfo)
        {
            const double Timescale = 10000000.0;

            if (!(shot.Asset is VideoAsset) && !(shot.Asset is AudioAsset))
            {
                return;
            }

            AssetType assetType = (shot.Asset is VideoAsset) ? AssetType.Video : AssetType.Audio;

            ulong position = (ulong)(shot.Position.TotalSeconds * Timescale);

            AddTransition(SmoothStreamingManifestGenerator.Models.TransitionType.FadeIn, assetType, position, shot.InTransition.Duration, compositeManifestInfo);

            position = (ulong)((shot.Position.TotalSeconds + shot.Duration.TotalSeconds - shot.OutTransition.Duration) * Timescale);
            AddTransition(SmoothStreamingManifestGenerator.Models.TransitionType.FadeOut, assetType, position, shot.OutTransition.Duration, compositeManifestInfo);
        }
        private void AddRubberBandingPoints(Shot shot, CompositeManifestInfo compositeManifestInfo)
        {
            const ulong Timescale = 10000000;

            List <VolumeLevelNode> volumeNodes = shot.VolumeNodeCollection;

            foreach (VolumeLevelNode volumeNode in volumeNodes)
            {
                double         volume = volumeNode.Volume;
                long           frames = (long)volumeNode.Position;
                SmpteFrameRate frameRate;
                SmpteFrameRate.TryParse(this.project.SmpteFrameRate, true, out frameRate);
                double totalSeconds = TimeCode.FromFrames(frames, frameRate).TotalSeconds + shot.TrackAnchor.MarkIn.Value;

                long ticks = (long)(totalSeconds * Timescale);

                compositeManifestInfo.AddRubberBandingPoint(ticks, volume);
            }
        }
        private void AddTransitions(Shot shot, CompositeManifestInfo compositeManifestInfo)
        {
            const double Timescale         = 10000000.0;
            SubClipItem  subclipItem       = shot.Source as SubClipItem;
            Item         itemForTransition = subclipItem != null ? subclipItem.RelatedItem : shot.Source;

            if (!(itemForTransition is VideoItem) && !(itemForTransition is AudioItem))
            {
                return;
            }

            AssetType assetType = (itemForTransition is VideoItem) ? AssetType.Video : AssetType.Audio;

            ulong position = (ulong)(shot.TrackAnchor.MarkIn * Timescale);

            compositeManifestInfo.AddTransition(SmoothStreamingManifestGenerator.Models.TransitionType.FadeIn, assetType, position, shot.InTransition.Duration);

            position = (ulong)((shot.TrackAnchor.MarkIn + (shot.SourceAnchor.MarkOut - shot.SourceAnchor.MarkIn) - shot.OutTransition.Duration) * Timescale);
            compositeManifestInfo.AddTransition(SmoothStreamingManifestGenerator.Models.TransitionType.FadeOut, assetType, position, shot.OutTransition.Duration);
        }
Example #8
0
        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;
        }
        private void AddOverlay(TimelineElement shot, CompositeManifestInfo compositeManifestInfo)
        {
            var overlayAsset = shot.Asset as OverlayAsset;

            if (overlayAsset != null)
            {
                var dict = new Dictionary <string, object>();
                overlayAsset.Metadata.ForEach(mf => dict.Add(mf.Name, mf.Value));

                const double Timescale = 10000000.0;

                compositeManifestInfo.AddOverlay(
                    overlayAsset.Title,
                    overlayAsset.PositionX,
                    overlayAsset.PositionY,
                    overlayAsset.Height,
                    overlayAsset.Width,
                    dict,
                    overlayAsset.XamlResource,
                    (ulong)(shot.Position.TotalSeconds * Timescale),
                    (ulong)((shot.Position.TotalSeconds + shot.Duration.TotalSeconds) * Timescale));
            }
        }
        private void AddOverlay(Shot shot, CompositeManifestInfo compositeManifestInfo)
        {
            var overlayItem = shot.Source as OverlayItem;

            if (overlayItem != null)
            {
                var dict = new Dictionary <string, object>();
                overlayItem.Metadata.ForEach(mf => dict.Add(mf.Name, mf.Value));

                const double Timescale = 10000000.0;

                compositeManifestInfo.AddOverlay(
                    overlayItem.Title,
                    overlayItem.X,
                    overlayItem.Y,
                    overlayItem.Height,
                    overlayItem.Width,
                    dict,
                    overlayItem.XamlTemplate,
                    (ulong)((shot.SourceAnchor.MarkIn + shot.TrackAnchor.MarkIn) * Timescale),
                    (ulong)(((shot.SourceAnchor.MarkIn + shot.TrackAnchor.MarkIn) + (shot.SourceAnchor.MarkOut - shot.SourceAnchor.MarkIn)) * Timescale));
            }
        }
Example #11
0
        /// <summary>
        /// Generates a composite manifest based on the given <see cref="CompositeManifestInfo"/>.
        /// </summary>
        /// <param name="manifestInfo">The composite manifest info that contains all the information about the manifest go generate.</param>
        /// <param name="writeSourceDataStreams">Defines whether if the composite manifest should include the source data streams.</param>
        /// <param name="compressManifest">Defines whether if the composite manifest should be compressed.</param>
        /// <returns>The generated Smooth Streaming composite manifest.</returns>
        public string GenerateCompositeManifest(CompositeManifestInfo manifestInfo, bool writeSourceDataStreams, bool compressManifest)
        {
            StringBuilder output = new StringBuilder();

            XmlWriter writer = CreateWriter(output, false, true);

            if (writer != null)
            {
                writer.WriteProcessingInstruction("xml", "version=\"1.0\"");
                writer.WriteStartElement("SmoothStreamingMedia");

                WriteHeader(writer, manifestInfo, compressManifest);

                foreach (Clip clip in manifestInfo.Clips)
                {
                    WriteClip(writer, clip, compressManifest);
                }

                if (writeSourceDataStreams)
                {
                    foreach (StreamInfo streamInfo in manifestInfo.Streams)
                    {
                        WriteClipSparseStreamIndex(writer, streamInfo, manifestInfo.MajorVersion);
                    }
                }

                WriteAdOpportunities(writer, manifestInfo);

                WritePlayByPlay(writer, manifestInfo);

                writer.WriteEndElement();
                writer.Close();
            }

            return(output.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 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 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());
        }
        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);
        }
Example #16
0
        public string GetManifest(string projectXml, string pbpDataStreamName, string adsDataStreamName)
        {
            CompositeManifestInfo compositeManifestInfo = new CompositeManifestInfo(2, 0);

            compositeManifestInfo.PlayByPlayDataStreamName = pbpDataStreamName;
            compositeManifestInfo.AdsDataStreamName = adsDataStreamName;

            DownloaderManager manager = new DownloaderManager();

            const ulong Timescale = 10000000;

            Project project;

            try
            {
                project = Deserialize<Project>(projectXml);
            }
            catch
            {
                return Resources.Resources.InvalidRCEProjectXml;
            }

            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 (shot.Source != null && shot.Source is ImageItem && 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 imageStream = manager.DownloadManifest(assetUri, true, null);

                        //        if (imageStream != null)
                        //        {
                        //            double startPosition = shot.SourceAnchor.MarkIn.GetValueOrDefault();
                        //            //double startPosition = (shot.Source is SmoothStreamingVideoItem) ? ((SmoothStreamingVideoItem)shot.Source).StartPosition : 0;

                        //            SmoothStreamingManifestParser parser = new SmoothStreamingManifestParser(imageStream);

                        //            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);
                        //        }
                        //    }


                        }
                    }
                }
            }
        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 static void AddTransition(SmoothStreamingManifestGenerator.Models.TransitionType transitionType, AssetType assetType, ulong position, double duration, CompositeManifestInfo compositeManifestInfo)
 {
     compositeManifestInfo.AddTransition(transitionType, assetType, position, duration);
 }
        private static void AddClipToCompositeManifestInfo(TimelineElement shot, Stream manifestStream, CompositeManifestInfo compositeManifestInfo)
        {
            const ulong Timescale = 10000000;

            ulong startPosition = 0;

            SmoothStreamingManifestParser parser = new SmoothStreamingManifestParser(manifestStream);

            manifestStream.Seek(0, SeekOrigin.Begin);

            var subClipAsset  = shot.Asset as VideoAssetInOut;
            var adaptiveAsset = subClipAsset != null && subClipAsset.IsAdaptiveAsset ? (IAdaptiveAsset)subClipAsset.VideoAsset : shot.Asset as IAdaptiveAsset;

            // the timeline elements holds the in/out position, instead of creating an ISubClipAsset
            double markIn  = shot.InPosition.TotalSeconds;
            double markOut = shot.OutPosition.TotalSeconds;

            if (adaptiveAsset != null)
            {
                startPosition = GetStartPositionFromManifest(parser);
            }

            if (!string.IsNullOrEmpty(shot.SelectedAudioStream))
            {
                var audioStreamsToRemove = parser.ManifestInfo.Streams.Where(s => s.StreamType.Equals("Audio", StringComparison.CurrentCultureIgnoreCase) &&
                                                                             !s.Attributes["Name"].Equals(shot.SelectedAudioStream)).ToList();

                if (audioStreamsToRemove != null)
                {
                    foreach (var audioStream in audioStreamsToRemove)
                    {
                        parser.ManifestInfo.Streams.Remove(audioStream);
                    }
                }
            }

            if (subClipAsset != null)
            {
                if (!string.IsNullOrEmpty(subClipAsset.SequenceVideoCamera))
                {
                    var videoStream = parser.ManifestInfo.Streams.First(s => s.StreamType.Equals("Video", StringComparison.CurrentCultureIgnoreCase));

                    var qualityLevelsToRemove = videoStream.QualityLevels.Where(q => !q.CustomAttributes.ContainsKey("cameraAngle") ||
                                                                                !q.CustomAttributes["cameraAngle"].Equals(subClipAsset.SequenceVideoCamera)).ToList();

                    foreach (var qualityLevel in qualityLevelsToRemove)
                    {
                        videoStream.QualityLevels.Remove(qualityLevel);
                    }
                }

                startPosition = GetStartPositionFromManifest(parser);
            }

            ulong clipBegin        = (ulong)(Convert.ToUInt64(markIn * Timescale) + startPosition);
            ulong clipEnd          = (ulong)(Convert.ToUInt64(markOut * Timescale) + startPosition);
            var   customAttributes = new Dictionary <string, string> {
                { "CMSId", shot.Asset.CMSId }, { "AzureId", shot.Asset.AzureId }
            };

            compositeManifestInfo.AddClip(shot.Asset.Source, clipBegin, clipEnd, customAttributes, parser.ManifestInfo);
        }
        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());
        }
        private static void AddClipToCompositeManifestInfo(Shot shot, Stream manifestStream, CompositeManifestInfo compositeManifestInfo)
        {
            const ulong Timescale = 10000000;

            ulong startPosition = 0;

            SmoothStreamingManifestParser parser = new SmoothStreamingManifestParser(manifestStream);

            manifestStream.Seek(0, SeekOrigin.Begin);

            var subClipAsset             = shot.Source as SubClipItem;
            var smoothStreamingVideoItem = shot.Source as SmoothStreamingVideoItem;
            var smoothStreamingAudioItem = shot.Source as SmoothStreamingAudioItem;

            // the timeline elements holds the in/out position, instead of creating an ISubClipAsset
            double markIn  = shot.SourceAnchor.MarkIn.Value;
            double markOut = shot.SourceAnchor.MarkOut.Value;

            if (smoothStreamingVideoItem != null || smoothStreamingAudioItem != null)
            {
                startPosition = GetStartPositionFromManifest(parser);
            }

            if (!string.IsNullOrEmpty(shot.SequenceAudioStream))
            {
                var audioStreamsToRemove = parser.ManifestInfo.Streams.Where(s => s.StreamType.Equals("Audio", StringComparison.CurrentCultureIgnoreCase) &&
                                                                             !s.Attributes["Name"].Equals(shot.SequenceAudioStream)).ToList();

                if (audioStreamsToRemove != null)
                {
                    foreach (var audioStream in audioStreamsToRemove)
                    {
                        parser.ManifestInfo.Streams.Remove(audioStream);
                    }
                }
            }

            if (subClipAsset != null)
            {
                if (!string.IsNullOrEmpty(subClipAsset.SequenceVideoStream))
                {
                    var videoStream = parser.ManifestInfo.Streams.First(s => s.StreamType.Equals("Video", StringComparison.CurrentCultureIgnoreCase));

                    var qualityLevelsToRemove = videoStream.QualityLevels.Where(q => !q.CustomAttributes.ContainsKey("cameraAngle") ||
                                                                                !q.CustomAttributes["cameraAngle"].Equals(subClipAsset.SequenceVideoStream)).ToList();

                    foreach (var qualityLevel in qualityLevelsToRemove)
                    {
                        videoStream.QualityLevels.Remove(qualityLevel);
                    }
                }

                startPosition = GetStartPositionFromManifest(parser);
            }

            ulong clipBegin = (ulong)(Convert.ToUInt64(markIn * Timescale) + startPosition);
            ulong clipEnd   = (ulong)(Convert.ToUInt64(markOut * Timescale) + startPosition);

            Resource resource = shot.Source.Resources.SingleOrDefault(x => !string.IsNullOrEmpty(x.Ref));

            Uri assetUri;

            Uri.TryCreate(resource.Ref, UriKind.Absolute, out assetUri);

            var customAttributes = new Dictionary <string, string> {
                { "CMSId", shot.Source.CMSId }, { "AzureId", shot.Source.AzureId }
            };

            compositeManifestInfo.AddClip(assetUri, clipBegin, clipEnd, customAttributes, parser.ManifestInfo);
        }
Example #22
0
        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);
        }
        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);
            }
        }