Add histogram stats for average QP per frame for VP9 (for sent video streams):

- "WebRTC.Video.Encoded.Qp.Vp9"
- "WebRTC.Video.Encoded.Qp.Vp9.S0"
- "WebRTC.Video.Encoded.Qp.Vp9.S1"
- "WebRTC.Video.Encoded.Qp.Vp9.S2"

BUG=

Review URL: https://codereview.webrtc.org/1870043002

Cr-Commit-Position: refs/heads/master@{#12402}
This commit is contained in:
asapersson 2016-04-18 02:58:47 -07:00 committed by Commit bot
parent 8056acc6f5
commit 5265fedffe
5 changed files with 118 additions and 27 deletions

View File

@ -694,6 +694,9 @@ int VP9EncoderImpl::GetEncodedLayerFrame(const vpx_codec_cx_pkt* pkt) {
encoded_image_.capture_time_ms_ = input_image_->render_time_ms();
encoded_image_._encodedHeight = raw_->d_h;
encoded_image_._encodedWidth = raw_->d_w;
int qp = -1;
vpx_codec_control(encoder_, VP8E_GET_LAST_QUANTIZER, &qp);
encoded_image_.qp_ = qp;
encoded_complete_callback_->Encoded(encoded_image_, &codec_specific,
&frag_info);
}

View File

@ -69,6 +69,9 @@
#define RTC_HISTOGRAM_COUNTS_200(name, sample) \
RTC_HISTOGRAM_COUNTS(name, sample, 1, 200, 50)
#define RTC_HISTOGRAM_COUNTS_500(name, sample) \
RTC_HISTOGRAM_COUNTS(name, sample, 1, 500, 50)
#define RTC_HISTOGRAM_COUNTS_1000(name, sample) \
RTC_HISTOGRAM_COUNTS(name, sample, 1, 1000, 50)
@ -89,6 +92,9 @@
#define RTC_LOGGED_HISTOGRAM_COUNTS_200(name, sample) \
RTC_LOGGED_HISTOGRAM_COUNTS(name, sample, 1, 200, 50)
#define RTC_LOGGED_HISTOGRAM_COUNTS_500(name, sample) \
RTC_LOGGED_HISTOGRAM_COUNTS(name, sample, 1, 500, 50)
#define RTC_LOGGED_HISTOGRAM_COUNTS_1000(name, sample) \
RTC_LOGGED_HISTOGRAM_COUNTS(name, sample, 1, 1000, 50)
@ -175,6 +181,10 @@
RTC_HISTOGRAMS_COMMON(index, name, sample, \
RTC_HISTOGRAM_COUNTS(name, sample, 1, 200, 50))
#define RTC_HISTOGRAMS_COUNTS_500(index, name, sample) \
RTC_HISTOGRAMS_COMMON(index, name, sample, \
RTC_HISTOGRAM_COUNTS(name, sample, 1, 500, 50))
#define RTC_HISTOGRAMS_COUNTS_1000(index, name, sample) \
RTC_HISTOGRAMS_COMMON(index, name, sample, \
RTC_HISTOGRAM_COUNTS(name, sample, 1, 1000, 50))
@ -204,6 +214,10 @@
RTC_HISTOGRAMS_COMMON(index, name, sample, \
RTC_LOGGED_HISTOGRAM_COUNTS(name, sample, 1, 200, 50))
#define RTC_LOGGED_HISTOGRAMS_COUNTS_500(index, name, sample) \
RTC_HISTOGRAMS_COMMON(index, name, sample, \
RTC_LOGGED_HISTOGRAM_COUNTS(name, sample, 1, 500, 50))
#define RTC_LOGGED_HISTOGRAMS_COUNTS_1000(index, name, sample) \
RTC_HISTOGRAMS_COMMON(index, name, sample, \
RTC_LOGGED_HISTOGRAM_COUNTS(name, sample, 1, 1000, 50))

View File

@ -194,26 +194,46 @@ void SendStatisticsProxy::UmaSamplesContainer::UpdateHistograms(
}
for (const auto& it : qp_counters_) {
int qp = it.second.vp8.Avg(kMinRequiredSamples);
if (qp != -1) {
int qp_vp8 = it.second.vp8.Avg(kMinRequiredSamples);
if (qp_vp8 != -1) {
int spatial_idx = it.first;
if (spatial_idx == -1) {
RTC_LOGGED_HISTOGRAMS_COUNTS_200(kIndex, uma_prefix_ + "Encoded.Qp.Vp8",
qp);
qp_vp8);
} else if (spatial_idx == 0) {
RTC_LOGGED_HISTOGRAMS_COUNTS_200(kIndex,
uma_prefix_ + "Encoded.Qp.Vp8.S0", qp);
RTC_LOGGED_HISTOGRAMS_COUNTS_200(
kIndex, uma_prefix_ + "Encoded.Qp.Vp8.S0", qp_vp8);
} else if (spatial_idx == 1) {
RTC_LOGGED_HISTOGRAMS_COUNTS_200(kIndex,
uma_prefix_ + "Encoded.Qp.Vp8.S1", qp);
RTC_LOGGED_HISTOGRAMS_COUNTS_200(
kIndex, uma_prefix_ + "Encoded.Qp.Vp8.S1", qp_vp8);
} else if (spatial_idx == 2) {
RTC_LOGGED_HISTOGRAMS_COUNTS_200(kIndex,
uma_prefix_ + "Encoded.Qp.Vp8.S2", qp);
RTC_LOGGED_HISTOGRAMS_COUNTS_200(
kIndex, uma_prefix_ + "Encoded.Qp.Vp8.S2", qp_vp8);
} else {
LOG(LS_WARNING) << "QP stats not recorded for VP8 spatial idx "
<< spatial_idx;
}
}
int qp_vp9 = it.second.vp9.Avg(kMinRequiredSamples);
if (qp_vp9 != -1) {
int spatial_idx = it.first;
if (spatial_idx == -1) {
RTC_LOGGED_HISTOGRAMS_COUNTS_500(kIndex, uma_prefix_ + "Encoded.Qp.Vp9",
qp_vp9);
} else if (spatial_idx == 0) {
RTC_LOGGED_HISTOGRAMS_COUNTS_500(
kIndex, uma_prefix_ + "Encoded.Qp.Vp9.S0", qp_vp9);
} else if (spatial_idx == 1) {
RTC_LOGGED_HISTOGRAMS_COUNTS_500(
kIndex, uma_prefix_ + "Encoded.Qp.Vp9.S1", qp_vp9);
} else if (spatial_idx == 2) {
RTC_LOGGED_HISTOGRAMS_COUNTS_500(
kIndex, uma_prefix_ + "Encoded.Qp.Vp9.S2", qp_vp9);
} else {
LOG(LS_WARNING) << "QP stats not recorded for VP9 spatial layer "
<< spatial_idx;
}
}
}
if (first_rtcp_stats_time_ms_ != -1) {
@ -449,11 +469,19 @@ void SendStatisticsProxy::OnSendEncodedImage(
}
}
if (encoded_image.qp_ != -1 && rtp_video_header &&
rtp_video_header->codec == kRtpVideoVp8) {
int spatial_idx =
(config_.rtp.ssrcs.size() == 1) ? -1 : static_cast<int>(simulcast_idx);
uma_container_->qp_counters_[spatial_idx].vp8.Add(encoded_image.qp_);
if (encoded_image.qp_ != -1 && rtp_video_header) {
if (rtp_video_header->codec == kRtpVideoVp8) {
int spatial_idx = (config_.rtp.ssrcs.size() == 1)
? -1
: static_cast<int>(simulcast_idx);
uma_container_->qp_counters_[spatial_idx].vp8.Add(encoded_image.qp_);
} else if (rtp_video_header->codec == kRtpVideoVp9) {
int spatial_idx =
(rtp_video_header->codecHeader.VP9.num_spatial_layers == 1)
? -1
: rtp_video_header->codecHeader.VP9.spatial_idx;
uma_container_->qp_counters_[spatial_idx].vp9.Add(encoded_image.qp_);
}
}
// TODO(asapersson): This is incorrect if simulcast layers are encoded on

View File

@ -126,7 +126,8 @@ class SendStatisticsProxy : public CpuOveruseMetricsObserver,
int64_t bitrate_update_ms;
};
struct QpCounters {
SampleCounter vp8;
SampleCounter vp8; // QP range: 0-127
SampleCounter vp9; // QP range: 0-255
};
void PurgeOldStats() EXCLUSIVE_LOCKS_REQUIRED(crit_);
VideoSendStream::StreamStats* GetStatsEntry(uint32_t ssrc)

View File

@ -21,11 +21,16 @@
#include "webrtc/test/histogram.h"
namespace webrtc {
namespace {
const uint32_t kFirstSsrc = 17;
const uint32_t kSecondSsrc = 42;
const uint32_t kFirstRtxSsrc = 18;
const uint32_t kSecondRtxSsrc = 43;
static const uint32_t kFirstSsrc = 17;
static const uint32_t kSecondSsrc = 42;
static const uint32_t kFirstRtxSsrc = 18;
static const uint32_t kSecondRtxSsrc = 43;
const int kMinRequiredSamples = 200;
const int kQpIdx0 = 21;
const int kQpIdx1 = 39;
} // namespace
class SendStatisticsProxyTest : public ::testing::Test {
public:
@ -310,7 +315,6 @@ TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
test::ClearHistograms();
const int kMinRequiredSamples = 200;
const int kWidth = 640;
const int kHeight = 480;
@ -329,11 +333,7 @@ TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
test::ClearHistograms();
const int kMinRequiredSamples = 200;
const int kQpIdx0 = 21;
const int kQpIdx1 = 39;
EncodedImage encoded_image;
RTPVideoHeader rtp_video_header;
rtp_video_header.codec = kRtpVideoVp8;
@ -361,10 +361,7 @@ TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
&fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
test::ClearHistograms();
const int kMinRequiredSamples = 200;
const int kQpIdx0 = 21;
EncodedImage encoded_image;
RTPVideoHeader rtp_video_header;
rtp_video_header.codec = kRtpVideoVp8;
@ -378,6 +375,54 @@ TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
EXPECT_EQ(kQpIdx0, test::LastHistogramSample("WebRTC.Video.Encoded.Qp.Vp8"));
}
TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
test::ClearHistograms();
EncodedImage encoded_image;
RTPVideoHeader rtp_video_header;
rtp_video_header.simulcastIdx = 0;
rtp_video_header.codec = kRtpVideoVp9;
rtp_video_header.codecHeader.VP9.num_spatial_layers = 2;
for (int i = 0; i < kMinRequiredSamples; ++i) {
encoded_image.qp_ = kQpIdx0;
rtp_video_header.codecHeader.VP9.spatial_idx = 0;
statistics_proxy_->OnSendEncodedImage(encoded_image, &rtp_video_header);
encoded_image.qp_ = kQpIdx1;
rtp_video_header.codecHeader.VP9.spatial_idx = 1;
statistics_proxy_->OnSendEncodedImage(encoded_image, &rtp_video_header);
}
statistics_proxy_.reset();
EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
EXPECT_EQ(kQpIdx0,
test::LastHistogramSample("WebRTC.Video.Encoded.Qp.Vp9.S0"));
EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
EXPECT_EQ(kQpIdx1,
test::LastHistogramSample("WebRTC.Video.Encoded.Qp.Vp9.S1"));
}
TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
VideoSendStream::Config config(nullptr);
config.rtp.ssrcs.push_back(kFirstSsrc);
statistics_proxy_.reset(new SendStatisticsProxy(
&fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
test::ClearHistograms();
EncodedImage encoded_image;
RTPVideoHeader rtp_video_header;
rtp_video_header.simulcastIdx = 0;
rtp_video_header.codec = kRtpVideoVp9;
rtp_video_header.codecHeader.VP9.num_spatial_layers = 1;
for (int i = 0; i < kMinRequiredSamples; ++i) {
encoded_image.qp_ = kQpIdx0;
rtp_video_header.codecHeader.VP9.spatial_idx = 0;
statistics_proxy_->OnSendEncodedImage(encoded_image, &rtp_video_header);
}
statistics_proxy_.reset();
EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.Encoded.Qp.Vp9"));
EXPECT_EQ(kQpIdx0, test::LastHistogramSample("WebRTC.Video.Encoded.Qp.Vp9"));
}
TEST_F(SendStatisticsProxyTest, NoSubstreams) {
uint32_t excluded_ssrc =
std::max(