Update tgcalls, request required video channels.

This commit is contained in:
John Preston 2021-05-12 14:49:26 +04:00
parent 1471e9b8e2
commit e39ffbc83c
5 changed files with 116 additions and 105 deletions

View File

@ -538,6 +538,7 @@ void GroupCall::subscribeToReal(not_null<Data::GroupCall*> real) {
using Update = Data::GroupCall::ParticipantUpdate;
real->participantUpdated(
) | rpl::start_with_next([=](const Update &data) {
auto changed = false;
auto newLarge = _videoEndpointLarge.current();
auto updateCameraNotStreams = std::string();
auto updateScreenNotStreams = std::string();
@ -555,6 +556,8 @@ void GroupCall::subscribeToReal(not_null<Data::GroupCall*> real) {
}
if (_videoEndpointLarge.current() != newLarge) {
setVideoEndpointLarge(newLarge);
} else if (changed) {
updateRequestedVideoChannelsDelayed();
}
if (!updateCameraNotStreams.empty()) {
_streamsVideoUpdated.fire({ updateCameraNotStreams, false });
@ -575,13 +578,13 @@ void GroupCall::subscribeToReal(not_null<Data::GroupCall*> real) {
if (!nowCameraEndpoint.empty()
&& _activeVideoEndpoints.emplace(
nowCameraEndpoint,
EndpointType::Camera).second
&& _incomingVideoEndpoints.contains(nowCameraEndpoint)) {
EndpointType::Camera).second) {
changed = true;
_streamsVideoUpdated.fire({ nowCameraEndpoint, true });
}
if (!wasCameraEndpoint.empty()
&& _activeVideoEndpoints.remove(wasCameraEndpoint)
&& _incomingVideoEndpoints.contains(wasCameraEndpoint)) {
&& _activeVideoEndpoints.remove(wasCameraEndpoint)) {
changed = true;
updateCameraNotStreams = wasCameraEndpoint;
if (newLarge.endpoint == wasCameraEndpoint) {
newLarge = VideoEndpoint();
@ -599,13 +602,13 @@ void GroupCall::subscribeToReal(not_null<Data::GroupCall*> real) {
if (!nowScreenEndpoint.empty()
&& _activeVideoEndpoints.emplace(
nowScreenEndpoint,
EndpointType::Screen).second
&& _incomingVideoEndpoints.contains(nowScreenEndpoint)) {
EndpointType::Screen).second) {
changed = true;
_streamsVideoUpdated.fire({ nowScreenEndpoint, true });
}
if (!wasScreenEndpoint.empty()
&& _activeVideoEndpoints.remove(wasScreenEndpoint)
&& _incomingVideoEndpoints.contains(wasScreenEndpoint)) {
&& _activeVideoEndpoints.remove(wasScreenEndpoint)) {
changed = true;
updateScreenNotStreams = wasScreenEndpoint;
if (newLarge.endpoint == wasScreenEndpoint) {
newLarge = VideoEndpoint();
@ -872,9 +875,8 @@ void GroupCall::setMyEndpointType(
if (endpoint.empty()) {
return;
} else if (type == EndpointType::None) {
const auto was1 = _incomingVideoEndpoints.remove(endpoint);
const auto was2 = _activeVideoEndpoints.remove(endpoint);
if (was1 && was2) {
const auto was = _activeVideoEndpoints.remove(endpoint);
if (was) {
auto newLarge = _videoEndpointLarge.current();
if (newLarge.endpoint == endpoint) {
_videoEndpointPinned = false;
@ -883,11 +885,10 @@ void GroupCall::setMyEndpointType(
_streamsVideoUpdated.fire({ endpoint, false });
}
} else {
const auto now1 = _incomingVideoEndpoints.emplace(endpoint).second;
const auto now2 = _activeVideoEndpoints.emplace(
const auto now = _activeVideoEndpoints.emplace(
endpoint,
type).second;
if (now1 || now2) {
if (now) {
_streamsVideoUpdated.fire({ endpoint, true });
}
const auto nowLarge = activeVideoEndpointType(
@ -913,9 +914,6 @@ void GroupCall::setScreenEndpoint(std::string endpoint) {
if (_screenEndpoint.empty()) {
return;
}
if (_instance) {
_instance->setIgnoreVideoEndpointIds({ _screenEndpoint });
}
if (isSharingScreen()) {
setMyEndpointType(_screenEndpoint, EndpointType::Screen);
}
@ -1014,13 +1012,19 @@ void GroupCall::rejoin(not_null<PeerData*> as) {
const auto json = QByteArray::fromStdString(payload.json);
const auto wasMuteState = muted();
const auto wasVideoMuted = !isSharingCamera();
using Flag = MTPphone_JoinGroupCall::Flag;
const auto flags = (wasMuteState != MuteState::Active
? Flag::f_muted
: Flag(0))
| (_joinHash.isEmpty()
? Flag(0)
: Flag::f_invite_hash)
| (wasVideoMuted
? Flag::f_video_muted
: Flag(0));
_api.request(MTPphone_JoinGroupCall(
MTP_flags((wasMuteState != MuteState::Active
? Flag::f_muted
: Flag(0)) | (_joinHash.isEmpty()
? Flag(0)
: Flag::f_invite_hash)),
MTP_flags(flags),
inputCall(),
_joinAs->input,
MTP_string(_joinHash),
@ -1037,7 +1041,9 @@ void GroupCall::rejoin(not_null<PeerData*> as) {
_peer->session().api().applyUpdates(updates);
applyQueuedSelfUpdates();
checkFirstTimeJoined();
sendSelfUpdate(SendUpdateType::VideoMuted);
if (wasVideoMuted == isSharingCamera()) {
sendSelfUpdate(SendUpdateType::VideoMuted);
}
if (_screenSsrc && isSharingScreen()) {
LOG(("Call Info: Screen rejoin after rejoin()."));
rejoinPresentation();
@ -1452,8 +1458,9 @@ void GroupCall::handlePossibleCreateOrJoinResponse(
const auto json = data.vdata().v;
setCameraEndpoint(ParseVideoEndpoint(json));
_instance->setJoinResponsePayload(json.toStdString());
updateRequestedVideoChannels();
checkMediaChannelDescriptions();
});
checkMediaChannelDescriptions();
}
}
@ -1800,12 +1807,6 @@ void GroupCall::ensureControllerCreated() {
.createAudioDeviceModule = Webrtc::AudioDeviceModuleCreator(
settings.callAudioBackend()),
.videoCapture = _cameraCapture,
.incomingVideoSourcesUpdated = [=](
std::vector<std::string> endpointIds) {
crl::on_main(weak, [=, endpoints = std::move(endpointIds)] {
setIncomingVideoEndpoints(endpoints);
});
},
.requestBroadcastPart = [=, call = base::make_weak(this)](
int64_t time,
int64_t period,
@ -1854,9 +1855,10 @@ void GroupCall::ensureControllerCreated() {
_instance = std::make_unique<tgcalls::GroupInstanceCustomImpl>(
std::move(descriptor));
_videoEndpointLarge.changes(
_videoEndpointLarge.value(
) | rpl::start_with_next([=](const VideoEndpoint &endpoint) {
_instance->setFullSizeVideoEndpointId(endpoint.endpoint);
updateRequestedVideoChannels();
_videoLargeTrack = LargeTrack();
_videoLargeTrackWrap = nullptr;
if (!endpoint) {
@ -1873,10 +1875,6 @@ void GroupCall::ensureControllerCreated() {
updateInstanceMuteState();
updateInstanceVolumes();
if (!_screenEndpoint.empty()) {
_instance->setIgnoreVideoEndpointIds({ _screenEndpoint });
}
//raw->setAudioOutputDuckingEnabled(settings.callAudioDuckingEnabled());
}
@ -2071,43 +2069,52 @@ void GroupCall::mediaChannelDescriptionsCancel(
}
}
void GroupCall::setIncomingVideoEndpoints(
const std::vector<std::string> &endpoints) {
auto newLarge = _videoEndpointLarge.current();
auto newLargeFound = false;
auto removed = _incomingVideoEndpoints;
const auto feedOne = [&](const std::string &endpoint) {
if (endpoint.empty()) {
return;
} else if (endpoint == newLarge.endpoint) {
newLargeFound = true;
}
if (!removed.remove(endpoint)) {
_incomingVideoEndpoints.emplace(endpoint);
if (_activeVideoEndpoints.contains(endpoint)) {
_streamsVideoUpdated.fire({ endpoint, true });
}
}
};
for (const auto &endpoint : endpoints) {
if (endpoint != _cameraEndpoint && endpoint != _screenEndpoint) {
feedOne(endpoint);
}
void GroupCall::updateRequestedVideoChannels() {
_requestedVideoChannelsUpdateScheduled = false;
const auto real = lookupReal();
if (!real || !_instance) {
return;
}
feedOne(cameraSharingEndpoint());
feedOne(screenSharingEndpoint());
if (newLarge && !newLargeFound) {
_videoEndpointPinned = false;
newLarge = VideoEndpoint();
}
if (newLarge.empty()) {
setVideoEndpointLarge(chooseLargeVideoEndpoint());
}
for (const auto &endpoint : removed) {
if (_activeVideoEndpoints.contains(endpoint)) {
_streamsVideoUpdated.fire({ endpoint, false });
auto channels = std::vector<tgcalls::VideoChannelDescription>();
using Quality = tgcalls::VideoChannelDescription::Quality;
channels.reserve(_activeVideoEndpoints.size());
const auto &camera = cameraSharingEndpoint();
const auto &screen = screenSharingEndpoint();
const auto &large = _videoEndpointLarge.current().endpoint;
for (const auto &[endpoint, endpointType] : _activeVideoEndpoints) {
if (endpoint == camera || endpoint == screen) {
continue;
}
const auto participant = real->participantByEndpoint(endpoint);
const auto params = (participant && participant->ssrc)
? participant->videoParams.get()
: nullptr;
if (!params) {
continue;
}
channels.push_back({
.audioSsrc = participant->ssrc,
.videoInformation = (params->camera.endpoint == endpoint
? params->camera.json.toStdString()
: params->screen.json.toStdString()),
.quality = (endpoint == large
? Quality::Full
: Quality::Thumbnail),
});
}
_instance->setRequestedVideoChannels(std::move(channels));
}
void GroupCall::updateRequestedVideoChannelsDelayed() {
if (_requestedVideoChannelsUpdateScheduled) {
return;
}
_requestedVideoChannelsUpdateScheduled = true;
crl::on_main(this, [=] {
if (_requestedVideoChannelsUpdateScheduled) {
updateRequestedVideoChannels();
}
});
}
void GroupCall::fillActiveVideoEndpoints() {
@ -2128,9 +2135,7 @@ void GroupCall::fillActiveVideoEndpoints() {
}
if (!removed.remove(endpoint)) {
_activeVideoEndpoints.emplace(endpoint, type);
if (_incomingVideoEndpoints.contains(endpoint)) {
_streamsVideoUpdated.fire({ endpoint, true });
}
_streamsVideoUpdated.fire({ endpoint, true });
}
};
for (const auto &participant : participants) {
@ -2157,6 +2162,7 @@ void GroupCall::fillActiveVideoEndpoints() {
_streamsVideoUpdated.fire({ endpoint, false });
}
}
updateRequestedVideoChannels();
}
GroupCall::EndpointType GroupCall::activeVideoEndpointType(
@ -2182,10 +2188,8 @@ VideoEndpoint GroupCall::chooseLargeVideoEndpoint() const {
const auto &myCameraEndpoint = cameraSharingEndpoint();
const auto &myScreenEndpoint = screenSharingEndpoint();
const auto &participants = real->participants();
for (const auto &endpoint : _incomingVideoEndpoints) {
if (!_activeVideoEndpoints.contains(endpoint)
|| endpoint == _cameraEndpoint
|| endpoint == _screenEndpoint) {
for (const auto &[endpoint, endpointType] : _activeVideoEndpoints) {
if (endpoint == _cameraEndpoint || endpoint == _screenEndpoint) {
continue;
}
if (const auto participant = real->participantByEndpoint(endpoint)) {

View File

@ -280,7 +280,6 @@ public:
}
[[nodiscard]] bool streamsVideo(const std::string &endpoint) const {
return !endpoint.empty()
&& _incomingVideoEndpoints.contains(endpoint)
&& activeVideoEndpointType(endpoint) != EndpointType::None;
}
[[nodiscard]] bool videoEndpointPinned() const {
@ -446,8 +445,8 @@ private:
void stopConnectingSound();
void playConnectingSoundOnce();
void setIncomingVideoEndpoints(
const std::vector<std::string> &endpoints);
void updateRequestedVideoChannels();
void updateRequestedVideoChannelsDelayed();
void fillActiveVideoEndpoints();
[[nodiscard]] VideoEndpoint chooseLargeVideoEndpoint() const;
[[nodiscard]] EndpointType activeVideoEndpointType(
@ -484,6 +483,7 @@ private:
rpl::variable<State> _state = State::Creating;
base::flat_set<uint32> _unresolvedSsrcs;
bool _recordingStoppedByMe = false;
bool _requestedVideoChannelsUpdateScheduled = false;
MTP::DcId _broadcastDcId = 0;
base::flat_map<not_null<LoadPartTask*>, LoadingPart> _broadcastParts;
@ -537,7 +537,6 @@ private:
rpl::event_stream<LevelUpdate> _levelUpdates;
rpl::event_stream<StreamsVideoUpdate> _streamsVideoUpdated;
base::flat_set<std::string> _incomingVideoEndpoints;
base::flat_map<std::string, EndpointType> _activeVideoEndpoints;
rpl::variable<VideoEndpoint> _videoEndpointLarge;
rpl::variable<bool> _videoEndpointPinned;

View File

@ -221,8 +221,6 @@ Members::Controller::Controller(
ImageRoundRadius::Large,
st::groupCallMembersBgOver)
, _narrowRoundRect(ImageRoundRadius::Large, st::groupCallMembersBg) {
setupListChangeViewers();
style::PaletteChanged(
) | rpl::start_with_next([=] {
_inactiveCrossLine.invalidate();
@ -304,12 +302,12 @@ void Members::Controller::setupListChangeViewers() {
subscribeToChanges(real);
}, _lifetime);
_call->stateValue(
) | rpl::start_with_next([=] {
if (const auto real = _call->lookupReal()) {
//updateRow(channel->session().user());
}
}, _lifetime);
//_call->stateValue(
//) | rpl::start_with_next([=] {
// if (const auto real = _call->lookupReal()) {
// updateRow(channel->session().user());
// }
//}, _lifetime);
_call->levelUpdates(
) | rpl::start_with_next([=](const LevelUpdate &update) {
@ -769,6 +767,8 @@ void Members::Controller::prepare() {
loadMoreRows();
appendInvitedUsers();
_prepared = true;
setupListChangeViewers();
}
bool Members::Controller::isMe(not_null<PeerData*> participantPeer) const {
@ -1435,6 +1435,14 @@ std::unique_ptr<Row> Members::Controller::createRow(
const Data::GroupCallParticipant &participant) {
auto result = std::make_unique<Row>(this, participant.peer);
updateRow(result.get(), &participant);
const auto &camera = computeCameraEndpoint(&participant);
const auto &screen = computeScreenEndpoint(&participant);
if (!screen.empty() && _largeEndpoint != screen) {
setRowVideoEndpoint(result.get(), screen);
} else if (!camera.empty() && _largeEndpoint != camera) {
setRowVideoEndpoint(result.get(), camera);
}
return result;
}
@ -1457,25 +1465,13 @@ Members::Members(
, _listController(std::make_unique<Controller>(call, parent))
, _layout(_scroll->setOwnedWidget(
object_ptr<Ui::VerticalLayout>(_scroll.data())))
, _pinnedVideoWrap(_layout->add(object_ptr<Ui::RpWidget>(_layout.get())))
, _pinnedVideo(
std::make_unique<LargeVideo>(
_pinnedVideoWrap.get(),
st::groupCallLargeVideoNarrow,
true,
_call->videoLargeTrackValue(
) | rpl::map([=](GroupCall::LargeTrack track) {
const auto row = track ? lookupRow(track.peer) : nullptr;
Assert(!track || row != nullptr);
return LargeVideoTrack{ row ? track.track : nullptr, row };
}),
_call->videoEndpointPinnedValue())) {
, _pinnedVideoWrap(_layout->add(object_ptr<Ui::RpWidget>(_layout.get()))) {
setupAddMember(call);
setupList();
setupPinnedVideo();
setContent(_list);
setupFakeRoundCorners();
_listController->setDelegate(static_cast<PeerListDelegate*>(this));
setupPinnedVideo();
}
Members::~Members() = default;
@ -1652,6 +1648,18 @@ void Members::setupList() {
void Members::setupPinnedVideo() {
using namespace rpl::mappers;
_pinnedVideo = std::make_unique<LargeVideo>(
_pinnedVideoWrap.get(),
st::groupCallLargeVideoNarrow,
true,
_call->videoLargeTrackValue(
) | rpl::map([=](GroupCall::LargeTrack track) {
const auto row = track ? lookupRow(track.peer) : nullptr;
Assert(!track || row != nullptr);
return LargeVideoTrack{ row ? track.track : nullptr, row };
}),
_call->videoEndpointPinnedValue());
_pinnedVideo->pinToggled(
) | rpl::start_with_next([=](bool pinned) {
if (!pinned) {

View File

@ -94,7 +94,7 @@ private:
std::unique_ptr<Controller> _listController;
not_null<Ui::VerticalLayout*> _layout;
const not_null<Ui::RpWidget*> _pinnedVideoWrap;
const std::unique_ptr<LargeVideo> _pinnedVideo;
std::unique_ptr<LargeVideo> _pinnedVideo;
rpl::variable<Ui::RpWidget*> _addMemberButton = nullptr;
ListWidget *_list = nullptr;
rpl::event_stream<> _addMemberRequests;

@ -1 +1 @@
Subproject commit 9a2b95507fe19de2e969517453ae0874fbe1ae62
Subproject commit a362d24ee97ed1a5c2e3a82656e897adf3354613