Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Update libjingle to 42149930.

Review URL: https://webrtc-codereview.appspot.com/1098006

git-svn-id: http://libjingle.googlecode.com/svn/trunk@276 dd674b97-3498-5ee5-1854-bdd07cd0ff33
  • Loading branch information...
commit 7b4a72f8fe86d56c8cba27cda82723b026f7d389 1 parent 072110d
mallinath@google.com authored
Showing with 1,339 additions and 736 deletions.
  1. +4 −4 codereview.settings
  2. +4 −5 talk/app/webrtc/java/jni/peerconnection_jni.cc
  3. +1 −114 talk/app/webrtc/jsep.h
  4. +2 −0  talk/app/webrtc/jsepsessiondescription.cc
  5. +3 −0  talk/app/webrtc/mediastreaminterface.h
  6. +132 −27 talk/app/webrtc/mediastreamsignaling.cc
  7. +9 −12 talk/app/webrtc/mediastreamsignaling.h
  8. +142 −53 talk/app/webrtc/mediastreamsignaling_unittest.cc
  9. +5 −3 talk/app/webrtc/peerconnection.cc
  10. +1 −1  talk/app/webrtc/peerconnection.h
  11. +2 −2 talk/app/webrtc/peerconnection_unittest.cc
  12. +5 −5 talk/app/webrtc/peerconnectionfactory.cc
  13. +10 −8 talk/app/webrtc/peerconnectionfactory.h
  14. +5 −5 talk/app/webrtc/peerconnectionfactory_unittest.cc
  15. +69 −10 talk/app/webrtc/peerconnectioninterface.h
  16. +43 −12 talk/app/webrtc/peerconnectioninterface_unittest.cc
  17. +1 −1  talk/app/webrtc/peerconnectionproxy.cc
  18. +2 −6 talk/app/webrtc/peerconnectionproxy_unittest.cc
  19. +3 −3 talk/app/webrtc/statscollector.cc
  20. +136 −0 talk/app/webrtc/statscollector_unittest.cc
  21. +1 −1  talk/app/webrtc/statstypes.h
  22. +20 −0 talk/app/webrtc/test/fakeconstraints.h
  23. +5 −10 talk/app/webrtc/webrtcsdp.cc
  24. +5 −0 talk/app/webrtc/webrtcsdp_unittest.cc
  25. +16 −49 talk/app/webrtc/webrtcsession.cc
  26. +23 −11 talk/app/webrtc/webrtcsession.h
  27. +279 −295 talk/app/webrtc/webrtcsession_unittest.cc
  28. +8 −7 talk/base/base64.cc
  29. +9 −6 talk/base/socket_unittest.cc
  30. +3 −3 talk/examples/call/call_main.cc
  31. +2 −2 talk/examples/call/callclient_unittest.cc
  32. +1 −1  talk/examples/login/login_main.cc
  33. +2 −2 talk/examples/pcp/pcp_main.cc
  34. +9 −9 talk/libjingle_examples.gyp
  35. +2 −1  talk/libjingle_tests.gyp
  36. +6 −6 talk/media/base/mediachannel.h
  37. +6 −0 talk/media/base/videocapturer.cc
  38. +1 −1  talk/media/base/videoframe_unittest.h
  39. +6 −0 talk/media/webrtc/webrtcvoiceengine.cc
  40. +6 −3 talk/p2p/base/transportdescriptionfactory.cc
  41. +8 −2 talk/p2p/base/transportdescriptionfactory.h
  42. +139 −35 talk/p2p/base/transportdescriptionfactory_unittest.cc
  43. +51 −11 talk/session/media/mediasession.cc
  44. +15 −1 talk/session/media/mediasession.h
  45. +103 −2 talk/session/media/mediasession_unittest.cc
  46. +1 −0  talk/session/media/typingmonitor.cc
  47. +3 −2 talk/session/tunnel/tunnelsessionclient.cc
  48. +5 −0 talk/xmpp/xmpppump.cc
  49. +6 −2 talk/xmpp/xmpppump.h
  50. +5 −0 talk/xmpp/xmppsocket.cc
  51. +4 −0 talk/xmpp/xmppsocket.h
  52. +4 −1 talk/xmpp/xmppthread.cc
  53. +6 −2 talk/xmpp/xmppthread.h
View
8 codereview.settings
@@ -2,11 +2,11 @@
CODE_REVIEW_SERVER: webrtc-codereview.appspot.com
#CC_LIST:
VIEW_VC: https://code.google.com/p/libjingle/source/detail?r=
-#STATUS:
+#STATUS:
TRY_ON_UPLOAD: False
TRYSERVER_HTTP_HOST: webrtc-cb-linux-master.cbf.corp.google.com
TRYSERVER_HTTP_PORT: 9019
TRYSERVER_ROOT: src
-#TRYSERVER_SVN_URL:
-#GITCL_PREUPLOAD:
-#GITCL_PREDCOMMIT:
+#TRYSERVER_SVN_URL:
+#GITCL_PREUPLOAD:
+#GITCL_PREDCOMMIT:
View
9 talk/app/webrtc/java/jni/peerconnection_jni.cc
@@ -72,7 +72,6 @@ using webrtc::AudioSourceInterface;
using webrtc::AudioTrackInterface;
using webrtc::CreateSessionDescriptionObserver;
using webrtc::IceCandidateInterface;
-using webrtc::JsepInterface;
using webrtc::LocalMediaStreamInterface;
using webrtc::MediaConstraintsInterface;
using webrtc::MediaSourceInterface;
@@ -649,7 +648,7 @@ JOW(jlong, PeerConnectionFactory_nativeCreateAudioTrack)(
static void JavaIceServersToJsepIceServers(
JNIEnv* jni, jobject j_ice_servers,
- JsepInterface::IceServers* ice_servers) {
+ PeerConnectionInterface::IceServers* ice_servers) {
jclass list_class = GetObjectClass(jni, j_ice_servers);
jmethodID iterator_id = GetMethodID(
jni, list_class, "iterator", "()Ljava/util/Iterator;");
@@ -672,7 +671,7 @@ static void JavaIceServersToJsepIceServers(
GetObjectField(jni, j_ice_server, j_ice_server_uri_id));
jstring password = reinterpret_cast<jstring>(
GetObjectField(jni, j_ice_server, j_ice_server_password_id));
- JsepInterface::IceServer server;
+ PeerConnectionInterface::IceServer server;
server.uri = JavaToStdString(jni, uri);
server.password = JavaToStdString(jni, password);
ice_servers->push_back(server);
@@ -685,7 +684,7 @@ JOW(jlong, PeerConnectionFactory_nativeCreatePeerConnection)(
jobject j_constraints, jlong observer_p) {
talk_base::scoped_refptr<PeerConnectionFactoryInterface> f(
reinterpret_cast<PeerConnectionFactoryInterface*>(factory));
- JsepInterface::IceServers servers;
+ PeerConnectionInterface::IceServers servers;
JavaIceServersToJsepIceServers(jni, j_ice_servers, &servers);
PCOJava* observer = reinterpret_cast<PCOJava*>(observer_p);
observer->SetConstraints(new ConstraintsWrapper(jni, j_constraints));
@@ -779,7 +778,7 @@ JOW(void, PeerConnection_setRemoteDescription)(
JOW(jboolean, PeerConnection_updateIce)(
JNIEnv* jni, jobject j_pc, jobject j_ice_servers, jobject j_constraints) {
- JsepInterface::IceServers ice_servers;
+ PeerConnectionInterface::IceServers ice_servers;
JavaIceServersToJsepIceServers(jni, j_ice_servers, &ice_servers);
talk_base::scoped_ptr<ConstraintsWrapper> constraints(
new ConstraintsWrapper(jni, j_constraints));
View
115 talk/app/webrtc/jsep.h
@@ -25,10 +25,7 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-// Interfaces matching the draft-ietf-rtcweb-jsep-00.
-// TODO(ronghuawu): Remove all the jsep-00 APIs (marked as deprecated) once
-// chromium (WebKit and glue code) is ready. And update the comment above to
-// jsep-01.
+// Interfaces matching the draft-ietf-rtcweb-jsep-01.
#ifndef TALK_APP_WEBRTC_JSEP_H_
#define TALK_APP_WEBRTC_JSEP_H_
@@ -46,43 +43,6 @@ class Candidate;
namespace webrtc {
-class MediaConstraintsInterface;
-
-class SessionDescriptionOptions {
- public:
- SessionDescriptionOptions() : has_audio_(true), has_video_(true) {}
- SessionDescriptionOptions(bool receive_audio, bool receive_video)
- : has_audio_(receive_audio),
- has_video_(receive_video) {
- }
- // The peer wants to receive audio.
- bool has_audio() const { return has_audio_; }
- // The peer wants to receive video.
- bool has_video() const { return has_video_; }
-
- private:
- bool has_audio_;
- bool has_video_;
-};
-
-// Class used for describing what media a PeerConnection can receive.
-class MediaHints { // Deprecated (jsep00)
- public:
- MediaHints() : has_audio_(true), has_video_(true) {}
- MediaHints(bool receive_audio, bool receive_video)
- : has_audio_(receive_audio),
- has_video_(receive_video) {
- }
- // The peer wants to receive audio.
- bool has_audio() const { return has_audio_; }
- // The peer wants to receive video.
- bool has_video() const { return has_video_; }
-
- private:
- bool has_audio_;
- bool has_video_;
-};
-
// Class representation of an ICE candidate.
// An instance of this interface is supposed to be owned by one class at
// a time and is therefore not expected to be thread safe.
@@ -156,23 +116,6 @@ class SessionDescriptionInterface {
SessionDescriptionInterface* CreateSessionDescription(const std::string& type,
const std::string& sdp);
-// Jsep Ice candidate callback interface. An application should implement these
-// methods to be notified of new local candidates.
-class IceCandidateObserver {
- public:
- // TODO(ronghuawu): Implement OnIceChange.
- // Called any time the iceState changes.
- virtual void OnIceChange() {}
- // New Ice candidate have been found.
- virtual void OnIceCandidate(const IceCandidateInterface* candidate) = 0;
- // All Ice candidates have been found.
- // Deprecated (jsep00)
- virtual void OnIceComplete() {}
-
- protected:
- ~IceCandidateObserver() {}
-};
-
// Jsep CreateOffer and CreateAnswer callback interface.
class CreateSessionDescriptionObserver : public talk_base::RefCountInterface {
public:
@@ -195,62 +138,6 @@ class SetSessionDescriptionObserver : public talk_base::RefCountInterface {
~SetSessionDescriptionObserver() {}
};
-// Interface for implementing Jsep. PeerConnection implements these functions.
-class JsepInterface {
- public:
- // Indicates what types of local candidates should be used.
- // Deprecated (jsep00)
- enum IceOptions {
- kUseAll,
- kNoRelay,
- kOnlyRelay
- };
-
- struct IceServer {
- std::string uri;
- std::string password;
- };
-
- typedef std::vector<IceServer> IceServers;
-
- virtual const SessionDescriptionInterface* local_description() const = 0;
- virtual const SessionDescriptionInterface* remote_description() const = 0;
-
- // JSEP01
- // Create a new offer.
- // The CreateSessionDescriptionObserver callback will be called when done.
- virtual void CreateOffer(CreateSessionDescriptionObserver* observer,
- const MediaConstraintsInterface* constraints) = 0;
- // Create an answer to an offer.
- // The CreateSessionDescriptionObserver callback will be called when done.
- virtual void CreateAnswer(CreateSessionDescriptionObserver* observer,
- const MediaConstraintsInterface* constraints) = 0;
- // Sets the local session description.
- // JsepInterface takes the ownership of |desc| even if it fails.
- // The |observer| callback will be called when done.
- virtual void SetLocalDescription(SetSessionDescriptionObserver* observer,
- SessionDescriptionInterface* desc) = 0;
- // Sets the remote session description.
- // JsepInterface takes the ownership of |desc| even if it fails.
- // The |observer| callback will be called when done.
- virtual void SetRemoteDescription(SetSessionDescriptionObserver* observer,
- SessionDescriptionInterface* desc) = 0;
- // Restarts or updates the ICE Agent process of gathering local candidates
- // and pinging remote candidates.
- virtual bool UpdateIce(const IceServers& configuration,
- const MediaConstraintsInterface* constraints) = 0;
- // Provides a remote candidate to the ICE Agent.
- // A copy of the |candidate| will be created and added to the remote
- // description. So the caller of this method still has the ownership of the
- // |candidate|.
- // TODO(ronghuawu): Consider to change this so that the AddIceCandidate will
- // take the ownership of the |candidate|.
- virtual bool AddIceCandidate(const IceCandidateInterface* candidate) = 0;
-
- protected:
- virtual ~JsepInterface() {}
-};
-
} // namespace webrtc
#endif // TALK_APP_WEBRTC_JSEP_H_
View
2  talk/app/webrtc/jsepsessiondescription.cc
@@ -145,6 +145,8 @@ size_t JsepSessionDescription::number_of_mediasections() const {
const IceCandidateCollection* JsepSessionDescription::candidates(
size_t mediasection_index) const {
+ if (mediasection_index >= candidate_collection_.size())
+ return NULL;
return &candidate_collection_[mediasection_index];
}
View
3  talk/app/webrtc/mediastreaminterface.h
@@ -263,6 +263,9 @@ class MediaConstraintsInterface {
// Specified by the W3C PeerConnection spec
static const char kOfferToReceiveVideo[]; // OfferToReceiveVideo
static const char kOfferToReceiveAudio[]; // OfferToReceiveAudio
+ static const char kIceRestart[]; // IceRestart
+ // These keys are google specific.
+ static const char kUseRtpMux[]; // googUseRtpMUX
// Constraints values.
static const char kValueTrue[]; // true
View
159 talk/app/webrtc/mediastreamsignaling.cc
@@ -43,6 +43,116 @@ namespace webrtc {
using talk_base::scoped_ptr;
using talk_base::scoped_refptr;
+// Supported MediaConstraints.
+const char MediaConstraintsInterface::kOfferToReceiveAudio[] =
+ "OfferToReceiveAudio";
+const char MediaConstraintsInterface::kOfferToReceiveVideo[] =
+ "OfferToReceiveVideo";
+const char MediaConstraintsInterface::kIceRestart[] =
+ "IceRestart";
+const char MediaConstraintsInterface::kUseRtpMux[] =
+ "googUseRtpMUX";
+
+static bool FindConstraint(
+ const MediaConstraintsInterface::Constraints& constraints,
+ const std::string& key, std::string* value) {
+ for (MediaConstraintsInterface::Constraints::const_iterator iter =
+ constraints.begin(); iter != constraints.end(); ++iter) {
+ if (iter->key == key) {
+ if (value) {
+ *value = iter->value;
+ }
+
+ return true;
+ }
+ }
+ return false;
+}
+
+// Finds a a constraint key and its value. |constraints| can be null..
+// |mandatory_constraints| is increased by one if the constraint is mandatory.
+static bool FindConstraint(const MediaConstraintsInterface* constraints,
+ const std::string& key, std::string* value,
+ size_t* mandatory_constraints) {
+ if (!constraints) {
+ return false;
+ }
+ if (FindConstraint(constraints->GetMandatory(), key, value)) {
+ ++*mandatory_constraints;
+ return true;
+ }
+ if (FindConstraint(constraints->GetOptional(), key, value)) {
+ return true;
+ }
+ return false;
+}
+
+static bool ParseConstraints(
+ const MediaConstraintsInterface* constraints,
+ cricket::MediaSessionOptions* options) {
+ std::string value;
+ size_t mandatory_constraints_satisfied = 0;
+
+ if (FindConstraint(constraints,
+ MediaConstraintsInterface::kOfferToReceiveAudio,
+ &value, &mandatory_constraints_satisfied)) {
+ // |options-|has_audio| can only change from false to
+ // true, but never change from true to false. This is to make sure
+ // CreateOffer / CreateAnswer doesn't remove a media content
+ // description that has been created.
+ options->has_audio |=
+ (value == MediaConstraintsInterface::kValueTrue);
+ } else {
+ // kOfferToReceiveAudio is non mandatory true according to spec.
+ options->has_audio |= true;
+ }
+
+ if (FindConstraint(constraints,
+ MediaConstraintsInterface::kOfferToReceiveVideo,
+ &value, &mandatory_constraints_satisfied)) {
+ // |options->has_video| can only change from false to
+ // true, but never change from true to false. This is to make sure
+ // CreateOffer / CreateAnswer doesn't remove a media content
+ // description that has been created.
+ options->has_video |=
+ (value == MediaConstraintsInterface::kValueTrue);
+ } else {
+ // kOfferToReceiveVideo is non mandatory false according to spec.
+ }
+
+ if (FindConstraint(constraints,
+ MediaConstraintsInterface::kUseRtpMux,
+ &value, &mandatory_constraints_satisfied)) {
+ options->bundle_enabled = (value == MediaConstraintsInterface::kValueTrue);
+ } else {
+ // kUseRtpMux is non mandatory true according to spec.
+ options->bundle_enabled = true;
+ }
+ if (FindConstraint(constraints,
+ MediaConstraintsInterface::kIceRestart,
+ &value, &mandatory_constraints_satisfied)) {
+ options->transport_options.ice_restart =
+ (value == MediaConstraintsInterface::kValueTrue);;
+ } else {
+ // kIceRestart is non mandatory false according to spec.
+ options->transport_options.ice_restart = false;
+ }
+
+ if (!constraints) {
+ return true;
+ }
+ return mandatory_constraints_satisfied == constraints->GetMandatory().size();
+}
+
+// Returns true if if at least one media content is present and
+// |options.bundle_enabled| is true.
+// Bundle will be enabled by default if at least one media content is present
+// and the constraint kUseRtpMux has not disabled bundle.
+static bool EvaluateNeedForBundle(const cricket::MediaSessionOptions& options) {
+ return options.bundle_enabled &&
+ (options.has_audio || options.has_video || options.has_data);
+}
+
// Helper class used for tracking the mapping between a rtp stream and a
// remote MediaStreamTrack and MediaStream.
class RemoteTracksInterface {
@@ -192,37 +302,32 @@ bool MediaStreamSignaling::AddDataChannel(DataChannel* data_channel) {
return true;
}
-const cricket::MediaSessionOptions&
-MediaStreamSignaling::GetOptionsForOffer(const MediaHints& hints) {
+bool MediaStreamSignaling::GetOptionsForOffer(
+ const MediaConstraintsInterface* constraints,
+ cricket::MediaSessionOptions* options) {
UpdateSessionOptions();
- // has_video and has_audio can only change from false to true,
- // but never change from true to false if this is an offer. This is to make
- // sure CreateOffer doesn't remove a media content description that has been
- // created.
- options_.has_audio |= hints.has_audio();
- options_.has_video |= hints.has_video();
- // Enable BUNDLE feature by default if at least one media content is present.
- options_.bundle_enabled =
- options_.has_audio || options_.has_video || options_.has_data;
- return options_;
+ if (!ParseConstraints(constraints, &options_)) {
+ return false;
+ }
+ options_.bundle_enabled = EvaluateNeedForBundle(options_);
+ *options = options_;
+ return true;
}
-cricket::MediaSessionOptions
-MediaStreamSignaling::GetOptionsForAnswer(const MediaHints& hints) {
+bool MediaStreamSignaling::GetOptionsForAnswer(
+ const MediaConstraintsInterface* constraints,
+ cricket::MediaSessionOptions* options) {
UpdateSessionOptions();
- // Copy the |options_| to not let |receive_audio| and |receive_video| affect
- // subsequent offers.
- cricket::MediaSessionOptions options = options_;
- // has_video and has_audio can only change from false to true,
- // but never change from true to false. This is to make
- // sure CreateAnswer doesn't remove a media content description that has been
- // created.
- options.has_audio |= hints.has_audio();
- options.has_video |= hints.has_video();
- // Enable BUNDLE feature by default if at least one media content is present.
- options.bundle_enabled =
- options.has_audio || options.has_video || options.has_data;
- return options;
+
+ // Copy the |options_| to not let the flag MediaSessionOptions::has_audio and
+ // MediaSessionOptions::has_video affect subsequent offers.
+ cricket::MediaSessionOptions current_options = options_;
+ if (!ParseConstraints(constraints, &current_options)) {
+ return false;
+ }
+ current_options.bundle_enabled = EvaluateNeedForBundle(current_options);
+ *options = current_options;
+ return true;
}
// Updates or creates remote MediaStream objects given a
View
21 talk/app/webrtc/mediastreamsignaling.h
@@ -132,19 +132,17 @@ class MediaStreamSignaling {
// cricket::MediaSessionOptions returned by GetMediaSessionOptions().
bool AddDataChannel(DataChannel* data_channel);
- // Returns a MediaSessionOptions struct with options decided by |hints|,
- // the local MediaStreams and DataChannels. If a |hints| element
- // is true, media content description of that type will be
- // offered even if no tracks are sent.
- virtual const cricket::MediaSessionOptions& GetOptionsForOffer(
- const MediaHints& hints);
+ // Returns a MediaSessionOptions struct with options decided by |constraints|,
+ // the local MediaStreams and DataChannels.
+ virtual bool GetOptionsForOffer(
+ const MediaConstraintsInterface* constraints,
+ cricket::MediaSessionOptions* options);
// Returns a MediaSessionOptions struct with options decided by
- // |hints|, the local MediaStreams and DataChannels.
- // If a |hints| elements is true, media content description of
- // that type will be accepted even if no tracks are sent.
- virtual cricket::MediaSessionOptions GetOptionsForAnswer(
- const MediaHints& hints);
+ // |constraints|, the local MediaStreams and DataChannels.
+ virtual bool GetOptionsForAnswer(
+ const MediaConstraintsInterface* constraints,
+ cricket::MediaSessionOptions* options);
// Updates or creates remote MediaStream objects and Tracks given a
// remote SessionDescription.
@@ -192,7 +190,6 @@ class MediaStreamSignaling {
default_video_track_needed);
}
};
-
void UpdateSessionOptions();
// Makes sure a MediaStream Track is created for each StreamParam in
// |streams|. |media_type| is the type of the |streams| and can be either
View
195 talk/app/webrtc/mediastreamsignaling_unittest.cc
@@ -31,6 +31,7 @@
#include "talk/app/webrtc/mediastream.h"
#include "talk/app/webrtc/mediastreamsignaling.h"
#include "talk/app/webrtc/streamcollection.h"
+#include "talk/app/webrtc/test/fakeconstraints.h"
#include "talk/app/webrtc/videotrack.h"
#include "talk/base/gunit.h"
#include "talk/base/scoped_ptr.h"
@@ -42,22 +43,17 @@ static const char kStreams[][8] = {"stream1", "stream2"};
static const char kAudioTracks[][32] = {"audiotrack0", "audiotrack1"};
static const char kVideoTracks[][32] = {"videotrack0", "videotrack1"};
-static const char kStream1[] = "stream1";
-static const char kAudioTrack1[]= "audiotrack0";
-static const char kAudioTrack2[]= "audiotrack1";
-static const char kVideoTrack1[]= "videotrack0";
-static const char kVideoTrack2[]= "videotrack1";
-
using webrtc::AudioTrack;
using webrtc::AudioTrackVector;
using webrtc::VideoTrack;
using webrtc::VideoTrackVector;
using webrtc::DataChannelInterface;
+using webrtc::FakeConstraints;
using webrtc::IceCandidateInterface;
+using webrtc::MediaConstraintsInterface;
using webrtc::MediaStreamInterface;
using webrtc::SessionDescriptionInterface;
-using webrtc::MediaHints;
using webrtc::StreamCollection;
using webrtc::StreamCollectionInterface;
@@ -175,16 +171,13 @@ static const char kSdpStringMs1Video1[] =
"a=ssrc:4 cname:stream1\r\n"
"a=ssrc:4 msid:stream1 videotrack1\r\n";
-// Verifies that |options| contain all tracks in |collection| if |hints| allow
-// them.
+// Verifies that |options| contain all tracks in |collection| and that
+// the |options| has set the the has_audio and has_video flags correct.
static void VerifyMediaOptions(StreamCollectionInterface* collection,
- const MediaHints hints,
const cricket::MediaSessionOptions& options) {
- EXPECT_EQ(hints.has_audio(), options.has_audio);
- EXPECT_EQ(hints.has_video(), options.has_video);
-
- if (!collection)
+ if (!collection) {
return;
+ }
size_t stream_index = 0;
for (size_t i = 0; i < collection->count(); ++i) {
@@ -194,12 +187,14 @@ static void VerifyMediaOptions(StreamCollectionInterface* collection,
webrtc::AudioTrackInterface* audio = stream->audio_tracks()->at(j);
EXPECT_EQ(options.streams[stream_index].sync_label, stream->label());
EXPECT_EQ(options.streams[stream_index++].name, audio->id());
+ EXPECT_TRUE(options.has_audio);
}
ASSERT_GE(options.streams.size(), stream->audio_tracks()->count());
for (size_t j = 0; j < stream->video_tracks()->count(); ++j) {
webrtc::VideoTrackInterface* video = stream->video_tracks()->at(j);
EXPECT_EQ(options.streams[stream_index].sync_label, stream->label());
EXPECT_EQ(options.streams[stream_index++].name, video->id());
+ EXPECT_TRUE(options.has_video);
}
}
}
@@ -288,12 +283,13 @@ class MediaStreamSignalingTest: public testing::Test {
signaling_.reset(new MediaStreamSignalingForTest(observer_.get()));
}
- void TestGetMediaSessionOptions(const MediaHints& hints,
- StreamCollectionInterface* streams) {
+ void TestGetMediaSessionOptionsForOffer(
+ StreamCollectionInterface* streams,
+ const MediaConstraintsInterface* constraints) {
signaling_->SetLocalStreams(streams);
- cricket::MediaSessionOptions options =
- signaling_->GetOptionsForOffer(hints);
- VerifyMediaOptions(streams, hints, options);
+ cricket::MediaSessionOptions options;
+ EXPECT_TRUE(signaling_->GetOptionsForOffer(constraints, &options));
+ VerifyMediaOptions(streams, options);
}
// Create a collection of streams.
@@ -389,54 +385,142 @@ class MediaStreamSignalingTest: public testing::Test {
talk_base::scoped_ptr<MediaStreamSignalingForTest> signaling_;
};
-TEST_F(MediaStreamSignalingTest, AudioVideoHints) {
- MediaHints hints;
- talk_base::scoped_refptr<StreamCollection> local_streams(
- CreateStreamCollection(1));
- TestGetMediaSessionOptions(hints, local_streams.get());
+// Test that a MediaSessionOptions is created for an offer if
+// kOfferToReceiveAudio and kOfferToReceiveVideo constraints are set but no
+// MediaStreams are sent.
+TEST_F(MediaStreamSignalingTest, GetMediaSessionOptionsForOfferWithAudioVideo) {
+ FakeConstraints constraints;
+ constraints.SetMandatoryReceiveAudio(true);
+ constraints.SetMandatoryReceiveVideo(true);
+ cricket::MediaSessionOptions options;
+ EXPECT_TRUE(signaling_->GetOptionsForOffer(&constraints, &options));
+ EXPECT_TRUE(options.has_audio);
+ EXPECT_TRUE(options.has_video);
+ EXPECT_TRUE(options.bundle_enabled);
}
-TEST_F(MediaStreamSignalingTest, AudioHints) {
- MediaHints hints(true, false);
- // Don't use all MediaStreams so we only create offer based on hints without
- // sending streams.
- TestGetMediaSessionOptions(hints, NULL);
+// Test that a correct MediaSessionOptions is created for an offer if
+// kOfferToReceiveAudio constraints is set but no MediaStreams are sent.
+TEST_F(MediaStreamSignalingTest, GetMediaSessionOptionsForOfferWithAudio) {
+ FakeConstraints constraints;
+ constraints.SetMandatoryReceiveAudio(true);
+ cricket::MediaSessionOptions options;
+ EXPECT_TRUE(signaling_->GetOptionsForOffer(&constraints, &options));
+ EXPECT_TRUE(options.has_audio);
+ EXPECT_FALSE(options.has_video);
+ EXPECT_TRUE(options.bundle_enabled);
}
-TEST_F(MediaStreamSignalingTest, VideoHints) {
- MediaHints hints(false, true);
- // Don't use all MediaStreams so we only create offer based on hints without
- // sending streams.
- TestGetMediaSessionOptions(hints, NULL);
+// Test that a correct MediaSessionOptions is created for an offer if
+// no constraints or MediaStreams are sent.
+TEST_F(MediaStreamSignalingTest, GetDefaultMediaSessionOptionsForOffer) {
+ cricket::MediaSessionOptions options;
+ EXPECT_TRUE(signaling_->GetOptionsForOffer(NULL, &options));
+ EXPECT_TRUE(options.has_audio);
+ EXPECT_FALSE(options.has_video);
+ EXPECT_TRUE(options.bundle_enabled);
+}
+
+// Test that a correct MediaSessionOptions is created for an offer if
+// kOfferToReceiveVideo constraints is set but no MediaStreams are sent.
+TEST_F(MediaStreamSignalingTest, GetMediaSessionOptionsForOfferWithVideo) {
+ FakeConstraints constraints;
+ constraints.SetMandatoryReceiveAudio(false);
+ constraints.SetMandatoryReceiveVideo(true);
+ cricket::MediaSessionOptions options;
+ EXPECT_TRUE(signaling_->GetOptionsForOffer(&constraints, &options));
+ EXPECT_FALSE(options.has_audio);
+ EXPECT_TRUE(options.has_video);
+ EXPECT_TRUE(options.bundle_enabled);
+}
+
+// Test that a correct MediaSessionOptions is created for an offer if
+// kUseRtpMux constraints is set to false.
+TEST_F(MediaStreamSignalingTest,
+ GetMediaSessionOptionsForOfferWithBundleDisabled) {
+ FakeConstraints constraints;
+ constraints.SetMandatoryReceiveAudio(true);
+ constraints.SetMandatoryReceiveVideo(true);
+ constraints.SetMandatoryUseRtpMux(false);
+ cricket::MediaSessionOptions options;
+ EXPECT_TRUE(signaling_->GetOptionsForOffer(&constraints, &options));
+ EXPECT_TRUE(options.has_audio);
+ EXPECT_TRUE(options.has_video);
+ EXPECT_FALSE(options.bundle_enabled);
}
+// Test that a correct MediaSessionOptions is created to restart ice if
+// kIceRestart constraints is set. It also tests that subsequent
+// MediaSessionOptions don't have |transport_options.ice_restart| set.
+TEST_F(MediaStreamSignalingTest,
+ GetMediaSessionOptionsForOfferWithIceRestart) {
+ FakeConstraints constraints;
+ constraints.SetMandatoryIceRestart(true);
+ cricket::MediaSessionOptions options;
+ EXPECT_TRUE(signaling_->GetOptionsForOffer(&constraints, &options));
+ EXPECT_TRUE(options.transport_options.ice_restart);
+
+ EXPECT_TRUE(signaling_->GetOptionsForOffer(NULL, &options));
+ EXPECT_FALSE(options.transport_options.ice_restart);
+}
+
+// Test that GetMediaSessionOptionsForOffer and GetOptionsForAnswer work as
+// expected if unknown constraints are used.
+TEST_F(MediaStreamSignalingTest, GetMediaSessionOptionsWithBadConstraints) {
+ FakeConstraints mandatory;
+ mandatory.AddMandatory("bad_key", "bad_value");
+ cricket::MediaSessionOptions options;
+ EXPECT_FALSE(signaling_->GetOptionsForOffer(&mandatory, &options));
+ EXPECT_FALSE(signaling_->GetOptionsForAnswer(&mandatory, &options));
+
+ FakeConstraints optional;
+ optional.AddOptional("bad_key", "bad_value");
+ EXPECT_TRUE(signaling_->GetOptionsForOffer(&optional, &options));
+ EXPECT_TRUE(signaling_->GetOptionsForAnswer(&optional, &options));
+}
+
+// Test that a correct MediaSessionOptions are created for an offer if
+// a MediaStream is sent and later updated with a new track.
+// MediaConstraints are not used.
TEST_F(MediaStreamSignalingTest, AddTrackToLocalMediaStream) {
- MediaHints hints;
talk_base::scoped_refptr<StreamCollection> local_streams(
CreateStreamCollection(1));
- TestGetMediaSessionOptions(hints, local_streams);
+ TestGetMediaSessionOptionsForOffer(local_streams, NULL);
+
local_streams->at(0)->AddTrack(AudioTrack::Create(kAudioTracks[1], NULL));
- TestGetMediaSessionOptions(hints, local_streams);
+ TestGetMediaSessionOptionsForOffer(local_streams, NULL);
}
-// Test that the hints in an answer don't affect the hints in an offer but that
-// if hints are true in an offer, the media type they will be included in
-// subsequent answers.
-TEST_F(MediaStreamSignalingTest, HintsInAnswer) {
- MediaHints answer_hints(true, true);
- cricket::MediaSessionOptions answer_options =
- signaling_->GetOptionsForAnswer(answer_hints);
+// Test that the MediaConstraints in an answer don't affect if audio and video
+// is offered in an offer but that if kOfferToReceiveAudio or
+// kOfferToReceiveVideo constraints are true in an offer, the media type will be
+// included in subsequent answers.
+TEST_F(MediaStreamSignalingTest, MediaConstraintsInAnswer) {
+ FakeConstraints answer_c;
+ answer_c.SetMandatoryReceiveAudio(true);
+ answer_c.SetMandatoryReceiveVideo(true);
+
+ cricket::MediaSessionOptions answer_options;
+ EXPECT_TRUE(signaling_->GetOptionsForAnswer(&answer_c, &answer_options));
EXPECT_TRUE(answer_options.has_audio);
EXPECT_TRUE(answer_options.has_video);
- MediaHints offer_hints(false, false);
- cricket::MediaSessionOptions offer_options =
- signaling_->GetOptionsForAnswer(offer_hints);
+ FakeConstraints offer_c;
+ offer_c.SetMandatoryReceiveAudio(false);
+ offer_c.SetMandatoryReceiveVideo(false);
+
+ cricket::MediaSessionOptions offer_options;
+ EXPECT_TRUE(signaling_->GetOptionsForOffer(&offer_c, &offer_options));
EXPECT_FALSE(offer_options.has_audio);
EXPECT_FALSE(offer_options.has_video);
- cricket::MediaSessionOptions updated_offer_options =
- signaling_->GetOptionsForOffer(MediaHints(true, true));
+ FakeConstraints updated_offer_c;
+ updated_offer_c.SetMandatoryReceiveAudio(true);
+ updated_offer_c.SetMandatoryReceiveVideo(true);
+
+ cricket::MediaSessionOptions updated_offer_options;
+ EXPECT_TRUE(signaling_->GetOptionsForOffer(&updated_offer_c,
+ &updated_offer_options));
EXPECT_TRUE(updated_offer_options.has_audio);
EXPECT_TRUE(updated_offer_options.has_video);
@@ -445,13 +529,18 @@ TEST_F(MediaStreamSignalingTest, HintsInAnswer) {
// Answers will only contain the media types that exist in the offer
// regardless of the value of |updated_answer_options.has_audio| and
// |updated_answer_options.has_video|.
- cricket::MediaSessionOptions updated_answer_options =
- signaling_->GetOptionsForAnswer(MediaHints(false, false));
+ FakeConstraints updated_answer_c;
+ answer_c.SetMandatoryReceiveAudio(false);
+ answer_c.SetMandatoryReceiveVideo(false);
+
+ cricket::MediaSessionOptions updated_answer_options;
+ EXPECT_TRUE(signaling_->GetOptionsForAnswer(&updated_answer_c,
+ &updated_answer_options));
EXPECT_TRUE(updated_answer_options.has_audio);
EXPECT_TRUE(updated_answer_options.has_video);
- updated_offer_options = signaling_->GetOptionsForOffer(MediaHints(false,
- false));
+ EXPECT_TRUE(signaling_->GetOptionsForOffer(NULL,
+ &updated_offer_options));
EXPECT_TRUE(updated_offer_options.has_audio);
EXPECT_TRUE(updated_offer_options.has_video);
}
View
8 talk/app/webrtc/peerconnection.cc
@@ -40,6 +40,8 @@
namespace {
+using webrtc::PeerConnectionInterface;
+
// The min number of tokens in the ice uri.
static const size_t kMinIceUriTokens = 2;
// The min number of tokens must present in Turn host uri.
@@ -112,7 +114,7 @@ typedef webrtc::PortAllocatorFactoryInterface::StunConfiguration
typedef webrtc::PortAllocatorFactoryInterface::TurnConfiguration
TurnConfiguration;
-bool ParseIceServers(const webrtc::JsepInterface::IceServers& configuration,
+bool ParseIceServers(const PeerConnectionInterface::IceServers& configuration,
std::vector<StunConfiguration>* stun_config,
std::vector<TurnConfiguration>* turn_config) {
// draft-nandakumar-rtcweb-stun-uri-01
@@ -132,7 +134,7 @@ bool ParseIceServers(const webrtc::JsepInterface::IceServers& configuration,
// TODO(ronghuawu): Handle IPV6 address
for (size_t i = 0; i < configuration.size(); ++i) {
- webrtc::JsepInterface::IceServer server = configuration[i];
+ webrtc::PeerConnectionInterface::IceServer server = configuration[i];
if (server.uri.empty()) {
LOG(WARNING) << "Empty uri.";
continue;
@@ -243,7 +245,7 @@ PeerConnection::~PeerConnection() {
}
bool PeerConnection::Initialize(
- const JsepInterface::IceServers& configuration,
+ const PeerConnectionInterface::IceServers& configuration,
const MediaConstraintsInterface* constraints,
webrtc::PortAllocatorFactoryInterface* allocator_factory,
PeerConnectionObserver* observer) {
View
2  talk/app/webrtc/peerconnection.h
@@ -57,7 +57,7 @@ class PeerConnection : public PeerConnectionInterface,
public:
explicit PeerConnection(PeerConnectionFactory* factory);
- bool Initialize(const JsepInterface::IceServers& configuration,
+ bool Initialize(const PeerConnectionInterface::IceServers& configuration,
const MediaConstraintsInterface* constraints,
webrtc::PortAllocatorFactoryInterface* allocator_factory,
PeerConnectionObserver* observer);
View
4 talk/app/webrtc/peerconnection_unittest.cc
@@ -565,8 +565,8 @@ class JsepTestClient
CreatePeerConnection(webrtc::PortAllocatorFactoryInterface* factory,
const MediaConstraintsInterface* constraints) {
// CreatePeerConnection with IceServers.
- webrtc::JsepInterface::IceServers ice_servers;
- webrtc::JsepInterface::IceServer ice_server;
+ webrtc::PeerConnectionInterface::IceServers ice_servers;
+ webrtc::PeerConnectionInterface::IceServer ice_server;
ice_server.uri = "stun:stun.l.google.com:19302";
ice_servers.push_back(ice_server);
return peer_connection_factory()->CreatePeerConnection(
View
10 talk/app/webrtc/peerconnectionfactory.cc
@@ -48,7 +48,7 @@ typedef talk_base::TypedMessageData<bool> InitMessageData;
struct CreatePeerConnectionParams : public talk_base::MessageData {
CreatePeerConnectionParams(
- const webrtc::JsepInterface::IceServers& configuration,
+ const webrtc::PeerConnectionInterface::IceServers& configuration,
const webrtc::MediaConstraintsInterface* constraints,
webrtc::PortAllocatorFactoryInterface* allocator_factory,
webrtc::PeerConnectionObserver* observer)
@@ -58,7 +58,7 @@ struct CreatePeerConnectionParams : public talk_base::MessageData {
observer(observer) {
}
scoped_refptr<webrtc::PeerConnectionInterface> peerconnection;
- const webrtc::JsepInterface::IceServers& configuration;
+ const webrtc::PeerConnectionInterface::IceServers& configuration;
const webrtc::MediaConstraintsInterface* constraints;
scoped_refptr<webrtc::PortAllocatorFactoryInterface> allocator_factory;
webrtc::PeerConnectionObserver* observer;
@@ -263,7 +263,7 @@ PeerConnectionFactory::CreateVideoSource_s(
scoped_refptr<PeerConnectionInterface>
PeerConnectionFactory::CreatePeerConnection(
- const JsepInterface::IceServers& configuration,
+ const PeerConnectionInterface::IceServers& configuration,
const MediaConstraintsInterface* constraints,
PortAllocatorFactoryInterface* allocator_factory,
PeerConnectionObserver* observer) {
@@ -275,7 +275,7 @@ PeerConnectionFactory::CreatePeerConnection(
scoped_refptr<PeerConnectionInterface>
PeerConnectionFactory::CreatePeerConnection(
- const JsepInterface::IceServers& configuration,
+ const PeerConnectionInterface::IceServers& configuration,
const MediaConstraintsInterface* constraints,
PeerConnectionObserver* observer) {
return CreatePeerConnection(configuration, constraints, NULL, observer);
@@ -283,7 +283,7 @@ PeerConnectionFactory::CreatePeerConnection(
talk_base::scoped_refptr<PeerConnectionInterface>
PeerConnectionFactory::CreatePeerConnection_s(
- const JsepInterface::IceServers& configuration,
+ const PeerConnectionInterface::IceServers& configuration,
const MediaConstraintsInterface* constraints,
PortAllocatorFactoryInterface* allocator_factory,
PeerConnectionObserver* observer) {
View
18 talk/app/webrtc/peerconnectionfactory.h
@@ -41,15 +41,17 @@ class PeerConnectionFactory : public PeerConnectionFactoryInterface,
public talk_base::MessageHandler {
public:
virtual talk_base::scoped_refptr<PeerConnectionInterface>
- CreatePeerConnection(const JsepInterface::IceServers& configuration,
- const MediaConstraintsInterface* constraints,
- PeerConnectionObserver* observer);
+ CreatePeerConnection(
+ const PeerConnectionInterface::IceServers& configuration,
+ const MediaConstraintsInterface* constraints,
+ PeerConnectionObserver* observer);
virtual talk_base::scoped_refptr<PeerConnectionInterface>
- CreatePeerConnection(const JsepInterface::IceServers& configuration,
- const MediaConstraintsInterface* constraints,
- PortAllocatorFactoryInterface* allocator_factory,
- PeerConnectionObserver* observer);
+ CreatePeerConnection(
+ const PeerConnectionInterface::IceServers& configuration,
+ const MediaConstraintsInterface* constraints,
+ PortAllocatorFactoryInterface* allocator_factory,
+ PeerConnectionObserver* observer);
bool Initialize();
virtual talk_base::scoped_refptr<LocalMediaStreamInterface>
@@ -100,7 +102,7 @@ class PeerConnectionFactory : public PeerConnectionFactoryInterface,
cricket::VideoCapturer* capturer,
const MediaConstraintsInterface* constraints);
talk_base::scoped_refptr<PeerConnectionInterface> CreatePeerConnection_s(
- const JsepInterface::IceServers& configuration,
+ const PeerConnectionInterface::IceServers& configuration,
const MediaConstraintsInterface* constraints,
PortAllocatorFactoryInterface* allocator_factory,
PeerConnectionObserver* observer);
View
10 talk/app/webrtc/peerconnectionfactory_unittest.cc
@@ -90,7 +90,7 @@ TEST(PeerConnectionFactoryTestInternal, CreatePCUsingInternalModules) {
webrtc::CreatePeerConnectionFactory());
NullPeerConnectionObserver observer;
- webrtc::JsepInterface::IceServers servers;
+ webrtc::PeerConnectionInterface::IceServers servers;
talk_base::scoped_refptr<PeerConnectionInterface> pc(
factory->CreatePeerConnection(servers, NULL, &observer));
@@ -99,8 +99,8 @@ TEST(PeerConnectionFactoryTestInternal, CreatePCUsingInternalModules) {
}
TEST_F(PeerConnectionFactoryTest, CreatePCUsingIceServers) {
- webrtc::JsepInterface::IceServers ice_servers;
- webrtc::JsepInterface::IceServer ice_server;
+ webrtc::PeerConnectionInterface::IceServers ice_servers;
+ webrtc::PeerConnectionInterface::IceServer ice_server;
ice_server.uri = kStunIceServer;
ice_servers.push_back(ice_server);
ice_server.uri = kTurnIceServer;
@@ -114,8 +114,8 @@ TEST_F(PeerConnectionFactoryTest, CreatePCUsingIceServers) {
}
TEST_F(PeerConnectionFactoryTest, CreatePCUsingInvalidTurnUrl) {
- webrtc::JsepInterface::IceServers ice_servers;
- webrtc::JsepInterface::IceServer ice_server;
+ webrtc::PeerConnectionInterface::IceServers ice_servers;
+ webrtc::PeerConnectionInterface::IceServer ice_server;
ice_server.uri = kInvalidTurnIceServer;
ice_server.password = kTurnPassword;
ice_servers.push_back(ice_server);
View
79 talk/app/webrtc/peerconnectioninterface.h
@@ -108,7 +108,7 @@ class StreamCollectionInterface : public talk_base::RefCountInterface {
// PeerConnection callback interface. Application should implement these
// methods.
-class PeerConnectionObserver : public IceCandidateObserver {
+class PeerConnectionObserver {
public:
enum StateType {
kSignalingState,
@@ -133,6 +133,16 @@ class PeerConnectionObserver : public IceCandidateObserver {
// Triggered when renegotation is needed, for example the ICE has restarted.
virtual void OnRenegotiationNeeded() {}
+ // TODO(ronghuawu): Implement OnIceChange.
+ // Called any time the iceState changes.
+ virtual void OnIceChange() {}
+
+ // New Ice candidate have been found.
+ virtual void OnIceCandidate(const IceCandidateInterface* candidate) = 0;
+
+ // All Ice candidates have been found.
+ virtual void OnIceComplete() {}
+
protected:
// Dtor protected as objects shouldn't be deleted via this interface.
~PeerConnectionObserver() {}
@@ -146,8 +156,7 @@ class StatsObserver : public talk_base::RefCountInterface {
virtual ~StatsObserver() {}
};
-class PeerConnectionInterface : public JsepInterface,
- public talk_base::RefCountInterface {
+class PeerConnectionInterface : public talk_base::RefCountInterface {
public:
// Keep in sync with org.webrtc.PeerConnection.SignalingState.
enum SignalingState {
@@ -171,6 +180,12 @@ class PeerConnectionInterface : public JsepInterface,
kIceClosed,
};
+ struct IceServer {
+ std::string uri;
+ std::string password;
+ };
+ typedef std::vector<IceServer> IceServers;
+
// Accessor methods to active local streams.
virtual talk_base::scoped_refptr<StreamCollectionInterface>
local_streams() = 0;
@@ -202,6 +217,39 @@ class PeerConnectionInterface : public JsepInterface,
const std::string& label,
const DataChannelInit* config) = 0;
+ virtual const SessionDescriptionInterface* local_description() const = 0;
+ virtual const SessionDescriptionInterface* remote_description() const = 0;
+
+ // Create a new offer.
+ // The CreateSessionDescriptionObserver callback will be called when done.
+ virtual void CreateOffer(CreateSessionDescriptionObserver* observer,
+ const MediaConstraintsInterface* constraints) = 0;
+ // Create an answer to an offer.
+ // The CreateSessionDescriptionObserver callback will be called when done.
+ virtual void CreateAnswer(CreateSessionDescriptionObserver* observer,
+ const MediaConstraintsInterface* constraints) = 0;
+ // Sets the local session description.
+ // JsepInterface takes the ownership of |desc| even if it fails.
+ // The |observer| callback will be called when done.
+ virtual void SetLocalDescription(SetSessionDescriptionObserver* observer,
+ SessionDescriptionInterface* desc) = 0;
+ // Sets the remote session description.
+ // JsepInterface takes the ownership of |desc| even if it fails.
+ // The |observer| callback will be called when done.
+ virtual void SetRemoteDescription(SetSessionDescriptionObserver* observer,
+ SessionDescriptionInterface* desc) = 0;
+ // Restarts or updates the ICE Agent process of gathering local candidates
+ // and pinging remote candidates.
+ virtual bool UpdateIce(const IceServers& configuration,
+ const MediaConstraintsInterface* constraints) = 0;
+ // Provides a remote candidate to the ICE Agent.
+ // A copy of the |candidate| will be created and added to the remote
+ // description. So the caller of this method still has the ownership of the
+ // |candidate|.
+ // TODO(ronghuawu): Consider to change this so that the AddIceCandidate will
+ // take the ownership of the |candidate|.
+ virtual bool AddIceCandidate(const IceCandidateInterface* candidate) = 0;
+
// Deprecated, please use SignalingState instead.
// TODO(perkj): Remove ready_state when callers are changed.
typedef SignalingState ReadyState;
@@ -263,14 +311,16 @@ class PortAllocatorFactoryInterface : public talk_base::RefCountInterface {
class PeerConnectionFactoryInterface : public talk_base::RefCountInterface {
public:
virtual talk_base::scoped_refptr<PeerConnectionInterface>
- CreatePeerConnection(const JsepInterface::IceServers& configuration,
- const MediaConstraintsInterface* constraints,
- PeerConnectionObserver* observer) = 0;
+ CreatePeerConnection(
+ const PeerConnectionInterface::IceServers& configuration,
+ const MediaConstraintsInterface* constraints,
+ PeerConnectionObserver* observer) = 0;
virtual talk_base::scoped_refptr<PeerConnectionInterface>
- CreatePeerConnection(const JsepInterface::IceServers& configuration,
- const MediaConstraintsInterface* constraints,
- PortAllocatorFactoryInterface* allocator_factory,
- PeerConnectionObserver* observer) = 0;
+ CreatePeerConnection(
+ const PeerConnectionInterface::IceServers& configuration,
+ const MediaConstraintsInterface* constraints,
+ PortAllocatorFactoryInterface* allocator_factory,
+ PeerConnectionObserver* observer) = 0;
virtual talk_base::scoped_refptr<LocalMediaStreamInterface>
CreateLocalMediaStream(const std::string& label) = 0;
@@ -326,6 +376,15 @@ CreatePeerConnectionFactory(talk_base::Thread* worker_thread,
talk_base::Thread* signaling_thread,
AudioDeviceModule* default_adm);
+// TODO(perkj): The JsepInterface has been combined with
+// PeerConnectionInterface. Remove the below interface once no clients use
+// JsepInterface::IceServer.
+class JsepInterface {
+ public:
+ typedef PeerConnectionInterface::IceServer IceServer;
+ typedef std::vector<PeerConnectionInterface::IceServer> IceServers;
+};
+
} // namespace webrtc
#endif // TALK_APP_WEBRTC_PEERCONNECTIONINTERFACE_H_
View
55 talk/app/webrtc/peerconnectioninterface_unittest.cc
@@ -65,7 +65,6 @@ using webrtc::FakePortAllocatorFactory;
using webrtc::IceCandidateInterface;
using webrtc::DataBuffer;
-using webrtc::JsepInterface;
using webrtc::LocalMediaStreamInterface;
using webrtc::MediaStreamInterface;
using webrtc::MediaStreamTrackInterface;
@@ -208,8 +207,8 @@ class PeerConnectionInterfaceTest : public testing::Test {
void CreatePeerConnection(const std::string& uri,
const std::string& password,
webrtc::MediaConstraintsInterface* constraints) {
- JsepInterface::IceServer server;
- JsepInterface::IceServers servers;
+ PeerConnectionInterface::IceServer server;
+ PeerConnectionInterface::IceServers servers;
server.uri = uri;
server.password = password;
servers.push_back(server);
@@ -364,16 +363,34 @@ class PeerConnectionInterfaceTest : public testing::Test {
}
void CreateOfferAsRemoteDescription() {
- SessionDescriptionInterface* offer = NULL;
- EXPECT_TRUE(DoCreateOffer(&offer));
- EXPECT_TRUE(DoSetRemoteDescription(offer));
+ talk_base::scoped_ptr<SessionDescriptionInterface> offer;
+ EXPECT_TRUE(DoCreateOffer(offer.use()));
+ std::string sdp;
+ EXPECT_TRUE(offer->ToString(&sdp));
+ SessionDescriptionInterface* remote_offer =
+ webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
+ sdp);
+ EXPECT_TRUE(DoSetRemoteDescription(remote_offer));
EXPECT_EQ(PeerConnectionInterface::kHaveRemoteOffer, observer_.state_);
}
void CreateAnswerAsLocalDescription() {
- SessionDescriptionInterface* answer = NULL;
- EXPECT_TRUE(DoCreateAnswer(&answer));
- EXPECT_TRUE(DoSetLocalDescription(answer));
+ scoped_ptr<SessionDescriptionInterface> answer;
+ EXPECT_TRUE(DoCreateAnswer(answer.use()));
+
+ // TODO(perkj): Currently SetLocalDescription fails if any parameters in an
+ // audio codec change, even if the parameter has nothing to do with
+ // receiving. Not all parameters are serialized to SDP.
+ // Since CreatePrAnswerAsLocalDescription serialize/deserialize
+ // the SessionDescription, it is necessary to do that here to in order to
+ // get ReceiveOfferCreatePrAnswerAndAnswer and RenegotiateAudioOnly to pass.
+ // https://code.google.com/p/webrtc/issues/detail?id=1356
+ std::string sdp;
+ EXPECT_TRUE(answer->ToString(&sdp));
+ SessionDescriptionInterface* new_answer =
+ webrtc::CreateSessionDescription(SessionDescriptionInterface::kAnswer,
+ sdp);
+ EXPECT_TRUE(DoSetLocalDescription(new_answer));
EXPECT_EQ(PeerConnectionInterface::kStable, observer_.state_);
}
@@ -398,9 +415,23 @@ class PeerConnectionInterfaceTest : public testing::Test {
}
void CreateOfferAsLocalDescription() {
- SessionDescriptionInterface* offer = NULL;
- ASSERT_TRUE(DoCreateOffer(&offer));
- EXPECT_TRUE(DoSetLocalDescription(offer));
+ talk_base::scoped_ptr<SessionDescriptionInterface> offer;
+ ASSERT_TRUE(DoCreateOffer(offer.use()));
+ // TODO(perkj): Currently SetLocalDescription fails if any parameters in an
+ // audio codec change, even if the parameter has nothing to do with
+ // receiving. Not all parameters are serialized to SDP.
+ // Since CreatePrAnswerAsLocalDescription serialize/deserialize
+ // the SessionDescription, it is necessary to do that here to in order to
+ // get ReceiveOfferCreatePrAnswerAndAnswer and RenegotiateAudioOnly to pass.
+ // https://code.google.com/p/webrtc/issues/detail?id=1356
+ std::string sdp;
+ EXPECT_TRUE(offer->ToString(&sdp));
+ SessionDescriptionInterface* new_offer =
+ webrtc::CreateSessionDescription(
+ SessionDescriptionInterface::kOffer,
+ sdp);
+
+ EXPECT_TRUE(DoSetLocalDescription(new_offer));
EXPECT_EQ(PeerConnectionInterface::kHaveLocalOffer, observer_.state_);
}
View
2  talk/app/webrtc/peerconnectionproxy.cc
@@ -77,7 +77,7 @@ struct IceConfigurationParams : public talk_base::MessageData {
constraints(NULL),
result(false) {
}
- const webrtc::JsepInterface::IceServers* configuration;
+ const webrtc::PeerConnectionInterface::IceServers* configuration;
const webrtc::MediaConstraintsInterface* constraints;
bool result;
};
View
8 talk/app/webrtc/peerconnectionproxy_unittest.cc
@@ -71,11 +71,6 @@ class MockPeerConnection : public PeerConnectionInterface {
talk_base::scoped_refptr<DataChannelInterface>(
const std::string& label,
const DataChannelInit* config));
- MOCK_METHOD1(CreateOffer,
- SessionDescriptionInterface*(const MediaHints& hints));
- MOCK_METHOD2(CreateAnswer,
- SessionDescriptionInterface*(const MediaHints& hints,
- const SessionDescriptionInterface* offer));
MOCK_CONST_METHOD0(local_description,
const SessionDescriptionInterface*());
MOCK_CONST_METHOD0(remote_description,
@@ -307,7 +302,8 @@ TEST_F(PeerConnectionProxyTest, UpdateIce) {
.WillOnce(
DoAll(InvokeWithoutArgs(this, &PeerConnectionProxyTest::CheckThread),
Return(true)));
- EXPECT_TRUE(pc_proxy_->UpdateIce(JsepInterface::IceServers(), constraints));
+ EXPECT_TRUE(pc_proxy_->UpdateIce(PeerConnectionInterface::IceServers(),
+ constraints));
}
TEST_F(PeerConnectionProxyTest, AddIceCandidate) {
View
6 talk/app/webrtc/statscollector.cc
@@ -69,8 +69,8 @@ void StatsElement::AddValue(const std::string& name, const std::string& value) {
values.push_back(temp);
}
-void StatsElement::AddValue(const std::string& name, int value) {
- AddValue(name, talk_base::ToString<int>(value));
+void StatsElement::AddValue(const std::string& name, int64 value) {
+ AddValue(name, talk_base::ToString<int64>(value));
}
namespace {
@@ -188,7 +188,7 @@ void ExtractStatsFromList(const std::vector<T>& data,
for (; it != data.end(); ++it) {
std::string label;
uint32 ssrc = ExtractSsrc(*it);
- if (!collector->session()->GetTrackLabelBySsrc(ssrc, &label)) {
+ if (!collector->session()->GetTrackIdBySsrc(ssrc, &label)) {
LOG(LS_ERROR) << "The SSRC " << ssrc
<< " is not associated with a track";
continue;
View
136 talk/app/webrtc/statscollector_unittest.cc
@@ -0,0 +1,136 @@
+/*
+ * libjingle
+ *
+ * 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 <stdio.h>
+
+#include "talk/app/webrtc/statscollector.h"
+
+#include "talk/app/webrtc/mediastream.h"
+#include "talk/app/webrtc/videotrack.h"
+#include "talk/base/gunit.h"
+#include "talk/media/base/fakemediaengine.h"
+#include "talk/media/devices/fakedevicemanager.h"
+#include "talk/p2p/base/fakesession.h"
+#include "talk/session/media/channelmanager.h"
+#include "testing/base/public/gmock.h"
+
+using testing::_;
+using testing::DoAll;
+using testing::Return;
+using testing::SetArgPointee;
+
+namespace cricket {
+
+class ChannelManager;
+class FakeDeviceManager;
+
+} // namespace cricket
+
+namespace {
+
+class MockWebRtcSession : public webrtc::WebRtcSession {
+ public:
+ explicit MockWebRtcSession(cricket::ChannelManager* channel_manager)
+ : WebRtcSession(channel_manager, talk_base::Thread::Current(),
+ NULL, NULL, NULL) {
+ }
+ MOCK_METHOD0(video_channel, cricket::VideoChannel*());
+ MOCK_METHOD2(GetTrackIdBySsrc, bool(uint32, std::string*));
+};
+
+class MockVideoMediaChannel : public cricket::FakeVideoMediaChannel {
+ public:
+ MockVideoMediaChannel()
+ : cricket::FakeVideoMediaChannel(NULL) {
+ }
+ MOCK_METHOD1(GetStats, bool(cricket::VideoMediaInfo*));
+};
+
+std::string ExtractStatsValue(webrtc::StatsReports reports,
+ const std::string name) {
+ if (reports.empty()) {
+ return "NO REPORTS";
+ }
+ webrtc::StatsElement::Values::const_iterator it =
+ reports[0].local.values.begin();
+ for (; it != reports[0].local.values.end(); ++it) {
+ if (it->name == name) {
+ return it->value;
+ }
+ }
+ return "NOT FOUND";
+}
+
+// This test verifies that 64-bit counters are handled by truncation when
+// they pass the 32-bit possible values.
+// It documents existing behavior, it does not recommend it.
+TEST(StatsCollector, BytesCounterHandles64Bits) {
+ webrtc::StatsCollector stats; // Implementation under test.
+ cricket::FakeMediaEngine* media_engine = new cricket::FakeMediaEngine;
+ // The media_engine is owned by the channel_manager.
+ talk_base::scoped_ptr<cricket::ChannelManager> channel_manager(
+ new cricket::ChannelManager(media_engine,
+ new cricket::FakeDeviceManager(),
+ talk_base::Thread::Current()));
+ MockWebRtcSession session(channel_manager.get());
+ MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
+ cricket::VideoChannel video_channel(talk_base::Thread::Current(),
+ media_engine, media_channel, &session, "", false, NULL);
+ webrtc::StatsReports reports; // returned values.
+ cricket::VideoSenderInfo video_sender_info;
+ cricket::VideoMediaInfo stats_read;
+ const uint32 kSsrcOfTrack = 1234;
+ const std::string kNameOfTrack("somename");
+ // The number of bytes must be larger than 0xFFFFFFFF for this test.
+ const int64 kBytesSent = 12345678901234LL;
+ const std::string kBytesSentString("12345678901234");
+
+ stats.set_session(&session);
+ talk_base::scoped_refptr<webrtc::MediaStream> stream(
+ webrtc::MediaStream::Create("streamlabel"));
+ stream->AddTrack(webrtc::VideoTrack::Create(kNameOfTrack, NULL));
+ stats.AddStream(stream);
+
+ // Construct a stats value to read.
+ video_sender_info.ssrcs.push_back(1234);
+ video_sender_info.bytes_sent = kBytesSent;
+ stats_read.senders.push_back(video_sender_info);
+
+ EXPECT_CALL(session, video_channel())
+ .WillRepeatedly(Return(&video_channel));
+ EXPECT_CALL(*media_channel, GetStats(_))
+ .WillOnce(DoAll(SetArgPointee<0>(stats_read),
+ Return(true)));
+ EXPECT_CALL(session, GetTrackIdBySsrc(kSsrcOfTrack, _))
+ .WillOnce(DoAll(SetArgPointee<1>(kNameOfTrack),
+ Return(true)));
+ stats.UpdateStats();
+ stats.GetStats(NULL, &reports);
+ std::string result = ExtractStatsValue(reports, "bytesSent");
+ EXPECT_EQ(kBytesSentString, result);
+}
+
+} // namespace
View
2  talk/app/webrtc/statstypes.h
@@ -50,7 +50,7 @@ class StatsElement {
StatsElement() : timestamp(0) { }
void AddValue(const std::string& name, const std::string& value);
- void AddValue(const std::string& name, int value);
+ void AddValue(const std::string& name, int64 value);
double timestamp; // Time since 1970-01-01T00:00:00Z in milliseconds.
typedef std::vector<Value> Values;
View
20 talk/app/webrtc/test/fakeconstraints.h
@@ -97,6 +97,26 @@ class FakeConstraints : public webrtc::MediaConstraintsInterface {
}
}
+ void SetMandatoryUseRtpMux(bool enable) {
+ if (enable) {
+ AddMandatory(MediaConstraintsInterface::kUseRtpMux,
+ MediaConstraintsInterface::kValueTrue);
+ } else {
+ AddMandatory(MediaConstraintsInterface::kUseRtpMux,
+ MediaConstraintsInterface::kValueFalse);
+ }
+ }
+
+ void SetMandatoryIceRestart(bool enable) {
+ if (enable) {
+ AddMandatory(MediaConstraintsInterface::kIceRestart,
+ MediaConstraintsInterface::kValueTrue);
+ } else {
+ AddMandatory(MediaConstraintsInterface::kIceRestart,
+ MediaConstraintsInterface::kValueFalse);
+ }
+ }
+
void SetAllowRtpDataChannels() {
AddMandatory(MediaConstraintsInterface::kEnableRtpDataChannels,
MediaConstraintsInterface::kValueTrue);
View
15 talk/app/webrtc/webrtcsdp.cc
@@ -163,8 +163,6 @@ static const char kMediaTypeVideo[] = "video";
static const char kMediaTypeAudio[] = "audio";
static const char kMediaTypeData[] = "application";
static const char kMediaPortRejected[] = "0";
-static const char kMediaProtocolAvpf[] = "RTP/AVPF";
-static const char kMediaProtocolSavpf[] = "RTP/SAVPF";
static const char kDefaultAddress[] = "0.0.0.0";
static const char kDefaultPort[] = "1";
@@ -970,17 +968,12 @@ void BuildMediaDescription(const ContentInfo* content_info,
// the answer MUST be set to zero.
const std::string port = content_info->rejected ?
kMediaPortRejected : kDefaultPort;
- const char* proto = kMediaProtocolAvpf;
+
talk_base::SSLFingerprint* fp = (transport_info) ?
transport_info->description.identity_fingerprint.get() : NULL;
- // RFC 4568
- // If we're doing SRTP (either SDES or DTLS), use the SAVPF profile.
- if (media_desc->cryptos().size() > 0 || fp) {
- proto = kMediaProtocolSavpf;
- }
InitLine(kLineTypeMedia, type, &os);
- os << " " << port << " " << proto << fmt;
+ os << " " << port << " " << media_desc->protocol() << fmt;
AddLine(os.str(), message);
// Use the transport_info to build the media level ice-ufrag and ice-pwd.
@@ -1514,6 +1507,8 @@ bool ParseMediaDescription(const std::string& message,
rejected = true;
}
+ std::string protocol = fields[2];
+
// <fmt>
std::vector<int> codec_preference;
for (size_t j = 3 ; j < fields.size(); ++j) {
@@ -1589,7 +1584,7 @@ bool ParseMediaDescription(const std::string& message,
for (size_t i = 0; i < session_extmaps.size(); ++i) {
content->AddRtpHeaderExtension(session_extmaps[i]);
}
-
+ content->set_protocol(protocol);
desc->AddContent(content_name, cricket::NS_JINGLE_RTP, rejected,
content.release());
// Create TransportInfo with the media level "ice-pwd" and "ice-ufrag".
View
5 talk/app/webrtc/webrtcsdp_unittest.cc
@@ -397,6 +397,7 @@ class WebRtcSdpTest : public testing::Test {
audio->AddCrypto(CryptoParams(1, "AES_CM_128_HMAC_SHA1_32",
"inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32",
"dummy_session_params"));
+ audio->set_protocol(cricket::kMediaProtocolSavpf);
audio->AddCodec(AudioCodec(103, "ISAC", 16000, 0, 1, 2));
audio->AddCodec(AudioCodec(104, "CELT", 32000, 0, 2, 1));
desc_.AddContent(kAudioContentName, NS_JINGLE_RTP,
@@ -429,6 +430,7 @@ class WebRtcSdpTest : public testing::Test {
video->AddStream(video_stream3);
video->AddCrypto(CryptoParams(1, "AES_CM_128_HMAC_SHA1_80",
"inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32", ""));
+ video->set_protocol(cricket::kMediaProtocolSavpf);
video->AddCodec(VideoCodec(
120,
JsepSessionDescription::kDefaultVideoCodecName,
@@ -603,6 +605,8 @@ class WebRtcSdpTest : public testing::Test {
const CryptoParams c2 = cd2->cryptos().at(i);
EXPECT_TRUE(c1.Matches(c2));
}
+ // protocol
+ EXPECT_EQ(cd1->protocol(), cd2->protocol());
// codecs
EXPECT_EQ(cd1->codecs(), cd2->codecs());
@@ -921,6 +925,7 @@ class WebRtcSdpTest : public testing::Test {
data_desc_->AddCrypto(CryptoParams(
1, "AES_CM_128_HMAC_SHA1_80",
"inline:FvLcvU2P3ZWmQxgPAgcDu7Zl9vftYElFOjEzhWs5", ""));
+ data_desc_->set_protocol(cricket::kMediaProtocolSavpf);
desc_.AddContent(kDataContentName, NS_JINGLE_RTP, data.release());
EXPECT_TRUE(desc_.AddTransportInfo(
TransportInfo(kDataContentName,
View
65 talk/app/webrtc/webrtcsession.cc
@@ -64,10 +64,6 @@ static const uint64 kInitSessionVersion = 2;
static const int kCallSetupTimeout = 30 * 1000;
// Supported MediaConstraints.
-const char MediaConstraintsInterface::kOfferToReceiveAudio[] =
- "OfferToReceiveAudio";
-const char MediaConstraintsInterface::kOfferToReceiveVideo[] =
- "OfferToReceiveVideo";
// DTLS-SRTP pseudo-constraints.
const char MediaConstraintsInterface::kEnableDtlsSrtp[] =
"DtlsSrtpKeyAgreement";
@@ -385,9 +381,14 @@ void WebRtcSession::set_secure_policy(
}
SessionDescriptionInterface* WebRtcSession::CreateOffer(
- const MediaHints& hints) {
- cricket::MediaSessionOptions options =
- mediastream_signaling_->GetOptionsForOffer(hints);
+ const MediaConstraintsInterface* constraints) {
+ cricket::MediaSessionOptions options;
+
+ if (!mediastream_signaling_->GetOptionsForOffer(constraints, &options)) {
+ LOG(LS_ERROR) << "CreateOffer called with invalid constraints.";
+ return NULL;
+ }
+
if (!ValidStreams(options.streams)) {
LOG(LS_ERROR) << "CreateOffer called with invalid media streams.";
return NULL;
@@ -417,30 +418,15 @@ SessionDescriptionInterface* WebRtcSession::CreateOffer(
return offer;
}
-SessionDescriptionInterface* WebRtcSession::CreateOffer(
- const MediaConstraintsInterface* constraints) {
- bool receive_audio = false;
- std::string value;
- if (FindConstraint(constraints,
- MediaConstraintsInterface::kOfferToReceiveAudio,
- &value, NULL)) {
- receive_audio = (value == MediaConstraintsInterface::kValueTrue);
- }
- bool receive_video = false;
- if (FindConstraint(constraints,
- MediaConstraintsInterface::kOfferToReceiveVideo,
- &value, NULL)) {
- receive_video = (value == MediaConstraintsInterface::kValueTrue);
- }
-
- return CreateOffer(MediaHints(receive_audio, receive_video));
-}
-
SessionDescriptionInterface* WebRtcSession::CreateAnswer(
- const MediaHints& hints,
+ const MediaConstraintsInterface* constraints,
const SessionDescriptionInterface* offer) {
- cricket::MediaSessionOptions options =
- mediastream_signaling_->GetOptionsForAnswer(hints);
+ cricket::MediaSessionOptions options;
+ if (!mediastream_signaling_->GetOptionsForAnswer(constraints, &options)) {
+ LOG(LS_ERROR) << "CreateAnswer called with invalid constraints.";
+ return NULL;
+ }
+
if (!offer) {
LOG(LS_ERROR) << "Offer can't be NULL in CreateAnswer.";
return NULL;
@@ -472,25 +458,6 @@ SessionDescriptionInterface* WebRtcSession::CreateAnswer(
return answer;
}
-SessionDescriptionInterface* WebRtcSession::CreateAnswer(
- const MediaConstraintsInterface* constraints,
- const SessionDescriptionInterface* offer) {
- bool receive_audio = true;
- std::string value;
- if (FindConstraint(constraints,
- MediaConstraintsInterface::kOfferToReceiveAudio,
- &value, NULL)) {
- receive_audio = (value == MediaConstraintsInterface::kValueTrue);
- }
- bool receive_video = true;
- if (FindConstraint(constraints,
- MediaConstraintsInterface::kOfferToReceiveVideo,
- &value, NULL)) {
- receive_video = (value == MediaConstraintsInterface::kValueTrue);
- }
- return CreateAnswer(MediaHints(receive_audio, receive_video), offer);
-}
-
bool WebRtcSession::SetLocalDescription(SessionDescriptionInterface* desc) {
if (!desc || !desc->description()) {
LOG(LS_ERROR) << "SetLocalDescription called with an invalid session"
@@ -690,7 +657,7 @@ bool WebRtcSession::ProcessIceMessage(const IceCandidateInterface* candidate) {
return UseCandidatesInSessionDescription(remote_desc_.get());
}
-bool WebRtcSession::GetTrackLabelBySsrc(uint32 ssrc, std::string* name) {
+bool WebRtcSession::GetTrackIdBySsrc(uint32 ssrc, std::string* name) {
if (GetLocalTrackName(ssrc, name)) {
if (GetRemoteTrackName(ssrc, name)) {
LOG(LS_WARNING) << "SSRC " << ssrc
View
34 talk/app/webrtc/webrtcsession.h
@@ -30,8 +30,8 @@
#include <string>
+#include "talk/app/webrtc/peerconnectioninterface.h"
#include "talk/app/webrtc/dtmfsender.h"
-#include "talk/app/webrtc/jsep.h"
#include "talk/app/webrtc/mediastreamprovider.h"
#include "talk/app/webrtc/datachannel.h"
#include "talk/app/webrtc/statstypes.h"
@@ -59,6 +59,21 @@ namespace webrtc {
class MediaStreamSignaling;
+// Ice candidate callback interface.
+class IceCandidateObserver {
+ public:
+ // TODO(ronghuawu): Implement OnIceChange.
+ // Called any time the iceState changes.
+ virtual void OnIceChange() {}
+ // New Ice candidate have been found.
+ virtual void OnIceCandidate(const IceCandidateInterface* candidate) = 0;
+ // All Ice candidates have been found.
+ virtual void OnIceComplete() {}
+
+ protected:
+ ~IceCandidateObserver() {}
+};
+
class WebRtcSession : public cricket::BaseSession,
public AudioProviderInterface,
public DataChannelFactory,
@@ -78,13 +93,13 @@ class WebRtcSession : public cricket::BaseSession,
ice_observer_ = observer;
}
- cricket::VoiceChannel* voice_channel() {
+ virtual cricket::VoiceChannel* voice_channel() {
return voice_channel_.get();
}
- cricket::VideoChannel* video_channel() {
+ virtual cricket::VideoChannel* video_channel() {
return video_channel_.get();
}
- cricket::DataChannel* data_channel() {
+ virtual cricket::DataChannel* data_channel() {
return data_channel_.get();
}
@@ -97,12 +112,9 @@ class WebRtcSession : public cricket::BaseSession,
// TODO - It may be necessary to supply error code as well.
sigslot::signal0<> SignalError;
- SessionDescriptionInterface* CreateOffer(const MediaHints& hints);
SessionDescriptionInterface* CreateOffer(
const MediaConstraintsInterface* constraints);
- SessionDescriptionInterface* CreateAnswer(
- const MediaHints& hints,
- const SessionDescriptionInterface* offer);
+
SessionDescriptionInterface* CreateAnswer(
const MediaConstraintsInterface* constraints,
const SessionDescriptionInterface* offer);
@@ -117,8 +129,8 @@ class WebRtcSession : public cricket::BaseSession,
return remote_desc_.get();
}
- // Get the label used as a media stream track's "label" field from ssrc.
- bool GetTrackLabelBySsrc(uint32 ssrc, std::string* name);
+ // Get the id used as a media stream track's "id" field from ssrc.
+ virtual bool GetTrackIdBySsrc(uint32 ssrc, std::string* name);
// AudioMediaProviderInterface implementation.
virtual void SetAudioPlayout(const std::string& name, bool enable);
@@ -223,7 +235,7 @@ class WebRtcSession : public cricket::BaseSession,
cricket::TransportDescriptionFactory transport_desc_factory_;
cricket::MediaSessionDescriptionFactory session_desc_factory_;
MediaStreamSignaling* mediastream_signaling_;
- IceCandidateObserver * ice_observer_;
+ IceCandidateObserver* ice_observer_;
talk_base::scoped_ptr<SessionDescriptionInterface> local_desc_;
talk_base::scoped_ptr<SessionDescriptionInterface> remote_desc_;
// Candidates that arrived before the remote description was set.
View
574 talk/app/webrtc/webrtcsession_unittest.cc
@@ -25,9 +25,12 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "talk/app/webrtc/audiotrack.h"
#include "talk/app/webrtc/jsepicecandidate.h"
#include "talk/app/webrtc/jsepsessiondescription.h"
#include "talk/app/webrtc/mediastreamsignaling.h"
+#include "talk/app/webrtc/streamcollection.h"
+#include "talk/app/webrtc/videotrack.h"
#include "talk/app/webrtc/test/fakeconstraints.h"
#include "talk/app/webrtc/webrtcsession.h"
#include "talk/base/fakenetwork.h"
@@ -69,11 +72,8 @@ using talk_base::scoped_ptr;
using talk_base::SocketAddress;
using webrtc::IceCandidateCollection;
using webrtc::FakeConstraints;
-using webrtc::MediaHints;
-using webrtc::JsepInterface;
using webrtc::JsepSessionDescription;
using webrtc::JsepIceCandidate;
-using webrtc::MediaHints;
using webrtc::SessionDescriptionInterface;
static const SocketAddress kClientAddr1("11.11.11.11", 0);
@@ -166,85 +166,46 @@ class FakeMediaStreamSignaling : public webrtc::MediaStreamSignaling,
public:
FakeMediaStreamSignaling() :
webrtc::MediaStreamSignaling(talk_base::Thread::Current(), this) {
- options_.has_audio = false;
- options_.has_video = false;
}
- // Overrides GetMediaSessionOptions in MediaStreamSignaling.
- // This function returns MediaSessionOptions based on what UseOptions...
- // function that have been called previous to this call.
- // The MediaSessionOptions.has_audio and MediaSessionOptions.had_video is true
- // if |offer_audio| or |offer_video| request it to be true or if a track of
- // the type have been added.
- // This is the same behavior as the real MediaStreamSignaling
- // implementation.
- virtual const cricket::MediaSessionOptions& GetOptionsForOffer(
- const MediaHints& hints) {
- options_.has_audio |= hints.has_audio();
- options_.has_video |= hints.has_video();
- return options_;
+ void SendAudioVideoStream1() {
+ talk_base::scoped_refptr<webrtc::StreamCollection> streams(
+ webrtc::StreamCollection::Create());
+ streams->AddStream(CreateStream(kStream1, kAudioTrack1, kVideoTrack1));
+ SetLocalStreams(streams);
}
- virtual cricket::MediaSessionOptions GetOptionsForAnswer(
- const MediaHints& hints) {
- cricket::MediaSessionOptions options = options_;
- options.has_audio |= hints.has_audio();
- options.has_video |= hints.has_video();
- return options;
+ void SendAudioVideoStream2() {
+ talk_base::scoped_refptr<webrtc::StreamCollection> streams(
+ webrtc::StreamCollection::Create());
+ streams->AddStream(CreateStream(kStream2, kAudioTrack2, kVideoTrack2));
+ SetLocalStreams(streams);
}
- void UseOptionsWithStream1(bool bundle = false) {
- cricket::MediaSessionOptions options;
- options.bundle_enabled = bundle;
- options.AddStream(cricket::MEDIA_TYPE_VIDEO, kVideoTrack1, kStream1);
- options.AddStream(cricket::MEDIA_TYPE_AUDIO, kAudioTrack1, kStream1);
- options.has_audio = true;
- options.has_video = true;
- options_ = options;
- }
-
- void UseOptionsWithStream2(bool bundle = false) {
- cricket::MediaSessionOptions options;
- options.bundle_enabled = bundle;
- options.AddStream(cricket::MEDIA_TYPE_VIDEO, kVideoTrack2, kStream2);
- options.AddStream(cricket::MEDIA_TYPE_AUDIO, kAudioTrack2, kStream2);
- options.has_audio = true;
- options.has_video = true;
- options_ = options;
+ void SendAudioVideoStream1And2() {
+ talk_base::scoped_refptr<webrtc::StreamCollection> streams(
+ webrtc::StreamCollection::Create());
+ streams->AddStream(CreateStream(kStream1, kAudioTrack1, kVideoTrack1));
+ streams->AddStream(CreateStream(kStream2, kAudioTrack2, kVideoTrack2));
+ SetLocalStreams(streams);
}
- void UseOptionsWithStream1And2() {
- cricket::MediaSessionOptions options;
- options.AddStream(cricket::MEDIA_TYPE_VIDEO, kVideoTrack1, kStream1);
- options.AddStream(cricket::MEDIA_TYPE_AUDIO, kAudioTrack1, kStream1);
- options.AddStream(cricket::MEDIA_TYPE_VIDEO, kVideoTrack2, kStream2);
- options.AddStream(cricket::MEDIA_TYPE_AUDIO, kAudioTrack2, kStream2);
- options.has_audio = true;
- options.has_video = true;
- options_ = options;
- }
-
- void UseOptionsReceiveOnly() {
- cricket::MediaSessionOptions options;
- options.has_audio = true;
- options.has_video = true;
- options_ = options;
+ void SendNothing() {
+ SetLocalStreams(webrtc::StreamCollection::Create());
}
void UseOptionsAudioOnly() {
- cricket::MediaSessionOptions options;
- options.AddStream(cricket::MEDIA_TYPE_AUDIO, kAudioTrack2, kStream2);
- options.has_audio = true;
- options.has_video = false;
- options_ = options;
+ talk_base::scoped_refptr<webrtc::StreamCollection> streams(
+ webrtc::StreamCollection::Create());
+ streams->AddStream(CreateStream(kStream2, kAudioTrack2, ""));
+ SetLocalStreams(streams);
}
void UseOptionsVideoOnly() {
- cricket::MediaSessionOptions options;
- options.AddStream(cricket::MEDIA_TYPE_VIDEO, kVideoTrack2, kStream2);
- options.has_audio = false;
- options.has_video = true;
- options_ = options;
+ talk_base::scoped_refptr<webrtc::StreamCollection> streams(
+ webrtc::StreamCollection::Create());
+ streams->AddStream(CreateStream(kStream2, kAudioTrack1, kVideoTrack2));
+ SetLocalStreams(streams);
}
// Implements RemoteMediaStreamObserver.
@@ -257,6 +218,27 @@ class FakeMediaStreamSignaling : public webrtc::MediaStreamSignaling,
private:
+ talk_base::scoped_refptr<webrtc::MediaStreamInterface> CreateStream(
+ const std::string& stream_label,
+ const std::string& audio_track_id,
+ const std::string& video_track_id) {
+ talk_base::scoped_refptr<webrtc::MediaStreamInterface> stream(
+ webrtc::MediaStream::Create(stream_label));
+
+ if (!audio_track_id.empty()) {
+ talk_base::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
+ webrtc::AudioTrack::Create(audio_track_id, NULL));
+ stream->AddTrack(audio_track);
+ }
+
+ if (!video_track_id.empty()) {
+ talk_base::scoped_refptr<webrtc::VideoTrackInterface> video_track(
+ webrtc::VideoTrack::Create(video_track_id, NULL));
+ stream->AddTrack(video_track);
+ }
+ return stream;
+ }
+
cricket::MediaSessionOptions options_;
};
@@ -323,7 +305,7 @@ class WebRtcSessionTest : public testing::Test {
// Call mediastream_signaling_.UseOptionsWithStreamX() before this function
// to decide which streams to create.
void InitiateCall() {
- SessionDescriptionInterface* offer = session_->CreateOffer(MediaHints());
+ SessionDescriptionInterface* offer = session_->CreateOffer(NULL);
EXPECT_TRUE(session_->SetLocalDescription(offer));
}
@@ -339,8 +321,7 @@ class WebRtcSessionTest : public testing::Test {
EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 2) != NULL);
}
- void VerifyCryptoParams(const cricket::SessionDescription* sdp,
- bool offer) {
+ void VerifyCryptoParams(const cricket::SessionDescription* sdp) {
ASSERT_TRUE(session_.get() != NULL);
const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
ASSERT_TRUE(content != NULL);
@@ -348,22 +329,12 @@ class WebRtcSessionTest : public testing::Test {
static_cast<const cricket::AudioContentDescription*>(
content->description);
ASSERT_TRUE(audio_content != NULL);
- if (offer) {
- ASSERT_EQ(2U, audio_content->cryptos().size());
- // key(40) + inline string
- ASSERT_EQ(47U, audio_content->cryptos()[0].key_params.size());
- ASSERT_EQ("AES_CM_128_HMAC_SHA1_32",
- audio_content->cryptos()[0].cipher_suite);
- ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
- audio_content->cryptos()[1].cipher_suite);
- ASSERT_EQ(47U, audio_content->cryptos()[1].key_params.size());
- } else {
- ASSERT_EQ(1U, audio_content->cryptos().size());
- // key(40) + inline string
- ASSERT_EQ(47U, audio_content->cryptos()[0].key_params.size());
- ASSERT_EQ("AES_CM_128_HMAC_SHA1_32",
- audio_content->cryptos()[0].cipher_suite);
- }
+ ASSERT_EQ(1U, audio_content->cryptos().size());
+ ASSERT_EQ(47U, audio_content->cryptos()[0].key_params.size());
+ ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
+ audio_content->cryptos()[0].cipher_suite);
+ EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
+ audio_content->protocol());
content = cricket::GetFirstVideoContent(sdp);
ASSERT_TRUE(content != NULL);
@@ -375,9 +346,11 @@ class WebRtcSessionTest : public testing::Test {
ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
video_content->cryptos()[0].cipher_suite);
ASSERT_EQ(47U, video_content->cryptos()[0].key_params.size());
+ EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
+ video_content->protocol());
}
- void VerifyNoCryptoParams(const cricket::SessionDescription* sdp) {
+ void VerifyNoCryptoParams(const cricket::SessionDescription* sdp, bool dtls) {
const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
ASSERT_TRUE(content != NULL);
const cricket::AudioContentDescription* audio_content =
@@ -393,6 +366,18 @@ class WebRtcSessionTest : public testing::Test {
content->description);
ASSERT_TRUE(video_content != NULL);
ASSERT_EQ(0U, video_content->cryptos().size());
+
+ if (dtls) {
+ EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
+ audio_content->protocol());
+ EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
+ video_content->protocol());
+ } else {
+ EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
+ audio_content->protocol());
+ EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
+ video_content->protocol());
+ }
}
// Set the internal fake description factories to do DTLS-SRTP.
@@ -432,9 +417,9 @@ class WebRtcSessionTest : public testing::Test {
scoped_ptr<JsepSessionDescription> offer(
CreateOfferSessionDescription(options));
ASSERT_TRUE(offer.get() != NULL);
- VerifyNoCryptoParams(offer->description());
+ VerifyNoCryptoParams(offer->description(), false);
const webrtc::SessionDescriptionInterface* answer =
- session_->CreateAnswer(MediaHints(), offer.get());
+ session_->CreateAnswer(NULL, offer.get());
// Answer should be NULL as no crypto params in offer.
ASSERT_TRUE(answer == NULL);
}
@@ -443,14 +428,15 @@ class WebRtcSessionTest : public testing::Test {
desc_factory_->set_secure(cricket::SEC_REQUIRED);
cricket::MediaSessionOptions options;
options.has_video = true;
+ options.bundle_enabled = true;
scoped_ptr<JsepSessionDescription> offer(
CreateOfferSessionDescription(options));
ASSERT_TRUE(offer.get() != NULL);
- VerifyCryptoParams(offer->description(), true);
+ VerifyCryptoParams(offer->description());
scoped_ptr<SessionDescriptionInterface> answer(
- session_->CreateAnswer(MediaHints(), offer.get()));
+ session_->CreateAnswer(NULL, offer.get()));
ASSERT_TRUE(answer.get() != NULL);
- VerifyCryptoParams(answer->description(), false);
+ VerifyCryptoParams(answer->description());
}
// Creates and offer and an answer and applies it on the offer.
// Call mediastream_signaling_.UseOptionsWithStreamX() before this function
@@ -475,12 +461,12 @@ class WebRtcSessionTest : public testing::Test {
void CreateCryptoOfferAndNonCryptoAnswer(SessionDescriptionInterface** offer,
JsepSessionDescription** nocrypto_answer) {
- mediastream_signaling_.UseOptionsWithStream2();
- *offer = session_->CreateOffer(MediaHints());
+ mediastream_signaling_.SendAudioVideoStream2();
+ *offer = session_->CreateOffer(NULL);
- mediastream_signaling_.UseOptionsWithStream1();
+ mediastream_signaling_.SendAudioVideoStream1();
talk_base::scoped_ptr<SessionDescriptionInterface> answer(
- session_->CreateAnswer(MediaHints(), *offer));
+ session_->CreateAnswer(NULL, *offer));
std::string nocrypto_answer_str;
answer->ToString(&nocrypto_answer_str);
// Disable the crypto
@@ -512,33 +498,56 @@ class WebRtcSessionTest : public testing::Test {
return CreateOfferSessionDescriptionWithVersion(options,
kSessionVersion);
}
+
+ JsepSessionDescription* CreateAnswerSessionDescription(
+ SessionDescriptionInterface* offer,
+ cricket::MediaSessionOptions options) {
+ desc_factory_->set_secure(cricket::SEC_REQUIRED);
+ const std::string session_id =
+ talk_base::ToString(talk_base::CreateRandomId());
+ JsepSessionDescription* answer(
+ new JsepSessionDescription(JsepSessionDescription::kAnswer));
+ if (!answer->Initialize(desc_factory_->CreateAnswer(offer->description(),
+ options, NULL),
+ session_id, kSessionVersion)) {
+ delete answer;
+ answer = NULL;
+ }
+ return answer;
+ }
+
void TestSessionCandidatesWithBundleRtcpMux(bool bundle, bool rtcp_mux) {
AddInterface(kClientAddr1);
WebRtcSessionTest::Init();
- mediastream_signaling_.UseOptionsWithStream1(bundle);
- SessionDescriptionInterface* offer = session_->CreateOffer(MediaHints());
- mediastream_signaling_.UseOptionsWithStream2(bundle);
- SessionDescriptionInterface* answer = session_->CreateAnswer(MediaHints(),
+ mediastream_signaling_.SendAudioVideoStream1();
+ FakeConstraints constraints;
+ constraints.SetMandatoryUseRtpMux(bundle);
+ SessionDescriptionInterface* offer = session_->CreateOffer(&constraints);
+ mediastream_signaling_.SendAudioVideoStream2();
+ SessionDescriptionInterface* answer = session_->CreateAnswer(NULL,
offer);
+ std::string sdp;
+ EXPECT_TRUE(answer->ToString(&sdp));
+
size_t expected_candidate_num = 2;
if (!rtcp_mux) {
// If rtcp_mux is enabled we should expect 4 candidates - host and srflex
// for rtp and rtcp.
expected_candidate_num = 4;
// Disable rtcp-mux from the answer
- std::string sdp;
- EXPECT_TRUE(answer->ToString(&sdp));
+
const std::string kRtcpMux = "a=rtcp-mux";
const std::string kXRtcpMux = "a=xrtcp-mux";
talk_base::replace_substrs(kRtcpMux.c_str(), kRtcpMux.length(),
kXRtcpMux.c_str(), kXRtcpMux.length(),
&sdp);
- JsepSessionDescription* new_answer(
- new JsepSessionDescription(JsepSessionDescription::kAnswer));
- EXPECT_TRUE(new_answer->Initialize(sdp));
- delete answer;
- answer = new_answer;
}
+
+ JsepSessionDescription* new_answer(
+ new JsepSessionDescription(JsepSessionDescription::kAnswer));
+ EXPECT_TRUE(new_answer->Initialize(sdp));
+ delete answer;
+ answer = new_answer;
// SetLocalDescription and SetRemoteDescriptions takes ownership of offer
// and answer.
EXPECT_TRUE(session_->SetLocalDescription(offer));
@@ -564,7 +573,7 @@ class WebRtcSessionTest : public testing::Test {
} else {
WebRtcSessionTest::Init();
}
- mediastream_signaling_.UseOptionsWithStream1();
+ mediastream_signaling_.SendAudioVideoStream1();
SetRemoteAndLocalSessionDescription();
EXPECT_FALSE(session_->CanInsertDtmf(""));
EXPECT_EQ(can, session_->CanInsertDtmf(kAudioTrack1));
@@ -633,10 +642,11 @@ TEST_F(WebRtcSessionTest, TestSessionCandidatesWithBundleRtcpMux) {
TestSessionCandidatesWithBundleRtcpMux(true, true);
}
-TEST_F(WebRtcSessionTest, TestMultihomeCandidataes) {
+TEST_F(WebRtcSessionTest, TestMultihomeCandidates) {
AddInterface(kClientAddr1);
AddInterface(kClientAddr2);
WebRtcSessionTest::Init();
+ mediastream_signaling_.SendAudioVideoStream1();
WebRtcSessionTest::InitiateCall();
EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
EXPECT_EQ(8u, observer_.mline_0_candidates_.size());
@@ -648,6 +658,7 @@ TEST_F(WebRtcSessionTest, TestStunError) {
AddInterface(kClientAddr2);
fss_->AddRule(false, talk_base::FP_UDP, talk_base::FD_ANY, kClientAddr1);
WebRtcSessionTest::Init();
+ mediastream_signaling_.SendAudioVideoStream1();
WebRtcSessionTest::InitiateCall();
// Since kClientAddr1 is blocked, not expecting stun candidates for it.
EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
@@ -659,13 +670,13 @@ TEST_F(WebRtcSessionTest, TestStunError) {
// media engine creates the expected send and receive streams.
TEST_F(WebRtcSessionTest, TestCreateOfferReceiveAnswer) {
WebRtcSessionTest::Init();
- mediastream_signaling_.UseOptionsWithStream1();
- SessionDescriptionInterface* offer = session_->CreateOffer(MediaHints());
+ mediastream_signaling_.SendAudioVideoStream1();
+ SessionDescriptionInterface* offer = session_->CreateOffer(NULL);
const std::string session_id_orig = offer->session_id();
const std::string session_version_orig = offer->session_version();
- mediastream_signaling_.UseOptionsWithStream2();
- SessionDescriptionInterface* answer = session_->CreateAnswer(MediaHints(),
+ mediastream_signaling_.SendAudioVideoStream2();
+ SessionDescriptionInterface* answer = session_->CreateAnswer(NULL,
offer);
// SetLocalDescription and SetRemoteDescriptions takes ownership of offer
// and answer.
@@ -687,8 +698,8 @@ TEST_F(WebRtcSessionTest, TestCreateOfferReceiveAnswer) {
EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].name);
// Create new offer without send streams.
- mediastream_signaling_.UseOptionsReceiveOnly();
- offer = session_->CreateOffer(MediaHints());
+ mediastream_signaling_.SendNothing();
+ offer = session_->CreateOffer(NULL);
// Verify the session id is the same and the session version is
// increased.
@@ -698,8 +709,8 @@ TEST_F(WebRtcSessionTest, TestCreateOfferReceiveAnswer) {
EXPECT_TRUE(session_->SetLocalDescription(offer));
- mediastream_signaling_.UseOptionsWithStream2();
- answer = session_->CreateAnswer(MediaHints(), offer);
+ mediastream_signaling_.SendAudioVideoStream2();
+ answer = session_->CreateAnswer(NULL, offer);
EXPECT_TRUE(session_->SetRemoteDescription(answer));
EXPECT_EQ(0u, video_channel_->send_streams().size());
@@ -716,11 +727,11 @@ TEST_F(WebRtcSessionTest, TestCreateOfferReceiveAnswer) {
// media engine creates the expected send and receive streams.
TEST_F(WebRtcSessionTest, TestReceiveOfferCreateAnswer) {
WebRtcSessionTest::Init();
- mediastream_signaling_.UseOptionsWithStream2();
- SessionDescriptionInterface* offer = session_->CreateOffer(MediaHints());