in chime-sdk-signaling-cpp/src/signaling/default_signaling_client.cc [378:469]
void DefaultSignalingClient::HandleIndexFrame(const signal_sdk::SdkIndexFrame& index_frame) {
if (state_ != SignalingState::kConnected || !is_joined_) {
CHIME_LOG(LogLevel::kWarning, "Should not receive index frame before join")
return;
}
if (index_frame.has_at_capacity() && index_frame.at_capacity()) {
// TODO @hokyungh: handle capacity
CHIME_LOG(LogLevel::kWarning, "It reached video max capacity")
return;
}
CHIME_LOG(LogLevel::kDebug, SignalFrameDebugUtils::IndexFrameDebugString(index_frame))
std::vector<RemoteVideoSourceInfo> removed;
for (const auto& pair : attendee_id_to_internal_configurations_) {
auto it = std::find_if(index_frame.sources().begin(), index_frame.sources().end(),
[&](const signal_sdk::SdkStreamDescriptor& stream) {
return pair.second.attendee.attendee_id == stream.attendee_id();
});
// previous index does not exist anymore, so added to remove list
if (it == index_frame.sources().end()) {
RemoteVideoSourceInfo remote_video_source;
remote_video_source.max_bitrate_kbps = pair.second.max_bitrate_kbps;
remote_video_source.attendee.attendee_id = pair.second.attendee.attendee_id;
remote_video_source.attendee.external_user_id = pair.second.attendee.external_user_id;
removed.push_back(remote_video_source);
}
}
for (const auto& remote_video_source : removed) {
attendee_id_to_internal_configurations_.erase(remote_video_source.attendee.attendee_id);
}
std::vector<RemoteVideoSourceInfo> sources;
for (const signal_sdk::SdkStreamDescriptor& stream : index_frame.sources()) {
auto attend_id_to_internal_config_it = attendee_id_to_internal_configurations_.find(stream.attendee_id());
if (attend_id_to_internal_config_it == attendee_id_to_internal_configurations_.end()) {
// Sets internal configuration for local mapping
InternalStreamConfiguration remote_configuration;
RemoteVideoSourceInfo remote_video_source;
remote_configuration.stream_id = stream.stream_id();
remote_configuration.group_id = stream.group_id();
remote_configuration.attendee.attendee_id = stream.attendee_id();
remote_configuration.attendee.external_user_id = stream.external_user_id();
remote_configuration.max_bitrate_kbps = stream.max_bitrate_kbps();
attendee_id_to_internal_configurations_[stream.attendee_id()] = remote_configuration;
// Sets remote video sources as well
remote_video_source.attendee.attendee_id = stream.attendee_id();
remote_video_source.attendee.external_user_id = stream.external_user_id();
remote_video_source.max_bitrate_kbps = stream.max_bitrate_kbps();
remote_video_source.stream_id = stream.stream_id();
sources.push_back(remote_video_source);
} else {
// Just updates value from the stream
attend_id_to_internal_config_it->second.max_bitrate_kbps = stream.max_bitrate_kbps();
attend_id_to_internal_config_it->second.attendee.attendee_id = stream.attendee_id();
attend_id_to_internal_config_it->second.attendee.external_user_id = stream.external_user_id();
attend_id_to_internal_config_it->second.group_id = stream.group_id();
}
}
if (!has_received_first_index_) {
has_received_first_index_ = true;
if (TurnCredentialsExpired()) {
CHIME_LOG(LogLevel::kError, "TURN credentials expired.")
return;
}
TurnCredentials credentials = turn_credentials_;
NotifySignalingObserver([&credentials, &sources](SignalingClientObserver* observer) -> void {
observer->OnSignalingClientStarted({credentials, sources});
});
// No need to call OnRemoteVideoSourcesAvailable or OnRemoteVideoSourcesUnavailable for the first time
return;
}
if (!sources.empty()) {
NotifySignalingObserver(
[&sources](SignalingClientObserver* observer) -> void { observer->OnRemoteVideoSourcesAvailable(sources); });
}
if (!removed.empty()) {
NotifySignalingObserver(
[&removed](SignalingClientObserver* observer) -> void { observer->OnRemoteVideoSourcesUnavailable(removed); });
}
}