diff --git a/talk/app/webrtc/statscollector.cc b/talk/app/webrtc/statscollector.cc index eb32356400..7f5f925b82 100644 --- a/talk/app/webrtc/statscollector.cc +++ b/talk/app/webrtc/statscollector.cc @@ -108,6 +108,11 @@ void ExtractCommonSendProperties(const cricket::MediaSenderInfo& info, report->AddInt64(StatsReport::kStatsValueNameRtt, info.rtt_ms); } +void ExtractCommonReceiveProperties(const cricket::MediaReceiverInfo& info, + StatsReport* report) { + report->AddString(StatsReport::kStatsValueNameCodecName, info.codec_name); +} + void SetAudioProcessingStats(StatsReport* report, int signal_level, bool typing_noise_detected, int echo_return_loss, int echo_return_loss_enhancement, int echo_delay_median_ms, @@ -131,6 +136,7 @@ void SetAudioProcessingStats(StatsReport* report, int signal_level, } void ExtractStats(const cricket::VoiceReceiverInfo& info, StatsReport* report) { + ExtractCommonReceiveProperties(info, report); const FloatForAdd floats[] = { { StatsReport::kStatsValueNameExpandRate, info.expand_rate }, { StatsReport::kStatsValueNameSecondaryDecodedRate, @@ -169,8 +175,6 @@ void ExtractStats(const cricket::VoiceReceiverInfo& info, StatsReport* report) { info.bytes_rcvd); report->AddInt64(StatsReport::kStatsValueNameCaptureStartNtpTimeMs, info.capture_start_ntp_time_ms); - - report->AddString(StatsReport::kStatsValueNameCodecName, info.codec_name); } void ExtractStats(const cricket::VoiceSenderInfo& info, StatsReport* report) { @@ -191,6 +195,7 @@ void ExtractStats(const cricket::VoiceSenderInfo& info, StatsReport* report) { } void ExtractStats(const cricket::VideoReceiverInfo& info, StatsReport* report) { + ExtractCommonReceiveProperties(info, report); report->AddInt64(StatsReport::kStatsValueNameBytesReceived, info.bytes_rcvd); report->AddInt64(StatsReport::kStatsValueNameCaptureStartNtpTimeMs, diff --git a/talk/media/webrtc/webrtcvideoengine2.cc b/talk/media/webrtc/webrtcvideoengine2.cc index da1ebf1d72..7e2c1d4151 100644 --- a/talk/media/webrtc/webrtcvideoengine2.cc +++ b/talk/media/webrtc/webrtcvideoengine2.cc @@ -2583,6 +2583,17 @@ void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetSize(int width, last_height_ = height; } +std::string +WebRtcVideoChannel2::WebRtcVideoReceiveStream::GetCodecNameFromPayloadType( + int payload_type) { + for (const webrtc::VideoReceiveStream::Decoder& decoder : config_.decoders) { + if (decoder.payload_type == payload_type) { + return decoder.payload_name; + } + } + return ""; +} + VideoReceiverInfo WebRtcVideoChannel2::WebRtcVideoReceiveStream::GetVideoReceiverInfo() { VideoReceiverInfo info; @@ -2616,6 +2627,8 @@ WebRtcVideoChannel2::WebRtcVideoReceiveStream::GetVideoReceiverInfo() { info.min_playout_delay_ms = stats.min_playout_delay_ms; info.render_delay_ms = stats.render_delay_ms; + info.codec_name = GetCodecNameFromPayloadType(stats.current_payload_type); + info.firs_sent = stats.rtcp_packet_type_counts.fir_packets; info.plis_sent = stats.rtcp_packet_type_counts.pli_packets; info.nacks_sent = stats.rtcp_packet_type_counts.nack_packets; diff --git a/talk/media/webrtc/webrtcvideoengine2.h b/talk/media/webrtc/webrtcvideoengine2.h index 263a93c7f0..c7c8bc0cf5 100644 --- a/talk/media/webrtc/webrtcvideoengine2.h +++ b/talk/media/webrtc/webrtcvideoengine2.h @@ -458,6 +458,8 @@ class WebRtcVideoChannel2 : public rtc::MessageHandler, const VideoCodec& codec); void ClearDecoders(std::vector* allocated_decoders); + std::string GetCodecNameFromPayloadType(int payload_type); + webrtc::Call* const call_; const std::vector ssrcs_; const std::vector ssrc_groups_; diff --git a/talk/media/webrtc/webrtcvideoengine2_unittest.cc b/talk/media/webrtc/webrtcvideoengine2_unittest.cc index fd87703eab..545520f891 100644 --- a/talk/media/webrtc/webrtcvideoengine2_unittest.cc +++ b/talk/media/webrtc/webrtcvideoengine2_unittest.cc @@ -2670,6 +2670,29 @@ TEST_F(WebRtcVideoChannel2Test, ReportsSsrcGroupsInStats) { EXPECT_EQ(receiver_sp.ssrc_groups, info.receivers[0].ssrc_groups); } +TEST_F(WebRtcVideoChannel2Test, MapsReceivedPayloadTypeToCodecName) { + FakeVideoReceiveStream* stream = AddRecvStream(); + webrtc::VideoReceiveStream::Stats stats; + cricket::VideoMediaInfo info; + + // Report no codec name before receiving. + stream->SetStats(stats); + ASSERT_TRUE(channel_->GetStats(&info)); + EXPECT_STREQ("", info.receivers[0].codec_name.c_str()); + + // Report VP8 if we're receiving it. + stats.current_payload_type = kDefaultVp8PlType; + stream->SetStats(stats); + ASSERT_TRUE(channel_->GetStats(&info)); + EXPECT_STREQ(kVp8CodecName, info.receivers[0].codec_name.c_str()); + + // Report no codec name for unknown playload types. + stats.current_payload_type = 3; + stream->SetStats(stats); + ASSERT_TRUE(channel_->GetStats(&info)); + EXPECT_STREQ("", info.receivers[0].codec_name.c_str()); +} + void WebRtcVideoChannel2Test::TestReceiveUnsignalledSsrcPacket( uint8_t payload_type, bool expect_created_receive_stream) { diff --git a/webrtc/modules/video_coding/main/interface/video_coding_defines.h b/webrtc/modules/video_coding/main/interface/video_coding_defines.h index ff844c663d..fd38d64415 100644 --- a/webrtc/modules/video_coding/main/interface/video_coding_defines.h +++ b/webrtc/modules/video_coding/main/interface/video_coding_defines.h @@ -76,7 +76,7 @@ class VCMReceiveCallback { return -1; } // Called when the current receive codec changes. - virtual void IncomingCodecChanged(const VideoCodec& codec) {} + virtual void OnIncomingPayloadType(int payload_type) {} protected: virtual ~VCMReceiveCallback() { diff --git a/webrtc/modules/video_coding/main/source/codec_database.cc b/webrtc/modules/video_coding/main/source/codec_database.cc index 2e2d91ec79..c0ec2c8442 100644 --- a/webrtc/modules/video_coding/main/source/codec_database.cc +++ b/webrtc/modules/video_coding/main/source/codec_database.cc @@ -581,7 +581,7 @@ VCMGenericDecoder* VCMCodecDataBase::GetDecoder( return NULL; } VCMReceiveCallback* callback = decoded_frame_callback->UserReceiveCallback(); - if (callback) callback->IncomingCodecChanged(receive_codec_); + if (callback) callback->OnIncomingPayloadType(receive_codec_.plType); if (ptr_decoder_->RegisterDecodeCompleteCallback(decoded_frame_callback) < 0) { ReleaseDecoder(ptr_decoder_); diff --git a/webrtc/video/end_to_end_tests.cc b/webrtc/video/end_to_end_tests.cc index 52bacc542a..9f62ec8add 100644 --- a/webrtc/video/end_to_end_tests.cc +++ b/webrtc/video/end_to_end_tests.cc @@ -2216,6 +2216,11 @@ TEST_F(EndToEndTest, GetStats) { stats.rtcp_packet_type_counts.pli_packets != 0 || stats.rtcp_packet_type_counts.nack_requests != 0 || stats.rtcp_packet_type_counts.unique_nack_requests != 0; + + assert(stats.current_payload_type == -1 || + stats.current_payload_type == kFakeSendPayloadType); + receive_stats_filled_["IncomingPayloadType"] |= + stats.current_payload_type == kFakeSendPayloadType; } return AllStatsFilled(receive_stats_filled_); diff --git a/webrtc/video/receive_statistics_proxy.cc b/webrtc/video/receive_statistics_proxy.cc index 6604d3de6f..ec5aacb75a 100644 --- a/webrtc/video/receive_statistics_proxy.cc +++ b/webrtc/video/receive_statistics_proxy.cc @@ -59,21 +59,25 @@ VideoReceiveStream::Stats ReceiveStatisticsProxy::GetStats() const { return stats_; } -void ReceiveStatisticsProxy::IncomingRate(const int video_channel, - const unsigned int framerate, - const unsigned int bitrate_bps) { +void ReceiveStatisticsProxy::OnIncomingPayloadType(int payload_type) { + rtc::CritScope lock(&crit_); + stats_.current_payload_type = payload_type; +} + +void ReceiveStatisticsProxy::OnIncomingRate(unsigned int framerate, + unsigned int bitrate_bps) { rtc::CritScope lock(&crit_); stats_.network_frame_rate = framerate; stats_.total_bitrate_bps = bitrate_bps; } -void ReceiveStatisticsProxy::DecoderTiming(int decode_ms, - 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) { +void ReceiveStatisticsProxy::OnDecoderTiming(int decode_ms, + 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) { rtc::CritScope lock(&crit_); stats_.decode_ms = decode_ms; stats_.max_decode_ms = max_decode_ms; diff --git a/webrtc/video/receive_statistics_proxy.h b/webrtc/video/receive_statistics_proxy.h index 50422109aa..3041d315ed 100644 --- a/webrtc/video/receive_statistics_proxy.h +++ b/webrtc/video/receive_statistics_proxy.h @@ -31,8 +31,7 @@ class Clock; class ViECodec; class ViEDecoderObserver; -class ReceiveStatisticsProxy : public ViEDecoderObserver, - public VCMReceiveStatisticsCallback, +class ReceiveStatisticsProxy : public VCMReceiveStatisticsCallback, public RtcpStatisticsCallback, public RtcpPacketTypeCounterObserver, public StreamDataCountersCallback { @@ -44,26 +43,21 @@ class ReceiveStatisticsProxy : public ViEDecoderObserver, void OnDecodedFrame(); void OnRenderedFrame(int width, int height); + void OnIncomingPayloadType(int payload_type); + void OnIncomingRate(unsigned int framerate, unsigned int bitrate_bps); + void OnDecoderTiming(int decode_ms, + 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); // Overrides VCMReceiveStatisticsCallback. void OnReceiveRatesUpdated(uint32_t bitRate, uint32_t frameRate) override; void OnFrameCountsUpdated(const FrameCounts& frame_counts) override; void OnDiscardedPacketsUpdated(int discarded_packets) override; - // Overrides ViEDecoderObserver. - void IncomingCodecChanged(const int video_channel, - const VideoCodec& video_codec) override {} - void IncomingRate(const int video_channel, - const unsigned int framerate, - const unsigned int bitrate_bps) override; - void DecoderTiming(int decode_ms, - 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) override; - // Overrides RtcpStatisticsCallback. void StatisticsUpdated(const webrtc::RtcpStatistics& statistics, uint32_t ssrc) override; diff --git a/webrtc/video/video_receive_stream.cc b/webrtc/video/video_receive_stream.cc index f3e20916de..52e37b7b7a 100644 --- a/webrtc/video/video_receive_stream.cc +++ b/webrtc/video/video_receive_stream.cc @@ -215,13 +215,11 @@ VideoReceiveStream::VideoReceiveStream(int num_cpu_cores, stats_proxy_.reset( new ReceiveStatisticsProxy(config_.rtp.remote_ssrc, clock_)); + vie_channel_->RegisterReceiveStatisticsProxy(stats_proxy_.get()); vie_channel_->RegisterReceiveChannelRtcpStatisticsCallback( stats_proxy_.get()); vie_channel_->RegisterReceiveChannelRtpStatisticsCallback(stats_proxy_.get()); vie_channel_->RegisterRtcpPacketTypeCounterObserver(stats_proxy_.get()); - vie_channel_->RegisterCodecObserver(stats_proxy_.get()); - - vie_channel_->RegisterReceiveStatisticsProxy(stats_proxy_.get()); DCHECK(!config_.decoders.empty()); for (size_t i = 0; i < config_.decoders.size(); ++i) { @@ -254,10 +252,6 @@ VideoReceiveStream::~VideoReceiveStream() { for (size_t i = 0; i < config_.decoders.size(); ++i) vie_channel_->DeRegisterExternalDecoder(config_.decoders[i].payload_type); - vie_channel_->RegisterCodecObserver(nullptr); - vie_channel_->RegisterReceiveChannelRtpStatisticsCallback(nullptr); - vie_channel_->RegisterReceiveChannelRtcpStatisticsCallback(nullptr); - vie_channel_->RegisterRtcpPacketTypeCounterObserver(nullptr); channel_group_->DeleteChannel(channel_id_); } diff --git a/webrtc/video_engine/vie_channel.cc b/webrtc/video_engine/vie_channel.cc index b8664cecc8..29b9efe6d3 100644 --- a/webrtc/video_engine/vie_channel.cc +++ b/webrtc/video_engine/vie_channel.cc @@ -105,16 +105,14 @@ ViEChannel::ViEChannel(int32_t channel_id, vie_receiver_(channel_id, vcm_, remote_bitrate_estimator, this), vie_sync_(vcm_), stats_observer_(new ChannelStatsObserver(this)), - vcm_receive_stats_callback_(NULL), + receive_stats_callback_(nullptr), incoming_video_stream_(nullptr), - codec_observer_(NULL), intra_frame_observer_(intra_frame_observer), rtt_stats_(rtt_stats), paced_sender_(paced_sender), packet_router_(packet_router), bandwidth_observer_(bandwidth_observer), send_time_observer_(send_time_observer), - decoder_reset_(true), nack_history_size_sender_(kSendSidePacketHistorySize), max_nack_reordering_threshold_(kMaxPacketAgeToNack), pre_render_callback_(NULL), @@ -437,20 +435,6 @@ int32_t ViEChannel::SetReceiveCodec(const VideoCodec& video_codec) { return 0; } -int32_t ViEChannel::RegisterCodecObserver(ViEDecoderObserver* observer) { - CriticalSectionScoped cs(crit_.get()); - if (observer) { - if (codec_observer_) { - LOG_F(LS_ERROR) << "Observer already registered."; - return -1; - } - codec_observer_ = observer; - } else { - codec_observer_ = NULL; - } - return 0; -} - int32_t ViEChannel::RegisterExternalDecoder(const uint8_t pl_type, VideoDecoder* decoder, bool buffered_rendering, @@ -1042,18 +1026,6 @@ CallStatsObserver* ViEChannel::GetStatsObserver() { int32_t ViEChannel::FrameToRender(VideoFrame& video_frame) { // NOLINT CriticalSectionScoped cs(crit_.get()); - if (decoder_reset_) { - // Trigger a callback to the user if the incoming codec has changed. - if (codec_observer_) { - // The codec set by RegisterReceiveCodec might not be the size we're - // actually decoding. - receive_codec_.width = static_cast(video_frame.width()); - receive_codec_.height = static_cast(video_frame.height()); - codec_observer_->IncomingCodecChanged(channel_id_, receive_codec_); - } - decoder_reset_ = false; - } - if (pre_render_callback_ != NULL) pre_render_callback_->FrameCallback(&video_frame); @@ -1066,28 +1038,29 @@ int32_t ViEChannel::ReceivedDecodedReferenceFrame( return rtp_rtcp_modules_[0]->SendRTCPReferencePictureSelection(picture_id); } -void ViEChannel::IncomingCodecChanged(const VideoCodec& codec) { +void ViEChannel::OnIncomingPayloadType(int payload_type) { CriticalSectionScoped cs(crit_.get()); - receive_codec_ = codec; + if (receive_stats_callback_) + receive_stats_callback_->OnIncomingPayloadType(payload_type); } void ViEChannel::OnReceiveRatesUpdated(uint32_t bit_rate, uint32_t frame_rate) { CriticalSectionScoped cs(crit_.get()); - if (codec_observer_) - codec_observer_->IncomingRate(channel_id_, frame_rate, bit_rate); + if (receive_stats_callback_) + receive_stats_callback_->OnIncomingRate(frame_rate, bit_rate); } void ViEChannel::OnDiscardedPacketsUpdated(int discarded_packets) { CriticalSectionScoped cs(crit_.get()); - if (vcm_receive_stats_callback_ != NULL) - vcm_receive_stats_callback_->OnDiscardedPacketsUpdated(discarded_packets); + if (receive_stats_callback_) + receive_stats_callback_->OnDiscardedPacketsUpdated(discarded_packets); } void ViEChannel::OnFrameCountsUpdated(const FrameCounts& frame_counts) { CriticalSectionScoped cs(crit_.get()); receive_frame_counts_ = frame_counts; - if (vcm_receive_stats_callback_ != NULL) - vcm_receive_stats_callback_->OnFrameCountsUpdated(frame_counts); + if (receive_stats_callback_) + receive_stats_callback_->OnFrameCountsUpdated(frame_counts); } void ViEChannel::OnDecoderTiming(int decode_ms, @@ -1098,15 +1071,11 @@ void ViEChannel::OnDecoderTiming(int decode_ms, int min_playout_delay_ms, int render_delay_ms) { CriticalSectionScoped cs(crit_.get()); - if (!codec_observer_) + if (!receive_stats_callback_) return; - codec_observer_->DecoderTiming(decode_ms, - max_decode_ms, - current_delay_ms, - target_delay_ms, - jitter_buffer_ms, - min_playout_delay_ms, - render_delay_ms); + receive_stats_callback_->OnDecoderTiming( + decode_ms, max_decode_ms, current_delay_ms, target_delay_ms, + jitter_buffer_ms, min_playout_delay_ms, render_delay_ms); } int32_t ViEChannel::RequestKeyFrame() { @@ -1261,6 +1230,8 @@ void ViEChannel::RegisterPreDecodeImageCallback( vcm_->RegisterPreDecodeImageCallback(pre_decode_callback); } +// TODO(pbos): Remove OnInitializeDecoder which is called from the RTP module, +// any decoder resetting should be handled internally within the VCM. int32_t ViEChannel::OnInitializeDecoder( const int32_t id, const int8_t payload_type, @@ -1272,8 +1243,6 @@ int32_t ViEChannel::OnInitializeDecoder( << " " << payload_name; vcm_->ResetDecoder(); - CriticalSectionScoped cs(crit_.get()); - decoder_reset_ = true; return 0; } @@ -1297,7 +1266,7 @@ void ViEChannel::RegisterSendFrameCountObserver( void ViEChannel::RegisterReceiveStatisticsProxy( ReceiveStatisticsProxy* receive_statistics_proxy) { CriticalSectionScoped cs(crit_.get()); - vcm_receive_stats_callback_ = receive_statistics_proxy; + receive_stats_callback_ = receive_statistics_proxy; } void ViEChannel::SetIncomingVideoStream( diff --git a/webrtc/video_engine/vie_channel.h b/webrtc/video_engine/vie_channel.h index 85b18cf645..b93dc0478c 100644 --- a/webrtc/video_engine/vie_channel.h +++ b/webrtc/video_engine/vie_channel.h @@ -44,7 +44,6 @@ class ReportBlockStats; class RtcpRttStats; class ThreadWrapper; class ViEChannelProtectionCallback; -class ViEDecoderObserver; class ViERTPObserver; class VideoCodingModule; class VideoDecoder; @@ -56,36 +55,6 @@ enum StreamType { kViEStreamTypeRtx = 1 // Retransmission media stream }; -// This class declares an abstract interface for a user defined observer. It is -// up to the VideoEngine user to implement a derived class which implements the -// observer class. The observer is registered using RegisterDecoderObserver() -// and deregistered using DeregisterDecoderObserver(). -class ViEDecoderObserver { - public: - // This method is called when a new incoming stream is detected, normally - // triggered by a new incoming SSRC or payload type. - virtual void IncomingCodecChanged(const int video_channel, - const VideoCodec& video_codec) = 0; - - // This method is called once per second containing the frame rate and bit - // rate for the incoming stream - virtual void IncomingRate(const int video_channel, - const unsigned int framerate, - const unsigned int bitrate) = 0; - - // Called periodically with decoder timing information. All values are - // "current" snapshots unless decorated with a min_/max_ prefix. - virtual void DecoderTiming(int decode_ms, - 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) = 0; - - protected: - virtual ~ViEDecoderObserver() {} -}; class ViEChannel : public VCMFrameTypeCallback, public VCMReceiveCallback, public VCMReceiveStatisticsCallback, @@ -118,7 +87,6 @@ class ViEChannel : public VCMFrameTypeCallback, // type has changed and we should start a new RTP stream. int32_t SetSendCodec(const VideoCodec& video_codec, bool new_stream = true); int32_t SetReceiveCodec(const VideoCodec& video_codec); - int32_t RegisterCodecObserver(ViEDecoderObserver* observer); // Registers an external decoder. |buffered_rendering| means that the decoder // will render frames after decoding according to the render timestamp // provided by the video coding module. |render_delay| indicates the time @@ -271,7 +239,7 @@ class ViEChannel : public VCMFrameTypeCallback, const uint64_t picture_id); // Implements VCMReceiveCallback. - virtual void IncomingCodecChanged(const VideoCodec& codec); + void OnIncomingPayloadType(int payload_type) override; // Implements VCMReceiveStatisticsCallback. void OnReceiveRatesUpdated(uint32_t bit_rate, uint32_t frame_rate) override; @@ -464,11 +432,9 @@ class ViEChannel : public VCMFrameTypeCallback, rtc::scoped_ptr stats_observer_; // Not owned. - VCMReceiveStatisticsCallback* vcm_receive_stats_callback_ - GUARDED_BY(crit_); + ReceiveStatisticsProxy* receive_stats_callback_ GUARDED_BY(crit_); FrameCounts receive_frame_counts_ GUARDED_BY(crit_); IncomingVideoStream* incoming_video_stream_ GUARDED_BY(crit_); - ViEDecoderObserver* codec_observer_ GUARDED_BY(crit_); RtcpIntraFrameObserver* const intra_frame_observer_; RtcpRttStats* const rtt_stats_; PacedSender* const paced_sender_; @@ -477,9 +443,6 @@ class ViEChannel : public VCMFrameTypeCallback, const rtc::scoped_ptr bandwidth_observer_; SendTimeObserver* const send_time_observer_; - bool decoder_reset_ GUARDED_BY(crit_); - // Current receive codec used for codec change callback. - VideoCodec receive_codec_ GUARDED_BY(crit_); rtc::scoped_ptr decode_thread_; int nack_history_size_sender_; diff --git a/webrtc/video_receive_stream.h b/webrtc/video_receive_stream.h index e613006412..955d87569b 100644 --- a/webrtc/video_receive_stream.h +++ b/webrtc/video_receive_stream.h @@ -75,6 +75,8 @@ class VideoReceiveStream : public ReceiveStream { int min_playout_delay_ms = 0; int render_delay_ms = 10; + int current_payload_type = -1; + int total_bitrate_bps = 0; int discarded_packets = 0;