Implement file reference update in streaming.

This commit is contained in:
John Preston 2019-03-01 16:22:47 +04:00
parent 648cd44ddd
commit c574119718
10 changed files with 132 additions and 82 deletions

View File

@ -361,8 +361,8 @@ public:
AudioMsgId() = default; AudioMsgId() = default;
AudioMsgId( AudioMsgId(
DocumentData *audio, not_null<DocumentData*> audio,
const FullMsgId &msgId, FullMsgId msgId,
uint32 externalPlayId = 0) uint32 externalPlayId = 0)
: _audio(audio) : _audio(audio)
, _contextId(msgId) , _contextId(msgId)
@ -373,21 +373,20 @@ public:
[[nodiscard]] static uint32 CreateExternalPlayId(); [[nodiscard]] static uint32 CreateExternalPlayId();
[[nodiscard]] static AudioMsgId ForVideo(); [[nodiscard]] static AudioMsgId ForVideo();
Type type() const { [[nodiscard]] Type type() const {
return _type; return _type;
} }
DocumentData *audio() const { [[nodiscard]] DocumentData *audio() const {
return _audio; return _audio;
} }
FullMsgId contextId() const { [[nodiscard]] FullMsgId contextId() const {
return _contextId; return _contextId;
} }
uint32 externalPlayId() const { [[nodiscard]] uint32 externalPlayId() const {
return _externalPlayId; return _externalPlayId;
} }
[[nodiscard]] explicit operator bool() const {
explicit operator bool() const { return (_audio != nullptr) || (_externalPlayId != 0);
return _audio != nullptr;
} }
private: private:

View File

@ -711,11 +711,10 @@ void HistoryDocument::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool
const auto type = AudioMsgId::Type::Voice; const auto type = AudioMsgId::Type::Voice;
const auto state = Media::Player::instance()->getState(type); const auto state = Media::Player::instance()->getState(type);
if (state.id == AudioMsgId(_data, _parent->data()->fullId(), state.id.externalPlayId()) && state.length) { if (state.id == AudioMsgId(_data, _parent->data()->fullId(), state.id.externalPlayId()) && state.length) {
auto currentProgress = voice->seekingCurrent(); const auto currentProgress = voice->seekingCurrent();
auto currentPosition = state.frequency Media::Player::instance()->finishSeeking(
? qRound(currentProgress * state.length * 1000. / state.frequency) AudioMsgId::Type::Voice,
: 0; currentProgress);
Media::Player::mixer()->seek(type, currentPosition);
voice->ensurePlayback(this); voice->ensurePlayback(this);
voice->_playback->_position = 0; voice->_playback->_position = 0;

View File

@ -1242,7 +1242,9 @@ void Mixer::setStoppedState(Track *current, State state) {
alSourceStop(current->stream.source); alSourceStop(current->stream.source);
alSourcef(current->stream.source, AL_GAIN, 1); 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) { void Mixer::clearStoppedAtStart(const AudioMsgId &audio) {

View File

@ -413,6 +413,8 @@ Mixer::Track *Loaders::checkLoader(AudioMsgId::Type type) {
} }
void Loaders::onCancel(const AudioMsgId &audio) { void Loaders::onCancel(const AudioMsgId &audio) {
Expects(audio.type() != AudioMsgId::Type::Unknown);
switch (audio.type()) { switch (audio.type()) {
case AudioMsgId::Type::Voice: if (_audio == audio) clear(audio.type()); break; case AudioMsgId::Type::Voice: if (_audio == audio) clear(audio.type()); break;
case AudioMsgId::Type::Song: if (_song == audio) clear(audio.type()); break; case AudioMsgId::Type::Song: if (_song == audio) clear(audio.type()); break;

View File

@ -112,10 +112,11 @@ Instance::Instance()
Instance::~Instance() = default; Instance::~Instance() = default;
AudioMsgId::Type Instance::getActiveType() const { AudioMsgId::Type Instance::getActiveType() const {
auto voiceData = getData(AudioMsgId::Type::Voice); const auto voiceData = getData(AudioMsgId::Type::Voice);
if (voiceData->current) { if (voiceData->current) {
const auto state = getState(voiceData->type); 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; return voiceData->type;
} }
} }
@ -149,11 +150,9 @@ void Instance::setCurrent(const AudioMsgId &audioId) {
data->current = audioId; data->current = audioId;
data->isPlaying = false; data->isPlaying = false;
auto history = data->history; const auto history = data->history;
auto migrated = data->migrated; const auto migrated = data->migrated;
auto item = data->current const auto item = App::histItemById(data->current.contextId());
? App::histItemById(data->current.contextId())
: nullptr;
if (item) { if (item) {
data->history = item->history()->migrateToOrMe(); data->history = item->history()->migrateToOrMe();
data->migrated = data->history->migrateFrom(); data->migrated = data->history->migrateFrom();
@ -333,7 +332,7 @@ void Instance::play(AudioMsgId::Type type) {
} else { } else {
mixer()->resume(state.id); mixer()->resume(state.id);
} }
} else if (data->current) { } else {
play(data->current); play(data->current);
} }
data->resumeOnCallEnd = false; data->resumeOnCallEnd = false;
@ -342,7 +341,7 @@ void Instance::play(AudioMsgId::Type type) {
void Instance::play(const AudioMsgId &audioId) { void Instance::play(const AudioMsgId &audioId) {
const auto document = audioId.audio(); const auto document = audioId.audio();
if (!audioId || !document) { if (!document) {
return; return;
} }
if (document->isAudioFile()) { if (document->isAudioFile()) {
@ -465,9 +464,7 @@ void Instance::playPause(AudioMsgId::Type type) {
mixer()->pause(state.id); mixer()->pause(state.id);
} }
} else if (auto data = getData(type)) { } else if (auto data = getData(type)) {
if (data->current) { play(data->current);
play(data->current);
}
} }
} }
data->resumeOnCallEnd = false; data->resumeOnCallEnd = false;

View File

@ -99,6 +99,7 @@ void LoaderMtproto::sendNext() {
} }
static auto DcIndex = 0; static auto DcIndex = 0;
const auto reference = locationFileReference();
const auto id = _sender.request(MTPupload_GetFile( const auto id = _sender.request(MTPupload_GetFile(
_location, _location,
MTP_int(offset), MTP_int(offset),
@ -106,7 +107,7 @@ void LoaderMtproto::sendNext() {
)).done([=](const MTPupload_File &result) { )).done([=](const MTPupload_File &result) {
requestDone(offset, result); requestDone(offset, result);
}).fail([=](const RPCError &error) { }).fail([=](const RPCError &error) {
requestFailed(offset, error); requestFailed(offset, error, reference);
}).toDC( }).toDC(
MTP::downloadDcId(_dcId, (++DcIndex) % MTP::kDownloadSessionsCount) MTP::downloadDcId(_dcId, (++DcIndex) % MTP::kDownloadSessionsCount)
).send(); ).send();
@ -138,21 +139,57 @@ void LoaderMtproto::changeCdnParams(
const QByteArray &encryptionKey, const QByteArray &encryptionKey,
const QByteArray &encryptionIV, const QByteArray &encryptionIV,
const QVector<MTPFileHash> &hashes) { 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(); const auto &type = error.type();
if (error.code() != 400 || !type.startsWith(qstr("FILE_REFERENCE_"))) { const auto fail = [=] {
_parts.fire({ LoadedPart::kFailedOffset }); _parts.fire({ LoadedPart::kFailedOffset });
return; };
if (error.code() != 400 || !type.startsWith(qstr("FILE_REFERENCE_"))) {
return fail();
} }
const auto callback = [=](const Data::UpdatedFileReferences &updated) { 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)); _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 { rpl::producer<LoadedPart> LoaderMtproto::parts() const {
return _parts.events(); return _parts.events();
} }

View File

@ -43,7 +43,10 @@ private:
void sendNext(); void sendNext();
void requestDone(int offset, const MTPupload_File &result); 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( void changeCdnParams(
int offset, int offset,
MTP::DcId dcId, MTP::DcId dcId,
@ -52,9 +55,14 @@ private:
const QByteArray &encryptionIV, const QByteArray &encryptionIV,
const QVector<MTPFileHash> &hashes); const QVector<MTPFileHash> &hashes);
[[nodiscard]] QByteArray locationFileReference() const;
const not_null<ApiWrap*> _api; const not_null<ApiWrap*> _api;
const MTP::DcId _dcId = 0; const MTP::DcId _dcId = 0;
const MTPInputFileLocation _location;
// _location can be changed with an updated file_reference.
MTPInputFileLocation _location;
const int _size = 0; const int _size = 0;
const Data::FileOrigin _origin; const Data::FileOrigin _origin;

View File

@ -218,7 +218,7 @@ void Player::fileReady(Stream &&video, Stream &&audio) {
}; };
const auto mode = _options.mode; const auto mode = _options.mode;
if (audio.codec && (mode == Mode::Audio || mode == Mode::Both)) { if (audio.codec && (mode == Mode::Audio || mode == Mode::Both)) {
if (_options.audioId) { if (_options.audioId.audio() != nullptr) {
_audioId = AudioMsgId( _audioId = AudioMsgId(
_options.audioId.audio(), _options.audioId.audio(),
_options.audioId.contextId(), _options.audioId.contextId(),

View File

@ -676,6 +676,39 @@ QRect OverlayWidget::contentRect() const {
return { _x, _y, _w, _h }; 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 { float64 OverlayWidget::radialProgress() const {
if (_doc) { if (_doc) {
return _doc->progress(); return _doc->progress();
@ -1645,18 +1678,7 @@ void OverlayWidget::displayPhoto(not_null<PhotoData*> photo, HistoryItem *item)
if (isHidden()) { if (isHidden()) {
moveToScreen(); moveToScreen();
} }
if (_w > width()) { contentSizeChanged();
_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;
if (_msgid && item) { if (_msgid && item) {
_from = item->senderOriginal(); _from = item->senderOriginal();
} else { } else {
@ -1798,36 +1820,7 @@ void OverlayWidget::displayDocument(DocumentData *doc, HistoryItem *item) {
if (isHidden()) { if (isHidden()) {
moveToScreen(); moveToScreen();
} }
_width = _w; contentSizeChanged();
_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;
if (_msgid && item) { if (_msgid && item) {
_from = item->senderOriginal(); _from = item->senderOriginal();
} else { } else {
@ -1927,6 +1920,19 @@ void OverlayWidget::initStreamingThumbnail() {
_current.setDevicePixelRatio(cRetinaFactor()); _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() { void OverlayWidget::createStreamingObjects() {
_streamed = std::make_unique<Streamed>( _streamed = std::make_unique<Streamed>(
&_doc->owner(), &_doc->owner(),
@ -1978,10 +1984,7 @@ void OverlayWidget::handleStreamingUpdate(Streaming::Update &&update) {
using namespace Streaming; using namespace Streaming;
update.data.match([&](Information &update) { update.data.match([&](Information &update) {
_streamed->info = std::move(update); streamingReady(std::move(update));
validateStreamedGoodThumbnail();
this->update(contentRect());
playbackWaitingChange(false);
}, [&](const PreloadedVideo &update) { }, [&](const PreloadedVideo &update) {
_streamed->info.video.state.receivedTill = update.till; _streamed->info.video.state.receivedTill = update.till;
//updatePlaybackState(); //updatePlaybackState();

View File

@ -37,6 +37,7 @@ namespace Player {
struct TrackState; struct TrackState;
} // namespace Player } // namespace Player
namespace Streaming { namespace Streaming {
struct Information;
struct Update; struct Update;
struct Error; struct Error;
} // namespace Streaming } // namespace Streaming
@ -236,6 +237,7 @@ private:
void initStreaming(); void initStreaming();
void initStreamingThumbnail(); void initStreamingThumbnail();
void streamingReady(Streaming::Information &&info);
void createStreamingObjects(); void createStreamingObjects();
void handleStreamingUpdate(Streaming::Update &&update); void handleStreamingUpdate(Streaming::Update &&update);
void handleStreamingError(Streaming::Error &&error); void handleStreamingError(Streaming::Error &&error);
@ -249,6 +251,7 @@ private:
void changingMsgId(not_null<HistoryItem*> row, MsgId newId); void changingMsgId(not_null<HistoryItem*> row, MsgId newId);
QRect contentRect() const; QRect contentRect() const;
void contentSizeChanged();
// Radial animation interface. // Radial animation interface.
float64 radialProgress() const; float64 radialProgress() const;