Add thread checks to ReceiveStatisticsProxy that reflect

design comments.

Change-Id: I4dd2b0be006440500cc7744de0e952263531ccd2
Bug: webrtc:8929
Reviewed-on: https://webrtc-review.googlesource.com/54940
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Commit-Queue: Tommi <tommi@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22179}
This commit is contained in:
Tommi
2018-02-24 17:57:33 +01:00
committed by Commit Bot
parent fdf50a6b14
commit 132e28e6aa
3 changed files with 36 additions and 1 deletions

View File

@ -113,6 +113,8 @@ ReceiveStatisticsProxy::ReceiveStatisticsProxy(
avg_rtt_ms_(0), avg_rtt_ms_(0),
last_content_type_(VideoContentType::UNSPECIFIED), last_content_type_(VideoContentType::UNSPECIFIED),
timing_frame_info_counter_(kMovingMaxWindowMs) { timing_frame_info_counter_(kMovingMaxWindowMs) {
decode_thread_.DetachFromThread();
network_thread_.DetachFromThread();
stats_.ssrc = config_.rtp.remote_ssrc; stats_.ssrc = config_.rtp.remote_ssrc;
// TODO(brandtr): Replace |rtx_stats_| with a single instance of // TODO(brandtr): Replace |rtx_stats_| with a single instance of
// StreamDataCounters. // StreamDataCounters.
@ -122,10 +124,19 @@ ReceiveStatisticsProxy::ReceiveStatisticsProxy(
} }
ReceiveStatisticsProxy::~ReceiveStatisticsProxy() { ReceiveStatisticsProxy::~ReceiveStatisticsProxy() {
RTC_DCHECK_RUN_ON(&main_thread_);
// In case you're reading this wondering "hmm... we're on the main thread but
// calling a method that needs to be called on the decoder thread...", then
// here's what's going on:
// - The decoder thread has been stopped and DecoderThreadStopped() has been
// called.
// - The decode_thread_ thread checker has been detached, and will now become
// attached to the current thread, which is OK since we're in the dtor.
UpdateHistograms(); UpdateHistograms();
} }
void ReceiveStatisticsProxy::UpdateHistograms() { void ReceiveStatisticsProxy::UpdateHistograms() {
RTC_DCHECK_RUN_ON(&decode_thread_);
std::ostringstream logStream; std::ostringstream logStream;
int stream_duration_sec = (clock_->TimeInMilliseconds() - start_ms_) / 1000; int stream_duration_sec = (clock_->TimeInMilliseconds() - start_ms_) / 1000;
if (stats_.frame_counts.key_frames > 0 || if (stats_.frame_counts.key_frames > 0 ||
@ -450,6 +461,8 @@ void ReceiveStatisticsProxy::UpdateHistograms() {
} }
void ReceiveStatisticsProxy::QualitySample() { void ReceiveStatisticsProxy::QualitySample() {
RTC_DCHECK_RUN_ON(&network_thread_);
int64_t now = clock_->TimeInMilliseconds(); int64_t now = clock_->TimeInMilliseconds();
if (last_sample_time_ + kMinSampleLengthMs > now) if (last_sample_time_ + kMinSampleLengthMs > now)
return; return;
@ -559,6 +572,7 @@ void ReceiveStatisticsProxy::OnDecoderImplementationName(
} }
void ReceiveStatisticsProxy::OnIncomingRate(unsigned int framerate, void ReceiveStatisticsProxy::OnIncomingRate(unsigned int framerate,
unsigned int bitrate_bps) { unsigned int bitrate_bps) {
RTC_DCHECK_RUN_ON(&network_thread_);
rtc::CritScope lock(&crit_); rtc::CritScope lock(&crit_);
if (stats_.rtp_stats.first_packet_time_ms != -1) if (stats_.rtp_stats.first_packet_time_ms != -1)
QualitySample(); QualitySample();
@ -783,6 +797,7 @@ void ReceiveStatisticsProxy::OnDiscardedPacketsUpdated(int discarded_packets) {
void ReceiveStatisticsProxy::OnPreDecode( void ReceiveStatisticsProxy::OnPreDecode(
const EncodedImage& encoded_image, const EncodedImage& encoded_image,
const CodecSpecificInfo* codec_specific_info) { const CodecSpecificInfo* codec_specific_info) {
RTC_DCHECK_RUN_ON(&decode_thread_);
if (!codec_specific_info || encoded_image.qp_ == -1) { if (!codec_specific_info || encoded_image.qp_ == -1) {
return; return;
} }
@ -839,6 +854,15 @@ void ReceiveStatisticsProxy::OnRttUpdate(int64_t avg_rtt_ms,
avg_rtt_ms_ = avg_rtt_ms; avg_rtt_ms_ = avg_rtt_ms;
} }
void ReceiveStatisticsProxy::DecoderThreadStarting() {
RTC_DCHECK_RUN_ON(&main_thread_);
}
void ReceiveStatisticsProxy::DecoderThreadStopped() {
RTC_DCHECK_RUN_ON(&main_thread_);
decode_thread_.DetachFromThread();
}
ReceiveStatisticsProxy::ContentSpecificStats::ContentSpecificStats() ReceiveStatisticsProxy::ContentSpecificStats::ContentSpecificStats()
: interframe_delay_percentiles(kMaxCommonInterframeDelayMs) {} : interframe_delay_percentiles(kMaxCommonInterframeDelayMs) {}

View File

@ -26,6 +26,7 @@
#include "rtc_base/rate_statistics.h" #include "rtc_base/rate_statistics.h"
#include "rtc_base/ratetracker.h" #include "rtc_base/ratetracker.h"
#include "rtc_base/thread_annotations.h" #include "rtc_base/thread_annotations.h"
#include "rtc_base/thread_checker.h"
#include "video/quality_threshold.h" #include "video/quality_threshold.h"
#include "video/report_block_stats.h" #include "video/report_block_stats.h"
#include "video/stats_counter.h" #include "video/stats_counter.h"
@ -98,6 +99,11 @@ class ReceiveStatisticsProxy : public VCMReceiveStatisticsCallback,
// Implements CallStatsObserver. // Implements CallStatsObserver.
void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) override; void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) override;
// Notification methods that are used to check our internal state and validate
// threading assumptions. These are called by VideoReceiveStream.
void DecoderThreadStarting();
void DecoderThreadStopped();
private: private:
struct SampleCounter { struct SampleCounter {
SampleCounter() : sum(0), num_samples(0) {} SampleCounter() : sum(0), num_samples(0) {}
@ -179,7 +185,7 @@ class ReceiveStatisticsProxy : public VCMReceiveStatisticsCallback,
MaxCounter freq_offset_counter_ RTC_GUARDED_BY(crit_); MaxCounter freq_offset_counter_ RTC_GUARDED_BY(crit_);
int64_t first_report_block_time_ms_ RTC_GUARDED_BY(crit_); int64_t first_report_block_time_ms_ RTC_GUARDED_BY(crit_);
ReportBlockStats report_block_stats_ RTC_GUARDED_BY(crit_); ReportBlockStats report_block_stats_ RTC_GUARDED_BY(crit_);
QpCounters qp_counters_; // Only accessed on the decoding thread. QpCounters qp_counters_ RTC_GUARDED_BY(decode_thread_);
std::map<uint32_t, StreamDataCounters> rtx_stats_ RTC_GUARDED_BY(crit_); std::map<uint32_t, StreamDataCounters> rtx_stats_ RTC_GUARDED_BY(crit_);
int64_t avg_rtt_ms_ RTC_GUARDED_BY(crit_); int64_t avg_rtt_ms_ RTC_GUARDED_BY(crit_);
mutable std::map<int64_t, size_t> frame_window_ RTC_GUARDED_BY(&crit_); mutable std::map<int64_t, size_t> frame_window_ RTC_GUARDED_BY(&crit_);
@ -191,6 +197,9 @@ class ReceiveStatisticsProxy : public VCMReceiveStatisticsCallback,
mutable rtc::MovingMaxCounter<TimingFrameInfo> timing_frame_info_counter_ mutable rtc::MovingMaxCounter<TimingFrameInfo> timing_frame_info_counter_
RTC_GUARDED_BY(&crit_); RTC_GUARDED_BY(&crit_);
rtc::Optional<int> num_unique_frames_ RTC_GUARDED_BY(crit_); rtc::Optional<int> num_unique_frames_ RTC_GUARDED_BY(crit_);
rtc::ThreadChecker decode_thread_;
rtc::ThreadChecker network_thread_;
rtc::ThreadChecker main_thread_;
}; };
} // namespace webrtc } // namespace webrtc

View File

@ -227,6 +227,7 @@ void VideoReceiveStream::Start() {
// Start the decode thread // Start the decode thread
video_receiver_.DecoderThreadStarting(); video_receiver_.DecoderThreadStarting();
stats_proxy_.DecoderThreadStarting();
decode_thread_.Start(); decode_thread_.Start();
rtp_video_stream_receiver_.StartReceive(); rtp_video_stream_receiver_.StartReceive();
} }
@ -251,6 +252,7 @@ void VideoReceiveStream::Stop() {
decode_thread_.Stop(); decode_thread_.Stop();
video_receiver_.DecoderThreadStopped(); video_receiver_.DecoderThreadStopped();
stats_proxy_.DecoderThreadStopped();
// Deregister external decoders so they are no longer running during // Deregister external decoders so they are no longer running during
// destruction. This effectively stops the VCM since the decoder thread is // destruction. This effectively stops the VCM since the decoder thread is
// stopped, the VCM is deregistered and no asynchronous decoder threads are // stopped, the VCM is deregistered and no asynchronous decoder threads are