Skip to content

Commit 9621d03

Browse files
committed
Bring back original video quality option
1 parent b1d08b3 commit 9621d03

12 files changed

Lines changed: 145 additions & 36 deletions

Telegram/SourceFiles/core/core_settings.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,13 @@ void LogPosition(const WindowPosition &position, const QString &name) {
102102
auto result = Media::VideoQuality();
103103
const auto data = static_cast<void*>(&result);
104104
memcpy(data, &value, sizeof(result));
105-
return (result.height <= 4320) ? result : Media::VideoQuality();
105+
106+
const auto height = result.height;
107+
const auto offset = Media::kVideoQualityOriginalOffset;
108+
const auto max = 4320;
109+
return (height <= max || (height >= offset && height <= offset + max))
110+
? result
111+
: Media::VideoQuality();
106112
}
107113

108114
} // namespace

Telegram/SourceFiles/data/data_document.cpp

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -578,18 +578,55 @@ void DocumentData::setVideoQualities(
578578
}
579579
qualities.erase(qualities.begin() + count, qualities.end());
580580
if (!qualities.empty()) {
581-
if (const auto mine = resolveVideoQuality()) {
582-
if (mine > qualities.front()->resolveVideoQuality()) {
583-
qualities.insert(begin(qualities), this);
581+
auto mine = resolveVideoQuality();
582+
for (const auto &quality : qualities) {
583+
const auto qres = quality->resolveVideoQuality();
584+
if (qres > mine) {
585+
mine = qres;
584586
}
585587
}
588+
if (mine) {
589+
qualities.insert(begin(qualities), this);
590+
}
586591
}
587592
data->qualities = std::move(qualities);
588593
}
589594

590595
int DocumentData::resolveVideoQuality() const {
591-
const auto size = isVideoFile() ? dimensions : QSize();
592-
return size.isEmpty() ? 0 : std::min(size.width(), size.height());
596+
if (const auto data = video()) {
597+
if (!data->realVideoSize.isEmpty()) {
598+
const auto size = data->realVideoSize;
599+
const auto result = std::min(size.width(), size.height());
600+
return result;
601+
}
602+
const auto apiSize = isVideoFile() ? dimensions : QSize();
603+
const auto api = apiSize.isEmpty()
604+
? 0
605+
: std::min(apiSize.width(), apiSize.height());
606+
if (!data->qualities.empty()) {
607+
auto transcodeMax = 0;
608+
for (const auto &quality : data->qualities) {
609+
if (quality != this) {
610+
const auto qres = quality->resolveVideoQuality();
611+
if (qres > transcodeMax) {
612+
transcodeMax = qres;
613+
}
614+
}
615+
}
616+
if (transcodeMax > 0) {
617+
// trust attributes if delta is small
618+
if (api < transcodeMax || api > transcodeMax * 1.5) {
619+
return transcodeMax;
620+
}
621+
return api;
622+
}
623+
}
624+
}
625+
const auto apiSize = isVideoFile() ? dimensions : QSize();
626+
const auto api = apiSize.isEmpty()
627+
? 0
628+
: std::min(apiSize.width(), apiSize.height());
629+
return api;
593630
}
594631

595632
auto DocumentData::resolveQualities(HistoryItem *context) const
@@ -611,19 +648,29 @@ not_null<DocumentData*> DocumentData::chooseQuality(
611648
return this;
612649
}
613650
const auto height = int(request.height);
614-
auto closest = this;
615-
auto closestAbs = std::abs(height - resolveVideoQuality());
616-
auto closestSize = size;
651+
if (height >= Media::kVideoQualityOriginalOffset) {
652+
return this;
653+
}
654+
655+
auto closest = (DocumentData*)nullptr;
656+
auto closestAbs = -1;
657+
auto closestSize = -1;
658+
617659
for (const auto &quality : list) {
618-
const auto abs = std::abs(height - quality->resolveVideoQuality());
619-
if (abs < closestAbs
620-
|| (abs == closestAbs && quality->size < closestSize)) {
660+
const auto qres = quality->resolveVideoQuality();
661+
const auto abs = std::abs(height - qres);
662+
if (!closest
663+
|| abs < closestAbs
664+
|| (abs == closestAbs &&
665+
(quality->size < closestSize
666+
|| (closest == this && quality != this)))) {
621667
closest = quality;
622668
closestAbs = abs;
623669
closestSize = quality->size;
624670
}
625671
}
626-
return closest;
672+
673+
return closest ? closest : this;
627674
}
628675

629676
void DocumentData::validateLottieSticker() {

Telegram/SourceFiles/data/data_document.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ struct VoiceData : public DocumentAdditionalData {
9999
struct VideoData : public DocumentAdditionalData {
100100
QString codec;
101101
std::vector<not_null<DocumentData*>> qualities;
102+
QSize realVideoSize;
102103
};
103104

104105
using RoundData = VoiceData;

Telegram/SourceFiles/media/media_common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ inline constexpr auto kSpeedMin = 0.5;
4141
inline constexpr auto kSpeedMax = 2.5;
4242
inline constexpr auto kSpedUpDefault = 1.7;
4343

44+
inline constexpr auto kVideoQualityOriginalOffset = 1000000;
45+
4446
[[nodiscard]] inline bool EqualSpeeds(float64 a, float64 b) {
4547
return int(base::SafeRound(a * 10.)) == int(base::SafeRound(b * 10.));
4648
}

Telegram/SourceFiles/media/player/media_player_button.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -437,13 +437,16 @@ void SettingsButton::prepareFrame() {
437437
: u"%1X"_q.arg(rounded / 10);
438438
paintBadge(p, text, RectPart::TopLeft, color);
439439
}
440-
const auto text = (!_quality)
440+
const auto displayQuality = (_quality >= Media::kVideoQualityOriginalOffset)
441+
? (_quality - Media::kVideoQualityOriginalOffset)
442+
: _quality;
443+
const auto text = (!displayQuality)
441444
? QString()
442-
: (_quality > 2000)
445+
: (displayQuality > 2000)
443446
? u"4K"_q
444-
: (_quality > 1000)
447+
: (displayQuality > 1000)
445448
? u"FHD"_q
446-
: (_quality > 700)
449+
: (displayQuality > 700)
447450
? u"HD"_q
448451
: u"SD"_q;
449452
if (!text.isEmpty()) {

Telegram/SourceFiles/media/player/media_player_dropdown.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ For license and copyright information please follow this link:
77
*/
88
#include "media/player/media_player_dropdown.h"
99

10+
#include <algorithm>
1011
#include "base/invoke_queued.h"
1112
#include "base/timer.h"
1213
#include "lang/lang_keys.h"
@@ -819,7 +820,12 @@ void SpeedController::fillMenu(not_null<Ui::DropdownMenu*> menu) {
819820

820821
const auto add = [&](int quality) {
821822
const auto automatic = tr::lng_mediaview_quality_auto(tr::now);
822-
const auto text = quality ? u"%1p"_q.arg(quality) : automatic;
823+
const auto offset = Media::kVideoQualityOriginalOffset;
824+
const auto text = !quality
825+
? automatic
826+
: (quality >= offset)
827+
? u"Original (%1p)"_q.arg(std::clamp(quality - offset, 0, 4320))
828+
: u"%1p"_q.arg(quality);
823829
auto action = base::make_unique_q<Ui::Menu::Action>(
824830
raw,
825831
st.qualityMenu,
@@ -852,8 +858,14 @@ void SpeedController::fillMenu(not_null<Ui::DropdownMenu*> menu) {
852858
: !quality;
853859
raw->action()->setEnabled(!chosen);
854860
if (!quality) {
855-
raw->action()->setText(automatic
856-
+ (now.manual ? QString() : u"\t%1p"_q.arg(now.height)));
861+
const auto offset = Media::kVideoQualityOriginalOffset;
862+
const auto displayHeight = (now.height >= offset)
863+
? std::clamp(int(now.height - offset), 0, 4320)
864+
: now.height;
865+
const auto suffix = now.manual
866+
? QString()
867+
: u"\t%1p"_q.arg(displayHeight);
868+
raw->action()->setText(automatic + suffix);
857869
}
858870
check->setVisible(chosen);
859871
}, raw->lifetime());

Telegram/SourceFiles/media/streaming/media_streaming_common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ struct TrackState {
5959
struct VideoInformation {
6060
TrackState state;
6161
QSize size;
62+
QSize realSize;
6263
QImage cover;
6364
int rotation = 0;
6465
bool alpha = false;

Telegram/SourceFiles/media/streaming/media_streaming_player.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ void SaveValidVideoInformation(
6262

6363
SaveValidStateInformation(to.state, std::move(from.state));
6464
to.size = from.size;
65+
to.realSize = from.realSize;
6566
to.cover = std::move(from.cover);
6667
to.rotation = from.rotation;
6768
to.alpha = from.alpha;

Telegram/SourceFiles/media/streaming/media_streaming_video_track.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,10 @@ void VideoTrackObject::callReady() {
716716
const auto frame = _shared->frameForPaint();
717717
++_frameIndex;
718718

719+
const auto frameSize = frame->original.isNull()
720+
? frame->yuv.size
721+
: frame->original.size();
722+
719723
base::take(_ready)({ VideoInformation{
720724
.state = {
721725
.position = _syncTimePoint.trackTime,
@@ -725,7 +729,10 @@ void VideoTrackObject::callReady() {
725729
.duration = _stream.duration,
726730
},
727731
.size = FFmpeg::TransposeSizeByRotation(
728-
FFmpeg::CorrectByAspect(frame->original.size(), _stream.aspect),
732+
FFmpeg::CorrectByAspect(frameSize, _stream.aspect),
733+
_stream.rotation),
734+
.realSize = FFmpeg::TransposeSizeByRotation(
735+
frameSize,
729736
_stream.rotation),
730737
.cover = frame->original,
731738
.rotation = _stream.rotation,

Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,7 +1181,9 @@ QSize OverlayWidget::videoSize() const {
11811181
Expects(videoShown());
11821182

11831183
const auto use = (_document && _chosenQuality != _document)
1184-
? _document->dimensions
1184+
// get dimentions using the selected quality
1185+
// not the original
1186+
? _chosenQuality->dimensions
11851187
: _streamed->instance.info().video.size;
11861188
return flipSizeByRotation(use);
11871189
}
@@ -4265,8 +4267,21 @@ void OverlayWidget::initStreamingThumbnail() {
42654267
void OverlayWidget::streamingReady(Streaming::Information &&info) {
42664268
markStreamedReady();
42674269
if (videoShown()) {
4270+
if (_document && _streamed && _streamed->ready) {
4271+
const auto targetDocument = _chosenQuality ? _chosenQuality : _document;
4272+
if (const auto video = targetDocument->video()) {
4273+
video->realVideoSize = info.video.realSize;
4274+
}
4275+
}
42684276
applyVideoSize();
42694277
_streamedQualityChangeFrame = QImage();
4278+
if (_streamed && _streamed->controls) {
4279+
crl::on_main(_widget, [=] {
4280+
if (_streamed && _streamed->controls) {
4281+
_streamed->controls->updateSpeedToggleQuality();
4282+
}
4283+
});
4284+
}
42704285
} else {
42714286
updateContentRect();
42724287
}
@@ -4659,12 +4674,16 @@ void OverlayWidget::restartAtSeekPosition(crl::time position) {
46594674
}
46604675
const auto overrideDuration = _stories
46614676
|| (_chosenQuality && _chosenQuality != _document);
4677+
const auto durationDocument = (_chosenQuality && _chosenQuality != _document)
4678+
? _chosenQuality
4679+
: _document;
4680+
46624681
auto options = Streaming::PlaybackOptions{
46634682
.position = position,
46644683
.durationOverride = ((overrideDuration
4665-
&& _document
4666-
&& _document->hasDuration())
4667-
? _document->duration()
4684+
&& durationDocument
4685+
&& durationDocument->hasDuration())
4686+
? durationDocument->duration()
46684687
: crl::time(0)),
46694688
.hwAllowed = Core::App().settings().hardwareAcceleratedVideo(),
46704689
.seekable = !_stories,
@@ -4769,21 +4788,30 @@ std::vector<int> OverlayWidget::playbackControlsQualities() {
47694788
}
47704789
auto result = std::vector<int>();
47714790
result.reserve(list.size());
4791+
auto seen = std::vector<int>();
47724792
for (const auto &quality : list) {
4773-
result.push_back(quality->resolveVideoQuality());
4793+
const auto res = quality->resolveVideoQuality();
4794+
const auto value = (quality == _document)
4795+
? (res + Media::kVideoQualityOriginalOffset)
4796+
: res;
4797+
if (!ranges::contains(seen, value)) {
4798+
result.push_back(value);
4799+
seen.push_back(value);
4800+
}
47744801
}
47754802
return result;
47764803
}
47774804

47784805
VideoQuality OverlayWidget::playbackControlsCurrentQuality() {
4779-
return _chosenQuality
4780-
? VideoQuality{
4781-
.manual = _quality.manual,
4782-
.height = uint32(_chosenQuality->resolveVideoQuality()),
4783-
}
4784-
: _quality;
4806+
if (!_chosenQuality) {
4807+
return _quality;
4808+
}
4809+
auto height = uint32(_chosenQuality->resolveVideoQuality());
4810+
if (_chosenQuality == _document) {
4811+
height += Media::kVideoQualityOriginalOffset;
4812+
}
4813+
return { .manual = _quality.manual, .height = height };
47854814
}
4786-
47874815
void OverlayWidget::playbackControlsQualityChanged(int quality) {
47884816
applyVideoQuality({
47894817
.manual = (quality > 0),
@@ -5085,6 +5113,7 @@ void OverlayWidget::updatePlaybackState() {
50855113
_streamedPosition = state.position;
50865114
if (_streamed->controls) {
50875115
_streamed->controls->updatePlayback(state);
5116+
_streamed->controls->updateSpeedToggleQuality();
50885117
_touchbarTrackState.fire_copy(state);
50895118
updatePowerSaveBlocker(state);
50905119
}

0 commit comments

Comments
 (0)