/// <summary> /// Create new demux from a stream /// </summary> /// <param name="stream"></param> private void UpdateDemux(EncryptedStream stream) { TSDemux newDemux; if (_demux != null && _demux.IsMediaInfoReady ) { newDemux = new TSDemux(stream, _demux, _playback.Metadata, _playback.CurrentDownloadBitrate, _bwHistory); } else { newDemux = new TSDemux(stream, _audioBuffer, _videoBuffer, _playback.Metadata, _playback.CurrentDownloadBitrate, _bwHistory); } if (_demux != null) { if (!_demux.IsMediaInfoReady) { // If last demux has no media info ready, we are not carrying over demux parser buffers has been allocated, // so make sure we discard those buffers by Flush(true) _demux.Flush(true); HLSTrace.WriteLine("Discard samples as last demux has no media info ready"); } _demux.Dispose(); } _demux = newDemux; while (!_demux.IsMediaInfoReady && !_demux.IsEndOfStream) { _demux.ReadChunk(); } if (!_demux.IsMediaInfoReady) RaiseError("unable to parse stream"); }
/// <summary> /// Handler for Close command /// </summary> private void DoCloseMedia() { lock (_workQueueThreadLock) { HLSTrace.WriteLine("DoCloseMedia"); _bwHistory.Close(); _playback.AbortStreamDownloads(); _isWorkQueueThreadStarted = false; _workQueueThread = null; _workQueue = null; _audioBuffer = null; _videoBuffer = null; _playlist = null; _playback = null; _program = null; if (_demux != null) { _demux.Dispose(); _demux = null; } } }
/// <summary> /// Handler for Seek command /// </summary> /// <param name="seekToTime"></param> private void DoSeek(long seekToTime) { HLSTrace.WriteLine("HLS MSS DoSeek, seek time {0} Hns", seekToTime); if (_noSeekYet && _noSampleRequestYet && 0 == seekToTime) { // There is no need to cancel download and start download again for the very first seek _noSeekYet = false; return; } _noSeekYet = false; // If a stream download is in progress using HttpWebRequest, then this call will flag // that request to discard its download stream. The playback impl will not // start any new stream download until ResumeDownloads is called. After this call, // no more data should be pushed into TSDemux or audio/video buffers. _playback.AbortStreamDownloads(); // Clear work queue as after _playback.AbortStreamDownloads() there shouldn't be any pending NextStream work queue items _workQueue.Clear(WorkQueueElement.Command.NextStream); _isBuffering = false; _audioBuffer.EndOfPlayback = false; _videoBuffer.EndOfPlayback = false; ReportPendingSamples(); // Flush and discard all data that are in the TSDemux or audio/video buffers _demux.Flush(false); _demux.Dispose(); _demux = null; _audioBuffer.Flush(); _videoBuffer.Flush(); PlayListOverrideInfo overrideInfo = new PlayListOverrideInfo(); overrideInfo.reason = PlayListOverrideReason.eSeek; overrideInfo.position = new TimeSpan(seekToTime); if (!OverridePlaylistIfNecessary(overrideInfo)) { // This will find the .ts stream that should contain the seek point, and would // position the playback's stream index to point to that stream. _playback.FindSeekStream(seekToTime); } if (Playback.CurrentStream != null) { _audioBuffer.ResetTSRollverOffset(); } _lastSeekPlaylistPosition = _playback.CurrentPosition; _playback.ResumeDownloads(); // enter buffering mode right after seek _isBuffering = true; TSDemux currentTSDemux = _demux; if (_playback.BeginGetNextStream(new AsyncCallback(AsyncStreamCallback), _playback) == null) RaiseError("unable to open stream"); }
/// <summary> /// Special constructor for creating new demux for next stream in sequence /// </summary> /// <param name="stream"></param> /// <param name="previousDemux"></param> public TSDemux(EncryptedStream stream, TSDemux previousDemux, IContainerMetadata metadata, uint bitrate, BandwidthHistory BWHistory) { if (previousDemux == null) throw new ArgumentNullException("previousDemux"); CommonConstruct(stream, previousDemux._audioBuffer, previousDemux._videoBuffer, metadata, bitrate, BWHistory); if (!stream.Discontinuity) _streams = previousDemux._streams; _audioFormatParser = previousDemux._audioFormatParser; _videoFormatParser = previousDemux._videoFormatParser; _audioFormatParser.HLSStream = stream.HLSStream; _videoFormatParser.HLSStream = stream.HLSStream; }