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