private void OnAllSubPlayListLoaded() { // DoCloseMedia may happend before the AllSubPlayListEvent event fired. if (_playlist == null || _program == null) return; uint maxBitrate = 0; _playback.AllSubPlayListEvent -= OnAllSubPlayListLoaded; foreach (HLSVariant hlsVariant in _program.Variants) { hlsVariant.Playback = null; if (hlsVariant.Bitrate > maxBitrate) { maxBitrate = hlsVariant.Bitrate; } } // // Allocate video buffer based on max bitrate and buffer length plus 10 extra seconds of pending chunk progressive // downloading / parsing. // Minimal initial buffer size is 5MB (corresponding 1Mb bitrate) in case playlist returns unreasonable low bitrate. // Max initial buffer size is 50MB (corrsponding 10Mb bitrate) in case playlist returns unsupported high bitrate. // int initialVideoBufferSize = Math.Max((int)((_bufferLength.TotalSeconds + 10) * maxBitrate / 8), 5 * 1024 * 1024); initialVideoBufferSize = Math.Min(initialVideoBufferSize, 50 * 1024 * 1024); _videoBuffer = new SampleBuffer(initialVideoBufferSize); // Allocate audio buffer based on 256Kb audio bitrate and buffer length plus 10 extra seconds of pending chunk progressive // downloading / parsing. _audioBuffer = new SampleBuffer((int)((_bufferLength.TotalSeconds + 10) * 256 * 1024) / 8); PlayListOverrideInfo overrideInfo = new PlayListOverrideInfo(); overrideInfo.reason = PlayListOverrideReason.ePlaylistLoaded; overrideInfo.position = TimeSpan.Zero; OverridePlaylistIfNecessary(overrideInfo); if (_playback.Program == null) _playback.Program = _program; if (_playback.BeginGetNextStream(new AsyncCallback(AsyncStreamCallback), _playback) == null) { RaiseError("unable to open stream"); } }
private bool OverridePlaylistIfNecessary(PlayListOverrideInfo overrideInfo) { bool isOverrided = false; if (null != _playlistOverrideEvent) { HLSExternalPlayListImpl externalPlayLsit = new HLSExternalPlayListImpl(); if (overrideInfo.reason == PlayListOverrideReason.ePlaylistLoaded) { externalPlayLsit.FromHLSPlaylist(_playlist); } if (_playlistOverrideEvent(externalPlayLsit, overrideInfo)) { isOverrided = true; _playlist.FromHLSExternalPlaylist(externalPlayLsit); lock (_playback) { _program = _playlist.Programs[0]; _playback.Program = _program; _playback.ResetPlayback(_program, _playlist.PlaylistDuration); List<SampleBuffer.TimeLineInfo> timelineInfoList = new List<SampleBuffer.TimeLineInfo>(); foreach (TimelineEstablishInfo establishInfo in externalPlayLsit.timelineEstablishInfoList) { timelineInfoList.Add(new SampleBuffer.TimeLineInfo(establishInfo.timelineStartOffset.Ticks, establishInfo.isMonoIncrease)); } _videoBuffer.EstablishTimeline(timelineInfoList); _audioBuffer.EstablishTimeline(timelineInfoList); } } } if (!isOverrided && overrideInfo.reason == PlayListOverrideReason.ePlaylistLoaded) { List<SampleBuffer.TimeLineInfo> timelineInfoList = new List<SampleBuffer.TimeLineInfo>(); timelineInfoList.Add(new SampleBuffer.TimeLineInfo(0, false)); _videoBuffer.EstablishTimeline(timelineInfoList); _audioBuffer.EstablishTimeline(timelineInfoList); } _playlistOverrided = isOverrided; return isOverrided; }
/// <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"); }