internal DataReceivedEventArgs(byte[] data, long startTime, long endTime, IManifestStream stream, IManifestTrack track) { StartTime = startTime; EndTime = endTime; Data = data; Stream = stream; Track = track; }
internal AdaptiveAudioStream(IManifestStream manifestStream) { ManifestStream = manifestStream; Name = manifestStream.Language; Language = manifestStream.Language; if (string.IsNullOrEmpty(manifestStream.Name)) { if (!string.IsNullOrEmpty(manifestStream.Language)) { var name = new Windows.Globalization.Language(manifestStream.Language).DisplayName; if (!string.IsNullOrEmpty(name)) { name = manifestStream.Language; } Name = name; } } }
internal AdaptiveCaptionStream(IManifestStream manifestStream) { ManifestStream = manifestStream; Name = manifestStream.Name; Language = manifestStream.Language; if (string.IsNullOrEmpty(Name)) { if (!string.IsNullOrEmpty(Language)) { var name = new Windows.Globalization.Language(manifestStream.Language).DisplayName; if (!string.IsNullOrEmpty(name)) { name = manifestStream.Language; } Name = name; } } }
private async Task UpdateCaptionStreamAsync(IManifestStream captionStream, List <IManifestStream> selectedStreams) { // cancel any active polling operations if (fragmentCancellationTokenSource != null) { fragmentCancellationTokenSource.Cancel(); } // start downloading chunks using (var cts = CancellationTokenSource.CreateLinkedTokenSource(mainCancellationTokenSource.Token)) { fragmentCancellationTokenSource = cts; var token = cts.Token; try { // select the new streams await ActiveAdaptiveSource.Manifest.SelectStreamsAsync(selectedStreams); if (captionStream != null && IsIsmtEnabled) { token.ThrowIfCancellationRequested(); var captionTrack = captionStream.AvailableTracks.FirstOrDefault(); if (captionTrack != null) { await PollFragmentsAsync(captionStream, captionTrack, token); } } } catch (OperationCanceledException) { /* ignore */ } finally { // null the cts if it is the same one we started with. if (fragmentCancellationTokenSource == cts) { fragmentCancellationTokenSource = null; } } } }
internal DataErrorEventArgs(Exception error, IManifestStream stream, IManifestTrack track) { Error = error; Stream = stream; Track = track; }
private async Task PollFragmentsAsync(IManifestStream stream, IManifestTrack track, CancellationToken cancellationToken) { try { var iter = stream.FirstInCurrentChunkList; var finished = false; ChunkInfo?chunkInfo = await stream.GetChunkInfoAsync(iter); cancellationToken.ThrowIfCancellationRequested(); do { try { // add small artificial delay if chunk is more than 1 minute away so we don't hog bandwidth if (chunkInfo.Value.ChunkTime > Position.Add(TimeSpan.FromMinutes(1)).Ticks) { await Task.Delay(ChunkCachePollingIntervalMilliseconds, cancellationToken); } var chunkData = (await stream.GetChunkDataAsync(iter, track)).ToArray(); cancellationToken.ThrowIfCancellationRequested(); var currentChunkInfo = chunkInfo.Value; if (iter.MoveNext()) { chunkInfo = await stream.GetChunkInfoAsync(iter); cancellationToken.ThrowIfCancellationRequested(); } else { chunkInfo = null; finished = true; } OnDataReceived(new DataReceivedEventArgs(chunkData, currentChunkInfo.ChunkTime, chunkInfo.HasValue ? chunkInfo.Value.ChunkTime : ActiveAdaptiveSource.Manifest.Duration, stream, track)); if (finished && IsLive) // for live situations, we need to keep checking { do { await Task.Delay(ChunkLivePollingIntervalMilliseconds, cancellationToken); // wait 1 second before checking again finished = !IsLive; // recheck in case EndOfLive occurred } while (!finished && !iter.MoveNext()); if (!finished) { chunkInfo = await stream.GetChunkInfoAsync(iter); cancellationToken.ThrowIfCancellationRequested(); } } } catch (OperationCanceledException) { throw; } catch (Exception ex) { OnDataError(new DataErrorEventArgs(ex, stream, track)); finished = true; } } while (!finished); } catch (OperationCanceledException) { throw; } catch (Exception ex) { OnDataError(new DataErrorEventArgs(ex, stream, track)); } }
static bool IsCaptionStream(IManifestStream stream) { return(stream.Type == MediaStreamType.Text && (stream.SubType == "CAPT" || stream.SubType == "SUBT")); }
static bool IsAudioStream(IManifestStream stream) { return(stream.Type == MediaStreamType.Audio); }