private async Task <M3U8Parser> FetchPlaylistAsync(CancellationToken cancellationToken) { var urls = Urls; if (urls == null || urls.Count < 1) { return(null); } foreach (Uri 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 memoryStream = new MemoryStream(bytes)) { parser.Parse(actualUri, memoryStream); } return(parser); }, cancellationToken, webResponse).ConfigureAwait(false); if (null != parsedPlaylist) { if (null != webResponse) { StreamMetadata = _webMetadataFactory.CreateStreamMetadata(webResponse); } return(parsedPlaylist); } } return(null); }
private Task OpenStream(Action <ISegmentMetadata> setMetadata, CancellationToken cancellationToken) { this.ThrowIfDisposed(); WebResponse webResponse = new 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)); }
private async Task SimplePlayAsync(ContentType contentType, IWebReader webReader, IWebStreamResponse webStreamResponse, WebResponse webResponse, TaskCompletionSource <bool> configurationTaskCompletionSource, CancellationToken cancellationToken) { try { this._mediaStreamConfigurator.Initialize(); this._mediaStreamConfigurator.MediaManager = (IMediaManager)this; IMediaParser mediaParser = await this._mediaParserFactory.CreateAsync((IMediaParserParameters) new MediaParserParameters(), contentType, cancellationToken).ConfigureAwait(false); if (null == mediaParser) { throw new NotSupportedException("Unsupported content type: " + (object)contentType); } this.State = MediaManagerState.Opening; EventHandler configurationComplete = (EventHandler)null; configurationComplete = (EventHandler)((sender, args) => { mediaParser.ConfigurationComplete -= configurationComplete; configurationTaskCompletionSource.TrySetResult(true); }); mediaParser.ConfigurationComplete += configurationComplete; using (IBufferingManager bufferingManager = this._bufferingManagerFactory()) { SingleStreamMediaManager.QueueThrottle throttle = new SingleStreamMediaManager.QueueThrottle(); bufferingManager.Initialize((IQueueThrottling)throttle, new Action(this._mediaStreamConfigurator.CheckForSamples)); mediaParser.Initialize(bufferingManager, (Action <IProgramStreams>)null); IStreamMetadata streamMetadata = this._webMetadataFactory.CreateStreamMetadata(webResponse, (ContentType)null); mediaParser.InitializeStream(streamMetadata); Task reader = (Task)null; try { using (webReader) { try { if (null == webStreamResponse) { webStreamResponse = await webReader.GetWebStreamAsync((Uri)null, false, cancellationToken, (Uri)null, new long?(), new long?(), webResponse).ConfigureAwait(false); } reader = this.ReadResponseAsync(mediaParser, webStreamResponse, webResponse, throttle, cancellationToken); Task task = await TaskEx.WhenAny((Task)configurationTaskCompletionSource.Task, CancellationTokenExtensions.AsTask(cancellationToken)).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); await MediaStreamSourceExtensions.PlayAsync(this._mediaStreamConfigurator, (IEnumerable <IMediaParserMediaStream>) mediaParser.MediaStreams, new TimeSpan?(), cancellationToken).ConfigureAwait(false); this.State = MediaManagerState.Playing; await reader.ConfigureAwait(false); reader = (Task)null; } finally { if (null != webStreamResponse) { webStreamResponse.Dispose(); } } } } catch (OperationCanceledException ex) { } catch (Exception ex) { string message = ExceptionExtensions.ExtendedMessage(ex); Debug.WriteLine("SingleStreamMediaManager.SimplePlayAsync() failed: " + message); this.SetMediaState(MediaManagerState.Error, message); } this.State = MediaManagerState.Closing; if (null != reader) { try { await reader.ConfigureAwait(false); } catch (OperationCanceledException ex) { } catch (Exception ex) { Debug.WriteLine("SingleStreamMediaManager.SimplePlayAsync() reader failed: " + ExceptionExtensions.ExtendedMessage(ex)); } } mediaParser.ConfigurationComplete -= configurationComplete; mediaParser.EnableProcessing = false; mediaParser.FlushBuffers(); bufferingManager.Flush(); bufferingManager.Shutdown((IQueueThrottling)throttle); await this._mediaStreamConfigurator.CloseAsync().ConfigureAwait(false); } } catch (Exception ex) { Debug.WriteLine("SingleStreamMediaManager.SimplePlayAsync() cleanup failed: " + ExceptionExtensions.ExtendedMessage(ex)); } this._mediaStreamConfigurator.MediaManager = (IMediaManager)null; if (!configurationTaskCompletionSource.Task.IsCompleted) { configurationTaskCompletionSource.TrySetCanceled(); } this.State = MediaManagerState.Closed; await this._reportStateTask.WaitAsync().ConfigureAwait(false); }
private async Task ReadResponseAsync(IMediaParser mediaParser, IWebStreamResponse webStreamResponse, WebResponse webResponse, SingleStreamMediaManager.QueueThrottle throttle, CancellationToken cancellationToken) { byte[] buffer = new byte[16384]; Task cancellationTask = CancellationTokenExtensions.AsTask(cancellationToken); try { ISegmentMetadata segmentMetadata = this._webMetadataFactory.CreateSegmentMetadata(webResponse, (ContentType)null); mediaParser.StartSegment(segmentMetadata); using (Stream stream = await webStreamResponse.GetStreamAsync(cancellationToken).ConfigureAwait(false)) { while (true) { Task waitTask = throttle.WaitAsync(); if (!waitTask.IsCompleted) { Task task = await TaskEx.WhenAny(waitTask, cancellationTask).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); } int length = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false); if (length > 0) { mediaParser.ProcessData(buffer, 0, length); } else { break; } } } } finally { mediaParser.ProcessEndOfData(); } }
public async Task <IMediaStreamConfigurator> OpenMediaAsync(ICollection <Uri> source, CancellationToken cancellationToken) { this.State = MediaManagerState.OpenMedia; WebResponse response = new WebResponse(); IMediaStreamConfigurator streamConfigurator; using (IWebReader rootReader = WebReaderManagerExtensions.CreateRootReader(this._webReaderManager, (ContentType)null)) { using (IEnumerator <Uri> enumerator = source.GetEnumerator()) { label_25: if (enumerator.MoveNext()) { Uri url = enumerator.Current; IWebReader webReader = (IWebReader)null; IWebStreamResponse webStream = (IWebStreamResponse)null; CancellationTokenSource playCancellationTokenSource = (CancellationTokenSource)null; Task playTask = (Task)null; try { webReader = WebReaderExtensions.CreateChild(rootReader, url, ContentKind.Unknown, this.ContentType); webStream = await webReader.GetWebStreamAsync((Uri)null, false, cancellationToken, (Uri)null, new long?(), new long?(), response).ConfigureAwait(false); if (webStream.IsSuccessStatusCode) { ContentType contentType = response.ContentType; if (!((ContentType)null == contentType)) { if ((ContentType)null == contentType || ContentKind.Playlist == contentType.Kind) { throw new FileNotFoundException("Content not supported with this media manager"); } TaskCompletionSource <bool> configurationTaskCompletionSource = new TaskCompletionSource <bool>(); playCancellationTokenSource = new CancellationTokenSource(); CancellationTokenSource localPlayCancellationTokenSource = playCancellationTokenSource; Task cancelPlayTask = configurationTaskCompletionSource.Task.ContinueWith((Action <Task <bool> >)(t => { if (!t.IsFaulted && !t.IsCanceled) { return; } localPlayCancellationTokenSource.Cancel(); })); TaskCollector.Default.Add(cancelPlayTask, "SingleStreamMediaManager play cancellation"); IWebReader localWebReader = webReader; IWebStreamResponse localWebStream = webStream; CancellationToken playCancellationToken = playCancellationTokenSource.Token; playTask = TaskEx.Run((Func <Task>)(() => this.SimplePlayAsync(contentType, localWebReader, localWebStream, response, configurationTaskCompletionSource, playCancellationToken)), playCancellationToken); bool lockTaken = false; object obj = null; try { Monitor.Enter(obj = this._lock, ref lockTaken); this._playCancellationTokenSource = playCancellationTokenSource; playCancellationTokenSource = (CancellationTokenSource)null; this._playTask = playTask; playTask = (Task)null; } finally { if (lockTaken) { Monitor.Exit(obj); } } bool isConfigured = await configurationTaskCompletionSource.Task.ConfigureAwait(false); if (isConfigured) { webReader = (IWebReader)null; webStream = (IWebStreamResponse)null; streamConfigurator = this._mediaStreamConfigurator; goto label_33; } else { goto label_25; } } else { goto label_25; } } else { goto label_25; } } 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(); label_33: return(streamConfigurator); }