Keep alternative video qualities list.

This commit is contained in:
John Preston 2024-10-25 10:01:26 +04:00
parent 19afb49fce
commit 7ba78540ac
9 changed files with 129 additions and 16 deletions

View file

@ -39,8 +39,8 @@ constexpr auto kTransactionsLimit = 100;
if (const auto list = tl.data().vextended_media()) {
extended.reserve(list->v.size());
for (const auto &media : list->v) {
media.match([&](const MTPDmessageMediaPhoto &photo) {
if (const auto inner = photo.vphoto()) {
media.match([&](const MTPDmessageMediaPhoto &data) {
if (const auto inner = data.vphoto()) {
const auto photo = owner->processPhoto(*inner);
if (!photo->isNull()) {
extended.push_back(CreditsHistoryMedia{
@ -49,9 +49,11 @@ constexpr auto kTransactionsLimit = 100;
});
}
}
}, [&](const MTPDmessageMediaDocument &document) {
if (const auto inner = document.vdocument()) {
const auto document = owner->processDocument(*inner);
}, [&](const MTPDmessageMediaDocument &data) {
if (const auto inner = data.vdocument()) {
const auto document = owner->processDocument(
*inner,
data.valt_documents());
if (document->isAnimation()
|| document->isVideoFile()
|| document->isGifv()) {

View file

@ -346,7 +346,9 @@ void SponsoredMessages::append(
}, [&](const MTPDmessageMediaDocument &media) {
if (const auto tlDocument = media.vdocument()) {
tlDocument->match([&](const MTPDdocument &data) {
const auto d = history->owner().processDocument(data);
const auto d = history->owner().processDocument(
data,
media.valt_documents());
if (d->isVideoFile()
|| d->isSilentVideo()
|| d->isAnimation()

View file

@ -332,6 +332,8 @@ void DocumentData::setattributes(
validateLottieSticker();
auto wasVideoData = isVideoFile() ? std::move(_additional) : nullptr;
_videoPreloadPrefix = 0;
for (const auto &attribute : attributes) {
attribute.match([&](const MTPDdocumentAttributeImageSize &data) {
@ -388,11 +390,21 @@ void DocumentData::setattributes(
: VideoDocument;
if (data.is_round_message()) {
_additional = std::make_unique<RoundData>();
} else if (const auto size = data.vpreload_prefix_size()) {
if (size->v > 0 && size->v < kMaxAllowedPreloadPrefix) {
_videoPreloadPrefix = size->v;
} else {
if (const auto size = data.vpreload_prefix_size()) {
if (size->v > 0
&& size->v < kMaxAllowedPreloadPrefix) {
_videoPreloadPrefix = size->v;
}
}
_additional = wasVideoData
? std::move(wasVideoData)
: std::make_unique<VideoData>();
video()->codec = qs(
data.vvideo_codec().value_or_empty());
}
} else if (type == VideoDocument && wasVideoData) {
_additional = std::move(wasVideoData);
} else if (const auto info = sticker()) {
info->type = StickerType::Webm;
}
@ -511,6 +523,67 @@ void DocumentData::setattributes(
}
}
void DocumentData::setVideoQualities(const QVector<MTPDocument> &list) {
auto qualities = std::vector<not_null<DocumentData*>>();
qualities.reserve(list.size());
for (const auto &document : list) {
qualities.push_back(owner().processDocument(document));
}
setVideoQualities(std::move(qualities));
}
void DocumentData::setVideoQualities(
std::vector<not_null<DocumentData*>> qualities) {
const auto data = video();
if (!data) {
return;
}
auto count = int(qualities.size());
if (qualities.empty()) {
return;
}
const auto good = [&](not_null<DocumentData*> document) {
return document->isVideoFile()
&& !document->dimensions.isEmpty()
&& !document->inappPlaybackFailed()
&& document->useStreamingLoader()
&& document->canBeStreamed(nullptr);
};
ranges::sort(
qualities,
ranges::greater(),
&DocumentData::resolveVideoQuality);
for (auto i = 0; i != count - 1;) {
const auto my = qualities[i];
const auto next = qualities[i + 1];
const auto myQuality = my->resolveVideoQuality();
const auto nextQuality = next->resolveVideoQuality();
const auto myGood = good(my);
const auto nextGood = good(next);
if (!myGood || !nextGood || myQuality == nextQuality) {
const auto removeMe = !myGood
|| (nextGood && (my->size > next->size));
const auto from = i + (removeMe ? 1 : 2);
for (auto j = from; j != count; ++j) {
qualities[j - 1] = qualities[j];
}
--count;
} else {
++i;
}
}
if (!qualities[count - 1]->resolveVideoQuality()) {
--count;
}
qualities.erase(qualities.begin() + count, qualities.end());
data->qualities = std::move(qualities);
}
int DocumentData::resolveVideoQuality() const {
const auto size = isVideoFile() ? dimensions : QSize();
return size.isEmpty() ? 0 : std::min(size.width(), size.height());
}
void DocumentData::validateLottieSticker() {
if (type == FileDocument
&& hasMimeType(u"application/x-tgsticker"_q)) {
@ -1384,6 +1457,16 @@ const RoundData *DocumentData::round() const {
return const_cast<DocumentData*>(this)->round();
}
VideoData *DocumentData::video() {
return isVideoFile()
? static_cast<VideoData*>(_additional.get())
: nullptr;
}
const VideoData *DocumentData::video() const {
return const_cast<DocumentData*>(this)->video();
}
bool DocumentData::hasRemoteLocation() const {
return (_dc != 0 && _access != 0);
}

View file

@ -92,6 +92,11 @@ struct VoiceData : public DocumentAdditionalData {
char wavemax = 0;
};
struct VideoData : public DocumentAdditionalData {
QString codec;
std::vector<not_null<DocumentData*>> qualities;
};
using RoundData = VoiceData;
namespace Serialize {
@ -108,8 +113,11 @@ public:
void setattributes(
const QVector<MTPDocumentAttribute> &attributes);
void setVideoQualities(const QVector<MTPDocument> &list);
void automaticLoadSettingsChanged();
void setVideoQualities(std::vector<not_null<DocumentData*>> qualities);
[[nodiscard]] int resolveVideoQuality() const;
[[nodiscard]] bool loading() const;
[[nodiscard]] QString loadingFilePath() const;
@ -161,6 +169,8 @@ public:
[[nodiscard]] const VoiceData *voice() const;
[[nodiscard]] RoundData *round();
[[nodiscard]] const RoundData *round() const;
[[nodiscard]] VideoData *video();
[[nodiscard]] const VideoData *video() const;
void forceIsStreamedAnimation();
[[nodiscard]] bool isVoiceMessage() const;

View file

@ -87,6 +87,7 @@ struct FileReferenceAccumulator {
push(data.vphoto());
}, [&](const MTPDmessageMediaDocument &data) {
push(data.vdocument());
push(data.valt_documents());
}, [&](const MTPDmessageMediaWebPage &data) {
push(data.vwebpage());
}, [&](const MTPDmessageMediaGame &data) {

View file

@ -3139,17 +3139,24 @@ not_null<DocumentData*> Session::document(DocumentId id) {
return i->second.get();
}
not_null<DocumentData*> Session::processDocument(const MTPDocument &data) {
not_null<DocumentData*> Session::processDocument(
const MTPDocument &data,
const MTPVector<MTPDocument> *qualities) {
return data.match([&](const MTPDdocument &data) {
return processDocument(data);
return processDocument(data, qualities);
}, [&](const MTPDdocumentEmpty &data) {
return document(data.vid().v);
});
}
not_null<DocumentData*> Session::processDocument(const MTPDdocument &data) {
not_null<DocumentData*> Session::processDocument(
const MTPDdocument &data,
const MTPVector<MTPDocument> *qualities) {
const auto result = document(data.vid().v);
documentApplyFields(result, data);
if (qualities) {
result->setVideoQualities(qualities->v);
}
return result;
}

View file

@ -558,8 +558,12 @@ public:
const ImageLocation &thumbnailLocation);
[[nodiscard]] not_null<DocumentData*> document(DocumentId id);
not_null<DocumentData*> processDocument(const MTPDocument &data);
not_null<DocumentData*> processDocument(const MTPDdocument &data);
not_null<DocumentData*> processDocument(
const MTPDocument &data,
const MTPVector<MTPDocument> *qualities = nullptr);
not_null<DocumentData*> processDocument(
const MTPDdocument &data,
const MTPVector<MTPDocument> *qualities = nullptr);
not_null<DocumentData*> processDocument(
const MTPdocument &data,
const ImageWithLocation &thumbnail);

View file

@ -62,7 +62,9 @@ using UpdateFlag = StoryUpdate::Flag;
}, [&](const MTPDmessageMediaDocument &data)
-> std::optional<StoryMedia> {
if (const auto document = data.vdocument()) {
const auto result = owner->processDocument(*document);
const auto result = owner->processDocument(
*document,
data.valt_documents());
if (!result->isNull()
&& (result->isGifv() || result->isVideoFile())) {
result->setStoryMedia(true);

View file

@ -299,7 +299,9 @@ std::unique_ptr<Data::Media> HistoryItem::CreateMedia(
return document->match([&](const MTPDdocument &document) -> Result {
return std::make_unique<Data::MediaFile>(
item,
item->history()->owner().processDocument(document),
item->history()->owner().processDocument(
document,
media.valt_documents()),
media.is_nopremium(),
media.is_spoiler(),
media.vttl_seconds().value_or_empty());