[DVQA] Extract FrameInFlight into separate file

Also add ability to remove expected receivers for the frame.

Bug: b/231397778
Change-Id: Id1fb2df05a69e0dca4f05eaa995521b6be2ac52a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/265396
Commit-Queue: Artem Titov <titovartem@webrtc.org>
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#37191}
This commit is contained in:
Artem Titov 2022-06-13 10:21:58 +02:00 committed by WebRTC LUCI CQ
parent c62e1b8d10
commit 42d09cb1ba
7 changed files with 383 additions and 282 deletions

View File

@ -734,6 +734,8 @@ if (!build_with_chromium) {
sources = [
"analyzer/video/default_video_quality_analyzer_cpu_measurer.cc",
"analyzer/video/default_video_quality_analyzer_cpu_measurer.h",
"analyzer/video/default_video_quality_analyzer_frame_in_flight.cc",
"analyzer/video/default_video_quality_analyzer_frame_in_flight.h",
"analyzer/video/default_video_quality_analyzer_frames_comparator.cc",
"analyzer/video/default_video_quality_analyzer_frames_comparator.h",
"analyzer/video/default_video_quality_analyzer_internal_shared_objects.cc",

View File

@ -12,7 +12,9 @@
#include <algorithm>
#include <memory>
#include <set>
#include <utility>
#include <vector>
#include "api/array_view.h"
#include "api/numerics/samples_stats_counter.h"
@ -25,6 +27,7 @@
#include "rtc_base/strings/string_builder.h"
#include "rtc_base/time_utils.h"
#include "rtc_tools/frame_analyzer/video_geometry_aligner.h"
#include "test/pc/e2e/analyzer/video/default_video_quality_analyzer_frame_in_flight.h"
#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"
@ -227,10 +230,13 @@ uint16_t DefaultVideoQualityAnalyzer::OnFrameCaptured(
captured_frames_in_flight_.erase(it);
}
std::set<size_t> frame_receivers_indexes = peers_->GetPresentIndexes();
if (!options_.enable_receive_own_stream) {
frame_receivers_indexes.erase(peer_index);
}
captured_frames_in_flight_.emplace(
frame_id,
FrameInFlight(stream_index, frame, captured_time, peer_index,
peers_->size(), options_.enable_receive_own_stream));
frame_id, FrameInFlight(stream_index, frame, captured_time,
std::move(frame_receivers_indexes)));
// Set frame id on local copy of the frame
captured_frames_in_flight_.at(frame_id).SetFrameId(frame_id);
@ -593,7 +599,7 @@ void DefaultVideoQualityAnalyzer::RegisterParticipantInCall(
// frame, the frame will be removed by OnFrameRendered after next frame comes
// for the new peer. It is important because FrameInFlight is a large object.
for (auto& key_val : captured_frames_in_flight_) {
key_val.second.AddPeer();
key_val.second.AddExpectedReceiver(new_peer_index);
}
}
@ -988,170 +994,4 @@ DefaultVideoQualityAnalyzer::GetStreamFrames() const {
return out;
}
bool DefaultVideoQualityAnalyzer::FrameInFlight::RemoveFrame() {
if (!frame_) {
return false;
}
frame_ = absl::nullopt;
return true;
}
void DefaultVideoQualityAnalyzer::FrameInFlight::SetFrameId(uint16_t id) {
if (frame_) {
frame_->set_id(id);
}
}
std::vector<size_t>
DefaultVideoQualityAnalyzer::FrameInFlight::GetPeersWhichDidntReceive() const {
std::vector<size_t> out;
for (size_t i = 0; i < peers_count_; ++i) {
auto it = receiver_stats_.find(i);
bool should_current_peer_receive =
i != owner_ || enable_receive_own_stream_;
if (should_current_peer_receive &&
(it == receiver_stats_.end() ||
it->second.rendered_time.IsInfinite())) {
out.push_back(i);
}
}
return out;
}
bool DefaultVideoQualityAnalyzer::FrameInFlight::HaveAllPeersReceived() const {
for (size_t i = 0; i < peers_count_; ++i) {
// Skip `owner_` only if peer can't receive its own stream.
if (i == owner_ && !enable_receive_own_stream_) {
continue;
}
auto it = receiver_stats_.find(i);
if (it == receiver_stats_.end()) {
return false;
}
if (!it->second.dropped && it->second.rendered_time.IsInfinite()) {
return false;
}
}
return true;
}
void DefaultVideoQualityAnalyzer::FrameInFlight::OnFrameEncoded(
webrtc::Timestamp time,
VideoFrameType frame_type,
DataSize encoded_image_size,
uint32_t target_encode_bitrate,
StreamCodecInfo used_encoder) {
encoded_time_ = time;
frame_type_ = frame_type;
encoded_image_size_ = encoded_image_size;
target_encode_bitrate_ += target_encode_bitrate;
// Update used encoder info. If simulcast/SVC is used, this method can
// be called multiple times, in such case we should preserve the value
// of `used_encoder_.switched_on_at` from the first invocation as the
// smallest one.
Timestamp encoder_switched_on_at = used_encoder_.has_value()
? used_encoder_->switched_on_at
: Timestamp::PlusInfinity();
RTC_DCHECK(used_encoder.switched_on_at.IsFinite());
RTC_DCHECK(used_encoder.switched_from_at.IsFinite());
used_encoder_ = used_encoder;
if (encoder_switched_on_at < used_encoder_->switched_on_at) {
used_encoder_->switched_on_at = encoder_switched_on_at;
}
}
void DefaultVideoQualityAnalyzer::FrameInFlight::OnFramePreDecode(
size_t peer,
webrtc::Timestamp received_time,
webrtc::Timestamp decode_start_time,
VideoFrameType frame_type,
DataSize encoded_image_size) {
receiver_stats_[peer].received_time = received_time;
receiver_stats_[peer].decode_start_time = decode_start_time;
receiver_stats_[peer].frame_type = frame_type;
receiver_stats_[peer].encoded_image_size = encoded_image_size;
}
bool DefaultVideoQualityAnalyzer::FrameInFlight::HasReceivedTime(
size_t peer) const {
auto it = receiver_stats_.find(peer);
if (it == receiver_stats_.end()) {
return false;
}
return it->second.received_time.IsFinite();
}
void DefaultVideoQualityAnalyzer::FrameInFlight::OnFrameDecoded(
size_t peer,
webrtc::Timestamp time,
StreamCodecInfo used_decoder) {
receiver_stats_[peer].decode_end_time = time;
receiver_stats_[peer].used_decoder = used_decoder;
}
bool DefaultVideoQualityAnalyzer::FrameInFlight::HasDecodeEndTime(
size_t peer) const {
auto it = receiver_stats_.find(peer);
if (it == receiver_stats_.end()) {
return false;
}
return it->second.decode_end_time.IsFinite();
}
void DefaultVideoQualityAnalyzer::FrameInFlight::OnFrameRendered(
size_t peer,
webrtc::Timestamp time,
int width,
int height) {
receiver_stats_[peer].rendered_time = time;
receiver_stats_[peer].rendered_frame_width = width;
receiver_stats_[peer].rendered_frame_height = height;
}
bool DefaultVideoQualityAnalyzer::FrameInFlight::HasRenderedTime(
size_t peer) const {
auto it = receiver_stats_.find(peer);
if (it == receiver_stats_.end()) {
return false;
}
return it->second.rendered_time.IsFinite();
}
bool DefaultVideoQualityAnalyzer::FrameInFlight::IsDropped(size_t peer) const {
auto it = receiver_stats_.find(peer);
if (it == receiver_stats_.end()) {
return false;
}
return it->second.dropped;
}
FrameStats DefaultVideoQualityAnalyzer::FrameInFlight::GetStatsForPeer(
size_t peer) const {
FrameStats stats(captured_time_);
stats.pre_encode_time = pre_encode_time_;
stats.encoded_time = encoded_time_;
stats.target_encode_bitrate = target_encode_bitrate_;
stats.encoded_frame_type = frame_type_;
stats.encoded_image_size = encoded_image_size_;
stats.used_encoder = used_encoder_;
absl::optional<ReceiverFrameStats> receiver_stats =
MaybeGetValue<ReceiverFrameStats>(receiver_stats_, peer);
if (receiver_stats.has_value()) {
stats.received_time = receiver_stats->received_time;
stats.decode_start_time = receiver_stats->decode_start_time;
stats.decode_end_time = receiver_stats->decode_end_time;
stats.rendered_time = receiver_stats->rendered_time;
stats.prev_frame_rendered_time = receiver_stats->prev_frame_rendered_time;
stats.rendered_frame_width = receiver_stats->rendered_frame_width;
stats.rendered_frame_height = receiver_stats->rendered_frame_height;
stats.used_decoder = receiver_stats->used_decoder;
stats.pre_decoded_frame_type = receiver_stats->frame_type;
stats.pre_decoded_image_size = receiver_stats->encoded_image_size;
}
return stats;
}
} // namespace webrtc

View File

@ -34,6 +34,7 @@
#include "rtc_base/thread_annotations.h"
#include "system_wrappers/include/clock.h"
#include "test/pc/e2e/analyzer/video/default_video_quality_analyzer_cpu_measurer.h"
#include "test/pc/e2e/analyzer/video/default_video_quality_analyzer_frame_in_flight.h"
#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"
@ -108,118 +109,6 @@ class DefaultVideoQualityAnalyzer : public VideoQualityAnalyzerInterface {
private:
enum State { kNew, kActive, kStopped };
struct ReceiverFrameStats {
// Time when last packet of a frame was received.
Timestamp received_time = Timestamp::MinusInfinity();
Timestamp decode_start_time = Timestamp::MinusInfinity();
Timestamp decode_end_time = Timestamp::MinusInfinity();
Timestamp rendered_time = Timestamp::MinusInfinity();
Timestamp prev_frame_rendered_time = Timestamp::MinusInfinity();
// Type and encoded size of received frame.
VideoFrameType frame_type = VideoFrameType::kEmptyFrame;
DataSize encoded_image_size = DataSize::Bytes(0);
absl::optional<int> rendered_frame_width = absl::nullopt;
absl::optional<int> rendered_frame_height = absl::nullopt;
// Can be not set if frame was dropped in the network.
absl::optional<StreamCodecInfo> used_decoder = absl::nullopt;
bool dropped = false;
};
class FrameInFlight {
public:
FrameInFlight(size_t stream,
VideoFrame frame,
Timestamp captured_time,
size_t owner,
size_t peers_count,
bool enable_receive_own_stream)
: stream_(stream),
owner_(owner),
peers_count_(peers_count),
enable_receive_own_stream_(enable_receive_own_stream),
frame_(std::move(frame)),
captured_time_(captured_time) {}
size_t stream() const { return stream_; }
const absl::optional<VideoFrame>& frame() const { return frame_; }
// Returns was frame removed or not.
bool RemoveFrame();
void SetFrameId(uint16_t id);
void AddPeer() { ++peers_count_; }
std::vector<size_t> GetPeersWhichDidntReceive() const;
bool HaveAllPeersReceived() const;
void SetPreEncodeTime(webrtc::Timestamp time) { pre_encode_time_ = time; }
void OnFrameEncoded(webrtc::Timestamp time,
VideoFrameType frame_type,
DataSize encoded_image_size,
uint32_t target_encode_bitrate,
StreamCodecInfo used_encoder);
bool HasEncodedTime() const { return encoded_time_.IsFinite(); }
void OnFramePreDecode(size_t peer,
webrtc::Timestamp received_time,
webrtc::Timestamp decode_start_time,
VideoFrameType frame_type,
DataSize encoded_image_size);
bool HasReceivedTime(size_t peer) const;
void OnFrameDecoded(size_t peer,
webrtc::Timestamp time,
StreamCodecInfo used_decoder);
bool HasDecodeEndTime(size_t peer) const;
void OnFrameRendered(size_t peer,
webrtc::Timestamp time,
int width,
int height);
bool HasRenderedTime(size_t peer) const;
// Crash if rendered time is not set for specified `peer`.
webrtc::Timestamp rendered_time(size_t peer) const {
return receiver_stats_.at(peer).rendered_time;
}
void MarkDropped(size_t peer) { receiver_stats_[peer].dropped = true; }
bool IsDropped(size_t peer) const;
void SetPrevFrameRenderedTime(size_t peer, webrtc::Timestamp time) {
receiver_stats_[peer].prev_frame_rendered_time = time;
}
FrameStats GetStatsForPeer(size_t peer) const;
private:
const size_t stream_;
const size_t owner_;
size_t peers_count_;
const bool enable_receive_own_stream_;
absl::optional<VideoFrame> frame_;
// Frame events timestamp.
Timestamp captured_time_;
Timestamp pre_encode_time_ = Timestamp::MinusInfinity();
Timestamp encoded_time_ = Timestamp::MinusInfinity();
// Type and encoded size of sent frame.
VideoFrameType frame_type_ = VideoFrameType::kEmptyFrame;
DataSize encoded_image_size_ = DataSize::Bytes(0);
uint32_t target_encode_bitrate_ = 0;
// Can be not set if frame was dropped by encoder.
absl::optional<StreamCodecInfo> used_encoder_ = absl::nullopt;
std::map<size_t, ReceiverFrameStats> receiver_stats_;
};
// Returns next frame id to use. Frame ID can't be `VideoFrame::kNotSetId`,
// because this value is reserved by `VideoFrame` as "ID not set".
uint16_t GetNextFrameId() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);

View File

@ -0,0 +1,194 @@
/*
* 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_frame_in_flight.h"
#include <utility>
#include <vector>
#include "absl/types/optional.h"
#include "api/units/data_size.h"
#include "api/units/timestamp.h"
#include "api/video/video_frame_type.h"
#include "test/pc/e2e/analyzer/video/default_video_quality_analyzer_internal_shared_objects.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
FrameInFlight::FrameInFlight(size_t stream,
VideoFrame frame,
Timestamp captured_time,
std::set<size_t> expected_receivers)
: stream_(stream),
expected_receivers_(std::move(expected_receivers)),
frame_(std::move(frame)),
captured_time_(captured_time) {}
bool FrameInFlight::RemoveFrame() {
if (!frame_) {
return false;
}
frame_ = absl::nullopt;
return true;
}
void FrameInFlight::SetFrameId(uint16_t id) {
if (frame_) {
frame_->set_id(id);
}
}
std::vector<size_t> FrameInFlight::GetPeersWhichDidntReceive() const {
std::vector<size_t> out;
for (size_t peer : expected_receivers_) {
auto it = receiver_stats_.find(peer);
if (it == receiver_stats_.end() ||
(!it->second.dropped && it->second.rendered_time.IsInfinite())) {
out.push_back(peer);
}
}
return out;
}
bool FrameInFlight::HaveAllPeersReceived() const {
for (size_t peer : expected_receivers_) {
auto it = receiver_stats_.find(peer);
if (it == receiver_stats_.end()) {
return false;
}
if (!it->second.dropped && it->second.rendered_time.IsInfinite()) {
return false;
}
}
return true;
}
void FrameInFlight::OnFrameEncoded(webrtc::Timestamp time,
VideoFrameType frame_type,
DataSize encoded_image_size,
uint32_t target_encode_bitrate,
StreamCodecInfo used_encoder) {
encoded_time_ = time;
frame_type_ = frame_type;
encoded_image_size_ = encoded_image_size;
target_encode_bitrate_ += target_encode_bitrate;
// Update used encoder info. If simulcast/SVC is used, this method can
// be called multiple times, in such case we should preserve the value
// of `used_encoder_.switched_on_at` from the first invocation as the
// smallest one.
Timestamp encoder_switched_on_at = used_encoder_.has_value()
? used_encoder_->switched_on_at
: Timestamp::PlusInfinity();
RTC_DCHECK(used_encoder.switched_on_at.IsFinite());
RTC_DCHECK(used_encoder.switched_from_at.IsFinite());
used_encoder_ = used_encoder;
if (encoder_switched_on_at < used_encoder_->switched_on_at) {
used_encoder_->switched_on_at = encoder_switched_on_at;
}
}
void FrameInFlight::OnFramePreDecode(size_t peer,
webrtc::Timestamp received_time,
webrtc::Timestamp decode_start_time,
VideoFrameType frame_type,
DataSize encoded_image_size) {
receiver_stats_[peer].received_time = received_time;
receiver_stats_[peer].decode_start_time = decode_start_time;
receiver_stats_[peer].frame_type = frame_type;
receiver_stats_[peer].encoded_image_size = encoded_image_size;
}
bool FrameInFlight::HasReceivedTime(size_t peer) const {
auto it = receiver_stats_.find(peer);
if (it == receiver_stats_.end()) {
return false;
}
return it->second.received_time.IsFinite();
}
void FrameInFlight::OnFrameDecoded(size_t peer,
webrtc::Timestamp time,
StreamCodecInfo used_decoder) {
receiver_stats_[peer].decode_end_time = time;
receiver_stats_[peer].used_decoder = used_decoder;
}
bool FrameInFlight::HasDecodeEndTime(size_t peer) const {
auto it = receiver_stats_.find(peer);
if (it == receiver_stats_.end()) {
return false;
}
return it->second.decode_end_time.IsFinite();
}
void FrameInFlight::OnFrameRendered(size_t peer,
webrtc::Timestamp time,
int width,
int height) {
receiver_stats_[peer].rendered_time = time;
receiver_stats_[peer].rendered_frame_width = width;
receiver_stats_[peer].rendered_frame_height = height;
}
bool FrameInFlight::HasRenderedTime(size_t peer) const {
auto it = receiver_stats_.find(peer);
if (it == receiver_stats_.end()) {
return false;
}
return it->second.rendered_time.IsFinite();
}
bool FrameInFlight::IsDropped(size_t peer) const {
auto it = receiver_stats_.find(peer);
if (it == receiver_stats_.end()) {
return false;
}
return it->second.dropped;
}
FrameStats FrameInFlight::GetStatsForPeer(size_t peer) const {
FrameStats stats(captured_time_);
stats.pre_encode_time = pre_encode_time_;
stats.encoded_time = encoded_time_;
stats.target_encode_bitrate = target_encode_bitrate_;
stats.encoded_frame_type = frame_type_;
stats.encoded_image_size = encoded_image_size_;
stats.used_encoder = used_encoder_;
absl::optional<ReceiverFrameStats> receiver_stats =
MaybeGetValue<ReceiverFrameStats>(receiver_stats_, peer);
if (receiver_stats.has_value()) {
stats.received_time = receiver_stats->received_time;
stats.decode_start_time = receiver_stats->decode_start_time;
stats.decode_end_time = receiver_stats->decode_end_time;
stats.rendered_time = receiver_stats->rendered_time;
stats.prev_frame_rendered_time = receiver_stats->prev_frame_rendered_time;
stats.rendered_frame_width = receiver_stats->rendered_frame_width;
stats.rendered_frame_height = receiver_stats->rendered_frame_height;
stats.used_decoder = receiver_stats->used_decoder;
stats.pre_decoded_frame_type = receiver_stats->frame_type;
stats.pre_decoded_image_size = receiver_stats->encoded_image_size;
}
return stats;
}
} // namespace webrtc

View File

@ -0,0 +1,159 @@
/*
* 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_FRAME_IN_FLIGHT_H_
#define TEST_PC_E2E_ANALYZER_VIDEO_DEFAULT_VIDEO_QUALITY_ANALYZER_FRAME_IN_FLIGHT_H_
#include <map>
#include <set>
#include <utility>
#include <vector>
#include "absl/types/optional.h"
#include "api/units/data_size.h"
#include "api/units/timestamp.h"
#include "api/video/video_frame.h"
#include "api/video/video_frame_type.h"
#include "test/pc/e2e/analyzer/video/default_video_quality_analyzer_internal_shared_objects.h"
namespace webrtc {
struct ReceiverFrameStats {
// Time when last packet of a frame was received.
Timestamp received_time = Timestamp::MinusInfinity();
Timestamp decode_start_time = Timestamp::MinusInfinity();
Timestamp decode_end_time = Timestamp::MinusInfinity();
Timestamp rendered_time = Timestamp::MinusInfinity();
Timestamp prev_frame_rendered_time = Timestamp::MinusInfinity();
// Type and encoded size of received frame.
VideoFrameType frame_type = VideoFrameType::kEmptyFrame;
DataSize encoded_image_size = DataSize::Bytes(0);
absl::optional<int> rendered_frame_width = absl::nullopt;
absl::optional<int> rendered_frame_height = absl::nullopt;
// Can be not set if frame was dropped in the network.
absl::optional<StreamCodecInfo> used_decoder = absl::nullopt;
bool dropped = false;
};
// Represents a frame which was sent by sender and is currently on the way to
// multiple receivers. Some receivers may receive this frame and some don't.
//
// Contains all statistic associated with the frame and gathered in multiple
// points of the video pipeline.
//
// Internally may store the copy of the source frame which was sent. In such
// case this frame is "alive".
class FrameInFlight {
public:
FrameInFlight(size_t stream,
VideoFrame frame,
Timestamp captured_time,
std::set<size_t> expected_receivers);
size_t stream() const { return stream_; }
// Returns internal copy of source `VideoFrame` or `absl::nullopt` if it was
// removed before.
const absl::optional<VideoFrame>& frame() const { return frame_; }
// Removes internal copy of the source `VideoFrame` to free up extra memory.
// Returns was frame removed or not.
bool RemoveFrame();
void SetFrameId(uint16_t id);
void AddExpectedReceiver(size_t peer) { expected_receivers_.insert(peer); }
void RemoveExpectedReceiver(size_t peer) { expected_receivers_.erase(peer); }
std::vector<size_t> GetPeersWhichDidntReceive() const;
// Returns if all peers which were expected to receive this frame actually
// received it or not.
bool HaveAllPeersReceived() const;
void SetPreEncodeTime(webrtc::Timestamp time) { pre_encode_time_ = time; }
void OnFrameEncoded(webrtc::Timestamp time,
VideoFrameType frame_type,
DataSize encoded_image_size,
uint32_t target_encode_bitrate,
StreamCodecInfo used_encoder);
bool HasEncodedTime() const { return encoded_time_.IsFinite(); }
void OnFramePreDecode(size_t peer,
webrtc::Timestamp received_time,
webrtc::Timestamp decode_start_time,
VideoFrameType frame_type,
DataSize encoded_image_size);
bool HasReceivedTime(size_t peer) const;
void OnFrameDecoded(size_t peer,
webrtc::Timestamp time,
StreamCodecInfo used_decoder);
bool HasDecodeEndTime(size_t peer) const;
void OnFrameRendered(size_t peer,
webrtc::Timestamp time,
int width,
int height);
bool HasRenderedTime(size_t peer) const;
// Crash if rendered time is not set for specified `peer`.
webrtc::Timestamp rendered_time(size_t peer) const {
return receiver_stats_.at(peer).rendered_time;
}
// Marks that frame was dropped and wasn't seen by particular `peer`.
void MarkDropped(size_t peer) { receiver_stats_[peer].dropped = true; }
bool IsDropped(size_t peer) const;
void SetPrevFrameRenderedTime(size_t peer, webrtc::Timestamp time) {
receiver_stats_[peer].prev_frame_rendered_time = time;
}
FrameStats GetStatsForPeer(size_t peer) const;
private:
const size_t stream_;
// Set of peer's indexes who are expected to receive this frame. This is not
// the set of peer's indexes that received the frame. For example, if peer A
// was among expected receivers, it received frame and then left the call, A
// will be removed from this set, but the Stats for peer A still will be
// preserved in the FrameInFlight.
//
// This set is used to determine if this frame is expected to be received by
// any peer or can be safely deleted. It is responsibility of the user of this
// object to decide when it should be deleted.
std::set<size_t> expected_receivers_;
absl::optional<VideoFrame> frame_;
// Frame events timestamp.
Timestamp captured_time_;
Timestamp pre_encode_time_ = Timestamp::MinusInfinity();
Timestamp encoded_time_ = Timestamp::MinusInfinity();
// Type and encoded size of sent frame.
VideoFrameType frame_type_ = VideoFrameType::kEmptyFrame;
DataSize encoded_image_size_ = DataSize::Bytes(0);
uint32_t target_encode_bitrate_ = 0;
// Can be not set if frame was dropped by encoder.
absl::optional<StreamCodecInfo> used_encoder_ = absl::nullopt;
// Map from the receiver peer's index to frame stats for that peer.
std::map<size_t, ReceiverFrameStats> receiver_stats_;
};
} // namespace webrtc
#endif // TEST_PC_E2E_ANALYZER_VIDEO_DEFAULT_VIDEO_QUALITY_ANALYZER_FRAME_IN_FLIGHT_H_

View File

@ -10,6 +10,8 @@
#include "test/pc/e2e/analyzer/video/names_collection.h"
#include <set>
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
@ -78,4 +80,14 @@ absl::optional<size_t> NamesCollection::RemoveIfPresent(
return index;
}
std::set<size_t> NamesCollection::GetPresentIndexes() const {
std::set<size_t> out;
for (size_t i = 0; i < removed_.size(); ++i) {
if (!removed_[i]) {
out.insert(i);
}
}
return out;
}
} // namespace webrtc

View File

@ -12,6 +12,7 @@
#define TEST_PC_E2E_ANALYZER_VIDEO_NAMES_COLLECTION_H_
#include <map>
#include <set>
#include <string>
#include <vector>
@ -70,6 +71,10 @@ class NamesCollection {
// registered in the collection.
absl::optional<size_t> RemoveIfPresent(absl::string_view name);
// Returns a set of indexes for all currently present names in the
// collection.
std::set<size_t> GetPresentIndexes() const;
private:
std::vector<std::string> names_;
std::vector<bool> removed_;