Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Telegram/SourceFiles/ffmpeg/ffmpeg_utility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ constexpr auto kAlignImageBy = 64;
constexpr auto kImageFormat = QImage::Format_ARGB32_Premultiplied;
constexpr auto kMaxScaleByAspectRatio = 16;
constexpr auto kAvioBlockSize = 4096;
constexpr auto kMaxFrameStorageBytes = 64 * 1024 * 1024;
constexpr auto kMaxFrameStorageBytes = 128 * 1024 * 1024;
constexpr auto kMaxPixelsPaddingRatio = 32;
constexpr auto kMaxPixelsFixedPadding = 64 * 1024;
constexpr auto kTimeUnknown = std::numeric_limits<crl::time>::min();
Expand Down
10 changes: 9 additions & 1 deletion Telegram/SourceFiles/media/clip/media_clip_ffmpeg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace {

constexpr auto kSkipInvalidDataPackets = 10;
constexpr auto kMaxInlineArea = 1280 * 720;
constexpr auto kMaxSendingArea = 3840 * 2160; // usual 4K
constexpr auto kMaxSendingArea = 7680 * 4320; // usual 8K

[[nodiscard]] auto MaxAreaForMode(ReaderImplementation::Mode mode) {
return (mode == ReaderImplementation::Mode::Inspecting)
Expand Down Expand Up @@ -168,6 +168,14 @@ crl::time FFMpegReaderImplementation::framePresentationTime() const {
return qMax(_frameTime + _frameTimeCorrection, crl::time(0));
}

QSize FFMpegReaderImplementation::frameSize() const {
auto result = QSize(_frame->width, _frame->height);
if (rotationSwapWidthHeight()) {
result.transpose();
}
return result;
}

crl::time FFMpegReaderImplementation::durationMs() const {
const auto rebase = [](int64_t duration, const AVRational &base) {
return (duration * 1000LL * base.num) / base.den;
Expand Down
1 change: 1 addition & 0 deletions Telegram/SourceFiles/media/clip/media_clip_ffmpeg.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class FFMpegReaderImplementation : public ReaderImplementation {

crl::time frameRealTime() const override;
crl::time framePresentationTime() const override;
QSize frameSize() const override;

bool renderFrame(
QImage &to,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class ReaderImplementation {
// Get current frame real and presentation time.
virtual crl::time frameRealTime() const = 0;
virtual crl::time framePresentationTime() const = 0;
virtual QSize frameSize() const = 0;

// Render current frame to an image with specific size.
virtual bool renderFrame(
Expand Down
27 changes: 18 additions & 9 deletions Telegram/SourceFiles/media/clip/media_clip_reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ namespace {

constexpr auto kClipThreadsCount = 8;
constexpr auto kAverageGifSize = 320 * 240;
constexpr auto kPreparedVideoThumbnailSide = 320;
constexpr auto kWaitBeforeGifPause = crl::time(200);

QImage PrepareFrame(
Expand Down Expand Up @@ -493,13 +494,12 @@ class ReaderPrivate {
if (reader->start(internal::ReaderImplementation::Mode::Silent, firstFramePositionMs)) {
auto firstFrameReadResult = reader->readFramesTill(-1, ms);
if (firstFrameReadResult == internal::ReaderImplementation::ReadResult::Success) {
if (reader->renderFrame(frame()->original, frame()->alpha, frame()->index, QSize())) {
frame()->original.fill(QColor(0, 0, 0));

const auto dimensions = reader->frameSize();
if (!dimensions.isEmpty()) {
frame()->positionMs = _seekPositionMs;

_width = frame()->original.width();
_height = frame()->original.height();
_width = dimensions.width();
_height = dimensions.height();
_durationMs = _implementation->durationMs();
return ProcessResult::Started;
}
Expand All @@ -510,13 +510,14 @@ class ReaderPrivate {
} else if (readResult != internal::ReaderImplementation::ReadResult::Success) { // Read the first frame.
return error();
}
if (!_implementation->renderFrame(frame()->original, frame()->alpha, frame()->index, QSize())) {
const auto dimensions = _implementation->frameSize();
if (dimensions.isEmpty()) {
return error();
}
frame()->positionMs = _implementation->frameRealTime();

_width = frame()->original.width();
_height = frame()->original.height();
_width = dimensions.width();
_height = dimensions.height();
_durationMs = _implementation->durationMs();
return ProcessResult::Started;
}
Expand Down Expand Up @@ -784,6 +785,8 @@ bool Manager::handleProcessResult(ReaderPrivate *reader, ProcessResult result, c

if (result == ProcessResult::Started) {
_loadLevel.fetchAndAddRelaxed(reader->_width * reader->_height - kAverageGifSize);
it.key()->_width = reader->_width;
it.key()->_height = reader->_height;
it.key()->_durationMs = reader->_durationMs;
}
// See if we need to pause GIF because it is not displayed right now.
Expand Down Expand Up @@ -990,7 +993,13 @@ Ui::PreparedFileInformation PrepareForSending(
auto hasAlpha = false;
auto readResult = reader->readFramesTill(-1, crl::now());
auto readFrame = (readResult == internal::ReaderImplementation::ReadResult::Success);
if (readFrame && reader->renderFrame(result.thumbnail, hasAlpha, index, QSize())) {
const auto dimensions = reader->frameSize();
result.dimensions = dimensions;
const auto thumbnailSize = dimensions.scaled(
kPreparedVideoThumbnailSide,
kPreparedVideoThumbnailSide,
Qt::KeepAspectRatio);
if (readFrame && reader->renderFrame(result.thumbnail, hasAlpha, index, thumbnailSize)) {
if (hasAlpha && !result.isWebmSticker) {
result.thumbnail = Images::Opaque(std::move(result.thumbnail));
}
Expand Down
2 changes: 2 additions & 0 deletions Telegram/SourceFiles/media/player/media_player_button.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,8 @@ void SettingsButton::prepareFrame() {
const auto height = _quality.height;
const auto text = !height
? QString()
: (height > 4000)
? u"8K"_q
: (height > 2000)
? u"4K"_q
: (height > 1000)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ bool SupportsSpeedControl();

namespace Streaming {

inline constexpr auto kMaxFrameArea = 3840 * 2160;
inline constexpr auto kMaxFrameArea = 7680 * 4320;

inline bool SupportsSpeedControl() {
return Media::Audio::SupportsSpeedControl();
Expand Down
17 changes: 13 additions & 4 deletions Telegram/SourceFiles/storage/localimageloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,13 @@ struct PreparedFileThumbnail {
return result;
}

[[nodiscard]] QSize VideoDimensions(
const Ui::PreparedFileInformation::Video &video) {
return video.dimensions.isEmpty()
? video.thumbnail.size()
: video.dimensions;
}

[[nodiscard]] bool FileThumbnailUploadRequired(
const QString &filemime,
int64 filesize) {
Expand Down Expand Up @@ -815,8 +822,9 @@ void FileLoadTask::process(ProcessArgs &&args) {
if (auto video = std::get_if<Ui::PreparedFileInformation::Video>(
&_information->media)) {
isVideo = true;
auto coverWidth = video->thumbnail.width();
auto coverHeight = video->thumbnail.height();
const auto dimensions = VideoDimensions(*video);
auto coverWidth = dimensions.width();
auto coverHeight = dimensions.height();
if (video->isGifv && !_album) {
attributes.push_back(MTP_documentAttributeAnimated());
}
Expand Down Expand Up @@ -859,8 +867,9 @@ void FileLoadTask::process(ProcessArgs &&args) {
} else if (auto video = std::get_if<Ui::PreparedFileInformation::Video>(
&_information->media)) {
isVideo = true;
auto coverWidth = video->thumbnail.width();
auto coverHeight = video->thumbnail.height();
const auto dimensions = VideoDimensions(*video);
auto coverWidth = dimensions.width();
auto coverHeight = dimensions.height();
if (!_forceFile) {
if (video->isGifv && !_album) {
attributes.push_back(MTP_documentAttributeAnimated());
Expand Down
2 changes: 2 additions & 0 deletions Telegram/SourceFiles/ui/chat/attach/attach_prepare.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ For license and copyright information please follow this link:
#include "ui/rect_part.h"

#include <QtCore/QSemaphore>
#include <QtCore/QSize>
#include <deque>

class QPainter;
Expand Down Expand Up @@ -44,6 +45,7 @@ struct PreparedFileInformation {
bool isWebmSticker = false;
bool supportsStreaming = false;
crl::time duration = -1;
QSize dimensions;
QImage thumbnail;
};

Expand Down
Loading