[DVQA] Extract StreamState into separate file
Bug: b/231397778
Change-Id: Ic7207cd17e8179151824a2257b3173481e9f4f6e
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/265399
Commit-Queue: Artem Titov <titovartem@webrtc.org>
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#37187}
diff --git a/test/pc/e2e/BUILD.gn b/test/pc/e2e/BUILD.gn
index 1778c6a..e88d53d 100644
--- a/test/pc/e2e/BUILD.gn
+++ b/test/pc/e2e/BUILD.gn
@@ -738,12 +738,15 @@
"analyzer/video/default_video_quality_analyzer_frames_comparator.h",
"analyzer/video/default_video_quality_analyzer_internal_shared_objects.cc",
"analyzer/video/default_video_quality_analyzer_internal_shared_objects.h",
+ "analyzer/video/default_video_quality_analyzer_stream_state.cc",
+ "analyzer/video/default_video_quality_analyzer_stream_state.h",
"analyzer/video/names_collection.cc",
"analyzer/video/names_collection.h",
]
deps = [
":default_video_quality_analyzer_shared",
+ ":multi_head_queue",
"../../../api:array_view",
"../../../api:scoped_refptr",
"../../../api/numerics:numerics",
diff --git a/test/pc/e2e/analyzer/video/default_video_quality_analyzer.cc b/test/pc/e2e/analyzer/video/default_video_quality_analyzer.cc
index 88a6f3d..ebebe92 100644
--- a/test/pc/e2e/analyzer/video/default_video_quality_analyzer.cc
+++ b/test/pc/e2e/analyzer/video/default_video_quality_analyzer.cc
@@ -28,6 +28,7 @@
#include "test/pc/e2e/analyzer/video/default_video_quality_analyzer_frames_comparator.h"
#include "test/pc/e2e/analyzer/video/default_video_quality_analyzer_internal_shared_objects.h"
#include "test/pc/e2e/analyzer/video/default_video_quality_analyzer_shared_objects.h"
+#include "test/pc/e2e/analyzer/video/default_video_quality_analyzer_stream_state.h"
namespace webrtc {
namespace {
@@ -987,82 +988,6 @@
return out;
}
-uint16_t DefaultVideoQualityAnalyzer::StreamState::PopFront(size_t peer) {
- size_t peer_queue = GetPeerQueueIndex(peer);
- size_t alive_frames_queue = GetAliveFramesQueueIndex();
- absl::optional<uint16_t> frame_id = frame_ids_.PopFront(peer_queue);
- 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(alive_frames_queue);
- size_t other_size = 0;
- for (size_t i = 0; i < frame_ids_.readers_count(); ++i) {
- size_t cur_size = frame_ids_.size(i);
- if (i != alive_frames_queue && cur_size > other_size) {
- other_size = cur_size;
- }
- }
- // 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(alive_frames_queue);
- RTC_DCHECK(alive_frame_id.has_value());
- RTC_DCHECK_EQ(frame_id.value(), alive_frame_id.value());
- }
-
- return frame_id.value();
-}
-
-uint16_t DefaultVideoQualityAnalyzer::StreamState::MarkNextAliveFrameAsDead() {
- absl::optional<uint16_t> frame_id =
- frame_ids_.PopFront(GetAliveFramesQueueIndex());
- RTC_DCHECK(frame_id.has_value());
- return frame_id.value();
-}
-
-void DefaultVideoQualityAnalyzer::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>
-DefaultVideoQualityAnalyzer::StreamState::last_rendered_frame_time(
- size_t peer) const {
- return MaybeGetValue(last_rendered_frame_time_, peer);
-}
-
-size_t DefaultVideoQualityAnalyzer::StreamState::GetPeerQueueIndex(
- size_t peer_index) const {
- // When sender isn't expecting to receive its own stream we will use their
- // queue for tracking alive frames. Otherwise we will use the queue #0 to
- // track alive frames and will shift all other queues for peers on 1.
- // It means when `enable_receive_own_stream_` is true peer's queue will have
- // index equal to `peer_index` + 1 and when `enable_receive_own_stream_` is
- // false peer's queue will have index equal to `peer_index`.
- if (!enable_receive_own_stream_) {
- return peer_index;
- }
- return peer_index + 1;
-}
-
-size_t DefaultVideoQualityAnalyzer::StreamState::GetAliveFramesQueueIndex()
- const {
- // When sender isn't expecting to receive its own stream we will use their
- // queue for tracking alive frames. Otherwise we will use the queue #0 to
- // track alive frames and will shift all other queues for peers on 1.
- if (!enable_receive_own_stream_) {
- return owner_;
- }
- return 0;
-}
-
bool DefaultVideoQualityAnalyzer::FrameInFlight::RemoveFrame() {
if (!frame_) {
return false;
diff --git a/test/pc/e2e/analyzer/video/default_video_quality_analyzer.h b/test/pc/e2e/analyzer/video/default_video_quality_analyzer.h
index 0f4c1dd..b9d8e3e 100644
--- a/test/pc/e2e/analyzer/video/default_video_quality_analyzer.h
+++ b/test/pc/e2e/analyzer/video/default_video_quality_analyzer.h
@@ -37,6 +37,7 @@
#include "test/pc/e2e/analyzer/video/default_video_quality_analyzer_frames_comparator.h"
#include "test/pc/e2e/analyzer/video/default_video_quality_analyzer_internal_shared_objects.h"
#include "test/pc/e2e/analyzer/video/default_video_quality_analyzer_shared_objects.h"
+#include "test/pc/e2e/analyzer/video/default_video_quality_analyzer_stream_state.h"
#include "test/pc/e2e/analyzer/video/multi_head_queue.h"
#include "test/pc/e2e/analyzer/video/names_collection.h"
#include "test/testsupport/perf_test.h"
@@ -105,77 +106,6 @@
std::map<std::string, std::vector<uint16_t>> GetStreamFrames() const;
private:
- // Represents a current state of video stream.
- class StreamState {
- public:
- StreamState(size_t owner,
- size_t peers_count,
- bool enable_receive_own_stream,
- Timestamp stream_started_time)
- : owner_(owner),
- enable_receive_own_stream_(enable_receive_own_stream),
- stream_started_time_(stream_started_time),
- frame_ids_(enable_receive_own_stream ? peers_count + 1
- : peers_count) {}
-
- size_t owner() const { return owner_; }
- Timestamp stream_started_time() const { return stream_started_time_; }
-
- void PushBack(uint16_t frame_id) { frame_ids_.PushBack(frame_id); }
- // Crash if state is empty. Guarantees that there can be no alive frames
- // that are not in the owner queue
- uint16_t PopFront(size_t peer);
- bool IsEmpty(size_t peer) const {
- return frame_ids_.IsEmpty(GetPeerQueueIndex(peer));
- }
- // Crash if state is empty.
- uint16_t Front(size_t peer) const {
- return frame_ids_.Front(GetPeerQueueIndex(peer)).value();
- }
-
- // When new peer is added - all current alive frames will be sent to it as
- // well. So we need to register them as expected by copying owner_ head to
- // the new head.
- void AddPeer() { frame_ids_.AddHead(GetAliveFramesQueueIndex()); }
-
- size_t GetAliveFramesCount() const {
- return frame_ids_.size(GetAliveFramesQueueIndex());
- }
- uint16_t MarkNextAliveFrameAsDead();
-
- void SetLastRenderedFrameTime(size_t peer, Timestamp time);
- absl::optional<Timestamp> last_rendered_frame_time(size_t peer) const;
-
- private:
- // Returns index of the `frame_ids_` queue which is used for specified
- // `peer_index`.
- size_t GetPeerQueueIndex(size_t peer_index) const;
-
- // Returns index of the `frame_ids_` queue which is used to track alive
- // frames for this stream. The frame is alive if it contains VideoFrame
- // payload in `captured_frames_in_flight_`.
- size_t GetAliveFramesQueueIndex() const;
-
- // Index of the owner. Owner's queue in `frame_ids_` will keep alive frames.
- const size_t owner_;
- const bool enable_receive_own_stream_;
- const Timestamp stream_started_time_;
- // To correctly determine dropped frames we have to know sequence of frames
- // in each stream so we will keep a list of frame ids inside the stream.
- // This list is represented by multi head queue of frame ids with separate
- // head for each receiver. When the frame is rendered, we will pop ids from
- // the corresponding head until id will match with rendered one. All ids
- // before matched one can be considered as dropped:
- //
- // | frame_id1 |->| frame_id2 |->| frame_id3 |->| frame_id4 |
- //
- // If we received frame with id frame_id3, then we will pop frame_id1 and
- // frame_id2 and consider that frames as dropped and then compare received
- // frame with the one from `captured_frames_in_flight_` with id frame_id3.
- MultiHeadQueue<uint16_t> frame_ids_;
- std::map<size_t, Timestamp> last_rendered_frame_time_;
- };
-
enum State { kNew, kActive, kStopped };
struct ReceiverFrameStats {
diff --git a/test/pc/e2e/analyzer/video/default_video_quality_analyzer_stream_state.cc b/test/pc/e2e/analyzer/video/default_video_quality_analyzer_stream_state.cc
new file mode 100644
index 0000000..f1d98b8
--- /dev/null
+++ b/test/pc/e2e/analyzer/video/default_video_quality_analyzer_stream_state.cc
@@ -0,0 +1,104 @@
+/*
+ * 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 <map>
+
+#include "absl/types/optional.h"
+#include "api/units/timestamp.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+namespace {
+
+template <typename T>
+absl::optional<T> MaybeGetValue(const std::map<size_t, T>& map, size_t key) {
+ auto it = map.find(key);
+ if (it == map.end()) {
+ return absl::nullopt;
+ }
+ return it->second;
+}
+
+} // namespace
+
+uint16_t StreamState::PopFront(size_t peer) {
+ size_t peer_queue = GetPeerQueueIndex(peer);
+ size_t alive_frames_queue = GetAliveFramesQueueIndex();
+ absl::optional<uint16_t> frame_id = frame_ids_.PopFront(peer_queue);
+ 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(alive_frames_queue);
+ size_t other_size = 0;
+ for (size_t i = 0; i < frame_ids_.readers_count(); ++i) {
+ size_t cur_size = frame_ids_.size(i);
+ if (i != alive_frames_queue && cur_size > other_size) {
+ other_size = cur_size;
+ }
+ }
+ // 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(alive_frames_queue);
+ RTC_DCHECK(alive_frame_id.has_value());
+ RTC_DCHECK_EQ(frame_id.value(), alive_frame_id.value());
+ }
+
+ return frame_id.value();
+}
+
+uint16_t StreamState::MarkNextAliveFrameAsDead() {
+ absl::optional<uint16_t> frame_id =
+ frame_ids_.PopFront(GetAliveFramesQueueIndex());
+ RTC_DCHECK(frame_id.has_value());
+ return frame_id.value();
+}
+
+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::GetPeerQueueIndex(size_t peer_index) const {
+ // When sender isn't expecting to receive its own stream we will use their
+ // queue for tracking alive frames. Otherwise we will use the queue #0 to
+ // track alive frames and will shift all other queues for peers on 1.
+ // It means when `enable_receive_own_stream_` is true peer's queue will have
+ // index equal to `peer_index` + 1 and when `enable_receive_own_stream_` is
+ // false peer's queue will have index equal to `peer_index`.
+ if (!enable_receive_own_stream_) {
+ return peer_index;
+ }
+ return peer_index + 1;
+}
+
+size_t StreamState::GetAliveFramesQueueIndex() const {
+ // When sender isn't expecting to receive its own stream we will use their
+ // queue for tracking alive frames. Otherwise we will use the queue #0 to
+ // track alive frames and will shift all other queues for peers on 1.
+ if (!enable_receive_own_stream_) {
+ return owner_;
+ }
+ return 0;
+}
+
+} // namespace webrtc
diff --git a/test/pc/e2e/analyzer/video/default_video_quality_analyzer_stream_state.h b/test/pc/e2e/analyzer/video/default_video_quality_analyzer_stream_state.h
new file mode 100644
index 0000000..c127dd1
--- /dev/null
+++ b/test/pc/e2e/analyzer/video/default_video_quality_analyzer_stream_state.h
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+
+#ifndef TEST_PC_E2E_ANALYZER_VIDEO_DEFAULT_VIDEO_QUALITY_ANALYZER_STREAM_STATE_H_
+#define TEST_PC_E2E_ANALYZER_VIDEO_DEFAULT_VIDEO_QUALITY_ANALYZER_STREAM_STATE_H_
+
+#include <map>
+
+#include "absl/types/optional.h"
+#include "api/units/timestamp.h"
+#include "test/pc/e2e/analyzer/video/multi_head_queue.h"
+
+namespace webrtc {
+
+// Represents a current state of video stream inside
+// DefaultVideoQualityAnalyzer.
+class StreamState {
+ public:
+ StreamState(size_t owner,
+ size_t peers_count,
+ bool enable_receive_own_stream,
+ Timestamp stream_started_time)
+ : owner_(owner),
+ enable_receive_own_stream_(enable_receive_own_stream),
+ stream_started_time_(stream_started_time),
+ frame_ids_(enable_receive_own_stream ? peers_count + 1 : peers_count) {}
+
+ size_t owner() const { return owner_; }
+ Timestamp stream_started_time() const { return stream_started_time_; }
+
+ void PushBack(uint16_t frame_id) { frame_ids_.PushBack(frame_id); }
+ // Crash if state is empty. Guarantees that there can be no alive frames
+ // that are not in the owner queue
+ uint16_t PopFront(size_t peer);
+ bool IsEmpty(size_t peer) const {
+ return frame_ids_.IsEmpty(GetPeerQueueIndex(peer));
+ }
+ // Crash if state is empty.
+ uint16_t Front(size_t peer) const {
+ return frame_ids_.Front(GetPeerQueueIndex(peer)).value();
+ }
+
+ // When new peer is added - all current alive frames will be sent to it as
+ // well. So we need to register them as expected by copying owner_ head to
+ // the new head.
+ void AddPeer() { frame_ids_.AddHead(GetAliveFramesQueueIndex()); }
+
+ size_t GetAliveFramesCount() const {
+ return frame_ids_.size(GetAliveFramesQueueIndex());
+ }
+ uint16_t MarkNextAliveFrameAsDead();
+
+ void SetLastRenderedFrameTime(size_t peer, Timestamp time);
+ absl::optional<Timestamp> last_rendered_frame_time(size_t peer) const;
+
+ private:
+ // Returns index of the `frame_ids_` queue which is used for specified
+ // `peer_index`.
+ size_t GetPeerQueueIndex(size_t peer_index) const;
+
+ // Returns index of the `frame_ids_` queue which is used to track alive
+ // frames for this stream. The frame is alive if it contains VideoFrame
+ // payload in `captured_frames_in_flight_`.
+ size_t GetAliveFramesQueueIndex() const;
+
+ // Index of the owner. Owner's queue in `frame_ids_` will keep alive frames.
+ const size_t owner_;
+ const bool enable_receive_own_stream_;
+ const Timestamp stream_started_time_;
+ // To correctly determine dropped frames we have to know sequence of frames
+ // in each stream so we will keep a list of frame ids inside the stream.
+ // This list is represented by multi head queue of frame ids with separate
+ // head for each receiver. When the frame is rendered, we will pop ids from
+ // the corresponding head until id will match with rendered one. All ids
+ // before matched one can be considered as dropped:
+ //
+ // | frame_id1 |->| frame_id2 |->| frame_id3 |->| frame_id4 |
+ //
+ // If we received frame with id frame_id3, then we will pop frame_id1 and
+ // frame_id2 and consider those frames as dropped and then compare received
+ // frame with the one from `FrameInFlight` with id frame_id3.
+ MultiHeadQueue<uint16_t> frame_ids_;
+ std::map<size_t, Timestamp> last_rendered_frame_time_;
+};
+
+} // namespace webrtc
+
+#endif // TEST_PC_E2E_ANALYZER_VIDEO_DEFAULT_VIDEO_QUALITY_ANALYZER_STREAM_STATE_H_