From b6a757842aab8da4b7e338aa6440072ed0c75f92 Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Tue, 26 Feb 2019 18:09:08 +0400
Subject: [PATCH] Pause loading if loaded for 1 minute.

---
 .../streaming/media_streaming_player.cpp      | 37 +++++++++++++++----
 .../media/streaming/media_streaming_player.h  |  7 +++-
 2 files changed, 36 insertions(+), 8 deletions(-)

diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp b/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp
index 6722a8071..c281cf6c8 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp
@@ -18,7 +18,12 @@ namespace Streaming {
 namespace {
 
 constexpr auto kReceivedTillEnd = std::numeric_limits<crl::time>::max();
-constexpr auto kBufferFor = crl::time(3000);
+constexpr auto kBufferFor = 3 * crl::time(1000);
+constexpr auto kLoadInAdvanceFor = 64 * crl::time(1000);
+
+// If we played for 3 seconds and got stuck it looks like we're loading
+// slower than we're playing, so load full file in that case.
+constexpr auto kLoadFullIfStuckAfterPlayback = 3 * crl::time(1000);
 
 [[nodiscard]] crl::time TrackClampReceivedTill(
 		crl::time position,
@@ -127,6 +132,9 @@ void Player::trackReceivedTill(
 	} else {
 		state.receivedTill = position;
 	}
+	if (!_pauseReading && bothReceivedEnough(kLoadInAdvanceFor)) {
+		_pauseReading = true;
+	}
 }
 
 template <typename Track>
@@ -141,6 +149,10 @@ void Player::trackPlayedTill(
 		state.position = position;
 		_updates.fire({ PlaybackUpdate<Track>{ position } });
 	}
+	if (_pauseReading && !bothReceivedEnough(kLoadInAdvanceFor)) {
+		_pauseReading = false;
+		_file->wake();
+	}
 }
 
 template <typename Track>
@@ -284,7 +296,7 @@ bool Player::fileProcessPacket(Packet &&packet) {
 
 bool Player::fileReadMore() {
 	// return true if looping.
-	return !_readTillEnd;
+	return !_readTillEnd && !_pauseReading;
 }
 
 void Player::streamReady(Information &&information) {
@@ -380,6 +392,10 @@ void Player::updatePausedState() {
 	}
 	if (_paused) {
 		_pausedTime = crl::now();
+		//if (_pausedByWaitingForData
+		//	&& _pausedTime - _startedTime > kLoadFullIfStuckAfterPlayback) {
+		//	_loadFull = true;
+		//}
 		if (_audio) {
 			_audio->pause(_pausedTime);
 		}
@@ -397,15 +413,21 @@ void Player::updatePausedState() {
 	}
 }
 
-bool Player::trackReceivedEnough(const TrackState &state) const {
+bool Player::trackReceivedEnough(
+		const TrackState &state,
+		crl::time amount) const {
 	return FullTrackReceived(state)
-		|| (state.position + kBufferFor <= state.receivedTill);
+		|| (state.position + amount <= state.receivedTill);
+}
+
+bool Player::bothReceivedEnough(crl::time amount) const {
+	auto &info = _information;
+	return (!_audio || trackReceivedEnough(info.audio.state, amount))
+		&& (!_video || trackReceivedEnough(info.video.state, amount));
 }
 
 void Player::checkResumeFromWaitingForData() {
-	if (_pausedByWaitingForData
-		&& (!_audio || trackReceivedEnough(_information.audio.state))
-		&& (!_video || trackReceivedEnough(_information.video.state))) {
+	if (_pausedByWaitingForData && bothReceivedEnough(kBufferFor)) {
 		_pausedByWaitingForData = false;
 		updatePausedState();
 	}
@@ -478,6 +500,7 @@ void Player::stop() {
 	_renderFrameTimer.cancel();
 	_audioFinished = false;
 	_videoFinished = false;
+	_pauseReading = false;
 	_readTillEnd = false;
 	_information = Information();
 }
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_player.h b/Telegram/SourceFiles/media/streaming/media_streaming_player.h
index 0111a4fbe..bac478566 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_player.h
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_player.h
@@ -90,7 +90,10 @@ private:
 	void videoPlayedTill(crl::time position);
 
 	void updatePausedState();
-	[[nodiscard]] bool trackReceivedEnough(const TrackState &state) const;
+	[[nodiscard]] bool trackReceivedEnough(
+		const TrackState &state,
+		crl::time amount) const;
+	[[nodiscard]] bool bothReceivedEnough(crl::time amount) const;
 	void checkResumeFromWaitingForData();
 
 	template <typename Track>
@@ -125,6 +128,8 @@ private:
 	bool _readTillEnd = false;
 	bool _waitingForData = false;
 
+	std::atomic<bool> _pauseReading = false;
+
 	// Belongs to the main thread.
 	Information _information;
 	Stage _stage = Stage::Uninitialized;