Beispiel #1
0
        public async Task Start()
        {
            var streams = M3UPlaylist.Parse(await _client.GetStringAsync(_slideUrl));

            // This will typically select a 720p stream with 3500 Kbps bitrate, the best on offer
            var bestStream = streams.StreamItems.OrderByDescending(s => s.Width * s.Height).First();

            var url          = _slideUrl.Substring(0, _slideUrl.LastIndexOf('/') + 1);
            var itemsListSrc = await _client.GetStringAsync(url + bestStream.Path);

            var itemsList = M3UPlaylist.Parse(itemsListSrc);

            _client.DefaultRequestHeaders.Remove("accept");
            _client.DefaultRequestHeaders.Add("accept", "*/*");

            // Prefetch all the AES keys
            foreach (var key in itemsList.Keys)
            {
                key.Key = await _client.GetByteArrayAsync(key.Uri);

                if (key.Key == null || key.Key.Length != 16)
                {
                    throw new Exception("Failed to retrieve AES key: " + key.Uri);
                }
            }

            var videoBaseUrl = url + bestStream.Path;

            videoBaseUrl = videoBaseUrl.Substring(0, videoBaseUrl.LastIndexOf('/') + 1);
            int i = 0;

            foreach (var video in itemsList.VideoItems)
            {
                var videoUrl = videoBaseUrl + video.Path;
                var raw      = await _client.GetByteArrayAsync(videoUrl);

                i++;
                Aes    crypto    = Aes.Create();
                var    decryptor = crypto.CreateDecryptor(video.Key.Key, video.Key.IV);
                byte[] decrypted = decryptor.TransformFinalBlock(raw, 0, raw.Length);

                if (NewVideoSequence != null)
                {
                    NewVideoSequence(this, new VideoSequenceData {
                        SourceUrl      = videoUrl,
                        RawData        = decrypted,
                        SequenceNumber = video.Sequence,
                        PartsInQueue   = itemsList.VideoItems.Count - i
                    });
                }
            }
        }
Beispiel #2
0
        public static M3UPlaylist Parse(string content)
        {
            var lines = content.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries);

            if (lines[0] != "#EXTM3U")
            {
                return(null);
            }

            var ret = new M3UPlaylist();
            int seq = 0;
            M3UEncryptionKey currentKey = null;

            for (int i = 1; i < lines.Length; i++)
            {
                var line = lines[i];
                if (line.StartsWith("#EXT-X-STREAM-INF:") && (i + 1) != lines.Length)
                {
                    var props = ParseProperties(line);
                    var item  = new M3UStreamItem {
                        Path = lines[++i]
                    };
                    if (props.ContainsKey("RESOLUTION"))
                    {
                        var rect = props["RESOLUTION"].Split('x');
                        item.Width  = int.Parse(rect[0]);
                        item.Height = int.Parse(rect[1]);
                    }
                    if (props.ContainsKey("BANDWIDTH"))
                    {
                        item.Bandwidth = int.Parse(props["BANDWIDTH"]);
                    }
                    if (props.ContainsKey("AVERAGE-BANDWIDTH"))
                    {
                        item.AverageBandwidth = int.Parse(props["AVERAGE-BANDWIDTH"]);
                    }
                    ret.StreamItems.Add(item);
                }
                else if (line.StartsWith("#EXT-X-MEDIA-SEQUENCE"))
                {
                    ret.MediaSequence = int.Parse(line.Split(':')[1]);
                }
                else if (line.StartsWith("#EXT-X-KEY"))
                {
                    var props = ParseProperties(line);
                    currentKey = new M3UEncryptionKey
                    {
                        Method = props["METHOD"],
                        Uri    = props["URI"],
                    };
                    var iv = props["IV"];
                    iv            = iv.Substring(2);
                    currentKey.IV = new byte[iv.Length / 2];
                    for (int j = 0; j < (iv.Length / 2); j++)
                    {
                        currentKey.IV[j] = byte.Parse(iv[j * 2 + 0].ToString() + iv[j * 2 + 1], NumberStyles.HexNumber);
                    }
                    ret.Keys.Add(currentKey);
                }
                else if (line.StartsWith("#EXTINF") && (i + 1) != lines.Length)
                {
                    ret.VideoItems.Add(new M3UVideoItem {
                        Path     = lines[++i],
                        Sequence = ret.MediaSequence + (seq++),
                        Key      = currentKey
                    });
                }
            }
            return(ret);
        }