Skip to content

Commit 14dab6f

Browse files
committed
Bring back original video quality option
1 parent b1d08b3 commit 14dab6f

12 files changed

Lines changed: 130 additions & 33 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: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -578,18 +578,41 @@ 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 {
596+
if (const auto data = video()) {
597+
if (!data->realVideoSize.isEmpty()) {
598+
const auto size = data->realVideoSize;
599+
return std::min(size.width(), size.height());
600+
}
601+
if (!data->qualities.empty()) {
602+
auto result = 0;
603+
for (const auto &quality : data->qualities) {
604+
if (quality != this) {
605+
result = std::max(result, quality->resolveVideoQuality());
606+
}
607+
}
608+
if (result > 0) {
609+
return result;
610+
}
611+
}
612+
}
591613
const auto size = isVideoFile() ? dimensions : QSize();
592-
return size.isEmpty() ? 0 : std::min(size.width(), size.height());
614+
const auto result = size.isEmpty() ? 0 : std::min(size.width(), size.height());
615+
return result;
593616
}
594617

595618
auto DocumentData::resolveQualities(HistoryItem *context) const
@@ -611,19 +634,31 @@ not_null<DocumentData*> DocumentData::chooseQuality(
611634
return this;
612635
}
613636
const auto height = int(request.height);
614-
auto closest = this;
615-
auto closestAbs = std::abs(height - resolveVideoQuality());
616-
auto closestSize = size;
637+
if (height >= Media::kVideoQualityOriginalOffset) {
638+
return this;
639+
}
640+
641+
// If a standard quality is requested, try to find the best match
642+
// among transcoded streams only
643+
auto closest = (DocumentData*)nullptr;
644+
auto closestAbs = -1;
645+
auto closestSize = -1;
646+
617647
for (const auto &quality : list) {
648+
if (quality == this) {
649+
continue; // Skip Original stream for standard quality requests
650+
}
618651
const auto abs = std::abs(height - quality->resolveVideoQuality());
619-
if (abs < closestAbs
652+
if (!closest
653+
|| abs < closestAbs
620654
|| (abs == closestAbs && quality->size < closestSize)) {
621655
closest = quality;
622656
closestAbs = abs;
623657
closestSize = quality->size;
624658
}
625659
}
626-
return closest;
660+
661+
return closest ? closest : this;
627662
}
628663

629664
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: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -819,7 +819,12 @@ void SpeedController::fillMenu(not_null<Ui::DropdownMenu*> menu) {
819819

820820
const auto add = [&](int quality) {
821821
const auto automatic = tr::lng_mediaview_quality_auto(tr::now);
822-
const auto text = quality ? u"%1p"_q.arg(quality) : automatic;
822+
const auto offset = Media::kVideoQualityOriginalOffset;
823+
const auto text = !quality
824+
? automatic
825+
: (quality >= offset)
826+
? u"Original (%1p)"_q.arg(quality - offset)
827+
: u"%1p"_q.arg(quality);
823828
auto action = base::make_unique_q<Ui::Menu::Action>(
824829
raw,
825830
st.qualityMenu,
@@ -852,8 +857,14 @@ void SpeedController::fillMenu(not_null<Ui::DropdownMenu*> menu) {
852857
: !quality;
853858
raw->action()->setEnabled(!chosen);
854859
if (!quality) {
855-
raw->action()->setText(automatic
856-
+ (now.manual ? QString() : u"\t%1p"_q.arg(now.height)));
860+
const auto offset = Media::kVideoQualityOriginalOffset;
861+
const auto displayHeight = (now.height >= offset)
862+
? (now.height - offset)
863+
: now.height;
864+
const auto suffix = now.manual
865+
? QString()
866+
: u"\t%1p"_q.arg(displayHeight);
867+
raw->action()->setText(automatic + suffix);
857868
}
858869
check->setVisible(chosen);
859870
}, 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: 42 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,22 @@ 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+
const auto weak = base::make_weak(_widget);
4280+
crl::on_main(weak, [=] {
4281+
if (_streamed && _streamed->controls) {
4282+
_streamed->controls->updateSpeedToggleQuality();
4283+
}
4284+
});
4285+
}
42704286
} else {
42714287
updateContentRect();
42724288
}
@@ -4659,12 +4675,16 @@ void OverlayWidget::restartAtSeekPosition(crl::time position) {
46594675
}
46604676
const auto overrideDuration = _stories
46614677
|| (_chosenQuality && _chosenQuality != _document);
4678+
const auto durationDocument = (_chosenQuality && _chosenQuality != _document)
4679+
? _chosenQuality
4680+
: _document;
4681+
46624682
auto options = Streaming::PlaybackOptions{
46634683
.position = position,
46644684
.durationOverride = ((overrideDuration
4665-
&& _document
4666-
&& _document->hasDuration())
4667-
? _document->duration()
4685+
&& durationDocument
4686+
&& durationDocument->hasDuration())
4687+
? durationDocument->duration()
46684688
: crl::time(0)),
46694689
.hwAllowed = Core::App().settings().hardwareAcceleratedVideo(),
46704690
.seekable = !_stories,
@@ -4769,21 +4789,30 @@ std::vector<int> OverlayWidget::playbackControlsQualities() {
47694789
}
47704790
auto result = std::vector<int>();
47714791
result.reserve(list.size());
4792+
auto seen = std::vector<int>();
47724793
for (const auto &quality : list) {
4773-
result.push_back(quality->resolveVideoQuality());
4794+
const auto res = quality->resolveVideoQuality();
4795+
const auto value = (quality == _document)
4796+
? (res + Media::kVideoQualityOriginalOffset)
4797+
: res;
4798+
if (std::find(seen.begin(), seen.end(), value) == seen.end()) {
4799+
result.push_back(value);
4800+
seen.push_back(value);
4801+
}
47744802
}
47754803
return result;
47764804
}
47774805

47784806
VideoQuality OverlayWidget::playbackControlsCurrentQuality() {
4779-
return _chosenQuality
4780-
? VideoQuality{
4781-
.manual = _quality.manual,
4782-
.height = uint32(_chosenQuality->resolveVideoQuality()),
4783-
}
4784-
: _quality;
4807+
if (!_chosenQuality) {
4808+
return _quality;
4809+
}
4810+
auto height = uint32(_chosenQuality->resolveVideoQuality());
4811+
if (_chosenQuality == _document) {
4812+
height += Media::kVideoQualityOriginalOffset;
4813+
}
4814+
return { .manual = _quality.manual, .height = height };
47854815
}
4786-
47874816
void OverlayWidget::playbackControlsQualityChanged(int quality) {
47884817
applyVideoQuality({
47894818
.manual = (quality > 0),
@@ -5085,6 +5114,7 @@ void OverlayWidget::updatePlaybackState() {
50855114
_streamedPosition = state.position;
50865115
if (_streamed->controls) {
50875116
_streamed->controls->updatePlayback(state);
5117+
_streamed->controls->updateSpeedToggleQuality();
50885118
_touchbarTrackState.fire_copy(state);
50895119
updatePowerSaveBlocker(state);
50905120
}

0 commit comments

Comments
 (0)