Example #1
0
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req, ILogger log)
        {
            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));
            }

            ConfigWrapper config             = null;
            var           generalOutputInfos = new List <GeneralOutputInfo>();

            // 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)
            {
                try
                {
                    config = new ConfigWrapper(new ConfigurationBuilder()
                                               .SetBasePath(Directory.GetCurrentDirectory())
                                               .AddEnvironmentVariables()
                                               .Build(),
                                               region
                                               );
                }
                catch (Exception ex)
                {
                    return(IrdetoHelpers.ReturnErrorException(log, ex));
                }
                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;

                var liveEvents = client.LiveEvents.List(config.ResourceGroup, config.AccountName);

                // object to store the output of the function
                var generalOutputInfo = new GeneralOutputInfo();

                // let's list live events
                try
                {
                    generalOutputInfo = GenerateInfoHelpers.GenerateOutputInformation(config, client, liveEvents.ToList());
                }
                catch (Exception ex)
                {
                    return(IrdetoHelpers.ReturnErrorException(log, ex));
                }

                try
                {
                    var success = new List <bool>();
                    foreach (var le in generalOutputInfo.LiveEvents)
                    {
                        success.Add(await CosmosHelpers.CreateOrUpdateGeneralInfoDocument(le));
                    }

                    if (success.Any(b => b == false))
                    {
                        log.LogWarning("Cosmos access not configured.");
                    }
                }
                catch (Exception ex)
                {
                    return(IrdetoHelpers.ReturnErrorException(log, ex));
                }

                generalOutputInfos.Add(generalOutputInfo);
            }

            return(new OkObjectResult(
                       JsonConvert.SerializeObject(new GeneralOutputInfo {
                Success = true, LiveEvents = generalOutputInfos.SelectMany(i => i.LiveEvents).ToList()
            }, Formatting.Indented)
                       ));
        }
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req, ILogger log)
        {
            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 liveEventName = (string)data.liveEventName;

            if (liveEventName == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass liveEventName 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);
            }

            // init default
            var uniquenessAssets = Guid.NewGuid().ToString().Substring(0, 13);

            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;

            var manifestName = liveEventName.ToLower();

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

            foreach (var region in azureRegions)
            {
                var task = Task <LiveEventEntry> .Run(async() =>
                {
                    Asset asset           = null;
                    LiveOutput liveOutput = 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 check that the channel exists
                    var liveEvent = await client.LiveEvents.GetAsync(config.ResourceGroup, config.AccountName, liveEventName);
                    if (liveEvent == null)
                    {
                        throw new Exception($"Live event {liveEventName} does not exist.");
                    }

                    var outputs =
                        await client.LiveOutputs.ListAsync(config.ResourceGroup, config.AccountName, liveEventName);

                    if (outputs.FirstOrDefault() != null)
                    {
                        liveOutput = outputs.FirstOrDefault();
                        asset      = await client.Assets.GetAsync(config.ResourceGroup, config.AccountName,
                                                                  liveOutput.AssetName);
                    }

                    if (asset == null)
                    {
                        throw new Exception("Error - asset not found");
                    }

                    try
                    {
                        // streaming locator creation
                        MediaServicesHelpers.LogInformation(log, "Locator creation...", region);

                        var locator = await IrdetoHelpers.CreateClearLocator(config, streamingLocatorName, client, asset, streamingLocatorGuid);

                        MediaServicesHelpers.LogInformation(log, "locator : " + locator.Name, region);

                        if (liveOutput != null)
                        {
                            await client.Assets.UpdateAsync(config.ResourceGroup, config.AccountName, asset.Name, asset);
                        }
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("locator creation error", ex);
                    }

                    // object to store the output of the function
                    var generalOutputInfo = new GeneralOutputInfo();

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

                    generalOutputInfo =
                        GenerateInfoHelpers.GenerateOutputInformation(config, client, new List <LiveEvent> {
                        liveEvent
                    });

                    if (!await CosmosHelpers.CreateOrUpdateGeneralInfoDocument(generalOutputInfo.LiveEvents[0]))
                    {
                        MediaServicesHelpers.LogWarning(log, "Cosmos access not configured.", region);
                    }

                    return(generalOutputInfo.LiveEvents[0]);
                });

                clientTasks.Add(task);
            }

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

            return(new OkObjectResult(
                       JsonConvert.SerializeObject(new GeneralOutputInfo {
                Success = true, LiveEvents = clientTasks.Select(i => i.Result).ToList()
            }, Formatting.Indented)
                       ));
        }
        public static GeneralOutputInfo GenerateOutputInformation(ConfigWrapper config,
                                                                  IAzureMediaServicesClient client, List <LiveEvent> liveEvents)
        {
            var generalOutputInfo = new GeneralOutputInfo {
                Success = true, LiveEvents = new List <LiveEventEntry>()
            };

            foreach (var liveEventenum in liveEvents)
            {
                var liveEvent =
                    client.LiveEvents.Get(config.ResourceGroup, config.AccountName,
                                          liveEventenum.Name); // we refresh the object

                var liveOutputs = client.LiveOutputs.List(config.ResourceGroup, config.AccountName, liveEvent.Name);

                // let's provide DASH format for preview
                var previewE = liveEvent.Preview.Endpoints
                               .Select(a => new PreviewInfo {
                    Protocol = a.Protocol, Url = a.Url
                }).ToList();

                /*
                 * // Code to expose Preview DASH and not Smooth
                 * if (previewE.Count == 1 && previewE[0].Protocol == "FragmentedMP4")
                 * {
                 *  previewE[0].Protocol = "DashCsf";
                 *  previewE[0].Url = previewE[0].Url + "(format=mpd-time-csf)";
                 * }
                 */


                // output info
                var liveEventInfo = new LiveEventEntry()
                {
                    LiveEventName = liveEvent.Name,
                    ResourceState = liveEvent.ResourceState.ToString(),
                    VanityUrl     = liveEvent.VanityUrl,
                    Input         = liveEvent.Input.Endpoints
                                    .Select(endPoint => new UrlEntry {
                        Protocol = endPoint.Protocol, Url = endPoint.Url
                    }).ToList(),
                    InputACL = liveEvent.Input.AccessControl?.Ip.Allow
                               .Select(ip => ip.Address + "/" + ip.SubnetPrefixLength).ToList(),
                    Preview = previewE
                              .Select(endPoint => new UrlEntry {
                        Protocol = endPoint.Protocol, Url = endPoint.Url
                    }).ToList(),
                    PreviewACL = liveEvent.Preview.AccessControl?.Ip.Allow
                                 .Select(ip => ip.Address + "/" + ip.SubnetPrefixLength).ToList(),
                    LiveOutputs    = new List <LiveOutputEntry>(),
                    AMSAccountName = config.AccountName,
                    Region         = config.Region,
                    ResourceGroup  = config.ResourceGroup,
                    LowLatency     = liveEvent.StreamOptions?.Contains(StreamOptionsFlag.LowLatency)
                };
                generalOutputInfo.LiveEvents.Add(liveEventInfo);

                foreach (var liveOutput in liveOutputs)
                {
                    var             urls = new List <OutputUrl>();
                    string          streamingPolicyName = null;
                    StreamingPolicy streamingPolicy     = null;

                    var asset = client.Assets.Get(config.ResourceGroup, config.AccountName, liveOutput.AssetName);

                    // output info
                    var liveOutputInfo = new LiveOutputEntry
                    {
                        LiveOutputName          = liveOutput.Name,
                        ResourceState           = liveOutput.ResourceState,
                        ArchiveWindowLength     = (int)liveOutput.ArchiveWindowLength.TotalMinutes,
                        AssetName               = liveOutput.AssetName,
                        AssetStorageAccountName = asset?.StorageAccountName,
                        StreamingLocators       = new List <StreamingLocatorEntry>()
                    };
                    liveEventInfo.LiveOutputs.Add(liveOutputInfo);

                    var streamingLocatorsNames = client.Assets.ListStreamingLocators(config.ResourceGroup, config.AccountName, liveOutput.AssetName).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();
                                }

                                urls = MediaServicesHelpers.GetUrls(config, client, streamingLocator,
                                                                    liveOutput.ManifestName, true, true, true, true, true);
                            }
                        }

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

                        liveOutputInfo.StreamingLocators.Add(StreamingLocatorInfo);
                    }
                }
            }

            return(generalOutputInfo);
        }