Example #1
0
        void HandleKey(SubStreamSegment segment, IEnumerable<ExtKeyTagInstance> extKeys, CancellationToken cancellationToken)
        {
            var keys = extKeys.ToArray();

            if (keys.Length < 1)
                return;

            string keyUri = null;
            byte[] iv = null;

            foreach (var key in keys)
            {
                var method = key.AttributeObject(ExtKeySupport.AttrMethod);

                if (string.Equals(MethodNone, method, StringComparison.OrdinalIgnoreCase))
                {
                    keyUri = null;
                    continue;
                }

                if (!string.Equals(MethodAes, method, StringComparison.OrdinalIgnoreCase))
                {
                    if (string.Equals(MethodSampleAes, method, StringComparison.OrdinalIgnoreCase))
                        throw new NotImplementedException("Method SAMPLE-AES decryption is not implemented");

                    throw new NotSupportedException("Unknown decryption method type: " + method);
                }

                var newUri = key.AttributeObject(ExtKeySupport.AttrUri);
                if (null != newUri)
                    keyUri = newUri;

                var newIv = key.AttributeObject(ExtKeySupport.AttrIv);
                if (null != newIv)
                    iv = newIv;
            }

            if (null == keyUri)
                return;

            if (null == iv)
            {
                iv = new byte[16];

                var ms = segment.MediaSequence ?? (_segmentIndex - 1);

                iv[15] = (byte)(ms & 0xff);
                iv[14] = (byte)((ms >> 8) & 0xff);
                iv[13] = (byte)((ms >> 16) & 0xff);
                iv[12] = (byte)((ms >> 24) & 0xff);
            }

            var filter = segment.AsyncStreamFilter;

            var uri = _parser.ResolveUrl(keyUri);

            segment.AsyncStreamFilter =
                async (stream, ct) =>
                {
                    if (null != filter)
                        stream = await filter(stream, ct).ConfigureAwait(false);

                    byte[] key;

                    if (!_keyCache.TryGetValue(uri, out key))
                    {
                        key = await LoadKeyAsync(uri, cancellationToken).ConfigureAwait(false);

                        if (16 != key.Length)
                            throw new FormatException("AES-128 key length mismatch: " + key.Length);

                        _keyCache[uri] = key;
                    }

                    Debug.WriteLine("Segment AES-128: key {0} iv {1}", BitConverter.ToString(key), BitConverter.ToString(iv));

                    return _platformServices.Aes128DecryptionFilter(stream, key, iv);
                };
        }
Example #2
0
        ISegment CreateStreamSegment(M3U8Parser.M3U8Uri uri, CancellationToken cancellationToken)
        {
            var url = _parser.ResolveUrl(uri.Uri);

            var segment = new SubStreamSegment(url, _parser.BaseUrl);

            if (_mediaSequence.HasValue)
                segment.MediaSequence = _mediaSequence + _segmentIndex;

            ++_segmentIndex;

            var tags = uri.Tags;

            if (null == tags || 0 == tags.Length)
                return segment;

            var info = M3U8Tags.ExtXInf.Find(tags);

            if (null != info)
                segment.Duration = TimeSpan.FromSeconds((double)info.Duration);

            var byteRange = M3U8Tags.ExtXByteRange.Find(tags);
            if (null != byteRange)
                HandleByteRange(segment, byteRange);

            var extKeys = M3U8Tags.ExtXKey.FindAll(tags);

            if (null != extKeys)
                HandleKey(segment, extKeys, cancellationToken);

            return segment;
        }
Example #3
0
        void HandleByteRange(SubStreamSegment segment, ByterangeTagInstance byteRange)
        {
            if (byteRange.Offset.HasValue)
            {
                segment.Offset = byteRange.Offset.Value;
                _byteRangeOffset = byteRange.Offset.Value;
            }
            else
                segment.Offset = _byteRangeOffset;

            segment.Length = byteRange.Length;
            _byteRangeOffset += byteRange.Length;
        }