diff --git a/talk/media/webrtc/webrtcvideoengine2.cc b/talk/media/webrtc/webrtcvideoengine2.cc index 723ef1dd83..6593b2a9e2 100644 --- a/talk/media/webrtc/webrtcvideoengine2.cc +++ b/talk/media/webrtc/webrtcvideoengine2.cc @@ -197,22 +197,15 @@ WebRtcVideoEncoderFactory2::~WebRtcVideoEncoderFactory2() { class DefaultVideoEncoderFactory : public WebRtcVideoEncoderFactory2 { public: - virtual bool CreateEncoderSettings( - webrtc::VideoSendStream::Config::EncoderSettings* encoder_settings, - const VideoOptions& options, + virtual std::vector CreateVideoStreams( const VideoCodec& codec, + const VideoOptions& options, size_t num_streams) OVERRIDE { + assert(SupportsCodec(codec)); if (num_streams != 1) { LOG(LS_ERROR) << "Unsupported number of streams: " << num_streams; - return false; + return std::vector(); } - if (!SupportsCodec(codec)) { - LOG(LS_ERROR) << "Can't create encoder settings for unsupported codec: '" - << codec.name << "'"; - return false; - } - - *encoder_settings = webrtc::VideoSendStream::Config::EncoderSettings(); webrtc::VideoStream stream; stream.width = codec.width; @@ -230,13 +223,16 @@ class DefaultVideoEncoderFactory : public WebRtcVideoEncoderFactory2 { int max_qp = 56; codec.GetParam(kCodecParamMaxQuantization, &max_qp); stream.max_qp = max_qp; - encoder_settings->streams.push_back(stream); + std::vector streams; + streams.push_back(stream); + return streams; + } - encoder_settings->encoder = webrtc::VP8Encoder::Create(); - encoder_settings->payload_type = kDefaultVideoCodecPref.payload_type; - encoder_settings->payload_name = kDefaultVideoCodecPref.name; - - return true; + virtual webrtc::VideoEncoder* CreateVideoEncoder( + const VideoCodec& codec, + const VideoOptions& options) OVERRIDE { + assert(SupportsCodec(codec)); + return webrtc::VP8Encoder::Create(); } virtual bool SupportsCodec(const VideoCodec& codec) OVERRIDE { @@ -471,11 +467,11 @@ WebRtcVideoEncoderFactory2* WebRtcVideoEngine2::GetVideoEncoderFactory() const { return default_video_encoder_factory_.get(); } -// Thin map between cricket::VideoFrame and an existing webrtc::I420VideoFrame +// Thin map between VideoFrame and an existing webrtc::I420VideoFrame // to avoid having to copy the rendered VideoFrame prematurely. // This implementation is only safe to use in a const context and should never // be written to. -class WebRtcVideoRenderFrame : public cricket::VideoFrame { +class WebRtcVideoRenderFrame : public VideoFrame { public: explicit WebRtcVideoRenderFrame(const webrtc::I420VideoFrame* frame) : frame_(frame) {} @@ -924,14 +920,17 @@ bool WebRtcVideoChannel2::AddSendStream(const StreamParams& sp) { // CreateEncoderSettings will allocate a suitable VideoEncoder instance // matching current settings. - if (!encoder_factory_->CreateEncoderSettings(&config.encoder_settings, - options_, - codec_settings.codec, - config.rtp.ssrcs.size())) { - LOG(LS_ERROR) << "Failed to create suitable encoder settings."; + std::vector video_streams = + encoder_factory_->CreateVideoStreams( + codec_settings.codec, options_, config.rtp.ssrcs.size()); + if (video_streams.empty()) { return false; } + config.encoder_settings.encoder = + encoder_factory_->CreateVideoEncoder(codec_settings.codec, options_); + config.encoder_settings.payload_name = codec_settings.codec.name; + config.encoder_settings.payload_type = codec_settings.codec.id; config.rtp.c_name = sp.cname; config.rtp.fec = codec_settings.fec; if (!config.rtp.rtx.ssrcs.empty()) { @@ -942,7 +941,12 @@ bool WebRtcVideoChannel2::AddSendStream(const StreamParams& sp) { config.rtp.max_packet_size = kVideoMtu; WebRtcVideoSendStream* stream = - new WebRtcVideoSendStream(call_.get(), config, encoder_factory_); + new WebRtcVideoSendStream(call_.get(), + config, + options_, + codec_settings.codec, + video_streams, + encoder_factory_); send_streams_[ssrc] = stream; if (rtcp_receiver_report_ssrc_ == kDefaultRtcpReceiverReportSsrc) { @@ -1339,21 +1343,35 @@ void WebRtcVideoChannel2::SetCodecForAllSendStreams( } } +WebRtcVideoChannel2::WebRtcVideoSendStream::VideoSendStreamParameters:: + VideoSendStreamParameters( + const webrtc::VideoSendStream::Config& config, + const VideoOptions& options, + const VideoCodec& codec, + const std::vector& video_streams) + : config(config), + options(options), + codec(codec), + video_streams(video_streams) { +} + WebRtcVideoChannel2::WebRtcVideoSendStream::WebRtcVideoSendStream( webrtc::Call* call, const webrtc::VideoSendStream::Config& config, + const VideoOptions& options, + const VideoCodec& codec, + const std::vector& video_streams, WebRtcVideoEncoderFactory2* encoder_factory) : call_(call), - config_(config), + parameters_(config, options, codec, video_streams), encoder_factory_(encoder_factory), capturer_(NULL), stream_(NULL), sending_(false), muted_(false), - format_(static_cast(config.encoder_settings.streams.back().height), - static_cast(config.encoder_settings.streams.back().width), - VideoFormat::FpsToInterval( - config.encoder_settings.streams.back().max_framerate), + format_(static_cast(video_streams.back().height), + static_cast(video_streams.back().width), + VideoFormat::FpsToInterval(video_streams.back().max_framerate), FOURCC_I420) { RecreateWebRtcStream(); } @@ -1361,7 +1379,7 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::WebRtcVideoSendStream( WebRtcVideoChannel2::WebRtcVideoSendStream::~WebRtcVideoSendStream() { DisconnectCapturer(); call_->DestroyVideoSendStream(stream_); - delete config_.encoder_settings.encoder; + delete parameters_.config.encoder_settings.encoder; } static void SetWebRtcFrameToBlack(webrtc::I420VideoFrame* video_frame) { @@ -1428,8 +1446,8 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::InputFrame( } LOG(LS_VERBOSE) << "SwapFrame: " << video_frame_.width() << "x" << video_frame_.height() << " -> (codec) " - << config_.encoder_settings.streams.back().width << "x" - << config_.encoder_settings.streams.back().height; + << parameters_.video_streams.back().width << "x" + << parameters_.video_streams.back().height; stream_->Input()->SwapFrame(&video_frame_); } @@ -1480,10 +1498,10 @@ bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoFormat( if (format.width == 0 && format.height == 0) { LOG(LS_INFO) << "0x0 resolution selected. Captured frames will be dropped for ssrc: " - << config_.rtp.ssrcs[0] << "."; + << parameters_.config.rtp.ssrcs[0] << "."; } else { // TODO(pbos): Fix me, this only affects the last stream! - config_.encoder_settings.streams.back().max_framerate = + parameters_.video_streams.back().max_framerate = VideoFormat::IntervalToFps(format.interval); SetDimensions(format.width, format.height); } @@ -1513,44 +1531,46 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodec( const VideoOptions& options, const VideoCodecSettings& codec) { talk_base::CritScope cs(&lock_); - webrtc::VideoEncoder* old_encoder = config_.encoder_settings.encoder; - if (!encoder_factory_->CreateEncoderSettings( - &config_.encoder_settings, - options, - codec.codec, - config_.encoder_settings.streams.size())) { - LOG(LS_ERROR) << "Could not create encoder settings for: '" - << codec.codec.name - << "'. This is most definitely a bug as SetCodec should only " - "receive codecs which the encoder factory claims to " - "support."; + + std::vector video_streams = + encoder_factory_->CreateVideoStreams( + codec.codec, options, parameters_.video_streams.size()); + if (video_streams.empty()) { return; } + parameters_.video_streams = video_streams; format_ = VideoFormat(codec.codec.width, codec.codec.height, VideoFormat::FpsToInterval(30), FOURCC_I420); - config_.rtp.fec = codec.fec; + + webrtc::VideoEncoder* old_encoder = + parameters_.config.encoder_settings.encoder; + parameters_.config.encoder_settings.encoder = + encoder_factory_->CreateVideoEncoder(codec.codec, options); + parameters_.config.rtp.fec = codec.fec; // TODO(pbos): Should changing RTX payload type be allowed? + parameters_.codec = codec.codec; + parameters_.options = options; RecreateWebRtcStream(); delete old_encoder; } void WebRtcVideoChannel2::WebRtcVideoSendStream::SetDimensions(int width, - int height) { - assert(!config_.encoder_settings.streams.empty()); + int height) { + assert(!parameters_.video_streams.empty()); LOG(LS_VERBOSE) << "SetDimensions: " << width << "x" << height; - if (config_.encoder_settings.streams.back().width == width && - config_.encoder_settings.streams.back().height == height) { + if (parameters_.video_streams.back().width == width && + parameters_.video_streams.back().height == height) { return; } // TODO(pbos): Fix me, this only affects the last stream! - config_.encoder_settings.streams.back().width = width; - config_.encoder_settings.streams.back().height = height; - // TODO(pbos): Last parameter shouldn't always be NULL? - if (!stream_->ReconfigureVideoEncoder(config_.encoder_settings.streams, - NULL)) { + parameters_.video_streams.back().width = width; + parameters_.video_streams.back().height = height; + + // TODO(pbos): Wire up encoder_parameters, webrtc:3424. + if (!stream_->ReconfigureVideoEncoder(parameters_.video_streams, NULL)) { LOG(LS_WARNING) << "Failed to reconfigure video encoder for dimensions: " << width << "x" << height; return; @@ -1573,7 +1593,10 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::RecreateWebRtcStream() { if (stream_ != NULL) { call_->DestroyVideoSendStream(stream_); } - stream_ = call_->CreateVideoSendStream(config_); + + // TODO(pbos): Wire up encoder_parameters, webrtc:3424. + stream_ = call_->CreateVideoSendStream( + parameters_.config, parameters_.video_streams, NULL); if (sending_) { stream_->Start(); } diff --git a/talk/media/webrtc/webrtcvideoengine2.h b/talk/media/webrtc/webrtcvideoengine2.h index 10a1608484..4287d2826e 100644 --- a/talk/media/webrtc/webrtcvideoengine2.h +++ b/talk/media/webrtc/webrtcvideoengine2.h @@ -83,11 +83,15 @@ class WebRtcVideoChannel2; class WebRtcVideoEncoderFactory2 { public: virtual ~WebRtcVideoEncoderFactory2(); - virtual bool CreateEncoderSettings( - webrtc::VideoSendStream::Config::EncoderSettings* encoder_settings, + virtual std::vector CreateVideoStreams( + const VideoCodec& codec, const VideoOptions& options, - const cricket::VideoCodec& codec, size_t num_streams) = 0; + + virtual webrtc::VideoEncoder* CreateVideoEncoder( + const VideoCodec& codec, + const VideoOptions& options) = 0; + virtual bool SupportsCodec(const cricket::VideoCodec& codec) = 0; }; @@ -258,7 +262,7 @@ class WebRtcVideoChannel2 : public talk_base::MessageHandler, struct VideoCodecSettings { VideoCodecSettings(); - cricket::VideoCodec codec; + VideoCodec codec; webrtc::FecConfig fec; int rtx_payload_type; }; @@ -266,8 +270,11 @@ class WebRtcVideoChannel2 : public talk_base::MessageHandler, class WebRtcVideoSendStream : public sigslot::has_slots<> { public: WebRtcVideoSendStream(webrtc::Call* call, - const webrtc::VideoSendStream::Config& config, - WebRtcVideoEncoderFactory2* encoder_factory); + const webrtc::VideoSendStream::Config& config, + const VideoOptions& options, + const VideoCodec& codec, + const std::vector& video_streams, + WebRtcVideoEncoderFactory2* encoder_factory); ~WebRtcVideoSendStream(); void SetCodec(const VideoOptions& options, const VideoCodecSettings& codec); @@ -281,6 +288,25 @@ class WebRtcVideoChannel2 : public talk_base::MessageHandler, void Stop(); private: + // Parameters needed to reconstruct the underlying stream. + // webrtc::VideoSendStream doesn't support setting a lot of options on the + // fly, so when those need to be changed we tear down and reconstruct with + // similar parameters depending on which options changed etc. + struct VideoSendStreamParameters { + VideoSendStreamParameters( + const webrtc::VideoSendStream::Config& config, + const VideoOptions& options, + const VideoCodec& codec, + const std::vector& video_streams); + webrtc::VideoSendStream::Config config; + VideoOptions options; + VideoCodec codec; + // Sent resolutions + bitrates etc. by the underlying VideoSendStream, + // typically changes when setting a new resolution or reconfiguring + // bitrates. + std::vector video_streams; + }; + void RecreateWebRtcStream(); void SetDimensions(int width, int height); @@ -289,7 +315,8 @@ class WebRtcVideoChannel2 : public talk_base::MessageHandler, talk_base::CriticalSection lock_; webrtc::VideoSendStream* stream_ GUARDED_BY(lock_); - webrtc::VideoSendStream::Config config_ GUARDED_BY(lock_); + VideoSendStreamParameters parameters_ GUARDED_BY(lock_); + VideoCapturer* capturer_ GUARDED_BY(lock_); bool sending_ GUARDED_BY(lock_); bool muted_ GUARDED_BY(lock_); diff --git a/talk/media/webrtc/webrtcvideoengine2_unittest.cc b/talk/media/webrtc/webrtcvideoengine2_unittest.cc index bba14555f3..c478b42ca8 100644 --- a/talk/media/webrtc/webrtcvideoengine2_unittest.cc +++ b/talk/media/webrtc/webrtcvideoengine2_unittest.cc @@ -52,12 +52,12 @@ static const uint32 kRtxSsrcs1[] = {4}; namespace cricket { class FakeVideoSendStream : public webrtc::VideoSendStream { public: - explicit FakeVideoSendStream(const webrtc::VideoSendStream::Config& config) - : sending_(false) { - config_ = config; - } + FakeVideoSendStream(const webrtc::VideoSendStream::Config& config, + const std::vector& video_streams) + : sending_(false), config_(config), video_streams_(video_streams) {} webrtc::VideoSendStream::Config GetConfig() { return config_; } + std::vector GetVideoStreams() { return video_streams_; } bool IsSending() { return sending_; } @@ -68,9 +68,8 @@ class FakeVideoSendStream : public webrtc::VideoSendStream { virtual bool ReconfigureVideoEncoder( const std::vector& streams, - void* encoder_specific) OVERRIDE { - // TODO(pbos): Store encoder_specific ptr? - config_.encoder_settings.streams = streams; + const void* encoder_specific) OVERRIDE { + video_streams_ = streams; return true; } @@ -85,6 +84,7 @@ class FakeVideoSendStream : public webrtc::VideoSendStream { bool sending_; webrtc::VideoSendStream::Config config_; + std::vector video_streams_; }; class FakeVideoReceiveStream : public webrtc::VideoReceiveStream { @@ -178,8 +178,11 @@ class FakeCall : public webrtc::Call { } virtual webrtc::VideoSendStream* CreateVideoSendStream( - const webrtc::VideoSendStream::Config& config) OVERRIDE { - FakeVideoSendStream* fake_stream = new FakeVideoSendStream(config); + const webrtc::VideoSendStream::Config& config, + const std::vector& video_streams, + const void* encoder_settings) OVERRIDE { + FakeVideoSendStream* fake_stream = + new FakeVideoSendStream(config, video_streams); video_send_streams_.push_back(fake_stream); return fake_stream; } @@ -515,13 +518,10 @@ class WebRtcVideoChannel2Test : public WebRtcVideoEngine2Test { FakeVideoSendStream* stream = AddSendStream(); - webrtc::VideoSendStream::Config::EncoderSettings encoder_settings = - stream->GetConfig().encoder_settings; - ASSERT_EQ(1u, encoder_settings.streams.size()); - EXPECT_EQ(atoi(min_bitrate), - encoder_settings.streams.back().min_bitrate_bps / 1000); - EXPECT_EQ(atoi(max_bitrate), - encoder_settings.streams.back().max_bitrate_bps / 1000); + std::vector video_streams = stream->GetVideoStreams(); + ASSERT_EQ(1u, video_streams.size()); + EXPECT_EQ(atoi(min_bitrate), video_streams.back().min_bitrate_bps / 1000); + EXPECT_EQ(atoi(max_bitrate), video_streams.back().max_bitrate_bps / 1000); VideoCodec codec; EXPECT_TRUE(channel_->GetSendCodec(&codec)); @@ -556,15 +556,14 @@ TEST_F(WebRtcVideoChannel2Test, DISABLED_StartSendBitrate) { const unsigned int kVideoTargetSendBitrateKbps = 300; const unsigned int kVideoMaxSendBitrateKbps = 2000; FakeVideoSendStream* stream = AddSendStream(); - webrtc::VideoSendStream::Config::EncoderSettings encoder_settings = - stream->GetConfig().encoder_settings; - ASSERT_EQ(1u, encoder_settings.streams.size()); + std::vector video_streams = stream->GetVideoStreams(); + ASSERT_EQ(1u, video_streams.size()); EXPECT_EQ(kVideoMinSendBitrateKbps, - encoder_settings.streams.back().min_bitrate_bps / 1000); + video_streams.back().min_bitrate_bps / 1000); EXPECT_EQ(kVideoTargetSendBitrateKbps, - encoder_settings.streams.back().target_bitrate_bps / 1000); + video_streams.back().target_bitrate_bps / 1000); EXPECT_EQ(kVideoMaxSendBitrateKbps, - encoder_settings.streams.back().max_bitrate_bps / 1000); + video_streams.back().max_bitrate_bps / 1000); #if 0 // TODO(pbos): un-#if VerifyVP8SendCodec(send_channel, kVP8Codec.width, kVP8Codec.height, 0, @@ -925,9 +924,8 @@ TEST_F(WebRtcVideoChannel2Test, SetSendCodecsWithMaxQuantization) { codecs.push_back(kVp8Codec); codecs[0].params[kCodecParamMaxQuantization] = kMaxQuantization; EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - EXPECT_EQ( - static_cast(atoi(kMaxQuantization)), - AddSendStream()->GetConfig().encoder_settings.streams.back().max_qp); + EXPECT_EQ(static_cast(atoi(kMaxQuantization)), + AddSendStream()->GetVideoStreams().back().max_qp); VideoCodec codec; EXPECT_TRUE(channel_->GetSendCodec(&codec)); diff --git a/webrtc/call.h b/webrtc/call.h index 53b17edadb..1771ad8813 100644 --- a/webrtc/call.h +++ b/webrtc/call.h @@ -83,7 +83,9 @@ class Call { virtual VideoSendStream::Config GetDefaultSendConfig() = 0; virtual VideoSendStream* CreateVideoSendStream( - const VideoSendStream::Config& config) = 0; + const VideoSendStream::Config& config, + const std::vector& video_streams, + const void* encoder_settings) = 0; virtual void DestroyVideoSendStream(VideoSendStream* send_stream) = 0; diff --git a/webrtc/test/encoder_settings.cc b/webrtc/test/encoder_settings.cc index d02c29f991..5193be65fb 100644 --- a/webrtc/test/encoder_settings.cc +++ b/webrtc/test/encoder_settings.cc @@ -16,18 +16,14 @@ namespace webrtc { namespace test { -VideoSendStream::Config::EncoderSettings CreateEncoderSettings( - VideoEncoder* encoder, - const char* payload_name, - int payload_type, - size_t num_streams) { +std::vector CreateVideoStreams(size_t num_streams) { assert(num_streams > 0); // Add more streams to the settings above with reasonable values if required. static const size_t kNumSettings = 3; assert(num_streams <= kNumSettings); - VideoStream stream_settings[kNumSettings]; + std::vector stream_settings(kNumSettings); stream_settings[0].width = 320; stream_settings[0].height = 180; @@ -52,28 +48,20 @@ VideoSendStream::Config::EncoderSettings CreateEncoderSettings( stream_settings[2].target_bitrate_bps = stream_settings[2].max_bitrate_bps = 1500000; stream_settings[2].max_qp = 56; - - VideoSendStream::Config::EncoderSettings settings; - - for (size_t i = 0; i < num_streams; ++i) - settings.streams.push_back(stream_settings[i]); - - settings.encoder = encoder; - settings.payload_name = payload_name; - settings.payload_type = payload_type; - return settings; + stream_settings.resize(num_streams); + return stream_settings; } VideoCodec CreateDecoderVideoCodec( - const VideoSendStream::Config::EncoderSettings& settings) { - assert(settings.streams.size() > 0); + const VideoSendStream::Config::EncoderSettings& encoder_settings) { VideoCodec codec; memset(&codec, 0, sizeof(codec)); - codec.plType = settings.payload_type; - strcpy(codec.plName, settings.payload_name.c_str()); + codec.plType = encoder_settings.payload_type; + strcpy(codec.plName, encoder_settings.payload_name.c_str()); codec.codecType = - (settings.payload_name == "VP8" ? kVideoCodecVP8 : kVideoCodecGeneric); + (encoder_settings.payload_name == "VP8" ? kVideoCodecVP8 + : kVideoCodecGeneric); if (codec.codecType == kVideoCodecVP8) { codec.codecSpecific.VP8.resilience = kResilientStream; @@ -85,33 +73,9 @@ VideoCodec CreateDecoderVideoCodec( codec.codecSpecific.VP8.keyFrameInterval = 3000; } - codec.minBitrate = settings.streams[0].min_bitrate_bps / 1000; - for (size_t i = 0; i < settings.streams.size(); ++i) { - const VideoStream& stream = settings.streams[i]; - if (stream.width > codec.width) - codec.width = static_cast(stream.width); - if (stream.height > codec.height) - codec.height = static_cast(stream.height); - if (static_cast(stream.min_bitrate_bps / 1000) < - codec.minBitrate) - codec.minBitrate = - static_cast(stream.min_bitrate_bps / 1000); - codec.maxBitrate += stream.max_bitrate_bps / 1000; - if (static_cast(stream.max_qp) > codec.qpMax) - codec.qpMax = static_cast(stream.max_qp); - } - - if (codec.minBitrate < kViEMinCodecBitrate) - codec.minBitrate = kViEMinCodecBitrate; - if (codec.maxBitrate < kViEMinCodecBitrate) - codec.maxBitrate = kViEMinCodecBitrate; - - codec.startBitrate = 300; - - if (codec.startBitrate < codec.minBitrate) - codec.startBitrate = codec.minBitrate; - if (codec.startBitrate > codec.maxBitrate) - codec.startBitrate = codec.maxBitrate; + codec.width = 320; + codec.height = 180; + codec.startBitrate = codec.minBitrate = codec.maxBitrate = 300; return codec; } diff --git a/webrtc/test/encoder_settings.h b/webrtc/test/encoder_settings.h index 1d8e355aba..ea2be97742 100644 --- a/webrtc/test/encoder_settings.h +++ b/webrtc/test/encoder_settings.h @@ -14,14 +14,10 @@ namespace webrtc { namespace test { -VideoSendStream::Config::EncoderSettings CreateEncoderSettings( - VideoEncoder* encoder, - const char* payload_name, - int payload_type, - size_t num_streams); +std::vector CreateVideoStreams(size_t num_streams); VideoCodec CreateDecoderVideoCodec( - const VideoSendStream::Config::EncoderSettings& settings); + const VideoSendStream::Config::EncoderSettings& encoder_settings); } // namespace test } // namespace webrtc diff --git a/webrtc/video/bitrate_estimator_tests.cc b/webrtc/video/bitrate_estimator_tests.cc index 7b74818e72..f8b9060f60 100644 --- a/webrtc/video/bitrate_estimator_tests.cc +++ b/webrtc/video/bitrate_estimator_tests.cc @@ -70,8 +70,10 @@ class BitrateEstimatorTest : public ::testing::Test { send_config_ = sender_call_->GetDefaultSendConfig(); send_config_.rtp.ssrcs.push_back(kSendSsrc); // Encoders will be set separately per stream. - send_config_.encoder_settings = - test::CreateEncoderSettings(NULL, "FAKE", kSendPayloadType, 1); + send_config_.encoder_settings.encoder = NULL; + send_config_.encoder_settings.payload_name = "FAKE"; + send_config_.encoder_settings.payload_type = kSendPayloadType; + video_streams_ = test::CreateVideoStreams(1); receive_config_ = receiver_call_->GetDefaultReceiveConfig(); assert(receive_config_.codecs.empty()); @@ -169,15 +171,15 @@ class BitrateEstimatorTest : public ::testing::Test { fake_decoder_() { test_->send_config_.rtp.ssrcs[0]++; test_->send_config_.encoder_settings.encoder = &fake_encoder_; - send_stream_ = - test_->sender_call_->CreateVideoSendStream(test_->send_config_); - assert(test_->send_config_.encoder_settings.streams.size() == 1); - frame_generator_capturer_.reset(test::FrameGeneratorCapturer::Create( - send_stream_->Input(), - test_->send_config_.encoder_settings.streams[0].width, - test_->send_config_.encoder_settings.streams[0].height, - 30, - Clock::GetRealTimeClock())); + send_stream_ = test_->sender_call_->CreateVideoSendStream( + test_->send_config_, test_->video_streams_, NULL); + assert(test_->video_streams_.size() == 1); + frame_generator_capturer_.reset( + test::FrameGeneratorCapturer::Create(send_stream_->Input(), + test_->video_streams_[0].width, + test_->video_streams_[0].height, + 30, + Clock::GetRealTimeClock())); send_stream_->Start(); frame_generator_capturer_->Start(); @@ -227,6 +229,7 @@ class BitrateEstimatorTest : public ::testing::Test { scoped_ptr sender_call_; scoped_ptr receiver_call_; VideoSendStream::Config send_config_; + std::vector video_streams_; VideoReceiveStream::Config receive_config_; std::vector streams_; }; diff --git a/webrtc/video/call.cc b/webrtc/video/call.cc index 6adb0fccfd..6103074bf1 100644 --- a/webrtc/video/call.cc +++ b/webrtc/video/call.cc @@ -70,7 +70,9 @@ class Call : public webrtc::Call, public PacketReceiver { virtual VideoSendStream::Config GetDefaultSendConfig() OVERRIDE; virtual VideoSendStream* CreateVideoSendStream( - const VideoSendStream::Config& config) OVERRIDE; + const VideoSendStream::Config& config, + const std::vector& video_streams, + const void* encoder_settings) OVERRIDE; virtual void DestroyVideoSendStream(webrtc::VideoSendStream* send_stream) OVERRIDE; @@ -175,15 +177,19 @@ VideoSendStream::Config Call::GetDefaultSendConfig() { } VideoSendStream* Call::CreateVideoSendStream( - const VideoSendStream::Config& config) { + const VideoSendStream::Config& config, + const std::vector& video_streams, + const void* encoder_settings) { assert(config.rtp.ssrcs.size() > 0); - VideoSendStream* send_stream = new VideoSendStream( - config_.send_transport, - overuse_observer_proxy_.get(), - video_engine_, - config, - base_channel_id_); + VideoSendStream* send_stream = + new VideoSendStream(config_.send_transport, + overuse_observer_proxy_.get(), + video_engine_, + config, + video_streams, + encoder_settings, + base_channel_id_); WriteLockScoped write_lock(*send_lock_); for (size_t i = 0; i < config.rtp.ssrcs.size(); ++i) { diff --git a/webrtc/video/call_perf_tests.cc b/webrtc/video/call_perf_tests.cc index bc0a1e011b..f9e44aed18 100644 --- a/webrtc/video/call_perf_tests.cc +++ b/webrtc/video/call_perf_tests.cc @@ -53,18 +53,19 @@ class CallPerfTest : public ::testing::Test { : send_stream_(NULL), fake_encoder_(Clock::GetRealTimeClock()) {} protected: - VideoSendStream::Config GetSendTestConfig(Call* call) { - VideoSendStream::Config config = call->GetDefaultSendConfig(); - config.rtp.ssrcs.push_back(kSendSsrc); - config.encoder_settings = test::CreateEncoderSettings( - &fake_encoder_, "FAKE", kSendPayloadType, 1); - return config; + void CreateTestConfig(Call* call) { + send_config_ = call->GetDefaultSendConfig(); + send_config_.rtp.ssrcs.push_back(kSendSsrc); + send_config_.encoder_settings.encoder = &fake_encoder_; + send_config_.encoder_settings.payload_type = kSendPayloadType; + send_config_.encoder_settings.payload_name = "FAKE"; + video_streams_ = test::CreateVideoStreams(1); } void RunVideoSendTest(Call* call, const VideoSendStream::Config& config, test::RtpRtcpObserver* observer) { - send_stream_ = call->CreateVideoSendStream(config); + send_stream_ = call->CreateVideoSendStream(config, video_streams_, NULL); scoped_ptr frame_generator_capturer( test::FrameGeneratorCapturer::Create( send_stream_->Input(), 320, 240, 30, Clock::GetRealTimeClock())); @@ -86,6 +87,8 @@ class CallPerfTest : public ::testing::Test { int start_time_ms, int run_time_ms); + VideoSendStream::Config send_config_; + std::vector video_streams_; VideoSendStream* send_stream_; test::FakeEncoder fake_encoder_; }; @@ -288,35 +291,34 @@ TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSync) { test::FakeDecoder fake_decoder; - VideoSendStream::Config send_config = GetSendTestConfig(sender_call.get()); + CreateTestConfig(sender_call.get()); VideoReceiveStream::Config receive_config = receiver_call->GetDefaultReceiveConfig(); assert(receive_config.codecs.empty()); VideoCodec codec = - test::CreateDecoderVideoCodec(send_config.encoder_settings); + test::CreateDecoderVideoCodec(send_config_.encoder_settings); receive_config.codecs.push_back(codec); assert(receive_config.external_decoders.empty()); ExternalVideoDecoder decoder; decoder.decoder = &fake_decoder; - decoder.payload_type = send_config.encoder_settings.payload_type; + decoder.payload_type = send_config_.encoder_settings.payload_type; receive_config.external_decoders.push_back(decoder); - receive_config.rtp.remote_ssrc = send_config.rtp.ssrcs[0]; + receive_config.rtp.remote_ssrc = send_config_.rtp.ssrcs[0]; receive_config.rtp.local_ssrc = kReceiverLocalSsrc; receive_config.renderer = &observer; receive_config.audio_channel_id = channel; VideoSendStream* send_stream = - sender_call->CreateVideoSendStream(send_config); + sender_call->CreateVideoSendStream(send_config_, video_streams_, NULL); VideoReceiveStream* receive_stream = receiver_call->CreateVideoReceiveStream(receive_config); scoped_ptr capturer( - test::FrameGeneratorCapturer::Create( - send_stream->Input(), - send_config.encoder_settings.streams[0].width, - send_config.encoder_settings.streams[0].height, - 30, - Clock::GetRealTimeClock())); + test::FrameGeneratorCapturer::Create(send_stream->Input(), + video_streams_[0].width, + video_streams_[0].height, + 30, + Clock::GetRealTimeClock())); receive_stream->Start(); send_stream->Start(); capturer->Start(); @@ -465,16 +467,15 @@ void CallPerfTest::TestCaptureNtpTime(const FakeNetworkPipe::Config& net_config, observer.SetReceivers(receiver_call->Receiver(), sender_call->Receiver()); // Configure send stream. - VideoSendStream::Config send_config = GetSendTestConfig(sender_call.get()); + CreateTestConfig(sender_call.get()); VideoSendStream* send_stream = - sender_call->CreateVideoSendStream(send_config); + sender_call->CreateVideoSendStream(send_config_, video_streams_, NULL); scoped_ptr capturer( - test::FrameGeneratorCapturer::Create( - send_stream->Input(), - send_config.encoder_settings.streams[0].width, - send_config.encoder_settings.streams[0].height, - 30, - Clock::GetRealTimeClock())); + test::FrameGeneratorCapturer::Create(send_stream->Input(), + video_streams_[0].width, + video_streams_[0].height, + 30, + Clock::GetRealTimeClock())); observer.SetCapturer(capturer.get()); // Configure receive stream. @@ -482,15 +483,15 @@ void CallPerfTest::TestCaptureNtpTime(const FakeNetworkPipe::Config& net_config, receiver_call->GetDefaultReceiveConfig(); assert(receive_config.codecs.empty()); VideoCodec codec = - test::CreateDecoderVideoCodec(send_config.encoder_settings); + test::CreateDecoderVideoCodec(send_config_.encoder_settings); receive_config.codecs.push_back(codec); assert(receive_config.external_decoders.empty()); ExternalVideoDecoder decoder; test::FakeDecoder fake_decoder; decoder.decoder = &fake_decoder; - decoder.payload_type = send_config.encoder_settings.payload_type; + decoder.payload_type = send_config_.encoder_settings.payload_type; receive_config.external_decoders.push_back(decoder); - receive_config.rtp.remote_ssrc = send_config.rtp.ssrcs[0]; + receive_config.rtp.remote_ssrc = send_config_.rtp.ssrcs[0]; receive_config.rtp.local_ssrc = kReceiverLocalSsrc; receive_config.renderer = &observer; // Enable the receiver side rtt calculation. @@ -559,8 +560,8 @@ TEST_F(CallPerfTest, RegisterCpuOveruseObserver) { call_config.overuse_callback = &observer; scoped_ptr call(Call::Create(call_config)); - VideoSendStream::Config send_config = GetSendTestConfig(call.get()); - RunVideoSendTest(call.get(), send_config, &observer); + CreateTestConfig(call.get()); + RunVideoSendTest(call.get(), send_config_, &observer); } void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) { @@ -636,43 +637,42 @@ void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) { scoped_ptr receiver_call( Call::Create(Call::Config(observer.ReceiveTransport()))); - VideoSendStream::Config send_config = GetSendTestConfig(sender_call.get()); + CreateTestConfig(sender_call.get()); fake_encoder_.SetMaxBitrate(kMaxEncodeBitrateKbps); observer.SetReceivers(receiver_call->Receiver(), sender_call->Receiver()); - send_config.pacing = true; + send_config_.pacing = true; if (pad_to_min_bitrate) { - send_config.rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps; + send_config_.rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps; } else { - assert(send_config.rtp.min_transmit_bitrate_bps == 0); + assert(send_config_.rtp.min_transmit_bitrate_bps == 0); } VideoReceiveStream::Config receive_config = receiver_call->GetDefaultReceiveConfig(); receive_config.codecs.clear(); VideoCodec codec = - test::CreateDecoderVideoCodec(send_config.encoder_settings); + test::CreateDecoderVideoCodec(send_config_.encoder_settings); receive_config.codecs.push_back(codec); test::FakeDecoder fake_decoder; ExternalVideoDecoder decoder; decoder.decoder = &fake_decoder; - decoder.payload_type = send_config.encoder_settings.payload_type; + decoder.payload_type = send_config_.encoder_settings.payload_type; receive_config.external_decoders.push_back(decoder); - receive_config.rtp.remote_ssrc = send_config.rtp.ssrcs[0]; + receive_config.rtp.remote_ssrc = send_config_.rtp.ssrcs[0]; receive_config.rtp.local_ssrc = kReceiverLocalSsrc; VideoSendStream* send_stream = - sender_call->CreateVideoSendStream(send_config); + sender_call->CreateVideoSendStream(send_config_, video_streams_, NULL); VideoReceiveStream* receive_stream = receiver_call->CreateVideoReceiveStream(receive_config); scoped_ptr capturer( - test::FrameGeneratorCapturer::Create( - send_stream->Input(), - send_config.encoder_settings.streams[0].width, - send_config.encoder_settings.streams[0].height, - 30, - Clock::GetRealTimeClock())); + test::FrameGeneratorCapturer::Create(send_stream->Input(), + video_streams_[0].width, + video_streams_[0].height, + 30, + Clock::GetRealTimeClock())); observer.SetSendStream(send_stream); receive_stream->Start(); send_stream->Start(); diff --git a/webrtc/video/call_tests.cc b/webrtc/video/call_tests.cc index 7b78af3d0e..5bcf115764 100644 --- a/webrtc/video/call_tests.cc +++ b/webrtc/video/call_tests.cc @@ -73,8 +73,10 @@ class CallTest : public ::testing::Test { receive_config_ = receiver_call_->GetDefaultReceiveConfig(); send_config_.rtp.ssrcs.push_back(kSendSsrc); - send_config_.encoder_settings = test::CreateEncoderSettings( - &fake_encoder_, "FAKE", kSendPayloadType, 1); + send_config_.encoder_settings.encoder = &fake_encoder_; + send_config_.encoder_settings.payload_name = "FAKE"; + send_config_.encoder_settings.payload_type = kSendPayloadType; + video_streams_ = test::CreateVideoStreams(1); assert(receive_config_.codecs.empty()); VideoCodec codec = @@ -92,17 +94,18 @@ class CallTest : public ::testing::Test { assert(send_stream_ == NULL); assert(receive_stream_ == NULL); - send_stream_ = sender_call_->CreateVideoSendStream(send_config_); + send_stream_ = + sender_call_->CreateVideoSendStream(send_config_, video_streams_, NULL); receive_stream_ = receiver_call_->CreateVideoReceiveStream(receive_config_); } void CreateFrameGenerator() { - frame_generator_capturer_.reset(test::FrameGeneratorCapturer::Create( - send_stream_->Input(), - send_config_.encoder_settings.streams[0].width, - send_config_.encoder_settings.streams[0].height, - 30, - Clock::GetRealTimeClock())); + frame_generator_capturer_.reset( + test::FrameGeneratorCapturer::Create(send_stream_->Input(), + video_streams_[0].width, + video_streams_[0].height, + 30, + Clock::GetRealTimeClock())); } void StartSending() { @@ -139,6 +142,7 @@ class CallTest : public ::testing::Test { scoped_ptr receiver_call_; VideoSendStream::Config send_config_; + std::vector video_streams_; VideoReceiveStream::Config receive_config_; VideoSendStream* send_stream_; @@ -350,8 +354,7 @@ TEST_F(CallTest, TransmitsFirstFrame) { StartSending(); scoped_ptr frame_generator(test::FrameGenerator::Create( - send_config_.encoder_settings.streams[0].width, - send_config_.encoder_settings.streams[0].height)); + video_streams_[0].width, video_streams_[0].height)); send_stream_->Input()->SwapFrame(frame_generator->NextFrame()); EXPECT_EQ(kEventSignaled, renderer.Wait()) @@ -701,10 +704,9 @@ TEST_F(CallTest, UsesFrameCallbacks) { scoped_ptr encoder(VP8Encoder::Create()); send_config_.encoder_settings.encoder = encoder.get(); send_config_.encoder_settings.payload_name = "VP8"; - ASSERT_EQ(1u, send_config_.encoder_settings.streams.size()) - << "Test setup error."; - send_config_.encoder_settings.streams[0].width = kWidth; - send_config_.encoder_settings.streams[0].height = kHeight; + ASSERT_EQ(1u, video_streams_.size()) << "Test setup error."; + video_streams_[0].width = kWidth; + video_streams_[0].height = kHeight; send_config_.pre_encode_callback = &pre_encode_callback; receive_config_.codecs.clear(); VideoCodec codec = @@ -1055,15 +1057,18 @@ TEST_F(CallTest, SendsAndReceivesMultipleStreams) { VideoSendStream::Config send_config = sender_call->GetDefaultSendConfig(); send_config.rtp.ssrcs.push_back(ssrc); - send_config.encoder_settings = - test::CreateEncoderSettings(encoders[i].get(), "VP8", 124, 1); - VideoStream* stream = &send_config.encoder_settings.streams[0]; + send_config.encoder_settings.encoder = encoders[i].get(); + send_config.encoder_settings.payload_name = "VP8"; + send_config.encoder_settings.payload_type = 124; + std::vector video_streams = test::CreateVideoStreams(1); + VideoStream* stream = &video_streams[0]; stream->width = width; stream->height = height; stream->max_framerate = 5; stream->min_bitrate_bps = stream->target_bitrate_bps = stream->max_bitrate_bps = 100000; - send_streams[i] = sender_call->CreateVideoSendStream(send_config); + send_streams[i] = + sender_call->CreateVideoSendStream(send_config, video_streams, NULL); send_streams[i]->Start(); VideoReceiveStream::Config receive_config = @@ -1154,8 +1159,7 @@ TEST_F(CallTest, ObserversEncodedFrames) { StartSending(); scoped_ptr frame_generator(test::FrameGenerator::Create( - send_config_.encoder_settings.streams[0].width, - send_config_.encoder_settings.streams[0].height)); + video_streams_[0].width, video_streams_[0].height)); send_stream_->Input()->SwapFrame(frame_generator->NextFrame()); EXPECT_EQ(kEventSignaled, post_encode_observer.Wait()) diff --git a/webrtc/video/full_stack.cc b/webrtc/video/full_stack.cc index cb97cd85bb..6b21cbe12c 100644 --- a/webrtc/video/full_stack.cc +++ b/webrtc/video/full_stack.cc @@ -398,16 +398,19 @@ TEST_P(FullStackTest, NoPacketLoss) { send_config.rtp.ssrcs.push_back(kSendSsrc); scoped_ptr encoder(VP8Encoder::Create()); - send_config.encoder_settings = - test::CreateEncoderSettings(encoder.get(), "VP8", 124, 1); - VideoStream* stream = &send_config.encoder_settings.streams[0]; + send_config.encoder_settings.encoder = encoder.get(); + send_config.encoder_settings.payload_name = "VP8"; + send_config.encoder_settings.payload_type = 124; + std::vector video_streams = test::CreateVideoStreams(1); + VideoStream* stream = &video_streams[0]; stream->width = params.clip.width; stream->height = params.clip.height; stream->min_bitrate_bps = stream->target_bitrate_bps = stream->max_bitrate_bps = params.bitrate * 1000; stream->max_framerate = params.clip.fps; - VideoSendStream* send_stream = call->CreateVideoSendStream(send_config); + VideoSendStream* send_stream = + call->CreateVideoSendStream(send_config, video_streams, NULL); analyzer.input_ = send_stream->Input(); scoped_ptr file_capturer( diff --git a/webrtc/video/loopback.cc b/webrtc/video/loopback.cc index eb2d5ae316..ecc208909c 100644 --- a/webrtc/video/loopback.cc +++ b/webrtc/video/loopback.cc @@ -72,19 +72,21 @@ void Loopback() { send_config.local_renderer = local_preview.get(); scoped_ptr encoder(VP8Encoder::Create()); - send_config.encoder_settings = - test::CreateEncoderSettings(encoder.get(), "VP8", 124, 1); - VideoStream* stream = &send_config.encoder_settings.streams[0]; + send_config.encoder_settings.encoder = encoder.get(); + send_config.encoder_settings.payload_name = "VP8"; + send_config.encoder_settings.payload_type = 124; + std::vector video_streams = test::CreateVideoStreams(1); + VideoStream* stream = &video_streams[0]; stream->width = flags::Width(); stream->height = flags::Height(); stream->min_bitrate_bps = static_cast(flags::MinBitrate()) * 1000; - stream->target_bitrate_bps = - static_cast(flags::MaxBitrate()) * 1000; + stream->target_bitrate_bps = static_cast(flags::MaxBitrate()) * 1000; stream->max_bitrate_bps = static_cast(flags::MaxBitrate()) * 1000; stream->max_framerate = 30; stream->max_qp = 56; - VideoSendStream* send_stream = call->CreateVideoSendStream(send_config); + VideoSendStream* send_stream = + call->CreateVideoSendStream(send_config, video_streams, NULL); Clock* test_clock = Clock::GetRealTimeClock(); diff --git a/webrtc/video/rampup_tests.cc b/webrtc/video/rampup_tests.cc index c86963d033..989deeaf5d 100644 --- a/webrtc/video/rampup_tests.cc +++ b/webrtc/video/rampup_tests.cc @@ -430,12 +430,15 @@ class RampUpTest : public ::testing::Test { receiver_transport.SetReceiver(call->Receiver()); test::FakeEncoder encoder(Clock::GetRealTimeClock()); - send_config.encoder_settings = - test::CreateEncoderSettings(&encoder, "FAKE", 125, num_streams); + send_config.encoder_settings.encoder = &encoder; + send_config.encoder_settings.payload_type = 125; + send_config.encoder_settings.payload_name = "FAKE"; + std::vector video_streams = + test::CreateVideoStreams(num_streams); if (num_streams == 1) { - send_config.encoder_settings.streams[0].target_bitrate_bps = 2000000; - send_config.encoder_settings.streams[0].max_bitrate_bps = 2000000; + video_streams[0].target_bitrate_bps = 2000000; + video_streams[0].max_bitrate_bps = 2000000; } send_config.pacing = pacing; @@ -455,25 +458,22 @@ class RampUpTest : public ::testing::Test { // For multi stream rampup until all streams are being sent. That means // enough birate to sent all the target streams plus the min bitrate of // the last one. - int expected_bitrate_bps = - send_config.encoder_settings.streams.back().min_bitrate_bps; - for (size_t i = 0; i < send_config.encoder_settings.streams.size() - 1; - ++i) { - expected_bitrate_bps += - send_config.encoder_settings.streams[i].target_bitrate_bps; + int expected_bitrate_bps = video_streams.back().min_bitrate_bps; + for (size_t i = 0; i < video_streams.size() - 1; ++i) { + expected_bitrate_bps += video_streams[i].target_bitrate_bps; } stream_observer.set_expected_bitrate_bps(expected_bitrate_bps); } - VideoSendStream* send_stream = call->CreateVideoSendStream(send_config); + VideoSendStream* send_stream = + call->CreateVideoSendStream(send_config, video_streams, NULL); scoped_ptr frame_generator_capturer( - test::FrameGeneratorCapturer::Create( - send_stream->Input(), - send_config.encoder_settings.streams.back().width, - send_config.encoder_settings.streams.back().height, - send_config.encoder_settings.streams.back().max_framerate, - Clock::GetRealTimeClock())); + test::FrameGeneratorCapturer::Create(send_stream->Input(), + video_streams.back().width, + video_streams.back().height, + video_streams.back().max_framerate, + Clock::GetRealTimeClock())); send_stream->Start(); frame_generator_capturer->Start(); @@ -504,23 +504,29 @@ class RampUpTest : public ::testing::Test { receiver_transport.SetReceiver(call->Receiver()); test::FakeEncoder encoder(Clock::GetRealTimeClock()); - send_config.encoder_settings = - test::CreateEncoderSettings(&encoder, "FAKE", 125, number_of_streams); + send_config.encoder_settings.encoder = &encoder; + send_config.encoder_settings.payload_type = 125; + send_config.encoder_settings.payload_name = "FAKE"; + std::vector video_streams = + test::CreateVideoStreams(number_of_streams); + send_config.rtp.nack.rtp_history_ms = 1000; send_config.rtp.ssrcs.insert( send_config.rtp.ssrcs.begin(), ssrcs.begin(), ssrcs.end()); send_config.rtp.extensions.push_back( RtpExtension(RtpExtension::kAbsSendTime, kAbsoluteSendTimeExtensionId)); send_config.suspend_below_min_bitrate = true; + send_config.pacing = true; - VideoSendStream* send_stream = call->CreateVideoSendStream(send_config); + VideoSendStream* send_stream = + call->CreateVideoSendStream(send_config, video_streams, NULL); stream_observer.SetSendStream(send_stream); size_t width = 0; size_t height = 0; - for (size_t i = 0; i < send_config.encoder_settings.streams.size(); ++i) { - size_t stream_width = send_config.encoder_settings.streams[i].width; - size_t stream_height = send_config.encoder_settings.streams[i].height; + for (size_t i = 0; i < video_streams.size(); ++i) { + size_t stream_width = video_streams[i].width; + size_t stream_height = video_streams[i].height; if (stream_width > width) width = stream_width; if (stream_height > height) diff --git a/webrtc/video/video_receive_stream.cc b/webrtc/video/video_receive_stream.cc index 012ca68e53..9c3298c55d 100644 --- a/webrtc/video/video_receive_stream.cc +++ b/webrtc/video/video_receive_stream.cc @@ -150,13 +150,13 @@ VideoReceiveStream::VideoReceiveStream(webrtc::VideoEngine* video_engine, external_codec_ = ViEExternalCodec::GetInterface(video_engine); for (size_t i = 0; i < config_.external_decoders.size(); ++i) { - ExternalVideoDecoder* decoder = &config_.external_decoders[i]; + const ExternalVideoDecoder& decoder = config_.external_decoders[i]; if (external_codec_->RegisterExternalReceiveCodec( channel_, - decoder->payload_type, - decoder->decoder, - decoder->renderer, - decoder->expected_delay_ms) != 0) { + decoder.payload_type, + decoder.decoder, + decoder.renderer, + decoder.expected_delay_ms) != 0) { // TODO(pbos): Abort gracefully? Can this be a runtime error? abort(); } diff --git a/webrtc/video/video_receive_stream.h b/webrtc/video/video_receive_stream.h index 4ff086a5b7..2a3c6dfed3 100644 --- a/webrtc/video/video_receive_stream.h +++ b/webrtc/video/video_receive_stream.h @@ -69,7 +69,7 @@ class VideoReceiveStream : public webrtc::VideoReceiveStream, private: TransportAdapter transport_adapter_; EncodedFrameCallbackAdapter encoded_frame_proxy_; - VideoReceiveStream::Config config_; + const VideoReceiveStream::Config config_; Clock* const clock_; ViEBase* video_engine_base_; diff --git a/webrtc/video/video_send_stream.cc b/webrtc/video/video_send_stream.cc index 886e3dc39a..8a43387553 100644 --- a/webrtc/video/video_send_stream.cc +++ b/webrtc/video/video_send_stream.cc @@ -15,6 +15,7 @@ #include #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" +#include "webrtc/system_wrappers/interface/logging.h" #include "webrtc/video_engine/include/vie_base.h" #include "webrtc/video_engine/include/vie_capture.h" #include "webrtc/video_engine/include/vie_codec.h" @@ -32,18 +33,7 @@ VideoSendStream::Config::EncoderSettings::ToString() const { ss << "{payload_name: " << payload_name; ss << ", payload_type: " << payload_type; if (encoder != NULL) - ss << ", (encoder)"; - if (encoder_settings != NULL) - ss << ", (encoder_settings)"; - - ss << ", streams: {"; - for (size_t i = 0; i < streams.size(); ++i) { - ss << streams[i].ToString(); - if (i != streams.size() - 1) - ss << "}, {"; - } - ss << '}'; - + ss << ", encoder: " << (encoder != NULL ? "(encoder)" : "NULL"); ss << '}'; return ss.str(); } @@ -124,10 +114,11 @@ VideoSendStream::VideoSendStream(newapi::Transport* transport, CpuOveruseObserver* overuse_observer, webrtc::VideoEngine* video_engine, const VideoSendStream::Config& config, + const std::vector video_streams, + const void* encoder_settings, int base_channel) : transport_adapter_(transport), encoded_frame_proxy_(config.post_encode_callback), - codec_lock_(CriticalSectionWrapper::CreateCriticalSection()), config_(config), external_codec_(NULL), channel_(-1), @@ -141,7 +132,7 @@ VideoSendStream::VideoSendStream(newapi::Transport* transport, assert(config_.rtp.ssrcs.size() > 0); if (config_.suspend_below_min_bitrate) - config_.pacing = true; + assert(config_.pacing); rtp_rtcp_->SetTransmissionSmoothingStatus(channel_, config_.pacing); assert(config_.rtp.min_transmit_bitrate_bps >= 0); @@ -216,10 +207,8 @@ VideoSendStream::VideoSendStream(newapi::Transport* transport, } codec_ = ViECodec::GetInterface(video_engine); - if (!ReconfigureVideoEncoder(config_.encoder_settings.streams, - config_.encoder_settings.encoder_settings)) { + if (!ReconfigureVideoEncoder(video_streams, encoder_settings)) abort(); - } if (overuse_observer) video_engine_base_->RegisterCpuOveruseObserver(channel_, overuse_observer); @@ -232,9 +221,8 @@ VideoSendStream::VideoSendStream(newapi::Transport* transport, &encoded_frame_proxy_); } - if (config_.suspend_below_min_bitrate) { + if (config_.suspend_below_min_bitrate) codec_->SuspendBelowMinBitrate(channel_); - } rtp_rtcp_->RegisterSendChannelRtcpStatisticsCallback(channel_, stats_proxy_.get()); @@ -304,15 +292,12 @@ void VideoSendStream::Stop() { bool VideoSendStream::ReconfigureVideoEncoder( const std::vector& streams, - void* encoder_settings) { + const void* encoder_settings) { assert(!streams.empty()); assert(config_.rtp.ssrcs.size() >= streams.size()); // TODO(pbos): Wire encoder_settings. assert(encoder_settings == NULL); - // VideoStreams in config_.encoder_settings need to be locked. - CriticalSectionScoped crit(codec_lock_.get()); - VideoCodec video_codec; memset(&video_codec, 0, sizeof(video_codec)); video_codec.codecType = @@ -383,8 +368,8 @@ bool VideoSendStream::ReconfigureVideoEncoder( if (video_codec.startBitrate > video_codec.maxBitrate) video_codec.startBitrate = video_codec.maxBitrate; - assert(config_.encoder_settings.streams[0].max_framerate > 0); - video_codec.maxFramerate = config_.encoder_settings.streams[0].max_framerate; + assert(streams[0].max_framerate > 0); + video_codec.maxFramerate = streams[0].max_framerate; if (codec_->SetSendCodec(channel_, video_codec) != 0) return false; @@ -396,9 +381,6 @@ bool VideoSendStream::ReconfigureVideoEncoder( static_cast(i)); } - config_.encoder_settings.streams = streams; - config_.encoder_settings.encoder_settings = encoder_settings; - if (config_.rtp.rtx.ssrcs.empty()) return true; diff --git a/webrtc/video/video_send_stream.h b/webrtc/video/video_send_stream.h index a7e22676e4..125c7fdeb8 100644 --- a/webrtc/video/video_send_stream.h +++ b/webrtc/video/video_send_stream.h @@ -42,6 +42,8 @@ class VideoSendStream : public webrtc::VideoSendStream, CpuOveruseObserver* overuse_observer, webrtc::VideoEngine* video_engine, const VideoSendStream::Config& config, + const std::vector video_streams, + const void* encoder_settings, int base_channel); virtual ~VideoSendStream(); @@ -50,7 +52,7 @@ class VideoSendStream : public webrtc::VideoSendStream, virtual void Stop() OVERRIDE; virtual bool ReconfigureVideoEncoder(const std::vector& streams, - void* encoder_settings) OVERRIDE; + const void* encoder_settings) OVERRIDE; virtual Stats GetStats() const OVERRIDE; @@ -70,8 +72,7 @@ class VideoSendStream : public webrtc::VideoSendStream, private: TransportAdapter transport_adapter_; EncodedFrameCallbackAdapter encoded_frame_proxy_; - scoped_ptr codec_lock_; - VideoSendStream::Config config_; + const VideoSendStream::Config config_; ViEBase* video_engine_base_; ViECapture* capture_; diff --git a/webrtc/video/video_send_stream_tests.cc b/webrtc/video/video_send_stream_tests.cc index 666286650b..db71f54196 100644 --- a/webrtc/video/video_send_stream_tests.cc +++ b/webrtc/video/video_send_stream_tests.cc @@ -45,9 +45,9 @@ class VideoSendStreamTest : public ::testing::Test { protected: void RunSendTest(Call* call, - const VideoSendStream::Config& config, test::RtpRtcpObserver* observer) { - send_stream_ = call->CreateVideoSendStream(config); + send_stream_ = + call->CreateVideoSendStream(send_config_, video_streams_, NULL); scoped_ptr frame_generator_capturer( test::FrameGeneratorCapturer::Create( send_stream_->Input(), 320, 240, 30, Clock::GetRealTimeClock())); @@ -62,17 +62,16 @@ class VideoSendStreamTest : public ::testing::Test { call->DestroyVideoSendStream(send_stream_); } - VideoSendStream::Config GetSendTestConfig(Call* call, size_t num_streams) { + void CreateTestConfig(Call* call, size_t num_streams) { assert(num_streams <= kNumSendSsrcs); - VideoSendStream::Config config = call->GetDefaultSendConfig(); - config.encoder_settings = test::CreateEncoderSettings( - &fake_encoder_, "FAKE", kFakeSendPayloadType, num_streams); - config.encoder_settings.encoder = &fake_encoder_; - config.encoder_settings.payload_type = kFakeSendPayloadType; + send_config_ = call->GetDefaultSendConfig(); + send_config_.encoder_settings.encoder = &fake_encoder_; + send_config_.encoder_settings.payload_name = "FAKE"; + send_config_.encoder_settings.payload_type = kFakeSendPayloadType; + video_streams_ = test::CreateVideoStreams(num_streams); + send_config_.encoder_settings.payload_type = kFakeSendPayloadType; for (size_t i = 0; i < num_streams; ++i) - config.rtp.ssrcs.push_back(kSendSsrcs[i]); - config.pacing = true; - return config; + send_config_.rtp.ssrcs.push_back(kSendSsrcs[i]); } void TestNackRetransmission(uint32_t retransmit_ssrc, @@ -91,6 +90,8 @@ class VideoSendStreamTest : public ::testing::Test { static const uint32_t kSendRtxSsrc; static const uint32_t kSendSsrcs[kNumSendSsrcs]; + VideoSendStream::Config send_config_; + std::vector video_streams_; VideoSendStream* send_stream_; test::FakeEncoder fake_encoder_; }; @@ -158,24 +159,23 @@ void VideoSendStreamTest::SendsSetSsrcs(size_t num_ssrcs, Call::Config call_config(observer.SendTransport()); scoped_ptr call(Call::Create(call_config)); - VideoSendStream::Config send_config = - GetSendTestConfig(call.get(), num_ssrcs); + CreateTestConfig(call.get(), num_ssrcs); if (num_ssrcs > 1) { // Set low simulcast bitrates to not have to wait for bandwidth ramp-up. - std::vector* streams = &send_config.encoder_settings.streams; - for (size_t i = 0; i < streams->size(); ++i) { - (*streams)[i].min_bitrate_bps = 10000; - (*streams)[i].target_bitrate_bps = 10000; - (*streams)[i].max_bitrate_bps = 10000; + for (size_t i = 0; i < video_streams_.size(); ++i) { + video_streams_[i].min_bitrate_bps = 10000; + video_streams_[i].target_bitrate_bps = 10000; + video_streams_[i].max_bitrate_bps = 10000; } } - std::vector all_streams = send_config.encoder_settings.streams; + std::vector all_streams = video_streams_; if (send_single_ssrc_first) - send_config.encoder_settings.streams.resize(1); + video_streams_.resize(1); - send_stream_ = call->CreateVideoSendStream(send_config); + send_stream_ = + call->CreateVideoSendStream(send_config_, video_streams_, NULL); scoped_ptr frame_generator_capturer( test::FrameGeneratorCapturer::Create( send_stream_->Input(), 320, 240, 30, Clock::GetRealTimeClock())); @@ -204,8 +204,9 @@ TEST_F(VideoSendStreamTest, CanStartStartedStream) { Call::Config call_config(&transport); scoped_ptr call(Call::Create(call_config)); - VideoSendStream::Config config = GetSendTestConfig(call.get(), 1); - VideoSendStream* stream = call->CreateVideoSendStream(config); + CreateTestConfig(call.get(), 1); + VideoSendStream* stream = + call->CreateVideoSendStream(send_config_, video_streams_, NULL); stream->Start(); stream->Start(); call->DestroyVideoSendStream(stream); @@ -216,8 +217,9 @@ TEST_F(VideoSendStreamTest, CanStopStoppedStream) { Call::Config call_config(&transport); scoped_ptr call(Call::Create(call_config)); - VideoSendStream::Config config = GetSendTestConfig(call.get(), 1); - VideoSendStream* stream = call->CreateVideoSendStream(config); + CreateTestConfig(call.get(), 1); + VideoSendStream* stream = + call->CreateVideoSendStream(send_config_, video_streams_, NULL); stream->Stop(); stream->Stop(); call->DestroyVideoSendStream(stream); @@ -260,10 +262,10 @@ TEST_F(VideoSendStreamTest, SupportsCName) { Call::Config call_config(observer.SendTransport()); scoped_ptr call(Call::Create(call_config)); - VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 1); - send_config.rtp.c_name = kCName; + CreateTestConfig(call.get(), 1); + send_config_.rtp.c_name = kCName; - RunSendTest(call.get(), send_config, &observer); + RunSendTest(call.get(), &observer); } TEST_F(VideoSendStreamTest, SupportsAbsoluteSendTime) { @@ -292,11 +294,11 @@ TEST_F(VideoSendStreamTest, SupportsAbsoluteSendTime) { Call::Config call_config(observer.SendTransport()); scoped_ptr call(Call::Create(call_config)); - VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 1); - send_config.rtp.extensions.push_back( + CreateTestConfig(call.get(), 1); + send_config_.rtp.extensions.push_back( RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId)); - RunSendTest(call.get(), send_config, &observer); + RunSendTest(call.get(), &observer); } TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) { @@ -339,12 +341,12 @@ TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) { Call::Config call_config(observer.SendTransport()); scoped_ptr call(Call::Create(call_config)); - VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 1); - send_config.encoder_settings.encoder = &encoder; - send_config.rtp.extensions.push_back( + CreateTestConfig(call.get(), 1); + send_config_.encoder_settings.encoder = &encoder; + send_config_.rtp.extensions.push_back( RtpExtension(RtpExtension::kTOffset, kTOffsetExtensionId)); - RunSendTest(call.get(), send_config, &observer); + RunSendTest(call.get(), &observer); } class FakeReceiveStatistics : public NullReceiveStatistics { @@ -413,8 +415,9 @@ TEST_F(VideoSendStreamTest, SwapsI420VideoFrames) { Call::Config call_config(&transport); scoped_ptr call(Call::Create(call_config)); - VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 1); - VideoSendStream* video_send_stream = call->CreateVideoSendStream(send_config); + CreateTestConfig(call.get(), 1); + VideoSendStream* video_send_stream = + call->CreateVideoSendStream(send_config_, video_streams_, NULL); video_send_stream->Start(); I420VideoFrame frame; @@ -492,11 +495,11 @@ TEST_F(VideoSendStreamTest, SupportsFec) { observer.SetReceivers(call->Receiver(), NULL); - VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 1); - send_config.rtp.fec.red_payload_type = kRedPayloadType; - send_config.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType; + CreateTestConfig(call.get(), 1); + send_config_.rtp.fec.red_payload_type = kRedPayloadType; + send_config_.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType; - RunSendTest(call.get(), send_config, &observer); + RunSendTest(call.get(), &observer); } void VideoSendStreamTest::TestNackRetransmission( @@ -568,14 +571,14 @@ void VideoSendStreamTest::TestNackRetransmission( scoped_ptr call(Call::Create(call_config)); observer.SetReceivers(call->Receiver(), NULL); - VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 1); - send_config.rtp.nack.rtp_history_ms = 1000; - send_config.rtp.rtx.payload_type = retransmit_payload_type; - send_config.pacing = enable_pacing; + CreateTestConfig(call.get(), 1); + send_config_.rtp.nack.rtp_history_ms = 1000; + send_config_.rtp.rtx.payload_type = retransmit_payload_type; + send_config_.pacing = enable_pacing; if (retransmit_ssrc != kSendSsrc) - send_config.rtp.rtx.ssrcs.push_back(retransmit_ssrc); + send_config_.rtp.rtx.ssrcs.push_back(retransmit_ssrc); - RunSendTest(call.get(), send_config, &observer); + RunSendTest(call.get(), &observer); } TEST_F(VideoSendStreamTest, RetransmitsNack) { @@ -762,27 +765,27 @@ void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format, observer.SetReceivers(call->Receiver(), NULL); - VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 1); + CreateTestConfig(call.get(), 1); if (with_fec) { - send_config.rtp.fec.red_payload_type = kRedPayloadType; - send_config.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType; + send_config_.rtp.fec.red_payload_type = kRedPayloadType; + send_config_.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType; } if (format == kVP8) - send_config.encoder_settings.payload_name = "VP8"; + send_config_.encoder_settings.payload_name = "VP8"; - send_config.pacing = false; - send_config.encoder_settings.encoder = &encoder; - send_config.rtp.max_packet_size = kMaxPacketSize; - send_config.post_encode_callback = &observer; + send_config_.pacing = false; + send_config_.encoder_settings.encoder = &encoder; + send_config_.rtp.max_packet_size = kMaxPacketSize; + send_config_.post_encode_callback = &observer; // Add an extension header, to make the RTP header larger than the base // length of 12 bytes. static const uint8_t kAbsSendTimeExtensionId = 13; - send_config.rtp.extensions.push_back( + send_config_.rtp.extensions.push_back( RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId)); - RunSendTest(call.get(), send_config, &observer); + RunSendTest(call.get(), &observer); } // TODO(sprang): Is there any way of speeding up these tests? @@ -948,18 +951,19 @@ TEST_F(VideoSendStreamTest, SuspendBelowMinBitrate) { scoped_ptr call(Call::Create(call_config)); observer.SetReceiver(call->Receiver()); - VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 1); - send_config.rtp.nack.rtp_history_ms = 1000; - send_config.pre_encode_callback = &observer; - send_config.suspend_below_min_bitrate = true; - int min_bitrate_bps = send_config.encoder_settings.streams[0].min_bitrate_bps; + CreateTestConfig(call.get(), 1); + send_config_.rtp.nack.rtp_history_ms = 1000; + send_config_.pre_encode_callback = &observer; + send_config_.suspend_below_min_bitrate = true; + send_config_.pacing = true; + int min_bitrate_bps = video_streams_[0].min_bitrate_bps; observer.set_low_remb_bps(min_bitrate_bps - 10000); int threshold_window = std::max(min_bitrate_bps / 10, 10000); - ASSERT_GT(send_config.encoder_settings.streams[0].max_bitrate_bps, + ASSERT_GT(video_streams_[0].max_bitrate_bps, min_bitrate_bps + threshold_window + 5000); observer.set_high_remb_bps(min_bitrate_bps + threshold_window + 5000); - RunSendTest(call.get(), send_config, &observer); + RunSendTest(call.get(), &observer); observer.Stop(); } @@ -1022,9 +1026,10 @@ TEST_F(VideoSendStreamTest, NoPaddingWhenVideoIsMuted) { scoped_ptr call(Call::Create(call_config)); observer.SetReceivers(call->Receiver(), call->Receiver()); - VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 3); + CreateTestConfig(call.get(), 3); - send_stream_ = call->CreateVideoSendStream(send_config); + send_stream_ = + call->CreateVideoSendStream(send_config_, video_streams_, NULL); scoped_ptr frame_generator_capturer( test::FrameGeneratorCapturer::Create( send_stream_->Input(), 320, 240, 30, Clock::GetRealTimeClock())); @@ -1107,11 +1112,13 @@ TEST_F(VideoSendStreamTest, ProducesStats) { Call::Config call_config(observer.SendTransport()); scoped_ptr call(Call::Create(call_config)); - VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 1); - send_config.rtp.c_name = kCName; - observer.SetConfig(send_config); + CreateTestConfig(call.get(), 1); + send_config_.rtp.c_name = kCName; + send_config_.pacing = true; + observer.SetConfig(send_config_); - send_stream_ = call->CreateVideoSendStream(send_config); + send_stream_ = + call->CreateVideoSendStream(send_config_, video_streams_, NULL); observer.SetSendStream(send_stream_); scoped_ptr frame_generator_capturer( test::FrameGeneratorCapturer::Create( @@ -1202,9 +1209,10 @@ TEST_F(VideoSendStreamTest, MinTransmitBitrateRespectsRemb) { scoped_ptr call(Call::Create(call_config)); observer.SetReceivers(&observer, call->Receiver()); - VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 1); - send_config.rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps; - send_stream_ = call->CreateVideoSendStream(send_config); + CreateTestConfig(call.get(), 1); + send_config_.rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps; + send_stream_ = + call->CreateVideoSendStream(send_config_, video_streams_, NULL); observer.SetSendStream(send_stream_); scoped_ptr frame_generator_capturer( diff --git a/webrtc/video_send_stream.h b/webrtc/video_send_stream.h index e173e3bea8..b33f389347 100644 --- a/webrtc/video_send_stream.h +++ b/webrtc/video_send_stream.h @@ -66,8 +66,7 @@ class VideoSendStream { std::string ToString() const; struct EncoderSettings { - EncoderSettings() - : payload_type(-1), encoder(NULL), encoder_settings(NULL) {} + EncoderSettings() : payload_type(-1), encoder(NULL) {} std::string ToString() const; std::string payload_name; @@ -76,13 +75,6 @@ class VideoSendStream { // Uninitialized VideoEncoder instance to be used for encoding. Will be // initialized from inside the VideoSendStream. webrtc::VideoEncoder* encoder; - // TODO(pbos): Wire up encoder-specific settings. - // Encoder-specific settings, will be passed to the encoder during - // initialization. - void* encoder_settings; - - // List of stream settings to encode (resolution, bitrates, framerate). - std::vector streams; } encoder_settings; static const size_t kDefaultMaxPacketSize = 1500 - 40; // TCP over IPv4. @@ -155,8 +147,7 @@ class VideoSendStream { // True if the stream should be suspended when the available bitrate fall // below the minimum configured bitrate. If this variable is false, the // stream may send at a rate higher than the estimated available bitrate. - // Enabling suspend_below_min_bitrate will also enable pacing and padding, - // otherwise, the video will be unable to recover from suspension. + // |suspend_below_min_bitrate| requires |pacing| to be enabled as well. bool suspend_below_min_bitrate; }; @@ -171,7 +162,7 @@ class VideoSendStream { // in the config. Encoder settings are passed on to the encoder instance along // with the VideoStream settings. virtual bool ReconfigureVideoEncoder(const std::vector& streams, - void* encoder_settings) = 0; + const void* encoder_settings) = 0; virtual Stats GetStats() const = 0;