Compare commits

...

10 Commits

Author SHA1 Message Date
John Preston
8f8725e1af Beta version 4.16.3: Fix dav1d in FFmpeg on macOS. 2024-04-05 21:25:20 +04:00
John Preston
0ce6a4cbdb Beta version 4.16.3: Re-enable system proxy (Linux).
This reverts commit 1e6fb202f0.
2024-04-05 20:48:06 +04:00
John Preston
ad3f705f50 Beta version 4.16.3.
- Improve media upload speed.
- Update FFmpeg to 6.1.1.
2024-04-05 15:35:01 +04:00
John Preston
c5847caa91 Update FFmpeg to 6.1.1: Fix AV1 videos. 2024-04-05 14:42:29 +04:00
John Preston
8df6d9db7e Don't update server-time too frequently. 2024-04-05 09:51:20 +04:00
John Preston
a9c1970f41 Send up to 1MB of parts to a single session. 2024-04-05 09:51:20 +04:00
John Preston
c3f0d2ef31 Adaptive upload up to 8 sessions. 2024-04-05 09:51:20 +04:00
John Preston
0dcc439dda Allow upload requests for several files at once. 2024-04-05 09:51:20 +04:00
John Preston
5b0cac47ad Reapply "Use plain vector for prepared upload parts."
This reverts commit f6f8eefaa0.
2024-04-05 09:51:20 +04:00
John Preston
b39e78a4a9 Reapply "Remove SendMediaReady legacy helper."
This reverts commit 09f07a7a9d.
2024-04-05 09:51:20 +04:00
29 changed files with 880 additions and 776 deletions

View File

@@ -10,7 +10,7 @@
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
ProcessorArchitecture="ARCHITECTURE"
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
Version="4.16.2.0" />
Version="4.16.3.0" />
<Properties>
<DisplayName>Telegram Desktop</DisplayName>
<PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName>

View File

@@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,16,2,0
PRODUCTVERSION 4,16,2,0
FILEVERSION 4,16,3,0
PRODUCTVERSION 4,16,3,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -62,10 +62,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Telegram FZ-LLC"
VALUE "FileDescription", "Telegram Desktop"
VALUE "FileVersion", "4.16.2.0"
VALUE "FileVersion", "4.16.3.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2024"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "4.16.2.0"
VALUE "ProductVersion", "4.16.3.0"
END
END
BLOCK "VarFileInfo"

View File

@@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,16,2,0
PRODUCTVERSION 4,16,2,0
FILEVERSION 4,16,3,0
PRODUCTVERSION 4,16,3,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -53,10 +53,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Telegram FZ-LLC"
VALUE "FileDescription", "Telegram Desktop Updater"
VALUE "FileVersion", "4.16.2.0"
VALUE "FileVersion", "4.16.3.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2024"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "4.16.2.0"
VALUE "ProductVersion", "4.16.3.0"
END
END
BLOCK "VarFileInfo"

View File

@@ -34,7 +34,7 @@ namespace {
constexpr auto kSharedMediaLimit = 100;
[[nodiscard]] SendMediaReady PreparePeerPhoto(
[[nodiscard]] std::shared_ptr<FilePrepareResult> PreparePeerPhoto(
MTP::DcId dcId,
PeerId peerId,
QImage &&image) {
@@ -80,24 +80,17 @@ constexpr auto kSharedMediaLimit = 100;
MTPVector<MTPVideoSize>(),
MTP_int(dcId));
QString file, filename;
int64 filesize = 0;
QByteArray data;
return SendMediaReady(
SendMediaType::Photo,
file,
filename,
filesize,
data,
id,
id,
u"jpg"_q,
peerId,
photo,
photoThumbs,
MTP_documentEmpty(MTP_long(0)),
jpeg);
auto result = MakePreparedFile({
.id = id,
.type = SendMediaType::Photo,
});
result->type = SendMediaType::Photo;
result->setFileData(jpeg);
result->thumbId = id;
result->thumbname = "thumb.jpg";
result->photo = photo;
result->photoThumbs = photoThumbs;
return result;
}
[[nodiscard]] std::optional<MTPVideoSize> PrepareMtpMarkup(
@@ -239,7 +232,7 @@ void PeerPhoto::upload(
_api.instance().mainDcId(),
peer->id,
base::take(photo.image));
_session->uploader().uploadMedia(fakeId, ready);
_session->uploader().upload(fakeId, ready);
}
}

View File

@@ -24,16 +24,25 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Api {
namespace {
SendMediaReady PrepareRingtoneDocument(
std::shared_ptr<FilePrepareResult> PrepareRingtoneDocument(
MTP::DcId dcId,
const QString &filename,
const QString &filemime,
const QByteArray &content) {
const auto id = base::RandomValue<DocumentId>();
auto attributes = QVector<MTPDocumentAttribute>(
1,
MTP_documentAttributeFilename(MTP_string(filename)));
const auto id = base::RandomValue<DocumentId>();
const auto document = MTP_document(
auto result = MakePreparedFile({
.id = id,
.type = SendMediaType::File,
});
result->filename = filename;
result->content = content;
result->filesize = content.size();
result->setFileData(content);
result->document = MTP_document(
MTP_flags(0),
MTP_long(id),
MTP_long(0),
@@ -45,21 +54,7 @@ SendMediaReady PrepareRingtoneDocument(
MTPVector<MTPVideoSize>(),
MTP_int(dcId),
MTP_vector<MTPDocumentAttribute>(std::move(attributes)));
return SendMediaReady(
SendMediaType::File,
QString(), // filepath
filename,
content.size(),
content,
id,
0,
QString(),
PeerId(),
MTP_photoEmpty(MTP_long(0)),
PreparedPhotoThumbs(),
document,
QByteArray());
return result;
}
} // namespace
@@ -102,7 +97,7 @@ void Ringtones::upload(
_uploads.erase(already);
}
_uploads.emplace(fakeId, uploadedData);
_session->uploader().uploadMedia(fakeId, ready);
_session->uploader().upload(fakeId, ready);
}
void Ringtones::ready(const FullMsgId &msgId, const MTPInputFile &file) {

View File

@@ -353,7 +353,7 @@ void FillMessagePostFlags(
void SendConfirmedFile(
not_null<Main::Session*> session,
const std::shared_ptr<FileLoadResult> &file) {
const std::shared_ptr<FilePrepareResult> &file) {
const auto isEditing = (file->type != SendMediaType::Audio)
&& (file->to.replaceMediaOf != 0);
const auto newId = FullMsgId(

View File

@@ -14,7 +14,7 @@ class Session;
class History;
class PhotoData;
class DocumentData;
struct FileLoadResult;
struct FilePrepareResult;
namespace Api {
@@ -40,6 +40,6 @@ void FillMessagePostFlags(
void SendConfirmedFile(
not_null<Main::Session*> session,
const std::shared_ptr<FileLoadResult> &file);
const std::shared_ptr<FilePrepareResult> &file);
} // namespace Api

View File

@@ -593,11 +593,11 @@ void BackgroundPreviewBox::uploadForPeer(bool both) {
const auto ready = Window::Theme::PrepareWallPaper(
session->mainDcId(),
_paper.localThumbnail()->original());
const auto documentId = ready.id;
const auto documentId = ready->id;
_uploadId = FullMsgId(
session->userPeerId(),
session->data().nextLocalMessageId());
session->uploader().uploadMedia(_uploadId, ready);
session->uploader().upload(_uploadId, ready);
if (_uploadLifetime) {
return;
}

View File

@@ -33,7 +33,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtGui/QSessionManager>
#include <QtGui/QScreen>
#include <QtGui/qpa/qplatformscreen.h>
#include <ksandbox.h>
namespace Core {
namespace {
@@ -518,10 +517,8 @@ void Sandbox::refreshGlobalProxy() {
|| proxy.type == MTP::ProxyData::Type::Http) {
QNetworkProxy::setApplicationProxy(
MTP::ToNetworkProxy(MTP::ToDirectIpProxy(proxy)));
} else if ((!Core::IsAppLaunched()
|| Core::App().settings().proxy().isSystem())
// this works stable only in sandboxed environment where it works through portal
&& (!Platform::IsLinux() || KSandbox::isInside() || cDebugMode())) {
} else if (!Core::IsAppLaunched()
|| Core::App().settings().proxy().isSystem()) {
QNetworkProxyFactory::setUseSystemConfiguration(true);
} else {
QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy);

View File

@@ -22,7 +22,7 @@ constexpr auto AppId = "{53F49750-6209-4FBF-9CA8-7A333C87D1ED}"_cs;
constexpr auto AppNameOld = "Telegram Win (Unofficial)"_cs;
constexpr auto AppName = "Telegram Desktop"_cs;
constexpr auto AppFile = "Telegram"_cs;
constexpr auto AppVersion = 4016002;
constexpr auto AppVersionStr = "4.16.2";
constexpr auto AppBetaVersion = false;
constexpr auto AppVersion = 4016003;
constexpr auto AppVersionStr = "4.16.3";
constexpr auto AppBetaVersion = true;
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;

View File

@@ -18,7 +18,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/fields/input_field.h"
#include "mtproto/sender.h"
struct FileLoadResult;
enum class SendMediaType;
class MessageLinksParser;
struct InlineBotQuery;

View File

@@ -25,7 +25,7 @@ QByteArray GeoPointId(Geo point) {
const auto lon = int(point.lon * 1000000);
const auto combined = (std::uint64_t(std::uint32_t(lat)) << 32)
| std::uint64_t(std::uint32_t(lon));
return QByteArray::number(combined)
return QByteArray::number(quint64(combined))
+ ','
+ QByteArray::number(point.access);
}

View File

@@ -16,7 +16,6 @@ struct HistoryMessageMarkupButton;
class MainWindow;
class HistoryWidget;
class StackItem;
struct FileLoadResult;
class History;
class Image;

View File

@@ -40,8 +40,6 @@ constexpr ShiftedDcId groupCallStreamDcId(DcId dcId) {
return ShiftDcId(dcId, kGroupCallStreamDcShift);
}
constexpr auto kUploadSessionsCount = 2;
namespace details {
constexpr ShiftedDcId downloadDcId(DcId dcId, int index) {
@@ -92,7 +90,6 @@ inline DcId getTemporaryIdFromRealDcId(ShiftedDcId shiftedDcId) {
namespace details {
constexpr ShiftedDcId uploadDcId(DcId dcId, int index) {
static_assert(kUploadSessionsCount < kMaxMediaDcCount, "Too large MTPUploadSessionsCount!");
return ShiftDcId(dcId, kBaseUploadDcShift + index);
};
@@ -101,14 +98,14 @@ constexpr ShiftedDcId uploadDcId(DcId dcId, int index) {
// send(req, callbacks, MTP::uploadDcId(index)) - for upload shifted dc id
// uploading always to the main dc so BareDcId(result) == 0
inline ShiftedDcId uploadDcId(int index) {
Expects(index >= 0 && index < kUploadSessionsCount);
Expects(index >= 0 && index < kMaxMediaDcCount);
return details::uploadDcId(0, index);
};
constexpr bool isUploadDcId(ShiftedDcId shiftedDcId) {
return (shiftedDcId >= details::uploadDcId(0, 0))
&& (shiftedDcId < details::uploadDcId(0, kUploadSessionsCount - 1) + kDcShift);
&& (shiftedDcId < details::uploadDcId(0, kMaxMediaDcCount - 1) + kDcShift);
}
inline ShiftedDcId destroyKeyNextDcId(ShiftedDcId shiftedDcId) {

View File

@@ -60,6 +60,8 @@ constexpr auto kSendStateRequestWaiting = crl::time(1000);
// How much time to wait for some more requests, when sending msg acks.
constexpr auto kAckSendWaiting = 10 * crl::time(1000);
constexpr auto kCutContainerOnSize = 16 * 1024;
auto SyncTimeRequestDuration = kFastRequestDuration;
using namespace details;
@@ -696,7 +698,8 @@ void SessionPrivate::tryToSend() {
initSize = initSizeInInts * sizeof(mtpPrime);
}
bool needAnyResponse = false;
auto needAnyResponse = false;
auto someSkipped = false;
SerializedRequest toSendRequest;
{
QWriteLocker locker1(_sessionData->toSendMutex());
@@ -711,15 +714,33 @@ void SessionPrivate::tryToSend() {
locker1.unlock();
}
uint32 toSendCount = toSend.size();
if (pingRequest) ++toSendCount;
if (ackRequest) ++toSendCount;
if (resendRequest) ++toSendCount;
if (stateRequest) ++toSendCount;
if (httpWaitRequest) ++toSendCount;
if (bindDcKeyRequest) ++toSendCount;
auto totalSending = int(toSend.size());
auto sendingFrom = begin(toSend);
auto sendingTill = end(toSend);
auto combinedLength = 0;
for (auto i = sendingFrom; i != sendingTill; ++i) {
combinedLength += i->second->size();
if (combinedLength >= kCutContainerOnSize) {
++i;
if (const auto skipping = int(sendingTill - i)) {
sendingTill = i;
totalSending -= skipping;
Assert(totalSending > 0);
someSkipped = true;
}
break;
}
}
auto sendingRange = ranges::make_subrange(sendingFrom, sendingTill);
const auto sendingCount = totalSending;
if (pingRequest) ++totalSending;
if (ackRequest) ++totalSending;
if (resendRequest) ++totalSending;
if (stateRequest) ++totalSending;
if (httpWaitRequest) ++totalSending;
if (bindDcKeyRequest) ++totalSending;
if (!toSendCount) {
if (!totalSending) {
return; // nothing to send
}
@@ -735,11 +756,11 @@ void SessionPrivate::tryToSend() {
? httpWaitRequest
: bindDcKeyRequest
? bindDcKeyRequest
: toSend.begin()->second;
if (toSendCount == 1 && !first->forceSendInContainer) {
: sendingRange.begin()->second;
if (totalSending == 1 && !first->forceSendInContainer) {
toSendRequest = first;
if (sendAll) {
toSend.clear();
toSend.erase(sendingFrom, sendingTill);
locker1.unlock();
}
@@ -808,7 +829,7 @@ void SessionPrivate::tryToSend() {
if (stateRequest) containerSize += stateRequest.messageSize();
if (httpWaitRequest) containerSize += httpWaitRequest.messageSize();
if (bindDcKeyRequest) containerSize += bindDcKeyRequest.messageSize();
for (const auto &[requestId, request] : toSend) {
for (const auto &[requestId, request] : sendingRange) {
containerSize += request.messageSize();
if (needsLayer && request->needsLayer) {
containerSize += initSizeInInts;
@@ -825,9 +846,9 @@ void SessionPrivate::tryToSend() {
// prepare container + each in invoke after
toSendRequest = SerializedRequest::Prepare(
containerSize,
containerSize + 3 * toSend.size());
containerSize + 3 * sendingCount);
toSendRequest->push_back(mtpc_msg_container);
toSendRequest->push_back(toSendCount);
toSendRequest->push_back(totalSending);
// check for a valid container
auto bigMsgId = base::unixtime::mtproto_msg_id();
@@ -839,7 +860,7 @@ void SessionPrivate::tryToSend() {
// prepare sent container
auto sentIdsWrap = SentContainer();
sentIdsWrap.sent = crl::now();
sentIdsWrap.messages.reserve(toSendCount);
sentIdsWrap.messages.reserve(totalSending);
if (bindDcKeyRequest) {
_bindMsgId = placeToContainer(
@@ -859,7 +880,7 @@ void SessionPrivate::tryToSend() {
needAnyResponse = true;
}
for (auto &[requestId, request] : toSend) {
for (auto &[requestId, request] : sendingRange) {
const auto msgId = prepareToSend(
request,
bigMsgId,
@@ -904,7 +925,7 @@ void SessionPrivate::tryToSend() {
memcpy(toSendRequest->data() + from, request->constData() + 4, len * sizeof(mtpPrime));
}
}
toSend.clear();
toSend.erase(sendingFrom, sendingTill);
if (stateRequest) {
const auto msgId = placeToContainer(
@@ -951,6 +972,11 @@ void SessionPrivate::tryToSend() {
}
}
sendSecureRequest(std::move(toSendRequest), needAnyResponse);
if (someSkipped) {
InvokeQueued(this, [=] {
tryToSend();
});
}
}
void SessionPrivate::retryByTimer() {
@@ -1108,9 +1134,6 @@ void SessionPrivate::onSentSome(uint64 size) {
DEBUG_LOG(("Checking connect for request with size %1 bytes, delay will be %2").arg(size).arg(remain));
}
}
if (isUploadDcId(_shiftedDcId)) {
remain *= kUploadSessionsCount;
}
_waitForReceivedTimer.callOnce(remain);
}
if (!_firstSentAt) {
@@ -1628,7 +1651,9 @@ SessionPrivate::HandleResult SessionPrivate::handleOneReceived(
}
_sessionSalt = data.vnew_server_salt().v;
correctUnixtimeWithBadLocal(info.serverTime);
// Don't force time update here.
base::unixtime::update(info.serverTime);
if (_bindMsgId) {
LOG(("Message Info: bad_server_salt received while binding temp key, restarting."));
@@ -2056,7 +2081,7 @@ void SessionPrivate::correctUnixtimeByFastRequest(
locker.unlock();
SyncTimeRequestDuration = duration;
base::unixtime::update(serverTime, true);
base::unixtime::update(serverTime);
return;
}
}

View File

@@ -1581,14 +1581,10 @@ void FormController::uploadEncryptedFile(
&session(),
std::make_unique<UploadScanData>(std::move(data)));
auto prepared = std::make_shared<FileLoadResult>(
TaskId(),
file.uploadData->fileId,
FileLoadTo(PeerId(), Api::SendOptions(), FullReplyTo(), MsgId()),
TextWithTags(),
false,
std::shared_ptr<SendingAlbum>(nullptr));
prepared->type = SendMediaType::Secure;
auto prepared = MakePreparedFile({
.id = file.uploadData->fileId,
.type = SendMediaType::Secure,
});
prepared->content = QByteArray::fromRawData(
reinterpret_cast<char*>(file.uploadData->bytes.data()),
file.uploadData->bytes.size());

File diff suppressed because it is too large Load Diff

View File

@@ -9,11 +9,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_common.h"
#include "base/timer.h"
#include "base/weak_ptr.h"
#include "mtproto/facade.h"
class ApiWrap;
struct FileLoadResult;
struct SendMediaReady;
struct FilePrepareResult;
namespace Api {
enum class SendProgressType;
@@ -47,54 +47,48 @@ struct UploadSecureDone {
int partsCount = 0;
};
class Uploader final : public QObject {
class Uploader final : public base::has_weak_ptr {
public:
explicit Uploader(not_null<ApiWrap*> api);
~Uploader();
[[nodiscard]] Main::Session &session() const;
[[nodiscard]] FullMsgId currentUploadId() const;
[[nodiscard]] FullMsgId currentUploadId() const {
return uploadingId;
}
void uploadMedia(const FullMsgId &msgId, const SendMediaReady &image);
void upload(
const FullMsgId &msgId,
const std::shared_ptr<FileLoadResult> &file);
void cancel(const FullMsgId &msgId);
void pause(const FullMsgId &msgId);
void confirm(const FullMsgId &msgId);
FullMsgId itemId,
const std::shared_ptr<FilePrepareResult> &file);
void pause(FullMsgId itemId);
void cancel(FullMsgId itemId);
void cancelAll();
void clear();
rpl::producer<UploadedMedia> photoReady() const {
[[nodiscard]] rpl::producer<UploadedMedia> photoReady() const {
return _photoReady.events();
}
rpl::producer<UploadedMedia> documentReady() const {
[[nodiscard]] rpl::producer<UploadedMedia> documentReady() const {
return _documentReady.events();
}
rpl::producer<UploadSecureDone> secureReady() const {
[[nodiscard]] rpl::producer<UploadSecureDone> secureReady() const {
return _secureReady.events();
}
rpl::producer<FullMsgId> photoProgress() const {
[[nodiscard]] rpl::producer<FullMsgId> photoProgress() const {
return _photoProgress.events();
}
rpl::producer<FullMsgId> documentProgress() const {
[[nodiscard]] rpl::producer<FullMsgId> documentProgress() const {
return _documentProgress.events();
}
rpl::producer<UploadSecureProgress> secureProgress() const {
[[nodiscard]] auto secureProgress() const
-> rpl::producer<UploadSecureProgress> {
return _secureProgress.events();
}
rpl::producer<FullMsgId> photoFailed() const {
[[nodiscard]] rpl::producer<FullMsgId> photoFailed() const {
return _photoFailed.events();
}
rpl::producer<FullMsgId> documentFailed() const {
[[nodiscard]] rpl::producer<FullMsgId> documentFailed() const {
return _documentFailed.events();
}
rpl::producer<FullMsgId> secureFailed() const {
[[nodiscard]] rpl::producer<FullMsgId> secureFailed() const {
return _secureFailed.events();
}
@@ -103,23 +97,53 @@ public:
}
void unpause();
void sendNext();
void stopSessions();
private:
struct File;
struct Entry;
struct Request;
enum class SendResult : uchar {
Success,
Failed,
DcIndexFull,
};
void maybeSend();
[[nodiscard]] bool canAddDcIndex() const;
[[nodiscard]] std::optional<uchar> chooseDcIndexForNextRequest(
const base::flat_set<uchar> &used);
[[nodiscard]] Entry *chooseEntryForNextRequest();
[[nodiscard]] SendResult sendPart(not_null<Entry*> entry, uchar dcIndex);
[[nodiscard]] auto sendPendingPart(not_null<Entry*> entry, uchar dcIndex)
-> SendResult;
[[nodiscard]] auto sendDocPart(not_null<Entry*> entry, uchar dcIndex)
-> SendResult;
[[nodiscard]] auto sendSlicedPart(not_null<Entry*> entry, uchar dcIndex)
-> SendResult;
[[nodiscard]] QByteArray readDocPart(not_null<Entry*> entry);
void removeDcIndex();
template <typename Prepared>
void sendPreparedRequest(Prepared &&prepared, Request &&request);
void maybeFinishFront();
void finishFront();
void partLoaded(const MTPBool &result, mtpRequestId requestId);
void partFailed(const MTP::Error &error, mtpRequestId requestId);
Request finishRequest(mtpRequestId requestId);
void processPhotoProgress(const FullMsgId &msgId);
void processPhotoFailed(const FullMsgId &msgId);
void processDocumentProgress(const FullMsgId &msgId);
void processDocumentFailed(const FullMsgId &msgId);
void processPhotoProgress(FullMsgId itemId);
void processPhotoFailed(FullMsgId itemId);
void processDocumentProgress(FullMsgId itemId);
void processDocumentFailed(FullMsgId itemId);
void notifyFailed(FullMsgId id, const File &file);
void currentFailed();
void cancelRequests();
void notifyFailed(const Entry &entry);
void failed(FullMsgId itemId);
void cancelRequests(FullMsgId itemId);
void cancelAllRequests();
void clear();
void sendProgressUpdate(
not_null<HistoryItem*> item,
@@ -127,16 +151,19 @@ private:
int progress = 0);
const not_null<ApiWrap*> _api;
base::flat_map<mtpRequestId, QByteArray> requestsSent;
base::flat_map<mtpRequestId, int32> docRequestsSent;
base::flat_map<mtpRequestId, int32> dcMap;
base::flat_set<mtpRequestId> _nonPremiumDelayed;
uint32 sentSize = 0; // FileSize: Right now any file size fits 32 bit.
uint32 sentSizes[MTP::kUploadSessionsCount] = { 0 };
FullMsgId uploadingId;
std::vector<Entry> _queue;
base::flat_map<mtpRequestId, Request> _requests;
std::vector<int> _sentPerDcIndex;
// Fast requests since the latest dc index addition.
base::flat_set<uchar> _dcIndicesWithFastRequests;
crl::time _latestDcIndexAdded = 0;
crl::time _latestDcIndexRemoved = 0;
std::vector<Request> _pendingFromRemovedDcIndices;
FullMsgId _pausedId;
std::map<FullMsgId, File> queue;
base::Timer _nextTimer, _stopSessionsTimer;
rpl::event_stream<UploadedMedia> _photoReady;

View File

@@ -222,42 +222,6 @@ int PhotoSideLimit() {
return PhotoSideLimit(SendLargePhotos.value());
}
SendMediaReady::SendMediaReady(
SendMediaType type,
const QString &file,
const QString &filename,
int64 filesize,
const QByteArray &data,
const uint64 &id,
const uint64 &thumbId,
const QString &thumbExt,
const PeerId &peer,
const MTPPhoto &photo,
const PreparedPhotoThumbs &photoThumbs,
const MTPDocument &document,
const QByteArray &jpeg)
: type(type)
, file(file)
, filename(filename)
, filesize(filesize)
, data(data)
, thumbExt(thumbExt)
, id(id)
, thumbId(thumbId)
, peer(peer)
, photo(photo)
, document(document)
, photoThumbs(photoThumbs) {
if (!jpeg.isEmpty()) {
int32 size = jpeg.size();
for (int32 i = 0, part = 0; i < size; i += kPhotoUploadPartSize, ++part) {
parts.insert(part, jpeg.mid(i, kPhotoUploadPartSize));
}
jpeg_md5.resize(32);
hashMd5Hex(jpeg.constData(), jpeg.size(), jpeg_md5.data());
}
}
TaskQueue::TaskQueue(crl::time stopTimeoutMs) {
if (stopTimeoutMs > 0) {
_stopTimer = new QTimer(this);
@@ -455,46 +419,50 @@ SendingAlbum::Item::Item(TaskId taskId)
: taskId(taskId) {
}
FileLoadResult::FileLoadResult(
TaskId taskId,
uint64 id,
const FileLoadTo &to,
const TextWithTags &caption,
bool spoiler,
std::shared_ptr<SendingAlbum> album)
: taskId(taskId)
, id(id)
, to(to)
, album(std::move(album))
, caption(caption)
, spoiler(spoiler) {
FilePrepareResult::FilePrepareResult(FilePrepareDescriptor &&descriptor)
: taskId(descriptor.taskId)
, id(descriptor.id)
, to(std::move(descriptor.to))
, album(std::move(descriptor.album))
, type(descriptor.type)
, caption(std::move(descriptor.caption))
, spoiler(descriptor.spoiler) {
}
void FileLoadResult::setFileData(const QByteArray &filedata) {
void FilePrepareResult::setFileData(const QByteArray &filedata) {
if (filedata.isEmpty()) {
partssize = 0;
} else {
partssize = filedata.size();
fileparts.reserve(
(partssize + kPhotoUploadPartSize - 1) / kPhotoUploadPartSize);
for (int32 i = 0, part = 0; i < partssize; i += kPhotoUploadPartSize, ++part) {
fileparts.insert(part, filedata.mid(i, kPhotoUploadPartSize));
fileparts.push_back(filedata.mid(i, kPhotoUploadPartSize));
}
filemd5.resize(32);
hashMd5Hex(filedata.constData(), filedata.size(), filemd5.data());
}
}
void FileLoadResult::setThumbData(const QByteArray &thumbdata) {
void FilePrepareResult::setThumbData(const QByteArray &thumbdata) {
if (!thumbdata.isEmpty()) {
thumbbytes = thumbdata;
int32 size = thumbdata.size();
thumbparts.reserve(
(size + kPhotoUploadPartSize - 1) / kPhotoUploadPartSize);
for (int32 i = 0, part = 0; i < size; i += kPhotoUploadPartSize, ++part) {
thumbparts.insert(part, thumbdata.mid(i, kPhotoUploadPartSize));
thumbparts.push_back(thumbdata.mid(i, kPhotoUploadPartSize));
}
thumbmd5.resize(32);
hashMd5Hex(thumbdata.constData(), thumbdata.size(), thumbmd5.data());
}
}
std::shared_ptr<FilePrepareResult> MakePreparedFile(
FilePrepareDescriptor &&descriptor) {
return std::make_shared<FilePrepareResult>(std::move(descriptor));
}
FileLoadTask::FileLoadTask(
not_null<Main::Session*> session,
const QString &filepath,
@@ -710,13 +678,14 @@ bool FileLoadTask::FillImageInformation(
}
void FileLoadTask::process(Args &&args) {
_result = std::make_shared<FileLoadResult>(
id(),
_id,
_to,
_caption,
_spoiler,
_album);
_result = MakePreparedFile({
.taskId = id(),
.id = _id,
.to = _to,
.caption = _caption,
.spoiler = _spoiler,
.album = _album,
});
QString filename, filemime;
qint64 filesize = 0;
@@ -1062,7 +1031,7 @@ void FileLoadTask::finish() {
}
}
FileLoadResult *FileLoadTask::peekResult() const {
FilePrepareResult *FileLoadTask::peekResult() const {
return _result.get();
}

View File

@@ -36,43 +36,8 @@ enum class SendMediaType {
Secure,
};
using UploadFileParts = QMap<int, QByteArray>;
struct SendMediaReady {
SendMediaReady() = default; // temp
SendMediaReady(
SendMediaType type,
const QString &file,
const QString &filename,
int64 filesize,
const QByteArray &data,
const uint64 &id,
const uint64 &thumbId,
const QString &thumbExt,
const PeerId &peer,
const MTPPhoto &photo,
const PreparedPhotoThumbs &photoThumbs,
const MTPDocument &document,
const QByteArray &jpeg);
SendMediaType type;
QString file, filename;
int64 filesize = 0;
QByteArray data;
QString thumbExt;
uint64 id, thumbId; // id always file-id of media, thumbId is file-id of thumb ( == id for photos)
PeerId peer;
MTPPhoto photo;
MTPDocument document;
PreparedPhotoThumbs photoThumbs;
UploadFileParts parts;
QByteArray jpeg_md5;
QString caption;
};
using TaskId = void*; // no interface, just id
inline constexpr auto kEmptyTaskId = TaskId();
class Task {
public:
@@ -144,7 +109,7 @@ struct SendingAlbum {
struct Item {
explicit Item(TaskId taskId);
TaskId taskId;
TaskId taskId = kEmptyTaskId;
uint64 randomId = 0;
FullMsgId msgId;
std::optional<MTPInputSingleMedia> media;
@@ -182,17 +147,21 @@ struct FileLoadTo {
MsgId replaceMediaOf;
};
struct FileLoadResult {
FileLoadResult(
TaskId taskId,
uint64 id,
const FileLoadTo &to,
const TextWithTags &caption,
bool spoiler,
std::shared_ptr<SendingAlbum> album);
using UploadFileParts = std::vector<QByteArray>;
struct FilePrepareDescriptor {
TaskId taskId = kEmptyTaskId;
base::required<uint64> id;
SendMediaType type = SendMediaType::File;
FileLoadTo to = { PeerId(), Api::SendOptions(), FullReplyTo(), MsgId() };
TextWithTags caption;
bool spoiler = false;
std::shared_ptr<SendingAlbum> album;
};
struct FilePrepareResult {
explicit FilePrepareResult(FilePrepareDescriptor &&descriptor);
TaskId taskId;
uint64 id;
TaskId taskId = kEmptyTaskId;
uint64 id = 0;
FileLoadTo to;
std::shared_ptr<SendingAlbum> album;
SendMediaType type = SendMediaType::File;
@@ -216,8 +185,8 @@ struct FileLoadResult {
QImage goodThumbnail;
QByteArray goodThumbnailBytes;
MTPPhoto photo;
MTPDocument document;
MTPPhoto photo = MTP_photoEmpty(MTP_long(0));
MTPDocument document = MTP_documentEmpty(MTP_long(0));
PreparedPhotoThumbs photoThumbs;
TextWithTags caption;
@@ -230,6 +199,9 @@ struct FileLoadResult {
};
[[nodiscard]] std::shared_ptr<FilePrepareResult> MakePreparedFile(
FilePrepareDescriptor &&descriptor);
class FileLoadTask final : public Task {
public:
static std::unique_ptr<Ui::PreparedFileInformation> ReadMediaInformation(
@@ -276,7 +248,7 @@ public:
}
void finish() override;
FileLoadResult *peekResult() const;
FilePrepareResult *peekResult() const;
private:
static bool CheckForSong(
@@ -312,6 +284,6 @@ private:
TextWithTags _caption;
bool _spoiler = false;
std::shared_ptr<FileLoadResult> _result;
std::shared_ptr<FilePrepareResult> _result;
};

View File

@@ -585,11 +585,11 @@ void ChatBackground::checkUploadWallPaper() {
}
const auto ready = PrepareWallPaper(_session->mainDcId(), _original);
const auto documentId = ready.id;
const auto documentId = ready->id;
_wallPaperUploadId = FullMsgId(
_session->userPeerId(),
_session->data().nextLocalMessageId());
_session->uploader().uploadMedia(_wallPaperUploadId, ready);
_session->uploader().upload(_wallPaperUploadId, ready);
if (_wallPaperUploadLifetime) {
return;
}
@@ -1529,7 +1529,9 @@ bool ReadPaletteValues(const QByteArray &content, Fn<bool(QLatin1String name, QL
};
}
SendMediaReady PrepareWallPaper(MTP::DcId dcId, const QImage &image) {
std::shared_ptr<FilePrepareResult> PrepareWallPaper(
MTP::DcId dcId,
const QImage &image) {
PreparedPhotoThumbs thumbnails;
QVector<MTPPhotoSize> sizes;
@@ -1555,6 +1557,7 @@ SendMediaReady PrepareWallPaper(MTP::DcId dcId, const QImage &image) {
};
push("s", scaled(320));
const auto id = base::RandomValue<DocumentId>();
const auto filename = u"wallpaper.jpg"_q;
auto attributes = QVector<MTPDocumentAttribute>(
1,
@@ -1562,8 +1565,20 @@ SendMediaReady PrepareWallPaper(MTP::DcId dcId, const QImage &image) {
attributes.push_back(MTP_documentAttributeImageSize(
MTP_int(image.width()),
MTP_int(image.height())));
const auto id = base::RandomValue<DocumentId>();
const auto document = MTP_document(
auto result = MakePreparedFile({
.id = id,
.type = SendMediaType::ThemeFile,
});
result->filename = filename;
result->content = jpeg;
result->filesize = jpeg.size();
result->setFileData(jpeg);
if (thumbnails.empty()) {
result->thumb = thumbnails.front().second.image;
result->thumbbytes = thumbnails.front().second.bytes;
}
result->document = MTP_document(
MTP_flags(0),
MTP_long(id),
MTP_long(0),
@@ -1575,21 +1590,7 @@ SendMediaReady PrepareWallPaper(MTP::DcId dcId, const QImage &image) {
MTPVector<MTPVideoSize>(),
MTP_int(dcId),
MTP_vector<MTPDocumentAttribute>(attributes));
return SendMediaReady(
SendMediaType::ThemeFile,
QString(), // filepath
filename,
jpeg.size(),
jpeg,
id,
0,
QString(),
PeerId(),
MTP_photoEmpty(MTP_long(0)),
thumbnails,
document,
QByteArray());
return result;
}
std::unique_ptr<Ui::ChatTheme> DefaultChatThemeOn(rpl::lifetime &lifetime) {

View File

@@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/style/style_core_palette.h"
class QFileSystemWatcher;
struct SendMediaReady;
struct FilePrepareResult;
namespace style {
struct colorizer;
@@ -298,7 +298,7 @@ private:
};
[[nodiscard]] SendMediaReady PrepareWallPaper(
[[nodiscard]] std::shared_ptr<FilePrepareResult> PrepareWallPaper(
MTP::DcId dcId,
const QImage &image);

View File

@@ -385,7 +385,7 @@ bool CopyColorsToPalette(
});
}
SendMediaReady PrepareThemeMedia(
std::shared_ptr<FilePrepareResult> PrepareThemeMedia(
MTP::DcId dcId,
const QString &name,
const QByteArray &content) {
@@ -403,28 +403,29 @@ SendMediaReady PrepareThemeMedia(
thumbnail.save(&buffer, "JPG", 87);
}
const auto push = [&](
const char *type,
QImage &&image,
QByteArray bytes = QByteArray()) {
sizes.push_back(MTP_photoSize(
MTP_string(type),
MTP_int(image.width()),
MTP_int(image.height()), MTP_int(0)));
thumbnails.emplace(type[0], PreparedPhotoThumb{
.image = std::move(image),
.bytes = std::move(bytes)
});
};
push("s", std::move(thumbnail), thumbnailBytes);
sizes.push_back(MTP_photoSize(
MTP_string("s"),
MTP_int(thumbnail.width()),
MTP_int(thumbnail.height()), MTP_int(0)));
const auto id = base::RandomValue<DocumentId>();
const auto filename = base::FileNameFromUserString(name)
+ u".tdesktop-theme"_q;
auto attributes = QVector<MTPDocumentAttribute>(
1,
MTP_documentAttributeFilename(MTP_string(filename)));
const auto id = base::RandomValue<DocumentId>();
const auto document = MTP_document(
auto result = MakePreparedFile({
.id = id,
.type = SendMediaType::ThemeFile,
});
result->filename = filename;
result->content = content;
result->filesize = content.size();
result->thumb = thumbnail;
result->thumbname = "thumb.jpg";
result->setThumbData(thumbnailBytes);
result->document = MTP_document(
MTP_flags(0),
MTP_long(id),
MTP_long(0),
@@ -436,21 +437,7 @@ SendMediaReady PrepareThemeMedia(
MTPVector<MTPVideoSize>(),
MTP_int(dcId),
MTP_vector<MTPDocumentAttribute>(attributes));
return SendMediaReady(
SendMediaType::ThemeFile,
QString(), // filepath
filename,
content.size(),
content,
id,
0,
QString(),
PeerId(),
MTP_photoEmpty(MTP_long(0)),
thumbnails,
document,
thumbnailBytes);
return result;
}
Fn<void()> SavePreparedTheme(
@@ -570,7 +557,7 @@ Fn<void()> SavePreparedTheme(
session->mainDcId(),
fields.title,
theme);
state->filename = media.filename;
state->filename = media->filename;
state->themeContent = theme;
session->uploader().documentReady(
@@ -580,7 +567,7 @@ Fn<void()> SavePreparedTheme(
uploadTheme(data);
}, state->lifetime);
session->uploader().uploadMedia(state->id, media);
session->uploader().upload(state->id, media);
};
const auto save = [=] {
@@ -999,12 +986,15 @@ ParsedTheme ParseTheme(
[[nodiscard]] QString GenerateSlug() {
const auto letters = uint8('Z' + 1 - 'A');
const auto digits = uint8('9' + 1 - '0');
const auto firstValues = uint8(2 * letters);
const auto values = uint8(2 * letters + digits);
auto result = QString();
result.reserve(kRandomSlugSize);
for (auto i = 0; i != kRandomSlugSize; ++i) {
const auto value = base::RandomValue<uint8>() % values;
const auto value = i
? (base::RandomValue<uint8>() % values)
: (base::RandomValue<uint8>() % firstValues);
if (value < letters) {
result.append(char('A' + value));
} else if (value < 2 * letters) {

View File

@@ -479,7 +479,7 @@ RUN git clone -b 1.19.0 --depth=1 {{ GIT_FREEDESKTOP }}/wayland.git \
&& rm -rf wayland
FROM builder AS nv-codec-headers
RUN git clone -b n12.0.16.0 --depth=1 {{ GIT }}/FFmpeg/nv-codec-headers.git \
RUN git clone -b n12.1.14.0 --depth=1 {{ GIT }}/FFmpeg/nv-codec-headers.git \
&& DESTDIR="{{ LibrariesPath }}/nv-codec-headers-cache" make -C nv-codec-headers install \
&& rm -rf nv-codec-headers
@@ -491,7 +491,7 @@ COPY --link --from=libXext {{ LibrariesPath }}/libXext-cache /
COPY --link --from=libXv {{ LibrariesPath }}/libXv-cache /
COPY --link --from=nv-codec-headers {{ LibrariesPath }}/nv-codec-headers-cache /
RUN git clone -b n5.1.3 --depth=1 {{ GIT }}/FFmpeg/FFmpeg.git \
RUN git clone -b n6.1.1 --depth=1 {{ GIT }}/FFmpeg/FFmpeg.git \
&& cd FFmpeg \
&& ./configure \
--extra-cflags="-DCONFIG_SAFE_BITSTREAM_READER=1" \

View File

@@ -425,7 +425,7 @@ if customRunCommand:
stage('patches', """
git clone https://github.com/desktop-app/patches.git
cd patches
git checkout cc0c2f8365
git checkout 1fef4b342a
""")
stage('msys64', """
@@ -696,14 +696,17 @@ mac:
make install
""")
# Somehow in x86 Debug build dav1d crashes on AV1 10bpc videos.
stage('dav1d', """
git clone -b 1.4.1 --depth 1 https://code.videolan.org/videolan/dav1d.git
git clone -b 1.4.1 https://code.videolan.org/videolan/dav1d.git
cd dav1d
win:
if "%X8664%" equ "x64" (
SET "TARGET=x86_64"
SET "DAV1D_ASM_DISABLE="
) else (
SET "TARGET=x86"
SET "DAV1D_ASM_DISABLE=-Denable_asm=false"
)
set FILE=cross-file.txt
echo [binaries] > %FILE%
@@ -719,7 +722,7 @@ win:
depends:python/Scripts/activate.bat
%THIRDPARTY_DIR%\\python\\Scripts\\activate.bat
meson setup --cross-file %FILE% --prefix %LIBS_DIR%/local --default-library=static --buildtype=debug -Denable_tools=false -Denable_tests=false -Db_vscrt=mtd builddir-debug
meson setup --cross-file %FILE% --prefix %LIBS_DIR%/local --default-library=static --buildtype=debug -Denable_tools=false -Denable_tests=false %DAV1D_ASM_DISABLE% -Db_vscrt=mtd builddir-debug
meson compile -C builddir-debug
meson install -C builddir-debug
release:
@@ -775,7 +778,7 @@ mac:
""")
stage('libavif', """
git clone -b v1.0.4 --depth 1 https://github.com/AOMediaCodec/libavif.git
git clone -b v1.0.4 https://github.com/AOMediaCodec/libavif.git
cd libavif
win:
cmake . ^
@@ -805,7 +808,7 @@ mac:
""")
stage('libde265', """
git clone --depth 1 -b v1.0.15 https://github.com/strukturag/libde265.git
git clone -b v1.0.15 https://github.com/strukturag/libde265.git
cd libde265
win:
cmake . ^
@@ -881,7 +884,7 @@ mac:
""")
stage('libheif', """
git clone --depth 1 -b v1.17.6 https://github.com/strukturag/libheif.git
git clone -b v1.17.6 https://github.com/strukturag/libheif.git
cd libheif
win:
%THIRDPARTY_DIR%\\msys64\\usr\\bin\\sed.exe -i 's/LIBHEIF_EXPORTS/LIBDE265_STATIC_BUILD/g' libheif/CMakeLists.txt
@@ -933,7 +936,7 @@ mac:
""")
stage('libjxl', """
git clone -b v0.8.2 --depth 1 --recursive --shallow-submodules https://github.com/libjxl/libjxl.git
git clone -b v0.8.2 --recursive --shallow-submodules https://github.com/libjxl/libjxl.git
cd libjxl
""" + setVar("cmake_defines", """
-DBUILD_SHARED_LIBS=OFF
@@ -1052,9 +1055,7 @@ depends:yasm/yasm
stage('nv-codec-headers', """
win:
git clone https://github.com/FFmpeg/nv-codec-headers.git
cd nv-codec-headers
git checkout n11.1.5.1
git clone -b n12.1.14.0 https://github.com/FFmpeg/nv-codec-headers.git
""")
stage('regex', """
@@ -1062,9 +1063,8 @@ stage('regex', """
""")
stage('ffmpeg', """
git clone https://github.com/FFmpeg/FFmpeg.git ffmpeg
git clone -b n6.1.1 https://github.com/FFmpeg/FFmpeg.git ffmpeg
cd ffmpeg
git checkout 7268323193
win:
SET PATH_BACKUP_=%PATH%
SET PATH=%ROOT_DIR%\\ThirdParty\\msys64\\usr\\bin;%PATH%
@@ -1095,6 +1095,7 @@ depends:yasm/yasm
--disable-network \
--disable-everything \
--enable-protocol=file \
--enable-libdav1d \
--enable-libopus \
--enable-libvpx \
--enable-hwaccel=h264_videotoolbox \
@@ -1116,6 +1117,7 @@ depends:yasm/yasm
--enable-decoder=gif \
--enable-decoder=h264 \
--enable-decoder=hevc \
--enable-decoder=libdav1d \
--enable-decoder=libvpx_vp8 \
--enable-decoder=libvpx_vp9 \
--enable-decoder=mp1 \

View File

@@ -1,7 +1,7 @@
AppVersion 4016002
AppVersion 4016003
AppVersionStrMajor 4.16
AppVersionStrSmall 4.16.2
AppVersionStr 4.16.2
BetaChannel 0
AppVersionStrSmall 4.16.3
AppVersionStr 4.16.3
BetaChannel 1
AlphaVersion 0
AppVersionOriginal 4.16.2
AppVersionOriginal 4.16.3.beta

View File

@@ -1,3 +1,8 @@
4.16.3 beta (05.04.24)
- Improve media upload speed.
- Update FFmpeg to 6.1.1.
4.16.2 (04.04.24)
- Use IV by default for Telegraph and some Telegram links.

2
cmake

Submodule cmake updated: 9f1b85aa9d...022c15d437