mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/telegramdesktop/tdesktop
synced 2026-09-20 08:03:45 +08:00
Added sending of silent looping video for animated edited photos.
This commit is contained in:
@@ -2584,6 +2584,15 @@ void SendFilesBox::send(
|
||||
|
||||
Storage::ApplyModifications(_list);
|
||||
|
||||
if ((_limits & SendFilesAllow::OnlyOne)
|
||||
&& (_list.files.size() > 1)
|
||||
&& ranges::any_of(_list.files, [](const auto &file) {
|
||||
return file.animationJob != nullptr;
|
||||
})) {
|
||||
showToast(tr::lng_slowmode_no_many(tr::now));
|
||||
return;
|
||||
}
|
||||
|
||||
_confirmed = true;
|
||||
if (_confirmedCallback) {
|
||||
auto caption = fieldText();
|
||||
|
||||
@@ -319,8 +319,9 @@ void Uploader::upload(
|
||||
file->thumbbytes));
|
||||
document->uploadingData = std::make_unique<Data::UploadState>(
|
||||
document->size);
|
||||
preparing = (file->videoTranscodeHeight > 0)
|
||||
&& (!file->content.isEmpty() || !file->filepath.isEmpty());
|
||||
preparing = (file->animationJob != nullptr)
|
||||
|| ((file->videoTranscodeHeight > 0)
|
||||
&& (!file->content.isEmpty() || !file->filepath.isEmpty()));
|
||||
if (preparing) {
|
||||
document->uploadingData->preparing = true;
|
||||
}
|
||||
@@ -386,16 +387,10 @@ void Uploader::startTranscode(FullMsgId itemId) {
|
||||
auto &entry = *i;
|
||||
const auto file = entry.file;
|
||||
const auto height = file->videoTranscodeHeight;
|
||||
const auto job = file->animationJob;
|
||||
const auto cancel = std::make_shared<std::atomic<bool>>(false);
|
||||
entry.cancelPreparing = cancel;
|
||||
crl::async([=, weak = base::make_weak(this)]() mutable {
|
||||
auto source = file->content;
|
||||
if (source.isEmpty() && !file->filepath.isEmpty()) {
|
||||
auto f = QFile(file->filepath);
|
||||
if (f.open(QIODevice::ReadOnly)) {
|
||||
source = f.readAll();
|
||||
}
|
||||
}
|
||||
auto lastReported = -1.;
|
||||
const auto progress = [&](float64 value) {
|
||||
if (value - lastReported >= 0.01 || value >= 1.) {
|
||||
@@ -406,10 +401,36 @@ void Uploader::startTranscode(FullMsgId itemId) {
|
||||
}
|
||||
return !cancel->load();
|
||||
};
|
||||
auto bytes = Media::Encode::TranscodeVideoToMp4(
|
||||
source,
|
||||
height,
|
||||
progress);
|
||||
auto bytes = QByteArray();
|
||||
if (job) {
|
||||
auto result = Media::Encode::Run(
|
||||
Media::Encode::Job(*job),
|
||||
progress);
|
||||
if (result.bytes.isEmpty() && !cancel->load()) {
|
||||
auto fallback = Media::Encode::Job(*job);
|
||||
fallback.overlay.erase(
|
||||
ranges::remove_if(
|
||||
fallback.overlay,
|
||||
[](const Media::Encode::Layer &layer) {
|
||||
return !std::get_if<QImage>(&layer);
|
||||
}),
|
||||
end(fallback.overlay));
|
||||
result = Media::Encode::Run(std::move(fallback), nullptr);
|
||||
}
|
||||
bytes = std::move(result.bytes);
|
||||
} else {
|
||||
auto source = file->content;
|
||||
if (source.isEmpty() && !file->filepath.isEmpty()) {
|
||||
auto f = QFile(file->filepath);
|
||||
if (f.open(QIODevice::ReadOnly)) {
|
||||
source = f.readAll();
|
||||
}
|
||||
}
|
||||
bytes = Media::Encode::TranscodeVideoToMp4(
|
||||
source,
|
||||
height,
|
||||
progress);
|
||||
}
|
||||
crl::on_main(weak, [=, bytes = std::move(bytes)]() mutable {
|
||||
if (!cancel->load()) {
|
||||
finishTranscode(itemId, std::move(bytes));
|
||||
|
||||
@@ -715,6 +715,48 @@ void FileLoadTask::process(ProcessArgs &&args) {
|
||||
}
|
||||
}
|
||||
|
||||
auto animationPreparing = false;
|
||||
if (_animationJob) {
|
||||
const auto still = _forceFile
|
||||
? nullptr
|
||||
: std::get_if<Media::Encode::StillSource>(&_animationJob->source);
|
||||
auto preview = QImage();
|
||||
if (_information) {
|
||||
const auto media = &_information->media;
|
||||
if (const auto image = std::get_if<
|
||||
Ui::PreparedFileInformation::Image>(media)) {
|
||||
preview = std::move(image->data);
|
||||
}
|
||||
}
|
||||
if (still && !still->base.isNull() && still->duration > 0) {
|
||||
if (preview.isNull()) {
|
||||
preview = still->base;
|
||||
} else if (preview.size() != still->base.size()) {
|
||||
preview = preview.scaled(
|
||||
still->base.size(),
|
||||
Qt::IgnoreAspectRatio,
|
||||
Qt::SmoothTransformation);
|
||||
}
|
||||
auto information = std::make_unique<
|
||||
Ui::PreparedFileInformation>();
|
||||
information->filemime = "video/mp4";
|
||||
information->media = Ui::PreparedFileInformation::Video{
|
||||
.isGifv = true,
|
||||
.supportsStreaming = true,
|
||||
.duration = still->duration,
|
||||
.thumbnail = std::move(preview),
|
||||
};
|
||||
_information = std::move(information);
|
||||
_content = QByteArray();
|
||||
_filepath = QString();
|
||||
_type = SendMediaType::File;
|
||||
_displayName = u"animation.mp4"_q;
|
||||
_result->animationJob = _animationJob;
|
||||
animationPreparing = true;
|
||||
}
|
||||
_animationJob = nullptr;
|
||||
}
|
||||
|
||||
QString filename, filemime;
|
||||
qint64 filesize = 0;
|
||||
QByteArray filedata;
|
||||
@@ -759,6 +801,19 @@ void FileLoadTask::process(ProcessArgs &&args) {
|
||||
}
|
||||
isAnimation = image->animated;
|
||||
}
|
||||
} else if (animationPreparing) {
|
||||
const auto video = std::get_if<Ui::PreparedFileInformation::Video>(
|
||||
&_information->media);
|
||||
const auto seconds = std::max(
|
||||
int64(video->duration / 1000),
|
||||
int64(1));
|
||||
filesize = seconds * 200'000;
|
||||
filename = filedialogDefaultName(
|
||||
u"animation"_q,
|
||||
u".mp4"_q,
|
||||
QString(),
|
||||
true);
|
||||
filemime = "video/mp4";
|
||||
} else if (!_content.isEmpty()) {
|
||||
filesize = _content.size();
|
||||
if (isVoice) {
|
||||
|
||||
@@ -211,6 +211,7 @@ struct FilePrepareResult {
|
||||
bool spoiler = false;
|
||||
bool forceFile = false;
|
||||
int videoTranscodeHeight = 0;
|
||||
std::shared_ptr<Media::Encode::Job> animationJob;
|
||||
|
||||
std::vector<MTPInputDocument> attachedStickers;
|
||||
|
||||
|
||||
@@ -135,10 +135,12 @@ struct HighQualityBadgeCache {
|
||||
auto from = 0;
|
||||
auto groupType = AlbumType::None;
|
||||
for (auto i = 0; i != int(files.size()); ++i) {
|
||||
const auto fileGroupType = GroupTypeForFile(
|
||||
files[i].type,
|
||||
groupFiles,
|
||||
sendImagesAsPhotos);
|
||||
const auto fileGroupType = files[i].animationJob
|
||||
? AlbumType::None
|
||||
: GroupTypeForFile(
|
||||
files[i].type,
|
||||
groupFiles,
|
||||
sendImagesAsPhotos);
|
||||
const auto count = (i - from);
|
||||
if ((i > from && groupType != fileGroupType)
|
||||
|| ((groupType != AlbumType::None) && (count == kMaxAlbumCount))) {
|
||||
|
||||
Reference in New Issue
Block a user