summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Preston <johnprestonmail@gmail.com>2019-03-01 16:22:47 +0400
committerJohn Preston <johnprestonmail@gmail.com>2019-03-11 12:08:08 +0400
commitc574119718888ae12a1f9f31f9d9ae9d192688e0 (patch)
treef57dd80f18ab45deec9e3b53833a1522421624e3
parent648cd44ddd683a80b2ced4cf838f7c7344303655 (diff)
Implement file reference update in streaming.
-rw-r--r--Telegram/SourceFiles/data/data_types.h17
-rw-r--r--Telegram/SourceFiles/history/media/history_media_document.cpp9
-rw-r--r--Telegram/SourceFiles/media/audio/media_audio.cpp4
-rw-r--r--Telegram/SourceFiles/media/audio/media_audio_loaders.cpp2
-rw-r--r--Telegram/SourceFiles/media/player/media_player_instance.cpp21
-rw-r--r--Telegram/SourceFiles/media/streaming/media_streaming_loader_mtproto.cpp49
-rw-r--r--Telegram/SourceFiles/media/streaming/media_streaming_loader_mtproto.h12
-rw-r--r--Telegram/SourceFiles/media/streaming/media_streaming_player.cpp2
-rw-r--r--Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp95
-rw-r--r--Telegram/SourceFiles/media/view/media_view_overlay_widget.h3
10 files changed, 132 insertions, 82 deletions
diff --git a/Telegram/SourceFiles/data/data_types.h b/Telegram/SourceFiles/data/data_types.h
index 4f313c6406..4574299f78 100644
--- a/Telegram/SourceFiles/data/data_types.h
+++ b/Telegram/SourceFiles/data/data_types.h
@@ -361,8 +361,8 @@ public:
AudioMsgId() = default;
AudioMsgId(
- DocumentData *audio,
- const FullMsgId &msgId,
+ not_null<DocumentData*> audio,
+ FullMsgId msgId,
uint32 externalPlayId = 0)
: _audio(audio)
, _contextId(msgId)
@@ -373,21 +373,20 @@ public:
[[nodiscard]] static uint32 CreateExternalPlayId();
[[nodiscard]] static AudioMsgId ForVideo();
- Type type() const {
+ [[nodiscard]] Type type() const {
return _type;
}
- DocumentData *audio() const {
+ [[nodiscard]] DocumentData *audio() const {
return _audio;
}
- FullMsgId contextId() const {
+ [[nodiscard]] FullMsgId contextId() const {
return _contextId;
}
- uint32 externalPlayId() const {
+ [[nodiscard]] uint32 externalPlayId() const {
return _externalPlayId;
}
-
- explicit operator bool() const {
- return _audio != nullptr;
+ [[nodiscard]] explicit operator bool() const {
+ return (_audio != nullptr) || (_externalPlayId != 0);
}
private:
diff --git a/Telegram/SourceFiles/history/media/history_media_document.cpp b/Telegram/SourceFiles/history/media/history_media_document.cpp
index 9d1eec2555..4d95cf6733 100644
--- a/Telegram/SourceFiles/history/media/history_media_document.cpp
+++ b/Telegram/SourceFiles/history/media/history_media_document.cpp
@@ -711,11 +711,10 @@ void HistoryDocument::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool
const auto type = AudioMsgId::Type::Voice;
const auto state = Media::Player::instance()->getState(type);
if (state.id == AudioMsgId(_data, _parent->data()->fullId(), state.id.externalPlayId()) && state.length) {
- auto currentProgress = voice->seekingCurrent();
- auto currentPosition = state.frequency
- ? qRound(currentProgress * state.length * 1000. / state.frequency)
- : 0;
- Media::Player::mixer()->seek(type, currentPosition);
+ const auto currentProgress = voice->seekingCurrent();
+ Media::Player::instance()->finishSeeking(
+ AudioMsgId::Type::Voice,
+ currentProgress);
voice->ensurePlayback(this);
voice->_playback->_position = 0;
diff --git a/Telegram/SourceFiles/media/audio/media_audio.cpp b/Telegram/SourceFiles/media/audio/media_audio.cpp
index 319ce04f0d..d53aceee1c 100644
--- a/Telegram/SourceFiles/media/audio/media_audio.cpp
+++ b/Telegram/SourceFiles/media/audio/media_audio.cpp
@@ -1242,7 +1242,9 @@ void Mixer::setStoppedState(Track *current, State state) {
alSourceStop(current->stream.source);
alSourcef(current->stream.source, AL_GAIN, 1);
}
- emit loaderOnCancel(current->state.id);
+ if (current->state.id) {
+ emit loaderOnCancel(current->state.id);
+ }
}
void Mixer::clearStoppedAtStart(const AudioMsgId &audio) {
diff --git a/Telegram/SourceFiles/media/audio/media_audio_loaders.cpp b/Telegram/SourceFiles/media/audio/media_audio_loaders.cpp
index 7839ff87b7..c0de29ce49 100644
--- a/Telegram/SourceFiles/media/audio/media_audio_loaders.cpp
+++ b/Telegram/SourceFiles/media/audio/media_audio_loaders.cpp
@@ -413,6 +413,8 @@ Mixer::Track *Loaders::checkLoader(AudioMsgId::Type type) {
}
void Loaders::onCancel(const AudioMsgId &audio) {
+ Expects(audio.type() != AudioMsgId::Type::Unknown);
+
switch (audio.type()) {
case AudioMsgId::Type::Voice: if (_audio == audio) clear(audio.type()); break;
case AudioMsgId::Type::Song: if (_song == audio) clear(audio.type()); break;
diff --git a/Telegram/SourceFiles/media/player/media_player_instance.cpp b/Telegram/SourceFiles/media/player/media_player_instance.cpp
index 226d6c53d5..71ba6b9f75 100644
--- a/Telegram/SourceFiles/media/player/media_player_instance.cpp
+++ b/Telegram/SourceFiles/media/player/media_player_instance.cpp
@@ -112,10 +112,11 @@ Instance::Instance()
Instance::~Instance() = default;
AudioMsgId::Type Instance::getActiveType() const {
- auto voiceData = getData(AudioMsgId::Type::Voice);
+ const auto voiceData = getData(AudioMsgId::Type::Voice);
if (voiceData->current) {
const auto state = getState(voiceData->type);
- if (voiceData->current == state.id && !IsStoppedOrStopping(state.state)) {
+ if (voiceData->current == state.id
+ && !IsStoppedOrStopping(state.state)) {
return voiceData->type;
}
}
@@ -149,11 +150,9 @@ void Instance::setCurrent(const AudioMsgId &audioId) {
data->current = audioId;
data->isPlaying = false;
- auto history = data->history;
- auto migrated = data->migrated;
- auto item = data->current
- ? App::histItemById(data->current.contextId())
- : nullptr;
+ const auto history = data->history;
+ const auto migrated = data->migrated;
+ const auto item = App::histItemById(data->current.contextId());
if (item) {
data->history = item->history()->migrateToOrMe();
data->migrated = data->history->migrateFrom();
@@ -333,7 +332,7 @@ void Instance::play(AudioMsgId::Type type) {
} else {
mixer()->resume(state.id);
}
- } else if (data->current) {
+ } else {
play(data->current);
}
data->resumeOnCallEnd = false;
@@ -342,7 +341,7 @@ void Instance::play(AudioMsgId::Type type) {
void Instance::play(const AudioMsgId &audioId) {
const auto document = audioId.audio();
- if (!audioId || !document) {
+ if (!document) {
return;
}
if (document->isAudioFile()) {
@@ -465,9 +464,7 @@ void Instance::playPause(AudioMsgId::Type type) {
mixer()->pause(state.id);
}
} else if (auto data = getData(type)) {
- if (data->current) {
- play(data->current);
- }
+ play(data->current);
}
}
data->resumeOnCallEnd = false;
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_loader_mtproto.cpp b/Telegram/SourceFiles/media/streaming/media_streaming_loader_mtproto.cpp
index 4b70c3eb96..3acb29a4cd 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_loader_mtproto.cpp
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_loader_mtproto.cpp
@@ -99,6 +99,7 @@ void LoaderMtproto::sendNext() {
}
static auto DcIndex = 0;
+ const auto reference = locationFileReference();
const auto id = _sender.request(MTPupload_GetFile(
_location,
MTP_int(offset),
@@ -106,7 +107,7 @@ void LoaderMtproto::sendNext() {
)).done([=](const MTPupload_File &result) {
requestDone(offset, result);
}).fail([=](const RPCError &error) {
- requestFailed(offset, error);
+ requestFailed(offset, error, reference);
}).toDC(
MTP::downloadDcId(_dcId, (++DcIndex) % MTP::kDownloadSessionsCount)
).send();
@@ -138,21 +139,57 @@ void LoaderMtproto::changeCdnParams(
const QByteArray &encryptionKey,
const QByteArray &encryptionIV,
const QVector<MTPFileHash> &hashes) {
- // #TODO streaming cdn
+ // #TODO streaming later cdn
+ _parts.fire({ LoadedPart::kFailedOffset });
}
-void LoaderMtproto::requestFailed(int offset, const RPCError &error) {
+void LoaderMtproto::requestFailed(
+ int offset,
+ const RPCError &error,
+ const QByteArray &usedFileReference) {
const auto &type = error.type();
- if (error.code() != 400 || !type.startsWith(qstr("FILE_REFERENCE_"))) {
+ const auto fail = [=] {
_parts.fire({ LoadedPart::kFailedOffset });
- return;
+ };
+ if (error.code() != 400 || !type.startsWith(qstr("FILE_REFERENCE_"))) {
+ return fail();
}
const auto callback = [=](const Data::UpdatedFileReferences &updated) {
- // #TODO streaming file_reference
+ _location.match([&](const MTPDinputDocumentFileLocation &location) {
+ const auto i = updated.data.find(location.vid.v);
+ if (i == end(updated.data)) {
+ return fail();
+ }
+ const auto reference = i->second;
+ if (reference == usedFileReference) {
+ return fail();
+ } else if (reference != location.vfile_reference.v) {
+ _location = MTP_inputDocumentFileLocation(
+ MTP_long(location.vid.v),
+ MTP_long(location.vaccess_hash.v),
+ MTP_bytes(reference));
+ }
+ if (!_requests.take(offset)) {
+ // Request with such offset was already cancelled.
+ return;
+ }
+ _requested.add(offset);
+ sendNext();
+ }, [](auto &&) {
+ Unexpected("Not implemented file location type.");
+ });
};
_api->refreshFileReference(_origin, crl::guard(this, callback));
}
+QByteArray LoaderMtproto::locationFileReference() const {
+ return _location.match([&](const MTPDinputDocumentFileLocation &data) {
+ return data.vfile_reference.v;
+ }, [](auto &&) -> QByteArray {
+ Unexpected("Not implemented file location type.");
+ });
+}
+
rpl::producer<LoadedPart> LoaderMtproto::parts() const {
return _parts.events();
}
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_loader_mtproto.h b/Telegram/SourceFiles/media/streaming/media_streaming_loader_mtproto.h
index 3174b62367..c2a9058d6b 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_loader_mtproto.h
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_loader_mtproto.h
@@ -43,7 +43,10 @@ private:
void sendNext();
void requestDone(int offset, const MTPupload_File &result);
- void requestFailed(int offset, const RPCError &error);
+ void requestFailed(
+ int offset,
+ const RPCError &error,
+ const QByteArray &usedFileReference);
void changeCdnParams(
int offset,
MTP::DcId dcId,
@@ -52,9 +55,14 @@ private:
const QByteArray &encryptionIV,
const QVector<MTPFileHash> &hashes);
+ [[nodiscard]] QByteArray locationFileReference() const;
+
const not_null<ApiWrap*> _api;
const MTP::DcId _dcId = 0;
- const MTPInputFileLocation _location;
+
+ // _location can be changed with an updated file_reference.
+ MTPInputFileLocation _location;
+
const int _size = 0;
const Data::FileOrigin _origin;
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp b/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp
index a5acce8227..3218dd0397 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp
@@ -218,7 +218,7 @@ void Player::fileReady(Stream &&video, Stream &&audio) {
};
const auto mode = _options.mode;
if (audio.codec && (mode == Mode::Audio || mode == Mode::Both)) {
- if (_options.audioId) {
+ if (_options.audioId.audio() != nullptr) {
_audioId = AudioMsgId(
_options.audioId.audio(),
_options.audioId.contextId(),
diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp
index ccc583444a..961ec312ef 100644
--- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp
+++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp
@@ -676,6 +676,39 @@ QRect OverlayWidget::contentRect() const {
return { _x, _y, _w, _h };
}
+void OverlayWidget::contentSizeChanged() {
+ _width = _w;
+ _height = _h;
+ if (_w > 0 && _h > 0) {
+ _zoomToScreen = float64(width()) / _w;
+ if (_h * _zoomToScreen > height()) {
+ _zoomToScreen = float64(height()) / _h;
+ }
+ if (_zoomToScreen >= 1.) {
+ _zoomToScreen -= 1.;
+ } else {
+ _zoomToScreen = 1. - (1. / _zoomToScreen);
+ }
+ } else {
+ _zoomToScreen = 0;
+ }
+ if ((_w > width()) || (_h > height()) || _fullScreenVideo) {
+ _zoom = ZoomToScreenLevel;
+ if (_zoomToScreen >= 0) {
+ _w = qRound(_w * (_zoomToScreen + 1));
+ _h = qRound(_h * (_zoomToScreen + 1));
+ } else {
+ _w = qRound(_w / (-_zoomToScreen + 1));
+ _h = qRound(_h / (-_zoomToScreen + 1));
+ }
+ snapXY();
+ } else {
+ _zoom = 0;
+ }
+ _x = (width() - _w) / 2;
+ _y = (height() - _h) / 2;
+}
+
float64 OverlayWidget::radialProgress() const {
if (_doc) {
return _doc->progress();
@@ -1645,18 +1678,7 @@ void OverlayWidget::displayPhoto(not_null<PhotoData*> photo, HistoryItem *item)
if (isHidden()) {
moveToScreen();
}
- if (_w > width()) {
- _h = qRound(_h * width() / float64(_w));
- _w = width();
- }
- if (_h > height()) {
- _w = qRound(_w * height() / float64(_h));
- _h = height();
- }
- _x = (width() - _w) / 2;
- _y = (height() - _h) / 2;
- _width = _w;
- _height = _h;
+ contentSizeChanged();
if (_msgid && item) {
_from = item->senderOriginal();
} else {
@@ -1798,36 +1820,7 @@ void OverlayWidget::displayDocument(DocumentData *doc, HistoryItem *item) {
if (isHidden()) {
moveToScreen();
}
- _width = _w;
- _height = _h;
- if (_w > 0 && _h > 0) {
- _zoomToScreen = float64(width()) / _w;
- if (_h * _zoomToScreen > height()) {
- _zoomToScreen = float64(height()) / _h;
- }
- if (_zoomToScreen >= 1.) {
- _zoomToScreen -= 1.;
- } else {
- _zoomToScreen = 1. - (1. / _zoomToScreen);
- }
- } else {
- _zoomToScreen = 0;
- }
- if ((_w > width()) || (_h > height()) || _fullScreenVideo) {
- _zoom = ZoomToScreenLevel;
- if (_zoomToScreen >= 0) {
- _w = qRound(_w * (_zoomToScreen + 1));
- _h = qRound(_h * (_zoomToScreen + 1));
- } else {
- _w = qRound(_w / (-_zoomToScreen + 1));
- _h = qRound(_h / (-_zoomToScreen + 1));
- }
- snapXY();
- } else {
- _zoom = 0;
- }
- _x = (width() - _w) / 2;
- _y = (height() - _h) / 2;
+ contentSizeChanged();
if (_msgid && item) {
_from = item->senderOriginal();
} else {
@@ -1927,6 +1920,19 @@ void OverlayWidget::initStreamingThumbnail() {
_current.setDevicePixelRatio(cRetinaFactor());
}
+void OverlayWidget::streamingReady(Streaming::Information &&info) {
+ _streamed->info = std::move(info);
+ validateStreamedGoodThumbnail();
+ if (videoShown()) {
+ const auto contentSize = ConvertScale(videoSize());
+ _w = contentSize.width();
+ _h = contentSize.height();
+ contentSizeChanged();
+ }
+ this->update(contentRect());
+ playbackWaitingChange(false);
+}
+
void OverlayWidget::createStreamingObjects() {
_streamed = std::make_unique<Streamed>(
&_doc->owner(),
@@ -1978,10 +1984,7 @@ void OverlayWidget::handleStreamingUpdate(Streaming::Update &&update) {
using namespace Streaming;
update.data.match([&](Information &update) {
- _streamed->info = std::move(update);
- validateStreamedGoodThumbnail();
- this->update(contentRect());
- playbackWaitingChange(false);
+ streamingReady(std::move(update));
}, [&](const PreloadedVideo &update) {
_streamed->info.video.state.receivedTill = update.till;
//updatePlaybackState();
diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.h b/Telegram/SourceFiles/media/view/media_view_overlay_widget.h
index 1a90c76cb6..c9bcd2afd8 100644
--- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.h
+++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.h
@@ -37,6 +37,7 @@ namespace Player {
struct TrackState;
} // namespace Player
namespace Streaming {
+struct Information;
struct Update;
struct Error;
} // namespace Streaming
@@ -236,6 +237,7 @@ private:
void initStreaming();
void initStreamingThumbnail();
+ void streamingReady(Streaming::Information &&info);
void createStreamingObjects();
void handleStreamingUpdate(Streaming::Update &&update);
void handleStreamingError(Streaming::Error &&error);
@@ -249,6 +251,7 @@ private:
void changingMsgId(not_null<HistoryItem*> row, MsgId newId);
QRect contentRect() const;
+ void contentSizeChanged();
// Radial animation interface.
float64 radialProgress() const;