From 1d1ffc9ad267d7e6e9ec9001052fd4abf29d7622 Mon Sep 17 00:00:00 2001 From: "wu@webrtc.org" Date: Wed, 16 Oct 2013 18:12:02 +0000 Subject: [PATCH] Update talk to 54898858. TEST=try bots TBR=mallinath Review URL: https://webrtc-codereview.appspot.com/2414004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@4979 4adac7df-926f-26a2-2b94-8c16560cd09d --- talk/app/webrtc/mediastreamsignaling.cc | 138 -------------- talk/app/webrtc/mediastreamsignaling.h | 6 - talk/app/webrtc/webrtcsession.cc | 32 +--- talk/app/webrtc/webrtcsession.h | 6 +- talk/libjingle.gyp | 2 + talk/libjingle.scons | 2 + talk/media/base/mediachannel.h | 9 + talk/media/sctp/sctpdataengine.cc | 20 +- talk/media/sctp/sctpdataengine_unittest.cc | 44 ++++- talk/media/sctp/sctputils.cc | 176 ++++++++++++++++++ talk/media/sctp/sctputils.h | 53 ++++++ talk/media/sctp/sctputils_unittest.cc | 148 +++++++++++++++ talk/media/webrtc/webrtcvoiceengine.cc | 60 ++++-- talk/media/webrtc/webrtcvoiceengine.h | 4 + .../webrtc/webrtcvoiceengine_unittest.cc | 35 +++- talk/p2p/base/fakesession.h | 2 +- talk/session/media/channel.cc | 18 ++ talk/session/media/channel.h | 19 ++ talk/session/media/channelmanager_unittest.cc | 2 +- 19 files changed, 575 insertions(+), 201 deletions(-) create mode 100644 talk/media/sctp/sctputils.cc create mode 100644 talk/media/sctp/sctputils.h create mode 100644 talk/media/sctp/sctputils_unittest.cc diff --git a/talk/app/webrtc/mediastreamsignaling.cc b/talk/app/webrtc/mediastreamsignaling.cc index a23799f736..771a4e800f 100644 --- a/talk/app/webrtc/mediastreamsignaling.cc +++ b/talk/app/webrtc/mediastreamsignaling.cc @@ -916,144 +916,6 @@ void MediaStreamSignaling::CreateRemoteDataChannel(const std::string& label, } -// Format defined at -// http://tools.ietf.org/html/draft-jesup-rtcweb-data-protocol-04 -const uint8 DATA_CHANNEL_OPEN_MESSAGE_TYPE = 0x03; - -enum DataChannelOpenMessageChannelType { - DCOMCT_ORDERED_RELIABLE = 0x00, - DCOMCT_ORDERED_PARTIAL_RTXS = 0x01, - DCOMCT_ORDERED_PARTIAL_TIME = 0x02, - DCOMCT_UNORDERED_RELIABLE = 0x80, - DCOMCT_UNORDERED_PARTIAL_RTXS = 0x81, - DCOMCT_UNORDERED_PARTIAL_TIME = 0x82, -}; - -bool MediaStreamSignaling::ParseDataChannelOpenMessage( - const talk_base::Buffer& payload, - std::string* label, - DataChannelInit* config) { - // Format defined at - // http://tools.ietf.org/html/draft-jesup-rtcweb-data-protocol-04 - - talk_base::ByteBuffer buffer(payload.data(), payload.length()); - - uint8 message_type; - if (!buffer.ReadUInt8(&message_type)) { - LOG(LS_WARNING) << "Could not read OPEN message type."; - return false; - } - if (message_type != DATA_CHANNEL_OPEN_MESSAGE_TYPE) { - LOG(LS_WARNING) << "Data Channel OPEN message of unexpected type: " - << message_type; - return false; - } - - uint8 channel_type; - if (!buffer.ReadUInt8(&channel_type)) { - LOG(LS_WARNING) << "Could not read OPEN message channel type."; - return false; - } - uint16 priority; - if (!buffer.ReadUInt16(&priority)) { - LOG(LS_WARNING) << "Could not read OPEN message reliabilility prioirty."; - return false; - } - uint32 reliability_param; - if (!buffer.ReadUInt32(&reliability_param)) { - LOG(LS_WARNING) << "Could not read OPEN message reliabilility param."; - return false; - } - uint16 label_length; - if (!buffer.ReadUInt16(&label_length)) { - LOG(LS_WARNING) << "Could not read OPEN message label length."; - return false; - } - uint16 protocol_length; - if (!buffer.ReadUInt16(&protocol_length)) { - LOG(LS_WARNING) << "Could not read OPEN message protocol length."; - return false; - } - if (!buffer.ReadString(label, (size_t) label_length)) { - LOG(LS_WARNING) << "Could not read OPEN message label"; - return false; - } - if (!buffer.ReadString(&config->protocol, protocol_length)) { - LOG(LS_WARNING) << "Could not read OPEN message protocol."; - return false; - } - - config->ordered = true; - switch (channel_type) { - case DCOMCT_UNORDERED_RELIABLE: - case DCOMCT_UNORDERED_PARTIAL_RTXS: - case DCOMCT_UNORDERED_PARTIAL_TIME: - config->ordered = false; - } - - config->maxRetransmits = -1; - config->maxRetransmitTime = -1; - switch (channel_type) { - case DCOMCT_ORDERED_PARTIAL_RTXS: - case DCOMCT_UNORDERED_PARTIAL_RTXS: - config->maxRetransmits = reliability_param; - - case DCOMCT_ORDERED_PARTIAL_TIME: - case DCOMCT_UNORDERED_PARTIAL_TIME: - config->maxRetransmitTime = reliability_param; - } - - return true; -} - -bool MediaStreamSignaling::WriteDataChannelOpenMessage( - const std::string& label, - const DataChannelInit& config, - talk_base::Buffer* payload) { - // Format defined at - // http://tools.ietf.org/html/draft-jesup-rtcweb-data-protocol-04 - // TODO(pthatcher) - - uint8 channel_type = 0; - uint32 reliability_param = 0; - uint16 priority = 0; - if (config.ordered) { - if (config.maxRetransmits > -1) { - channel_type = DCOMCT_ORDERED_PARTIAL_RTXS; - reliability_param = config.maxRetransmits; - } else if (config.maxRetransmitTime > -1) { - channel_type = DCOMCT_ORDERED_PARTIAL_TIME; - reliability_param = config.maxRetransmitTime; - } else { - channel_type = DCOMCT_ORDERED_RELIABLE; - } - } else { - if (config.maxRetransmits > -1) { - channel_type = DCOMCT_UNORDERED_PARTIAL_RTXS; - reliability_param = config.maxRetransmits; - } else if (config.maxRetransmitTime > -1) { - channel_type = DCOMCT_UNORDERED_PARTIAL_TIME; - reliability_param = config.maxRetransmitTime; - } else { - channel_type = DCOMCT_UNORDERED_RELIABLE; - } - } - - talk_base::ByteBuffer buffer( - NULL, 20 + label.length() + config.protocol.length(), - talk_base::ByteBuffer::ORDER_NETWORK); - buffer.WriteUInt8(DATA_CHANNEL_OPEN_MESSAGE_TYPE); - buffer.WriteUInt8(channel_type); - buffer.WriteUInt16(priority); - buffer.WriteUInt32(reliability_param); - buffer.WriteUInt16(static_cast(label.length())); - buffer.WriteUInt16(static_cast(config.protocol.length())); - buffer.WriteString(label); - buffer.WriteString(config.protocol); - payload->SetData(buffer.Data(), buffer.Length()); - return true; -} - void MediaStreamSignaling::UpdateLocalSctpDataChannels() { DataChannels::iterator it = data_channels_.begin(); for (; it != data_channels_.end(); ++it) { diff --git a/talk/app/webrtc/mediastreamsignaling.h b/talk/app/webrtc/mediastreamsignaling.h index f64bf978ff..067ed2f3b7 100644 --- a/talk/app/webrtc/mediastreamsignaling.h +++ b/talk/app/webrtc/mediastreamsignaling.h @@ -196,12 +196,6 @@ class MediaStreamSignaling { // After we receive an OPEN message, create a data channel and add it. bool AddDataChannelFromOpenMessage( const std::string& label, const DataChannelInit& config); - bool ParseDataChannelOpenMessage( - const talk_base::Buffer& payload, std::string* label, - DataChannelInit* config); - bool WriteDataChannelOpenMessage( - const std::string& label, const DataChannelInit& config, - talk_base::Buffer* payload); // Returns a MediaSessionOptions struct with options decided by |constraints|, // the local MediaStreams and DataChannels. diff --git a/talk/app/webrtc/webrtcsession.cc b/talk/app/webrtc/webrtcsession.cc index c7805c16d4..74d1488e7b 100644 --- a/talk/app/webrtc/webrtcsession.cc +++ b/talk/app/webrtc/webrtcsession.cc @@ -42,6 +42,7 @@ #include "talk/base/stringencode.h" #include "talk/media/base/constants.h" #include "talk/media/base/videocapturer.h" +#include "talk/media/sctp/sctputils.h" #include "talk/session/media/channel.h" #include "talk/session/media/channelmanager.h" #include "talk/session/media/mediasession.h" @@ -1031,8 +1032,7 @@ talk_base::scoped_refptr WebRtcSession::CreateDataChannel( } if (!config->negotiated) { talk_base::Buffer *payload = new talk_base::Buffer; - if (!mediastream_signaling_->WriteDataChannelOpenMessage( - label, *config, payload)) { + if (!cricket::WriteDataChannelOpenMessage(label, *config, payload)) { LOG(LS_WARNING) << "Could not write data channel OPEN message"; } // SendControl may queue the message until the data channel's set up, @@ -1368,8 +1368,8 @@ bool WebRtcSession::CreateDataChannel(const cricket::ContentInfo* content) { if (!data_channel_.get()) { return false; } - data_channel_->SignalDataReceived.connect( - this, &WebRtcSession::OnDataReceived); + data_channel_->SignalNewStreamReceived.connect( + this, &WebRtcSession::OnNewDataChannelReceived); return true; } @@ -1386,27 +1386,11 @@ void WebRtcSession::CopySavedCandidates( saved_candidates_.clear(); } -// Look for OPEN messages and set up data channels in response. -void WebRtcSession::OnDataReceived( - cricket::DataChannel* channel, - const cricket::ReceiveDataParams& params, - const talk_base::Buffer& payload) { - if (params.type != cricket::DMT_CONTROL) { - return; - } - - std::string label; - DataChannelInit config; - if (!mediastream_signaling_->ParseDataChannelOpenMessage( - payload, &label, &config)) { - LOG(LS_WARNING) << "Failed to parse data channel OPEN message."; - return; - } - - config.negotiated = true; // This is the negotiation. - +void WebRtcSession::OnNewDataChannelReceived( + const std::string& label, const DataChannelInit& init) { + ASSERT(data_channel_type_ == cricket::DCT_SCTP); if (!mediastream_signaling_->AddDataChannelFromOpenMessage( - label, config)) { + label, init)) { LOG(LS_WARNING) << "Failed to create data channel from OPEN message."; return; } diff --git a/talk/app/webrtc/webrtcsession.h b/talk/app/webrtc/webrtcsession.h index be8979801c..12e2291c79 100644 --- a/talk/app/webrtc/webrtcsession.h +++ b/talk/app/webrtc/webrtcsession.h @@ -271,10 +271,8 @@ class WebRtcSession : public cricket::BaseSession, // The |saved_candidates_| will be cleared after this function call. void CopySavedCandidates(SessionDescriptionInterface* dest_desc); - void OnDataReceived( - cricket::DataChannel* channel, - const cricket::ReceiveDataParams& params, - const talk_base::Buffer& payload); + void OnNewDataChannelReceived(const std::string& label, + const DataChannelInit& init); bool GetLocalTrackId(uint32 ssrc, std::string* track_id); bool GetRemoteTrackId(uint32 ssrc, std::string* track_id); diff --git a/talk/libjingle.gyp b/talk/libjingle.gyp index f9edd83426..16044b515e 100755 --- a/talk/libjingle.gyp +++ b/talk/libjingle.gyp @@ -841,6 +841,8 @@ # TODO(ronghuawu): Enable when SCTP is ready. # 'media/sctp/sctpdataengine.cc', # 'media/sctp/sctpdataengine.h', + 'media/sctp/sctputils.cc', + 'media/sctp/sctputils.h', 'media/webrtc/webrtccommon.h', 'media/webrtc/webrtcexport.h', 'media/webrtc/webrtcmediaengine.h', diff --git a/talk/libjingle.scons b/talk/libjingle.scons index cfc02491d1..87b43f50ed 100644 --- a/talk/libjingle.scons +++ b/talk/libjingle.scons @@ -290,6 +290,7 @@ talk.Library(env, name = "jingle", "media/base/videoframe.cc", "media/devices/devicemanager.cc", "media/devices/filevideocapturer.cc", + "media/sctp/sctputils.cc", "session/media/audiomonitor.cc", "session/media/call.cc", "session/media/channel.cc", @@ -676,6 +677,7 @@ talk.Unittest(env, name = "media", "media/base/videocommon_unittest.cc", "media/devices/devicemanager_unittest.cc", "media/devices/filevideocapturer_unittest.cc", + "media/sctp/sctputils_unittest.cc", "session/media/channel_unittest.cc", "session/media/channelmanager_unittest.cc", "session/media/currentspeakermonitor_unittest.cc", diff --git a/talk/media/base/mediachannel.h b/talk/media/base/mediachannel.h index 7431bc1001..f90265c40b 100644 --- a/talk/media/base/mediachannel.h +++ b/talk/media/base/mediachannel.h @@ -50,6 +50,10 @@ class RateLimiter; class Timing; } +namespace webrtc { +struct DataChannelInit; +} + namespace cricket { class AudioRenderer; @@ -980,6 +984,11 @@ class DataMediaChannel : public MediaChannel { // Signal when the media channel is ready to send the stream. Arguments are: // writable(bool) sigslot::signal1 SignalReadyToSend; + // Signal for notifying when a new stream is added from the remote side. Used + // for the in-band negotioation through the OPEN message for SCTP data + // channel. + sigslot::signal2 + SignalNewStreamReceived; }; } // namespace cricket diff --git a/talk/media/sctp/sctpdataengine.cc b/talk/media/sctp/sctpdataengine.cc index 2e8e90c193..2b86001f16 100644 --- a/talk/media/sctp/sctpdataengine.cc +++ b/talk/media/sctp/sctpdataengine.cc @@ -31,12 +31,14 @@ #include #include +#include "talk/app/webrtc/datachannelinterface.h" #include "talk/base/buffer.h" #include "talk/base/helpers.h" #include "talk/base/logging.h" #include "talk/media/base/codec.h" #include "talk/media/base/constants.h" #include "talk/media/base/streamparams.h" +#include "talk/media/sctp/sctputils.h" #include "usrsctplib/usrsctp.h" namespace cricket { @@ -584,7 +586,23 @@ void SctpDataMediaChannel::OnDataFromSctpToChannel( StreamParams found_stream; if (!GetStreamBySsrc(streams_, params.ssrc, &found_stream)) { if (params.type == DMT_CONTROL) { - SignalDataReceived(params, buffer->data(), buffer->length()); + std::string label; + webrtc::DataChannelInit config; + if (ParseDataChannelOpenMessage(*buffer, &label, &config)) { + config.id = params.ssrc; + // Do not send the OPEN message for this data channel. + config.negotiated = true; + SignalNewStreamReceived(label, config); + + // Add the stream immediately. + cricket::StreamParams sparams = + cricket::StreamParams::CreateLegacy(params.ssrc); + AddSendStream(sparams); + AddRecvStream(sparams); + } else { + LOG(LS_ERROR) << debug_name_ << "->OnDataFromSctpToChannel(...): " + << "Received malformed control message"; + } } else { LOG(LS_WARNING) << debug_name_ << "->OnDataFromSctpToChannel(...): " << "Received packet for unknown ssrc: " << params.ssrc; diff --git a/talk/media/sctp/sctpdataengine_unittest.cc b/talk/media/sctp/sctpdataengine_unittest.cc index 363e7dfeb6..cab60b03f0 100644 --- a/talk/media/sctp/sctpdataengine_unittest.cc +++ b/talk/media/sctp/sctpdataengine_unittest.cc @@ -30,6 +30,7 @@ #include #include +#include "talk/app/webrtc/datachannelinterface.h" #include "talk/base/buffer.h" #include "talk/base/criticalsection.h" #include "talk/base/gunit.h" @@ -41,6 +42,7 @@ #include "talk/media/base/constants.h" #include "talk/media/base/mediachannel.h" #include "talk/media/sctp/sctpdataengine.h" +#include "talk/media/sctp/sctputils.h" enum { MSG_PACKET = 1, @@ -161,7 +163,8 @@ class SignalReadyToSendObserver : public sigslot::has_slots<> { }; // SCTP Data Engine testing framework. -class SctpDataMediaChannelTest : public testing::Test { +class SctpDataMediaChannelTest : public testing::Test, + public sigslot::has_slots<> { protected: virtual void SetUp() { engine_.reset(new cricket::SctpDataEngine()); @@ -212,6 +215,8 @@ class SctpDataMediaChannelTest : public testing::Test { // When data is received, pass it to the SctpFakeDataReceiver. channel->SignalDataReceived.connect( recv, &SctpFakeDataReceiver::OnDataReceived); + channel->SignalNewStreamReceived.connect( + this, &SctpDataMediaChannelTest::OnNewStreamReceived); return channel; } @@ -246,6 +251,14 @@ class SctpDataMediaChannelTest : public testing::Test { SctpFakeDataReceiver* receiver1() { return recv1_.get(); } SctpFakeDataReceiver* receiver2() { return recv2_.get(); } + void OnNewStreamReceived(const std::string& label, + const webrtc::DataChannelInit& init) { + last_label_ = label; + last_dc_init_ = init; + } + std::string last_label() { return last_label_; } + webrtc::DataChannelInit last_dc_init() { return last_dc_init_; } + private: talk_base::scoped_ptr engine_; talk_base::scoped_ptr net1_; @@ -254,6 +267,8 @@ class SctpDataMediaChannelTest : public testing::Test { talk_base::scoped_ptr recv2_; talk_base::scoped_ptr chan1_; talk_base::scoped_ptr chan2_; + std::string last_label_; + webrtc::DataChannelInit last_dc_init_; }; // Verifies that SignalReadyToSend is fired. @@ -316,3 +331,30 @@ TEST_F(SctpDataMediaChannelTest, SendData) { channel2()->SetSend(false); LOG(LS_VERBOSE) << "Cleaning up. -----------------------------"; } + +TEST_F(SctpDataMediaChannelTest, SendReceiveOpenMessage) { + SetupConnectedChannels(); + + std::string label("x"); + webrtc::DataChannelInit config; + config.id = 10; + + // Send the OPEN message on a unknown ssrc. + channel1()->AddSendStream(cricket::StreamParams::CreateLegacy(config.id)); + cricket::SendDataParams params; + params.ssrc = config.id; + params.type = cricket::DMT_CONTROL; + cricket::SendDataResult result; + talk_base::Buffer buffer; + ASSERT_TRUE(cricket::WriteDataChannelOpenMessage(label, config, &buffer)); + ASSERT_TRUE(channel1()->SendData(params, buffer, &result)); + // Send data on the new ssrc immediately after sending the OPEN message. + ASSERT_TRUE(SendData(channel1(), config.id, "hi chan2", &result)); + + // Verifies the received OPEN message. + EXPECT_TRUE_WAIT(last_label() == label, 1000); + EXPECT_EQ(config.id, last_dc_init().id); + EXPECT_EQ(true, last_dc_init().negotiated); + // Verifies the received data. + EXPECT_TRUE_WAIT(ReceivedData(receiver2(), config.id, "hi chan2"), 1000); +} diff --git a/talk/media/sctp/sctputils.cc b/talk/media/sctp/sctputils.cc new file mode 100644 index 0000000000..c33c64e06f --- /dev/null +++ b/talk/media/sctp/sctputils.cc @@ -0,0 +1,176 @@ +/* + * libjingle + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "talk/media/sctp/sctputils.h" + +#include "talk/app/webrtc/datachannelinterface.h" +#include "talk/base/buffer.h" +#include "talk/base/bytebuffer.h" +#include "talk/base/logging.h" + +namespace cricket { + +// Format defined at +// http://tools.ietf.org/html/draft-jesup-rtcweb-data-protocol-04 + +static const uint8 DATA_CHANNEL_OPEN_MESSAGE_TYPE = 0x03; + +enum DataChannelOpenMessageChannelType { + DCOMCT_ORDERED_RELIABLE = 0x00, + DCOMCT_ORDERED_PARTIAL_RTXS = 0x01, + DCOMCT_ORDERED_PARTIAL_TIME = 0x02, + DCOMCT_UNORDERED_RELIABLE = 0x80, + DCOMCT_UNORDERED_PARTIAL_RTXS = 0x81, + DCOMCT_UNORDERED_PARTIAL_TIME = 0x82, +}; + +bool ParseDataChannelOpenMessage( + const talk_base::Buffer& payload, + std::string* label, + webrtc::DataChannelInit* config) { + // Format defined at + // http://tools.ietf.org/html/draft-jesup-rtcweb-data-protocol-04 + + talk_base::ByteBuffer buffer(payload.data(), payload.length()); + + uint8 message_type; + if (!buffer.ReadUInt8(&message_type)) { + LOG(LS_WARNING) << "Could not read OPEN message type."; + return false; + } + if (message_type != DATA_CHANNEL_OPEN_MESSAGE_TYPE) { + LOG(LS_WARNING) << "Data Channel OPEN message of unexpected type: " + << message_type; + return false; + } + + uint8 channel_type; + if (!buffer.ReadUInt8(&channel_type)) { + LOG(LS_WARNING) << "Could not read OPEN message channel type."; + return false; + } + uint16 reliability_param; + if (!buffer.ReadUInt16(&reliability_param)) { + LOG(LS_WARNING) << "Could not read OPEN message reliabilility param."; + return false; + } + uint16 priority; + if (!buffer.ReadUInt16(&priority)) { + LOG(LS_WARNING) << "Could not read OPEN message reliabilility prioirty."; + return false; + } + uint16 label_length; + if (!buffer.ReadUInt16(&label_length)) { + LOG(LS_WARNING) << "Could not read OPEN message label length."; + return false; + } + uint16 protocol_length; + if (!buffer.ReadUInt16(&protocol_length)) { + LOG(LS_WARNING) << "Could not read OPEN message protocol length."; + return false; + } + if (!buffer.ReadString(label, (size_t) label_length)) { + LOG(LS_WARNING) << "Could not read OPEN message label"; + return false; + } + if (!buffer.ReadString(&config->protocol, protocol_length)) { + LOG(LS_WARNING) << "Could not read OPEN message protocol."; + return false; + } + + config->ordered = true; + switch (channel_type) { + case DCOMCT_UNORDERED_RELIABLE: + case DCOMCT_UNORDERED_PARTIAL_RTXS: + case DCOMCT_UNORDERED_PARTIAL_TIME: + config->ordered = false; + } + + config->maxRetransmits = -1; + config->maxRetransmitTime = -1; + switch (channel_type) { + case DCOMCT_ORDERED_PARTIAL_RTXS: + case DCOMCT_UNORDERED_PARTIAL_RTXS: + config->maxRetransmits = reliability_param; + + case DCOMCT_ORDERED_PARTIAL_TIME: + case DCOMCT_UNORDERED_PARTIAL_TIME: + config->maxRetransmitTime = reliability_param; + } + + return true; +} + +bool WriteDataChannelOpenMessage( + const std::string& label, + const webrtc::DataChannelInit& config, + talk_base::Buffer* payload) { + // Format defined at + // http://tools.ietf.org/html/draft-jesup-rtcweb-data-protocol-04 + // TODO(pthatcher) + + uint8 channel_type = 0; + uint16 reliability_param = 0; + uint16 priority = 0; + if (config.ordered) { + if (config.maxRetransmits > -1) { + channel_type = DCOMCT_ORDERED_PARTIAL_RTXS; + reliability_param = config.maxRetransmits; + } else if (config.maxRetransmitTime > -1) { + channel_type = DCOMCT_ORDERED_PARTIAL_TIME; + reliability_param = config.maxRetransmitTime; + } else { + channel_type = DCOMCT_ORDERED_RELIABLE; + } + } else { + if (config.maxRetransmits > -1) { + channel_type = DCOMCT_UNORDERED_PARTIAL_RTXS; + reliability_param = config.maxRetransmits; + } else if (config.maxRetransmitTime > -1) { + channel_type = DCOMCT_UNORDERED_PARTIAL_TIME; + reliability_param = config.maxRetransmitTime; + } else { + channel_type = DCOMCT_UNORDERED_RELIABLE; + } + } + + talk_base::ByteBuffer buffer( + NULL, 20 + label.length() + config.protocol.length(), + talk_base::ByteBuffer::ORDER_NETWORK); + buffer.WriteUInt8(DATA_CHANNEL_OPEN_MESSAGE_TYPE); + buffer.WriteUInt8(channel_type); + buffer.WriteUInt16(reliability_param); + buffer.WriteUInt16(priority); + buffer.WriteUInt16(static_cast(label.length())); + buffer.WriteUInt16(static_cast(config.protocol.length())); + buffer.WriteString(label); + buffer.WriteString(config.protocol); + payload->SetData(buffer.Data(), buffer.Length()); + return true; +} + +} // namespace cricket diff --git a/talk/media/sctp/sctputils.h b/talk/media/sctp/sctputils.h new file mode 100644 index 0000000000..d349274a9a --- /dev/null +++ b/talk/media/sctp/sctputils.h @@ -0,0 +1,53 @@ +/* + * libjingle + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TALK_MEDIA_BASE_SCTPUTILS_H_ +#define TALK_MEDIA_BASE_SCTPUTILS_H_ + +#include + +namespace talk_base { +class Buffer; +} // namespace talk_base + +namespace webrtc { +struct DataChannelInit; +} // namespace webrtc + +namespace cricket { + +bool ParseDataChannelOpenMessage(const talk_base::Buffer& payload, + std::string* label, + webrtc::DataChannelInit* config); + +bool WriteDataChannelOpenMessage(const std::string& label, + const webrtc::DataChannelInit& config, + talk_base::Buffer* payload); + +} // namespace cricket + +#endif // TALK_MEDIA_BASE_SCTPUTILS_H_ diff --git a/talk/media/sctp/sctputils_unittest.cc b/talk/media/sctp/sctputils_unittest.cc new file mode 100644 index 0000000000..1cc9a709f9 --- /dev/null +++ b/talk/media/sctp/sctputils_unittest.cc @@ -0,0 +1,148 @@ +/* + * libjingle + * Copyright 2013 Google Inc + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "talk/app/webrtc/datachannelinterface.h" +#include "talk/base/bytebuffer.h" +#include "talk/base/gunit.h" +#include "talk/media/sctp/sctputils.h" + +class SctpUtilsTest : public testing::Test { + public: + void VerifyOpenMessageFormat(const talk_base::Buffer& packet, + const std::string& label, + const webrtc::DataChannelInit& config) { + uint8 message_type; + uint8 channel_type; + uint16 reliability; + uint16 priority; + uint16 label_length; + uint16 protocol_length; + + talk_base::ByteBuffer buffer(packet.data(), packet.length()); + ASSERT_TRUE(buffer.ReadUInt8(&message_type)); + EXPECT_EQ(0x03, message_type); + + ASSERT_TRUE(buffer.ReadUInt8(&channel_type)); + if (config.ordered) { + EXPECT_EQ(config.maxRetransmits > -1 ? + 0x01 : (config.maxRetransmitTime > -1 ? 0x02 : 0), + channel_type); + } else { + EXPECT_EQ(config.maxRetransmits > -1 ? + 0x81 : (config.maxRetransmitTime > -1 ? 0x82 : 0x80), + channel_type); + } + + ASSERT_TRUE(buffer.ReadUInt16(&reliability)); + if (config.maxRetransmits > -1 || config.maxRetransmitTime > -1) { + EXPECT_EQ(config.maxRetransmits > -1 ? + config.maxRetransmits : config.maxRetransmitTime, + reliability); + } + + ASSERT_TRUE(buffer.ReadUInt16(&priority)); + + ASSERT_TRUE(buffer.ReadUInt16(&label_length)); + ASSERT_TRUE(buffer.ReadUInt16(&protocol_length)); + EXPECT_EQ(label.size(), label_length); + EXPECT_EQ(config.protocol.size(), protocol_length); + + std::string label_output; + ASSERT_TRUE(buffer.ReadString(&label_output, label_length)); + EXPECT_EQ(label, label_output); + std::string protocol_output; + ASSERT_TRUE(buffer.ReadString(&protocol_output, protocol_length)); + EXPECT_EQ(config.protocol, protocol_output); + } +}; + +TEST_F(SctpUtilsTest, WriteParseMessageWithOrderedReliable) { + std::string input_label = "abc"; + webrtc::DataChannelInit config; + config.protocol = "y"; + + talk_base::Buffer packet; + ASSERT(cricket::WriteDataChannelOpenMessage(input_label, config, &packet)); + + VerifyOpenMessageFormat(packet, input_label, config); + + std::string output_label; + webrtc::DataChannelInit output_config; + ASSERT(cricket::ParseDataChannelOpenMessage( + packet, &output_label, &output_config)); + + EXPECT_EQ(input_label, output_label); + EXPECT_EQ(config.protocol, output_config.protocol); + EXPECT_EQ(config.ordered, output_config.ordered); + EXPECT_EQ(config.maxRetransmitTime, output_config.maxRetransmitTime); + EXPECT_EQ(config.maxRetransmits, output_config.maxRetransmits); +} + +TEST_F(SctpUtilsTest, WriteParseOpenMessageWithMaxRetransmitTime) { + std::string input_label = "abc"; + webrtc::DataChannelInit config; + config.ordered = false; + config.maxRetransmitTime = 10; + config.protocol = "y"; + + talk_base::Buffer packet; + ASSERT(cricket::WriteDataChannelOpenMessage(input_label, config, &packet)); + + VerifyOpenMessageFormat(packet, input_label, config); + + std::string output_label; + webrtc::DataChannelInit output_config; + ASSERT(cricket::ParseDataChannelOpenMessage( + packet, &output_label, &output_config)); + + EXPECT_EQ(input_label, output_label); + EXPECT_EQ(config.protocol, output_config.protocol); + EXPECT_EQ(config.ordered, output_config.ordered); + EXPECT_EQ(config.maxRetransmitTime, output_config.maxRetransmitTime); +} + +TEST_F(SctpUtilsTest, WriteParseOpenMessageWithMaxRetransmits) { + std::string input_label = "abc"; + webrtc::DataChannelInit config; + config.maxRetransmits = 10; + config.protocol = "y"; + + talk_base::Buffer packet; + ASSERT(cricket::WriteDataChannelOpenMessage(input_label, config, &packet)); + + VerifyOpenMessageFormat(packet, input_label, config); + + std::string output_label; + webrtc::DataChannelInit output_config; + ASSERT(cricket::ParseDataChannelOpenMessage( + packet, &output_label, &output_config)); + + EXPECT_EQ(input_label, output_label); + EXPECT_EQ(config.protocol, output_config.protocol); + EXPECT_EQ(config.ordered, output_config.ordered); + EXPECT_EQ(config.maxRetransmits, output_config.maxRetransmits); +} diff --git a/talk/media/webrtc/webrtcvoiceengine.cc b/talk/media/webrtc/webrtcvoiceengine.cc index 5c16d6e626..83cbdaf573 100644 --- a/talk/media/webrtc/webrtcvoiceengine.cc +++ b/talk/media/webrtc/webrtcvoiceengine.cc @@ -204,11 +204,30 @@ static bool FindCodec(const std::vector& codecs, } return false; } + static bool IsNackEnabled(const AudioCodec& codec) { return codec.HasFeedbackParam(FeedbackParam(kRtcpFbParamNack, kParamValueEmpty)); } +// Gets the default set of options applied to the engine. Historically, these +// were supplied as a combination of flags from the channel manager (ec, agc, +// ns, and highpass) and the rest hardcoded in InitInternal. +static AudioOptions GetDefaultEngineOptions() { + AudioOptions options; + options.echo_cancellation.Set(true); + options.auto_gain_control.Set(true); + options.noise_suppression.Set(true); + options.highpass_filter.Set(true); + options.stereo_swapping.Set(false); + options.typing_detection.Set(true); + options.conference_mode.Set(false); + options.adjust_agc_delta.Set(0); + options.experimental_agc.Set(false); + options.experimental_aec.Set(false); + options.aec_dump.Set(false); + return options; +} class WebRtcSoundclipMedia : public SoundclipMedia { public: @@ -353,6 +372,7 @@ void WebRtcVoiceEngine::Construct() { rtp_header_extensions_.push_back( RtpHeaderExtension(kRtpAudioLevelHeaderExtension, kRtpAudioLevelHeaderExtensionId)); + options_ = GetDefaultEngineOptions(); } static bool IsOpus(const AudioCodec& codec) { @@ -482,24 +502,6 @@ bool WebRtcVoiceEngine::Init(talk_base::Thread* worker_thread) { return res; } -// Gets the default set of optoins applied to the engine. Historically, these -// were supplied as a combination of flags from the channel manager (ec, agc, -// ns, and highpass) and the rest hardcoded in InitInternal. -static AudioOptions GetDefaultEngineOptions() { - AudioOptions options; - options.echo_cancellation.Set(true); - options.auto_gain_control.Set(true); - options.noise_suppression.Set(true); - options.highpass_filter.Set(true); - options.typing_detection.Set(true); - options.conference_mode.Set(false); - options.adjust_agc_delta.Set(0); - options.experimental_agc.Set(false); - options.experimental_aec.Set(false); - options.aec_dump.Set(false); - return options; -} - bool WebRtcVoiceEngine::InitInternal() { // Temporarily turn logging level up for the Init call int old_filter = log_filter_; @@ -1524,6 +1526,9 @@ WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine *engine) : WebRtcMediaChannel( engine, engine->voe()->base()->CreateChannel()), + send_bw_setting_(false), + send_autobw_(false), + send_bw_bps_(0), options_(), dtmf_allowed_(false), desired_playout_(false), @@ -1828,6 +1833,10 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs( // Always update the |send_codec_| to the currently set send codec. send_codec_.reset(new webrtc::CodecInst(send_codec)); + if (send_bw_setting_) { + SetSendBandwidthInternal(send_autobw_, send_bw_bps_); + } + return true; } @@ -2731,9 +2740,20 @@ bool WebRtcVoiceMediaChannel::MuteStream(uint32 ssrc, bool muted) { bool WebRtcVoiceMediaChannel::SetSendBandwidth(bool autobw, int bps) { LOG(LS_INFO) << "WebRtcVoiceMediaChanne::SetSendBandwidth."; + send_bw_setting_ = true; + send_autobw_ = autobw; + send_bw_bps_ = bps; + + return SetSendBandwidthInternal(send_autobw_, send_bw_bps_); +} + +bool WebRtcVoiceMediaChannel::SetSendBandwidthInternal(bool autobw, int bps) { + LOG(LS_INFO) << "WebRtcVoiceMediaChanne::SetSendBandwidthInternal."; + if (!send_codec_) { - LOG(LS_INFO) << "The send codec has not been set up yet."; - return false; + LOG(LS_INFO) << "The send codec has not been set up yet. " + << "The send bandwidth setting will be applied later."; + return true; } // Bandwidth is auto by default. diff --git a/talk/media/webrtc/webrtcvoiceengine.h b/talk/media/webrtc/webrtcvoiceengine.h index 7809706a8c..b8b50b0bef 100644 --- a/talk/media/webrtc/webrtcvoiceengine.h +++ b/talk/media/webrtc/webrtcvoiceengine.h @@ -392,12 +392,16 @@ class WebRtcVoiceMediaChannel return channel_id == voe_channel(); } bool SetSendCodecs(int channel, const std::vector& codecs); + bool SetSendBandwidthInternal(bool autobw, int bps); talk_base::scoped_ptr ringback_tone_; std::set ringback_channels_; // channels playing ringback std::vector recv_codecs_; std::vector send_codecs_; talk_base::scoped_ptr send_codec_; + bool send_bw_setting_; + bool send_autobw_; + int send_bw_bps_; AudioOptions options_; bool dtmf_allowed_; bool desired_playout_; diff --git a/talk/media/webrtc/webrtcvoiceengine_unittest.cc b/talk/media/webrtc/webrtcvoiceengine_unittest.cc index 8dc0dffbc7..acefc38cdc 100644 --- a/talk/media/webrtc/webrtcvoiceengine_unittest.cc +++ b/talk/media/webrtc/webrtcvoiceengine_unittest.cc @@ -212,13 +212,10 @@ class WebRtcVoiceEngineTestFake : public testing::Test { codecs.push_back(codec); EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - webrtc::CodecInst temp_codec; - EXPECT_FALSE(voe_.GetSendCodec(channel_num, temp_codec)); - EXPECT_EQ(default_bitrate, temp_codec.rate); - bool result = channel_->SetSendBandwidth(auto_bitrate, desired_bitrate); EXPECT_EQ(expected_result, result); + webrtc::CodecInst temp_codec; EXPECT_FALSE(voe_.GetSendCodec(channel_num, temp_codec)); if (result) { @@ -589,7 +586,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendBandwidthAuto) { TestSendBandwidth(kOpusCodec, 64000, true, 96000, true); } -TEST_F(WebRtcVoiceEngineTestFake, SetSendBandwidthFixedMultiRate) { +TEST_F(WebRtcVoiceEngineTestFake, SetSendBandwidthFixedMultiRateAsCaller) { EXPECT_TRUE(SetupEngine()); EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); @@ -606,6 +603,24 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendBandwidthFixedMultiRate) { TestSendBandwidth(kOpusCodec, 64000, false, 96000, true); } +TEST_F(WebRtcVoiceEngineTestFake, SetSendBandwidthFixedMultiRateAsCallee) { + EXPECT_TRUE(engine_.Init(talk_base::Thread::Current())); + channel_ = engine_.CreateChannel(); + EXPECT_TRUE(channel_ != NULL); + EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); + + int desired_bitrate = 128000; + EXPECT_TRUE(channel_->SetSendBandwidth(false, desired_bitrate)); + + EXPECT_TRUE(channel_->AddSendStream( + cricket::StreamParams::CreateLegacy(kSsrc1))); + + int channel_num = voe_.GetLastChannel(); + webrtc::CodecInst codec; + EXPECT_EQ(0, voe_.GetSendCodec(channel_num, codec)); + EXPECT_EQ(desired_bitrate, codec.rate); +} + // Test that bitrate cannot be set for CBR codecs. // Bitrate is ignored if it is higher than the fixed bitrate. // Bitrate less then the fixed bitrate is an error. @@ -2606,6 +2621,16 @@ TEST_F(WebRtcVoiceEngineTestFake, SetOptionOverridesViaChannels) { EXPECT_FALSE(ns_enabled); } +TEST(WebRtcVoiceEngineTest, TestDefaultOptionsBeforeInit) { + cricket::WebRtcVoiceEngine engine; + cricket::AudioOptions options = engine.GetOptions(); + // The default options should have at least a few things set. We purposefully + // don't check the option values here, though. + EXPECT_TRUE(options.echo_cancellation.IsSet()); + EXPECT_TRUE(options.auto_gain_control.IsSet()); + EXPECT_TRUE(options.noise_suppression.IsSet()); +} + // Test that GetReceiveChannelNum returns the default channel for the first // recv stream in 1-1 calls. TEST_F(WebRtcVoiceEngineTestFake, TestGetReceiveChannelNumIn1To1Calls) { diff --git a/talk/p2p/base/fakesession.h b/talk/p2p/base/fakesession.h index 9a8fadaf2c..6a8ab4bdee 100644 --- a/talk/p2p/base/fakesession.h +++ b/talk/p2p/base/fakesession.h @@ -424,7 +424,7 @@ class FakeSession : public BaseSession { NULL, "", "", initiator), fail_create_channel_(false) { } - FakeSession(bool initiator, talk_base::Thread* worker_thread) + FakeSession(talk_base::Thread* worker_thread, bool initiator) : BaseSession(talk_base::Thread::Current(), worker_thread, NULL, "", "", initiator), diff --git a/talk/session/media/channel.cc b/talk/session/media/channel.cc index 1cb5992e69..db169bea40 100644 --- a/talk/session/media/channel.cc +++ b/talk/session/media/channel.cc @@ -81,6 +81,7 @@ enum { MSG_SETSCREENCASTFACTORY, MSG_FIRSTPACKETRECEIVED, MSG_SESSION_ERROR, + MSG_NEWSTREAMRECEIVED, }; // Value specified in RFC 5764. @@ -2500,6 +2501,8 @@ bool DataChannel::Init() { this, &DataChannel::OnDataChannelError); media_channel()->SignalReadyToSend.connect( this, &DataChannel::OnDataChannelReadyToSend); + media_channel()->SignalNewStreamReceived.connect( + this, &DataChannel::OnDataChannelNewStreamReceived); srtp_filter()->SignalSrtpError.connect( this, &DataChannel::OnSrtpError); return true; @@ -2722,6 +2725,13 @@ void DataChannel::OnMessage(talk_base::Message *pmsg) { delete data; break; } + case MSG_NEWSTREAMRECEIVED: { + DataChannelNewStreamReceivedMessageData* data = + static_cast(pmsg->pdata); + SignalNewStreamReceived(data->label, data->init); + delete data; + break; + } default: BaseChannel::OnMessage(pmsg); break; @@ -2777,6 +2787,14 @@ void DataChannel::OnDataChannelReadyToSend(bool writable) { new DataChannelReadyToSendMessageData(writable)); } +void DataChannel::OnDataChannelNewStreamReceived( + const std::string& label, const webrtc::DataChannelInit& init) { + signaling_thread()->Post( + this, + MSG_NEWSTREAMRECEIVED, + new DataChannelNewStreamReceivedMessageData(label, init)); +} + void DataChannel::OnSrtpError(uint32 ssrc, SrtpFilter::Mode mode, SrtpFilter::Error error) { switch (error) { diff --git a/talk/session/media/channel.h b/talk/session/media/channel.h index 6ee2e8cda4..3a627ed02a 100644 --- a/talk/session/media/channel.h +++ b/talk/session/media/channel.h @@ -31,6 +31,7 @@ #include #include +#include "talk/app/webrtc/datachannelinterface.h" #include "talk/base/asyncudpsocket.h" #include "talk/base/criticalsection.h" #include "talk/base/network.h" @@ -627,6 +628,11 @@ class DataChannel : public BaseChannel { // That occurs when the channel is enabled, the transport is writable, // both local and remote descriptions are set, and the channel is unblocked. sigslot::signal1 SignalReadyToSendData; + // Signal for notifying when a new stream is added from the remote side. Used + // for the in-band negotioation through the OPEN message for SCTP data + // channel. + sigslot::signal2 + SignalNewStreamReceived; protected: // downcasts a MediaChannel. @@ -666,6 +672,17 @@ class DataChannel : public BaseChannel { typedef talk_base::TypedMessageData DataChannelReadyToSendMessageData; + struct DataChannelNewStreamReceivedMessageData + : public talk_base::MessageData { + DataChannelNewStreamReceivedMessageData( + const std::string& label, const webrtc::DataChannelInit& init) + : label(label), + init(init) { + } + const std::string label; + const webrtc::DataChannelInit init; + }; + // overrides from BaseChannel virtual const ContentInfo* GetFirstContent(const SessionDescription* sdesc); // If data_channel_type_ is DCT_NONE, set it. Otherwise, check that @@ -694,6 +711,8 @@ class DataChannel : public BaseChannel { const ReceiveDataParams& params, const char* data, size_t len); void OnDataChannelError(uint32 ssrc, DataMediaChannel::Error error); void OnDataChannelReadyToSend(bool writable); + void OnDataChannelNewStreamReceived(const std::string& label, + const webrtc::DataChannelInit& init); void OnSrtpError(uint32 ssrc, SrtpFilter::Mode mode, SrtpFilter::Error error); talk_base::scoped_ptr media_monitor_; diff --git a/talk/session/media/channelmanager_unittest.cc b/talk/session/media/channelmanager_unittest.cc index d0ba8b9341..d0d380d3eb 100644 --- a/talk/session/media/channelmanager_unittest.cc +++ b/talk/session/media/channelmanager_unittest.cc @@ -154,7 +154,7 @@ TEST_F(ChannelManagerTest, CreateDestroyChannelsOnThread) { EXPECT_TRUE(cm_->set_worker_thread(&worker_)); EXPECT_TRUE(cm_->Init()); delete session_; - session_ = new cricket::FakeSession(true, &worker_); + session_ = new cricket::FakeSession(&worker_, true); cricket::VoiceChannel* voice_channel = cm_->CreateVoiceChannel( session_, cricket::CN_AUDIO, false); EXPECT_TRUE(voice_channel != NULL);