Allow to load video components of photos.

This commit is contained in:
John Preston 2020-07-03 12:42:09 +04:00
parent 1a9c241b96
commit 0126578dbd
9 changed files with 151 additions and 13 deletions

View file

@ -166,8 +166,8 @@ public:
[[nodiscard]] bool videoThumbnailLoading() const;
[[nodiscard]] bool videoThumbnailFailed() const;
void loadVideoThumbnail(Data::FileOrigin origin);
const ImageLocation &videoThumbnailLocation() const;
int videoThumbnailByteSize() const;
[[nodiscard]] const ImageLocation &videoThumbnailLocation() const;
[[nodiscard]] int videoThumbnailByteSize() const;
void updateThumbnails(
const QByteArray &inlineThumbnailBytes,

View file

@ -39,6 +39,7 @@ PhotoData::~PhotoData() {
for (auto &image : _images) {
base::take(image.loader).reset();
}
base::take(_video.loader).reset();
}
Data::Session &PhotoData::owner() const {
@ -294,7 +295,8 @@ void PhotoData::updateImages(
const QByteArray &inlineThumbnailBytes,
const ImageWithLocation &small,
const ImageWithLocation &thumbnail,
const ImageWithLocation &large) {
const ImageWithLocation &large,
const ImageWithLocation &video) {
if (!inlineThumbnailBytes.isEmpty()
&& _inlineThumbnailBytes.isEmpty()) {
_inlineThumbnailBytes = inlineThumbnailBytes;
@ -315,6 +317,13 @@ void PhotoData::updateImages(
update(PhotoSize::Small, small);
update(PhotoSize::Thumbnail, thumbnail);
update(PhotoSize::Large, large);
Data::UpdateCloudFile(
_video,
video,
owner().cache(),
Data::kAnimationCacheTag,
[&](Data::FileOrigin origin) { loadVideo(origin); });
}
int PhotoData::width() const {
@ -325,6 +334,50 @@ int PhotoData::height() const {
return _images[PhotoSizeIndex(PhotoSize::Large)].location.height();
}
bool PhotoData::hasVideo() const {
return _video.location.valid();
}
bool PhotoData::videoLoading() const {
return _video.loader != nullptr;
}
bool PhotoData::videoFailed() const {
return (_video.flags & Data::CloudFile::Flag::Failed);
}
void PhotoData::loadVideo(Data::FileOrigin origin) {
const auto autoLoading = false;
const auto finalCheck = [=] {
if (const auto active = activeMediaView()) {
return active->videoContent().isEmpty();
}
return true;
};
const auto done = [=](QByteArray result) {
if (const auto active = activeMediaView()) {
active->setVideo(std::move(result));
}
};
Data::LoadCloudFile(
&session(),
_video,
origin,
LoadFromCloudOrLocal,
autoLoading,
Data::kAnimationCacheTag,
finalCheck,
done);
}
const ImageLocation &PhotoData::videoLocation() const {
return _video.location;
}
int PhotoData::videoByteSize() const {
return _video.byteSize;
}
PhotoClickHandler::PhotoClickHandler(
not_null<PhotoData*> photo,
FullMsgId context,

View file

@ -82,7 +82,8 @@ public:
const QByteArray &inlineThumbnailBytes,
const ImageWithLocation &small,
const ImageWithLocation &thumbnail,
const ImageWithLocation &large);
const ImageWithLocation &large,
const ImageWithLocation &video);
[[nodiscard]] int validSizeIndex(Data::PhotoSize size) const;
[[nodiscard]] QByteArray inlineThumbnailBytes() const {
@ -111,6 +112,13 @@ public:
[[nodiscard]] std::optional<QSize> size(Data::PhotoSize size) const;
[[nodiscard]] int imageByteSize(Data::PhotoSize size) const;
[[nodiscard]] bool hasVideo() const;
[[nodiscard]] bool videoLoading() const;
[[nodiscard]] bool videoFailed() const;
void loadVideo(Data::FileOrigin origin);
[[nodiscard]] const ImageLocation &videoLocation() const;
[[nodiscard]] int videoByteSize() const;
// For now they return size of the 'large' image.
int width() const;
int height() const;
@ -127,6 +135,7 @@ public:
private:
QByteArray _inlineThumbnailBytes;
std::array<Data::CloudFile, Data::kPhotoSizeCount> _images;
Data::CloudFile _video;
int32 _dc = 0;
uint64 _access = 0;

View file

@ -85,6 +85,25 @@ void PhotoMedia::set(PhotoSize size, QImage image) {
_owner->session().notifyDownloaderTaskFinished();
}
QByteArray PhotoMedia::videoContent() const {
return _videoBytes;
}
QSize PhotoMedia::videoSize() const {
const auto &location = _owner->videoLocation();
return { location.width(), location.height() };
}
void PhotoMedia::videoWanted(Data::FileOrigin origin) {
if (_videoBytes.isEmpty()) {
_owner->loadVideo(origin);
}
}
void PhotoMedia::setVideo(QByteArray content) {
_videoBytes = std::move(content);
}
bool PhotoMedia::loaded() const {
const auto index = PhotoSizeIndex(PhotoSize::Large);
return (_images[index] != nullptr);

View file

@ -28,6 +28,11 @@ public:
void wanted(PhotoSize size, Data::FileOrigin origin);
void set(PhotoSize size, QImage image);
[[nodiscard]] QByteArray videoContent() const;
[[nodiscard]] QSize videoSize() const;
void videoWanted(Data::FileOrigin origin);
void setVideo(QByteArray content);
[[nodiscard]] bool loaded() const;
[[nodiscard]] float64 progress() const;
@ -42,6 +47,7 @@ private:
const not_null<PhotoData*> _owner;
mutable std::unique_ptr<Image> _inlineThumbnail;
std::array<std::unique_ptr<Image>, kPhotoSizeCount> _images;
QByteArray _videoBytes;
};

View file

@ -2157,7 +2157,8 @@ not_null<PhotoData*> Session::processPhoto(
QByteArray(),
small,
thumbnail,
large);
large,
ImageWithLocation{});
}, [&](const MTPDphotoEmpty &data) {
return photo(data.vid().v);
});
@ -2173,7 +2174,8 @@ not_null<PhotoData*> Session::photo(
const QByteArray &inlineThumbnailBytes,
const ImageWithLocation &small,
const ImageWithLocation &thumbnail,
const ImageWithLocation &large) {
const ImageWithLocation &large,
const ImageWithLocation &video) {
const auto result = photo(id);
photoApplyFields(
result,
@ -2185,7 +2187,8 @@ not_null<PhotoData*> Session::photo(
inlineThumbnailBytes,
small,
thumbnail,
large);
large,
video);
return result;
}
@ -2233,7 +2236,8 @@ PhotoData *Session::photoFromWeb(
QByteArray(),
ImageWithLocation{},
ImageWithLocation{ .location = thumbnailLocation },
ImageWithLocation{ .location = large });
ImageWithLocation{ .location = large },
ImageWithLocation{});
}
void Session::photoApplyFields(
@ -2271,6 +2275,22 @@ void Session::photoApplyFields(
? ImageWithLocation()
: Images::FromPhotoSize(_session, data, *i);
};
const auto video = [&] {
const auto sizes = data.vvideo_sizes();
if (!sizes || sizes->v.isEmpty()) {
return ImageWithLocation();
}
const auto area = [](const MTPVideoSize &size) {
return size.match([](const MTPDvideoSize &data) {
return data.vw().v * data.vh().v;
});
};
const auto max = ranges::max_element(
sizes->v,
std::greater<>(),
area);
return Images::FromVideoSize(_session, data, *max);
};
const auto large = image(LargeLevels);
if (large.location.valid()) {
photoApplyFields(
@ -2283,7 +2303,8 @@ void Session::photoApplyFields(
FindPhotoInlineThumbnail(data),
image(SmallLevels),
image(ThumbnailLevels),
large);
large,
video());
}
}
@ -2297,7 +2318,8 @@ void Session::photoApplyFields(
const QByteArray &inlineThumbnailBytes,
const ImageWithLocation &small,
const ImageWithLocation &thumbnail,
const ImageWithLocation &large) {
const ImageWithLocation &large,
const ImageWithLocation &video) {
if (!date) {
return;
}
@ -2308,7 +2330,8 @@ void Session::photoApplyFields(
inlineThumbnailBytes,
small,
thumbnail,
large);
large,
video);
}
not_null<DocumentData*> Session::document(DocumentId id) {

View file

@ -403,7 +403,8 @@ public:
const QByteArray &inlineThumbnailBytes,
const ImageWithLocation &small,
const ImageWithLocation &thumbnail,
const ImageWithLocation &large);
const ImageWithLocation &large,
const ImageWithLocation &video);
void photoConvert(
not_null<PhotoData*> original,
const MTPPhoto &data);
@ -671,7 +672,8 @@ private:
const QByteArray &inlineThumbnailBytes,
const ImageWithLocation &small,
const ImageWithLocation &thumbnail,
const ImageWithLocation &large);
const ImageWithLocation &large,
const ImageWithLocation &video);
void documentApplyFields(
not_null<DocumentData*> document,

View file

@ -268,4 +268,26 @@ ImageWithLocation FromVideoSize(
});
}
ImageWithLocation FromVideoSize(
not_null<Main::Session*> session,
const MTPDphoto &photo,
const MTPVideoSize &size) {
return size.match([&](const MTPDvideoSize &data) {
return ImageWithLocation{
.location = ImageLocation(
DownloadLocation{ StorageFileLocation(
photo.vdc_id().v,
session->userId(),
MTP_inputPhotoFileLocation(
photo.vid(),
photo.vaccess_hash(),
photo.vfile_reference(),
data.vtype())) },
data.vw().v,
data.vh().v),
.bytesCount = data.vsize().v
};
});
}
} // namespace Images

View file

@ -31,6 +31,10 @@ namespace Images {
not_null<Main::Session*> session,
const MTPDdocument &document,
const MTPVideoSize &size);
[[nodiscard]] ImageWithLocation FromVideoSize(
not_null<Main::Session*> session,
const MTPDphoto &photo,
const MTPVideoSize &size);
[[nodiscard]] ImageWithLocation FromImageInMemory(
const QImage &image,
const char *format);