示例#1
0
        public ISegmentMetadata CreateSegmentMetadata(WebResponse webResponse, ContentType contentType)
        {
            var shoutcast = new ShoutcastHeaders(webResponse.RequestUri, webResponse.Headers);

            if (shoutcast.MetaInterval > 0 || shoutcast.SupportsIcyMetadata)
            {
                var segmentMetadata = new ShoutcastSegmentMetadata
                {
                    Url = webResponse.RequestUri,
                    ContentType = contentType ?? webResponse.ContentType,
                    Length = webResponse.ContentLength,
                    IcyMetaInt = shoutcast.MetaInterval,
                    SupportsIcyMetadata = shoutcast.SupportsIcyMetadata
                };

                return segmentMetadata;
            }

            var streamMetadata = new SegmentMetadata
            {
                Url = webResponse.RequestUri,
                ContentType = contentType ?? webResponse.ContentType,
                Length = webResponse.ContentLength
            };

            return streamMetadata;
        }
示例#2
0
        public IStreamMetadata CreateStreamMetadata(WebResponse webResponse, ContentType contentType = null)
        {
            var shoutcast = new ShoutcastHeaders(webResponse.RequestUri, webResponse.Headers);

            var streamMetadata = new StreamMetadata
            {
                Url = webResponse.RequestUri,
                ContentType = contentType ?? webResponse.ContentType,
                Bitrate = shoutcast.Bitrate,
                Description = shoutcast.Description,
                Genre = shoutcast.Genre,
                Name = shoutcast.Name,
                Website = shoutcast.Website
            };

            return streamMetadata;
        }
示例#3
0
 private void Update(Uri url, HttpWebResponse response, SM.Media.Web.WebResponse webResponse)
 {
     if (null != webResponse)
     {
         webResponse.RequestUri    = response.ResponseUri;
         webResponse.ContentLength = response.ContentLength >= 0L ? new long?(response.ContentLength) : new long?();
         webResponse.Headers       = this.GetHeaders(response.Headers);
         webResponse.ContentType   = EnumerableExtensions.SingleOrDefaultSafe <ContentType>((IEnumerable <ContentType>) this._contentTypeDetector.GetContentType(response.ResponseUri, response.Headers[HttpRequestHeader.ContentType], (string)null));
     }
     if (url != this.BaseAddress)
     {
         return;
     }
     this.RequestUri = response.ResponseUri;
     if (!((ContentType)null == this.ContentType))
     {
         return;
     }
     this.ContentType = EnumerableExtensions.SingleOrDefaultSafe <ContentType>((IEnumerable <ContentType>) this._contentTypeDetector.GetContentType(this.RequestUri, response.Headers[HttpRequestHeader.ContentType], (string)null));
 }
示例#4
0
        async Task<M3U8Parser> FetchPlaylistAsync(CancellationToken cancellationToken)
        {
            var urls = Urls;

            if (null == urls || urls.Count < 1)
                return null;

            foreach (var playlist in urls)
            {
                UpdateSubPlaylistCache(playlist);

                cancellationToken.ThrowIfCancellationRequested();

                WebResponse webResponse = null;

                if (null == StreamMetadata)
                    webResponse = new WebResponse();

                var parsedPlaylist = await _subPlaylistCache.ReadAsync(
                    (actualUri, bytes) =>
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        if (bytes.Length < 1)
                            return null;

                        var parser = new M3U8Parser();

                        using (var ms = new MemoryStream(bytes))
                        {
                            parser.Parse(actualUri, ms);
                        }

                        return parser;
                    }, cancellationToken, webResponse)
                    .ConfigureAwait(false);


                if (null != parsedPlaylist)
                {
                    if (null != webResponse)
                        StreamMetadata = _webMetadataFactory.CreateStreamMetadata(webResponse);

                    return parsedPlaylist;
                }
            }

            return null;
        }
        async Task ReadResponseAsync(IMediaParser mediaParser, IWebStreamResponse webStreamResponse, WebResponse webResponse, QueueThrottle throttle, CancellationToken cancellationToken)
        {
            //Debug.WriteLine("SingleStreamMediaManager.ReadResponseAsync()");

            var buffer = new byte[16 * 1024];

            var cancellationTask = cancellationToken.AsTask();

            try
            {
                var segmentMetadata = _webMetadataFactory.CreateSegmentMetadata(webResponse);

                mediaParser.StartSegment(segmentMetadata);

                using (var stream = await webStreamResponse.GetStreamAsync(cancellationToken).ConfigureAwait(false))
                {
                    for (; ; )
                    {
                        var waitTask = throttle.WaitAsync();

                        if (!waitTask.IsCompleted)
                        {
                            await Task.WhenAny(waitTask, cancellationTask).ConfigureAwait(false);

                            cancellationToken.ThrowIfCancellationRequested();
                        }

                        var length = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false);

                        if (length <= 0)
                            return;

                        mediaParser.ProcessData(buffer, 0, length);
                    }
                }
            }
            finally
            {
                mediaParser.ProcessEndOfData();

                //Debug.WriteLine("SingleStreamMediaManager.ReadResponseAsync() done");
            }
        }
        async Task SimplePlayAsync(ContentType contentType, IWebReader webReader, IWebStreamResponse webStreamResponse, WebResponse webResponse, TaskCompletionSource<bool> configurationTaskCompletionSource, CancellationToken cancellationToken)
        {
            try
            {
                _mediaStreamConfigurator.Initialize();

                _mediaStreamConfigurator.MediaManager = this;

                var mediaParser = await _mediaParserFactory.CreateAsync(new MediaParserParameters(), contentType, cancellationToken).ConfigureAwait(false);

                if (null == mediaParser)
                    throw new NotSupportedException("Unsupported content type: " + contentType);

                State = MediaManagerState.Opening;

                EventHandler configurationComplete = null;

                configurationComplete = (sender, args) =>
                {
                    // ReSharper disable once AccessToModifiedClosure
                    mediaParser.ConfigurationComplete -= configurationComplete;

                    configurationTaskCompletionSource.TrySetResult(true);
                };

                mediaParser.ConfigurationComplete += configurationComplete;

                using (var bufferingManager = _bufferingManagerFactory())
                {
                    var throttle = new QueueThrottle();

                    bufferingManager.Initialize(throttle, _mediaStreamConfigurator.CheckForSamples);

                    mediaParser.Initialize(bufferingManager);

                    var streamMetadata = _webMetadataFactory.CreateStreamMetadata(webResponse);

                    mediaParser.InitializeStream(streamMetadata);

                    Task reader = null;

                    try
                    {
                        using (webReader)
                        {
                            try
                            {
                                if (null == webStreamResponse)
                                    webStreamResponse = await webReader.GetWebStreamAsync(null, false, cancellationToken, response: webResponse).ConfigureAwait(false);

                                reader = ReadResponseAsync(mediaParser, webStreamResponse, webResponse, throttle, cancellationToken);

                                await Task.WhenAny(configurationTaskCompletionSource.Task, cancellationToken.AsTask()).ConfigureAwait(false);

                                cancellationToken.ThrowIfCancellationRequested();

                                await _mediaStreamConfigurator.PlayAsync(mediaParser.MediaStreams, null, cancellationToken).ConfigureAwait(false);

                                State = MediaManagerState.Playing;

                                await reader.ConfigureAwait(false);

                                reader = null;
                            }
                            finally
                            {
                                if (null != webStreamResponse)
                                    webStreamResponse.Dispose();
                            }
                        }
                    }
                    catch (OperationCanceledException)
                    { }
                    catch (Exception ex)
                    {
                        var message = ex.ExtendedMessage();

                        Debug.WriteLine("SingleStreamMediaManager.SimplePlayAsync() failed: " + message);

                        SetMediaState(MediaManagerState.Error, message);
                    }

                    State = MediaManagerState.Closing;

                    if (null != reader)
                    {
                        try
                        {
                            await reader.ConfigureAwait(false);
                        }
                        catch (OperationCanceledException)
                        { }
                        catch (Exception ex)
                        {
                            Debug.WriteLine("SingleStreamMediaManager.SimplePlayAsync() reader failed: " + ex.ExtendedMessage());
                        }
                    }

                    mediaParser.ConfigurationComplete -= configurationComplete;

                    mediaParser.EnableProcessing = false;
                    mediaParser.FlushBuffers();

                    bufferingManager.Flush();

                    bufferingManager.Shutdown(throttle);

                    await _mediaStreamConfigurator.CloseAsync().ConfigureAwait(false);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("SingleStreamMediaManager.SimplePlayAsync() cleanup failed: " + ex.ExtendedMessage());
            }

            _mediaStreamConfigurator.MediaManager = null;

            if (!configurationTaskCompletionSource.Task.IsCompleted)
                configurationTaskCompletionSource.TrySetCanceled();

            State = MediaManagerState.Closed;

            await _reportStateTask.WaitAsync().ConfigureAwait(false);
        }
        public async Task<IMediaStreamConfigurator> OpenMediaAsync(ICollection<Uri> source, CancellationToken cancellationToken)
        {
            State = MediaManagerState.OpenMedia;

            var response = new WebResponse();

            using (var rootWebReader = _webReaderManager.CreateRootReader())
            {
                foreach (var url in source)
                {
                    IWebReader webReader = null;
                    IWebStreamResponse webStream = null;
                    CancellationTokenSource playCancellationTokenSource = null;
                    Task playTask = null;

                    try
                    {
                        webReader = rootWebReader.CreateChild(url, ContentKind.Unknown, ContentType ?? StreamContentType);

                        webStream = await webReader.GetWebStreamAsync(null, false, cancellationToken, response: response).ConfigureAwait(false);

                        if (!webStream.IsSuccessStatusCode)
                            continue;

                        var contentType = response.ContentType;

                        if (null == contentType)
                            continue;

                        if (ContentKind.Playlist == contentType.Kind)
                            throw new FileNotFoundException("Content not supported with this media manager");

                        var configurationTaskCompletionSource = new TaskCompletionSource<bool>();

                        playCancellationTokenSource = new CancellationTokenSource();

                        var localPlayCancellationTokenSource = playCancellationTokenSource;

                        var cancelPlayTask = configurationTaskCompletionSource.Task
                            .ContinueWith(t =>
                            {
                                if (t.IsFaulted || t.IsCanceled)
                                    localPlayCancellationTokenSource.Cancel();
                            });

                        TaskCollector.Default.Add(cancelPlayTask, "SingleStreamMediaManager play cancellation");

                        var localWebReader = webReader;
                        var localWebStream = webStream;
                        var playCancellationToken = playCancellationTokenSource.Token;

                        playTask = Task.Run(() => SimplePlayAsync(contentType, localWebReader, localWebStream, response, configurationTaskCompletionSource, playCancellationToken), playCancellationToken);

                        lock (_lock)
                        {
                            _playCancellationTokenSource = playCancellationTokenSource;
                            playCancellationTokenSource = null;

                            _playTask = playTask;
                            playTask = null;
                        }

                        var isConfigured = await configurationTaskCompletionSource.Task.ConfigureAwait(false);

                        if (isConfigured)
                        {
                            webReader = null;
                            webStream = null;

                            return _mediaStreamConfigurator;
                        }
                    }
                    finally
                    {
                        if (null != webStream)
                            webStream.Dispose();

                        if (null != webReader)
                            webReader.Dispose();

                        if (null != playCancellationTokenSource)
                            playCancellationTokenSource.Cancel();

                        if (null != playTask)
                            TaskCollector.Default.Add(playTask, "SingleStreamMediaManager play task");
                    }
                }
            }

            throw new FileNotFoundException();
        }
        public async Task<IWebStreamResponse> GetWebStreamAsync(Uri url, bool waitForContent, CancellationToken cancellationToken,
            Uri referrer = null, long? from = null, long? to = null, WebResponse webResponse = null)
        {
            ThrowIfDisposed();

            var completionOption = waitForContent ? HttpCompletionOption.ResponseContentRead : HttpCompletionOption.ResponseHeadersRead;

            if (null == referrer && null == from && null == to)
            {
                //Debug.WriteLine("WinRtHttpClientWebReader.GetWebStreamAsync() url {0} wait {1}", url, waitForContent);

                var response = await _httpClient.GetAsync(url, completionOption, cancellationToken).ConfigureAwait(false);

                Update(url, ContentKind.Unknown, response, webResponse);

                return new WinRtHttpClientWebStreamResponse(response);
            }
            else
            {
                //Debug.WriteLine("WinRtHttpClientWebReader.GetWebStreamAsync() url {0} wait {1} referrer {2} [{3}-{4}]",
                //    url, waitForContent, null == referrer ? "<none>" : referrer.ToString(), from, to);

                var request = new HttpRequestMessage(HttpMethod.Get, url);

                var response = await _httpClient.SendAsync(request, completionOption, cancellationToken, referrer, from, to).ConfigureAwait(false);

                Update(url, ContentKind.Unknown, response, webResponse);

                return new WinRtHttpClientWebStreamResponse(request, response);
            }
        }
        void Update(Uri url, ContentKind requiredKind, HttpResponseMessage response, WebResponse webResponse)
        {
            if (!response.IsSuccessStatusCode)
                return;

            if (null != webResponse)
            {
                webResponse.RequestUri = response.RequestMessage.RequestUri;
                webResponse.ContentLength = (long?)response.Content.Headers.ContentLength;
                webResponse.Headers = response.Headers.Concat(response.Content.Headers)
                    .ToLookup(kv => kv.Key, kv => kv.Value)
                    .Select(l => new KeyValuePair<string, IEnumerable<string>>(l.Key, l));

                webResponse.ContentType = _contentTypeDetector.GetContentType(response.RequestMessage.RequestUri, requiredKind, response.Content.Headers, response.Content.FileName()).SingleOrDefaultSafe();
            }

            if (url != BaseAddress)
                return;

            RequestUri = response.RequestMessage.RequestUri;

            if (null == ContentType)
                ContentType = _contentTypeDetector.GetContentType(RequestUri, requiredKind, response.Content.Headers, response.Content.FileName()).SingleOrDefaultSafe();
        }
示例#10
0
        public async Task<byte[]> GetByteArrayAsync(Uri url, CancellationToken cancellationToken, WebResponse webResponse = null)
        {
            ThrowIfDisposed();

            using (var response = await _httpClient.GetAsync(url, HttpCompletionOption.ResponseContentRead, cancellationToken).ConfigureAwait(false))
            {
                StatusCodeWebException.ThrowIfNotSuccess((HttpStatusCode)response.StatusCode, response.ReasonPhrase);

                Update(url, ContentKind.Unknown, response, webResponse);

                return await response.Content.ReadAsByteArray(cancellationToken).ConfigureAwait(false);
            }
        }
示例#11
0
        public async Task <HttpWebResponse> SendAsync(HttpWebRequest request, bool allowBuffering, CancellationToken cancellationToken, SM.Media.Web.WebResponse webResponse = null)
        {
            Uri             url      = request.RequestUri;
            HttpWebResponse response = await this._webReaderManager.SendAsync(this._baseAddress, (IWebReader)this, cancellationToken, (string)null, (ContentType)null, allowBuffering, (Uri)null, new long?(), new long?()).ConfigureAwait(false);

            this.Update(url, response, webResponse);
            return(response);
        }
示例#12
0
 public async Task <byte[]> GetByteArrayAsync(Uri url, CancellationToken cancellationToken, SM.Media.Web.WebResponse webResponse = null)
 {
     if ((Uri)null != this._baseAddress && !url.IsAbsoluteUri)
     {
         url = new Uri(this._baseAddress, url);
     }
     byte[] numArray;
     using (HttpWebResponse response = await this._webReaderManager.SendAsync(url, (IWebReader)this, cancellationToken, (string)null, (ContentType)null, true, (Uri)null, new long?(), new long?()).ConfigureAwait(false))
     {
         this.Update(url, response, webResponse);
         numArray = await HttpWebRequestExtensions.ReadAsByteArrayAsync(response, cancellationToken).ConfigureAwait(false);
     }
     return(numArray);
 }
示例#13
0
        public async Task <IWebStreamResponse> GetWebStreamAsync(Uri url, bool waitForContent, CancellationToken cancellationToken, Uri referrer = null, long?from = null, long?to = null, SM.Media.Web.WebResponse webResponse = null)
        {
            HttpWebRequest  request  = this._webReaderManager.CreateRequest(url, referrer, (IWebReader)this, this.ContentType, (string)null, waitForContent, from, to);
            HttpWebResponse response = await HttpWebRequestExtensions.SendAsync(request, cancellationToken).ConfigureAwait(false);

            this.Update(url, response, webResponse);
            return((IWebStreamResponse) new HttpWebRequestWebStreamResponse(request, response));
        }
示例#14
0
        public async Task <TCached> ReadAsync <TCached>(Func <Uri, byte[], TCached> factory, CancellationToken cancellationToken, SM.Media.Web.WebResponse webResponse = null) where TCached : class
        {
            if (null == (object)(this._cachedObject as TCached))
            {
                this._cachedObject = (object)null;
            }
            IRetry retry = RetryManagerExtensions.CreateWebRetry(this._retryManager, 2, 250);
            await RetryExtensions.CallAsync(retry, (Func <Task>)(() => this.Fetch <TCached>(retry, factory, webResponse, cancellationToken)), cancellationToken).ConfigureAwait(false);

            return(this._cachedObject as TCached);
        }
示例#15
0
        public async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption responseContentRead, CancellationToken cancellationToken, WebResponse webResponse = null)
        {
            ThrowIfDisposed();

            var url = request.RequestUri;

            var response = await _httpClient.SendRequestAsync(request, responseContentRead, cancellationToken).ConfigureAwait(false);

            Update(url, ContentKind.Unknown, response, webResponse);

            return response;
        }
示例#16
0
        private async Task Fetch <TCached>(IRetry retry, Func <Uri, byte[], TCached> factory, SM.Media.Web.WebResponse webResponse, CancellationToken cancellationToken) where TCached : class
        {
label_12:
            HttpWebRequest request = this.CreateRequest();

            using (HttpWebResponse response = await this._webReader.SendAsync(request, true, cancellationToken, webResponse).ConfigureAwait(false))
            {
                int statusCode = (int)response.StatusCode;
                if (statusCode >= 200 && statusCode < 300)
                {
                    this._firstRequestCompleted = true;
                    Func <Uri, byte[], TCached> func1 = factory;
                    Uri responseUri = response.ResponseUri;
                    Func <Uri, byte[], TCached> func2 = func1;
                    HttpWebRequestWebCache      webRequestWebCache = this;
                    byte[] numArray = await this.FetchObject(response, cancellationToken).ConfigureAwait(false);

                    // ISSUE: variable of a boxed type
                    __Boxed <TCached> local = (object)func2(responseUri, numArray);
                    webRequestWebCache._cachedObject = (object)local;
                }
                else if (HttpStatusCode.NotModified != response.StatusCode)
                {
                    if (RetryPolicy.IsRetryable(response.StatusCode))
                    {
                        if (await retry.CanRetryAfterDelayAsync(cancellationToken).ConfigureAwait(false))
                        {
                            goto label_12;
                        }
                    }
                    this._cachedObject = (object)null;
                    throw new WebException("Unable to fetch");
                }
            }
        }
示例#17
0
        private Task OpenStream(Action <ISegmentMetadata> setMetadata, CancellationToken cancellationToken)
        {
            this.ThrowIfDisposed();
            SM.Media.Web.WebResponse webResponse = new SM.Media.Web.WebResponse();
            IRetry retry = this._retryManager.CreateRetry(2, 200, new Func <Exception, bool>(RetryPolicy.IsWebExceptionRetryable));

            return(RetryExtensions.CallAsync(retry, (Func <Task>)(async() =>
            {
                long?nullable1;
                long?nullable2;
                while (true)
                {
                    if (this._startOffset.HasValue && this._endOffset.HasValue)
                    {
                        nullable1 = this._endOffset;
                        nullable2 = this._startOffset;
                        nullable1 = nullable1.HasValue & nullable2.HasValue ? new long?(nullable1.GetValueOrDefault() - nullable2.GetValueOrDefault()) : new long?();
                        long?nullable3;
                        if (!nullable1.HasValue)
                        {
                            nullable2 = new long?();
                            nullable3 = nullable2;
                        }
                        else
                        {
                            nullable3 = new long?(nullable1.GetValueOrDefault() + 1L);
                        }
                        this._expectedBytes = nullable3;
                    }
                    else
                    {
                        this._expectedBytes = new long?();
                    }
                    this._response = await this._webReader.GetWebStreamAsync(this._actualUrl ?? this._segment.Url, false, cancellationToken, this._segment.ParentUrl, this._startOffset, this._endOffset, webResponse).ConfigureAwait(false);
                    if (!this._response.IsSuccessStatusCode)
                    {
                        HttpStatusCode statusCode = (HttpStatusCode)this._response.HttpStatusCode;
                        if (HttpStatusCode.NotFound != statusCode && !RetryPolicy.IsRetryable(statusCode))
                        {
                            this._response.EnsureSuccessStatusCode();
                        }
                        bool canRetry = await retry.CanRetryAfterDelayAsync(cancellationToken).ConfigureAwait(false);
                        if (!canRetry)
                        {
                            if ((Uri)null != this._actualUrl && this._actualUrl != this._segment.Url)
                            {
                                this._actualUrl = (Uri)null;
                            }
                            else
                            {
                                this._response.EnsureSuccessStatusCode();
                            }
                        }
                        this._response.Dispose();
                        this._response = (IWebStreamResponse)null;
                    }
                    else
                    {
                        break;
                    }
                }
                this._actualUrl = this._response.ActualUrl;
                long?contentLength = this._response.ContentLength;
                if (!this._endOffset.HasValue)
                {
                    nullable1 = contentLength;
                    long?nullable3;
                    if (!nullable1.HasValue)
                    {
                        nullable2 = new long?();
                        nullable3 = nullable2;
                    }
                    else
                    {
                        nullable3 = new long?(nullable1.GetValueOrDefault() - 1L);
                    }
                    this._endOffset = nullable3;
                }
                if (!this._expectedBytes.HasValue)
                {
                    this._expectedBytes = contentLength;
                }
                SegmentReader segmentReader1 = this;
                ConfiguredTaskAwaitable <Stream> configuredTaskAwaitable = this._response.GetStreamAsync(cancellationToken).ConfigureAwait(false);
                PositionStream positionStream = new PositionStream(await configuredTaskAwaitable);
                segmentReader1._responseStream = (Stream)positionStream;
                Task <Stream> filterStreamTask = this._segment.CreateFilterAsync(this._responseStream, cancellationToken);
                if (null != filterStreamTask)
                {
                    SegmentReader segmentReader2 = this;
                    configuredTaskAwaitable = filterStreamTask.ConfigureAwait(false);
                    Stream stream = await configuredTaskAwaitable;
                    segmentReader2._readStream = stream;
                }
                else
                {
                    this._readStream = this._responseStream;
                }
                ISegmentMetadata segmentMetadata = this._webMetadataFactory.CreateSegmentMetadata(webResponse, (ContentType)null);
                setMetadata(segmentMetadata);
            }), cancellationToken));
        }