2014-02-07 12:06:29 +00:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2013 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.
|
|
|
|
|
*/
|
|
|
|
|
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "video/receive_statistics_proxy.h"
|
2014-02-07 12:06:29 +00:00
|
|
|
|
2017-02-22 05:30:39 -08:00
|
|
|
#include <algorithm>
|
2015-10-08 00:41:59 -07:00
|
|
|
#include <cmath>
|
2017-02-22 05:30:39 -08:00
|
|
|
#include <utility>
|
2015-10-08 00:41:59 -07:00
|
|
|
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "modules/video_coding/include/video_codec_interface.h"
|
|
|
|
|
#include "rtc_base/checks.h"
|
|
|
|
|
#include "rtc_base/logging.h"
|
Adding a new string utility class: SimpleStringBuilder.
This is a fairly minimalistic string building class that
can be used instead of stringstream, which is discouraged
but tempting to use due to its convenient interface and
familiarity for anyone using our logging macros.
As a starter, I'm changing the string building code in
ReceiveStatisticsProxy and SendStatisticsProxy from using
stringstream and using SimpleStringBuilder instead.
In the case of SimpleStringBuilder, there's a single allocation,
it's done on the stack (fast), and minimal code is required for
each concatenation. The developer is responsible for ensuring
that the buffer size is adequate but the class won't overflow
the buffer. In dcheck-enabled builds, a check will go off if
we run out of buffer space.
As part of using SimpleStringBuilder for a small part of
rtc::LogMessage, a few more changes were made:
- SimpleStringBuilder is used for formatting errors instead of ostringstream.
- A new 'noop' state has been introduced for log messages that will be dropped.
- Use a static (singleton) noop ostream object for noop logging messages
instead of building up an actual ostringstream object that will be dropped.
- Add a LogMessageForTest class for better state inspection/testing.
- Fix benign bug in LogTest.Perf, change the test to not use File IO and
always enable it.
- Ensure that minimal work is done for noop messages.
- Remove dependency on rtc::Thread.
- Add tests for the extra_ field, correctly parsed paths and noop handling.
Bug: webrtc:8529, webrtc:4364, webrtc:8933
Change-Id: Ifa258c135135945e4560d9e24315f7d96f784acb
Reviewed-on: https://webrtc-review.googlesource.com/55520
Commit-Queue: Tommi <tommi@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Reviewed-by: Jonas Olsson <jonasolsson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22203}
2018-02-27 13:51:08 +01:00
|
|
|
#include "rtc_base/strings/string_builder.h"
|
2019-01-11 09:11:00 -08:00
|
|
|
#include "rtc_base/time_utils.h"
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "system_wrappers/include/clock.h"
|
|
|
|
|
#include "system_wrappers/include/metrics.h"
|
2014-02-07 12:06:29 +00:00
|
|
|
|
|
|
|
|
namespace webrtc {
|
2016-11-02 07:14:03 -07:00
|
|
|
namespace {
|
2021-07-27 16:22:11 +02:00
|
|
|
// Periodic time interval for processing samples for `freq_offset_counter_`.
|
2016-11-02 07:14:03 -07:00
|
|
|
const int64_t kFreqOffsetProcessIntervalMs = 40000;
|
2016-12-13 02:45:57 -08:00
|
|
|
|
|
|
|
|
// Configuration for bad call detection.
|
2017-01-13 05:58:34 -08:00
|
|
|
const int kBadCallMinRequiredSamples = 10;
|
2016-12-13 02:45:57 -08:00
|
|
|
const int kMinSampleLengthMs = 990;
|
|
|
|
|
const int kNumMeasurements = 10;
|
|
|
|
|
const int kNumMeasurementsVariance = kNumMeasurements * 1.5;
|
|
|
|
|
const float kBadFraction = 0.8f;
|
|
|
|
|
// For fps:
|
|
|
|
|
// Low means low enough to be bad, high means high enough to be good
|
|
|
|
|
const int kLowFpsThreshold = 12;
|
|
|
|
|
const int kHighFpsThreshold = 14;
|
|
|
|
|
// For qp and fps variance:
|
|
|
|
|
// Low means low enough to be good, high means high enough to be bad
|
|
|
|
|
const int kLowQpThresholdVp8 = 60;
|
|
|
|
|
const int kHighQpThresholdVp8 = 70;
|
|
|
|
|
const int kLowVarianceThreshold = 1;
|
|
|
|
|
const int kHighVarianceThreshold = 2;
|
2017-02-22 05:30:39 -08:00
|
|
|
|
2017-08-23 05:24:10 -07:00
|
|
|
// Some metrics are reported as a maximum over this period.
|
2017-10-16 17:59:12 +02:00
|
|
|
// This should be synchronized with a typical getStats polling interval in
|
|
|
|
|
// the clients.
|
|
|
|
|
const int kMovingMaxWindowMs = 1000;
|
2017-08-23 05:24:10 -07:00
|
|
|
|
2017-02-22 05:30:39 -08:00
|
|
|
// How large window we use to calculate the framerate/bitrate.
|
|
|
|
|
const int kRateStatisticsWindowSizeMs = 1000;
|
2017-08-30 03:32:14 -07:00
|
|
|
|
2017-10-06 12:29:47 +02:00
|
|
|
// Some sane ballpark estimate for maximum common value of inter-frame delay.
|
|
|
|
|
// Values below that will be stored explicitly in the array,
|
|
|
|
|
// values above - in the map.
|
|
|
|
|
const int kMaxCommonInterframeDelayMs = 500;
|
|
|
|
|
|
Adding a new string utility class: SimpleStringBuilder.
This is a fairly minimalistic string building class that
can be used instead of stringstream, which is discouraged
but tempting to use due to its convenient interface and
familiarity for anyone using our logging macros.
As a starter, I'm changing the string building code in
ReceiveStatisticsProxy and SendStatisticsProxy from using
stringstream and using SimpleStringBuilder instead.
In the case of SimpleStringBuilder, there's a single allocation,
it's done on the stack (fast), and minimal code is required for
each concatenation. The developer is responsible for ensuring
that the buffer size is adequate but the class won't overflow
the buffer. In dcheck-enabled builds, a check will go off if
we run out of buffer space.
As part of using SimpleStringBuilder for a small part of
rtc::LogMessage, a few more changes were made:
- SimpleStringBuilder is used for formatting errors instead of ostringstream.
- A new 'noop' state has been introduced for log messages that will be dropped.
- Use a static (singleton) noop ostream object for noop logging messages
instead of building up an actual ostringstream object that will be dropped.
- Add a LogMessageForTest class for better state inspection/testing.
- Fix benign bug in LogTest.Perf, change the test to not use File IO and
always enable it.
- Ensure that minimal work is done for noop messages.
- Remove dependency on rtc::Thread.
- Add tests for the extra_ field, correctly parsed paths and noop handling.
Bug: webrtc:8529, webrtc:4364, webrtc:8933
Change-Id: Ifa258c135135945e4560d9e24315f7d96f784acb
Reviewed-on: https://webrtc-review.googlesource.com/55520
Commit-Queue: Tommi <tommi@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Reviewed-by: Jonas Olsson <jonasolsson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22203}
2018-02-27 13:51:08 +01:00
|
|
|
const char* UmaPrefixForContentType(VideoContentType content_type) {
|
|
|
|
|
if (videocontenttypehelpers::IsScreenshare(content_type))
|
|
|
|
|
return "WebRTC.Video.Screenshare";
|
|
|
|
|
return "WebRTC.Video";
|
2017-08-30 03:32:14 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string UmaSuffixForContentType(VideoContentType content_type) {
|
2018-03-08 15:03:23 +01:00
|
|
|
char ss_buf[1024];
|
|
|
|
|
rtc::SimpleStringBuilder ss(ss_buf);
|
2017-08-30 03:32:14 -07:00
|
|
|
int simulcast_id = videocontenttypehelpers::GetSimulcastId(content_type);
|
|
|
|
|
if (simulcast_id > 0) {
|
|
|
|
|
ss << ".S" << simulcast_id - 1;
|
|
|
|
|
}
|
|
|
|
|
int experiment_id = videocontenttypehelpers::GetExperimentId(content_type);
|
|
|
|
|
if (experiment_id > 0) {
|
|
|
|
|
ss << ".ExperimentGroup" << experiment_id - 1;
|
|
|
|
|
}
|
|
|
|
|
return ss.str();
|
|
|
|
|
}
|
Adding a new string utility class: SimpleStringBuilder.
This is a fairly minimalistic string building class that
can be used instead of stringstream, which is discouraged
but tempting to use due to its convenient interface and
familiarity for anyone using our logging macros.
As a starter, I'm changing the string building code in
ReceiveStatisticsProxy and SendStatisticsProxy from using
stringstream and using SimpleStringBuilder instead.
In the case of SimpleStringBuilder, there's a single allocation,
it's done on the stack (fast), and minimal code is required for
each concatenation. The developer is responsible for ensuring
that the buffer size is adequate but the class won't overflow
the buffer. In dcheck-enabled builds, a check will go off if
we run out of buffer space.
As part of using SimpleStringBuilder for a small part of
rtc::LogMessage, a few more changes were made:
- SimpleStringBuilder is used for formatting errors instead of ostringstream.
- A new 'noop' state has been introduced for log messages that will be dropped.
- Use a static (singleton) noop ostream object for noop logging messages
instead of building up an actual ostringstream object that will be dropped.
- Add a LogMessageForTest class for better state inspection/testing.
- Fix benign bug in LogTest.Perf, change the test to not use File IO and
always enable it.
- Ensure that minimal work is done for noop messages.
- Remove dependency on rtc::Thread.
- Add tests for the extra_ field, correctly parsed paths and noop handling.
Bug: webrtc:8529, webrtc:4364, webrtc:8933
Change-Id: Ifa258c135135945e4560d9e24315f7d96f784acb
Reviewed-on: https://webrtc-review.googlesource.com/55520
Commit-Queue: Tommi <tommi@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Reviewed-by: Jonas Olsson <jonasolsson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22203}
2018-02-27 13:51:08 +01:00
|
|
|
|
2022-03-29 11:04:48 +02:00
|
|
|
bool EnableDecodeTimeHistogram(const FieldTrialsView* field_trials) {
|
2022-03-14 12:52:48 +01:00
|
|
|
if (field_trials == nullptr) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return !field_trials->IsEnabled("WebRTC-DecodeTimeHistogramsKillSwitch");
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-02 07:14:03 -07:00
|
|
|
} // namespace
|
2014-02-07 12:06:29 +00:00
|
|
|
|
2022-03-14 12:52:48 +01:00
|
|
|
ReceiveStatisticsProxy::ReceiveStatisticsProxy(
|
|
|
|
|
uint32_t remote_ssrc,
|
|
|
|
|
Clock* clock,
|
2022-03-29 11:04:48 +02:00
|
|
|
const FieldTrialsView* field_trials)
|
2014-12-19 15:45:03 +00:00
|
|
|
: clock_(clock),
|
2016-07-27 00:39:09 -07:00
|
|
|
start_ms_(clock->TimeInMilliseconds()),
|
2022-03-14 12:52:48 +01:00
|
|
|
enable_decode_time_histograms_(EnableDecodeTimeHistogram(field_trials)),
|
2016-12-13 02:45:57 -08:00
|
|
|
last_sample_time_(clock->TimeInMilliseconds()),
|
|
|
|
|
fps_threshold_(kLowFpsThreshold,
|
|
|
|
|
kHighFpsThreshold,
|
|
|
|
|
kBadFraction,
|
|
|
|
|
kNumMeasurements),
|
|
|
|
|
qp_threshold_(kLowQpThresholdVp8,
|
|
|
|
|
kHighQpThresholdVp8,
|
|
|
|
|
kBadFraction,
|
|
|
|
|
kNumMeasurements),
|
|
|
|
|
variance_threshold_(kLowVarianceThreshold,
|
|
|
|
|
kHighVarianceThreshold,
|
|
|
|
|
kBadFraction,
|
|
|
|
|
kNumMeasurementsVariance),
|
2017-01-13 05:58:34 -08:00
|
|
|
num_bad_states_(0),
|
|
|
|
|
num_certain_states_(0),
|
2014-02-07 12:06:29 +00:00
|
|
|
// 1000ms window, scale 1000 for ms to s.
|
|
|
|
|
decode_fps_estimator_(1000, 1000),
|
2015-09-14 10:38:08 -07:00
|
|
|
renders_fps_estimator_(1000, 1000),
|
2016-05-06 11:29:15 -07:00
|
|
|
render_fps_tracker_(100, 10u),
|
2016-11-02 07:14:03 -07:00
|
|
|
render_pixel_tracker_(100, 10u),
|
2018-05-23 11:53:19 +02:00
|
|
|
video_quality_observer_(
|
|
|
|
|
new VideoQualityObserver(VideoContentType::UNSPECIFIED)),
|
2017-08-23 05:24:10 -07:00
|
|
|
interframe_delay_max_moving_(kMovingMaxWindowMs),
|
2016-11-30 01:42:26 -08:00
|
|
|
freq_offset_counter_(clock, nullptr, kFreqOffsetProcessIntervalMs),
|
2017-04-11 10:34:31 -07:00
|
|
|
avg_rtt_ms_(0),
|
2017-09-04 03:35:40 -07:00
|
|
|
last_content_type_(VideoContentType::UNSPECIFIED),
|
2018-05-23 11:53:19 +02:00
|
|
|
last_codec_type_(kVideoCodecVP8),
|
2018-06-05 13:34:33 +02:00
|
|
|
num_delayed_frames_rendered_(0),
|
|
|
|
|
sum_missed_render_deadline_ms_(0),
|
2020-04-07 18:02:39 +00:00
|
|
|
timing_frame_info_counter_(kMovingMaxWindowMs) {
|
|
|
|
|
decode_thread_.Detach();
|
|
|
|
|
network_thread_.Detach();
|
2021-10-15 16:29:25 +02:00
|
|
|
stats_.ssrc = remote_ssrc;
|
2014-02-07 12:06:29 +00:00
|
|
|
}
|
|
|
|
|
|
2019-08-02 13:52:37 +02:00
|
|
|
void ReceiveStatisticsProxy::UpdateHistograms(
|
2019-08-13 14:43:02 +02:00
|
|
|
absl::optional<int> fraction_lost,
|
|
|
|
|
const StreamDataCounters& rtp_stats,
|
|
|
|
|
const StreamDataCounters* rtx_stats) {
|
2020-04-07 18:02:39 +00:00
|
|
|
// Not actually running on the decoder thread, but must be called after
|
2019-08-02 13:52:37 +02:00
|
|
|
// DecoderThreadStopped, which detaches the thread checker. It is therefore
|
2021-07-27 16:22:11 +02:00
|
|
|
// safe to access `qp_counters_`, which were updated on the decode thread
|
2019-08-02 13:52:37 +02:00
|
|
|
// earlier.
|
2020-04-07 18:02:39 +00:00
|
|
|
RTC_DCHECK_RUN_ON(&decode_thread_);
|
2019-08-02 13:52:37 +02:00
|
|
|
|
2020-07-08 13:13:32 +02:00
|
|
|
MutexLock lock(&mutex_);
|
2019-08-02 13:52:37 +02:00
|
|
|
|
2018-03-08 15:03:23 +01:00
|
|
|
char log_stream_buf[8 * 1024];
|
|
|
|
|
rtc::SimpleStringBuilder log_stream(log_stream_buf);
|
2017-08-30 03:32:14 -07:00
|
|
|
int stream_duration_sec = (clock_->TimeInMilliseconds() - start_ms_) / 1000;
|
|
|
|
|
if (stats_.frame_counts.key_frames > 0 ||
|
|
|
|
|
stats_.frame_counts.delta_frames > 0) {
|
|
|
|
|
RTC_HISTOGRAM_COUNTS_100000("WebRTC.Video.ReceiveStreamLifetimeInSeconds",
|
|
|
|
|
stream_duration_sec);
|
Adding a new string utility class: SimpleStringBuilder.
This is a fairly minimalistic string building class that
can be used instead of stringstream, which is discouraged
but tempting to use due to its convenient interface and
familiarity for anyone using our logging macros.
As a starter, I'm changing the string building code in
ReceiveStatisticsProxy and SendStatisticsProxy from using
stringstream and using SimpleStringBuilder instead.
In the case of SimpleStringBuilder, there's a single allocation,
it's done on the stack (fast), and minimal code is required for
each concatenation. The developer is responsible for ensuring
that the buffer size is adequate but the class won't overflow
the buffer. In dcheck-enabled builds, a check will go off if
we run out of buffer space.
As part of using SimpleStringBuilder for a small part of
rtc::LogMessage, a few more changes were made:
- SimpleStringBuilder is used for formatting errors instead of ostringstream.
- A new 'noop' state has been introduced for log messages that will be dropped.
- Use a static (singleton) noop ostream object for noop logging messages
instead of building up an actual ostringstream object that will be dropped.
- Add a LogMessageForTest class for better state inspection/testing.
- Fix benign bug in LogTest.Perf, change the test to not use File IO and
always enable it.
- Ensure that minimal work is done for noop messages.
- Remove dependency on rtc::Thread.
- Add tests for the extra_ field, correctly parsed paths and noop handling.
Bug: webrtc:8529, webrtc:4364, webrtc:8933
Change-Id: Ifa258c135135945e4560d9e24315f7d96f784acb
Reviewed-on: https://webrtc-review.googlesource.com/55520
Commit-Queue: Tommi <tommi@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Reviewed-by: Jonas Olsson <jonasolsson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22203}
2018-02-27 13:51:08 +01:00
|
|
|
log_stream << "WebRTC.Video.ReceiveStreamLifetimeInSeconds "
|
|
|
|
|
<< stream_duration_sec << '\n';
|
2017-08-30 03:32:14 -07:00
|
|
|
}
|
2016-07-27 00:39:09 -07:00
|
|
|
|
2018-05-23 11:53:19 +02:00
|
|
|
log_stream << "Frames decoded " << stats_.frames_decoded << '\n';
|
2018-02-21 15:57:09 +01:00
|
|
|
|
|
|
|
|
if (num_unique_frames_) {
|
|
|
|
|
int num_dropped_frames = *num_unique_frames_ - stats_.frames_decoded;
|
|
|
|
|
RTC_HISTOGRAM_COUNTS_1000("WebRTC.Video.DroppedFrames.Receiver",
|
|
|
|
|
num_dropped_frames);
|
2018-05-23 11:53:19 +02:00
|
|
|
log_stream << "WebRTC.Video.DroppedFrames.Receiver " << num_dropped_frames
|
|
|
|
|
<< '\n';
|
2018-02-21 15:57:09 +01:00
|
|
|
}
|
|
|
|
|
|
2019-08-02 13:52:37 +02:00
|
|
|
if (fraction_lost && stream_duration_sec >= metrics::kMinRunTimeInSeconds) {
|
|
|
|
|
RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.ReceivedPacketsLostInPercent",
|
|
|
|
|
*fraction_lost);
|
|
|
|
|
log_stream << "WebRTC.Video.ReceivedPacketsLostInPercent " << *fraction_lost
|
|
|
|
|
<< '\n';
|
2015-04-27 10:09:49 +02:00
|
|
|
}
|
2016-11-30 01:42:26 -08:00
|
|
|
|
2018-01-24 17:04:07 +01:00
|
|
|
if (first_decoded_frame_time_ms_) {
|
|
|
|
|
const int64_t elapsed_ms =
|
|
|
|
|
(clock_->TimeInMilliseconds() - *first_decoded_frame_time_ms_);
|
|
|
|
|
if (elapsed_ms >=
|
|
|
|
|
metrics::kMinRunTimeInSeconds * rtc::kNumMillisecsPerSec) {
|
2019-05-21 14:42:29 +02:00
|
|
|
int decoded_fps = static_cast<int>(
|
|
|
|
|
(stats_.frames_decoded * 1000.0f / elapsed_ms) + 0.5f);
|
|
|
|
|
RTC_HISTOGRAM_COUNTS_100("WebRTC.Video.DecodedFramesPerSecond",
|
|
|
|
|
decoded_fps);
|
|
|
|
|
log_stream << "WebRTC.Video.DecodedFramesPerSecond " << decoded_fps
|
|
|
|
|
<< '\n';
|
2018-06-05 13:34:33 +02:00
|
|
|
|
|
|
|
|
const uint32_t frames_rendered = stats_.frames_rendered;
|
|
|
|
|
if (frames_rendered > 0) {
|
|
|
|
|
RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.DelayedFramesToRenderer",
|
|
|
|
|
static_cast<int>(num_delayed_frames_rendered_ *
|
|
|
|
|
100 / frames_rendered));
|
|
|
|
|
if (num_delayed_frames_rendered_ > 0) {
|
|
|
|
|
RTC_HISTOGRAM_COUNTS_1000(
|
|
|
|
|
"WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs",
|
|
|
|
|
static_cast<int>(sum_missed_render_deadline_ms_ /
|
|
|
|
|
num_delayed_frames_rendered_));
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-01-24 17:04:07 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-24 00:20:58 -07:00
|
|
|
const int kMinRequiredSamples = 200;
|
2015-10-08 00:41:59 -07:00
|
|
|
int samples = static_cast<int>(render_fps_tracker_.TotalSampleCount());
|
2017-05-11 05:37:35 -07:00
|
|
|
if (samples >= kMinRequiredSamples) {
|
2019-05-21 14:42:29 +02:00
|
|
|
int rendered_fps = round(render_fps_tracker_.ComputeTotalRate());
|
2016-09-09 22:40:25 -07:00
|
|
|
RTC_HISTOGRAM_COUNTS_100("WebRTC.Video.RenderFramesPerSecond",
|
2019-05-21 14:42:29 +02:00
|
|
|
rendered_fps);
|
|
|
|
|
log_stream << "WebRTC.Video.RenderFramesPerSecond " << rendered_fps << '\n';
|
2016-09-09 22:40:25 -07:00
|
|
|
RTC_HISTOGRAM_COUNTS_100000(
|
2016-01-25 05:58:23 -08:00
|
|
|
"WebRTC.Video.RenderSqrtPixelsPerSecond",
|
2015-11-10 16:34:50 -08:00
|
|
|
round(render_pixel_tracker_.ComputeTotalRate()));
|
2015-10-08 00:41:59 -07:00
|
|
|
}
|
2017-08-30 03:32:14 -07:00
|
|
|
|
2018-06-15 12:28:07 +02:00
|
|
|
absl::optional<int> sync_offset_ms =
|
2018-05-22 10:54:30 +02:00
|
|
|
sync_offset_counter_.Avg(kMinRequiredSamples);
|
|
|
|
|
if (sync_offset_ms) {
|
|
|
|
|
RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.AVSyncOffsetInMs",
|
|
|
|
|
*sync_offset_ms);
|
|
|
|
|
log_stream << "WebRTC.Video.AVSyncOffsetInMs " << *sync_offset_ms << '\n';
|
2016-05-03 03:32:10 -07:00
|
|
|
}
|
2016-11-02 07:14:03 -07:00
|
|
|
AggregatedStats freq_offset_stats = freq_offset_counter_.GetStats();
|
|
|
|
|
if (freq_offset_stats.num_samples > 0) {
|
|
|
|
|
RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.RtpToNtpFreqOffsetInKhz",
|
|
|
|
|
freq_offset_stats.average);
|
Adding a new string utility class: SimpleStringBuilder.
This is a fairly minimalistic string building class that
can be used instead of stringstream, which is discouraged
but tempting to use due to its convenient interface and
familiarity for anyone using our logging macros.
As a starter, I'm changing the string building code in
ReceiveStatisticsProxy and SendStatisticsProxy from using
stringstream and using SimpleStringBuilder instead.
In the case of SimpleStringBuilder, there's a single allocation,
it's done on the stack (fast), and minimal code is required for
each concatenation. The developer is responsible for ensuring
that the buffer size is adequate but the class won't overflow
the buffer. In dcheck-enabled builds, a check will go off if
we run out of buffer space.
As part of using SimpleStringBuilder for a small part of
rtc::LogMessage, a few more changes were made:
- SimpleStringBuilder is used for formatting errors instead of ostringstream.
- A new 'noop' state has been introduced for log messages that will be dropped.
- Use a static (singleton) noop ostream object for noop logging messages
instead of building up an actual ostringstream object that will be dropped.
- Add a LogMessageForTest class for better state inspection/testing.
- Fix benign bug in LogTest.Perf, change the test to not use File IO and
always enable it.
- Ensure that minimal work is done for noop messages.
- Remove dependency on rtc::Thread.
- Add tests for the extra_ field, correctly parsed paths and noop handling.
Bug: webrtc:8529, webrtc:4364, webrtc:8933
Change-Id: Ifa258c135135945e4560d9e24315f7d96f784acb
Reviewed-on: https://webrtc-review.googlesource.com/55520
Commit-Queue: Tommi <tommi@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Reviewed-by: Jonas Olsson <jonasolsson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22203}
2018-02-27 13:51:08 +01:00
|
|
|
log_stream << "WebRTC.Video.RtpToNtpFreqOffsetInKhz "
|
|
|
|
|
<< freq_offset_stats.ToString() << '\n';
|
2016-11-02 07:14:03 -07:00
|
|
|
}
|
2016-03-15 01:00:47 -07:00
|
|
|
|
2017-04-20 04:05:43 -07:00
|
|
|
int num_total_frames =
|
|
|
|
|
stats_.frame_counts.key_frames + stats_.frame_counts.delta_frames;
|
|
|
|
|
if (num_total_frames >= kMinRequiredSamples) {
|
|
|
|
|
int num_key_frames = stats_.frame_counts.key_frames;
|
2017-02-22 05:30:39 -08:00
|
|
|
int key_frames_permille =
|
2017-04-20 04:05:43 -07:00
|
|
|
(num_key_frames * 1000 + num_total_frames / 2) / num_total_frames;
|
2017-02-22 05:30:39 -08:00
|
|
|
RTC_HISTOGRAM_COUNTS_1000("WebRTC.Video.KeyFramesReceivedInPermille",
|
|
|
|
|
key_frames_permille);
|
Adding a new string utility class: SimpleStringBuilder.
This is a fairly minimalistic string building class that
can be used instead of stringstream, which is discouraged
but tempting to use due to its convenient interface and
familiarity for anyone using our logging macros.
As a starter, I'm changing the string building code in
ReceiveStatisticsProxy and SendStatisticsProxy from using
stringstream and using SimpleStringBuilder instead.
In the case of SimpleStringBuilder, there's a single allocation,
it's done on the stack (fast), and minimal code is required for
each concatenation. The developer is responsible for ensuring
that the buffer size is adequate but the class won't overflow
the buffer. In dcheck-enabled builds, a check will go off if
we run out of buffer space.
As part of using SimpleStringBuilder for a small part of
rtc::LogMessage, a few more changes were made:
- SimpleStringBuilder is used for formatting errors instead of ostringstream.
- A new 'noop' state has been introduced for log messages that will be dropped.
- Use a static (singleton) noop ostream object for noop logging messages
instead of building up an actual ostringstream object that will be dropped.
- Add a LogMessageForTest class for better state inspection/testing.
- Fix benign bug in LogTest.Perf, change the test to not use File IO and
always enable it.
- Ensure that minimal work is done for noop messages.
- Remove dependency on rtc::Thread.
- Add tests for the extra_ field, correctly parsed paths and noop handling.
Bug: webrtc:8529, webrtc:4364, webrtc:8933
Change-Id: Ifa258c135135945e4560d9e24315f7d96f784acb
Reviewed-on: https://webrtc-review.googlesource.com/55520
Commit-Queue: Tommi <tommi@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Reviewed-by: Jonas Olsson <jonasolsson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22203}
2018-02-27 13:51:08 +01:00
|
|
|
log_stream << "WebRTC.Video.KeyFramesReceivedInPermille "
|
|
|
|
|
<< key_frames_permille << '\n';
|
2017-02-22 05:30:39 -08:00
|
|
|
}
|
|
|
|
|
|
2018-06-15 12:28:07 +02:00
|
|
|
absl::optional<int> qp = qp_counters_.vp8.Avg(kMinRequiredSamples);
|
2018-05-22 10:54:30 +02:00
|
|
|
if (qp) {
|
|
|
|
|
RTC_HISTOGRAM_COUNTS_200("WebRTC.Video.Decoded.Vp8.Qp", *qp);
|
|
|
|
|
log_stream << "WebRTC.Video.Decoded.Vp8.Qp " << *qp << '\n';
|
2017-05-11 05:37:35 -07:00
|
|
|
}
|
2018-06-15 12:28:07 +02:00
|
|
|
absl::optional<int> decode_ms = decode_time_counter_.Avg(kMinRequiredSamples);
|
2018-05-22 10:54:30 +02:00
|
|
|
if (decode_ms) {
|
|
|
|
|
RTC_HISTOGRAM_COUNTS_1000("WebRTC.Video.DecodeTimeInMs", *decode_ms);
|
|
|
|
|
log_stream << "WebRTC.Video.DecodeTimeInMs " << *decode_ms << '\n';
|
2017-05-11 05:37:35 -07:00
|
|
|
}
|
2018-06-15 12:28:07 +02:00
|
|
|
absl::optional<int> jb_delay_ms =
|
2018-05-22 10:54:30 +02:00
|
|
|
jitter_buffer_delay_counter_.Avg(kMinRequiredSamples);
|
|
|
|
|
if (jb_delay_ms) {
|
2017-02-22 05:30:39 -08:00
|
|
|
RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.JitterBufferDelayInMs",
|
2018-05-22 10:54:30 +02:00
|
|
|
*jb_delay_ms);
|
|
|
|
|
log_stream << "WebRTC.Video.JitterBufferDelayInMs " << *jb_delay_ms << '\n';
|
2016-04-27 23:42:35 -07:00
|
|
|
}
|
2017-02-22 05:30:39 -08:00
|
|
|
|
2018-06-15 12:28:07 +02:00
|
|
|
absl::optional<int> target_delay_ms =
|
2018-05-22 10:54:30 +02:00
|
|
|
target_delay_counter_.Avg(kMinRequiredSamples);
|
|
|
|
|
if (target_delay_ms) {
|
|
|
|
|
RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.TargetDelayInMs",
|
|
|
|
|
*target_delay_ms);
|
|
|
|
|
log_stream << "WebRTC.Video.TargetDelayInMs " << *target_delay_ms << '\n';
|
2016-04-27 23:42:35 -07:00
|
|
|
}
|
2018-06-15 12:28:07 +02:00
|
|
|
absl::optional<int> current_delay_ms =
|
2018-05-22 10:54:30 +02:00
|
|
|
current_delay_counter_.Avg(kMinRequiredSamples);
|
|
|
|
|
if (current_delay_ms) {
|
2016-09-09 22:40:25 -07:00
|
|
|
RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.CurrentDelayInMs",
|
2018-05-22 10:54:30 +02:00
|
|
|
*current_delay_ms);
|
|
|
|
|
log_stream << "WebRTC.Video.CurrentDelayInMs " << *current_delay_ms << '\n';
|
2016-04-27 23:42:35 -07:00
|
|
|
}
|
2018-06-15 12:28:07 +02:00
|
|
|
absl::optional<int> delay_ms = delay_counter_.Avg(kMinRequiredSamples);
|
2018-05-22 10:54:30 +02:00
|
|
|
if (delay_ms)
|
|
|
|
|
RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.OnewayDelayInMs", *delay_ms);
|
2016-02-24 01:35:40 -08:00
|
|
|
|
2017-08-30 03:32:14 -07:00
|
|
|
// Aggregate content_specific_stats_ by removing experiment or simulcast
|
|
|
|
|
// information;
|
|
|
|
|
std::map<VideoContentType, ContentSpecificStats> aggregated_stats;
|
2019-01-27 17:29:42 +01:00
|
|
|
for (const auto& it : content_specific_stats_) {
|
2017-08-30 03:32:14 -07:00
|
|
|
// Calculate simulcast specific metrics (".S0" ... ".S2" suffixes).
|
|
|
|
|
VideoContentType content_type = it.first;
|
|
|
|
|
if (videocontenttypehelpers::GetSimulcastId(content_type) > 0) {
|
|
|
|
|
// Aggregate on experiment id.
|
|
|
|
|
videocontenttypehelpers::SetExperimentId(&content_type, 0);
|
|
|
|
|
aggregated_stats[content_type].Add(it.second);
|
|
|
|
|
}
|
|
|
|
|
// Calculate experiment specific metrics (".ExperimentGroup[0-7]" suffixes).
|
|
|
|
|
content_type = it.first;
|
|
|
|
|
if (videocontenttypehelpers::GetExperimentId(content_type) > 0) {
|
|
|
|
|
// Aggregate on simulcast id.
|
|
|
|
|
videocontenttypehelpers::SetSimulcastId(&content_type, 0);
|
|
|
|
|
aggregated_stats[content_type].Add(it.second);
|
|
|
|
|
}
|
|
|
|
|
// Calculate aggregated metrics (no suffixes. Aggregated on everything).
|
|
|
|
|
content_type = it.first;
|
|
|
|
|
videocontenttypehelpers::SetSimulcastId(&content_type, 0);
|
|
|
|
|
videocontenttypehelpers::SetExperimentId(&content_type, 0);
|
|
|
|
|
aggregated_stats[content_type].Add(it.second);
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-27 17:29:42 +01:00
|
|
|
for (const auto& it : aggregated_stats) {
|
2017-08-30 03:32:14 -07:00
|
|
|
// For the metric Foo we report the following slices:
|
|
|
|
|
// WebRTC.Video.Foo,
|
|
|
|
|
// WebRTC.Video.Screenshare.Foo,
|
|
|
|
|
// WebRTC.Video.Foo.S[0-3],
|
|
|
|
|
// WebRTC.Video.Foo.ExperimentGroup[0-7],
|
|
|
|
|
// WebRTC.Video.Screenshare.Foo.S[0-3],
|
|
|
|
|
// WebRTC.Video.Screenshare.Foo.ExperimentGroup[0-7].
|
|
|
|
|
auto content_type = it.first;
|
|
|
|
|
auto stats = it.second;
|
|
|
|
|
std::string uma_prefix = UmaPrefixForContentType(content_type);
|
|
|
|
|
std::string uma_suffix = UmaSuffixForContentType(content_type);
|
|
|
|
|
// Metrics can be sliced on either simulcast id or experiment id but not
|
|
|
|
|
// both.
|
|
|
|
|
RTC_DCHECK(videocontenttypehelpers::GetExperimentId(content_type) == 0 ||
|
|
|
|
|
videocontenttypehelpers::GetSimulcastId(content_type) == 0);
|
|
|
|
|
|
2018-06-15 12:28:07 +02:00
|
|
|
absl::optional<int> e2e_delay_ms =
|
2018-05-22 10:54:30 +02:00
|
|
|
stats.e2e_delay_counter.Avg(kMinRequiredSamples);
|
|
|
|
|
if (e2e_delay_ms) {
|
2017-08-30 03:32:14 -07:00
|
|
|
RTC_HISTOGRAM_COUNTS_SPARSE_10000(
|
2018-05-22 10:54:30 +02:00
|
|
|
uma_prefix + ".EndToEndDelayInMs" + uma_suffix, *e2e_delay_ms);
|
Adding a new string utility class: SimpleStringBuilder.
This is a fairly minimalistic string building class that
can be used instead of stringstream, which is discouraged
but tempting to use due to its convenient interface and
familiarity for anyone using our logging macros.
As a starter, I'm changing the string building code in
ReceiveStatisticsProxy and SendStatisticsProxy from using
stringstream and using SimpleStringBuilder instead.
In the case of SimpleStringBuilder, there's a single allocation,
it's done on the stack (fast), and minimal code is required for
each concatenation. The developer is responsible for ensuring
that the buffer size is adequate but the class won't overflow
the buffer. In dcheck-enabled builds, a check will go off if
we run out of buffer space.
As part of using SimpleStringBuilder for a small part of
rtc::LogMessage, a few more changes were made:
- SimpleStringBuilder is used for formatting errors instead of ostringstream.
- A new 'noop' state has been introduced for log messages that will be dropped.
- Use a static (singleton) noop ostream object for noop logging messages
instead of building up an actual ostringstream object that will be dropped.
- Add a LogMessageForTest class for better state inspection/testing.
- Fix benign bug in LogTest.Perf, change the test to not use File IO and
always enable it.
- Ensure that minimal work is done for noop messages.
- Remove dependency on rtc::Thread.
- Add tests for the extra_ field, correctly parsed paths and noop handling.
Bug: webrtc:8529, webrtc:4364, webrtc:8933
Change-Id: Ifa258c135135945e4560d9e24315f7d96f784acb
Reviewed-on: https://webrtc-review.googlesource.com/55520
Commit-Queue: Tommi <tommi@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Reviewed-by: Jonas Olsson <jonasolsson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22203}
2018-02-27 13:51:08 +01:00
|
|
|
log_stream << uma_prefix << ".EndToEndDelayInMs" << uma_suffix << " "
|
2018-05-22 10:54:30 +02:00
|
|
|
<< *e2e_delay_ms << '\n';
|
2017-08-30 03:32:14 -07:00
|
|
|
}
|
2018-06-15 12:28:07 +02:00
|
|
|
absl::optional<int> e2e_delay_max_ms = stats.e2e_delay_counter.Max();
|
2018-05-22 10:54:30 +02:00
|
|
|
if (e2e_delay_max_ms && e2e_delay_ms) {
|
2017-08-30 03:32:14 -07:00
|
|
|
RTC_HISTOGRAM_COUNTS_SPARSE_100000(
|
2018-05-22 10:54:30 +02:00
|
|
|
uma_prefix + ".EndToEndDelayMaxInMs" + uma_suffix, *e2e_delay_max_ms);
|
Adding a new string utility class: SimpleStringBuilder.
This is a fairly minimalistic string building class that
can be used instead of stringstream, which is discouraged
but tempting to use due to its convenient interface and
familiarity for anyone using our logging macros.
As a starter, I'm changing the string building code in
ReceiveStatisticsProxy and SendStatisticsProxy from using
stringstream and using SimpleStringBuilder instead.
In the case of SimpleStringBuilder, there's a single allocation,
it's done on the stack (fast), and minimal code is required for
each concatenation. The developer is responsible for ensuring
that the buffer size is adequate but the class won't overflow
the buffer. In dcheck-enabled builds, a check will go off if
we run out of buffer space.
As part of using SimpleStringBuilder for a small part of
rtc::LogMessage, a few more changes were made:
- SimpleStringBuilder is used for formatting errors instead of ostringstream.
- A new 'noop' state has been introduced for log messages that will be dropped.
- Use a static (singleton) noop ostream object for noop logging messages
instead of building up an actual ostringstream object that will be dropped.
- Add a LogMessageForTest class for better state inspection/testing.
- Fix benign bug in LogTest.Perf, change the test to not use File IO and
always enable it.
- Ensure that minimal work is done for noop messages.
- Remove dependency on rtc::Thread.
- Add tests for the extra_ field, correctly parsed paths and noop handling.
Bug: webrtc:8529, webrtc:4364, webrtc:8933
Change-Id: Ifa258c135135945e4560d9e24315f7d96f784acb
Reviewed-on: https://webrtc-review.googlesource.com/55520
Commit-Queue: Tommi <tommi@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Reviewed-by: Jonas Olsson <jonasolsson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22203}
2018-02-27 13:51:08 +01:00
|
|
|
log_stream << uma_prefix << ".EndToEndDelayMaxInMs" << uma_suffix << " "
|
2018-05-22 10:54:30 +02:00
|
|
|
<< *e2e_delay_max_ms << '\n';
|
2017-08-30 03:32:14 -07:00
|
|
|
}
|
2018-06-15 12:28:07 +02:00
|
|
|
absl::optional<int> interframe_delay_ms =
|
2017-08-30 03:32:14 -07:00
|
|
|
stats.interframe_delay_counter.Avg(kMinRequiredSamples);
|
2018-05-22 10:54:30 +02:00
|
|
|
if (interframe_delay_ms) {
|
2017-08-30 03:32:14 -07:00
|
|
|
RTC_HISTOGRAM_COUNTS_SPARSE_10000(
|
|
|
|
|
uma_prefix + ".InterframeDelayInMs" + uma_suffix,
|
2018-05-22 10:54:30 +02:00
|
|
|
*interframe_delay_ms);
|
Adding a new string utility class: SimpleStringBuilder.
This is a fairly minimalistic string building class that
can be used instead of stringstream, which is discouraged
but tempting to use due to its convenient interface and
familiarity for anyone using our logging macros.
As a starter, I'm changing the string building code in
ReceiveStatisticsProxy and SendStatisticsProxy from using
stringstream and using SimpleStringBuilder instead.
In the case of SimpleStringBuilder, there's a single allocation,
it's done on the stack (fast), and minimal code is required for
each concatenation. The developer is responsible for ensuring
that the buffer size is adequate but the class won't overflow
the buffer. In dcheck-enabled builds, a check will go off if
we run out of buffer space.
As part of using SimpleStringBuilder for a small part of
rtc::LogMessage, a few more changes were made:
- SimpleStringBuilder is used for formatting errors instead of ostringstream.
- A new 'noop' state has been introduced for log messages that will be dropped.
- Use a static (singleton) noop ostream object for noop logging messages
instead of building up an actual ostringstream object that will be dropped.
- Add a LogMessageForTest class for better state inspection/testing.
- Fix benign bug in LogTest.Perf, change the test to not use File IO and
always enable it.
- Ensure that minimal work is done for noop messages.
- Remove dependency on rtc::Thread.
- Add tests for the extra_ field, correctly parsed paths and noop handling.
Bug: webrtc:8529, webrtc:4364, webrtc:8933
Change-Id: Ifa258c135135945e4560d9e24315f7d96f784acb
Reviewed-on: https://webrtc-review.googlesource.com/55520
Commit-Queue: Tommi <tommi@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Reviewed-by: Jonas Olsson <jonasolsson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22203}
2018-02-27 13:51:08 +01:00
|
|
|
log_stream << uma_prefix << ".InterframeDelayInMs" << uma_suffix << " "
|
2018-05-22 10:54:30 +02:00
|
|
|
<< *interframe_delay_ms << '\n';
|
2017-08-30 03:32:14 -07:00
|
|
|
}
|
2018-06-15 12:28:07 +02:00
|
|
|
absl::optional<int> interframe_delay_max_ms =
|
2018-05-22 10:54:30 +02:00
|
|
|
stats.interframe_delay_counter.Max();
|
|
|
|
|
if (interframe_delay_max_ms && interframe_delay_ms) {
|
2017-08-30 03:32:14 -07:00
|
|
|
RTC_HISTOGRAM_COUNTS_SPARSE_10000(
|
|
|
|
|
uma_prefix + ".InterframeDelayMaxInMs" + uma_suffix,
|
2018-05-22 10:54:30 +02:00
|
|
|
*interframe_delay_max_ms);
|
Adding a new string utility class: SimpleStringBuilder.
This is a fairly minimalistic string building class that
can be used instead of stringstream, which is discouraged
but tempting to use due to its convenient interface and
familiarity for anyone using our logging macros.
As a starter, I'm changing the string building code in
ReceiveStatisticsProxy and SendStatisticsProxy from using
stringstream and using SimpleStringBuilder instead.
In the case of SimpleStringBuilder, there's a single allocation,
it's done on the stack (fast), and minimal code is required for
each concatenation. The developer is responsible for ensuring
that the buffer size is adequate but the class won't overflow
the buffer. In dcheck-enabled builds, a check will go off if
we run out of buffer space.
As part of using SimpleStringBuilder for a small part of
rtc::LogMessage, a few more changes were made:
- SimpleStringBuilder is used for formatting errors instead of ostringstream.
- A new 'noop' state has been introduced for log messages that will be dropped.
- Use a static (singleton) noop ostream object for noop logging messages
instead of building up an actual ostringstream object that will be dropped.
- Add a LogMessageForTest class for better state inspection/testing.
- Fix benign bug in LogTest.Perf, change the test to not use File IO and
always enable it.
- Ensure that minimal work is done for noop messages.
- Remove dependency on rtc::Thread.
- Add tests for the extra_ field, correctly parsed paths and noop handling.
Bug: webrtc:8529, webrtc:4364, webrtc:8933
Change-Id: Ifa258c135135945e4560d9e24315f7d96f784acb
Reviewed-on: https://webrtc-review.googlesource.com/55520
Commit-Queue: Tommi <tommi@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Reviewed-by: Jonas Olsson <jonasolsson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22203}
2018-02-27 13:51:08 +01:00
|
|
|
log_stream << uma_prefix << ".InterframeDelayMaxInMs" << uma_suffix << " "
|
2018-05-22 10:54:30 +02:00
|
|
|
<< *interframe_delay_max_ms << '\n';
|
2017-08-30 03:32:14 -07:00
|
|
|
}
|
2017-04-11 10:34:31 -07:00
|
|
|
|
2018-06-15 12:28:07 +02:00
|
|
|
absl::optional<uint32_t> interframe_delay_95p_ms =
|
2017-10-06 12:29:47 +02:00
|
|
|
stats.interframe_delay_percentiles.GetPercentile(0.95f);
|
|
|
|
|
if (interframe_delay_95p_ms && interframe_delay_ms != -1) {
|
|
|
|
|
RTC_HISTOGRAM_COUNTS_SPARSE_10000(
|
|
|
|
|
uma_prefix + ".InterframeDelay95PercentileInMs" + uma_suffix,
|
|
|
|
|
*interframe_delay_95p_ms);
|
Adding a new string utility class: SimpleStringBuilder.
This is a fairly minimalistic string building class that
can be used instead of stringstream, which is discouraged
but tempting to use due to its convenient interface and
familiarity for anyone using our logging macros.
As a starter, I'm changing the string building code in
ReceiveStatisticsProxy and SendStatisticsProxy from using
stringstream and using SimpleStringBuilder instead.
In the case of SimpleStringBuilder, there's a single allocation,
it's done on the stack (fast), and minimal code is required for
each concatenation. The developer is responsible for ensuring
that the buffer size is adequate but the class won't overflow
the buffer. In dcheck-enabled builds, a check will go off if
we run out of buffer space.
As part of using SimpleStringBuilder for a small part of
rtc::LogMessage, a few more changes were made:
- SimpleStringBuilder is used for formatting errors instead of ostringstream.
- A new 'noop' state has been introduced for log messages that will be dropped.
- Use a static (singleton) noop ostream object for noop logging messages
instead of building up an actual ostringstream object that will be dropped.
- Add a LogMessageForTest class for better state inspection/testing.
- Fix benign bug in LogTest.Perf, change the test to not use File IO and
always enable it.
- Ensure that minimal work is done for noop messages.
- Remove dependency on rtc::Thread.
- Add tests for the extra_ field, correctly parsed paths and noop handling.
Bug: webrtc:8529, webrtc:4364, webrtc:8933
Change-Id: Ifa258c135135945e4560d9e24315f7d96f784acb
Reviewed-on: https://webrtc-review.googlesource.com/55520
Commit-Queue: Tommi <tommi@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Reviewed-by: Jonas Olsson <jonasolsson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22203}
2018-02-27 13:51:08 +01:00
|
|
|
log_stream << uma_prefix << ".InterframeDelay95PercentileInMs"
|
|
|
|
|
<< uma_suffix << " " << *interframe_delay_95p_ms << '\n';
|
2017-10-06 12:29:47 +02:00
|
|
|
}
|
|
|
|
|
|
2018-06-15 12:28:07 +02:00
|
|
|
absl::optional<int> width = stats.received_width.Avg(kMinRequiredSamples);
|
2018-05-22 10:54:30 +02:00
|
|
|
if (width) {
|
2017-08-30 03:32:14 -07:00
|
|
|
RTC_HISTOGRAM_COUNTS_SPARSE_10000(
|
2018-05-22 10:54:30 +02:00
|
|
|
uma_prefix + ".ReceivedWidthInPixels" + uma_suffix, *width);
|
Adding a new string utility class: SimpleStringBuilder.
This is a fairly minimalistic string building class that
can be used instead of stringstream, which is discouraged
but tempting to use due to its convenient interface and
familiarity for anyone using our logging macros.
As a starter, I'm changing the string building code in
ReceiveStatisticsProxy and SendStatisticsProxy from using
stringstream and using SimpleStringBuilder instead.
In the case of SimpleStringBuilder, there's a single allocation,
it's done on the stack (fast), and minimal code is required for
each concatenation. The developer is responsible for ensuring
that the buffer size is adequate but the class won't overflow
the buffer. In dcheck-enabled builds, a check will go off if
we run out of buffer space.
As part of using SimpleStringBuilder for a small part of
rtc::LogMessage, a few more changes were made:
- SimpleStringBuilder is used for formatting errors instead of ostringstream.
- A new 'noop' state has been introduced for log messages that will be dropped.
- Use a static (singleton) noop ostream object for noop logging messages
instead of building up an actual ostringstream object that will be dropped.
- Add a LogMessageForTest class for better state inspection/testing.
- Fix benign bug in LogTest.Perf, change the test to not use File IO and
always enable it.
- Ensure that minimal work is done for noop messages.
- Remove dependency on rtc::Thread.
- Add tests for the extra_ field, correctly parsed paths and noop handling.
Bug: webrtc:8529, webrtc:4364, webrtc:8933
Change-Id: Ifa258c135135945e4560d9e24315f7d96f784acb
Reviewed-on: https://webrtc-review.googlesource.com/55520
Commit-Queue: Tommi <tommi@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Reviewed-by: Jonas Olsson <jonasolsson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22203}
2018-02-27 13:51:08 +01:00
|
|
|
log_stream << uma_prefix << ".ReceivedWidthInPixels" << uma_suffix << " "
|
2018-05-22 10:54:30 +02:00
|
|
|
<< *width << '\n';
|
2017-08-30 03:32:14 -07:00
|
|
|
}
|
2017-04-11 10:34:31 -07:00
|
|
|
|
2018-06-15 12:28:07 +02:00
|
|
|
absl::optional<int> height = stats.received_height.Avg(kMinRequiredSamples);
|
2018-05-22 10:54:30 +02:00
|
|
|
if (height) {
|
2017-08-30 03:32:14 -07:00
|
|
|
RTC_HISTOGRAM_COUNTS_SPARSE_10000(
|
2018-05-22 10:54:30 +02:00
|
|
|
uma_prefix + ".ReceivedHeightInPixels" + uma_suffix, *height);
|
Adding a new string utility class: SimpleStringBuilder.
This is a fairly minimalistic string building class that
can be used instead of stringstream, which is discouraged
but tempting to use due to its convenient interface and
familiarity for anyone using our logging macros.
As a starter, I'm changing the string building code in
ReceiveStatisticsProxy and SendStatisticsProxy from using
stringstream and using SimpleStringBuilder instead.
In the case of SimpleStringBuilder, there's a single allocation,
it's done on the stack (fast), and minimal code is required for
each concatenation. The developer is responsible for ensuring
that the buffer size is adequate but the class won't overflow
the buffer. In dcheck-enabled builds, a check will go off if
we run out of buffer space.
As part of using SimpleStringBuilder for a small part of
rtc::LogMessage, a few more changes were made:
- SimpleStringBuilder is used for formatting errors instead of ostringstream.
- A new 'noop' state has been introduced for log messages that will be dropped.
- Use a static (singleton) noop ostream object for noop logging messages
instead of building up an actual ostringstream object that will be dropped.
- Add a LogMessageForTest class for better state inspection/testing.
- Fix benign bug in LogTest.Perf, change the test to not use File IO and
always enable it.
- Ensure that minimal work is done for noop messages.
- Remove dependency on rtc::Thread.
- Add tests for the extra_ field, correctly parsed paths and noop handling.
Bug: webrtc:8529, webrtc:4364, webrtc:8933
Change-Id: Ifa258c135135945e4560d9e24315f7d96f784acb
Reviewed-on: https://webrtc-review.googlesource.com/55520
Commit-Queue: Tommi <tommi@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Reviewed-by: Jonas Olsson <jonasolsson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22203}
2018-02-27 13:51:08 +01:00
|
|
|
log_stream << uma_prefix << ".ReceivedHeightInPixels" << uma_suffix << " "
|
2018-05-22 10:54:30 +02:00
|
|
|
<< *height << '\n';
|
2017-08-30 03:32:14 -07:00
|
|
|
}
|
2017-04-11 10:34:31 -07:00
|
|
|
|
2017-08-30 03:32:14 -07:00
|
|
|
if (content_type != VideoContentType::UNSPECIFIED) {
|
|
|
|
|
// Don't report these 3 metrics unsliced, as more precise variants
|
|
|
|
|
// are reported separately in this method.
|
|
|
|
|
float flow_duration_sec = stats.flow_duration_ms / 1000.0;
|
|
|
|
|
if (flow_duration_sec >= metrics::kMinRunTimeInSeconds) {
|
|
|
|
|
int media_bitrate_kbps = static_cast<int>(stats.total_media_bytes * 8 /
|
|
|
|
|
flow_duration_sec / 1000);
|
|
|
|
|
RTC_HISTOGRAM_COUNTS_SPARSE_10000(
|
|
|
|
|
uma_prefix + ".MediaBitrateReceivedInKbps" + uma_suffix,
|
|
|
|
|
media_bitrate_kbps);
|
Adding a new string utility class: SimpleStringBuilder.
This is a fairly minimalistic string building class that
can be used instead of stringstream, which is discouraged
but tempting to use due to its convenient interface and
familiarity for anyone using our logging macros.
As a starter, I'm changing the string building code in
ReceiveStatisticsProxy and SendStatisticsProxy from using
stringstream and using SimpleStringBuilder instead.
In the case of SimpleStringBuilder, there's a single allocation,
it's done on the stack (fast), and minimal code is required for
each concatenation. The developer is responsible for ensuring
that the buffer size is adequate but the class won't overflow
the buffer. In dcheck-enabled builds, a check will go off if
we run out of buffer space.
As part of using SimpleStringBuilder for a small part of
rtc::LogMessage, a few more changes were made:
- SimpleStringBuilder is used for formatting errors instead of ostringstream.
- A new 'noop' state has been introduced for log messages that will be dropped.
- Use a static (singleton) noop ostream object for noop logging messages
instead of building up an actual ostringstream object that will be dropped.
- Add a LogMessageForTest class for better state inspection/testing.
- Fix benign bug in LogTest.Perf, change the test to not use File IO and
always enable it.
- Ensure that minimal work is done for noop messages.
- Remove dependency on rtc::Thread.
- Add tests for the extra_ field, correctly parsed paths and noop handling.
Bug: webrtc:8529, webrtc:4364, webrtc:8933
Change-Id: Ifa258c135135945e4560d9e24315f7d96f784acb
Reviewed-on: https://webrtc-review.googlesource.com/55520
Commit-Queue: Tommi <tommi@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Reviewed-by: Jonas Olsson <jonasolsson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22203}
2018-02-27 13:51:08 +01:00
|
|
|
log_stream << uma_prefix << ".MediaBitrateReceivedInKbps" << uma_suffix
|
|
|
|
|
<< " " << media_bitrate_kbps << '\n';
|
2017-08-30 03:32:14 -07:00
|
|
|
}
|
2016-09-23 02:09:46 -07:00
|
|
|
|
2021-10-03 11:26:11 +02:00
|
|
|
int num_total_frames2 =
|
2017-08-30 03:32:14 -07:00
|
|
|
stats.frame_counts.key_frames + stats.frame_counts.delta_frames;
|
2021-10-03 11:26:11 +02:00
|
|
|
if (num_total_frames2 >= kMinRequiredSamples) {
|
2017-08-30 03:32:14 -07:00
|
|
|
int num_key_frames = stats.frame_counts.key_frames;
|
|
|
|
|
int key_frames_permille =
|
2021-10-03 11:26:11 +02:00
|
|
|
(num_key_frames * 1000 + num_total_frames2 / 2) / num_total_frames2;
|
2017-08-30 03:32:14 -07:00
|
|
|
RTC_HISTOGRAM_COUNTS_SPARSE_1000(
|
|
|
|
|
uma_prefix + ".KeyFramesReceivedInPermille" + uma_suffix,
|
|
|
|
|
key_frames_permille);
|
Adding a new string utility class: SimpleStringBuilder.
This is a fairly minimalistic string building class that
can be used instead of stringstream, which is discouraged
but tempting to use due to its convenient interface and
familiarity for anyone using our logging macros.
As a starter, I'm changing the string building code in
ReceiveStatisticsProxy and SendStatisticsProxy from using
stringstream and using SimpleStringBuilder instead.
In the case of SimpleStringBuilder, there's a single allocation,
it's done on the stack (fast), and minimal code is required for
each concatenation. The developer is responsible for ensuring
that the buffer size is adequate but the class won't overflow
the buffer. In dcheck-enabled builds, a check will go off if
we run out of buffer space.
As part of using SimpleStringBuilder for a small part of
rtc::LogMessage, a few more changes were made:
- SimpleStringBuilder is used for formatting errors instead of ostringstream.
- A new 'noop' state has been introduced for log messages that will be dropped.
- Use a static (singleton) noop ostream object for noop logging messages
instead of building up an actual ostringstream object that will be dropped.
- Add a LogMessageForTest class for better state inspection/testing.
- Fix benign bug in LogTest.Perf, change the test to not use File IO and
always enable it.
- Ensure that minimal work is done for noop messages.
- Remove dependency on rtc::Thread.
- Add tests for the extra_ field, correctly parsed paths and noop handling.
Bug: webrtc:8529, webrtc:4364, webrtc:8933
Change-Id: Ifa258c135135945e4560d9e24315f7d96f784acb
Reviewed-on: https://webrtc-review.googlesource.com/55520
Commit-Queue: Tommi <tommi@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Reviewed-by: Jonas Olsson <jonasolsson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22203}
2018-02-27 13:51:08 +01:00
|
|
|
log_stream << uma_prefix << ".KeyFramesReceivedInPermille" << uma_suffix
|
|
|
|
|
<< " " << key_frames_permille << '\n';
|
2017-08-30 03:32:14 -07:00
|
|
|
}
|
2017-07-03 01:15:58 -07:00
|
|
|
|
2021-10-03 11:26:11 +02:00
|
|
|
absl::optional<int> qp2 = stats.qp_counter.Avg(kMinRequiredSamples);
|
|
|
|
|
if (qp2) {
|
2017-08-30 03:32:14 -07:00
|
|
|
RTC_HISTOGRAM_COUNTS_SPARSE_200(
|
2021-10-03 11:26:11 +02:00
|
|
|
uma_prefix + ".Decoded.Vp8.Qp" + uma_suffix, *qp2);
|
2018-05-22 10:54:30 +02:00
|
|
|
log_stream << uma_prefix << ".Decoded.Vp8.Qp" << uma_suffix << " "
|
2021-10-03 11:26:11 +02:00
|
|
|
<< *qp2 << '\n';
|
2017-08-30 03:32:14 -07:00
|
|
|
}
|
|
|
|
|
}
|
2017-07-03 01:15:58 -07:00
|
|
|
}
|
|
|
|
|
|
2019-08-13 14:43:02 +02:00
|
|
|
StreamDataCounters rtp_rtx_stats = rtp_stats;
|
|
|
|
|
if (rtx_stats)
|
|
|
|
|
rtp_rtx_stats.Add(*rtx_stats);
|
2016-02-24 01:35:40 -08:00
|
|
|
int64_t elapsed_sec =
|
2019-08-13 14:43:02 +02:00
|
|
|
rtp_rtx_stats.TimeSinceFirstPacketInMs(clock_->TimeInMilliseconds()) /
|
|
|
|
|
1000;
|
2017-05-11 05:37:35 -07:00
|
|
|
if (elapsed_sec >= metrics::kMinRunTimeInSeconds) {
|
2016-09-09 22:40:25 -07:00
|
|
|
RTC_HISTOGRAM_COUNTS_10000(
|
2016-02-24 01:35:40 -08:00
|
|
|
"WebRTC.Video.BitrateReceivedInKbps",
|
2019-08-13 14:43:02 +02:00
|
|
|
static_cast<int>(rtp_rtx_stats.transmitted.TotalBytes() * 8 /
|
|
|
|
|
elapsed_sec / 1000));
|
|
|
|
|
int media_bitrate_kbs = static_cast<int>(rtp_stats.MediaPayloadBytes() * 8 /
|
|
|
|
|
elapsed_sec / 1000);
|
2017-08-30 03:32:14 -07:00
|
|
|
RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.MediaBitrateReceivedInKbps",
|
|
|
|
|
media_bitrate_kbs);
|
Adding a new string utility class: SimpleStringBuilder.
This is a fairly minimalistic string building class that
can be used instead of stringstream, which is discouraged
but tempting to use due to its convenient interface and
familiarity for anyone using our logging macros.
As a starter, I'm changing the string building code in
ReceiveStatisticsProxy and SendStatisticsProxy from using
stringstream and using SimpleStringBuilder instead.
In the case of SimpleStringBuilder, there's a single allocation,
it's done on the stack (fast), and minimal code is required for
each concatenation. The developer is responsible for ensuring
that the buffer size is adequate but the class won't overflow
the buffer. In dcheck-enabled builds, a check will go off if
we run out of buffer space.
As part of using SimpleStringBuilder for a small part of
rtc::LogMessage, a few more changes were made:
- SimpleStringBuilder is used for formatting errors instead of ostringstream.
- A new 'noop' state has been introduced for log messages that will be dropped.
- Use a static (singleton) noop ostream object for noop logging messages
instead of building up an actual ostringstream object that will be dropped.
- Add a LogMessageForTest class for better state inspection/testing.
- Fix benign bug in LogTest.Perf, change the test to not use File IO and
always enable it.
- Ensure that minimal work is done for noop messages.
- Remove dependency on rtc::Thread.
- Add tests for the extra_ field, correctly parsed paths and noop handling.
Bug: webrtc:8529, webrtc:4364, webrtc:8933
Change-Id: Ifa258c135135945e4560d9e24315f7d96f784acb
Reviewed-on: https://webrtc-review.googlesource.com/55520
Commit-Queue: Tommi <tommi@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Reviewed-by: Jonas Olsson <jonasolsson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22203}
2018-02-27 13:51:08 +01:00
|
|
|
log_stream << "WebRTC.Video.MediaBitrateReceivedInKbps "
|
|
|
|
|
<< media_bitrate_kbs << '\n';
|
2016-09-09 22:40:25 -07:00
|
|
|
RTC_HISTOGRAM_COUNTS_10000(
|
2016-02-24 01:35:40 -08:00
|
|
|
"WebRTC.Video.PaddingBitrateReceivedInKbps",
|
2019-08-13 14:43:02 +02:00
|
|
|
static_cast<int>(rtp_rtx_stats.transmitted.padding_bytes * 8 /
|
|
|
|
|
elapsed_sec / 1000));
|
2016-09-09 22:40:25 -07:00
|
|
|
RTC_HISTOGRAM_COUNTS_10000(
|
2016-02-24 01:35:40 -08:00
|
|
|
"WebRTC.Video.RetransmittedBitrateReceivedInKbps",
|
2019-08-13 14:43:02 +02:00
|
|
|
static_cast<int>(rtp_rtx_stats.retransmitted.TotalBytes() * 8 /
|
|
|
|
|
elapsed_sec / 1000));
|
|
|
|
|
if (rtx_stats) {
|
|
|
|
|
RTC_HISTOGRAM_COUNTS_10000(
|
|
|
|
|
"WebRTC.Video.RtxBitrateReceivedInKbps",
|
|
|
|
|
static_cast<int>(rtx_stats->transmitted.TotalBytes() * 8 /
|
|
|
|
|
elapsed_sec / 1000));
|
2016-02-24 01:35:40 -08:00
|
|
|
}
|
2016-02-24 07:55:00 -08:00
|
|
|
const RtcpPacketTypeCounter& counters = stats_.rtcp_packet_type_counts;
|
2016-09-09 22:40:25 -07:00
|
|
|
RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.NackPacketsSentPerMinute",
|
|
|
|
|
counters.nack_packets * 60 / elapsed_sec);
|
|
|
|
|
RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.FirPacketsSentPerMinute",
|
|
|
|
|
counters.fir_packets * 60 / elapsed_sec);
|
|
|
|
|
RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.PliPacketsSentPerMinute",
|
|
|
|
|
counters.pli_packets * 60 / elapsed_sec);
|
2016-02-24 07:55:00 -08:00
|
|
|
if (counters.nack_requests > 0) {
|
2016-09-09 22:40:25 -07:00
|
|
|
RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.UniqueNackRequestsSentInPercent",
|
|
|
|
|
counters.UniqueNackRequestsInPercent());
|
2016-02-24 07:55:00 -08:00
|
|
|
}
|
2016-02-24 01:35:40 -08:00
|
|
|
}
|
2017-01-13 05:58:34 -08:00
|
|
|
|
|
|
|
|
if (num_certain_states_ >= kBadCallMinRequiredSamples) {
|
|
|
|
|
RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.BadCall.Any",
|
|
|
|
|
100 * num_bad_states_ / num_certain_states_);
|
|
|
|
|
}
|
2018-06-15 12:28:07 +02:00
|
|
|
absl::optional<double> fps_fraction =
|
2017-01-13 05:58:34 -08:00
|
|
|
fps_threshold_.FractionHigh(kBadCallMinRequiredSamples);
|
|
|
|
|
if (fps_fraction) {
|
|
|
|
|
RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.BadCall.FrameRate",
|
|
|
|
|
static_cast<int>(100 * (1 - *fps_fraction)));
|
|
|
|
|
}
|
2018-06-15 12:28:07 +02:00
|
|
|
absl::optional<double> variance_fraction =
|
2017-01-13 05:58:34 -08:00
|
|
|
variance_threshold_.FractionHigh(kBadCallMinRequiredSamples);
|
|
|
|
|
if (variance_fraction) {
|
|
|
|
|
RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.BadCall.FrameRateVariance",
|
|
|
|
|
static_cast<int>(100 * *variance_fraction));
|
|
|
|
|
}
|
2018-06-15 12:28:07 +02:00
|
|
|
absl::optional<double> qp_fraction =
|
2017-01-13 05:58:34 -08:00
|
|
|
qp_threshold_.FractionHigh(kBadCallMinRequiredSamples);
|
|
|
|
|
if (qp_fraction) {
|
|
|
|
|
RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.BadCall.Qp",
|
|
|
|
|
static_cast<int>(100 * *qp_fraction));
|
|
|
|
|
}
|
Adding a new string utility class: SimpleStringBuilder.
This is a fairly minimalistic string building class that
can be used instead of stringstream, which is discouraged
but tempting to use due to its convenient interface and
familiarity for anyone using our logging macros.
As a starter, I'm changing the string building code in
ReceiveStatisticsProxy and SendStatisticsProxy from using
stringstream and using SimpleStringBuilder instead.
In the case of SimpleStringBuilder, there's a single allocation,
it's done on the stack (fast), and minimal code is required for
each concatenation. The developer is responsible for ensuring
that the buffer size is adequate but the class won't overflow
the buffer. In dcheck-enabled builds, a check will go off if
we run out of buffer space.
As part of using SimpleStringBuilder for a small part of
rtc::LogMessage, a few more changes were made:
- SimpleStringBuilder is used for formatting errors instead of ostringstream.
- A new 'noop' state has been introduced for log messages that will be dropped.
- Use a static (singleton) noop ostream object for noop logging messages
instead of building up an actual ostringstream object that will be dropped.
- Add a LogMessageForTest class for better state inspection/testing.
- Fix benign bug in LogTest.Perf, change the test to not use File IO and
always enable it.
- Ensure that minimal work is done for noop messages.
- Remove dependency on rtc::Thread.
- Add tests for the extra_ field, correctly parsed paths and noop handling.
Bug: webrtc:8529, webrtc:4364, webrtc:8933
Change-Id: Ifa258c135135945e4560d9e24315f7d96f784acb
Reviewed-on: https://webrtc-review.googlesource.com/55520
Commit-Queue: Tommi <tommi@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Reviewed-by: Jonas Olsson <jonasolsson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22203}
2018-02-27 13:51:08 +01:00
|
|
|
|
|
|
|
|
RTC_LOG(LS_INFO) << log_stream.str();
|
2019-08-02 13:52:37 +02:00
|
|
|
video_quality_observer_->UpdateHistograms();
|
2015-04-27 10:09:49 +02:00
|
|
|
}
|
2014-02-07 12:06:29 +00:00
|
|
|
|
2016-12-13 02:45:57 -08:00
|
|
|
void ReceiveStatisticsProxy::QualitySample() {
|
|
|
|
|
int64_t now = clock_->TimeInMilliseconds();
|
|
|
|
|
if (last_sample_time_ + kMinSampleLengthMs > now)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
double fps =
|
|
|
|
|
render_fps_tracker_.ComputeRateForInterval(now - last_sample_time_);
|
2018-06-15 12:28:07 +02:00
|
|
|
absl::optional<int> qp = qp_sample_.Avg(1);
|
2016-12-13 02:45:57 -08:00
|
|
|
|
|
|
|
|
bool prev_fps_bad = !fps_threshold_.IsHigh().value_or(true);
|
|
|
|
|
bool prev_qp_bad = qp_threshold_.IsHigh().value_or(false);
|
|
|
|
|
bool prev_variance_bad = variance_threshold_.IsHigh().value_or(false);
|
|
|
|
|
bool prev_any_bad = prev_fps_bad || prev_qp_bad || prev_variance_bad;
|
|
|
|
|
|
|
|
|
|
fps_threshold_.AddMeasurement(static_cast<int>(fps));
|
2018-05-22 10:54:30 +02:00
|
|
|
if (qp)
|
|
|
|
|
qp_threshold_.AddMeasurement(*qp);
|
2018-06-15 12:28:07 +02:00
|
|
|
absl::optional<double> fps_variance_opt = fps_threshold_.CalculateVariance();
|
2016-12-13 02:45:57 -08:00
|
|
|
double fps_variance = fps_variance_opt.value_or(0);
|
|
|
|
|
if (fps_variance_opt) {
|
|
|
|
|
variance_threshold_.AddMeasurement(static_cast<int>(fps_variance));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool fps_bad = !fps_threshold_.IsHigh().value_or(true);
|
|
|
|
|
bool qp_bad = qp_threshold_.IsHigh().value_or(false);
|
|
|
|
|
bool variance_bad = variance_threshold_.IsHigh().value_or(false);
|
|
|
|
|
bool any_bad = fps_bad || qp_bad || variance_bad;
|
|
|
|
|
|
|
|
|
|
if (!prev_any_bad && any_bad) {
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_INFO) << "Bad call (any) start: " << now;
|
2016-12-13 02:45:57 -08:00
|
|
|
} else if (prev_any_bad && !any_bad) {
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_INFO) << "Bad call (any) end: " << now;
|
2016-12-13 02:45:57 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!prev_fps_bad && fps_bad) {
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_INFO) << "Bad call (fps) start: " << now;
|
2016-12-13 02:45:57 -08:00
|
|
|
} else if (prev_fps_bad && !fps_bad) {
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_INFO) << "Bad call (fps) end: " << now;
|
2016-12-13 02:45:57 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!prev_qp_bad && qp_bad) {
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_INFO) << "Bad call (qp) start: " << now;
|
2016-12-13 02:45:57 -08:00
|
|
|
} else if (prev_qp_bad && !qp_bad) {
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_INFO) << "Bad call (qp) end: " << now;
|
2016-12-13 02:45:57 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!prev_variance_bad && variance_bad) {
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_INFO) << "Bad call (variance) start: " << now;
|
2016-12-13 02:45:57 -08:00
|
|
|
} else if (prev_variance_bad && !variance_bad) {
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_INFO) << "Bad call (variance) end: " << now;
|
2016-12-13 02:45:57 -08:00
|
|
|
}
|
|
|
|
|
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_VERBOSE) << "SAMPLE: sample_length: " << (now - last_sample_time_)
|
|
|
|
|
<< " fps: " << fps << " fps_bad: " << fps_bad
|
2018-05-22 10:54:30 +02:00
|
|
|
<< " qp: " << qp.value_or(-1) << " qp_bad: " << qp_bad
|
2017-11-09 11:09:25 +01:00
|
|
|
<< " variance_bad: " << variance_bad
|
|
|
|
|
<< " fps_variance: " << fps_variance;
|
2016-12-13 02:45:57 -08:00
|
|
|
|
|
|
|
|
last_sample_time_ = now;
|
|
|
|
|
qp_sample_.Reset();
|
2017-01-13 05:58:34 -08:00
|
|
|
|
|
|
|
|
if (fps_threshold_.IsHigh() || variance_threshold_.IsHigh() ||
|
|
|
|
|
qp_threshold_.IsHigh()) {
|
|
|
|
|
if (any_bad)
|
|
|
|
|
++num_bad_states_;
|
|
|
|
|
++num_certain_states_;
|
|
|
|
|
}
|
2016-12-13 02:45:57 -08:00
|
|
|
}
|
|
|
|
|
|
2017-03-28 02:44:58 -07:00
|
|
|
void ReceiveStatisticsProxy::UpdateFramerate(int64_t now_ms) const {
|
2017-02-22 05:30:39 -08:00
|
|
|
int64_t old_frames_ms = now_ms - kRateStatisticsWindowSizeMs;
|
|
|
|
|
while (!frame_window_.empty() &&
|
|
|
|
|
frame_window_.begin()->first < old_frames_ms) {
|
|
|
|
|
frame_window_.erase(frame_window_.begin());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t framerate =
|
|
|
|
|
(frame_window_.size() * 1000 + 500) / kRateStatisticsWindowSizeMs;
|
|
|
|
|
stats_.network_frame_rate = static_cast<int>(framerate);
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-22 13:22:26 +02:00
|
|
|
void ReceiveStatisticsProxy::UpdateDecodeTimeHistograms(
|
|
|
|
|
int width,
|
|
|
|
|
int height,
|
|
|
|
|
int decode_time_ms) const {
|
|
|
|
|
bool is_4k = (width == 3840 || width == 4096) && height == 2160;
|
|
|
|
|
bool is_hd = width == 1920 && height == 1080;
|
|
|
|
|
// Only update histograms for 4k/HD and VP9/H264.
|
|
|
|
|
if ((is_4k || is_hd) && (last_codec_type_ == kVideoCodecVP9 ||
|
|
|
|
|
last_codec_type_ == kVideoCodecH264)) {
|
|
|
|
|
const std::string kDecodeTimeUmaPrefix =
|
|
|
|
|
"WebRTC.Video.DecodeTimePerFrameInMs.";
|
|
|
|
|
|
|
|
|
|
// Each histogram needs its own line for it to not be reused in the wrong
|
|
|
|
|
// way when the format changes.
|
|
|
|
|
if (last_codec_type_ == kVideoCodecVP9) {
|
|
|
|
|
bool is_sw_decoder =
|
|
|
|
|
stats_.decoder_implementation_name.compare(0, 6, "libvpx") == 0;
|
|
|
|
|
if (is_4k) {
|
|
|
|
|
if (is_sw_decoder)
|
|
|
|
|
RTC_HISTOGRAM_COUNTS_1000(kDecodeTimeUmaPrefix + "Vp9.4k.Sw",
|
|
|
|
|
decode_time_ms);
|
|
|
|
|
else
|
|
|
|
|
RTC_HISTOGRAM_COUNTS_1000(kDecodeTimeUmaPrefix + "Vp9.4k.Hw",
|
|
|
|
|
decode_time_ms);
|
|
|
|
|
} else {
|
|
|
|
|
if (is_sw_decoder)
|
|
|
|
|
RTC_HISTOGRAM_COUNTS_1000(kDecodeTimeUmaPrefix + "Vp9.Hd.Sw",
|
|
|
|
|
decode_time_ms);
|
|
|
|
|
else
|
|
|
|
|
RTC_HISTOGRAM_COUNTS_1000(kDecodeTimeUmaPrefix + "Vp9.Hd.Hw",
|
|
|
|
|
decode_time_ms);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
bool is_sw_decoder =
|
|
|
|
|
stats_.decoder_implementation_name.compare(0, 6, "FFmpeg") == 0;
|
|
|
|
|
if (is_4k) {
|
|
|
|
|
if (is_sw_decoder)
|
|
|
|
|
RTC_HISTOGRAM_COUNTS_1000(kDecodeTimeUmaPrefix + "H264.4k.Sw",
|
|
|
|
|
decode_time_ms);
|
|
|
|
|
else
|
|
|
|
|
RTC_HISTOGRAM_COUNTS_1000(kDecodeTimeUmaPrefix + "H264.4k.Hw",
|
|
|
|
|
decode_time_ms);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
if (is_sw_decoder)
|
|
|
|
|
RTC_HISTOGRAM_COUNTS_1000(kDecodeTimeUmaPrefix + "H264.Hd.Sw",
|
|
|
|
|
decode_time_ms);
|
|
|
|
|
else
|
|
|
|
|
RTC_HISTOGRAM_COUNTS_1000(kDecodeTimeUmaPrefix + "H264.Hd.Hw",
|
|
|
|
|
decode_time_ms);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-22 15:23:44 +02:00
|
|
|
absl::optional<int64_t>
|
|
|
|
|
ReceiveStatisticsProxy::GetCurrentEstimatedPlayoutNtpTimestampMs(
|
|
|
|
|
int64_t now_ms) const {
|
|
|
|
|
if (!last_estimated_playout_ntp_timestamp_ms_ ||
|
|
|
|
|
!last_estimated_playout_time_ms_) {
|
|
|
|
|
return absl::nullopt;
|
|
|
|
|
}
|
|
|
|
|
int64_t elapsed_ms = now_ms - *last_estimated_playout_time_ms_;
|
|
|
|
|
return *last_estimated_playout_ntp_timestamp_ms_ + elapsed_ms;
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-07 12:06:29 +00:00
|
|
|
VideoReceiveStream::Stats ReceiveStatisticsProxy::GetStats() const {
|
2020-07-08 13:13:32 +02:00
|
|
|
MutexLock lock(&mutex_);
|
2017-05-04 02:47:13 -07:00
|
|
|
// Get current frame rates here, as only updating them on new frames prevents
|
|
|
|
|
// us from ever correctly displaying frame rate of 0.
|
|
|
|
|
int64_t now_ms = clock_->TimeInMilliseconds();
|
|
|
|
|
UpdateFramerate(now_ms);
|
|
|
|
|
stats_.render_frame_rate = renders_fps_estimator_.Rate(now_ms).value_or(0);
|
|
|
|
|
stats_.decode_frame_rate = decode_fps_estimator_.Rate(now_ms).value_or(0);
|
2017-08-23 05:24:10 -07:00
|
|
|
stats_.interframe_delay_max_ms =
|
|
|
|
|
interframe_delay_max_moving_.Max(now_ms).value_or(-1);
|
2019-01-31 16:45:42 +01:00
|
|
|
stats_.freeze_count = video_quality_observer_->NumFreezes();
|
|
|
|
|
stats_.pause_count = video_quality_observer_->NumPauses();
|
|
|
|
|
stats_.total_freezes_duration_ms =
|
|
|
|
|
video_quality_observer_->TotalFreezesDurationMs();
|
|
|
|
|
stats_.total_pauses_duration_ms =
|
|
|
|
|
video_quality_observer_->TotalPausesDurationMs();
|
|
|
|
|
stats_.total_frames_duration_ms =
|
|
|
|
|
video_quality_observer_->TotalFramesDurationMs();
|
|
|
|
|
stats_.sum_squared_frame_durations =
|
|
|
|
|
video_quality_observer_->SumSquaredFrameDurationsSec();
|
2017-09-04 07:57:17 -07:00
|
|
|
stats_.content_type = last_content_type_;
|
2019-01-31 16:45:42 +01:00
|
|
|
stats_.timing_frame_info = timing_frame_info_counter_.Max(now_ms);
|
2019-05-28 17:38:08 +02:00
|
|
|
stats_.jitter_buffer_delay_seconds =
|
|
|
|
|
static_cast<double>(current_delay_counter_.Sum(1).value_or(0)) /
|
|
|
|
|
rtc::kNumMillisecsPerSec;
|
|
|
|
|
stats_.jitter_buffer_emitted_count = current_delay_counter_.NumSamples();
|
2019-10-22 15:23:44 +02:00
|
|
|
stats_.estimated_playout_ntp_timestamp_ms =
|
|
|
|
|
GetCurrentEstimatedPlayoutNtpTimestampMs(now_ms);
|
2014-12-19 15:45:03 +00:00
|
|
|
return stats_;
|
2014-02-07 12:06:29 +00:00
|
|
|
}
|
|
|
|
|
|
2015-08-28 07:35:32 -07:00
|
|
|
void ReceiveStatisticsProxy::OnIncomingPayloadType(int payload_type) {
|
2020-07-08 13:13:32 +02:00
|
|
|
MutexLock lock(&mutex_);
|
2015-08-28 07:35:32 -07:00
|
|
|
stats_.current_payload_type = payload_type;
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-18 16:01:11 +01:00
|
|
|
void ReceiveStatisticsProxy::OnDecoderImplementationName(
|
|
|
|
|
const char* implementation_name) {
|
2020-07-08 13:13:32 +02:00
|
|
|
MutexLock lock(&mutex_);
|
2015-12-18 16:01:11 +01:00
|
|
|
stats_.decoder_implementation_name = implementation_name;
|
|
|
|
|
}
|
2014-02-07 12:06:29 +00:00
|
|
|
|
2017-02-22 05:30:39 -08:00
|
|
|
void ReceiveStatisticsProxy::OnFrameBufferTimingsUpdated(
|
|
|
|
|
int max_decode_ms,
|
|
|
|
|
int current_delay_ms,
|
|
|
|
|
int target_delay_ms,
|
|
|
|
|
int jitter_buffer_ms,
|
|
|
|
|
int min_playout_delay_ms,
|
|
|
|
|
int render_delay_ms) {
|
2020-07-08 13:13:32 +02:00
|
|
|
MutexLock lock(&mutex_);
|
2015-02-25 10:42:16 +00:00
|
|
|
stats_.max_decode_ms = max_decode_ms;
|
|
|
|
|
stats_.current_delay_ms = current_delay_ms;
|
|
|
|
|
stats_.target_delay_ms = target_delay_ms;
|
|
|
|
|
stats_.jitter_buffer_ms = jitter_buffer_ms;
|
|
|
|
|
stats_.min_playout_delay_ms = min_playout_delay_ms;
|
|
|
|
|
stats_.render_delay_ms = render_delay_ms;
|
2016-04-27 23:42:35 -07:00
|
|
|
jitter_buffer_delay_counter_.Add(jitter_buffer_ms);
|
|
|
|
|
target_delay_counter_.Add(target_delay_ms);
|
|
|
|
|
current_delay_counter_.Add(current_delay_ms);
|
2016-04-18 00:41:05 -07:00
|
|
|
// Network delay (rtt/2) + target_delay_ms (jitter delay + decode time +
|
|
|
|
|
// render delay).
|
2017-02-22 05:30:39 -08:00
|
|
|
delay_counter_.Add(target_delay_ms + avg_rtt_ms_ / 2);
|
2014-12-18 13:12:52 +00:00
|
|
|
}
|
|
|
|
|
|
2018-02-21 15:57:09 +01:00
|
|
|
void ReceiveStatisticsProxy::OnUniqueFramesCounted(int num_unique_frames) {
|
2020-07-08 13:13:32 +02:00
|
|
|
MutexLock lock(&mutex_);
|
2018-02-21 15:57:09 +01:00
|
|
|
num_unique_frames_.emplace(num_unique_frames);
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-06 03:06:50 -07:00
|
|
|
void ReceiveStatisticsProxy::OnTimingFrameInfoUpdated(
|
|
|
|
|
const TimingFrameInfo& info) {
|
2020-07-08 13:13:32 +02:00
|
|
|
MutexLock lock(&mutex_);
|
2018-12-07 03:45:19 -08:00
|
|
|
if (info.flags != VideoSendTiming::kInvalid) {
|
|
|
|
|
int64_t now_ms = clock_->TimeInMilliseconds();
|
|
|
|
|
timing_frame_info_counter_.Add(info, now_ms);
|
|
|
|
|
}
|
2018-12-10 09:55:17 -08:00
|
|
|
|
|
|
|
|
// Measure initial decoding latency between the first frame arriving and the
|
|
|
|
|
// first frame being decoded.
|
|
|
|
|
if (!first_frame_received_time_ms_.has_value()) {
|
|
|
|
|
first_frame_received_time_ms_ = info.receive_finish_ms;
|
|
|
|
|
}
|
|
|
|
|
if (stats_.first_frame_received_to_decoded_ms == -1 &&
|
|
|
|
|
first_decoded_frame_time_ms_) {
|
|
|
|
|
stats_.first_frame_received_to_decoded_ms =
|
|
|
|
|
*first_decoded_frame_time_ms_ - *first_frame_received_time_ms_;
|
|
|
|
|
}
|
2017-07-06 03:06:50 -07:00
|
|
|
}
|
|
|
|
|
|
2015-02-19 12:47:00 +00:00
|
|
|
void ReceiveStatisticsProxy::RtcpPacketTypesCounterUpdated(
|
|
|
|
|
uint32_t ssrc,
|
|
|
|
|
const RtcpPacketTypeCounter& packet_counter) {
|
2020-07-08 13:13:32 +02:00
|
|
|
MutexLock lock(&mutex_);
|
2015-02-19 12:47:00 +00:00
|
|
|
if (stats_.ssrc != ssrc)
|
|
|
|
|
return;
|
|
|
|
|
stats_.rtcp_packet_type_counts = packet_counter;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-05 12:45:19 +02:00
|
|
|
void ReceiveStatisticsProxy::OnCname(uint32_t ssrc, absl::string_view cname) {
|
2020-07-08 13:13:32 +02:00
|
|
|
MutexLock lock(&mutex_);
|
2015-09-17 00:24:34 -07:00
|
|
|
// TODO(pbos): Handle both local and remote ssrcs here and RTC_DCHECK that we
|
2015-02-19 12:47:00 +00:00
|
|
|
// receive stats from one of them.
|
|
|
|
|
if (stats_.ssrc != ssrc)
|
|
|
|
|
return;
|
2019-08-05 12:45:19 +02:00
|
|
|
stats_.c_name = std::string(cname);
|
2014-12-18 13:50:16 +00:00
|
|
|
}
|
|
|
|
|
|
2019-01-09 14:37:40 +01:00
|
|
|
void ReceiveStatisticsProxy::OnDecodedFrame(const VideoFrame& frame,
|
|
|
|
|
absl::optional<uint8_t> qp,
|
2019-07-01 10:07:50 +02:00
|
|
|
int32_t decode_time_ms,
|
2018-05-23 11:53:19 +02:00
|
|
|
VideoContentType content_type) {
|
2020-07-08 13:13:32 +02:00
|
|
|
MutexLock lock(&mutex_);
|
2017-08-30 03:32:14 -07:00
|
|
|
|
2020-04-07 18:02:39 +00:00
|
|
|
uint64_t now_ms = clock_->TimeInMilliseconds();
|
2017-10-10 11:18:49 +02:00
|
|
|
|
2018-05-23 11:53:19 +02:00
|
|
|
if (videocontenttypehelpers::IsScreenshare(content_type) !=
|
|
|
|
|
videocontenttypehelpers::IsScreenshare(last_content_type_)) {
|
2019-08-02 13:52:37 +02:00
|
|
|
// Reset the quality observer if content type is switched. But first report
|
|
|
|
|
// stats for the previous part of the call.
|
|
|
|
|
video_quality_observer_->UpdateHistograms();
|
2018-05-23 11:53:19 +02:00
|
|
|
video_quality_observer_.reset(new VideoQualityObserver(content_type));
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-09 14:37:40 +01:00
|
|
|
video_quality_observer_->OnDecodedFrame(frame, qp, last_codec_type_);
|
2018-05-23 11:53:19 +02:00
|
|
|
|
2017-08-30 03:32:14 -07:00
|
|
|
ContentSpecificStats* content_specific_stats =
|
|
|
|
|
&content_specific_stats_[content_type];
|
2016-10-26 07:09:24 -07:00
|
|
|
++stats_.frames_decoded;
|
Reland of Add QP sum stats for received streams. (patchset #2 id:300001 of https://codereview.webrtc.org/2680893002/ )
Reason for revert:
Fix the problem.
Original issue's description:
> Revert of Add QP sum stats for received streams. (patchset #10 id:180001 of https://codereview.webrtc.org/2649133005/ )
>
> Reason for revert:
> Breaks downstream build.
>
> Original issue's description:
> > Add QP sum stats for received streams.
> >
> > This is not implemented yet in any of the decoders.
> >
> > BUG=webrtc:6541
> >
> > Review-Url: https://codereview.webrtc.org/2649133005
> > Cr-Commit-Position: refs/heads/master@{#16475}
> > Committed: https://chromium.googlesource.com/external/webrtc/+/ff0e72fd165facac27f0313aa178648782e63bc4
>
> TBR=hta@webrtc.org,hbos@webrtc.org,sprang@webrtc.org,magjed@webrtc.org,stefan@webrtc.org,sakal@webrtc.org
> # Skipping CQ checks because original CL landed less than 1 days ago.
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
> BUG=webrtc:6541
>
> Review-Url: https://codereview.webrtc.org/2680893002 .
> Cr-Commit-Position: refs/heads/master@{#16480}
> Committed: https://chromium.googlesource.com/external/webrtc/+/69fb2cca4d54f3df7ceddcd1c3e9b0ad80fa849b
TBR=hta@webrtc.org,hbos@webrtc.org,sprang@webrtc.org,magjed@webrtc.org,stefan@webrtc.org,skvlad@webrtc.org
BUG=webrtc:6541
Review-Url: https://codereview.webrtc.org/2681663005
Cr-Commit-Position: refs/heads/master@{#16511}
2017-02-09 04:53:45 -08:00
|
|
|
if (qp) {
|
|
|
|
|
if (!stats_.qp_sum) {
|
|
|
|
|
if (stats_.frames_decoded != 1) {
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_WARNING)
|
Reland of Add QP sum stats for received streams. (patchset #2 id:300001 of https://codereview.webrtc.org/2680893002/ )
Reason for revert:
Fix the problem.
Original issue's description:
> Revert of Add QP sum stats for received streams. (patchset #10 id:180001 of https://codereview.webrtc.org/2649133005/ )
>
> Reason for revert:
> Breaks downstream build.
>
> Original issue's description:
> > Add QP sum stats for received streams.
> >
> > This is not implemented yet in any of the decoders.
> >
> > BUG=webrtc:6541
> >
> > Review-Url: https://codereview.webrtc.org/2649133005
> > Cr-Commit-Position: refs/heads/master@{#16475}
> > Committed: https://chromium.googlesource.com/external/webrtc/+/ff0e72fd165facac27f0313aa178648782e63bc4
>
> TBR=hta@webrtc.org,hbos@webrtc.org,sprang@webrtc.org,magjed@webrtc.org,stefan@webrtc.org,sakal@webrtc.org
> # Skipping CQ checks because original CL landed less than 1 days ago.
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
> BUG=webrtc:6541
>
> Review-Url: https://codereview.webrtc.org/2680893002 .
> Cr-Commit-Position: refs/heads/master@{#16480}
> Committed: https://chromium.googlesource.com/external/webrtc/+/69fb2cca4d54f3df7ceddcd1c3e9b0ad80fa849b
TBR=hta@webrtc.org,hbos@webrtc.org,sprang@webrtc.org,magjed@webrtc.org,stefan@webrtc.org,skvlad@webrtc.org
BUG=webrtc:6541
Review-Url: https://codereview.webrtc.org/2681663005
Cr-Commit-Position: refs/heads/master@{#16511}
2017-02-09 04:53:45 -08:00
|
|
|
<< "Frames decoded was not 1 when first qp value was received.";
|
|
|
|
|
}
|
2018-01-08 16:45:42 +01:00
|
|
|
stats_.qp_sum = 0;
|
Reland of Add QP sum stats for received streams. (patchset #2 id:300001 of https://codereview.webrtc.org/2680893002/ )
Reason for revert:
Fix the problem.
Original issue's description:
> Revert of Add QP sum stats for received streams. (patchset #10 id:180001 of https://codereview.webrtc.org/2649133005/ )
>
> Reason for revert:
> Breaks downstream build.
>
> Original issue's description:
> > Add QP sum stats for received streams.
> >
> > This is not implemented yet in any of the decoders.
> >
> > BUG=webrtc:6541
> >
> > Review-Url: https://codereview.webrtc.org/2649133005
> > Cr-Commit-Position: refs/heads/master@{#16475}
> > Committed: https://chromium.googlesource.com/external/webrtc/+/ff0e72fd165facac27f0313aa178648782e63bc4
>
> TBR=hta@webrtc.org,hbos@webrtc.org,sprang@webrtc.org,magjed@webrtc.org,stefan@webrtc.org,sakal@webrtc.org
> # Skipping CQ checks because original CL landed less than 1 days ago.
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
> BUG=webrtc:6541
>
> Review-Url: https://codereview.webrtc.org/2680893002 .
> Cr-Commit-Position: refs/heads/master@{#16480}
> Committed: https://chromium.googlesource.com/external/webrtc/+/69fb2cca4d54f3df7ceddcd1c3e9b0ad80fa849b
TBR=hta@webrtc.org,hbos@webrtc.org,sprang@webrtc.org,magjed@webrtc.org,stefan@webrtc.org,skvlad@webrtc.org
BUG=webrtc:6541
Review-Url: https://codereview.webrtc.org/2681663005
Cr-Commit-Position: refs/heads/master@{#16511}
2017-02-09 04:53:45 -08:00
|
|
|
}
|
|
|
|
|
*stats_.qp_sum += *qp;
|
2017-08-30 03:32:14 -07:00
|
|
|
content_specific_stats->qp_counter.Add(*qp);
|
Reland of Add QP sum stats for received streams. (patchset #2 id:300001 of https://codereview.webrtc.org/2680893002/ )
Reason for revert:
Fix the problem.
Original issue's description:
> Revert of Add QP sum stats for received streams. (patchset #10 id:180001 of https://codereview.webrtc.org/2649133005/ )
>
> Reason for revert:
> Breaks downstream build.
>
> Original issue's description:
> > Add QP sum stats for received streams.
> >
> > This is not implemented yet in any of the decoders.
> >
> > BUG=webrtc:6541
> >
> > Review-Url: https://codereview.webrtc.org/2649133005
> > Cr-Commit-Position: refs/heads/master@{#16475}
> > Committed: https://chromium.googlesource.com/external/webrtc/+/ff0e72fd165facac27f0313aa178648782e63bc4
>
> TBR=hta@webrtc.org,hbos@webrtc.org,sprang@webrtc.org,magjed@webrtc.org,stefan@webrtc.org,sakal@webrtc.org
> # Skipping CQ checks because original CL landed less than 1 days ago.
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
> BUG=webrtc:6541
>
> Review-Url: https://codereview.webrtc.org/2680893002 .
> Cr-Commit-Position: refs/heads/master@{#16480}
> Committed: https://chromium.googlesource.com/external/webrtc/+/69fb2cca4d54f3df7ceddcd1c3e9b0ad80fa849b
TBR=hta@webrtc.org,hbos@webrtc.org,sprang@webrtc.org,magjed@webrtc.org,stefan@webrtc.org,skvlad@webrtc.org
BUG=webrtc:6541
Review-Url: https://codereview.webrtc.org/2681663005
Cr-Commit-Position: refs/heads/master@{#16511}
2017-02-09 04:53:45 -08:00
|
|
|
} else if (stats_.qp_sum) {
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_WARNING)
|
Reland of Add QP sum stats for received streams. (patchset #2 id:300001 of https://codereview.webrtc.org/2680893002/ )
Reason for revert:
Fix the problem.
Original issue's description:
> Revert of Add QP sum stats for received streams. (patchset #10 id:180001 of https://codereview.webrtc.org/2649133005/ )
>
> Reason for revert:
> Breaks downstream build.
>
> Original issue's description:
> > Add QP sum stats for received streams.
> >
> > This is not implemented yet in any of the decoders.
> >
> > BUG=webrtc:6541
> >
> > Review-Url: https://codereview.webrtc.org/2649133005
> > Cr-Commit-Position: refs/heads/master@{#16475}
> > Committed: https://chromium.googlesource.com/external/webrtc/+/ff0e72fd165facac27f0313aa178648782e63bc4
>
> TBR=hta@webrtc.org,hbos@webrtc.org,sprang@webrtc.org,magjed@webrtc.org,stefan@webrtc.org,sakal@webrtc.org
> # Skipping CQ checks because original CL landed less than 1 days ago.
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
> BUG=webrtc:6541
>
> Review-Url: https://codereview.webrtc.org/2680893002 .
> Cr-Commit-Position: refs/heads/master@{#16480}
> Committed: https://chromium.googlesource.com/external/webrtc/+/69fb2cca4d54f3df7ceddcd1c3e9b0ad80fa849b
TBR=hta@webrtc.org,hbos@webrtc.org,sprang@webrtc.org,magjed@webrtc.org,stefan@webrtc.org,skvlad@webrtc.org
BUG=webrtc:6541
Review-Url: https://codereview.webrtc.org/2681663005
Cr-Commit-Position: refs/heads/master@{#16511}
2017-02-09 04:53:45 -08:00
|
|
|
<< "QP sum was already set and no QP was given for a frame.";
|
2019-10-03 15:52:36 +02:00
|
|
|
stats_.qp_sum.reset();
|
Reland of Add QP sum stats for received streams. (patchset #2 id:300001 of https://codereview.webrtc.org/2680893002/ )
Reason for revert:
Fix the problem.
Original issue's description:
> Revert of Add QP sum stats for received streams. (patchset #10 id:180001 of https://codereview.webrtc.org/2649133005/ )
>
> Reason for revert:
> Breaks downstream build.
>
> Original issue's description:
> > Add QP sum stats for received streams.
> >
> > This is not implemented yet in any of the decoders.
> >
> > BUG=webrtc:6541
> >
> > Review-Url: https://codereview.webrtc.org/2649133005
> > Cr-Commit-Position: refs/heads/master@{#16475}
> > Committed: https://chromium.googlesource.com/external/webrtc/+/ff0e72fd165facac27f0313aa178648782e63bc4
>
> TBR=hta@webrtc.org,hbos@webrtc.org,sprang@webrtc.org,magjed@webrtc.org,stefan@webrtc.org,sakal@webrtc.org
> # Skipping CQ checks because original CL landed less than 1 days ago.
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
> BUG=webrtc:6541
>
> Review-Url: https://codereview.webrtc.org/2680893002 .
> Cr-Commit-Position: refs/heads/master@{#16480}
> Committed: https://chromium.googlesource.com/external/webrtc/+/69fb2cca4d54f3df7ceddcd1c3e9b0ad80fa849b
TBR=hta@webrtc.org,hbos@webrtc.org,sprang@webrtc.org,magjed@webrtc.org,stefan@webrtc.org,skvlad@webrtc.org
BUG=webrtc:6541
Review-Url: https://codereview.webrtc.org/2681663005
Cr-Commit-Position: refs/heads/master@{#16511}
2017-02-09 04:53:45 -08:00
|
|
|
}
|
2019-07-01 10:07:50 +02:00
|
|
|
decode_time_counter_.Add(decode_time_ms);
|
|
|
|
|
stats_.decode_ms = decode_time_ms;
|
|
|
|
|
stats_.total_decode_time_ms += decode_time_ms;
|
2019-10-22 13:22:26 +02:00
|
|
|
if (enable_decode_time_histograms_) {
|
|
|
|
|
UpdateDecodeTimeHistograms(frame.width(), frame.height(), decode_time_ms);
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-11 10:34:31 -07:00
|
|
|
last_content_type_ = content_type;
|
2019-01-09 14:37:40 +01:00
|
|
|
decode_fps_estimator_.Update(1, now_ms);
|
2017-07-03 01:15:58 -07:00
|
|
|
if (last_decoded_frame_time_ms_) {
|
2019-01-09 14:37:40 +01:00
|
|
|
int64_t interframe_delay_ms = now_ms - *last_decoded_frame_time_ms_;
|
2017-07-03 01:15:58 -07:00
|
|
|
RTC_DCHECK_GE(interframe_delay_ms, 0);
|
2019-11-25 10:25:42 +01:00
|
|
|
double interframe_delay = interframe_delay_ms / 1000.0;
|
|
|
|
|
stats_.total_inter_frame_delay += interframe_delay;
|
|
|
|
|
stats_.total_squared_inter_frame_delay +=
|
|
|
|
|
interframe_delay * interframe_delay;
|
2019-01-09 14:37:40 +01:00
|
|
|
interframe_delay_max_moving_.Add(interframe_delay_ms, now_ms);
|
2017-08-30 03:32:14 -07:00
|
|
|
content_specific_stats->interframe_delay_counter.Add(interframe_delay_ms);
|
2017-10-06 12:29:47 +02:00
|
|
|
content_specific_stats->interframe_delay_percentiles.Add(
|
|
|
|
|
interframe_delay_ms);
|
2017-08-30 03:32:14 -07:00
|
|
|
content_specific_stats->flow_duration_ms += interframe_delay_ms;
|
2017-07-03 01:15:58 -07:00
|
|
|
}
|
2018-12-10 09:55:17 -08:00
|
|
|
if (stats_.frames_decoded == 1) {
|
2019-01-09 14:37:40 +01:00
|
|
|
first_decoded_frame_time_ms_.emplace(now_ms);
|
2018-12-10 09:55:17 -08:00
|
|
|
}
|
2019-01-09 14:37:40 +01:00
|
|
|
last_decoded_frame_time_ms_.emplace(now_ms);
|
2014-02-07 12:06:29 +00:00
|
|
|
}
|
|
|
|
|
|
2016-09-23 02:09:46 -07:00
|
|
|
void ReceiveStatisticsProxy::OnRenderedFrame(const VideoFrame& frame) {
|
|
|
|
|
int width = frame.width();
|
|
|
|
|
int height = frame.height();
|
2015-10-08 00:41:59 -07:00
|
|
|
RTC_DCHECK_GT(width, 0);
|
|
|
|
|
RTC_DCHECK_GT(height, 0);
|
2018-06-05 13:34:33 +02:00
|
|
|
int64_t now_ms = clock_->TimeInMilliseconds();
|
2020-07-08 13:13:32 +02:00
|
|
|
MutexLock lock(&mutex_);
|
2018-10-10 13:15:09 +02:00
|
|
|
|
2019-01-09 14:37:40 +01:00
|
|
|
video_quality_observer_->OnRenderedFrame(frame, now_ms);
|
2018-10-10 13:15:09 +02:00
|
|
|
|
2017-08-30 03:32:14 -07:00
|
|
|
ContentSpecificStats* content_specific_stats =
|
|
|
|
|
&content_specific_stats_[last_content_type_];
|
2018-06-05 13:34:33 +02:00
|
|
|
renders_fps_estimator_.Update(1, now_ms);
|
2017-01-23 07:21:55 -08:00
|
|
|
++stats_.frames_rendered;
|
2016-08-11 08:41:18 -07:00
|
|
|
stats_.width = width;
|
|
|
|
|
stats_.height = height;
|
2015-09-14 10:38:08 -07:00
|
|
|
render_fps_tracker_.AddSamples(1);
|
2015-10-08 00:41:59 -07:00
|
|
|
render_pixel_tracker_.AddSamples(sqrt(width * height));
|
2017-08-30 03:32:14 -07:00
|
|
|
content_specific_stats->received_width.Add(width);
|
|
|
|
|
content_specific_stats->received_height.Add(height);
|
2016-09-23 02:09:46 -07:00
|
|
|
|
2018-06-05 13:34:33 +02:00
|
|
|
// Consider taking stats_.render_delay_ms into account.
|
|
|
|
|
const int64_t time_until_rendering_ms = frame.render_time_ms() - now_ms;
|
|
|
|
|
if (time_until_rendering_ms < 0) {
|
|
|
|
|
sum_missed_render_deadline_ms_ += -time_until_rendering_ms;
|
|
|
|
|
++num_delayed_frames_rendered_;
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-23 02:09:46 -07:00
|
|
|
if (frame.ntp_time_ms() > 0) {
|
|
|
|
|
int64_t delay_ms = clock_->CurrentNtpInMilliseconds() - frame.ntp_time_ms();
|
2017-04-11 10:34:31 -07:00
|
|
|
if (delay_ms >= 0) {
|
2017-08-30 03:32:14 -07:00
|
|
|
content_specific_stats->e2e_delay_counter.Add(delay_ms);
|
2017-04-11 10:34:31 -07:00
|
|
|
}
|
2016-09-23 02:09:46 -07:00
|
|
|
}
|
2019-03-22 13:56:46 +01:00
|
|
|
QualitySample();
|
2014-02-07 12:06:29 +00:00
|
|
|
}
|
|
|
|
|
|
2019-10-22 15:23:44 +02:00
|
|
|
void ReceiveStatisticsProxy::OnSyncOffsetUpdated(int64_t video_playout_ntp_ms,
|
|
|
|
|
int64_t sync_offset_ms,
|
2016-11-02 07:14:03 -07:00
|
|
|
double estimated_freq_khz) {
|
2020-07-08 13:13:32 +02:00
|
|
|
MutexLock lock(&mutex_);
|
2016-03-15 01:00:47 -07:00
|
|
|
sync_offset_counter_.Add(std::abs(sync_offset_ms));
|
|
|
|
|
stats_.sync_offset_ms = sync_offset_ms;
|
2019-10-22 15:23:44 +02:00
|
|
|
last_estimated_playout_ntp_timestamp_ms_ = video_playout_ntp_ms;
|
|
|
|
|
last_estimated_playout_time_ms_ = clock_->TimeInMilliseconds();
|
2016-11-02 07:14:03 -07:00
|
|
|
|
|
|
|
|
const double kMaxFreqKhz = 10000.0;
|
|
|
|
|
int offset_khz = kMaxFreqKhz;
|
|
|
|
|
// Should not be zero or negative. If so, report max.
|
|
|
|
|
if (estimated_freq_khz < kMaxFreqKhz && estimated_freq_khz > 0.0)
|
|
|
|
|
offset_khz = static_cast<int>(std::fabs(estimated_freq_khz - 90.0) + 0.5);
|
|
|
|
|
|
|
|
|
|
freq_offset_counter_.Add(offset_khz);
|
2016-03-15 01:00:47 -07:00
|
|
|
}
|
|
|
|
|
|
2017-02-22 05:30:39 -08:00
|
|
|
void ReceiveStatisticsProxy::OnCompleteFrame(bool is_keyframe,
|
2017-08-30 03:32:14 -07:00
|
|
|
size_t size_bytes,
|
|
|
|
|
VideoContentType content_type) {
|
2020-07-08 13:13:32 +02:00
|
|
|
MutexLock lock(&mutex_);
|
2017-08-30 03:32:14 -07:00
|
|
|
if (is_keyframe) {
|
2017-02-22 05:30:39 -08:00
|
|
|
++stats_.frame_counts.key_frames;
|
2017-08-30 03:32:14 -07:00
|
|
|
} else {
|
2017-02-22 05:30:39 -08:00
|
|
|
++stats_.frame_counts.delta_frames;
|
2017-08-30 03:32:14 -07:00
|
|
|
}
|
|
|
|
|
|
2018-10-17 14:41:52 +02:00
|
|
|
// Content type extension is set only for keyframes and should be propagated
|
|
|
|
|
// for all the following delta frames. Here we may receive frames out of order
|
|
|
|
|
// and miscategorise some delta frames near the layer switch.
|
|
|
|
|
// This may slightly offset calculated bitrate and keyframes permille metrics.
|
|
|
|
|
VideoContentType propagated_content_type =
|
|
|
|
|
is_keyframe ? content_type : last_content_type_;
|
|
|
|
|
|
2017-08-30 03:32:14 -07:00
|
|
|
ContentSpecificStats* content_specific_stats =
|
2018-10-17 14:41:52 +02:00
|
|
|
&content_specific_stats_[propagated_content_type];
|
2017-08-30 03:32:14 -07:00
|
|
|
|
|
|
|
|
content_specific_stats->total_media_bytes += size_bytes;
|
|
|
|
|
if (is_keyframe) {
|
|
|
|
|
++content_specific_stats->frame_counts.key_frames;
|
|
|
|
|
} else {
|
|
|
|
|
++content_specific_stats->frame_counts.delta_frames;
|
|
|
|
|
}
|
2017-02-22 05:30:39 -08:00
|
|
|
|
|
|
|
|
int64_t now_ms = clock_->TimeInMilliseconds();
|
|
|
|
|
frame_window_.insert(std::make_pair(now_ms, size_bytes));
|
2017-03-28 02:44:58 -07:00
|
|
|
UpdateFramerate(now_ms);
|
2017-02-22 05:30:39 -08:00
|
|
|
}
|
|
|
|
|
|
2019-08-26 15:04:43 +02:00
|
|
|
void ReceiveStatisticsProxy::OnDroppedFrames(uint32_t frames_dropped) {
|
2020-07-08 13:13:32 +02:00
|
|
|
MutexLock lock(&mutex_);
|
2019-08-26 15:04:43 +02:00
|
|
|
stats_.frames_dropped += frames_dropped;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-01 15:56:33 +02:00
|
|
|
void ReceiveStatisticsProxy::OnPreDecode(VideoCodecType codec_type, int qp) {
|
2020-04-07 18:02:39 +00:00
|
|
|
RTC_DCHECK_RUN_ON(&decode_thread_);
|
2020-07-08 13:13:32 +02:00
|
|
|
MutexLock lock(&mutex_);
|
2018-10-01 15:56:33 +02:00
|
|
|
last_codec_type_ = codec_type;
|
|
|
|
|
if (last_codec_type_ == kVideoCodecVP8 && qp != -1) {
|
|
|
|
|
qp_counters_.vp8.Add(qp);
|
|
|
|
|
qp_sample_.Add(qp);
|
2015-10-20 23:55:26 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-22 09:23:28 -07:00
|
|
|
void ReceiveStatisticsProxy::OnStreamInactive() {
|
|
|
|
|
// TODO(sprang): Figure out any other state that should be reset.
|
|
|
|
|
|
2020-07-08 13:13:32 +02:00
|
|
|
MutexLock lock(&mutex_);
|
2017-08-22 09:23:28 -07:00
|
|
|
// Don't report inter-frame delay if stream was paused.
|
|
|
|
|
last_decoded_frame_time_ms_.reset();
|
2018-05-23 11:53:19 +02:00
|
|
|
video_quality_observer_->OnStreamInactive();
|
2017-08-22 09:23:28 -07:00
|
|
|
}
|
|
|
|
|
|
2017-02-22 05:30:39 -08:00
|
|
|
void ReceiveStatisticsProxy::OnRttUpdate(int64_t avg_rtt_ms,
|
|
|
|
|
int64_t max_rtt_ms) {
|
2020-07-08 13:13:32 +02:00
|
|
|
MutexLock lock(&mutex_);
|
2017-02-22 05:30:39 -08:00
|
|
|
avg_rtt_ms_ = avg_rtt_ms;
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-24 17:57:33 +01:00
|
|
|
void ReceiveStatisticsProxy::DecoderThreadStarting() {
|
|
|
|
|
RTC_DCHECK_RUN_ON(&main_thread_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ReceiveStatisticsProxy::DecoderThreadStopped() {
|
|
|
|
|
RTC_DCHECK_RUN_ON(&main_thread_);
|
2020-04-07 18:02:39 +00:00
|
|
|
decode_thread_.Detach();
|
2018-02-24 17:57:33 +01:00
|
|
|
}
|
|
|
|
|
|
2017-10-06 12:29:47 +02:00
|
|
|
ReceiveStatisticsProxy::ContentSpecificStats::ContentSpecificStats()
|
|
|
|
|
: interframe_delay_percentiles(kMaxCommonInterframeDelayMs) {}
|
|
|
|
|
|
2018-08-28 16:30:18 +02:00
|
|
|
ReceiveStatisticsProxy::ContentSpecificStats::~ContentSpecificStats() = default;
|
|
|
|
|
|
2017-08-30 03:32:14 -07:00
|
|
|
void ReceiveStatisticsProxy::ContentSpecificStats::Add(
|
|
|
|
|
const ContentSpecificStats& other) {
|
|
|
|
|
e2e_delay_counter.Add(other.e2e_delay_counter);
|
|
|
|
|
interframe_delay_counter.Add(other.interframe_delay_counter);
|
|
|
|
|
flow_duration_ms += other.flow_duration_ms;
|
|
|
|
|
total_media_bytes += other.total_media_bytes;
|
|
|
|
|
received_height.Add(other.received_height);
|
|
|
|
|
received_width.Add(other.received_width);
|
|
|
|
|
qp_counter.Add(other.qp_counter);
|
|
|
|
|
frame_counts.key_frames += other.frame_counts.key_frames;
|
|
|
|
|
frame_counts.delta_frames += other.frame_counts.delta_frames;
|
2017-10-06 12:29:47 +02:00
|
|
|
interframe_delay_percentiles.Add(other.interframe_delay_percentiles);
|
|
|
|
|
}
|
2014-02-07 12:06:29 +00:00
|
|
|
} // namespace webrtc
|