diff --git a/talk/media/webrtc/webrtcvideoengine2.cc b/talk/media/webrtc/webrtcvideoengine2.cc index 5a380cbad6..9006934121 100644 --- a/talk/media/webrtc/webrtcvideoengine2.cc +++ b/talk/media/webrtc/webrtcvideoengine2.cc @@ -1825,6 +1825,7 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::FillBandwidthEstimationInfo( bwe_info->transmit_bitrate += it->second.total_bitrate_bps; bwe_info->retransmit_bitrate += it->second.retransmit_bitrate_bps; } + bwe_info->target_enc_bitrate += stats.target_media_bitrate_bps; bwe_info->actual_enc_bitrate += stats.media_bitrate_bps; } diff --git a/talk/media/webrtc/webrtcvideoengine2_unittest.cc b/talk/media/webrtc/webrtcvideoengine2_unittest.cc index 751765dbb7..283ade1af9 100644 --- a/talk/media/webrtc/webrtcvideoengine2_unittest.cc +++ b/talk/media/webrtc/webrtcvideoengine2_unittest.cc @@ -2224,6 +2224,7 @@ TEST_F(WebRtcVideoChannel2Test, TranslatesCallStatsCorrectly) { TEST_F(WebRtcVideoChannel2Test, TranslatesSenderBitrateStatsCorrectly) { FakeVideoSendStream* stream = AddSendStream(); webrtc::VideoSendStream::Stats stats; + stats.target_media_bitrate_bps = 156; stats.media_bitrate_bps = 123; stats.substreams[17].total_bitrate_bps = 1; stats.substreams[17].retransmit_bitrate_bps = 2; @@ -2233,6 +2234,7 @@ TEST_F(WebRtcVideoChannel2Test, TranslatesSenderBitrateStatsCorrectly) { FakeVideoSendStream* stream2 = AddSendStream(); webrtc::VideoSendStream::Stats stats2; + stats2.target_media_bitrate_bps = 200; stats2.media_bitrate_bps = 321; stats2.substreams[13].total_bitrate_bps = 5; stats2.substreams[13].retransmit_bitrate_bps = 6; @@ -2247,6 +2249,8 @@ TEST_F(WebRtcVideoChannel2Test, TranslatesSenderBitrateStatsCorrectly) { // is OK as std::maps are sorted and AddSendStream() gives increasing SSRCs. EXPECT_EQ(stats.media_bitrate_bps, info.senders[0].nominal_bitrate); EXPECT_EQ(stats2.media_bitrate_bps, info.senders[1].nominal_bitrate); + EXPECT_EQ(stats.target_media_bitrate_bps + stats2.target_media_bitrate_bps, + info.bw_estimations[0].target_enc_bitrate); EXPECT_EQ(stats.media_bitrate_bps + stats2.media_bitrate_bps, info.bw_estimations[0].actual_enc_bitrate); EXPECT_EQ(1 + 3 + 5 + 7, info.bw_estimations[0].transmit_bitrate) diff --git a/webrtc/modules/utility/source/video_coder.cc b/webrtc/modules/utility/source/video_coder.cc index 2aff128ad9..78a99f0d1c 100644 --- a/webrtc/modules/utility/source/video_coder.cc +++ b/webrtc/modules/utility/source/video_coder.cc @@ -14,7 +14,8 @@ #include "webrtc/modules/video_coding/main/source/encoded_frame.h" namespace webrtc { -VideoCoder::VideoCoder() : _vcm(VideoCodingModule::Create()), _decodedVideo(0) { +VideoCoder::VideoCoder() + : _vcm(VideoCodingModule::Create(nullptr)), _decodedVideo(0) { _vcm->InitializeSender(); _vcm->InitializeReceiver(); diff --git a/webrtc/modules/video_coding/main/interface/video_coding.h b/webrtc/modules/video_coding/main/interface/video_coding.h index 2371685625..859f2852f2 100644 --- a/webrtc/modules/video_coding/main/interface/video_coding.h +++ b/webrtc/modules/video_coding/main/interface/video_coding.h @@ -81,7 +81,8 @@ public: kReferenceSelection }; - static VideoCodingModule* Create(); + static VideoCodingModule* Create( + VideoEncoderRateObserver* encoder_rate_observer); static VideoCodingModule* Create(Clock* clock, EventFactory* event_factory); 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 976a1761c9..ea47e312ec 100644 --- a/webrtc/modules/video_coding/main/interface/video_coding_defines.h +++ b/webrtc/modules/video_coding/main/interface/video_coding_defines.h @@ -148,6 +148,12 @@ class VCMProtectionCallback { } }; +class VideoEncoderRateObserver { + public: + virtual ~VideoEncoderRateObserver() {} + virtual void OnSetRates(uint32_t bitrate_bps, int framerate) = 0; +}; + // Callback class used for telling the user about what frame type needed to continue decoding. // Typically a key frame when the stream has been corrupted in some way. class VCMFrameTypeCallback { diff --git a/webrtc/modules/video_coding/main/source/codec_database.cc b/webrtc/modules/video_coding/main/source/codec_database.cc index e498054aca..6ca7d9dd09 100644 --- a/webrtc/modules/video_coding/main/source/codec_database.cc +++ b/webrtc/modules/video_coding/main/source/codec_database.cc @@ -93,7 +93,8 @@ VCMExtDecoderMapItem::VCMExtDecoderMapItem( internal_render_timing(internal_render_timing) { } -VCMCodecDataBase::VCMCodecDataBase() +VCMCodecDataBase::VCMCodecDataBase( + VideoEncoderRateObserver* encoder_rate_observer) : number_of_cores_(0), max_payload_size_(kDefaultPayloadSize), periodic_key_frames_(false), @@ -104,11 +105,13 @@ VCMCodecDataBase::VCMCodecDataBase() external_payload_type_(0), external_encoder_(NULL), internal_source_(false), + encoder_rate_observer_(encoder_rate_observer), ptr_encoder_(NULL), ptr_decoder_(NULL), current_dec_is_external_(false), dec_map_(), - dec_external_map_() {} + dec_external_map_() { +} VCMCodecDataBase::~VCMCodecDataBase() { ResetSender(); @@ -295,7 +298,8 @@ bool VCMCodecDataBase::SetSendCodec( DeleteEncoder(); if (send_codec->plType == external_payload_type_) { // External encoder. - ptr_encoder_ = new VCMGenericEncoder(*external_encoder_, internal_source_); + ptr_encoder_ = new VCMGenericEncoder( + external_encoder_, encoder_rate_observer_, internal_source_); current_enc_is_external_ = true; } else { ptr_encoder_ = CreateEncoder(send_codec->codecType); @@ -679,15 +683,18 @@ VCMGenericEncoder* VCMCodecDataBase::CreateEncoder( switch (type) { #ifdef VIDEOCODEC_VP8 case kVideoCodecVP8: - return new VCMGenericEncoder(*(VP8Encoder::Create())); + return new VCMGenericEncoder(VP8Encoder::Create(), encoder_rate_observer_, + false); #endif #ifdef VIDEOCODEC_VP9 case kVideoCodecVP9: - return new VCMGenericEncoder(*(VP9Encoder::Create())); + return new VCMGenericEncoder(VP9Encoder::Create(), encoder_rate_observer_, + false); #endif #ifdef VIDEOCODEC_I420 case kVideoCodecI420: - return new VCMGenericEncoder(*(new I420Encoder)); + return new VCMGenericEncoder(new I420Encoder(), encoder_rate_observer_, + false); #endif default: LOG(LS_WARNING) << "No internal encoder of this type exists."; @@ -698,9 +705,8 @@ VCMGenericEncoder* VCMCodecDataBase::CreateEncoder( void VCMCodecDataBase::DeleteEncoder() { if (ptr_encoder_) { ptr_encoder_->Release(); - if (!current_enc_is_external_) { - delete &ptr_encoder_->_encoder; - } + if (!current_enc_is_external_) + delete ptr_encoder_->encoder_; delete ptr_encoder_; ptr_encoder_ = NULL; } diff --git a/webrtc/modules/video_coding/main/source/codec_database.h b/webrtc/modules/video_coding/main/source/codec_database.h index a31decb63f..1aa8f4deb1 100644 --- a/webrtc/modules/video_coding/main/source/codec_database.h +++ b/webrtc/modules/video_coding/main/source/codec_database.h @@ -46,7 +46,7 @@ struct VCMExtDecoderMapItem { class VCMCodecDataBase { public: - VCMCodecDataBase(); + explicit VCMCodecDataBase(VideoEncoderRateObserver* encoder_rate_observer); ~VCMCodecDataBase(); // Sender Side @@ -180,6 +180,7 @@ class VCMCodecDataBase { uint8_t external_payload_type_; VideoEncoder* external_encoder_; bool internal_source_; + VideoEncoderRateObserver* const encoder_rate_observer_; VCMGenericEncoder* ptr_encoder_; VCMGenericDecoder* ptr_decoder_; bool current_dec_is_external_; diff --git a/webrtc/modules/video_coding/main/source/generic_encoder.cc b/webrtc/modules/video_coding/main/source/generic_encoder.cc index d01fbf4f5e..208f925563 100644 --- a/webrtc/modules/video_coding/main/source/generic_encoder.cc +++ b/webrtc/modules/video_coding/main/source/generic_encoder.cc @@ -55,18 +55,18 @@ void CopyCodecSpecific(const CodecSpecificInfo* info, RTPVideoHeader** rtp) { //#define DEBUG_ENCODER_BIT_STREAM -VCMGenericEncoder::VCMGenericEncoder(VideoEncoder& encoder, bool internalSource /*= false*/) -: -_encoder(encoder), -_codecType(kVideoCodecUnknown), -_VCMencodedFrameCallback(NULL), -_bitRate(0), -_frameRate(0), -_internalSource(internalSource) -{ +VCMGenericEncoder::VCMGenericEncoder(VideoEncoder* encoder, + VideoEncoderRateObserver* rate_observer, + bool internalSource) + : encoder_(encoder), + rate_observer_(rate_observer), + _codecType(kVideoCodecUnknown), + _VCMencodedFrameCallback(NULL), + _bitRate(0), + _frameRate(0), + _internalSource(internalSource) { } - VCMGenericEncoder::~VCMGenericEncoder() { } @@ -76,7 +76,7 @@ int32_t VCMGenericEncoder::Release() _bitRate = 0; _frameRate = 0; _VCMencodedFrameCallback = NULL; - return _encoder.Release(); + return encoder_->Release(); } int32_t @@ -87,7 +87,7 @@ VCMGenericEncoder::InitEncode(const VideoCodec* settings, _bitRate = settings->startBitrate * 1000; _frameRate = settings->maxFramerate; _codecType = settings->codecType; - if (_encoder.InitEncode(settings, numberOfCores, maxPayloadSize) != 0) { + if (encoder_->InitEncode(settings, numberOfCores, maxPayloadSize) != 0) { LOG(LS_ERROR) << "Failed to initialize the encoder associated with " "payload name: " << settings->plName; return -1; @@ -102,33 +102,35 @@ VCMGenericEncoder::Encode(const I420VideoFrame& inputFrame, std::vector video_frame_types(frameTypes.size(), kDeltaFrame); VCMEncodedFrame::ConvertFrameTypes(frameTypes, &video_frame_types); - return _encoder.Encode(inputFrame, codecSpecificInfo, &video_frame_types); + return encoder_->Encode(inputFrame, codecSpecificInfo, &video_frame_types); } int32_t VCMGenericEncoder::SetChannelParameters(int32_t packetLoss, int64_t rtt) { - return _encoder.SetChannelParameters(packetLoss, rtt); + return encoder_->SetChannelParameters(packetLoss, rtt); } int32_t VCMGenericEncoder::SetRates(uint32_t newBitRate, uint32_t frameRate) { uint32_t target_bitrate_kbps = (newBitRate + 500) / 1000; - int32_t ret = _encoder.SetRates(target_bitrate_kbps, frameRate); + int32_t ret = encoder_->SetRates(target_bitrate_kbps, frameRate); if (ret < 0) { return ret; } _bitRate = newBitRate; _frameRate = frameRate; + if (rate_observer_ != nullptr) + rate_observer_->OnSetRates(newBitRate, frameRate); return VCM_OK; } int32_t VCMGenericEncoder::CodecConfigParameters(uint8_t* buffer, int32_t size) { - int32_t ret = _encoder.CodecConfigParameters(buffer, size); + int32_t ret = encoder_->CodecConfigParameters(buffer, size); if (ret < 0) { return ret; @@ -149,7 +151,7 @@ uint32_t VCMGenericEncoder::FrameRate() const int32_t VCMGenericEncoder::SetPeriodicKeyFrames(bool enable) { - return _encoder.SetPeriodicKeyFrames(enable); + return encoder_->SetPeriodicKeyFrames(enable); } int32_t VCMGenericEncoder::RequestFrame( @@ -158,7 +160,7 @@ int32_t VCMGenericEncoder::RequestFrame( std::vector video_frame_types(frame_types.size(), kDeltaFrame); VCMEncodedFrame::ConvertFrameTypes(frame_types, &video_frame_types); - return _encoder.Encode(image, NULL, &video_frame_types); + return encoder_->Encode(image, NULL, &video_frame_types); } int32_t @@ -166,7 +168,7 @@ VCMGenericEncoder::RegisterEncodeCallback(VCMEncodedFrameCallback* VCMencodedFra { _VCMencodedFrameCallback = VCMencodedFrameCallback; _VCMencodedFrameCallback->SetInternalSource(_internalSource); - return _encoder.RegisterEncodeCompleteCallback(_VCMencodedFrameCallback); + return encoder_->RegisterEncodeCompleteCallback(_VCMencodedFrameCallback); } bool diff --git a/webrtc/modules/video_coding/main/source/generic_encoder.h b/webrtc/modules/video_coding/main/source/generic_encoder.h index 70569fa7dc..e547a473ca 100644 --- a/webrtc/modules/video_coding/main/source/generic_encoder.h +++ b/webrtc/modules/video_coding/main/source/generic_encoder.h @@ -12,6 +12,7 @@ #define WEBRTC_MODULES_VIDEO_CODING_GENERIC_ENCODER_H_ #include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h" +#include "webrtc/modules/video_coding/main/interface/video_coding_defines.h" #include @@ -73,7 +74,9 @@ class VCMGenericEncoder { friend class VCMCodecDataBase; public: - VCMGenericEncoder(VideoEncoder& encoder, bool internalSource = false); + VCMGenericEncoder(VideoEncoder* encoder, + VideoEncoderRateObserver* rate_observer, + bool internalSource); ~VCMGenericEncoder(); /** * Free encoder memory @@ -127,7 +130,8 @@ public: bool InternalSource() const; private: - VideoEncoder& _encoder; + VideoEncoder* const encoder_; + VideoEncoderRateObserver* const rate_observer_; VideoCodecType _codecType; VCMEncodedFrameCallback* _VCMencodedFrameCallback; uint32_t _bitRate; diff --git a/webrtc/modules/video_coding/main/source/video_coding_impl.cc b/webrtc/modules/video_coding/main/source/video_coding_impl.cc index 89eb29bf5b..eab45f0dc7 100644 --- a/webrtc/modules/video_coding/main/source/video_coding_impl.cc +++ b/webrtc/modules/video_coding/main/source/video_coding_impl.cc @@ -73,9 +73,12 @@ class VideoCodingModuleImpl : public VideoCodingModule { public: VideoCodingModuleImpl(Clock* clock, EventFactory* event_factory, - bool owns_event_factory) + bool owns_event_factory, + VideoEncoderRateObserver* encoder_rate_observer) : VideoCodingModule(), - sender_(new vcm::VideoSender(clock, &post_encode_callback_)), + sender_(new vcm::VideoSender(clock, + &post_encode_callback_, + encoder_rate_observer)), receiver_(new vcm::VideoReceiver(clock, event_factory)), own_event_factory_(owns_event_factory ? event_factory : NULL) {} @@ -383,16 +386,19 @@ int32_t VideoCodingModule::Codec(VideoCodecType codecType, VideoCodec* codec) { return VCMCodecDataBase::Codec(codecType, codec) ? 0 : -1; } -VideoCodingModule* VideoCodingModule::Create() { - return new VideoCodingModuleImpl( - Clock::GetRealTimeClock(), new EventFactoryImpl, true); +VideoCodingModule* VideoCodingModule::Create( + VideoEncoderRateObserver* encoder_rate_observer) { + return new VideoCodingModuleImpl(Clock::GetRealTimeClock(), + new EventFactoryImpl, true, + encoder_rate_observer); } -VideoCodingModule* VideoCodingModule::Create(Clock* clock, - EventFactory* event_factory) { +VideoCodingModule* VideoCodingModule::Create( + Clock* clock, + EventFactory* event_factory) { assert(clock); assert(event_factory); - return new VideoCodingModuleImpl(clock, event_factory, false); + return new VideoCodingModuleImpl(clock, event_factory, false, nullptr); } void VideoCodingModule::Destroy(VideoCodingModule* module) { diff --git a/webrtc/modules/video_coding/main/source/video_coding_impl.h b/webrtc/modules/video_coding/main/source/video_coding_impl.h index ed38bd5e8e..8faa1e4c40 100644 --- a/webrtc/modules/video_coding/main/source/video_coding_impl.h +++ b/webrtc/modules/video_coding/main/source/video_coding_impl.h @@ -56,7 +56,9 @@ class VideoSender { public: typedef VideoCodingModule::SenderNackMode SenderNackMode; - VideoSender(Clock* clock, EncodedImageCallback* post_encode_callback); + VideoSender(Clock* clock, + EncodedImageCallback* post_encode_callback, + VideoEncoderRateObserver* encoder_rate_observer); ~VideoSender(); diff --git a/webrtc/modules/video_coding/main/source/video_receiver.cc b/webrtc/modules/video_coding/main/source/video_receiver.cc index 3e20ed3757..4411e115fe 100644 --- a/webrtc/modules/video_coding/main/source/video_receiver.cc +++ b/webrtc/modules/video_coding/main/source/video_receiver.cc @@ -46,7 +46,7 @@ VideoReceiver::VideoReceiver(Clock* clock, EventFactory* event_factory) _scheduleKeyRequest(false), max_nack_list_size_(0), pre_decode_image_callback_(NULL), - _codecDataBase(), + _codecDataBase(NULL), _receiveStatsTimer(1000, clock_), _retransmissionTimer(10, clock_), _keyRequestTimer(500, clock_) { diff --git a/webrtc/modules/video_coding/main/source/video_sender.cc b/webrtc/modules/video_coding/main/source/video_sender.cc index 24240e2ed5..a805045c32 100644 --- a/webrtc/modules/video_coding/main/source/video_sender.cc +++ b/webrtc/modules/video_coding/main/source/video_sender.cc @@ -60,7 +60,8 @@ class DebugRecorder { }; VideoSender::VideoSender(Clock* clock, - EncodedImageCallback* post_encode_callback) + EncodedImageCallback* post_encode_callback, + VideoEncoderRateObserver* encoder_rate_observer) : clock_(clock), recorder_(new DebugRecorder()), process_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), @@ -70,7 +71,7 @@ VideoSender::VideoSender(Clock* clock, _nextFrameTypes(1, kVideoFrameDelta), _mediaOpt(clock_), _sendStatsCallback(NULL), - _codecDataBase(), + _codecDataBase(encoder_rate_observer), frame_dropper_enabled_(true), _sendStatsTimer(1000, clock_), current_codec_(), diff --git a/webrtc/modules/video_coding/main/source/video_sender_unittest.cc b/webrtc/modules/video_coding/main/source/video_sender_unittest.cc index c9d6648016..4be71ab777 100644 --- a/webrtc/modules/video_coding/main/source/video_sender_unittest.cc +++ b/webrtc/modules/video_coding/main/source/video_sender_unittest.cc @@ -172,7 +172,7 @@ class TestVideoSender : public ::testing::Test { TestVideoSender() : clock_(1000), packetization_callback_(&clock_) {} virtual void SetUp() OVERRIDE { - sender_.reset(new VideoSender(&clock_, &post_encode_callback_)); + sender_.reset(new VideoSender(&clock_, &post_encode_callback_, nullptr)); EXPECT_EQ(0, sender_->InitializeSender()); EXPECT_EQ(0, sender_->RegisterTransportCallback(&packetization_callback_)); } diff --git a/webrtc/modules/video_coding/main/test/codec_database_test.cc b/webrtc/modules/video_coding/main/test/codec_database_test.cc index ca269b3370..07342de426 100644 --- a/webrtc/modules/video_coding/main/test/codec_database_test.cc +++ b/webrtc/modules/video_coding/main/test/codec_database_test.cc @@ -29,7 +29,7 @@ using namespace webrtc; int CodecDataBaseTest::RunTest(CmdArgs& args) { - VideoCodingModule* vcm = VideoCodingModule::Create(); + VideoCodingModule* vcm = VideoCodingModule::Create(nullptr); CodecDataBaseTest* cdbt = new CodecDataBaseTest(vcm); cdbt->Perform(args); VideoCodingModule::Destroy(vcm); diff --git a/webrtc/modules/video_coding/main/test/media_opt_test.cc b/webrtc/modules/video_coding/main/test/media_opt_test.cc index f3b1cf05a0..4d4ff4c083 100644 --- a/webrtc/modules/video_coding/main/test/media_opt_test.cc +++ b/webrtc/modules/video_coding/main/test/media_opt_test.cc @@ -32,7 +32,7 @@ int MediaOptTest::RunTest(int testNum, CmdArgs& args) Trace::CreateTrace(); Trace::SetTraceFile((test::OutputPath() + "mediaOptTestTrace.txt").c_str()); Trace::set_level_filter(webrtc::kTraceAll); - VideoCodingModule* vcm = VideoCodingModule::Create(); + VideoCodingModule* vcm = VideoCodingModule::Create(nullptr); Clock* clock = Clock::GetRealTimeClock(); MediaOptTest* mot = new MediaOptTest(vcm, clock); if (testNum == 0) diff --git a/webrtc/modules/video_coding/main/test/mt_rx_tx_test.cc b/webrtc/modules/video_coding/main/test/mt_rx_tx_test.cc index d7beb46c2b..acbc5c91cf 100644 --- a/webrtc/modules/video_coding/main/test/mt_rx_tx_test.cc +++ b/webrtc/modules/video_coding/main/test/mt_rx_tx_test.cc @@ -145,7 +145,7 @@ int MTRxTxTest(CmdArgs& args) printf("Cannot read file %s.\n", outname.c_str()); return -1; } - VideoCodingModule* vcm = VideoCodingModule::Create(); + VideoCodingModule* vcm = VideoCodingModule::Create(nullptr); RtpDataCallback dataCallback(vcm); RTPSendCompleteCallback* outgoingTransport = diff --git a/webrtc/video/end_to_end_tests.cc b/webrtc/video/end_to_end_tests.cc index 07e3fdc917..fe2a6902da 100644 --- a/webrtc/video/end_to_end_tests.cc +++ b/webrtc/video/end_to_end_tests.cc @@ -1566,6 +1566,64 @@ void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs, RunBaseTest(&test); } +TEST_F(EndToEndTest, ReportsSetEncoderRates) { + class EncoderRateStatsTest : public test::EndToEndTest, + public test::FakeEncoder { + public: + EncoderRateStatsTest() + : EndToEndTest(kDefaultTimeoutMs), + FakeEncoder(Clock::GetRealTimeClock()) {} + + virtual void OnStreamsCreated( + VideoSendStream* send_stream, + const std::vector& receive_streams) override { + send_stream_ = send_stream; + } + + virtual void ModifyConfigs( + VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { + send_config->encoder_settings.encoder = this; + } + + int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override { + // Make sure not to trigger on any default zero bitrates. + if (new_target_bitrate == 0) + return 0; + CriticalSectionScoped lock(crit_.get()); + bitrate_kbps_ = new_target_bitrate; + observation_complete_->Set(); + return 0; + } + + void PerformTest() override { + ASSERT_EQ(kEventSignaled, Wait()) + << "Timed out while waiting for encoder SetRates() call."; + // Wait for GetStats to report a corresponding bitrate. + for (unsigned int i = 0; i < kDefaultTimeoutMs; ++i) { + VideoSendStream::Stats stats = send_stream_->GetStats(); + { + CriticalSectionScoped lock(crit_.get()); + if ((stats.target_media_bitrate_bps + 500) / 1000 == + static_cast(bitrate_kbps_)) { + return; + } + } + SleepMs(1); + } + FAIL() + << "Timed out waiting for stats reporting the currently set bitrate."; + } + + private: + VideoSendStream* send_stream_; + uint32_t bitrate_kbps_ GUARDED_BY(crit_); + } test; + + RunBaseTest(&test); +} + TEST_F(EndToEndTest, GetStats) { static const int kStartBitrateBps = 3000000; class StatsObserver : public test::EndToEndTest, public I420FrameCallback { diff --git a/webrtc/video/send_statistics_proxy.cc b/webrtc/video/send_statistics_proxy.cc index 7c148b7dac..33255f9b92 100644 --- a/webrtc/video/send_statistics_proxy.cc +++ b/webrtc/video/send_statistics_proxy.cc @@ -95,6 +95,11 @@ VideoSendStream::StreamStats* SendStatisticsProxy::GetStatsEntry( return &stats_.substreams[ssrc]; // Insert new entry and return ptr. } +void SendStatisticsProxy::OnSetRates(uint32_t bitrate_bps, int framerate) { + CriticalSectionScoped lock(crit_.get()); + stats_.target_media_bitrate_bps = bitrate_bps; +} + void SendStatisticsProxy::OnSendEncodedImage( const EncodedImage& encoded_image, const RTPVideoHeader* rtp_video_header) { diff --git a/webrtc/video/send_statistics_proxy.h b/webrtc/video/send_statistics_proxy.h index 540ee3277e..f33df8dac1 100644 --- a/webrtc/video/send_statistics_proxy.h +++ b/webrtc/video/send_statistics_proxy.h @@ -16,6 +16,7 @@ #include "webrtc/base/thread_annotations.h" #include "webrtc/common_types.h" #include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h" +#include "webrtc/modules/video_coding/main/interface/video_coding_defines.h" #include "webrtc/system_wrappers/interface/clock.h" #include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/video_engine/include/vie_base.h" @@ -35,6 +36,7 @@ class SendStatisticsProxy : public CpuOveruseMetricsObserver, public FrameCountObserver, public ViEEncoderObserver, public ViECaptureObserver, + public VideoEncoderRateObserver, public SendSideDelayObserver { public: static const int kStatsTimeoutMs; @@ -47,6 +49,9 @@ class SendStatisticsProxy : public CpuOveruseMetricsObserver, virtual void OnSendEncodedImage(const EncodedImage& encoded_image, const RTPVideoHeader* rtp_video_header); + // From VideoEncoderRateObserver. + void OnSetRates(uint32_t bitrate_bps, int framerate) override; + protected: // From CpuOveruseMetricsObserver. void CpuOveruseMetricsUpdated(const CpuOveruseMetrics& metrics) OVERRIDE; diff --git a/webrtc/video_engine/vie_channel.cc b/webrtc/video_engine/vie_channel.cc index f857298575..f95889445f 100644 --- a/webrtc/video_engine/vie_channel.cc +++ b/webrtc/video_engine/vie_channel.cc @@ -102,7 +102,7 @@ ViEChannel::ViEChannel(int32_t channel_id, rtp_rtcp_cs_(CriticalSectionWrapper::CreateCriticalSection()), send_payload_router_(new PayloadRouter()), vcm_protection_callback_(new ViEChannelProtectionCallback(this)), - vcm_(VideoCodingModule::Create()), + vcm_(VideoCodingModule::Create(nullptr)), vie_receiver_(channel_id, vcm_, remote_bitrate_estimator, this), vie_sender_(channel_id), vie_sync_(vcm_, this), diff --git a/webrtc/video_engine/vie_encoder.cc b/webrtc/video_engine/vie_encoder.cc index 9c105ee8e6..0b8ce9a1bb 100644 --- a/webrtc/video_engine/vie_encoder.cc +++ b/webrtc/video_engine/vie_encoder.cc @@ -136,7 +136,7 @@ ViEEncoder::ViEEncoder(int32_t channel_id, : channel_id_(channel_id), number_of_cores_(number_of_cores), disable_default_encoder_(disable_default_encoder), - vcm_(*webrtc::VideoCodingModule::Create()), + vcm_(*webrtc::VideoCodingModule::Create(this)), vpm_(*webrtc::VideoProcessingModule::Create(ViEModuleId(-1, channel_id))), send_payload_router_(NULL), vcm_protection_callback_(NULL), @@ -705,6 +705,12 @@ void ViEEncoder::SetSenderBufferingMode(int target_delay_ms) { } } +void ViEEncoder::OnSetRates(uint32_t bitrate_bps, int framerate) { + CriticalSectionScoped cs(callback_cs_.get()); + if (send_statistics_proxy_ != nullptr) + send_statistics_proxy_->OnSetRates(bitrate_bps, framerate); +} + int32_t ViEEncoder::SendData( const uint8_t payload_type, const EncodedImage& encoded_image, @@ -712,8 +718,10 @@ int32_t ViEEncoder::SendData( const RTPVideoHeader* rtp_video_hdr) { DCHECK(send_payload_router_ != NULL); - if (send_statistics_proxy_ != NULL) { - send_statistics_proxy_->OnSendEncodedImage(encoded_image, rtp_video_hdr); + { + CriticalSectionScoped cs(callback_cs_.get()); + if (send_statistics_proxy_ != NULL) + send_statistics_proxy_->OnSendEncodedImage(encoded_image, rtp_video_hdr); } return send_payload_router_->RoutePayload( @@ -959,6 +967,7 @@ void ViEEncoder::DeRegisterPostEncodeImageCallback() { void ViEEncoder::RegisterSendStatisticsProxy( SendStatisticsProxy* send_statistics_proxy) { + CriticalSectionScoped cs(callback_cs_.get()); send_statistics_proxy_ = send_statistics_proxy; } diff --git a/webrtc/video_engine/vie_encoder.h b/webrtc/video_engine/vie_encoder.h index 2aab5f6830..de264cadf3 100644 --- a/webrtc/video_engine/vie_encoder.h +++ b/webrtc/video_engine/vie_encoder.h @@ -46,6 +46,7 @@ class ViEPacedSenderCallback; class ViEEncoder : public RtcpIntraFrameObserver, + public VideoEncoderRateObserver, public VCMPacketizationCallback, public VCMSendStatisticsCallback, public ViEFrameCallback { @@ -130,6 +131,9 @@ class ViEEncoder // Buffering mode. void SetSenderBufferingMode(int target_delay_ms); + // Implements VideoEncoderRateObserver. + void OnSetRates(uint32_t bitrate_bps, int framerate) override; + // Implements VCMPacketizationCallback. virtual int32_t SendData(uint8_t payload_type, const EncodedImage& encoded_image, @@ -243,7 +247,7 @@ class ViEEncoder I420FrameCallback* pre_encode_callback_ GUARDED_BY(callback_cs_); const int64_t start_ms_; - SendStatisticsProxy* send_statistics_proxy_; + SendStatisticsProxy* send_statistics_proxy_ GUARDED_BY(callback_cs_); }; } // namespace webrtc diff --git a/webrtc/video_send_stream.h b/webrtc/video_send_stream.h index eb6dfe679f..c55d9e3e5c 100644 --- a/webrtc/video_send_stream.h +++ b/webrtc/video_send_stream.h @@ -57,12 +57,14 @@ class VideoSendStream { encode_frame_rate(0), avg_encode_time_ms(0), encode_usage_percent(0), + target_media_bitrate_bps(0), media_bitrate_bps(0), suspended(false) {} int input_frame_rate; int encode_frame_rate; int avg_encode_time_ms; int encode_usage_percent; + int target_media_bitrate_bps; int media_bitrate_bps; bool suspended; std::map substreams;