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 kFixManualLargeVideoDuration = 5 * 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() {
const auto &settings = Core::App().settings();
@ -2435,6 +2437,9 @@ void GroupCall::updateRequestedVideoChannels() {
channels.reserve(_activeVideoTracks.size());
const auto &camera = cameraSharingEndpoint();
const auto &screen = screenSharingEndpoint();
auto mediums = 0;
auto fullcameras = 0;
auto fullscreencasts = 0;
for (const auto &[endpoint, video] : _activeVideoTracks) {
const auto &endpointId = endpoint.id;
if (endpointId == camera || endpointId == screen) {
@ -2447,24 +2452,74 @@ void GroupCall::updateRequestedVideoChannels() {
if (!params) {
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({
.audioSsrc = participant->ssrc,
.endpointId = endpointId,
.ssrcGroups = (params->camera.endpointId == endpointId
? params->camera.ssrcGroups
: params->screen.ssrcGroups),
.minQuality = ((video->quality == Group::VideoQuality::Full
&& endpoint.type == VideoEndpointType::Screen)
? 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),
.minQuality = min,
.maxQuality = max,
});
}
// 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));
}

View file

@ -191,7 +191,7 @@ void Viewport::updateSelected(QPoint position) {
return;
}
for (const auto &tile : _tiles) {
const auto geometry = tile->shown()
const auto geometry = tile->visible()
? tile->geometry()
: QRect();
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 kSmall = style::ConvertScale(240);
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
: (min >= kSmall)
? VideoQuality::Medium

View file

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

View file

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

View file

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

View file

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