blob: bcdf16d1a4a5cf68bfd6c7f64d9a733423b58d31 [file] [log] [blame]
/*
* Copyright (c) 2022 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "test/pc/e2e/analyzer/video/default_video_quality_analyzer_stream_state.h"
#include <set>
#include <unordered_map>
#include "absl/types/optional.h"
#include "api/units/timestamp.h"
#include "rtc_base/checks.h"
#include "system_wrappers/include/clock.h"
#include "test/pc/e2e/analyzer/video/dvqa/pausable_state.h"
namespace webrtc {
namespace {
template <typename T>
absl::optional<T> MaybeGetValue(const std::unordered_map<size_t, T>& map,
size_t key) {
auto it = map.find(key);
if (it == map.end()) {
return absl::nullopt;
}
return it->second;
}
} // namespace
StreamState::StreamState(size_t sender,
std::set<size_t> receivers,
Timestamp stream_started_time,
Clock* clock)
: sender_(sender),
stream_started_time_(stream_started_time),
clock_(clock),
receivers_(receivers),
frame_ids_(std::move(receivers)) {
frame_ids_.AddReader(kAliveFramesQueueIndex);
RTC_CHECK_NE(sender_, kAliveFramesQueueIndex);
for (size_t receiver : receivers_) {
RTC_CHECK_NE(receiver, kAliveFramesQueueIndex);
pausable_state_.emplace(receiver, PausableState(clock_));
}
}
uint16_t StreamState::PopFront(size_t peer) {
RTC_CHECK_NE(peer, kAliveFramesQueueIndex);
absl::optional<uint16_t> frame_id = frame_ids_.PopFront(peer);
RTC_DCHECK(frame_id.has_value());
// If alive's frame queue is longer than all others, than also pop frame from
// it, because that frame is received by all receivers.
size_t alive_size = frame_ids_.size(kAliveFramesQueueIndex);
size_t other_size = GetLongestReceiverQueue();
// Pops frame from alive queue if alive's queue is the longest one.
if (alive_size > other_size) {
absl::optional<uint16_t> alive_frame_id =
frame_ids_.PopFront(kAliveFramesQueueIndex);
RTC_DCHECK(alive_frame_id.has_value());
RTC_DCHECK_EQ(frame_id.value(), alive_frame_id.value());
}
return frame_id.value();
}
void StreamState::AddPeer(size_t peer) {
RTC_CHECK_NE(peer, kAliveFramesQueueIndex);
frame_ids_.AddReader(peer, kAliveFramesQueueIndex);
receivers_.insert(peer);
pausable_state_.emplace(peer, PausableState(clock_));
}
void StreamState::RemovePeer(size_t peer) {
RTC_CHECK_NE(peer, kAliveFramesQueueIndex);
frame_ids_.RemoveReader(peer);
receivers_.erase(peer);
pausable_state_.erase(peer);
// If we removed the last receiver for the alive frames, we need to pop them
// from the queue, because now they received by all receivers.
size_t alive_size = frame_ids_.size(kAliveFramesQueueIndex);
size_t other_size = GetLongestReceiverQueue();
while (alive_size > other_size) {
frame_ids_.PopFront(kAliveFramesQueueIndex);
alive_size--;
}
}
PausableState* StreamState::GetPausableState(size_t peer) {
auto it = pausable_state_.find(peer);
RTC_CHECK(it != pausable_state_.end())
<< "No pausable state for receiver " << peer;
return &it->second;
}
void StreamState::SetLastRenderedFrameTime(size_t peer, Timestamp time) {
auto it = last_rendered_frame_time_.find(peer);
if (it == last_rendered_frame_time_.end()) {
last_rendered_frame_time_.insert({peer, time});
} else {
it->second = time;
}
}
absl::optional<Timestamp> StreamState::last_rendered_frame_time(
size_t peer) const {
return MaybeGetValue(last_rendered_frame_time_, peer);
}
size_t StreamState::GetLongestReceiverQueue() const {
size_t max = 0;
for (size_t receiver : receivers_) {
size_t cur_size = frame_ids_.size(receiver);
if (cur_size > max) {
max = cur_size;
}
}
return max;
}
} // namespace webrtc