Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8d1e01159 | ||
|
|
7e6f24552a | ||
|
|
27d58ba07b | ||
|
|
3a92a181a1 | ||
|
|
ddd5617043 | ||
|
|
70b3e414ce | ||
|
|
2b04653f24 | ||
|
|
868015da25 | ||
|
|
7aeffa242e | ||
|
|
3136c0586e | ||
|
|
fb0fcbca7f |
@@ -1432,10 +1432,6 @@ if ((NOT DESKTOP_APP_DISABLE_AUTOUPDATE OR APPLE) AND NOT build_macstore AND NOT
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (LINUX)
|
||||
target_link_options(Updater PRIVATE -static-libstdc++)
|
||||
endif()
|
||||
|
||||
if (DESKTOP_APP_SPECIAL_TARGET)
|
||||
add_executable(Packer)
|
||||
init_target(Packer)
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
|
||||
ProcessorArchitecture="ARCHITECTURE"
|
||||
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
|
||||
Version="2.9.5.0" />
|
||||
Version="2.9.8.0" />
|
||||
<Properties>
|
||||
<DisplayName>Telegram Desktop</DisplayName>
|
||||
<PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName>
|
||||
|
||||
@@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 2,9,5,0
|
||||
PRODUCTVERSION 2,9,5,0
|
||||
FILEVERSION 2,9,8,0
|
||||
PRODUCTVERSION 2,9,8,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -62,10 +62,10 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Telegram FZ-LLC"
|
||||
VALUE "FileDescription", "Telegram Desktop"
|
||||
VALUE "FileVersion", "2.9.5.0"
|
||||
VALUE "FileVersion", "2.9.8.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2021"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "2.9.5.0"
|
||||
VALUE "ProductVersion", "2.9.8.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 2,9,5,0
|
||||
PRODUCTVERSION 2,9,5,0
|
||||
FILEVERSION 2,9,8,0
|
||||
PRODUCTVERSION 2,9,8,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", "2.9.5.0"
|
||||
VALUE "FileVersion", "2.9.8.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2021"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "2.9.5.0"
|
||||
VALUE "ProductVersion", "2.9.8.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@@ -281,7 +281,8 @@ void ConfirmBox::confirmed() {
|
||||
}
|
||||
} else if (const auto callbackPtr = std::get_if<2>(confirmed)) {
|
||||
if (auto callback = base::take(*callbackPtr)) {
|
||||
callback([=] { closeBox(); });
|
||||
const auto weak = Ui::MakeWeak(this);
|
||||
callback(crl::guard(weak, [=] { closeBox(); }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "lang/lang_instance.h"
|
||||
#include "mainwidget.h"
|
||||
#include "core/file_utilities.h"
|
||||
#include "core/crash_reports.h"
|
||||
#include "main/main_account.h"
|
||||
#include "main/main_domain.h"
|
||||
#include "main/main_session.h"
|
||||
@@ -94,6 +95,27 @@ constexpr auto kQuitPreventTimeoutMs = crl::time(1500);
|
||||
constexpr auto kAutoLockTimeoutLateMs = crl::time(3000);
|
||||
constexpr auto kClearEmojiImageSourceTimeout = 10 * crl::time(1000);
|
||||
|
||||
void SetCrashAnnotationsGL() {
|
||||
#ifdef Q_OS_WIN
|
||||
CrashReports::SetAnnotation("OpenGL ANGLE", [] {
|
||||
if (Core::App().settings().disableOpenGL()) {
|
||||
return "Disabled";
|
||||
} else switch (Ui::GL::CurrentANGLE()) {
|
||||
case Ui::GL::ANGLE::Auto: return "Auto";
|
||||
case Ui::GL::ANGLE::D3D11: return "Direct3D 11";
|
||||
case Ui::GL::ANGLE::D3D9: return "Direct3D 9";
|
||||
case Ui::GL::ANGLE::D3D11on12: return "D3D11on12";
|
||||
case Ui::GL::ANGLE::OpenGL: return "OpenGL";
|
||||
}
|
||||
Unexpected("Ui::GL::CurrentANGLE value in SetupANGLE.");
|
||||
}());
|
||||
#else // Q_OS_WIN
|
||||
CrashReports::SetAnnotation(
|
||||
"OpenGL",
|
||||
Core::App().settings().disableOpenGL() ? "Disabled" : "Enabled");
|
||||
#endif // Q_OS_WIN
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Application *Application::Instance = nullptr;
|
||||
@@ -287,6 +309,7 @@ void Application::run() {
|
||||
LOG(("Shortcuts Error: %1").arg(error));
|
||||
}
|
||||
|
||||
SetCrashAnnotationsGL();
|
||||
if (!Platform::IsMac() && Ui::GL::LastCrashCheckFailed()) {
|
||||
showOpenGLCrashNotification();
|
||||
}
|
||||
|
||||
@@ -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 = 2009005;
|
||||
constexpr auto AppVersionStr = "2.9.5";
|
||||
constexpr auto AppVersion = 2009008;
|
||||
constexpr auto AppVersionStr = "2.9.8";
|
||||
constexpr auto AppBetaVersion = true;
|
||||
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
|
||||
|
||||
@@ -1094,7 +1094,7 @@ void ComposeControls::initKeyHandler() {
|
||||
return;
|
||||
}
|
||||
if (key == Qt::Key_Up && !hasModifiers) {
|
||||
if (!isEditingMessage()) {
|
||||
if (!isEditingMessage() && _field->empty()) {
|
||||
_editLastMessageRequests.fire(std::move(keyEvent));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "base/concurrent_timer.h"
|
||||
#include "core/crash_reports.h"
|
||||
|
||||
#include "zlib.h"
|
||||
|
||||
extern "C" {
|
||||
extern int __isa_available;
|
||||
}
|
||||
|
||||
#define TO_LOG(x) debugLog(QString x)
|
||||
|
||||
namespace Media {
|
||||
namespace Streaming {
|
||||
namespace {
|
||||
@@ -140,6 +148,9 @@ private:
|
||||
|
||||
[[nodiscard]] TimePoint trackTime() const;
|
||||
|
||||
void debugAssertKnownTime(int step, crl::time time) const;
|
||||
void debugLog(const QString &entry) const;
|
||||
|
||||
const crl::weak_on_queue<VideoTrackObject> _weak;
|
||||
PlaybackOptions _options;
|
||||
|
||||
@@ -167,6 +178,8 @@ private:
|
||||
// For initial frame skipping for an exact seek.
|
||||
FFmpeg::FramePointer _initialSkippingFrame;
|
||||
|
||||
mutable QStringList _debugLog;
|
||||
|
||||
};
|
||||
|
||||
VideoTrackObject::VideoTrackObject(
|
||||
@@ -188,6 +201,18 @@ VideoTrackObject::VideoTrackObject(
|
||||
Expects(_stream.duration > 1);
|
||||
Expects(_ready != nullptr);
|
||||
Expects(_error != nullptr);
|
||||
|
||||
TO_LOG(("created,speed:%1,mode:%2,position:%3,sync:%4,"
|
||||
"loop:%5,wait:%6,duration:%7,initialized:%8,isa:%9"
|
||||
).arg(options.speed
|
||||
).arg(int(options.mode)
|
||||
).arg(options.position
|
||||
).arg(options.syncVideoByAudio ? "true" : "false"
|
||||
).arg(options.loop ? "true" : "false"
|
||||
).arg(options.waitForMarkAsShown ? "true" : "false"
|
||||
).arg(_stream.duration
|
||||
).arg(_shared->initialized() ? "true" : "false"
|
||||
).arg(__isa_available));
|
||||
}
|
||||
|
||||
rpl::producer<> VideoTrackObject::checkNextFrame() const {
|
||||
@@ -209,9 +234,11 @@ void VideoTrackObject::process(std::vector<FFmpeg::Packet> &&packets) {
|
||||
return;
|
||||
}
|
||||
if (packets.front().empty()) {
|
||||
TO_LOG(("process,packets:%1,till_end").arg(packets.size()));
|
||||
Assert(packets.size() == 1);
|
||||
_readTillEnd = true;
|
||||
} else if (!_readTillEnd) {
|
||||
TO_LOG(("process,packets:%1,till:%2").arg(packets.size()).arg(durationByPacket(packets.back())));
|
||||
//for (const auto &packet : packets) {
|
||||
// // Maybe it is enough to count by list.back()?.. hope so.
|
||||
// accumulate_max(
|
||||
@@ -230,6 +257,7 @@ void VideoTrackObject::process(std::vector<FFmpeg::Packet> &&packets) {
|
||||
}
|
||||
for (auto i = begin(packets), e = end(packets); i != e; ++i) {
|
||||
if (_shared->initialized()) {
|
||||
TO_LOG(("queueing_packets,count:%1").arg(e - i));
|
||||
_stream.queue.insert(
|
||||
end(_stream.queue),
|
||||
std::make_move_iterator(i),
|
||||
@@ -237,6 +265,7 @@ void VideoTrackObject::process(std::vector<FFmpeg::Packet> &&packets) {
|
||||
queueReadFrames();
|
||||
break;
|
||||
} else if (!tryReadFirstFrame(std::move(*i))) {
|
||||
TO_LOG(("fail_read_first_frame"));
|
||||
fail(Error::InvalidData);
|
||||
break;
|
||||
}
|
||||
@@ -260,22 +289,105 @@ int VideoTrackObject::durationByPacket(const FFmpeg::Packet &packet) {
|
||||
|
||||
void VideoTrackObject::queueReadFrames(crl::time delay) {
|
||||
if (delay > 0) {
|
||||
TO_LOG(("queue_with_delay:%1").arg(delay));
|
||||
_readFramesTimer.callOnce(delay);
|
||||
} else if (!_queued) {
|
||||
TO_LOG(("queue_without_delay"));
|
||||
_queued = true;
|
||||
_weak.with([](VideoTrackObject &that) {
|
||||
that.TO_LOG(("unqueued_without_delay"));
|
||||
that._queued = false;
|
||||
that.readFrames();
|
||||
});
|
||||
} else {
|
||||
TO_LOG(("queued_already"));
|
||||
}
|
||||
}
|
||||
|
||||
void VideoTrackObject::debugAssertKnownTime(int step, crl::time time) const {
|
||||
if (time < kTimeUnknown / 2) {
|
||||
CrashReports::SetAnnotation("DebugStep", QString::number(step));
|
||||
CrashReports::SetAnnotation("CheckedValue", QString::number(time));
|
||||
CrashReports::SetAnnotation(
|
||||
"_syncTimePoint.trackTime",
|
||||
QString::number(_syncTimePoint.trackTime));
|
||||
CrashReports::SetAnnotation(
|
||||
"_syncTimePoint.worldTime",
|
||||
QString::number(_syncTimePoint.worldTime));
|
||||
CrashReports::SetAnnotation(
|
||||
"_pausedTime",
|
||||
QString::number(_pausedTime));
|
||||
CrashReports::SetAnnotation(
|
||||
"_resumedTime",
|
||||
QString::number(_resumedTime));
|
||||
if (!_shared) {
|
||||
CrashReports::SetAnnotation("_shared", "NULL");
|
||||
} else {
|
||||
CrashReports::SetAnnotation(
|
||||
"_shared->initialized",
|
||||
_shared->initialized() ? "true" : "false");
|
||||
}
|
||||
CrashReports::SetAnnotation("Now", QString::number(crl::now()));
|
||||
|
||||
const auto log = _debugLog.join('\n').toUtf8();
|
||||
const auto compressed = [&] {
|
||||
auto result = QByteArray(log.size() + 1024, char(0));
|
||||
z_stream stream;
|
||||
stream.zalloc = nullptr;
|
||||
stream.zfree = nullptr;
|
||||
stream.opaque = nullptr;
|
||||
stream.avail_in = log.size();
|
||||
stream.next_in = reinterpret_cast<Bytef*>(const_cast<char*>(log.data()));
|
||||
stream.avail_out = result.size();
|
||||
stream.next_out = reinterpret_cast<Bytef*>(result.data());
|
||||
int res = deflateInit2(&stream, Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
|
||||
if (res != Z_OK) {
|
||||
CrashReports::SetAnnotation("Log", "deflatInit2:" + QString::number(res));
|
||||
return QByteArray();
|
||||
}
|
||||
{
|
||||
const auto guard = gsl::finally([&] { deflateEnd(&stream); });
|
||||
int res = deflate(&stream, Z_FINISH);
|
||||
if (res != Z_OK && res != Z_STREAM_END) {
|
||||
CrashReports::SetAnnotation("Log", "deflate:" + QString::number(res));
|
||||
return QByteArray();
|
||||
} else if (!stream.avail_out) {
|
||||
CrashReports::SetAnnotation("Log", "deflate:no_avail_out");
|
||||
return QByteArray();
|
||||
}
|
||||
}
|
||||
result.resize(result.size() - stream.avail_out);
|
||||
return result;
|
||||
}();
|
||||
if (!compressed.isEmpty()) {
|
||||
CrashReports::SetAnnotation("Log", QString::fromUtf8(compressed.toBase64()));
|
||||
}
|
||||
|
||||
Unexpected("Bad time value.");
|
||||
}
|
||||
}
|
||||
|
||||
void VideoTrackObject::debugLog(const QString &entry) const {
|
||||
constexpr auto kMaxEntries = 2048;
|
||||
if (_debugLog.size() >= kMaxEntries) {
|
||||
return;
|
||||
} else if (_debugLog.size() == kMaxEntries - 1) {
|
||||
_debugLog.push_back("...");
|
||||
return;
|
||||
}
|
||||
_debugLog.push_back("stp.worldTime:"
|
||||
+ QString::number(_syncTimePoint.worldTime)
|
||||
+ ";stp.trackTime:" + QString::number(_syncTimePoint.trackTime)
|
||||
+ ";" + entry);
|
||||
}
|
||||
|
||||
void VideoTrackObject::readFrames() {
|
||||
if (interrupted()) {
|
||||
return;
|
||||
}
|
||||
auto time = trackTime().trackTime;
|
||||
Assert(1 && time >= kTimeUnknown / 2); // Debugging a crash.
|
||||
TO_LOG(("reading_frames,time:%1").arg(time));
|
||||
debugAssertKnownTime(1, time);
|
||||
while (true) {
|
||||
const auto result = readEnoughFrames(time);
|
||||
v::match(result, [&](FrameResult result) {
|
||||
@@ -286,7 +398,7 @@ void VideoTrackObject::readFrames() {
|
||||
const auto duration = computeDuration();
|
||||
Assert(duration != kDurationUnavailable);
|
||||
time -= duration;
|
||||
Assert(2 && time >= kTimeUnknown / 2); // Debugging a crash.
|
||||
debugAssertKnownTime(2, time);
|
||||
}
|
||||
}, [&](Shared::PrepareNextCheck delay) {
|
||||
Expects(delay == kTimeUnknown || delay > 0);
|
||||
@@ -304,6 +416,7 @@ void VideoTrackObject::readFrames() {
|
||||
|
||||
auto VideoTrackObject::readEnoughFrames(crl::time trackTime)
|
||||
-> ReadEnoughState {
|
||||
TO_LOG(("reading_enough_frames,time:%1").arg(trackTime));
|
||||
const auto dropStaleFrames = !_options.waitForMarkAsShown;
|
||||
const auto state = _shared->prepareState(trackTime, dropStaleFrames);
|
||||
return v::match(state, [&](Shared::PrepareFrame frame)
|
||||
@@ -311,13 +424,16 @@ auto VideoTrackObject::readEnoughFrames(crl::time trackTime)
|
||||
while (true) {
|
||||
const auto result = readFrame(frame);
|
||||
if (result != FrameResult::Done) {
|
||||
TO_LOG(("read_enough_state,frame_result:%1").arg(int(result)));
|
||||
return result;
|
||||
} else if (!dropStaleFrames
|
||||
|| !VideoTrack::IsStale(frame, trackTime)) {
|
||||
TO_LOG(("read_enough_state,null"));
|
||||
return v::null;
|
||||
}
|
||||
}
|
||||
}, [&](Shared::PrepareNextCheck delay) -> ReadEnoughState {
|
||||
TO_LOG(("read_enough_state,delay:%1").arg(delay));
|
||||
Expects(delay == kTimeUnknown || delay > 0); // Debugging crash.
|
||||
|
||||
return delay;
|
||||
@@ -329,6 +445,7 @@ auto VideoTrackObject::readEnoughFrames(crl::time trackTime)
|
||||
bool VideoTrackObject::loopAround() {
|
||||
const auto duration = computeDuration();
|
||||
if (duration == kDurationUnavailable) {
|
||||
TO_LOG(("loop_around,error_duration_unavailable"));
|
||||
LOG(("Streaming Error: "
|
||||
"Couldn't find out the real video stream duration."));
|
||||
return false;
|
||||
@@ -336,6 +453,7 @@ bool VideoTrackObject::loopAround() {
|
||||
avcodec_flush_buffers(_stream.codec.get());
|
||||
_loopingShift += duration;
|
||||
_readTillEnd = false;
|
||||
TO_LOG(("loop_around,duration:%1,shift:%2").arg(duration).arg(_loopingShift));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -353,31 +471,38 @@ auto VideoTrackObject::readFrame(not_null<Frame*> frame) -> FrameResult {
|
||||
if (const auto error = ReadNextFrame(_stream)) {
|
||||
if (error.code() == AVERROR_EOF) {
|
||||
if (!_options.loop) {
|
||||
TO_LOG(("read_frame,error_eof"));
|
||||
frame->position = kFinishedPosition;
|
||||
frame->displayed = kTimeUnknown;
|
||||
return FrameResult::Finished;
|
||||
} else if (loopAround()) {
|
||||
TO_LOG(("read_frame,error_looped"));
|
||||
return FrameResult::Looped;
|
||||
} else {
|
||||
TO_LOG(("read_frame,error_bad_data"));
|
||||
fail(Error::InvalidData);
|
||||
return FrameResult::Error;
|
||||
}
|
||||
} else if (error.code() != AVERROR(EAGAIN) || _readTillEnd) {
|
||||
TO_LOG(("read_frame,error_bad_data:%1,till_end:%2").arg(error.code()).arg(_readTillEnd ? "true" : "false"));
|
||||
fail(Error::InvalidData);
|
||||
return FrameResult::Error;
|
||||
}
|
||||
TO_LOG(("read_frame,error_again"));
|
||||
Assert(_stream.queue.empty());
|
||||
_waitingForData.fire({});
|
||||
return FrameResult::Waiting;
|
||||
}
|
||||
const auto position = currentFramePosition();
|
||||
if (position == kTimeUnknown) {
|
||||
TO_LOG(("read_frame,error_current_position:%1").arg(position));
|
||||
fail(Error::InvalidData);
|
||||
return FrameResult::Error;
|
||||
}
|
||||
std::swap(frame->decoded, _stream.frame);
|
||||
frame->position = position;
|
||||
frame->displayed = kTimeUnknown;
|
||||
TO_LOG(("read_frame,current_position:%1").arg(position));
|
||||
return FrameResult::Done;
|
||||
}
|
||||
|
||||
@@ -476,11 +601,14 @@ void VideoTrackObject::presentFrameIfNeeded() {
|
||||
return;
|
||||
}
|
||||
const auto dropStaleFrames = !_options.waitForMarkAsShown;
|
||||
const auto time = trackTime();
|
||||
TO_LOG(("present_frame_check,world:%1,track:%2").arg(time.worldTime).arg(time.trackTime));
|
||||
const auto presented = _shared->presentFrame(
|
||||
this,
|
||||
trackTime(),
|
||||
time,
|
||||
_options.speed,
|
||||
dropStaleFrames);
|
||||
TO_LOG(("present_frame_check,add:%1,position:%2,next:%3").arg(presented.addedWorldTimeDelay).arg(presented.displayPosition).arg(presented.nextCheckDelay));
|
||||
addTimelineDelay(presented.addedWorldTimeDelay);
|
||||
if (presented.displayPosition == kFinishedPosition) {
|
||||
interrupt();
|
||||
@@ -498,6 +626,7 @@ void VideoTrackObject::presentFrameIfNeeded() {
|
||||
void VideoTrackObject::pause(crl::time time) {
|
||||
Expects(_syncTimePoint.valid());
|
||||
|
||||
TO_LOG(("pause,time:%1,paused:%2").arg(time).arg(_pausedTime));
|
||||
if (interrupted()) {
|
||||
return;
|
||||
} else if (_pausedTime == kTimeUnknown) {
|
||||
@@ -508,6 +637,8 @@ void VideoTrackObject::pause(crl::time time) {
|
||||
void VideoTrackObject::resume(crl::time time) {
|
||||
Expects(_syncTimePoint.trackTime != kTimeUnknown);
|
||||
|
||||
TO_LOG(("resume,time:%1,paused:%2,resumed:%3").arg(time).arg(_pausedTime).arg(_resumedTime));
|
||||
|
||||
if (interrupted()) {
|
||||
return;
|
||||
}
|
||||
@@ -528,13 +659,15 @@ void VideoTrackObject::resume(crl::time time) {
|
||||
}
|
||||
|
||||
void VideoTrackObject::setSpeed(float64 speed) {
|
||||
TO_LOG(("set_speed,speed:%1").arg(speed));
|
||||
if (interrupted()) {
|
||||
return;
|
||||
}
|
||||
if (_syncTimePoint.valid()) {
|
||||
_syncTimePoint = trackTime();
|
||||
// Debugging a crash.
|
||||
Assert(3 && _syncTimePoint.trackTime >= kTimeUnknown / 2);
|
||||
const auto time = trackTime();
|
||||
TO_LOG(("set_speed_changing_time,world:%1,track:%2").arg(time.worldTime).arg(time.trackTime));
|
||||
_syncTimePoint = time;
|
||||
debugAssertKnownTime(3, _syncTimePoint.trackTime);
|
||||
}
|
||||
_options.speed = speed;
|
||||
}
|
||||
@@ -543,17 +676,23 @@ void VideoTrackObject::setWaitForMarkAsShown(bool wait) {
|
||||
if (interrupted()) {
|
||||
return;
|
||||
}
|
||||
TO_LOG(("set_wait_for_mark,wait:%1").arg(wait ? "true" : "false"));
|
||||
_options.waitForMarkAsShown = wait;
|
||||
}
|
||||
|
||||
bool VideoTrackObject::interrupted() const {
|
||||
return (_shared == nullptr);
|
||||
if (_shared == nullptr) {
|
||||
TO_LOG(("interruped_true"));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void VideoTrackObject::frameShown() {
|
||||
if (interrupted()) {
|
||||
return;
|
||||
}
|
||||
TO_LOG(("frame_shown"));
|
||||
queueReadFrames();
|
||||
}
|
||||
|
||||
@@ -563,6 +702,7 @@ void VideoTrackObject::addTimelineDelay(crl::time delayed) {
|
||||
if (!delayed) {
|
||||
return;
|
||||
}
|
||||
TO_LOG(("adding_delay:%1").arg(delayed));
|
||||
_syncTimePoint.worldTime += delayed;
|
||||
}
|
||||
|
||||
@@ -578,26 +718,34 @@ void VideoTrackObject::removeFrameRequest(const Instance *instance) {
|
||||
|
||||
bool VideoTrackObject::tryReadFirstFrame(FFmpeg::Packet &&packet) {
|
||||
if (ProcessPacket(_stream, std::move(packet)).failed()) {
|
||||
TO_LOG(("try_read_first_frame_process_failed"));
|
||||
return false;
|
||||
}
|
||||
TO_LOG(("try_read_first_frame"));
|
||||
while (true) {
|
||||
if (const auto error = ReadNextFrame(_stream)) {
|
||||
if (error.code() == AVERROR_EOF) {
|
||||
if (!_initialSkippingFrame) {
|
||||
TO_LOG(("try_read_first_frame_eof_bad"));
|
||||
return false;
|
||||
}
|
||||
// Return the last valid frame if we seek too far.
|
||||
_stream.frame = std::move(_initialSkippingFrame);
|
||||
TO_LOG(("try_read_first_frame_eof_to_initial"));
|
||||
return processFirstFrame();
|
||||
} else if (error.code() != AVERROR(EAGAIN) || _readTillEnd) {
|
||||
TO_LOG(("try_read_first_frame_error,end:%1").arg(_readTillEnd ? "true" : "false"));
|
||||
return false;
|
||||
} else {
|
||||
// Waiting for more packets.
|
||||
TO_LOG(("try_read_first_frame_waiting"));
|
||||
return true;
|
||||
}
|
||||
} else if (!fillStateFromFrame()) {
|
||||
TO_LOG(("try_read_first_frame_bad_state"));
|
||||
return false;
|
||||
} else if (_syncTimePoint.trackTime >= _options.position) {
|
||||
TO_LOG(("try_read_first_frame_process"));
|
||||
return processFirstFrame();
|
||||
}
|
||||
|
||||
@@ -622,8 +770,8 @@ bool VideoTrackObject::processFirstFrame() {
|
||||
if (frame.isNull()) {
|
||||
return false;
|
||||
}
|
||||
// Debugging a crash.
|
||||
Assert(4 && _syncTimePoint.trackTime >= kTimeUnknown / 2);
|
||||
debugAssertKnownTime(4, _syncTimePoint.trackTime);
|
||||
TO_LOG(("process_first_frame"));
|
||||
_shared->init(std::move(frame), _syncTimePoint.trackTime);
|
||||
callReady();
|
||||
queueReadFrames();
|
||||
@@ -644,11 +792,12 @@ crl::time VideoTrackObject::currentFramePosition() const {
|
||||
bool VideoTrackObject::fillStateFromFrame() {
|
||||
const auto position = currentFramePosition();
|
||||
if (position == kTimeUnknown) {
|
||||
TO_LOG(("fill_state_from_frame_bad"));
|
||||
return false;
|
||||
}
|
||||
TO_LOG(("fill_state_from_frame,position:%1").arg(position));
|
||||
_syncTimePoint.trackTime = position;
|
||||
// Debugging a crash.
|
||||
Assert(5 && _syncTimePoint.trackTime >= kTimeUnknown / 2);
|
||||
debugAssertKnownTime(5, _syncTimePoint.trackTime);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -671,12 +820,12 @@ void VideoTrackObject::callReady() {
|
||||
data.state.receivedTill = _readTillEnd
|
||||
? _stream.duration
|
||||
: _syncTimePoint.trackTime;
|
||||
TO_LOG(("call_ready,till:%1").arg(data.state.receivedTill));
|
||||
base::take(_ready)({ data });
|
||||
}
|
||||
|
||||
TimePoint VideoTrackObject::trackTime() const {
|
||||
// Debugging a crash.
|
||||
Assert(7 && _syncTimePoint.trackTime >= kTimeUnknown / 2);
|
||||
debugAssertKnownTime(7, _syncTimePoint.trackTime);
|
||||
|
||||
auto result = TimePoint();
|
||||
result.worldTime = (_pausedTime != kTimeUnknown)
|
||||
@@ -684,22 +833,117 @@ TimePoint VideoTrackObject::trackTime() const {
|
||||
: crl::now();
|
||||
if (!_syncTimePoint) {
|
||||
result.trackTime = _syncTimePoint.trackTime;
|
||||
TO_LOG(("track_time,paused:%1,result_world:%2").arg(_pausedTime).arg(result.worldTime));
|
||||
return result;
|
||||
}
|
||||
debugAssertKnownTime(8, _syncTimePoint.worldTime);
|
||||
debugAssertKnownTime(9, result.worldTime);
|
||||
|
||||
Assert(_resumedTime != kTimeUnknown);
|
||||
if (_options.syncVideoByAudio && _audioId.externalPlayId()) {
|
||||
const auto mixer = Media::Player::mixer();
|
||||
const auto point = mixer->getExternalSyncTimePoint(_audioId);
|
||||
if (point && point.worldTime > _resumedTime) {
|
||||
TO_LOG(("track_time_sync,world:%1,track:%2,resumed:%3").arg(point.worldTime).arg(point.trackTime).arg(_resumedTime));
|
||||
_syncTimePoint = point;
|
||||
// Debugging a crash.
|
||||
Assert(6 && _syncTimePoint.trackTime >= kTimeUnknown / 2);
|
||||
debugAssertKnownTime(6, _syncTimePoint.trackTime);
|
||||
debugAssertKnownTime(10, _syncTimePoint.worldTime);
|
||||
}
|
||||
}
|
||||
const auto adjust = (result.worldTime - _syncTimePoint.worldTime);
|
||||
result.trackTime = _syncTimePoint.trackTime
|
||||
+ crl::time(std::round(adjust * _options.speed));
|
||||
const auto adjustSpeed = adjust * _options.speed;
|
||||
const auto roundAdjustSpeed = std::round(adjustSpeed);
|
||||
auto timeRoundAdjustSpeed = crl::time(roundAdjustSpeed);
|
||||
const auto fpuErrorHappened = [](crl::time value) {
|
||||
return uint64(value) == 0x8000'0000'0000'0000ULL
|
||||
|| uint64(value) == 0x8000'0000ULL
|
||||
|| uint64(value) == 0xFFFF'FFFF'FFFF'FFFFULL
|
||||
|| uint64(value) == 0xFFFF'FFFFULL;
|
||||
};
|
||||
if (roundAdjustSpeed > -1000'000'000.
|
||||
&& roundAdjustSpeed < 1000'000'000.
|
||||
&& fpuErrorHappened(timeRoundAdjustSpeed)) {
|
||||
TO_LOG(("BAD1,round:%1").arg(roundAdjustSpeed));
|
||||
timeRoundAdjustSpeed = crl::time(roundAdjustSpeed);
|
||||
if (!fpuErrorHappened(timeRoundAdjustSpeed)) {
|
||||
TO_LOG(("GOOD2,round:%1,result:%2").arg(roundAdjustSpeed).arg(timeRoundAdjustSpeed));
|
||||
debugAssertKnownTime(-1, kTimeUnknown);
|
||||
} else {
|
||||
TO_LOG(("BAD2,round:%1").arg(roundAdjustSpeed));
|
||||
}
|
||||
const auto floatRoundAdjustSpeed = float(roundAdjustSpeed);
|
||||
timeRoundAdjustSpeed = crl::time(floatRoundAdjustSpeed);
|
||||
if (!fpuErrorHappened(timeRoundAdjustSpeed)) {
|
||||
TO_LOG(("GOOD3,round:%1,result:%2").arg(floatRoundAdjustSpeed).arg(timeRoundAdjustSpeed));
|
||||
debugAssertKnownTime(-2, kTimeUnknown);
|
||||
} else {
|
||||
TO_LOG(("BAD3,round:%1").arg(floatRoundAdjustSpeed));
|
||||
}
|
||||
const auto intRoundAdjustSpeet = int(roundAdjustSpeed);
|
||||
timeRoundAdjustSpeed = crl::time(intRoundAdjustSpeet);
|
||||
if (!fpuErrorHappened(timeRoundAdjustSpeed)) {
|
||||
TO_LOG(("GOOD4,int:%1,result:%2").arg(intRoundAdjustSpeet).arg(timeRoundAdjustSpeed));
|
||||
debugAssertKnownTime(-3, kTimeUnknown);
|
||||
} else {
|
||||
TO_LOG(("BAD4,int:%1").arg(intRoundAdjustSpeet));
|
||||
}
|
||||
const auto intFloatRoundAdjustSpeed = int(floatRoundAdjustSpeed);
|
||||
timeRoundAdjustSpeed = crl::time(intFloatRoundAdjustSpeed);
|
||||
if (!fpuErrorHappened(timeRoundAdjustSpeed)) {
|
||||
TO_LOG(("GOOD5,int:%1,result:%2").arg(intFloatRoundAdjustSpeed).arg(timeRoundAdjustSpeed));
|
||||
debugAssertKnownTime(-4, kTimeUnknown);
|
||||
} else {
|
||||
TO_LOG(("BAD5,int:%1").arg(intFloatRoundAdjustSpeed));
|
||||
}
|
||||
const auto uint64RoundAdjustSpeed = uint64((roundAdjustSpeed >= 0.)
|
||||
? roundAdjustSpeed
|
||||
: -roundAdjustSpeed);
|
||||
if (!fpuErrorHappened(uint64RoundAdjustSpeed)) {
|
||||
TO_LOG(("GOOD6,round:%1,uint:%2").arg(roundAdjustSpeed).arg(uint64RoundAdjustSpeed));
|
||||
debugAssertKnownTime(-5, kTimeUnknown);
|
||||
} else {
|
||||
TO_LOG(("BAD6,uint:%1").arg(uint64RoundAdjustSpeed));
|
||||
}
|
||||
const auto uint64FloatRoundAdjustSpeed = uint64((floatRoundAdjustSpeed >= 0.)
|
||||
? floatRoundAdjustSpeed
|
||||
: -floatRoundAdjustSpeed);
|
||||
if (!fpuErrorHappened(uint64FloatRoundAdjustSpeed)) {
|
||||
TO_LOG(("GOOD7,round:%1,uint:%2").arg(floatRoundAdjustSpeed).arg(uint64FloatRoundAdjustSpeed));
|
||||
debugAssertKnownTime(-6, kTimeUnknown);
|
||||
} else {
|
||||
TO_LOG(("BAD7,uint:%1").arg(uint64FloatRoundAdjustSpeed));
|
||||
}
|
||||
const auto uint32RoundAdjustSpeed = uint32((roundAdjustSpeed >= 0.)
|
||||
? roundAdjustSpeed
|
||||
: -roundAdjustSpeed);
|
||||
if (!fpuErrorHappened(uint32RoundAdjustSpeed)) {
|
||||
TO_LOG(("GOOD8,round:%1,uint:%2").arg(roundAdjustSpeed).arg(uint32RoundAdjustSpeed));
|
||||
debugAssertKnownTime(-7, kTimeUnknown);
|
||||
} else {
|
||||
TO_LOG(("BAD8,uint:%1").arg(uint32RoundAdjustSpeed));
|
||||
}
|
||||
const auto uint32FloatRoundAdjustSpeed = uint32((floatRoundAdjustSpeed >= 0.)
|
||||
? floatRoundAdjustSpeed
|
||||
: -floatRoundAdjustSpeed);
|
||||
if (!fpuErrorHappened(uint32FloatRoundAdjustSpeed)) {
|
||||
TO_LOG(("GOOD9,round:%1,uint:%2").arg(floatRoundAdjustSpeed).arg(uint32FloatRoundAdjustSpeed));
|
||||
debugAssertKnownTime(-8, kTimeUnknown);
|
||||
} else {
|
||||
TO_LOG(("BAD9,uint:%1").arg(uint32FloatRoundAdjustSpeed));
|
||||
}
|
||||
debugAssertKnownTime(-9, kTimeUnknown);
|
||||
}
|
||||
const auto trackTime = _syncTimePoint.trackTime + timeRoundAdjustSpeed;
|
||||
TO_LOG(("track_time_adjusted,world:%1,adjust:%2,speed:%3,delta:%4,rounded:%5,casted:%6,final:%7"
|
||||
).arg(result.worldTime
|
||||
).arg(adjust
|
||||
).arg(_options.speed
|
||||
).arg(adjustSpeed
|
||||
).arg(roundAdjustSpeed
|
||||
).arg(timeRoundAdjustSpeed
|
||||
).arg(result.trackTime));
|
||||
result.trackTime = trackTime;
|
||||
debugAssertKnownTime(11, result.trackTime);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -998,7 +1242,6 @@ VideoTrack::FrameWithIndex VideoTrack::Shared::frameForPaintWithIndex() {
|
||||
.frame = frame,
|
||||
.index = (_counterCycle * 2 * kFramesCount) + index,
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
VideoTrack::VideoTrack(
|
||||
|
||||
@@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/gl/gl_shader.h"
|
||||
#include "media/streaming/media_streaming_common.h"
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "core/crash_reports.h"
|
||||
#include "styles/style_media_view.h"
|
||||
|
||||
namespace Media::View {
|
||||
@@ -119,6 +120,12 @@ void OverlayWidget::RendererGL::init(
|
||||
FragmentSampleARGB32Texture(),
|
||||
FragmentGlobalOpacity(),
|
||||
}));
|
||||
|
||||
const auto renderer = reinterpret_cast<const char*>(
|
||||
f.glGetString(GL_RENDERER));
|
||||
CrashReports::SetAnnotation(
|
||||
"OpenGL Renderer",
|
||||
renderer ? renderer : "[nullptr]");
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererGL::deinit(
|
||||
|
||||
@@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "core/file_utilities.h"
|
||||
#include "core/mime_type.h"
|
||||
#include "core/ui_integration.h"
|
||||
#include "core/crash_reports.h"
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/image/image.h"
|
||||
@@ -294,6 +295,8 @@ OverlayWidget::OverlayWidget()
|
||||
, _lastAction(-st::mediaviewDeltaFromLastAction, -st::mediaviewDeltaFromLastAction)
|
||||
, _stateAnimation([=](crl::time now) { return stateAnimationCallback(now); })
|
||||
, _dropdown(_widget, st::mediaviewDropdownMenu) {
|
||||
CrashReports::SetAnnotation("OpenGL Renderer", "[not-initialized]");
|
||||
|
||||
Lang::Updated(
|
||||
) | rpl::start_with_next([=] {
|
||||
refreshLang();
|
||||
|
||||
@@ -30,11 +30,44 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "settings/settings_common.h"
|
||||
#include "api/api_updates.h"
|
||||
|
||||
#include "zlib.h"
|
||||
|
||||
namespace Settings {
|
||||
namespace {
|
||||
|
||||
using SessionController = Window::SessionController;
|
||||
|
||||
[[nodiscard]] QByteArray UnpackRawGzip(const QByteArray &bytes) {
|
||||
z_stream stream;
|
||||
stream.zalloc = nullptr;
|
||||
stream.zfree = nullptr;
|
||||
stream.opaque = nullptr;
|
||||
stream.avail_in = 0;
|
||||
stream.next_in = nullptr;
|
||||
int res = inflateInit2(&stream, -MAX_WBITS);
|
||||
if (res != Z_OK) {
|
||||
return QByteArray();
|
||||
}
|
||||
const auto guard = gsl::finally([&] { inflateEnd(&stream); });
|
||||
|
||||
auto result = QByteArray(1024 * 1024, char(0));
|
||||
stream.avail_in = bytes.size();
|
||||
stream.next_in = reinterpret_cast<Bytef*>(const_cast<char*>(bytes.data()));
|
||||
stream.avail_out = 0;
|
||||
while (!stream.avail_out) {
|
||||
stream.avail_out = result.size();
|
||||
stream.next_out = reinterpret_cast<Bytef*>(result.data());
|
||||
int res = inflate(&stream, Z_NO_FLUSH);
|
||||
if (res != Z_OK && res != Z_STREAM_END) {
|
||||
return QByteArray();
|
||||
} else if (!stream.avail_out) {
|
||||
return QByteArray();
|
||||
}
|
||||
}
|
||||
result.resize(result.size() - stream.avail_out);
|
||||
return result;
|
||||
}
|
||||
|
||||
auto GenerateCodes() {
|
||||
auto codes = std::map<QString, Fn<void(SessionController*)>>();
|
||||
codes.emplace(qsl("debugmode"), [](SessionController *window) {
|
||||
@@ -197,6 +230,50 @@ auto GenerateCodes() {
|
||||
Core::App().saveSettingsDelayed();
|
||||
Ui::show(Box<InformBox>("All sound overrides were reset."));
|
||||
});
|
||||
codes.emplace(qsl("unpacklog"), [](SessionController *window) {
|
||||
FileDialog::GetOpenPath(Core::App().getFileDialogParent(), "Open crash log file", "Crash dump (*.txt)", [=](const FileDialog::OpenResult &result) {
|
||||
if (result.paths.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
auto f = QFile(result.paths.front());
|
||||
if (!f.open(QIODevice::ReadOnly)) {
|
||||
Ui::Toast::Show("Could not open log :(");
|
||||
return;
|
||||
}
|
||||
const auto all = f.readAll();
|
||||
const auto log = all.indexOf("Log: ");
|
||||
if (log < 0) {
|
||||
Ui::Toast::Show("Could not find log :(");
|
||||
return;
|
||||
}
|
||||
const auto base = all.mid(log + 5);
|
||||
const auto end = base.indexOf('\n');
|
||||
if (end <= 0) {
|
||||
Ui::Toast::Show("Could not find log end :(");
|
||||
return;
|
||||
}
|
||||
const auto based = QByteArray::fromBase64(base.mid(0, end));
|
||||
const auto uncompressed = UnpackRawGzip(based);
|
||||
if (uncompressed.isEmpty()) {
|
||||
Ui::Toast::Show("Could not unpack log :(");
|
||||
return;
|
||||
}
|
||||
FileDialog::GetWritePath(Core::App().getFileDialogParent(), "Save detailed log", "Crash dump (*.txt)", QString(), [=](QString &&result) {
|
||||
if (result.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
auto f = QFile(result);
|
||||
if (!f.open(QIODevice::WriteOnly)) {
|
||||
Ui::Toast::Show("Could not open details :(");
|
||||
} else if (f.write(uncompressed) != uncompressed.size()) {
|
||||
Ui::Toast::Show("Could not write details :(");
|
||||
} else {
|
||||
f.close();
|
||||
Ui::Toast::Show("Done!");
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
@@ -291,7 +291,8 @@ void PrepareDetails(PreparedFile &file, int previewWidth) {
|
||||
if (ValidPhotoForAlbum(*image, file.information->filemime)) {
|
||||
UpdateImageDetails(file, previewWidth);
|
||||
file.type = PreparedFile::Type::Photo;
|
||||
} else if (Core::IsMimeSticker(file.information->filemime)) {
|
||||
} else if (Core::IsMimeSticker(file.information->filemime)
|
||||
|| image->animated) {
|
||||
file.type = PreparedFile::Type::None;
|
||||
}
|
||||
} else if (const auto video = std::get_if<Video>(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
AppVersion 2009005
|
||||
AppVersion 2009008
|
||||
AppVersionStrMajor 2.9
|
||||
AppVersionStrSmall 2.9.5
|
||||
AppVersionStr 2.9.5
|
||||
AppVersionStrSmall 2.9.8
|
||||
AppVersionStr 2.9.8
|
||||
BetaChannel 1
|
||||
AlphaVersion 0
|
||||
AppVersionOriginal 2.9.5.beta
|
||||
AppVersionOriginal 2.9.8.beta
|
||||
|
||||
Submodule Telegram/lib_ui updated: 6b320a99da...5938cb012f
@@ -1,3 +1,15 @@
|
||||
2.9.8 beta (23.08.21)
|
||||
|
||||
- And still debugging a video playback crash in 32 bit Windows version.
|
||||
|
||||
2.9.7 beta (23.08.21)
|
||||
|
||||
- Still debugging a video playback crash in 32 bit Windows version.
|
||||
|
||||
2.9.6 beta (21.08.21)
|
||||
|
||||
- Debugging a video playback crash in 32 bit Windows version.
|
||||
|
||||
2.9.5 beta (20.08.21)
|
||||
|
||||
- Tile chat background patterns horizontally.
|
||||
|
||||
Reference in New Issue
Block a user