Limit requested qualities to 4 Full / 16 Medium.

This commit is contained in:
John Preston 2021-06-18 18:43:13 +04:00
parent 7a588be54f
commit 8897f9e46a
6 changed files with 83 additions and 21 deletions

View file

@ -49,6 +49,8 @@ constexpr auto kUpdateSendActionEach = crl::time(500);
constexpr auto kPlayConnectingEach = crl::time(1056) + 2 * crl::time(1000); constexpr auto kPlayConnectingEach = crl::time(1056) + 2 * crl::time(1000);
constexpr auto kFixManualLargeVideoDuration = 5 * crl::time(1000); constexpr auto kFixManualLargeVideoDuration = 5 * crl::time(1000);
constexpr auto kFixSpeakingLargeVideoDuration = 3 * crl::time(1000); constexpr auto kFixSpeakingLargeVideoDuration = 3 * crl::time(1000);
constexpr auto kFullAsMediumsCount = 4; // 1 Full is like 4 Mediums.
constexpr auto kMaxMediumQualities = 16; // 4 Fulls or 16 Mediums.
[[nodiscard]] std::unique_ptr<Webrtc::MediaDevices> CreateMediaDevices() { [[nodiscard]] std::unique_ptr<Webrtc::MediaDevices> CreateMediaDevices() {
const auto &settings = Core::App().settings(); const auto &settings = Core::App().settings();
@ -2435,6 +2437,9 @@ void GroupCall::updateRequestedVideoChannels() {
channels.reserve(_activeVideoTracks.size()); channels.reserve(_activeVideoTracks.size());
const auto &camera = cameraSharingEndpoint(); const auto &camera = cameraSharingEndpoint();
const auto &screen = screenSharingEndpoint(); const auto &screen = screenSharingEndpoint();
auto mediums = 0;
auto fullcameras = 0;
auto fullscreencasts = 0;
for (const auto &[endpoint, video] : _activeVideoTracks) { for (const auto &[endpoint, video] : _activeVideoTracks) {
const auto &endpointId = endpoint.id; const auto &endpointId = endpoint.id;
if (endpointId == camera || endpointId == screen) { if (endpointId == camera || endpointId == screen) {
@ -2447,24 +2452,74 @@ void GroupCall::updateRequestedVideoChannels() {
if (!params) { if (!params) {
continue; continue;
} }
const auto min = (video->quality == Group::VideoQuality::Full
&& endpoint.type == VideoEndpointType::Screen)
? Quality::Full
: Quality::Thumbnail;
const auto max = (video->quality == Group::VideoQuality::Full)
? Quality::Full
: (video->quality == Group::VideoQuality::Medium
&& endpoint.type != VideoEndpointType::Screen)
? Quality::Medium
: Quality::Thumbnail;
if (max == Quality::Full) {
if (endpoint.type == VideoEndpointType::Screen) {
++fullscreencasts;
} else {
++fullcameras;
}
} else if (max == Quality::Medium) {
++mediums;
}
channels.push_back({ channels.push_back({
.audioSsrc = participant->ssrc, .audioSsrc = participant->ssrc,
.endpointId = endpointId, .endpointId = endpointId,
.ssrcGroups = (params->camera.endpointId == endpointId .ssrcGroups = (params->camera.endpointId == endpointId
? params->camera.ssrcGroups ? params->camera.ssrcGroups
: params->screen.ssrcGroups), : params->screen.ssrcGroups),
.minQuality = ((video->quality == Group::VideoQuality::Full .minQuality = min,
&& endpoint.type == VideoEndpointType::Screen) .maxQuality = max,
? Quality::Full
: Quality::Thumbnail),
.maxQuality = ((video->quality == Group::VideoQuality::Full)
? Quality::Full
: (video->quality == Group::VideoQuality::Medium
&& endpoint.type != VideoEndpointType::Screen)
? Quality::Medium
: Quality::Thumbnail),
}); });
} }
// We limit `count(Full) * kFullAsMediumsCount + count(medium)`.
//
// Try to preserve all qualities; If not
// Try to preserve all screencasts as Full and cameras as Medium; If not
// Try to preserve all screencasts as Full; If not
// Try to preserve all cameras as Medium;
const auto mediumsCount = mediums
+ (fullcameras + fullscreencasts) * kFullAsMediumsCount;
const auto downgradeSome = (mediumsCount > kMaxMediumQualities);
const auto downgradeAll = (fullscreencasts * kFullAsMediumsCount)
> kMaxMediumQualities;
if (downgradeSome) {
for (auto &channel : channels) {
if (channel.maxQuality == Quality::Full) {
const auto camera = (channel.minQuality != Quality::Full);
if (camera) {
channel.maxQuality = Quality::Medium;
} else if (downgradeAll) {
channel.maxQuality
= channel.minQuality
= Quality::Thumbnail;
--fullscreencasts;
}
}
}
mediums += fullcameras;
fullcameras = 0;
if (downgradeAll) {
fullscreencasts = 0;
}
}
if (mediums > kMaxMediumQualities) {
for (auto &channel : channels) {
if (channel.maxQuality == Quality::Medium) {
channel.maxQuality = Quality::Thumbnail;
}
}
}
_instance->setRequestedVideoChannels(std::move(channels)); _instance->setRequestedVideoChannels(std::move(channels));
} }

View file

@ -191,7 +191,7 @@ void Viewport::updateSelected(QPoint position) {
return; return;
} }
for (const auto &tile : _tiles) { for (const auto &tile : _tiles) {
const auto geometry = tile->shown() const auto geometry = tile->visible()
? tile->geometry() ? tile->geometry()
: QRect(); : QRect();
if (geometry.contains(position)) { if (geometry.contains(position)) {
@ -763,7 +763,11 @@ void Viewport::setTileGeometry(not_null<VideoTile*> tile, QRect geometry) {
const auto kMedium = style::ConvertScale(540); const auto kMedium = style::ConvertScale(540);
const auto kSmall = style::ConvertScale(240); const auto kSmall = style::ConvertScale(240);
const auto &endpoint = tile->endpoint(); const auto &endpoint = tile->endpoint();
const auto quality = (min >= kMedium) const auto forceThumbnailQuality = !wide()
&& (ranges::count(_tiles, false, &VideoTile::hidden) > 1);
const auto quality = forceThumbnailQuality
? VideoQuality::Thumbnail
: (min >= kMedium)
? VideoQuality::Full ? VideoQuality::Full
: (min >= kSmall) : (min >= kSmall)
? VideoQuality::Medium ? VideoQuality::Medium

View file

@ -439,7 +439,7 @@ void Viewport::RendererGL::paint(
validateDatas(); validateDatas();
auto index = 0; auto index = 0;
for (const auto &tile : _owner->_tiles) { for (const auto &tile : _owner->_tiles) {
if (!tile->shown()) { if (!tile->visible()) {
index++; index++;
continue; continue;
} }

View file

@ -45,7 +45,7 @@ void Viewport::RendererSW::paintFallback(
tileData.stale = true; tileData.stale = true;
} }
for (const auto &tile : _owner->_tiles) { for (const auto &tile : _owner->_tiles) {
if (!tile->shown()) { if (!tile->visible()) {
continue; continue;
} }
paintTile(p, tile.get(), bounding, bg); paintTile(p, tile.get(), bounding, bg);

View file

@ -82,14 +82,14 @@ bool Viewport::VideoTile::screencast() const {
void Viewport::VideoTile::setGeometry( void Viewport::VideoTile::setGeometry(
QRect geometry, QRect geometry,
TileAnimation animation) { TileAnimation animation) {
_shown = true; _hidden = false;
_geometry = geometry; _geometry = geometry;
_animation = animation; _animation = animation;
updateTopControlsPosition(); updateTopControlsPosition();
} }
void Viewport::VideoTile::hide() { void Viewport::VideoTile::hide() {
_shown = false; _hidden = true;
_quality = std::nullopt; _quality = std::nullopt;
} }
@ -106,7 +106,7 @@ void Viewport::VideoTile::toggleTopControlsShown(bool shown) {
} }
bool Viewport::VideoTile::updateRequestedQuality(VideoQuality quality) { bool Viewport::VideoTile::updateRequestedQuality(VideoQuality quality) {
if (!_shown) { if (_hidden) {
_quality = std::nullopt; _quality = std::nullopt;
return false; return false;
} else if (_quality && *_quality == quality) { } else if (_quality && *_quality == quality) {
@ -249,7 +249,7 @@ void Viewport::VideoTile::setup(rpl::producer<bool> pinned) {
}) | rpl::start_with_next([=](bool pinned) { }) | rpl::start_with_next([=](bool pinned) {
_pinned = pinned; _pinned = pinned;
updateTopControlsSize(); updateTopControlsSize();
if (_shown) { if (!_hidden) {
updateTopControlsPosition(); updateTopControlsPosition();
_update(); _update();
} }

View file

@ -45,8 +45,11 @@ public:
[[nodiscard]] bool pinned() const { [[nodiscard]] bool pinned() const {
return _pinned; return _pinned;
} }
[[nodiscard]] bool shown() const { [[nodiscard]] bool hidden() const {
return _shown && !_geometry.isEmpty(); return _hidden;
}
[[nodiscard]] bool visible() const {
return !_hidden && !_geometry.isEmpty();
} }
[[nodiscard]] QRect pinOuter() const; [[nodiscard]] QRect pinOuter() const;
[[nodiscard]] QRect pinInner() const; [[nodiscard]] QRect pinInner() const;
@ -115,7 +118,7 @@ private:
Ui::Animations::Simple _topControlsShownAnimation; Ui::Animations::Simple _topControlsShownAnimation;
bool _topControlsShown = false; bool _topControlsShown = false;
bool _pinned = false; bool _pinned = false;
bool _shown = false; bool _hidden = true;
std::optional<VideoQuality> _quality; std::optional<VideoQuality> _quality;
rpl::lifetime _lifetime; rpl::lifetime _lifetime;