diff --git a/talk/media/webrtc/webrtcvideoengine2.cc b/talk/media/webrtc/webrtcvideoengine2.cc index 7df6809523..d10870b829 100644 --- a/talk/media/webrtc/webrtcvideoengine2.cc +++ b/talk/media/webrtc/webrtcvideoengine2.cc @@ -423,6 +423,7 @@ WebRtcVideoChannel2* WebRtcVideoEngine2::CreateChannel( << " voice channel. Options: " << options.ToString(); WebRtcVideoChannel2* channel = new WebRtcVideoChannel2(call_factory_, + voice_engine_, voice_channel, options, external_encoder_factory_, @@ -745,20 +746,24 @@ class WebRtcVideoRenderFrame : public VideoFrame { WebRtcVideoChannel2::WebRtcVideoChannel2( WebRtcCallFactory* call_factory, + WebRtcVoiceEngine* voice_engine, VoiceMediaChannel* voice_channel, const VideoOptions& options, WebRtcVideoEncoderFactory* external_encoder_factory, WebRtcVideoDecoderFactory* external_decoder_factory, WebRtcVideoEncoderFactory2* encoder_factory) : unsignalled_ssrc_handler_(&default_unsignalled_ssrc_handler_), + voice_channel_(voice_channel), external_encoder_factory_(external_encoder_factory), external_decoder_factory_(external_decoder_factory), encoder_factory_(encoder_factory) { - // TODO(pbos): Connect the video and audio with |voice_channel|. SetDefaultOptions(); options_.SetAll(options); webrtc::Call::Config config(this); config.overuse_callback = this; + if (voice_engine != NULL) { + config.voice_engine = voice_engine->voe()->engine(); + } // Set start bitrate for the call. A default is provided by SetDefaultOptions. int start_bitrate_kbps; @@ -1009,6 +1014,18 @@ bool WebRtcVideoChannel2::AddRecvStream(const StreamParams& sp) { webrtc::VideoReceiveStream::Config config; ConfigureReceiverRtp(&config, sp); + + // Set up A/V sync if there is a VoiceChannel. + // TODO(pbos): The A/V is synched by the receiving channel. So we need to know + // the SSRC of the remote audio channel in order to sync the correct webrtc + // VoiceEngine channel. For now sync the first channel in non-conference to + // match existing behavior in WebRtcVideoEngine. + if (voice_channel_ != NULL && receive_streams_.empty() && + !options_.conference_mode.GetWithDefaultIfUnset(false)) { + config.audio_channel_id = + static_cast(voice_channel_)->voe_channel(); + } + receive_streams_[ssrc] = new WebRtcVideoReceiveStream( call_.get(), external_decoder_factory_, config, recv_codecs_); diff --git a/talk/media/webrtc/webrtcvideoengine2.h b/talk/media/webrtc/webrtcvideoengine2.h index d32abb2ef3..b9a8682ae5 100644 --- a/talk/media/webrtc/webrtcvideoengine2.h +++ b/talk/media/webrtc/webrtcvideoengine2.h @@ -211,6 +211,7 @@ class WebRtcVideoChannel2 : public rtc::MessageHandler, public webrtc::LoadObserver { public: WebRtcVideoChannel2(WebRtcCallFactory* call_factory, + WebRtcVoiceEngine* voice_engine, VoiceMediaChannel* voice_channel, const VideoOptions& options, WebRtcVideoEncoderFactory* external_encoder_factory, @@ -470,6 +471,7 @@ class WebRtcVideoChannel2 : public rtc::MessageHandler, Settable send_codec_; std::vector send_rtp_extensions_; + VoiceMediaChannel* const voice_channel_; WebRtcVideoEncoderFactory* const external_encoder_factory_; WebRtcVideoDecoderFactory* const external_decoder_factory_; WebRtcVideoEncoderFactory2* const encoder_factory_; diff --git a/talk/media/webrtc/webrtcvideoengine2_unittest.cc b/talk/media/webrtc/webrtcvideoengine2_unittest.cc index 835bb7c451..c5ce50399d 100644 --- a/talk/media/webrtc/webrtcvideoengine2_unittest.cc +++ b/talk/media/webrtc/webrtcvideoengine2_unittest.cc @@ -34,6 +34,7 @@ #include "talk/media/webrtc/webrtcvideochannelfactory.h" #include "talk/media/webrtc/webrtcvideoengine2.h" #include "talk/media/webrtc/webrtcvideoengine2_unittest.h" +#include "talk/media/webrtc/webrtcvoiceengine.h" #include "webrtc/base/gunit.h" #include "webrtc/base/stringutils.h" #include "webrtc/video_encoder.h" @@ -328,6 +329,22 @@ class WebRtcVideoEngine2Test : public ::testing::Test { } protected: + class FakeCallFactory : public WebRtcCallFactory { + public: + FakeCallFactory() : fake_call_(NULL) {} + FakeCall* GetCall() { return fake_call_; } + + private: + virtual webrtc::Call* CreateCall( + const webrtc::Call::Config& config) OVERRIDE { + assert(fake_call_ == NULL); + fake_call_ = new FakeCall(config); + return fake_call_; + } + + FakeCall* fake_call_; + }; + VideoMediaChannel* SetUpForExternalEncoderFactory( cricket::WebRtcVideoEncoderFactory* encoder_factory, const std::vector& codecs); @@ -341,9 +358,42 @@ class WebRtcVideoEngine2Test : public ::testing::Test { VideoCodec default_rtx_codec_; }; -// TODO(pbos): Add test that verifies that sync is configured properly. -TEST_F(WebRtcVideoEngine2Test, DISABLED_CreateChannelWithVoiceEngine) { - FAIL() << "Not implemented."; // TODO(pbos): Implement. +TEST_F(WebRtcVideoEngine2Test, ConfiguresAvSyncForFirstReceiveChannel) { + FakeCallFactory call_factory; + engine_.SetCallFactory(&call_factory); + + WebRtcVoiceEngine voice_engine; + engine_.SetVoiceEngine(&voice_engine); + voice_engine.Init(rtc::Thread::Current()); + engine_.Init(rtc::Thread::Current()); + + rtc::scoped_ptr voice_channel( + voice_engine.CreateChannel()); + ASSERT_TRUE(voice_channel.get() != NULL); + WebRtcVoiceMediaChannel* webrtc_voice_channel = + static_cast(voice_channel.get()); + ASSERT_NE(webrtc_voice_channel->voe_channel(), -1); + rtc::scoped_ptr channel( + engine_.CreateChannel(cricket::VideoOptions(), voice_channel.get())); + + FakeCall* fake_call = call_factory.GetCall(); + ASSERT_TRUE(fake_call != NULL); + + webrtc::Call::Config call_config = fake_call->GetConfig(); + + ASSERT_TRUE(voice_engine.voe()->engine() != NULL); + ASSERT_EQ(voice_engine.voe()->engine(), call_config.voice_engine); + + EXPECT_TRUE(channel->AddRecvStream(StreamParams::CreateLegacy(kSsrc))); + EXPECT_TRUE(channel->AddRecvStream(StreamParams::CreateLegacy(kSsrc + 1))); + std::vector receive_streams = + fake_call->GetVideoReceiveStreams(); + + ASSERT_EQ(2u, receive_streams.size()); + EXPECT_EQ(webrtc_voice_channel->voe_channel(), + receive_streams[0]->GetConfig().audio_channel_id); + EXPECT_EQ(-1, receive_streams[1]->GetConfig().audio_channel_id) + << "AV sync should only be set up for the first receive channel."; } TEST_F(WebRtcVideoEngine2Test, FindCodec) { @@ -431,25 +481,6 @@ TEST_F(WebRtcVideoEngine2Test, SupportsAbsoluteSenderTimeHeaderExtension) { void WebRtcVideoEngine2Test::TestStartBitrate(bool override_start_bitrate, int start_bitrate_bps) { - class FakeCallFactory : public WebRtcCallFactory { - public: - FakeCallFactory() : fake_call_(NULL) {} - - FakeCall* GetCall() { - return fake_call_; - } - - private: - virtual webrtc::Call* CreateCall( - const webrtc::Call::Config& config) OVERRIDE { - assert(fake_call_ == NULL); - fake_call_ = new FakeCall(config); - return fake_call_; - } - - FakeCall* fake_call_; - }; - FakeCallFactory call_factory; engine_.SetCallFactory(&call_factory); diff --git a/webrtc/video/video_receive_stream.cc b/webrtc/video/video_receive_stream.cc index 78dc64a53b..b1822402db 100644 --- a/webrtc/video/video_receive_stream.cc +++ b/webrtc/video/video_receive_stream.cc @@ -190,7 +190,7 @@ VideoReceiveStream::VideoReceiveStream(webrtc::VideoEngine* video_engine, render_->AddRenderCallback(channel_, this); - if (voice_engine) { + if (voice_engine && config_.audio_channel_id != -1) { video_engine_base_->SetVoiceEngine(voice_engine); video_engine_base_->ConnectAudioChannel(channel_, config_.audio_channel_id); } diff --git a/webrtc/video_receive_stream.h b/webrtc/video_receive_stream.h index 2db2a0ca03..5ab898c77d 100644 --- a/webrtc/video_receive_stream.h +++ b/webrtc/video_receive_stream.h @@ -85,7 +85,7 @@ class VideoReceiveStream { Config() : renderer(NULL), render_delay_ms(0), - audio_channel_id(0), + audio_channel_id(-1), pre_decode_callback(NULL), pre_render_callback(NULL), target_delay_ms(0) {}