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

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

BUG=

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

Cr-Commit-Position: refs/heads/master@{#12174}
This commit is contained in:
asapersson 2016-03-31 00:00:19 -07:00 committed by Commit bot
parent ff97631e3c
commit 118ef00594
4 changed files with 90 additions and 0 deletions

View File

@ -1040,6 +1040,10 @@ int VP8EncoderImpl::GetEncodedPartitions(const VideoFrame& input_image,
// Report once per frame (lowest stream always sent).
encoded_images_[encoder_idx].adapt_reason_.bw_resolutions_disabled =
(stream_idx == 0) ? bw_resolutions_disabled : -1;
int qp_128 = -1;
vpx_codec_control(&encoders_[encoder_idx], VP8E_GET_LAST_QUANTIZER,
&qp_128);
encoded_images_[encoder_idx].qp_ = qp_128;
encoded_complete_callback_->Encoded(encoded_images_[encoder_idx],
&codec_specific, &frag_info);
} else if (codec_.mode == kScreensharing) {

View File

@ -193,6 +193,29 @@ void SendStatisticsProxy::UmaSamplesContainer::UpdateHistograms(
kIndex, uma_prefix_ + "SendSideDelayMaxInMs", max_delay_ms);
}
for (const auto& it : qp_counters_) {
int qp = it.second.vp8.Avg(kMinRequiredSamples);
if (qp != -1) {
int spatial_idx = it.first;
if (spatial_idx == -1) {
RTC_LOGGED_HISTOGRAMS_COUNTS_200(kIndex, uma_prefix_ + "Encoded.Qp.Vp8",
qp);
} else if (spatial_idx == 0) {
RTC_LOGGED_HISTOGRAMS_COUNTS_200(kIndex,
uma_prefix_ + "Encoded.Qp.Vp8.S0", qp);
} else if (spatial_idx == 1) {
RTC_LOGGED_HISTOGRAMS_COUNTS_200(kIndex,
uma_prefix_ + "Encoded.Qp.Vp8.S1", qp);
} else if (spatial_idx == 2) {
RTC_LOGGED_HISTOGRAMS_COUNTS_200(kIndex,
uma_prefix_ + "Encoded.Qp.Vp8.S2", qp);
} else {
LOG(LS_WARNING) << "QP stats not recorded for VP8 spatial idx "
<< spatial_idx;
}
}
}
if (first_rtcp_stats_time_ms_ != -1) {
int64_t elapsed_sec =
(clock_->TimeInMilliseconds() - first_rtcp_stats_time_ms_) / 1000;
@ -427,6 +450,13 @@ void SendStatisticsProxy::OnSendEncodedImage(
}
}
if (encoded_image.qp_ != -1 && rtp_video_header != nullptr &&
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_);
}
// TODO(asapersson): This is incorrect if simulcast layers are encoded on
// different threads and there is no guarantee that one frame of all layers
// are encoded before the next start.

View File

@ -125,6 +125,9 @@ class SendStatisticsProxy : public CpuOveruseMetricsObserver,
int64_t resolution_update_ms;
int64_t bitrate_update_ms;
};
struct QpCounters {
SampleCounter vp8;
};
void PurgeOldStats() EXCLUSIVE_LOCKS_REQUIRED(crit_);
VideoSendStream::StreamStats* GetStatsEntry(uint32_t ssrc)
EXCLUSIVE_LOCKS_REQUIRED(crit_);
@ -172,6 +175,8 @@ class SendStatisticsProxy : public CpuOveruseMetricsObserver,
int64_t first_rtp_stats_time_ms_;
ReportBlockStats report_block_stats_;
const VideoSendStream::Stats start_stats_;
std::map<int, QpCounters>
qp_counters_; // QP counters mapped by spatial idx.
};
std::unique_ptr<UmaSamplesContainer> uma_container_ GUARDED_BY(crit_);

View File

@ -327,6 +327,57 @@ TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.InputWidthInPixels"));
}
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;
for (int i = 0; i < kMinRequiredSamples; ++i) {
rtp_video_header.simulcastIdx = 0;
encoded_image.qp_ = kQpIdx0;
statistics_proxy_->OnSendEncodedImage(encoded_image, &rtp_video_header);
rtp_video_header.simulcastIdx = 1;
encoded_image.qp_ = kQpIdx1;
statistics_proxy_->OnSendEncodedImage(encoded_image, &rtp_video_header);
}
statistics_proxy_.reset();
EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
EXPECT_EQ(kQpIdx0,
test::LastHistogramSample("WebRTC.Video.Encoded.Qp.Vp8.S0"));
EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
EXPECT_EQ(kQpIdx1,
test::LastHistogramSample("WebRTC.Video.Encoded.Qp.Vp8.S1"));
}
TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
VideoSendStream::Config config(nullptr);
config.rtp.ssrcs.push_back(kFirstSsrc);
statistics_proxy_.reset(new SendStatisticsProxy(
&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;
for (int i = 0; i < kMinRequiredSamples; ++i) {
rtp_video_header.simulcastIdx = 0;
encoded_image.qp_ = kQpIdx0;
statistics_proxy_->OnSendEncodedImage(encoded_image, &rtp_video_header);
}
statistics_proxy_.reset();
EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.Encoded.Qp.Vp8"));
EXPECT_EQ(kQpIdx0, test::LastHistogramSample("WebRTC.Video.Encoded.Qp.Vp8"));
}
TEST_F(SendStatisticsProxyTest, NoSubstreams) {
uint32_t excluded_ssrc =
std::max(