summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Preston <johnprestonmail@gmail.com>2019-02-21 17:40:09 +0400
committerJohn Preston <johnprestonmail@gmail.com>2019-03-11 11:49:53 +0400
commit3b369fc98ea5d0d272f82239d2ccd8bc60b6ec8a (patch)
treebef4e50d48eb7f007a8036e0f1497f4cceed5bc3
parente5cd7e6d400430dd8f3a6cdc9ea416480836a154 (diff)
Buffer audio when waiting data in streaming.
-rw-r--r--Telegram/SourceFiles/config.h1
-rw-r--r--Telegram/SourceFiles/data/data_document.cpp3
-rw-r--r--Telegram/SourceFiles/media/audio/media_audio.cpp15
-rw-r--r--Telegram/SourceFiles/media/audio/media_audio.h1
-rw-r--r--Telegram/SourceFiles/media/audio/media_audio_capture.cpp7
-rw-r--r--Telegram/SourceFiles/media/audio/media_audio_loader.h9
-rw-r--r--Telegram/SourceFiles/media/audio/media_audio_loaders.cpp98
-rw-r--r--Telegram/SourceFiles/media/audio/media_audio_loaders.h6
-rw-r--r--Telegram/SourceFiles/media/audio/media_child_ffmpeg_loader.cpp17
-rw-r--r--Telegram/SourceFiles/media/audio/media_child_ffmpeg_loader.h6
-rw-r--r--Telegram/SourceFiles/media/streaming/media_streaming_audio_track.cpp10
-rw-r--r--Telegram/SourceFiles/media/streaming/media_streaming_audio_track.h2
-rw-r--r--Telegram/SourceFiles/media/streaming/media_streaming_common.h1
-rw-r--r--Telegram/SourceFiles/media/streaming/media_streaming_file.cpp1
-rw-r--r--Telegram/SourceFiles/media/streaming/media_streaming_file_delegate.h1
-rw-r--r--Telegram/SourceFiles/media/streaming/media_streaming_loader_mtproto.cpp2
-rw-r--r--Telegram/SourceFiles/media/streaming/media_streaming_player.cpp43
-rw-r--r--Telegram/SourceFiles/media/streaming/media_streaming_player.h8
-rw-r--r--Telegram/SourceFiles/media/streaming/media_streaming_video_track.cpp5
-rw-r--r--Telegram/SourceFiles/media/streaming/media_streaming_video_track.h1
20 files changed, 188 insertions, 49 deletions
diff --git a/Telegram/SourceFiles/config.h b/Telegram/SourceFiles/config.h
index 498040e025..4ec78f7e86 100644
--- a/Telegram/SourceFiles/config.h
+++ b/Telegram/SourceFiles/config.h
@@ -48,7 +48,6 @@ enum {
AudioVoiceMsgMaxLength = 100 * 60, // 100 minutes
AudioVoiceMsgUpdateView = 100, // 100ms
AudioVoiceMsgChannels = 2, // stereo
- AudioVoiceMsgBufferSize = 256 * 1024, // 256 Kb buffers (1.3 - 3.0 secs)
StickerMaxSize = 2048, // 2048x2048 is a max image size for sticker
diff --git a/Telegram/SourceFiles/data/data_document.cpp b/Telegram/SourceFiles/data/data_document.cpp
index ed44df027c..941ee4ce69 100644
--- a/Telegram/SourceFiles/data/data_document.cpp
+++ b/Telegram/SourceFiles/data/data_document.cpp
@@ -326,7 +326,8 @@ void StartStreaming(
auto options = Media::Streaming::PlaybackOptions();
options.speed = 1.;
- options.position = (document->duration() / 2) * crl::time(1000);
+ //options.syncVideoByAudio = false;
+ //options.position = (document->duration() / 2) * crl::time(1000);
player->init(options);
player->updates(
) | rpl::start_with_next_error_done([=](Update &&update) {
diff --git a/Telegram/SourceFiles/media/audio/media_audio.cpp b/Telegram/SourceFiles/media/audio/media_audio.cpp
index e232ee34a7..bee9fef7f8 100644
--- a/Telegram/SourceFiles/media/audio/media_audio.cpp
+++ b/Telegram/SourceFiles/media/audio/media_audio.cpp
@@ -28,13 +28,14 @@ Q_DECLARE_METATYPE(VoiceWaveform);
namespace {
-QMutex AudioMutex;
-ALCdevice *AudioDevice = nullptr;
-ALCcontext *AudioContext = nullptr;
-
constexpr auto kSuppressRatioAll = 0.2;
constexpr auto kSuppressRatioSong = 0.05;
constexpr auto kPlaybackSpeedMultiplier = 1.7;
+constexpr auto kWaveformCounterBufferSize = 256 * 1024;
+
+QMutex AudioMutex;
+ALCdevice *AudioDevice = nullptr;
+ALCcontext *AudioContext = nullptr;
auto VolumeMultiplierAll = 1.;
auto VolumeMultiplierSong = 1.;
@@ -823,6 +824,10 @@ void Mixer::feedFromVideo(const VideoSoundPart &part) {
_loader->feedFromVideo(part);
}
+void Mixer::forceToBufferVideo(const AudioMsgId &audioId) {
+ _loader->forceToBufferVideo(audioId);
+}
+
Mixer::TimeCorrection Mixer::getVideoTimeCorrection(
const AudioMsgId &audio) const {
Expects(audio.type() == AudioMsgId::Type::Video);
@@ -1683,7 +1688,7 @@ public:
}
QByteArray buffer;
- buffer.reserve(AudioVoiceMsgBufferSize);
+ buffer.reserve(kWaveformCounterBufferSize);
int64 countbytes = sampleSize() * samplesCount();
int64 processed = 0;
int64 sumbytes = 0;
diff --git a/Telegram/SourceFiles/media/audio/media_audio.h b/Telegram/SourceFiles/media/audio/media_audio.h
index 8c64090a27..c3602a16ec 100644
--- a/Telegram/SourceFiles/media/audio/media_audio.h
+++ b/Telegram/SourceFiles/media/audio/media_audio.h
@@ -122,6 +122,7 @@ public:
// Video player audio stream interface.
void feedFromVideo(const VideoSoundPart &part);
+ void forceToBufferVideo(const AudioMsgId &audioId);
struct TimeCorrection {
crl::time audioPositionValue = kTimeUnknown;
crl::time audioPositionTime = kTimeUnknown;
diff --git a/Telegram/SourceFiles/media/audio/media_audio_capture.cpp b/Telegram/SourceFiles/media/audio/media_audio_capture.cpp
index 016da578d3..844f589a82 100644
--- a/Telegram/SourceFiles/media/audio/media_audio_capture.cpp
+++ b/Telegram/SourceFiles/media/audio/media_audio_capture.cpp
@@ -22,6 +22,7 @@ namespace {
constexpr auto kCaptureFrequency = Player::kDefaultFrequency;
constexpr auto kCaptureSkipDuration = crl::time(400);
constexpr auto kCaptureFadeInDuration = crl::time(300);
+constexpr auto kCaptureBufferSlice = 256 * 1024;
Instance *CaptureInstance = nullptr;
@@ -323,7 +324,7 @@ void Instance::Inner::onStart() {
_timer.start(50);
_captured.clear();
- _captured.reserve(AudioVoiceMsgBufferSize);
+ _captured.reserve(kCaptureBufferSlice);
DEBUG_LOG(("Audio Capture: started!"));
}
@@ -489,8 +490,8 @@ void Instance::Inner::onTimeout() {
// Get samples from OpenAL
auto s = _captured.size();
auto news = s + static_cast<int>(samples * sizeof(short));
- if (news / AudioVoiceMsgBufferSize > s / AudioVoiceMsgBufferSize) {
- _captured.reserve(((news / AudioVoiceMsgBufferSize) + 1) * AudioVoiceMsgBufferSize);
+ if (news / kCaptureBufferSlice > s / kCaptureBufferSlice) {
+ _captured.reserve(((news / kCaptureBufferSlice) + 1) * kCaptureBufferSlice);
}
_captured.resize(news);
alcCaptureSamples(d->device, (ALCvoid *)(_captured.data() + s), samples);
diff --git a/Telegram/SourceFiles/media/audio/media_audio_loader.h b/Telegram/SourceFiles/media/audio/media_audio_loader.h
index 46f05b5d41..075382ccb3 100644
--- a/Telegram/SourceFiles/media/audio/media_audio_loader.h
+++ b/Telegram/SourceFiles/media/audio/media_audio_loader.h
@@ -36,9 +36,16 @@ public:
EndOfFile,
};
virtual ReadResult readMore(QByteArray &samples, int64 &samplesCount) = 0;
- virtual void enqueuePackets(QQueue<FFMpeg::AVPacketDataWrap> &packets) {
+ virtual void enqueuePackets(
+ QQueue<FFMpeg::AVPacketDataWrap> &&packets) {
Unexpected("enqueuePackets() call on not ChildFFMpegLoader.");
}
+ virtual void setForceToBuffer(bool force) {
+ Unexpected("setForceToBuffer() call on not ChildFFMpegLoader.");
+ }
+ virtual bool forceToBuffer() const {
+ return false;
+ }
void saveDecodedSamples(QByteArray *samples, int64 *samplesCount);
void takeSavedDecodedSamples(QByteArray *samples, int64 *samplesCount);
diff --git a/Telegram/SourceFiles/media/audio/media_audio_loaders.cpp b/Telegram/SourceFiles/media/audio/media_audio_loaders.cpp
index 922da09d54..15964a2fc3 100644
--- a/Telegram/SourceFiles/media/audio/media_audio_loaders.cpp
+++ b/Telegram/SourceFiles/media/audio/media_audio_loaders.cpp
@@ -13,8 +13,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Media {
namespace Player {
+namespace {
-Loaders::Loaders(QThread *thread) : _fromVideoNotify([this] { videoSoundAdded(); }) {
+constexpr auto kPlaybackBufferSize = 256 * 1024;
+
+} // namespace
+
+Loaders::Loaders(QThread *thread)
+: _fromVideoNotify([=] { videoSoundAdded(); }) {
moveToThread(thread);
_fromVideoNotify.moveToThread(thread);
connect(thread, SIGNAL(started()), this, SLOT(onInit()));
@@ -25,8 +31,22 @@ void Loaders::feedFromVideo(const VideoSoundPart &part) {
auto invoke = false;
{
QMutexLocker lock(&_fromVideoMutex);
+ invoke = _fromVideoQueues.empty()
+ && _fromVideoForceToBuffer.empty();
_fromVideoQueues[part.audio].enqueue(FFMpeg::dataWrapFromPacket(*part.packet));
- invoke = true;
+ }
+ if (invoke) {
+ _fromVideoNotify.call();
+ }
+}
+
+void Loaders::forceToBufferVideo(const AudioMsgId &audioId) {
+ auto invoke = false;
+ {
+ QMutexLocker lock(&_fromVideoMutex);
+ invoke = _fromVideoQueues.empty()
+ && _fromVideoForceToBuffer.empty();
+ _fromVideoForceToBuffer.emplace(audioId);
}
if (invoke) {
_fromVideoNotify.call();
@@ -34,36 +54,53 @@ void Loaders::feedFromVideo(const VideoSoundPart &part) {
}
void Loaders::videoSoundAdded() {
- auto waitingAndAdded = false;
auto queues = decltype(_fromVideoQueues)();
+ auto forces = decltype(_fromVideoForceToBuffer)();
{
QMutexLocker lock(&_fromVideoMutex);
queues = base::take(_fromVideoQueues);
+ forces = base::take(_fromVideoForceToBuffer);
}
- auto tryLoader = [this](auto &audio, auto &loader, auto &it) {
- if (audio == it.key() && loader) {
- loader->enqueuePackets(it.value());
- if (loader->holdsSavedDecodedSamples()) {
- onLoad(audio);
+ for (const auto &audioId : forces) {
+ const auto tryLoader = [&](const auto &id, auto &loader) {
+ if (audioId == id && loader) {
+ loader->setForceToBuffer(true);
+ if (loader->holdsSavedDecodedSamples()
+ && !queues.contains(audioId)) {
+ loadData(audioId);
+ }
+ return true;
}
- return true;
- }
- return false;
- };
- for (auto i = queues.begin(), e = queues.end(); i != e; ++i) {
- if (!tryLoader(_audio, _audioLoader, i)
- && !tryLoader(_song, _songLoader, i)
- && !tryLoader(_video, _videoLoader, i)) {
- for (auto &packetData : i.value()) {
+ return false;
+ };
+ tryLoader(_audio, _audioLoader)
+ || tryLoader(_song, _songLoader)
+ || tryLoader(_video, _videoLoader);
+ }
+ for (auto &pair : queues) {
+ const auto audioId = pair.first;
+ auto &packets = pair.second;
+ const auto tryLoader = [&](const auto &id, auto &loader) {
+ if (id == audioId && loader) {
+ loader->enqueuePackets(std::move(packets));
+ if (loader->holdsSavedDecodedSamples()) {
+ loadData(audioId);
+ }
+ return true;
+ }
+ return false;
+ };
+ const auto used = tryLoader(_audio, _audioLoader)
+ || tryLoader(_song, _songLoader)
+ || tryLoader(_video, _videoLoader);
+ if (!used) {
+ for (auto &packetData : packets) {
AVPacket packet;
FFMpeg::packetFromDataWrap(packet, packetData);
FFMpeg::freePacket(&packet);
}
}
}
- if (waitingAndAdded) {
- onLoad(_video);
- }
}
Loaders::~Loaders() {
@@ -73,8 +110,10 @@ Loaders::~Loaders() {
void Loaders::clearFromVideoQueue() {
auto queues = base::take(_fromVideoQueues);
- for (auto &queue : queues) {
- for (auto &packetData : queue) {
+ for (auto &pair : queues) {
+ const auto audioId = pair.first;
+ auto &packets = pair.second;
+ for (auto &packetData : packets) {
AVPacket packet;
FFMpeg::packetFromDataWrap(packet, packetData);
FFMpeg::freePacket(&packet);
@@ -120,7 +159,7 @@ void Loaders::emitError(AudioMsgId::Type type) {
}
void Loaders::onLoad(const AudioMsgId &audio) {
- loadData(audio, crl::time(0));
+ loadData(audio);
}
void Loaders::loadData(AudioMsgId audio, crl::time positionMs) {
@@ -144,7 +183,7 @@ void Loaders::loadData(AudioMsgId audio, crl::time positionMs) {
if (l->holdsSavedDecodedSamples()) {
l->takeSavedDecodedSamples(&samples, &samplesCount);
}
- while (samples.size() < AudioVoiceMsgBufferSize) {
+ while (samples.size() < kPlaybackBufferSize) {
auto res = l->readMore(samples, samplesCount);
using Result = AudioPlayerLoader::ReadResult;
if (res == Result::Error) {
@@ -166,7 +205,8 @@ void Loaders::loadData(AudioMsgId audio, crl::time positionMs) {
} else if (res == Result::Ok) {
errAtStart = false;
} else if (res == Result::Wait) {
- waiting = (samples.size() < AudioVoiceMsgBufferSize);
+ waiting = (samples.size() < kPlaybackBufferSize)
+ && !l->forceToBuffer();
if (waiting) {
l->saveDecodedSamples(&samples, &samplesCount);
}
@@ -219,8 +259,16 @@ void Loaders::loadData(AudioMsgId audio, crl::time positionMs) {
if (bufferIndex < 0) { // No free buffers, wait.
l->saveDecodedSamples(&samples, &samplesCount);
return;
+ } else if (l->forceToBuffer()) {
+ l->setForceToBuffer(false);
}
+ //LOG(("[%4] PUSHING %1 SAMPLES (%2 BYTES) %3ms"
+ // ).arg(samplesCount
+ // ).arg(samples.size()
+ // ).arg((samplesCount * 1000LL) / track->frequency
+ // ).arg(crl::now() % 10000, 4, 10, QChar('0')));
+
track->bufferSamples[bufferIndex] = samples;
track->samplesCount[bufferIndex] = samplesCount;
track->bufferedLength += samplesCount;
diff --git a/Telegram/SourceFiles/media/audio/media_audio_loaders.h b/Telegram/SourceFiles/media/audio/media_audio_loaders.h
index e4aeff7f72..0fe96429e2 100644
--- a/Telegram/SourceFiles/media/audio/media_audio_loaders.h
+++ b/Telegram/SourceFiles/media/audio/media_audio_loaders.h
@@ -22,6 +22,7 @@ class Loaders : public QObject {
public:
Loaders(QThread *thread);
void feedFromVideo(const VideoSoundPart &part);
+ void forceToBufferVideo(const AudioMsgId &audioId);
~Loaders();
signals:
@@ -45,7 +46,8 @@ private:
std::unique_ptr<AudioPlayerLoader> _videoLoader;
QMutex _fromVideoMutex;
- QMap<AudioMsgId, QQueue<FFMpeg::AVPacketDataWrap>> _fromVideoQueues;
+ base::flat_map<AudioMsgId, QQueue<FFMpeg::AVPacketDataWrap>> _fromVideoQueues;
+ base::flat_set<AudioMsgId> _fromVideoForceToBuffer;
SingleQueuedInvokation _fromVideoNotify;
void emitError(AudioMsgId::Type type);
@@ -58,7 +60,7 @@ private:
SetupErrorLoadedFull = 2,
SetupNoErrorStarted = 3,
};
- void loadData(AudioMsgId audio, crl::time positionMs);
+ void loadData(AudioMsgId audio, crl::time positionMs = 0);
AudioPlayerLoader *setupLoader(
const AudioMsgId &audio,
SetupError &err,
diff --git a/Telegram/SourceFiles/media/audio/media_child_ffmpeg_loader.cpp b/Telegram/SourceFiles/media/audio/media_child_ffmpeg_loader.cpp
index 0284fd7118..282085e642 100644
--- a/Telegram/SourceFiles/media/audio/media_child_ffmpeg_loader.cpp
+++ b/Telegram/SourceFiles/media/audio/media_child_ffmpeg_loader.cpp
@@ -111,11 +111,24 @@ AudioPlayerLoader::ReadResult ChildFFMpegLoader::readMore(
return ReadResult::Ok;
}
-void ChildFFMpegLoader::enqueuePackets(QQueue<FFMpeg::AVPacketDataWrap> &packets) {
- _queue += std::move(packets);
+void ChildFFMpegLoader::enqueuePackets(
+ QQueue<FFMpeg::AVPacketDataWrap> &&packets) {
+ if (_queue.empty()) {
+ _queue = std::move(packets);
+ } else {
+ _queue += std::move(packets);
+ }
packets.clear();
}
+void ChildFFMpegLoader::setForceToBuffer(bool force) {
+ _forceToBuffer = force;
+}
+
+bool ChildFFMpegLoader::forceToBuffer() const {
+ return _forceToBuffer;
+}
+
ChildFFMpegLoader::~ChildFFMpegLoader() {
for (auto &packetData : base::take(_queue)) {
AVPacket packet;
diff --git a/Telegram/SourceFiles/media/audio/media_child_ffmpeg_loader.h b/Telegram/SourceFiles/media/audio/media_child_ffmpeg_loader.h
index c3003ca7d0..16a9965dd0 100644
--- a/Telegram/SourceFiles/media/audio/media_child_ffmpeg_loader.h
+++ b/Telegram/SourceFiles/media/audio/media_child_ffmpeg_loader.h
@@ -70,7 +70,10 @@ public:
}
ReadResult readMore(QByteArray &result, int64 &samplesAdded) override;
- void enqueuePackets(QQueue<FFMpeg::AVPacketDataWrap> &packets) override;
+ void enqueuePackets(
+ QQueue<FFMpeg::AVPacketDataWrap> &&packets) override;
+ void setForceToBuffer(bool force) override;
+ bool forceToBuffer() const override;
bool eofReached() const {
return _eofReached;
@@ -88,6 +91,7 @@ private:
std::unique_ptr<VideoSoundData> _parentData;
QQueue<FFMpeg::AVPacketDataWrap> _queue;
+ bool _forceToBuffer = false;
bool _eofReached = false;
};
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_audio_track.cpp b/Telegram/SourceFiles/media/streaming/media_streaming_audio_track.cpp
index 6d2d9cc129..95981ba88f 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_audio_track.cpp
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_audio_track.cpp
@@ -50,6 +50,12 @@ void AudioTrack::process(Packet &&packet) {
}
}
+void AudioTrack::waitForData() {
+ if (initialized()) {
+ mixerForceToBuffer();
+ }
+}
+
bool AudioTrack::initialized() const {
return !_ready;
}
@@ -115,6 +121,10 @@ void AudioTrack::mixerEnqueue(Packet &&packet) {
packet.release();
}
+void AudioTrack::mixerForceToBuffer() {
+ Media::Player::mixer()->forceToBufferVideo(_audioId);
+}
+
void AudioTrack::start(crl::time startTime) {
Expects(initialized());
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_audio_track.h b/Telegram/SourceFiles/media/streaming/media_streaming_audio_track.h
index 8bcbb0eee4..784a2f8a58 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_audio_track.h
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_audio_track.h
@@ -39,6 +39,7 @@ public:
// Called from the same unspecified thread.
void process(Packet &&packet);
+ void waitForData();
// Called from the main thread.
~AudioTrack();
@@ -50,6 +51,7 @@ private:
[[nodiscard]] bool fillStateFromFrame();
void mixerInit();
void mixerEnqueue(Packet &&packet);
+ void mixerForceToBuffer();
void callReady();
const PlaybackOptions _options;
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_common.h b/Telegram/SourceFiles/media/streaming/media_streaming_common.h
index e04ff61d5a..7890805692 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_common.h
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_common.h
@@ -27,6 +27,7 @@ struct PlaybackOptions {
Mode mode = Mode::Both;
crl::time position = 0;
float64 speed = 1.; // Valid values between 0.5 and 2.
+ bool syncVideoByAudio = true;
};
struct TrackState {
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_file.cpp b/Telegram/SourceFiles/media/streaming/media_streaming_file.cpp
index 94ddcfd94e..bc71b873a9 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_file.cpp
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_file.cpp
@@ -41,6 +41,7 @@ int File::Context::read(bytes::span buffer) {
}
buffer = buffer.subspan(0, amount);
while (!_reader->fill(buffer, _offset, &_semaphore)) {
+ _delegate->fileWaitingForData();
_semaphore.acquire();
if (_interrupted) {
return -1;
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_file_delegate.h b/Telegram/SourceFiles/media/streaming/media_streaming_file_delegate.h
index a3072a5762..8cab745682 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_file_delegate.h
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_file_delegate.h
@@ -17,6 +17,7 @@ class FileDelegate {
public:
virtual void fileReady(Stream &&video, Stream &&audio) = 0;
virtual void fileError() = 0;
+ virtual void fileWaitingForData() = 0;
// Return true if reading and processing more packets is desired.
// Return false if sleeping until 'wake()' is called is desired.
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_loader_mtproto.cpp b/Telegram/SourceFiles/media/streaming/media_streaming_loader_mtproto.cpp
index cb941510a0..8e3445b064 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_loader_mtproto.cpp
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_loader_mtproto.cpp
@@ -13,7 +13,7 @@ namespace Media {
namespace Streaming {
namespace {
-constexpr auto kMaxConcurrentRequests = 1; // #TODO streaming
+constexpr auto kMaxConcurrentRequests = 2; // #TODO streaming
} // namespace
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp b/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp
index d8607e88d1..6365f3b961 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp
@@ -158,7 +158,6 @@ void Player::trackPlayedTill(
void Player::audioReceivedTill(crl::time position) {
Expects(_audio != nullptr);
- //LOG(("AUDIO TILL: %1").arg(position));
trackReceivedTill(*_audio, _information.audio.state, position);
}
@@ -171,7 +170,6 @@ void Player::audioPlayedTill(crl::time position) {
void Player::videoReceivedTill(crl::time position) {
Expects(_video != nullptr);
- //LOG(("VIDEO TILL: %1").arg(position));
trackReceivedTill(*_video, _information.video.state, position);
}
@@ -182,6 +180,8 @@ void Player::videoPlayedTill(crl::time position) {
}
void Player::fileReady(Stream &&video, Stream &&audio) {
+ _waitingForData = false;
+
const auto weak = base::make_weak(&_sessionGuard);
const auto ready = [=](const Information & data) {
crl::on_main(weak, [=, data = data]() mutable {
@@ -226,12 +226,32 @@ void Player::fileReady(Stream &&video, Stream &&audio) {
}
void Player::fileError() {
+ _waitingForData = false;
+
crl::on_main(&_sessionGuard, [=] {
fail();
});
}
+void Player::fileWaitingForData() {
+ if (_waitingForData) {
+ return;
+ }
+ _waitingForData = true;
+ crl::on_main(&_sessionGuard, [=] {
+ _updates.fire({ WaitingForData() });
+ });
+ if (_audio) {
+ _audio->waitForData();
+ }
+ if (_video) {
+ _video->waitForData();
+ }
+}
+
bool Player::fileProcessPacket(Packet &&packet) {
+ _waitingForData = false;
+
const auto &native = packet.fields();
const auto index = native.stream_index;
if (packet.empty()) {
@@ -250,12 +270,20 @@ bool Player::fileProcessPacket(Packet &&packet) {
}
} else if (_audio && _audio->streamIndex() == native.stream_index) {
const auto time = PacketPosition(packet, _audio->streamTimeBase());
+ //LOG(("[%2] AUDIO PACKET FOR %1ms"
+ // ).arg(time
+ // ).arg(crl::now() % 10000, 4, 10, QChar('0')));
+
crl::on_main(&_sessionGuard, [=] {
audioReceivedTill(time);
});
_audio->process(std::move(packet));
} else if (_video && _video->streamIndex() == native.stream_index) {
const auto time = PacketPosition(packet, _video->streamTimeBase());
+ //LOG(("[%2] VIDEO PACKET FOR %1ms"
+ // ).arg(time
+ // ).arg(crl::now() % 10000, 4, 10, QChar('0')));
+
crl::on_main(&_sessionGuard, [=] {
videoReceivedTill(time);
});
@@ -368,7 +396,16 @@ rpl::lifetime &Player::lifetime() {
return _lifetime;
}
-Player::~Player() = default;
+Player::~Player() {
+ // The order of field destruction is important.
+ //
+ // We are forced to maintain the correct order in the stop() method,
+ // because it can be called even before the player destruction.
+ //
+ // So instead of maintaining it in the class definition as well we
+ // simply call stop() here, after that the destruction is trivial.
+ stop();
+}
} // namespace Streaming
} // namespace Media
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_player.h b/Telegram/SourceFiles/media/streaming/media_streaming_player.h
index a3ab28b722..e9b7489391 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_player.h
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_player.h
@@ -52,6 +52,9 @@ public:
~Player();
private:
+ static constexpr auto kReceivedTillEnd
+ = std::numeric_limits<crl::time>::max();
+
enum class Stage {
Uninitialized,
Initializing,
@@ -66,6 +69,7 @@ private:
// FileDelegate methods are called only from the File thread.
void fileReady(Stream &&video, Stream &&audio) override;
void fileError() override;
+ void fileWaitingForData() override;
bool fileProcessPacket(Packet &&packet) override;
bool fileReadMore() override;
@@ -95,9 +99,6 @@ private:
const std::unique_ptr<File> _file;
- static constexpr auto kReceivedTillEnd
- = std::numeric_limits<crl::time>::max();
-
// Immutable while File is active after it is ready.
AudioMsgId _audioId;
std::unique_ptr<AudioTrack> _audio;
@@ -109,6 +110,7 @@ private:
// Belongs to the File thread while File is active.
bool _readTillEnd = false;
+ bool _waitingForData = false;
// Belongs to the main thread.
Information _information;
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_video_track.cpp b/Telegram/SourceFiles/media/streaming/media_streaming_video_track.cpp
index 7736edd5a6..85baf550bb 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_video_track.cpp
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_video_track.cpp
@@ -277,7 +277,7 @@ VideoTrackObject::TrackTime VideoTrackObject::trackTime() const {
return result;
}
- const auto correction = _audioId.playId()
+ const auto correction = (_options.syncVideoByAudio && _audioId.playId())
? Media::Player::mixer()->getVideoTimeCorrection(_audioId)
: Media::Player::Mixer::TimeCorrection();
const auto knownValue = correction
@@ -478,6 +478,9 @@ void VideoTrack::process(Packet &&packet) {
});
}
+void VideoTrack::waitForData() {
+}
+
void VideoTrack::start(crl::time startTime) {
_wrapped.with([=](Implementation &unwrapped) {
unwrapped.start(startTime);
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_video_track.h b/Telegram/SourceFiles/media/streaming/media_streaming_video_track.h
index 01555de73b..1beba8b18c 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_video_track.h
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_video_track.h
@@ -33,6 +33,7 @@ public:
// Called from the same unspecified thread.
void process(Packet &&packet);
+ void waitForData();
// Called from the main thread.
void start(crl::time startTime);