public static async Task <AssetEntry> GenerateAssetInformation(ConfigWrapper config,
                                                                       IAzureMediaServicesClient client, Asset asset, VodSemaphore semaphore, string contentId = null, string region = null)
        {
            var assetEntry = new AssetEntry()
            {
                AMSAccountName          = config.AccountName,
                Region                  = config.Region,
                ResourceGroup           = config.ResourceGroup,
                AssetStorageAccountName = asset?.StorageAccountName,
                AssetName               = asset.Name,
                Urn               = semaphore?.Urn,
                Semaphore         = semaphore,
                StreamingLocators = new List <StreamingLocatorEntry>(),
                CreatedTime       = asset.Created.ToUniversalTime().ToString(AssetEntry.DateFormat),
                ContentId         = contentId,
            };

            var             urls = new List <OutputUrl>();
            string          streamingPolicyName = null;
            StreamingPolicy streamingPolicy     = null;

            var streamingLocatorsNames = client.Assets.ListStreamingLocators(config.ResourceGroup, config.AccountName, asset.Name).StreamingLocators.Select(l => l.Name);

            foreach (var locatorName in streamingLocatorsNames)
            {
                string           cenckeyId        = null;
                string           cbcskeyId        = null;
                StreamingLocator streamingLocator = null;

                if (locatorName != null)
                {
                    streamingLocator = client.StreamingLocators.Get(config.ResourceGroup,
                                                                    config.AccountName, locatorName);
                    if (streamingLocator != null)
                    {
                        streamingPolicyName = streamingLocator.StreamingPolicyName;

                        if (streamingLocator.ContentKeys
                            .Where(k => k.LabelReferenceInStreamingPolicy == IrdetoHelpers.labelCenc)
                            .FirstOrDefault() != null && streamingLocator.ContentKeys
                            .Where(k => k.LabelReferenceInStreamingPolicy == IrdetoHelpers.labelCbcs)
                            .FirstOrDefault() != null)
                        {
                            cenckeyId = streamingLocator.ContentKeys
                                        .Where(k => k.LabelReferenceInStreamingPolicy == IrdetoHelpers.labelCenc)
                                        .FirstOrDefault().Id.ToString();
                            cbcskeyId = streamingLocator.ContentKeys
                                        .Where(k => k.LabelReferenceInStreamingPolicy == IrdetoHelpers.labelCbcs)
                                        .FirstOrDefault().Id.ToString();
                        }


                        // let's get the manifest name
                        string manifestName        = null;
                        List <IListBlobItem> blobs = new List <IListBlobItem>();
                        try
                        {
                            ListContainerSasInput input = new ListContainerSasInput()
                            {
                                Permissions = AssetContainerPermission.Read,
                                ExpiryTime  = DateTime.Now.AddHours(2).ToUniversalTime()
                            };

                            var    responseListSas = client.Assets.ListContainerSas(config.ResourceGroup, config.AccountName, asset.Name, input.Permissions, input.ExpiryTime);
                            string uploadSasUrl    = responseListSas.AssetContainerSasUrls.First();

                            var sasUri    = new Uri(uploadSasUrl);
                            var container = new CloudBlobContainer(sasUri);

                            BlobContinuationToken continuationToken = null;
                            do
                            {
                                var response = await container.ListBlobsSegmentedAsync(continuationToken);

                                continuationToken = response.ContinuationToken;
                                blobs.AddRange(response.Results);
                            }while (continuationToken != null);

                            // let's take the first manifest file. It should exist
                            manifestName = blobs.Where(b => (b.GetType() == typeof(CloudBlockBlob))).Select(b => (CloudBlockBlob)b).Where(b => b.Name.ToLower().EndsWith(".ism")).FirstOrDefault().Name;
                        }
                        catch
                        {
                        }
                        if (manifestName != null) // there is a manifest
                        {
                            urls = MediaServicesHelpers.GetUrls(config, client, streamingLocator, manifestName, true, true, true, true, true);
                        }
                        else // no manifest
                        {
                            urls = MediaServicesHelpers.GetDownloadUrls(config, client, streamingLocator, blobs);
                        }
                    }
                }

                if (streamingPolicyName != null)
                {
                    streamingPolicy = client.StreamingPolicies.Get(config.ResourceGroup, config.AccountName,
                                                                   streamingPolicyName);
                }

                var drmlist = new List <Drm>();
                if (streamingPolicy != null)
                {
                    if (streamingPolicy.CommonEncryptionCbcs != null)
                    {
                        var enProt =
                            MediaServicesHelpers.ReturnOutputProtocolsListCbcs(streamingPolicy
                                                                               .CommonEncryptionCbcs.EnabledProtocols);
                        drmlist.Add(new Drm
                        {
                            Type       = "FairPlay",
                            LicenseUrl =
                                streamingPolicy?.CommonEncryptionCbcs?.Drm.FairPlay
                                .CustomLicenseAcquisitionUrlTemplate.Replace("{ContentKeyId}", cbcskeyId).Replace("{AlternativeMediaId}", streamingLocator.AlternativeMediaId),
                            Protocols      = enProt,
                            CertificateUrl = config.IrdetoFairPlayCertificateUrl
                        });
                    }

                    if (streamingPolicy.CommonEncryptionCenc != null)
                    {
                        var enProtW =
                            MediaServicesHelpers.ReturnOutputProtocolsListCencWidevine(streamingPolicy
                                                                                       .CommonEncryptionCbcs.EnabledProtocols);
                        var enProtP =
                            MediaServicesHelpers.ReturnOutputProtocolsListCencPlayReady(streamingPolicy
                                                                                        .CommonEncryptionCbcs.EnabledProtocols);

                        drmlist.Add(new Drm
                        {
                            Type       = "PlayReady",
                            LicenseUrl = streamingPolicy?.CommonEncryptionCenc?.Drm.PlayReady
                                         .CustomLicenseAcquisitionUrlTemplate.Replace("{AlternativeMediaId}", streamingLocator.AlternativeMediaId),
                            Protocols = enProtP
                        });
                        drmlist.Add(new Drm
                        {
                            Type       = "Widevine",
                            LicenseUrl = streamingPolicy?.CommonEncryptionCenc?.Drm.Widevine
                                         .CustomLicenseAcquisitionUrlTemplate.Replace("{AlternativeMediaId}", streamingLocator.AlternativeMediaId),
                            Protocols = enProtW
                        });
                    }
                }

                var StreamingLocatorInfo = new StreamingLocatorEntry
                {
                    StreamingLocatorName = locatorName,
                    StreamingPolicyName  = streamingPolicyName,
                    CencKeyId            = cenckeyId,
                    CbcsKeyId            = cbcskeyId,
                    Drm  = drmlist,
                    Urls = urls.Select(url => new UrlEntry {
                        Protocol = url.Protocol.ToString(), Url = url.Url
                    })
                           .ToList()
                };

                assetEntry.StreamingLocators.Add(StreamingLocatorInfo);
            }

            return(assetEntry);
        }
Exemple #2
0
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req, ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            dynamic data;

            try
            {
                data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }


            var assetName = (string)data.assetName;

            if (assetName == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass assetName in the JSON"));
            }


            // Azure region management
            var azureRegions = new List <string>();

            if ((string)data.azureRegion != null)
            {
                azureRegions = ((string)data.azureRegion).Split(',').ToList();
            }
            else
            {
                azureRegions.Add((string)null);
            }

            // semaphore file (json structure)
            VodSemaphore semaphore = null;

            if (data.semaphore != null)
            {
                semaphore = VodSemaphore.FromJson((string)data.semaphore);
            }


            // init default
            var    streamingLocatorGuid = Guid.NewGuid(); // same locator for the two ouputs if 2 live event namle created
            var    uniquenessLocator    = streamingLocatorGuid.ToString().Substring(0, 13);
            var    streamingLocatorName = "locator-" + uniquenessLocator;
            string locatorPath          = string.Empty;

            string uniquenessPolicyName = Guid.NewGuid().ToString().Substring(0, 13);

            // Default content id and semaphare value
            string irdetoContentId = null;

            if (semaphore != null && semaphore.DrmContentId != null) // semaphore data has higher priority
            {
                irdetoContentId = semaphore.DrmContentId;
            }
            else if (data.defaultIrdetoContentId != null)
            {
                irdetoContentId = (string)data.defaultIrdetoContentId;
            }

            var clientTasks = new List <Task <AssetEntry> >();

            foreach (var region in azureRegions)
            {
                var task = Task <AssetEntry> .Run(async() =>
                {
                    Asset asset = null;

                    ConfigWrapper config = new ConfigWrapper(new ConfigurationBuilder()
                                                             .SetBasePath(Directory.GetCurrentDirectory())
                                                             .AddEnvironmentVariables()
                                                             .Build(),
                                                             region
                                                             );

                    MediaServicesHelpers.LogInformation(log, "config loaded.", region);
                    MediaServicesHelpers.LogInformation(log, "connecting to AMS account : " + config.AccountName, region);

                    var client = await MediaServicesHelpers.CreateMediaServicesClientAsync(config);
                    // Set the polling interval for long running operations to 2 seconds.
                    // The default value is 30 seconds for the .NET client SDK
                    client.LongRunningOperationRetryTimeout = 2;

                    // let's get the asset
                    try
                    {
                        MediaServicesHelpers.LogInformation(log, "Getting asset.", region);
                        asset = await client.Assets.GetAsync(config.ResourceGroup, config.AccountName, assetName);
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("Error when retreving asset by name", ex);
                    }


                    // Locator creation
                    try
                    {
                        StreamingLocator locator = null;
                        locator = await IrdetoHelpers.CreateClearLocator(config, streamingLocatorName, client, asset, streamingLocatorGuid);

                        MediaServicesHelpers.LogInformation(log, "locator : " + locator.Name, region);
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("Error when creating the locator", ex);
                    }


                    // let's build info for the live event and output

                    AssetEntry assetEntry = await GenerateInfoHelpers.GenerateAssetInformation(config, client, asset, semaphore, irdetoContentId, region);

                    var locatorPath2 = assetEntry.StreamingLocators.Where(l => l.StreamingLocatorName == streamingLocatorName).First().Urls.Where(u => u.Protocol == OutputProtocol.SmoothStreaming.ToString()).First().Url;
                    var uriloc       = new Uri(locatorPath2);
                    locatorPath      = uriloc.Scheme + "://" + uriloc.Host + "/" + uriloc.Segments[1];

                    if (!await CosmosHelpers.CreateOrUpdateAssetDocument(assetEntry))
                    {
                        log.LogWarning("Cosmos access not configured.");
                    }

                    return(assetEntry);
                });

                clientTasks.Add(task);
            }

            try
            {
                Task.WaitAll(clientTasks.ToArray());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            return(new OkObjectResult(
                       JsonConvert.SerializeObject(new VodAssetInfoSimple {
                CreatedLocatorName = streamingLocatorName, CreatedLocatorPath = locatorPath, Success = true, Asset = clientTasks.Select(i => i.Result).First()
            }, Formatting.Indented)
                       ));
        }
        public async static Task <ManifestGenerated> LoadAndUpdateManifestTemplateUsingSemaphore(VodSemaphore semaphore, Microsoft.Azure.WebJobs.ExecutionContext execContext, string manifestFileName = null)
        {
            var mediaAssetFiles = semaphore.Files.Where(f => f.ContainsVideo || f.ContainsAudio);
            var audioFiles      = semaphore.Files.Where(f => f.ContainsAudio);
            var videoFiles      = semaphore.Files.Where(f => f.ContainsVideo);

            if (mediaAssetFiles.Count() != 0)
            {
                // let's load the manifest template
                string manifestPath = Path.Combine(System.IO.Directory.GetParent(execContext.FunctionDirectory).FullName, "ManifestTemplate", "manifest.ism");

                XDocument doc = XDocument.Load(manifestPath);

                XNamespace ns = "http://www.w3.org/2001/SMIL20/Language";

                var bodyxml = doc.Element(ns + "smil");
                var body2   = bodyxml.Element(ns + "body");

                var switchxml = body2.Element(ns + "switch");

                // audio tracks
                foreach (var file in audioFiles)
                {
                    var myListAt = new List <XAttribute>()
                    {
                        new XAttribute("src", file.FileName)
                    };
                    if (file.AudioLanguage != null)
                    {
                        myListAt.Add(new XAttribute("systemLanguage", file.AudioLanguage));
                    }

                    /*
                     * // No need as it is recommended to use trackName for audio
                     * if (file.AudioTitle != null)
                     *  myListAt.Add(new XAttribute("title", file.AudioTitle));
                     */

                    var myListElem = new List <XElement>();
                    if (file.AudioTrackName != null)
                    {
                        myListElem.Add(new XElement(ns + "param", new List <XAttribute> {
                            new XAttribute("name", "trackName"), new XAttribute("value", file.AudioTrackName)
                        }));
                    }
                    if (file.AudioAccessibility != null)
                    {
                        myListElem.Add(new XElement(ns + "param", new List <XAttribute> {
                            new XAttribute("name", "accessibility"), new XAttribute("value", file.AudioAccessibility)
                        }));
                    }
                    if (file.AudioRole != null)
                    {
                        myListElem.Add(new XElement(ns + "param", new List <XAttribute> {
                            new XAttribute("name", "role"), new XAttribute("value", file.AudioRole)
                        }));
                    }

                    var audioElement = new XElement(ns + "audio", myListAt);
                    audioElement.Add(myListElem);
                    switchxml.Add(audioElement);
                }


                // video tracks
                foreach (var file in videoFiles)
                {
                    switchxml.Add(new XElement(ns + "video", new XAttribute("src", file.FileName)));
                }

                // manifest filename
                if (manifestFileName == null)
                {
                    manifestFileName = CommonPrefix(mediaAssetFiles.Select(f => Path.GetFileNameWithoutExtension(f.FileName)).ToArray());
                    if (string.IsNullOrEmpty(manifestFileName))
                    {
                        manifestFileName = "manifest";
                    }
                    else if (manifestFileName.EndsWith("_") && manifestFileName.Length > 1) // i string ends with "_", let's remove it
                    {
                        manifestFileName = manifestFileName.Substring(0, manifestFileName.Length - 1);
                    }
                    manifestFileName = manifestFileName + ".ism";
                }
                else if (!manifestFileName.ToLower().EndsWith(".ism"))
                {
                    manifestFileName = manifestFileName + ".ism";
                }

                return(new ManifestGenerated()
                {
                    Content = doc.Declaration.ToString() + Environment.NewLine + doc.ToString(), FileName = manifestFileName
                });
            }
            else
            {
                return(new ManifestGenerated()
                {
                    Content = null, FileName = string.Empty
                });                                                                         // no mp4 in asset
            }
        }
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req, ILogger log, Microsoft.Azure.WebJobs.ExecutionContext execContext)
        {
            MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request.");

            dynamic data;

            try
            {
                data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            var generalOutputInfos = new List <GeneralOutputInfo>();

            var assetName = (string)data.assetName;

            if (assetName == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass assetName in the JSON"));
            }

            var fileName = (string)data.fileName;
            ManifestGenerated smildata = null;

            VodSemaphore semaphore = null;

            if (data.semaphore != null)
            {
                semaphore = VodSemaphore.FromJson((string)data.semaphore);
            }

            // Azure region management
            var azureRegions = new List <string>();

            if ((string)data.azureRegion != null)
            {
                azureRegions = ((string)data.azureRegion).Split(',').ToList();
            }
            else
            {
                azureRegions.Add((string)null);
            }


            foreach (var region in azureRegions)
            {
                ConfigWrapper config = new ConfigWrapper(new ConfigurationBuilder()
                                                         .SetBasePath(Directory.GetCurrentDirectory())
                                                         .AddEnvironmentVariables()
                                                         .Build(),
                                                         region
                                                         );

                MediaServicesHelpers.LogInformation(log, "config loaded.", region);
                MediaServicesHelpers.LogInformation(log, "connecting to AMS account : " + config.AccountName, region);

                var client = await MediaServicesHelpers.CreateMediaServicesClientAsync(config);

                // Set the polling interval for long running operations to 2 seconds.
                // The default value is 30 seconds for the .NET client SDK
                client.LongRunningOperationRetryTimeout = 2;

                MediaServicesHelpers.LogInformation(log, "asset name : " + assetName, region);
                var asset = client.Assets.Get(config.ResourceGroup, config.AccountName, assetName);

                if (asset == null)
                {
                    throw new Exception($"Asset {asset}  does not exist.");
                }

                // Access to container
                ListContainerSasInput input = new ListContainerSasInput()
                {
                    Permissions = AssetContainerPermission.ReadWriteDelete,
                    ExpiryTime  = DateTime.Now.AddHours(2).ToUniversalTime()
                };

                var responseListSas = await client.Assets.ListContainerSasAsync(config.ResourceGroup, config.AccountName, asset.Name, input.Permissions, input.ExpiryTime);

                string uploadSasUrl = responseListSas.AssetContainerSasUrls.First();

                var sasUri    = new Uri(uploadSasUrl);
                var container = new CloudBlobContainer(sasUri);

                // Manifest generate
                smildata = (semaphore == null) ? await ManifestHelpers.LoadAndUpdateManifestTemplate(asset, container, execContext, fileName)
                                                : await ManifestHelpers.LoadAndUpdateManifestTemplateUsingSemaphore(semaphore, execContext, fileName);

                // if not file name passed, then we use the one generated based on mp4 files names
                if (fileName == null)
                {
                    fileName = smildata.FileName;
                }

                var blob = container.GetBlockBlobReference(fileName);

                using (Stream s = ManifestHelpers.GenerateStreamFromString(smildata.Content))
                {
                    await blob.UploadFromStreamAsync(s);
                }
            }

            var response = new JObject
            {
                { "success", true },
                { "fileName", fileName },
                { "manifestContent", smildata.Content },
                {
                    "operationsVersion",
                    AssemblyName.GetAssemblyName(Assembly.GetExecutingAssembly().Location).Version.ToString()
                }
            };

            return(new OkObjectResult(
                       response
                       ));
        }
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req, ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            dynamic data;

            try
            {
                data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }


            var assetName = (string)data.assetName;

            if (assetName == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass assetName in the JSON"));
            }


            // Azure region management
            var azureRegions = new List <string>();

            if ((string)data.azureRegion != null)
            {
                azureRegions = ((string)data.azureRegion).Split(',').ToList();
            }
            else
            {
                azureRegions.Add((string)null);
            }

            // semaphore file (json structure)
            VodSemaphore semaphore = null;

            if (data.semaphore != null)
            {
                semaphore = VodSemaphore.FromJson((string)data.semaphore);
            }


            // init default
            var streamingLocatorGuid = Guid.NewGuid(); // same locator for the two ouputs if 2 live event namle created
            var uniquenessLocator    = streamingLocatorGuid.ToString().Substring(0, 13);
            var streamingLocatorName = "locator-" + uniquenessLocator;

            string uniquenessPolicyName = Guid.NewGuid().ToString().Substring(0, 13);

            // useDRM init
            var useDRM = true;

            if (data.useDRM != null)
            {
                useDRM = (bool)data.useDRM;
            }
            else if (semaphore != null & semaphore.ClearStream != null)
            {
                useDRM = !(bool)semaphore.ClearStream;
            }


            // Default content id and semaphare value
            string irdetoContentId = null;

            if (semaphore != null && semaphore.DrmContentId != null) // semaphore data has higher priority
            {
                irdetoContentId = semaphore.DrmContentId;
            }
            else if (data.defaultIrdetoContentId != null)
            {
                irdetoContentId = (string)data.defaultIrdetoContentId;
            }

            DateTime?startTime = null;
            DateTime?endTime   = null;

            try
            {
                if (semaphore != null && semaphore.StartTime != null)
                {
                    startTime = DateTime.ParseExact(semaphore.StartTime, AssetEntry.DateFormat, System.Globalization.CultureInfo.InvariantCulture);
                }
                if (semaphore != null && semaphore.EndTime != null)
                {
                    endTime = DateTime.ParseExact(semaphore.EndTime, AssetEntry.DateFormat, System.Globalization.CultureInfo.InvariantCulture);
                }
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }


            var cencKey = new StreamingLocatorContentKey();
            var cbcsKey = new StreamingLocatorContentKey();

            if (useDRM)
            {
                try
                {
                    ConfigWrapper config = new ConfigWrapper(new ConfigurationBuilder()
                                                             .SetBasePath(Directory.GetCurrentDirectory())
                                                             .AddEnvironmentVariables()
                                                             .Build(),
                                                             null);

                    MediaServicesHelpers.LogInformation(log, "Irdeto call...");

                    cencKey = await IrdetoHelpers.GenerateAndRegisterCENCKeyToIrdeto(irdetoContentId, config);

                    cbcsKey = await IrdetoHelpers.GenerateAndRegisterCBCSKeyToIrdeto(irdetoContentId, config);

                    MediaServicesHelpers.LogInformation(log, "Irdeto call done.");
                }
                catch (Exception ex)
                {
                    return(IrdetoHelpers.ReturnErrorException(log, ex, "Irdeto response error"));
                }
            }

            var clientTasks = new List <Task <AssetEntry> >();

            foreach (var region in azureRegions)
            {
                var task = Task <AssetEntry> .Run(async() =>
                {
                    Asset asset = null;
                    StreamingPolicy streamingPolicy = null;

                    ConfigWrapper config = new ConfigWrapper(new ConfigurationBuilder()
                                                             .SetBasePath(Directory.GetCurrentDirectory())
                                                             .AddEnvironmentVariables()
                                                             .Build(),
                                                             region
                                                             );

                    MediaServicesHelpers.LogInformation(log, "config loaded.", region);
                    MediaServicesHelpers.LogInformation(log, "connecting to AMS account : " + config.AccountName, region);

                    var client = await MediaServicesHelpers.CreateMediaServicesClientAsync(config);
                    // Set the polling interval for long running operations to 2 seconds.
                    // The default value is 30 seconds for the .NET client SDK
                    client.LongRunningOperationRetryTimeout = 2;

                    if (useDRM)
                    {
                        MediaServicesHelpers.LogInformation(log, "Trying to read streaming policy from Cosmos.", region);
                        string streamingPolicyName = null;
                        // Load streaming policy info from Cosmos
                        try
                        {
                            var info = await CosmosHelpers.ReadStreamingPolicyDocument(new StreamingPolicyInfo(true)
                            {
                                AMSAccountName = config.AccountName
                            });

                            if (info == null)
                            {
                                log.LogWarning("Streaming policy not read from Cosmos.");
                            }
                            else
                            {
                                streamingPolicyName = info.StreamingPolicyName;
                            }
                        }
                        catch (Exception ex)
                        {
                            throw new Exception("Error reading Cosmos DB", ex);
                        }


                        // STREAMING POLICY CREATION
                        if (streamingPolicyName == null) // not found in Cosmos let's create a new one
                        {
                            MediaServicesHelpers.LogInformation(log, "Creating streaming policy.", region);
                            try
                            {
                                streamingPolicy = await IrdetoHelpers.CreateStreamingPolicyIrdeto(config, client, uniquenessPolicyName);
                            }
                            catch (Exception ex)
                            {
                                throw new Exception("Streaming policy creation error", ex);
                            }

                            try
                            {
                                if (!await CosmosHelpers.CreateOrUpdatePolicyDocument(new StreamingPolicyInfo(true)
                                {
                                    AMSAccountName = config.AccountName,
                                    StreamingPolicyName = streamingPolicy.Name
                                }))
                                {
                                    log.LogWarning("Cosmos access not configured or error.");
                                }
                            }
                            catch (Exception ex)
                            {
                                throw new Exception("Streaming policy write error to Cosmos", ex);
                            }
                        }
                        else
                        {
                            MediaServicesHelpers.LogInformation(log, "Getting streaming policy in AMS.", region);
                            try
                            {
                                streamingPolicy = await client.StreamingPolicies.GetAsync(config.ResourceGroup, config.AccountName, streamingPolicyName);
                            }
                            catch (Exception ex)
                            {
                                throw new Exception("Error when getting streaming policy " + streamingPolicy, ex);
                            }
                        }
                    }


                    // let's get the asset
                    try
                    {
                        MediaServicesHelpers.LogInformation(log, "Getting asset.", region);
                        asset = await client.Assets.GetAsync(config.ResourceGroup, config.AccountName, assetName);
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("Error when retreving asset by name", ex);
                    }


                    // Locator creation
                    try
                    {
                        StreamingLocator locator = null;
                        if (useDRM)
                        {
                            locator = await IrdetoHelpers.SetupDRMAndCreateLocatorWithNewKeys(config, streamingPolicy.Name,
                                                                                              streamingLocatorName, client, asset, cencKey, cbcsKey, streamingLocatorGuid, irdetoContentId, startTime, endTime);
                        }
                        else // no DRM
                        {
                            locator = await IrdetoHelpers.CreateClearLocator(config, streamingLocatorName, client, asset, streamingLocatorGuid, startTime, endTime);
                        }

                        MediaServicesHelpers.LogInformation(log, "locator : " + locator.Name, region);
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("Error when creating the locator", ex);
                    }


                    // let's build info for the live event and output

                    AssetEntry assetEntry = await GenerateInfoHelpers.GenerateAssetInformation(config, client, asset, semaphore, irdetoContentId, region);

                    if (!await CosmosHelpers.CreateOrUpdateAssetDocument(assetEntry))
                    {
                        log.LogWarning("Cosmos access not configured.");
                    }

                    return(assetEntry);
                });

                clientTasks.Add(task);
            }

            try
            {
                Task.WaitAll(clientTasks.ToArray());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            return(new OkObjectResult(
                       JsonConvert.SerializeObject(new VodAssetInfo {
                Success = true, Assets = clientTasks.Select(i => i.Result).ToList()
            }, Formatting.Indented)
                       ));
        }