summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/webrtc/OWNERS12
-rw-r--r--app/webrtc/datachannelinterface.h2
-rw-r--r--app/webrtc/java/jni/peerconnection_jni.cc404
-rw-r--r--app/webrtc/java/src/org/webrtc/DataChannel.java282
-rw-r--r--app/webrtc/java/src/org/webrtc/PeerConnection.java6
-rw-r--r--app/webrtc/javatests/src/org/webrtc/PeerConnectionTest.java239
-rw-r--r--app/webrtc/mediastreamsignaling_unittest.cc5
-rw-r--r--app/webrtc/objc/RTCPeerConnectionFactory.mm4
-rw-r--r--app/webrtc/peerconnection_unittest.cc1
-rw-r--r--app/webrtc/portallocatorfactory.cc2
-rw-r--r--app/webrtc/webrtcsession_unittest.cc54
-rw-r--r--base/httpbase_unittest.cc1
-rw-r--r--base/multipart_unittest.cc4
-rw-r--r--base/nat_unittest.cc26
-rw-r--r--base/network.cc5
-rw-r--r--base/network_unittest.cc9
-rw-r--r--base/physicalsocketserver_unittest.cc3
-rw-r--r--base/proxydetect.cc4
-rw-r--r--base/signalthread_unittest.cc2
-rw-r--r--base/socket_unittest.cc2
-rw-r--r--build/common.gypi5
-rw-r--r--examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java11
-rwxr-xr-xlibjingle.gyp25
-rwxr-xr-xlibjingle_examples.gyp3
-rwxr-xr-xlibjingle_tests.gyp8
-rw-r--r--media/webrtc/fakewebrtcvideoengine.h6
-rw-r--r--media/webrtc/fakewebrtcvoiceengine.h6
-rw-r--r--session/media/channelmanager.cc9
-rw-r--r--session/media/channelmanager.h5
29 files changed, 934 insertions, 211 deletions
diff --git a/app/webrtc/OWNERS b/app/webrtc/OWNERS
new file mode 100644
index 0000000..548f6d1
--- /dev/null
+++ b/app/webrtc/OWNERS
@@ -0,0 +1,12 @@
+hellner
+juberti
+mallinath
+perkj
+ronghuawu
+tommi
+hellner
+juberti
+mallinath
+perkj
+ronghuawu
+tommi \ No newline at end of file
diff --git a/app/webrtc/datachannelinterface.h b/app/webrtc/datachannelinterface.h
index 9c66a50..6054e1b 100644
--- a/app/webrtc/datachannelinterface.h
+++ b/app/webrtc/datachannelinterface.h
@@ -95,7 +95,7 @@ class DataChannelObserver {
class DataChannelInterface : public talk_base::RefCountInterface {
public:
- enum DataState {
+ enum DataState { // Keep in sync with DataChannel.java:State.
kConnecting,
kOpen, // The DataChannel is ready to send data.
kClosing,
diff --git a/app/webrtc/java/jni/peerconnection_jni.cc b/app/webrtc/java/jni/peerconnection_jni.cc
index 6b5a6a4..63a32e8 100644
--- a/app/webrtc/java/jni/peerconnection_jni.cc
+++ b/app/webrtc/java/jni/peerconnection_jni.cc
@@ -56,6 +56,7 @@
#undef JNIEXPORT
#define JNIEXPORT __attribute__((visibility("default")))
+#include <limits>
#include <map>
#include "talk/app/webrtc/mediaconstraintsinterface.h"
@@ -77,6 +78,10 @@ using webrtc::AudioSourceInterface;
using webrtc::AudioTrackInterface;
using webrtc::AudioTrackVector;
using webrtc::CreateSessionDescriptionObserver;
+using webrtc::DataBuffer;
+using webrtc::DataChannelInit;
+using webrtc::DataChannelInterface;
+using webrtc::DataChannelObserver;
using webrtc::IceCandidateInterface;
using webrtc::MediaConstraintsInterface;
using webrtc::MediaSourceInterface;
@@ -156,6 +161,10 @@ class ClassReferenceHolder {
explicit ClassReferenceHolder(JNIEnv* jni) {
LoadClass(jni, "java/nio/ByteBuffer");
LoadClass(jni, "org/webrtc/AudioTrack");
+ LoadClass(jni, "org/webrtc/DataChannel");
+ LoadClass(jni, "org/webrtc/DataChannel$Buffer");
+ LoadClass(jni, "org/webrtc/DataChannel$Init");
+ LoadClass(jni, "org/webrtc/DataChannel$State");
LoadClass(jni, "org/webrtc/IceCandidate");
LoadClass(jni, "org/webrtc/MediaSource$State");
LoadClass(jni, "org/webrtc/MediaStream");
@@ -254,13 +263,28 @@ jobject GetObjectField(JNIEnv* jni, jobject object, jfieldID id) {
return o;
}
+jstring GetStringField(JNIEnv* jni, jobject object, jfieldID id) {
+ return static_cast<jstring>(GetObjectField(jni, object, id));
+}
+
jlong GetLongField(JNIEnv* jni, jobject object, jfieldID id) {
jlong l = jni->GetLongField(object, id);
CHECK_EXCEPTION(jni, "error during GetLongField");
- CHECK(l, "");
return l;
}
+jint GetIntField(JNIEnv* jni, jobject object, jfieldID id) {
+ jint i = jni->GetIntField(object, id);
+ CHECK_EXCEPTION(jni, "error during GetIntField");
+ return i;
+}
+
+bool GetBooleanField(JNIEnv* jni, jobject object, jfieldID id) {
+ jboolean b = jni->GetBooleanField(object, id);
+ CHECK_EXCEPTION(jni, "error during GetBooleanField");
+ return b;
+}
+
jobject NewGlobalRef(JNIEnv* jni, jobject o) {
jobject ret = jni->NewGlobalRef(o);
CHECK_EXCEPTION(jni, "error during NewGlobalRef");
@@ -314,18 +338,19 @@ class ScopedLocalRef {
};
// Scoped holder for global Java refs.
+template<class T> // T is jclass, jobject, jintArray, etc.
class ScopedGlobalRef {
public:
- explicit ScopedGlobalRef(JNIEnv* jni, jobject obj)
- : obj_(jni->NewGlobalRef(obj)) {}
+ explicit ScopedGlobalRef(JNIEnv* jni, T obj)
+ : obj_(static_cast<T>(jni->NewGlobalRef(obj))) {}
~ScopedGlobalRef() {
DeleteGlobalRef(AttachCurrentThreadIfNeeded(), obj_);
}
- jobject operator*() const {
+ T operator*() const {
return obj_;
}
private:
- jobject obj_;
+ T obj_;
};
// Return the (singleton) Java Enum object corresponding to |index|;
@@ -365,6 +390,32 @@ static std::string JavaToStdString(JNIEnv* jni, const jstring& j_string) {
return ustr.toUTF8String(ret);
}
+static DataChannelInit JavaDataChannelInitToNative(
+ JNIEnv* jni, jobject j_init) {
+ DataChannelInit init;
+
+ jclass j_init_class = FindClass(jni, "org/webrtc/DataChannel$Init");
+ jfieldID ordered_id = GetFieldID(jni, j_init_class, "ordered", "Z");
+ jfieldID max_retransmit_time_id =
+ GetFieldID(jni, j_init_class, "maxRetransmitTimeMs", "I");
+ jfieldID max_retransmits_id =
+ GetFieldID(jni, j_init_class, "maxRetransmits", "I");
+ jfieldID protocol_id =
+ GetFieldID(jni, j_init_class, "protocol", "Ljava/lang/String;");
+ jfieldID negotiated_id = GetFieldID(jni, j_init_class, "negotiated", "Z");
+ jfieldID id_id = GetFieldID(jni, j_init_class, "id", "I");
+
+ init.ordered = GetBooleanField(jni, j_init, ordered_id);
+ init.maxRetransmitTime = GetIntField(jni, j_init, max_retransmit_time_id);
+ init.maxRetransmits = GetIntField(jni, j_init, max_retransmits_id);
+ init.protocol = JavaToStdString(
+ jni, GetStringField(jni, j_init, protocol_id));
+ init.negotiated = GetBooleanField(jni, j_init, negotiated_id);
+ init.id = GetIntField(jni, j_init, id_id);
+
+ return init;
+}
+
class ConstraintsWrapper;
// Adapter between the C++ PeerConnectionObserver interface and the Java
@@ -374,25 +425,24 @@ class PCOJava : public PeerConnectionObserver {
public:
PCOJava(JNIEnv* jni, jobject j_observer)
: j_observer_global_(jni, j_observer),
- j_observer_class_((jclass)NewGlobalRef(
- jni, GetObjectClass(jni, *j_observer_global_))),
- j_media_stream_class_((jclass)NewGlobalRef(
- jni, FindClass(jni, "org/webrtc/MediaStream"))),
- j_media_stream_ctor_(GetMethodID(jni,
- j_media_stream_class_, "<init>", "(J)V")),
- j_audio_track_class_((jclass)NewGlobalRef(
- jni, FindClass(jni, "org/webrtc/AudioTrack"))),
+ j_observer_class_(jni, GetObjectClass(jni, *j_observer_global_)),
+ j_media_stream_class_(jni, FindClass(jni, "org/webrtc/MediaStream")),
+ j_media_stream_ctor_(GetMethodID(
+ jni, *j_media_stream_class_, "<init>", "(J)V")),
+ j_audio_track_class_(jni, FindClass(jni, "org/webrtc/AudioTrack")),
j_audio_track_ctor_(GetMethodID(
- jni, j_audio_track_class_, "<init>", "(J)V")),
- j_video_track_class_((jclass)NewGlobalRef(
- jni, FindClass(jni, "org/webrtc/VideoTrack"))),
- j_video_track_ctor_(GetMethodID(jni,
- j_video_track_class_, "<init>", "(J)V")) {
+ jni, *j_audio_track_class_, "<init>", "(J)V")),
+ j_video_track_class_(jni, FindClass(jni, "org/webrtc/VideoTrack")),
+ j_video_track_ctor_(GetMethodID(
+ jni, *j_video_track_class_, "<init>", "(J)V")),
+ j_data_channel_class_(jni, FindClass(jni, "org/webrtc/DataChannel")),
+ j_data_channel_ctor_(GetMethodID(
+ jni, *j_data_channel_class_, "<init>", "(J)V")) {
}
virtual ~PCOJava() {}
- virtual void OnIceCandidate(const IceCandidateInterface* candidate) {
+ virtual void OnIceCandidate(const IceCandidateInterface* candidate) OVERRIDE {
std::string sdp;
CHECK(candidate->ToString(&sdp), "got so far: " << sdp);
jclass candidate_class = FindClass(jni(), "org/webrtc/IceCandidate");
@@ -404,22 +454,22 @@ class PCOJava : public PeerConnectionObserver {
ScopedLocalRef<jobject> j_candidate(jni(), jni()->NewObject(
candidate_class, ctor, *j_mid, candidate->sdp_mline_index(), *j_sdp));
CHECK_EXCEPTION(jni(), "error during NewObject");
- jmethodID m = GetMethodID(jni(), j_observer_class_,
+ jmethodID m = GetMethodID(jni(), *j_observer_class_,
"onIceCandidate", "(Lorg/webrtc/IceCandidate;)V");
jni()->CallVoidMethod(*j_observer_global_, m, *j_candidate);
CHECK_EXCEPTION(jni(), "error during CallVoidMethod");
}
- virtual void OnError() {
- jmethodID m = GetMethodID(jni(), j_observer_class_, "onError", "(V)V");
+ virtual void OnError() OVERRIDE {
+ jmethodID m = GetMethodID(jni(), *j_observer_class_, "onError", "(V)V");
jni()->CallVoidMethod(*j_observer_global_, m);
CHECK_EXCEPTION(jni(), "error during CallVoidMethod");
}
virtual void OnSignalingChange(
- PeerConnectionInterface::SignalingState new_state) {
+ PeerConnectionInterface::SignalingState new_state) OVERRIDE {
jmethodID m = GetMethodID(
- jni(), j_observer_class_, "onSignalingChange",
+ jni(), *j_observer_class_, "onSignalingChange",
"(Lorg/webrtc/PeerConnection$SignalingState;)V");
ScopedLocalRef<jobject> new_state_enum(jni(), JavaEnumFromIndex(
jni(), "PeerConnection$SignalingState", new_state));
@@ -428,9 +478,9 @@ class PCOJava : public PeerConnectionObserver {
}
virtual void OnIceConnectionChange(
- PeerConnectionInterface::IceConnectionState new_state) {
+ PeerConnectionInterface::IceConnectionState new_state) OVERRIDE {
jmethodID m = GetMethodID(
- jni(), j_observer_class_, "onIceConnectionChange",
+ jni(), *j_observer_class_, "onIceConnectionChange",
"(Lorg/webrtc/PeerConnection$IceConnectionState;)V");
ScopedLocalRef<jobject> new_state_enum(jni(), JavaEnumFromIndex(
jni(), "PeerConnection$IceConnectionState", new_state));
@@ -439,9 +489,9 @@ class PCOJava : public PeerConnectionObserver {
}
virtual void OnIceGatheringChange(
- PeerConnectionInterface::IceGatheringState new_state) {
+ PeerConnectionInterface::IceGatheringState new_state) OVERRIDE {
jmethodID m = GetMethodID(
- jni(), j_observer_class_, "onIceGatheringChange",
+ jni(), *j_observer_class_, "onIceGatheringChange",
"(Lorg/webrtc/PeerConnection$IceGatheringState;)V");
ScopedLocalRef<jobject> new_state_enum(jni(), JavaEnumFromIndex(
jni(), "PeerConnection$IceGatheringState", new_state));
@@ -449,9 +499,9 @@ class PCOJava : public PeerConnectionObserver {
CHECK_EXCEPTION(jni(), "error during CallVoidMethod");
}
- virtual void OnAddStream(MediaStreamInterface* stream) {
+ virtual void OnAddStream(MediaStreamInterface* stream) OVERRIDE {
ScopedLocalRef<jobject> j_stream(jni(), jni()->NewObject(
- j_media_stream_class_, j_media_stream_ctor_, (jlong)stream));
+ *j_media_stream_class_, j_media_stream_ctor_, (jlong)stream));
CHECK_EXCEPTION(jni(), "error during NewObject");
AudioTrackVector audio_tracks = stream->GetAudioTracks();
@@ -460,10 +510,10 @@ class PCOJava : public PeerConnectionObserver {
ScopedLocalRef<jstring> id(
jni(), JavaStringFromStdString(jni(), track->id()));
ScopedLocalRef<jobject> j_track(jni(), jni()->NewObject(
- j_audio_track_class_, j_audio_track_ctor_, (jlong)track, *id));
+ *j_audio_track_class_, j_audio_track_ctor_, (jlong)track, *id));
CHECK_EXCEPTION(jni(), "error during NewObject");
- jfieldID audio_tracks_id = GetFieldID(jni(),
- j_media_stream_class_, "audioTracks", "Ljava/util/List;");
+ jfieldID audio_tracks_id = GetFieldID(
+ jni(), *j_media_stream_class_, "audioTracks", "Ljava/util/List;");
ScopedLocalRef<jobject> audio_tracks(jni(), GetObjectField(
jni(), *j_stream, audio_tracks_id));
jmethodID add = GetMethodID(jni(),
@@ -479,10 +529,10 @@ class PCOJava : public PeerConnectionObserver {
ScopedLocalRef<jstring> id(
jni(), JavaStringFromStdString(jni(), track->id()));
ScopedLocalRef<jobject> j_track(jni(), jni()->NewObject(
- j_video_track_class_, j_video_track_ctor_, (jlong)track, *id));
+ *j_video_track_class_, j_video_track_ctor_, (jlong)track, *id));
CHECK_EXCEPTION(jni(), "error during NewObject");
- jfieldID video_tracks_id = GetFieldID(jni(),
- j_media_stream_class_, "videoTracks", "Ljava/util/List;");
+ jfieldID video_tracks_id = GetFieldID(
+ jni(), *j_media_stream_class_, "videoTracks", "Ljava/util/List;");
ScopedLocalRef<jobject> video_tracks(jni(), GetObjectField(
jni(), *j_stream, video_tracks_id));
jmethodID add = GetMethodID(jni(),
@@ -494,13 +544,13 @@ class PCOJava : public PeerConnectionObserver {
streams_[stream] = jni()->NewWeakGlobalRef(*j_stream);
CHECK_EXCEPTION(jni(), "error during NewWeakGlobalRef");
- jmethodID m = GetMethodID(jni(),
- j_observer_class_, "onAddStream", "(Lorg/webrtc/MediaStream;)V");
+ jmethodID m = GetMethodID(jni(), *j_observer_class_, "onAddStream",
+ "(Lorg/webrtc/MediaStream;)V");
jni()->CallVoidMethod(*j_observer_global_, m, *j_stream);
CHECK_EXCEPTION(jni(), "error during CallVoidMethod");
}
- virtual void OnRemoveStream(MediaStreamInterface* stream) {
+ virtual void OnRemoveStream(MediaStreamInterface* stream) OVERRIDE {
NativeToJavaStreamsMap::iterator it = streams_.find(stream);
CHECK(it != streams_.end(), "unexpected stream: " << std::hex << stream);
@@ -509,12 +559,26 @@ class PCOJava : public PeerConnectionObserver {
if (!s.obj())
return;
- jmethodID m = GetMethodID(jni(),
- j_observer_class_, "onRemoveStream", "(Lorg/webrtc/MediaStream;)V");
+ jmethodID m = GetMethodID(jni(), *j_observer_class_, "onRemoveStream",
+ "(Lorg/webrtc/MediaStream;)V");
jni()->CallVoidMethod(*j_observer_global_, m, s.obj());
CHECK_EXCEPTION(jni(), "error during CallVoidMethod");
}
+ virtual void OnDataChannel(DataChannelInterface* channel) OVERRIDE {
+ ScopedLocalRef<jobject> j_channel(jni(), jni()->NewObject(
+ *j_data_channel_class_, j_data_channel_ctor_, (jlong)channel));
+ CHECK_EXCEPTION(jni(), "error during NewObject");
+ // Channel is now owned by Java object, and will be freed from
+ // DataChannel.dispose().
+ channel->AddRef();
+
+ jmethodID m = GetMethodID(jni(), *j_observer_class_, "onDataChannel",
+ "(Lorg/webrtc/DataChannel;)V");
+ jni()->CallVoidMethod(*j_observer_global_, m, *j_channel);
+ CHECK_EXCEPTION(jni(), "error during CallVoidMethod");
+ }
+
void SetConstraints(ConstraintsWrapper* constraints) {
CHECK(!constraints_.get(), "constraints already set!");
constraints_.reset(constraints);
@@ -527,14 +591,16 @@ class PCOJava : public PeerConnectionObserver {
return AttachCurrentThreadIfNeeded();
}
- const ScopedGlobalRef j_observer_global_;
- const jclass j_observer_class_;
- const jclass j_media_stream_class_;
+ const ScopedGlobalRef<jobject> j_observer_global_;
+ const ScopedGlobalRef<jclass> j_observer_class_;
+ const ScopedGlobalRef<jclass> j_media_stream_class_;
const jmethodID j_media_stream_ctor_;
- const jclass j_audio_track_class_;
+ const ScopedGlobalRef<jclass> j_audio_track_class_;
const jmethodID j_audio_track_ctor_;
- const jclass j_video_track_class_;
+ const ScopedGlobalRef<jclass> j_video_track_class_;
const jmethodID j_video_track_ctor_;
+ const ScopedGlobalRef<jclass> j_data_channel_class_;
+ const jmethodID j_data_channel_ctor_;
typedef std::map<void*, jweak> NativeToJavaStreamsMap;
NativeToJavaStreamsMap streams_; // C++ -> Java streams.
talk_base::scoped_ptr<ConstraintsWrapper> constraints_;
@@ -554,8 +620,13 @@ class ConstraintsWrapper : public MediaConstraintsInterface {
virtual ~ConstraintsWrapper() {}
// MediaConstraintsInterface.
- virtual const Constraints& GetMandatory() const { return mandatory_; }
- virtual const Constraints& GetOptional() const { return optional_; }
+ virtual const Constraints& GetMandatory() const OVERRIDE {
+ return mandatory_;
+ }
+
+ virtual const Constraints& GetOptional() const OVERRIDE {
+ return optional_;
+ }
private:
// Helper for translating a List<Pair<String, String>> to a Constraints.
@@ -630,28 +701,26 @@ class SdpObserverWrapper : public T {
SdpObserverWrapper(JNIEnv* jni, jobject j_observer,
ConstraintsWrapper* constraints)
: constraints_(constraints),
- j_observer_global_(NewGlobalRef(jni, j_observer)),
- j_observer_class_((jclass)NewGlobalRef(
- jni, GetObjectClass(jni, j_observer))) {
+ j_observer_global_(jni, j_observer),
+ j_observer_class_(jni, GetObjectClass(jni, j_observer)) {
}
- virtual ~SdpObserverWrapper() {
- DeleteGlobalRef(jni(), j_observer_global_);
- DeleteGlobalRef(jni(), j_observer_class_);
- }
+ virtual ~SdpObserverWrapper() {}
+ // Can't mark OVERRIDE because of templating.
virtual void OnSuccess() {
- jmethodID m = GetMethodID(jni(), j_observer_class_, "onSetSuccess", "()V");
- jni()->CallVoidMethod(j_observer_global_, m);
+ jmethodID m = GetMethodID(jni(), *j_observer_class_, "onSetSuccess", "()V");
+ jni()->CallVoidMethod(*j_observer_global_, m);
CHECK_EXCEPTION(jni(), "error during CallVoidMethod");
}
+ // Can't mark OVERRIDE because of templating.
virtual void OnSuccess(SessionDescriptionInterface* desc) {
jmethodID m = GetMethodID(
- jni(), j_observer_class_, "onCreateSuccess",
+ jni(), *j_observer_class_, "onCreateSuccess",
"(Lorg/webrtc/SessionDescription;)V");
ScopedLocalRef<jobject> j_sdp(jni(), JavaSdpFromNativeSdp(jni(), desc));
- jni()->CallVoidMethod(j_observer_global_, m, *j_sdp);
+ jni()->CallVoidMethod(*j_observer_global_, m, *j_sdp);
CHECK_EXCEPTION(jni(), "error during CallVoidMethod");
}
@@ -659,11 +728,11 @@ class SdpObserverWrapper : public T {
// Common implementation for failure of Set & Create types, distinguished by
// |op| being "Set" or "Create".
void OnFailure(const std::string& op, const std::string& error) {
- jmethodID m = GetMethodID(jni(),
- j_observer_class_, "on" + op + "Failure", "(Ljava/lang/String;)V");
+ jmethodID m = GetMethodID(jni(), *j_observer_class_, "on" + op + "Failure",
+ "(Ljava/lang/String;)V");
ScopedLocalRef<jstring> j_error_string(
jni(), JavaStringFromStdString(jni(), error));
- jni()->CallVoidMethod(j_observer_global_, m, *j_error_string);
+ jni()->CallVoidMethod(*j_observer_global_, m, *j_error_string);
CHECK_EXCEPTION(jni(), "error during CallVoidMethod");
}
@@ -673,8 +742,8 @@ class SdpObserverWrapper : public T {
}
talk_base::scoped_ptr<ConstraintsWrapper> constraints_;
- const jobject j_observer_global_;
- const jclass j_observer_class_;
+ const ScopedGlobalRef<jobject> j_observer_global_;
+ const ScopedGlobalRef<jclass> j_observer_class_;
};
class CreateSdpObserverWrapper
@@ -684,7 +753,7 @@ class CreateSdpObserverWrapper
ConstraintsWrapper* constraints)
: SdpObserverWrapper(jni, j_observer, constraints) {}
- virtual void OnFailure(const std::string& error) {
+ virtual void OnFailure(const std::string& error) OVERRIDE {
SdpObserverWrapper::OnFailure(std::string("Create"), error);
}
};
@@ -696,42 +765,84 @@ class SetSdpObserverWrapper
ConstraintsWrapper* constraints)
: SdpObserverWrapper(jni, j_observer, constraints) {}
- virtual void OnFailure(const std::string& error) {
+ virtual void OnFailure(const std::string& error) OVERRIDE {
SdpObserverWrapper::OnFailure(std::string("Set"), error);
}
};
+// Adapter for a Java DataChannel$Observer presenting a C++ DataChannelObserver
+// and dispatching the callback from C++ back to Java.
+class DataChannelObserverWrapper : public DataChannelObserver {
+ public:
+ DataChannelObserverWrapper(JNIEnv* jni, jobject j_observer)
+ : j_observer_global_(jni, j_observer),
+ j_observer_class_(jni, GetObjectClass(jni, j_observer)),
+ j_on_state_change_mid_(GetMethodID(jni, *j_observer_class_,
+ "onStateChange", "()V")),
+ j_on_message_mid_(GetMethodID(jni, *j_observer_class_, "onMessage",
+ "(Lorg/webrtc/DataChannel$Buffer;)V")),
+ j_buffer_class_(jni, FindClass(jni, "org/webrtc/DataChannel$Buffer")),
+ j_buffer_ctor_(GetMethodID(jni, *j_buffer_class_,
+ "<init>", "(Ljava/nio/ByteBuffer;Z)V")) {
+ }
+
+ virtual ~DataChannelObserverWrapper() {}
+
+ virtual void OnStateChange() OVERRIDE {
+ jni()->CallVoidMethod(*j_observer_global_, j_on_state_change_mid_);
+ CHECK_EXCEPTION(jni(), "error during CallVoidMethod");
+ }
+
+ virtual void OnMessage(const DataBuffer& buffer) OVERRIDE {
+ jobject byte_buffer =
+ jni()->NewDirectByteBuffer(const_cast<char*>(buffer.data.data()),
+ buffer.data.length());
+ jobject j_buffer = jni()->NewObject(*j_buffer_class_, j_buffer_ctor_,
+ byte_buffer, buffer.binary);
+ jni()->CallVoidMethod(*j_observer_global_, j_on_message_mid_, j_buffer);
+ CHECK_EXCEPTION(jni(), "error during CallVoidMethod");
+ }
+
+ private:
+ JNIEnv* jni() {
+ return AttachCurrentThreadIfNeeded();
+ }
+
+ const ScopedGlobalRef<jobject> j_observer_global_;
+ const ScopedGlobalRef<jclass> j_observer_class_;
+ const ScopedGlobalRef<jclass> j_buffer_class_;
+ const jmethodID j_on_state_change_mid_;
+ const jmethodID j_on_message_mid_;
+ const jmethodID j_buffer_ctor_;
+};
+
// Adapter for a Java StatsObserver presenting a C++ StatsObserver and
// dispatching the callback from C++ back to Java.
class StatsObserverWrapper : public StatsObserver {
public:
StatsObserverWrapper(JNIEnv* jni, jobject j_observer)
- : j_observer_global_(NewGlobalRef(jni, j_observer)),
- j_observer_class_((jclass)NewGlobalRef(
- jni, GetObjectClass(jni, j_observer))),
- j_stats_report_class_(FindClass(jni, "org/webrtc/StatsReport")),
+ : j_observer_global_(jni, j_observer),
+ j_observer_class_(jni, GetObjectClass(jni, j_observer)),
+ j_stats_report_class_(jni, FindClass(jni, "org/webrtc/StatsReport")),
j_stats_report_ctor_(GetMethodID(
- jni, j_stats_report_class_, "<init>",
+ jni, *j_stats_report_class_, "<init>",
"(Ljava/lang/String;Ljava/lang/String;D"
"[Lorg/webrtc/StatsReport$Value;)V")),
- j_value_class_(FindClass(
+ j_value_class_(jni, FindClass(
jni, "org/webrtc/StatsReport$Value")),
j_value_ctor_(GetMethodID(
- jni, j_value_class_, "<init>",
+ jni, *j_value_class_, "<init>",
"(Ljava/lang/String;Ljava/lang/String;)V")) {
}
- virtual ~StatsObserverWrapper() {
- DeleteGlobalRef(jni(), j_observer_global_);
- DeleteGlobalRef(jni(), j_observer_class_);
- }
+ virtual ~StatsObserverWrapper() {}
- virtual void OnComplete(const std::vector<StatsReport>& reports) {
+ virtual void OnComplete(const std::vector<StatsReport>& reports) OVERRIDE {
ScopedLocalRef<jobjectArray> j_reports(jni(),
ReportsToJava(jni(), reports));
- jmethodID m = GetMethodID(
- jni(), j_observer_class_, "onComplete", "([Lorg/webrtc/StatsReport;)V");
- jni()->CallVoidMethod(j_observer_global_, m, *j_reports);
+ jmethodID m = GetMethodID(jni(), *j_observer_class_, "onComplete",
+ "([Lorg/webrtc/StatsReport;)V");
+ jni()->CallVoidMethod(*j_observer_global_, m, *j_reports);
CHECK_EXCEPTION(jni(), "error during CallVoidMethod");
}
@@ -739,7 +850,7 @@ class StatsObserverWrapper : public StatsObserver {
jobjectArray ReportsToJava(
JNIEnv* jni, const std::vector<StatsReport>& reports) {
jobjectArray reports_array = jni->NewObjectArray(
- reports.size(), j_stats_report_class_, NULL);
+ reports.size(), *j_stats_report_class_, NULL);
for (int i = 0; i < reports.size(); ++i) {
const StatsReport& report = reports[i];
ScopedLocalRef<jstring> j_id(
@@ -749,7 +860,7 @@ class StatsObserverWrapper : public StatsObserver {
ScopedLocalRef<jobjectArray> j_values(
jni, ValuesToJava(jni, report.values));
ScopedLocalRef<jobject> j_report(jni, jni->NewObject(
- j_stats_report_class_, j_stats_report_ctor_, *j_id, *j_type,
+ *j_stats_report_class_, j_stats_report_ctor_, *j_id, *j_type,
report.timestamp, *j_values));
jni->SetObjectArrayElement(reports_array, i, *j_report);
}
@@ -758,7 +869,7 @@ class StatsObserverWrapper : public StatsObserver {
jobjectArray ValuesToJava(JNIEnv* jni, const StatsReport::Values& values) {
jobjectArray j_values = jni->NewObjectArray(
- values.size(), j_value_class_, NULL);
+ values.size(), *j_value_class_, NULL);
for (int i = 0; i < values.size(); ++i) {
const StatsReport::Value& value = values[i];
ScopedLocalRef<jstring> j_name(
@@ -766,7 +877,7 @@ class StatsObserverWrapper : public StatsObserver {
ScopedLocalRef<jstring> j_value(
jni, JavaStringFromStdString(jni, value.value));
ScopedLocalRef<jobject> j_element_value(jni, jni->NewObject(
- j_value_class_, j_value_ctor_, *j_name, *j_value));
+ *j_value_class_, j_value_ctor_, *j_name, *j_value));
jni->SetObjectArrayElement(j_values, i, *j_element_value);
}
return j_values;
@@ -776,11 +887,11 @@ class StatsObserverWrapper : public StatsObserver {
return AttachCurrentThreadIfNeeded();
}
- const jobject j_observer_global_;
- const jclass j_observer_class_;
- const jclass j_stats_report_class_;
+ const ScopedGlobalRef<jobject> j_observer_global_;
+ const ScopedGlobalRef<jclass> j_observer_class_;
+ const ScopedGlobalRef<jclass> j_stats_report_class_;
const jmethodID j_stats_report_ctor_;
- const jclass j_value_class_;
+ const ScopedGlobalRef<jclass> j_value_class_;
const jmethodID j_value_ctor_;
};
@@ -796,12 +907,12 @@ class VideoRendererWrapper : public VideoRendererInterface {
virtual ~VideoRendererWrapper() {}
- virtual void SetSize(int width, int height) {
+ virtual void SetSize(int width, int height) OVERRIDE {
const bool kNotReserved = false; // What does this param mean??
renderer_->SetSize(width, height, kNotReserved);
}
- virtual void RenderFrame(const cricket::VideoFrame* frame) {
+ virtual void RenderFrame(const cricket::VideoFrame* frame) OVERRIDE {
renderer_->RenderFrame(frame);
}
@@ -817,25 +928,28 @@ class VideoRendererWrapper : public VideoRendererInterface {
class JavaVideoRendererWrapper : public VideoRendererInterface {
public:
JavaVideoRendererWrapper(JNIEnv* jni, jobject j_callbacks)
- : j_callbacks_(jni, j_callbacks) {
- j_set_size_id_ = GetMethodID(
- jni, GetObjectClass(jni, j_callbacks), "setSize", "(II)V");
- j_render_frame_id_ = GetMethodID(
- jni, GetObjectClass(jni, j_callbacks), "renderFrame",
- "(Lorg/webrtc/VideoRenderer$I420Frame;)V");
- j_frame_class_ = FindClass(jni, "org/webrtc/VideoRenderer$I420Frame");
- j_frame_ctor_id_ = GetMethodID(
- jni, j_frame_class_, "<init>", "(II[I[Ljava/nio/ByteBuffer;)V");
- j_byte_buffer_class_ = FindClass(jni, "java/nio/ByteBuffer");
+ : j_callbacks_(jni, j_callbacks),
+ j_set_size_id_(GetMethodID(
+ jni, GetObjectClass(jni, j_callbacks), "setSize", "(II)V")),
+ j_render_frame_id_(GetMethodID(
+ jni, GetObjectClass(jni, j_callbacks), "renderFrame",
+ "(Lorg/webrtc/VideoRenderer$I420Frame;)V")),
+ j_frame_class_(jni,
+ FindClass(jni, "org/webrtc/VideoRenderer$I420Frame")),
+ j_frame_ctor_id_(GetMethodID(
+ jni, *j_frame_class_, "<init>", "(II[I[Ljava/nio/ByteBuffer;)V")),
+ j_byte_buffer_class_(jni, FindClass(jni, "java/nio/ByteBuffer")) {
CHECK_EXCEPTION(jni, "");
}
- virtual void SetSize(int width, int height) {
+ virtual ~JavaVideoRendererWrapper() {}
+
+ virtual void SetSize(int width, int height) OVERRIDE {
jni()->CallVoidMethod(*j_callbacks_, j_set_size_id_, width, height);
CHECK_EXCEPTION(jni(), "");
}
- virtual void RenderFrame(const cricket::VideoFrame* frame) {
+ virtual void RenderFrame(const cricket::VideoFrame* frame) OVERRIDE {
ScopedLocalRef<jobject> j_frame(jni(), CricketToJavaFrame(frame));
jni()->CallVoidMethod(*j_callbacks_, j_render_frame_id_, *j_frame);
CHECK_EXCEPTION(jni(), "");
@@ -851,7 +965,7 @@ class JavaVideoRendererWrapper : public VideoRendererInterface {
strides_array[2] = frame->GetVPitch();
jni()->ReleaseIntArrayElements(*strides, strides_array, 0);
ScopedLocalRef<jobjectArray> planes(
- jni(), jni()->NewObjectArray(3, j_byte_buffer_class_, NULL));
+ jni(), jni()->NewObjectArray(3, *j_byte_buffer_class_, NULL));
ScopedLocalRef<jobject> y_buffer(jni(), jni()->NewDirectByteBuffer(
const_cast<uint8*>(frame->GetYPlane()),
frame->GetYPitch() * frame->GetHeight()));
@@ -863,7 +977,7 @@ class JavaVideoRendererWrapper : public VideoRendererInterface {
jni()->SetObjectArrayElement(*planes, 1, *u_buffer);
jni()->SetObjectArrayElement(*planes, 2, *v_buffer);
return jni()->NewObject(
- j_frame_class_, j_frame_ctor_id_,
+ *j_frame_class_, j_frame_ctor_id_,
frame->GetWidth(), frame->GetHeight(), *strides, *planes);
}
@@ -871,12 +985,12 @@ class JavaVideoRendererWrapper : public VideoRendererInterface {
return AttachCurrentThreadIfNeeded();
}
- ScopedGlobalRef j_callbacks_;
+ ScopedGlobalRef<jobject> j_callbacks_;
jmethodID j_set_size_id_;
jmethodID j_render_frame_id_;
- jclass j_frame_class_;
+ ScopedGlobalRef<jclass> j_frame_class_;
jmethodID j_frame_ctor_id_;
- jclass j_byte_buffer_class_;
+ ScopedGlobalRef<jclass> j_byte_buffer_class_;
};
} // anonymous namespace
@@ -920,6 +1034,63 @@ extern "C" void JNIEXPORT JNICALL JNI_OnUnLoad(JavaVM *jvm, void *reserved) {
CHECK(talk_base::CleanupSSL(), "Failed to CleanupSSL()");
}
+static talk_base::scoped_refptr<DataChannelInterface> ExtractNativeDC(
+ JNIEnv* jni, jobject j_dc) {
+ jfieldID native_dc_id = GetFieldID(jni,
+ GetObjectClass(jni, j_dc), "nativeDataChannel", "J");
+ jlong j_d = GetLongField(jni, j_dc, native_dc_id);
+ return talk_base::scoped_refptr<DataChannelInterface>(
+ reinterpret_cast<DataChannelInterface*>(j_d));
+}
+
+JOW(jlong, DataChannel_registerObserverNative)(
+ JNIEnv* jni, jobject j_dc, jobject j_observer) {
+ talk_base::scoped_ptr<DataChannelObserverWrapper> observer(
+ new DataChannelObserverWrapper(jni, j_observer));
+ ExtractNativeDC(jni, j_dc)->RegisterObserver(observer.get());
+ return reinterpret_cast<jlong>(observer.release());
+}
+
+JOW(void, DataChannel_unregisterObserverNative)(
+ JNIEnv* jni, jobject j_dc, jlong native_observer) {
+ ExtractNativeDC(jni, j_dc)->UnregisterObserver();
+ delete reinterpret_cast<DataChannelObserverWrapper*>(native_observer);
+}
+
+JOW(jstring, DataChannel_label)(JNIEnv* jni, jobject j_dc) {
+ return JavaStringFromStdString(jni, ExtractNativeDC(jni, j_dc)->label());
+}
+
+JOW(jobject, DataChannel_state)(JNIEnv* jni, jobject j_dc) {
+ return JavaEnumFromIndex(
+ jni, "DataChannel$State", ExtractNativeDC(jni, j_dc)->state());
+}
+
+JOW(jlong, DataChannel_bufferedAmount)(JNIEnv* jni, jobject j_dc) {
+ uint64 buffered_amount = ExtractNativeDC(jni, j_dc)->buffered_amount();
+ CHECK(buffered_amount <= std::numeric_limits<int64>::max(),
+ "buffered_amount overflowed jlong!");
+ return static_cast<jlong>(buffered_amount);
+}
+
+JOW(void, DataChannel_close)(JNIEnv* jni, jobject j_dc) {
+ ExtractNativeDC(jni, j_dc)->Close();
+}
+
+JOW(jboolean, DataChannel_sendNative)(JNIEnv* jni, jobject j_dc,
+ jbyteArray data, jboolean binary) {
+ jbyte* bytes = jni->GetByteArrayElements(data, NULL);
+ bool ret = ExtractNativeDC(jni, j_dc)->Send(DataBuffer(
+ talk_base::Buffer(bytes, jni->GetArrayLength(data)),
+ binary));
+ jni->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
+ return ret;
+}
+
+JOW(void, DataChannel_dispose)(JNIEnv* jni, jobject j_dc) {
+ ExtractNativeDC(jni, j_dc)->Release();
+}
+
JOW(void, PeerConnection_freePeerConnection)(JNIEnv*, jclass, jlong j_p) {
reinterpret_cast<PeerConnectionInterface*>(j_p)->Release();
}
@@ -1134,6 +1305,23 @@ JOW(jobject, PeerConnection_getRemoteDescription)(JNIEnv* jni, jobject j_pc) {
return sdp ? JavaSdpFromNativeSdp(jni, sdp) : NULL;
}
+JOW(jobject, PeerConnection_createDataChannel)(
+ JNIEnv* jni, jobject j_pc, jstring j_label, jobject j_init) {
+ DataChannelInit init = JavaDataChannelInitToNative(jni, j_init);
+ talk_base::scoped_refptr<DataChannelInterface> channel(
+ ExtractNativePC(jni, j_pc)->CreateDataChannel(
+ JavaToStdString(jni, j_label), &init));
+ jclass j_data_channel_class = FindClass(jni, "org/webrtc/DataChannel");
+ jmethodID j_data_channel_ctor = GetMethodID(
+ jni, j_data_channel_class, "<init>", "(J)V");
+ jobject j_channel = jni->NewObject(
+ j_data_channel_class, j_data_channel_ctor, channel.get());
+ CHECK_EXCEPTION(jni, "error during NewObject");
+ // Channel is now owned by Java object, and will be freed from there.
+ channel->AddRef();
+ return j_channel;
+}
+
JOW(void, PeerConnection_createOffer)(
JNIEnv* jni, jobject j_pc, jobject j_observer, jobject j_constraints) {
ConstraintsWrapper* constraints =
diff --git a/app/webrtc/java/src/org/webrtc/DataChannel.java b/app/webrtc/java/src/org/webrtc/DataChannel.java
new file mode 100644
index 0000000..6f8d532
--- /dev/null
+++ b/app/webrtc/java/src/org/webrtc/DataChannel.java
@@ -0,0 +1,282 @@
+/*
+ * 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.
+ */
+
+package org.webrtc;
+
+import java.nio.ByteBuffer;
+
+/** Java wrapper for a C++ DataChannelInterface. */
+public class DataChannel {
+ /** Java wrapper for WebIDL RTCDataChannel. */
+ public static class Init {
+ public boolean ordered = true;
+ // Optional unsigned short in WebIDL, -1 means unspecified.
+ public int maxRetransmitTimeMs = -1;
+ // Optional unsigned short in WebIDL, -1 means unspecified.
+ public int maxRetransmits = -1;
+ public String protocol = "";
+ public boolean negotiated = true;
+ // Optional unsigned short in WebIDL, -1 means unspecified.
+ public int id = -1;
+
+ public Init() {}
+
+ // Called only by native code.
+ private Init(
+ boolean ordered, int maxRetransmitTimeMs, int maxRetransmits,
+ String protocol, boolean negotiated, int id) {
+ this.ordered = ordered;
+ this.maxRetransmitTimeMs = maxRetransmitTimeMs;
+ this.maxRetransmits = maxRetransmits;
+ this.protocol = protocol;
+ this.negotiated = negotiated;
+ this.id = id;
+ }
+ }
+
+ /** Java version of C++ DataBuffer. The atom of data in a DataChannel. */
+ public static class Buffer {
+ /** The underlying data. */
+ public final ByteBuffer data;
+
+ /**
+ * Indicates whether |data| contains UTF-8 text or "binary data"
+ * (i.e. anything else).
+ */
+ public final boolean binary;
+
+ public Buffer(ByteBuffer data, boolean binary) {
+ this.data = data;
+ this.binary = binary;
+ }
+ }
+
+ /** Java version of C++ DataChannelObserver. */
+ public interface Observer {
+ /** The data channel state has changed. */
+ public void onStateChange();
+ /**
+ * A data buffer was successfully received. NOTE: |buffer.data| will be
+ * freed once this function returns so callers who want to use the data
+ * asynchronously must make sure to copy it first.
+ */
+ public void onMessage(Buffer buffer);
+ }
+
+ /** Keep in sync with DataChannelInterface::DataState. */
+ public enum State { CONNECTING, OPEN, CLOSING, CLOSED };
+
+ private final long nativeDataChannel;
+ private long nativeObserver;
+
+ public DataChannel(long nativeDataChannel) {
+ this.nativeDataChannel = nativeDataChannel;
+ }
+
+ /** Register |observer|, replacing any previously-registered observer. */
+ public void registerObserver(Observer observer) {
+ if (nativeObserver != 0) {
+ unregisterObserverNative(nativeObserver);
+ }
+ nativeObserver = registerObserverNative(observer);
+ }
+ private native long registerObserverNative(Observer observer);
+
+ /** Unregister the (only) observer. */
+ public void unregisterObserver() {
+ unregisterObserverNative(nativeObserver);
+ }
+ private native void unregisterObserverNative(long nativeObserver);
+
+ public native String label();
+
+ public native State state();
+
+ /**
+ * Return the number of bytes of application data (UTF-8 text and binary data)
+ * that have been queued using SendBuffer but have not yet been transmitted
+ * to the network.
+ */
+ public native long bufferedAmount();
+
+ /** Close the channel. */
+ public native void close();
+
+ /** Send |data| to the remote peer; return success. */
+ public boolean send(Buffer buffer) {
+ // TODO(fischman): this could be cleverer about avoiding copies if the
+ // ByteBuffer is direct and/or is backed by an array.
+ byte[] data = new byte[buffer.data.remaining()];
+ buffer.data.get(data);
+ return sendNative(data, buffer.binary);
+ }
+ private native boolean sendNative(byte[] data, boolean binary);
+
+ /** Dispose of native resources attached to this channel. */
+ public native void dispose();
+};
+/*
+ * 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.
+ */
+
+package org.webrtc;
+
+import java.nio.ByteBuffer;
+
+/** Java wrapper for a C++ DataChannelInterface. */
+public class DataChannel {
+ /** Java wrapper for WebIDL RTCDataChannel. */
+ public static class Init {
+ public boolean ordered = true;
+ // Optional unsigned short in WebIDL, -1 means unspecified.
+ public int maxRetransmitTimeMs = -1;
+ // Optional unsigned short in WebIDL, -1 means unspecified.
+ public int maxRetransmits = -1;
+ public String protocol = "";
+ public boolean negotiated = true;
+ // Optional unsigned short in WebIDL, -1 means unspecified.
+ public int id = -1;
+
+ public Init() {}
+
+ // Called only by native code.
+ private Init(
+ boolean ordered, int maxRetransmitTimeMs, int maxRetransmits,
+ String protocol, boolean negotiated, int id) {
+ this.ordered = ordered;
+ this.maxRetransmitTimeMs = maxRetransmitTimeMs;
+ this.maxRetransmits = maxRetransmits;
+ this.protocol = protocol;
+ this.negotiated = negotiated;
+ this.id = id;
+ }
+ }
+
+ /** Java version of C++ DataBuffer. The atom of data in a DataChannel. */
+ public static class Buffer {
+ /** The underlying data. */
+ public final ByteBuffer data;
+
+ /**
+ * Indicates whether |data| contains UTF-8 text or "binary data"
+ * (i.e. anything else).
+ */
+ public final boolean binary;
+
+ public Buffer(ByteBuffer data, boolean binary) {
+ this.data = data;
+ this.binary = binary;
+ }
+ }
+
+ /** Java version of C++ DataChannelObserver. */
+ public interface Observer {
+ /** The data channel state has changed. */
+ public void onStateChange();
+ /**
+ * A data buffer was successfully received. NOTE: |buffer.data| will be
+ * freed once this function returns so callers who want to use the data
+ * asynchronously must make sure to copy it first.
+ */
+ public void onMessage(Buffer buffer);
+ }
+
+ /** Keep in sync with DataChannelInterface::DataState. */
+ public enum State { CONNECTING, OPEN, CLOSING, CLOSED };
+
+ private final long nativeDataChannel;
+ private long nativeObserver;
+
+ public DataChannel(long nativeDataChannel) {
+ this.nativeDataChannel = nativeDataChannel;
+ }
+
+ /** Register |observer|, replacing any previously-registered observer. */
+ public void registerObserver(Observer observer) {
+ if (nativeObserver != 0) {
+ unregisterObserverNative(nativeObserver);
+ }
+ nativeObserver = registerObserverNative(observer);
+ }
+ private native long registerObserverNative(Observer observer);
+
+ /** Unregister the (only) observer. */
+ public void unregisterObserver() {
+ unregisterObserverNative(nativeObserver);
+ }
+ private native void unregisterObserverNative(long nativeObserver);
+
+ public native String label();
+
+ public native State state();
+
+ /**
+ * Return the number of bytes of application data (UTF-8 text and binary data)
+ * that have been queued using SendBuffer but have not yet been transmitted
+ * to the network.
+ */
+ public native long bufferedAmount();
+
+ /** Close the channel. */
+ public native void close();
+
+ /** Send |data| to the remote peer; return success. */
+ public boolean send(Buffer buffer) {
+ // TODO(fischman): this could be cleverer about avoiding copies if the
+ // ByteBuffer is direct and/or is backed by an array.
+ byte[] data = new byte[buffer.data.remaining()];
+ buffer.data.get(data);
+ return sendNative(data, buffer.binary);
+ }
+ private native boolean sendNative(byte[] data, boolean binary);
+
+ /** Dispose of native resources attached to this channel. */
+ public native void dispose();
+};
diff --git a/app/webrtc/java/src/org/webrtc/PeerConnection.java b/app/webrtc/java/src/org/webrtc/PeerConnection.java
index 5d08c04..0a0a7f6 100644
--- a/app/webrtc/java/src/org/webrtc/PeerConnection.java
+++ b/app/webrtc/java/src/org/webrtc/PeerConnection.java
@@ -79,6 +79,9 @@ public class PeerConnection {
/** Triggered when a remote peer close a stream. */
public void onRemoveStream(MediaStream stream);
+
+ /** Triggered when a remote peer opens a DataChannel. */
+ public void onDataChannel(DataChannel dataChannel);
}
/** Java version of PeerConnectionInterface.IceServer. */
@@ -118,6 +121,9 @@ public class PeerConnection {
public native SessionDescription getRemoteDescription();
+ public native DataChannel createDataChannel(
+ String label, DataChannel.Init init);
+
public native void createOffer(
SdpObserver observer, MediaConstraints constraints);
diff --git a/app/webrtc/javatests/src/org/webrtc/PeerConnectionTest.java b/app/webrtc/javatests/src/org/webrtc/PeerConnectionTest.java
index cdd8c73..5d14ee5 100644
--- a/app/webrtc/javatests/src/org/webrtc/PeerConnectionTest.java
+++ b/app/webrtc/javatests/src/org/webrtc/PeerConnectionTest.java
@@ -35,9 +35,13 @@ import org.webrtc.PeerConnection.IceGatheringState;
import org.webrtc.PeerConnection.SignalingState;
import java.lang.ref.WeakReference;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.util.Arrays;
import java.util.IdentityHashMap;
import java.util.LinkedList;
import java.util.Map;
+import java.util.TreeSet;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -48,7 +52,9 @@ public class PeerConnectionTest extends TestCase {
private static class ObserverExpectations implements PeerConnection.Observer,
VideoRenderer.Callbacks,
+ DataChannel.Observer,
StatsObserver {
+ private final String name;
private int expectedIceCandidates = 0;
private int expectedErrors = 0;
private LinkedList<Integer> expectedSetSizeDimensions =
@@ -68,10 +74,28 @@ public class PeerConnectionTest extends TestCase {
new LinkedList<IceCandidate>();
private Map<MediaStream, WeakReference<VideoRenderer>> renderers =
new IdentityHashMap<MediaStream, WeakReference<VideoRenderer>>();
+ private DataChannel dataChannel;
+ private LinkedList<DataChannel.Buffer> expectedBuffers =
+ new LinkedList<DataChannel.Buffer>();
+ private LinkedList<DataChannel.State> expectedStateChanges =
+ new LinkedList<DataChannel.State>();
+ private LinkedList<String> expectedRemoteDataChannelLabels =
+ new LinkedList<String>();
private int expectedStatsCallbacks = 0;
private LinkedList<StatsReport[]> gotStatsReports =
new LinkedList<StatsReport[]>();
+ public ObserverExpectations(String name) {
+ this.name = name;
+ }
+
+ public synchronized void setDataChannel(DataChannel dataChannel) {
+ assertNull(this.dataChannel);
+ this.dataChannel = dataChannel;
+ this.dataChannel.registerObserver(this);
+ assertNotNull(this.dataChannel);
+ }
+
public synchronized void expectIceCandidates(int count) {
expectedIceCandidates += count;
}
@@ -93,17 +117,24 @@ public class PeerConnectionTest extends TestCase {
}
public synchronized void expectSetSize(int width, int height) {
+ if (RENDER_TO_GUI) {
+ // When new frames are delivered to the GUI renderer we don't get
+ // notified of frame size info.
+ return;
+ }
expectedSetSizeDimensions.add(width);
expectedSetSizeDimensions.add(height);
}
@Override
public synchronized void setSize(int width, int height) {
+ assertFalse(RENDER_TO_GUI);
assertEquals(width, expectedSetSizeDimensions.removeFirst().intValue());
assertEquals(height, expectedSetSizeDimensions.removeFirst().intValue());
}
public synchronized void expectFramesDelivered(int count) {
+ assertFalse(RENDER_TO_GUI);
expectedFramesDelivered += count;
}
@@ -127,7 +158,8 @@ public class PeerConnectionTest extends TestCase {
}
@Override
- public void onIceConnectionChange(IceConnectionState newState) {
+ public synchronized void onIceConnectionChange(
+ IceConnectionState newState) {
assertEquals(expectedIceConnectionChanges.removeFirst(), newState);
}
@@ -137,7 +169,7 @@ public class PeerConnectionTest extends TestCase {
}
@Override
- public void onIceGatheringChange(IceGatheringState newState) {
+ public synchronized void onIceGatheringChange(IceGatheringState newState) {
// It's fine to get a variable number of GATHERING messages before
// COMPLETE fires (depending on how long the test runs) so we don't assert
// any particular count.
@@ -178,6 +210,40 @@ public class PeerConnectionTest extends TestCase {
stream.videoTracks.get(0).removeRenderer(renderer.get());
}
+ public synchronized void expectDataChannel(String label) {
+ expectedRemoteDataChannelLabels.add(label);
+ }
+
+ @Override
+ public synchronized void onDataChannel(DataChannel remoteDataChannel) {
+ assertEquals(expectedRemoteDataChannelLabels.removeFirst(),
+ remoteDataChannel.label());
+ setDataChannel(remoteDataChannel);
+ assertEquals(DataChannel.State.CONNECTING, dataChannel.state());
+ }
+
+ public synchronized void expectMessage(ByteBuffer expectedBuffer,
+ boolean expectedBinary) {
+ expectedBuffers.add(
+ new DataChannel.Buffer(expectedBuffer, expectedBinary));
+ }
+
+ @Override
+ public synchronized void onMessage(DataChannel.Buffer buffer) {
+ DataChannel.Buffer expected = expectedBuffers.removeFirst();
+ assertEquals(expected.binary, buffer.binary);
+ assertTrue(expected.data.equals(buffer.data));
+ }
+
+ @Override
+ public synchronized void onStateChange() {
+ assertEquals(expectedStateChanges.removeFirst(), dataChannel.state());
+ }
+
+ public synchronized void expectStateChange(DataChannel.State state) {
+ expectedStateChanges.add(state);
+ }
+
@Override
public synchronized void onComplete(StatsReport[] reports) {
if (--expectedStatsCallbacks < 0) {
@@ -196,17 +262,61 @@ public class PeerConnectionTest extends TestCase {
return got;
}
- public synchronized boolean areAllExpectationsSatisfied() {
- return expectedIceCandidates <= 0 && // See comment in onIceCandidate.
- expectedErrors == 0 &&
- expectedSignalingChanges.size() == 0 &&
- expectedIceConnectionChanges.size() == 0 &&
- expectedIceGatheringChanges.size() == 0 &&
- expectedAddStreamLabels.size() == 0 &&
- expectedRemoveStreamLabels.size() == 0 &&
- expectedSetSizeDimensions.isEmpty() &&
- expectedFramesDelivered <= 0 &&
- expectedStatsCallbacks == 0;
+ // Return a set of expectations that haven't been satisfied yet, possibly
+ // empty if no such expectations exist.
+ public synchronized TreeSet<String> unsatisfiedExpectations() {
+ TreeSet<String> stillWaitingForExpectations = new TreeSet<String>();
+ if (expectedIceCandidates > 0) { // See comment in onIceCandidate.
+ stillWaitingForExpectations.add("expectedIceCandidates");
+ }
+ if (expectedErrors != 0) {
+ stillWaitingForExpectations.add("expectedErrors: " + expectedErrors);
+ }
+ if (expectedSignalingChanges.size() != 0) {
+ stillWaitingForExpectations.add(
+ "expectedSignalingChanges: " + expectedSignalingChanges.size());
+ }
+ if (expectedIceConnectionChanges.size() != 0) {
+ stillWaitingForExpectations.add("expectedIceConnectionChanges: " +
+ expectedIceConnectionChanges.size());
+ }
+ if (expectedIceGatheringChanges.size() != 0) {
+ stillWaitingForExpectations.add("expectedIceGatheringChanges: " +
+ expectedIceGatheringChanges.size());
+ }
+ if (expectedAddStreamLabels.size() != 0) {
+ stillWaitingForExpectations.add(
+ "expectedAddStreamLabels: " + expectedAddStreamLabels.size());
+ }
+ if (expectedRemoveStreamLabels.size() != 0) {
+ stillWaitingForExpectations.add(
+ "expectedRemoveStreamLabels: " + expectedRemoveStreamLabels.size());
+ }
+ if (!expectedSetSizeDimensions.isEmpty()) {
+ stillWaitingForExpectations.add(
+ "expectedSetSizeDimensions: " + expectedSetSizeDimensions.size());
+ }
+ if (expectedFramesDelivered > 0) {
+ stillWaitingForExpectations.add(
+ "expectedFramesDelivered: " + expectedFramesDelivered);
+ }
+ if (!expectedBuffers.isEmpty()) {
+ stillWaitingForExpectations.add(
+ "expectedBuffers: " + expectedBuffers.size());
+ }
+ if (!expectedStateChanges.isEmpty()) {
+ stillWaitingForExpectations.add(
+ "expectedStateChanges: " + expectedStateChanges.size());
+ }
+ if (!expectedRemoteDataChannelLabels.isEmpty()) {
+ stillWaitingForExpectations.add("expectedRemoteDataChannelLabels: " +
+ expectedRemoteDataChannelLabels.size());
+ }
+ if (expectedStatsCallbacks != 0) {
+ stillWaitingForExpectations.add(
+ "expectedStatsCallbacks: " + expectedStatsCallbacks);
+ }
+ return stillWaitingForExpectations;
}
public void waitForAllExpectationsToBeSatisfied() {
@@ -219,12 +329,27 @@ public class PeerConnectionTest extends TestCase {
// stall a wait). Use callbacks to fire off dependent steps instead of
// explicitly waiting, so there can be just a single wait at the end of
// the test.
- while (!areAllExpectationsSatisfied()) {
+ TreeSet<String> prev = null;
+ TreeSet<String> stillWaitingForExpectations = unsatisfiedExpectations();
+ while (!stillWaitingForExpectations.isEmpty()) {
+ if (!stillWaitingForExpectations.equals(prev)) {
+ System.out.println(
+ name + " still waiting at\n " +
+ (new Throwable()).getStackTrace()[1] +
+ "\n for: " +
+ Arrays.toString(stillWaitingForExpectations.toArray()));
+ }
try {
Thread.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
+ prev = stillWaitingForExpectations;
+ stillWaitingForExpectations = unsatisfiedExpectations();
+ }
+ if (prev == null) {
+ System.out.println(name + " didn't need to wait at\n " +
+ (new Throwable()).getStackTrace()[1]);
}
}
}
@@ -298,9 +423,9 @@ public class PeerConnectionTest extends TestCase {
}
private static VideoRenderer createVideoRenderer(
- ObserverExpectations observer) {
+ VideoRenderer.Callbacks videoCallbacks) {
if (!RENDER_TO_GUI) {
- return new VideoRenderer(observer);
+ return new VideoRenderer(videoCallbacks);
}
++videoWindowsMapped;
assertTrue(videoWindowsMapped < 4);
@@ -315,12 +440,12 @@ public class PeerConnectionTest extends TestCase {
PeerConnectionFactory factory, PeerConnection pc,
VideoSource videoSource,
String streamLabel, String videoTrackId, String audioTrackId,
- ObserverExpectations observer) {
+ VideoRenderer.Callbacks videoCallbacks) {
MediaStream lMS = factory.createLocalMediaStream(streamLabel);
VideoTrack videoTrack =
factory.createVideoTrack(videoTrackId, videoSource);
assertNotNull(videoTrack);
- VideoRenderer videoRenderer = createVideoRenderer(observer);
+ VideoRenderer videoRenderer = createVideoRenderer(videoCallbacks);
assertNotNull(videoRenderer);
videoTrack.addRenderer(videoRenderer);
lMS.addTrack(videoTrack);
@@ -343,7 +468,15 @@ public class PeerConnectionTest extends TestCase {
CountDownLatch testDone = new CountDownLatch(1);
PeerConnectionFactory factory = new PeerConnectionFactory();
- MediaConstraints constraints = new MediaConstraints();
+ MediaConstraints pcConstraints = new MediaConstraints();
+ pcConstraints.mandatory.add(
+ new MediaConstraints.KeyValuePair("DtlsSrtpKeyAgreement", "true"));
+ pcConstraints.optional.add(
+ new MediaConstraints.KeyValuePair("RtpDataChannels", "true"));
+ // TODO(fischman): replace above with below to test SCTP channels when
+ // supported (https://code.google.com/p/webrtc/issues/detail?id=1408).
+ // pcConstraints.optional.add(new MediaConstraints.KeyValuePair(
+ // "internalSctpDataChannels", "true"));
LinkedList<PeerConnection.IceServer> iceServers =
new LinkedList<PeerConnection.IceServer>();
@@ -351,14 +484,16 @@ public class PeerConnectionTest extends TestCase {
"stun:stun.l.google.com:19302"));
iceServers.add(new PeerConnection.IceServer(
"turn:fake.example.com", "fakeUsername", "fakePassword"));
- ObserverExpectations offeringExpectations = new ObserverExpectations();
+ ObserverExpectations offeringExpectations =
+ new ObserverExpectations("PCTest:offerer");
PeerConnection offeringPC = factory.createPeerConnection(
- iceServers, constraints, offeringExpectations);
+ iceServers, pcConstraints, offeringExpectations);
assertNotNull(offeringPC);
- ObserverExpectations answeringExpectations = new ObserverExpectations();
+ ObserverExpectations answeringExpectations =
+ new ObserverExpectations("PCTest:answerer");
PeerConnection answeringPC = factory.createPeerConnection(
- iceServers, constraints, answeringExpectations);
+ iceServers, pcConstraints, answeringExpectations);
assertNotNull(answeringPC);
// We want to use the same camera for offerer & answerer, so create it here
@@ -371,12 +506,16 @@ public class PeerConnectionTest extends TestCase {
// serialized SDP, because the C++ API doesn't auto-translate.
// Drop |label| params from {Audio,Video}Track-related APIs once
// https://code.google.com/p/webrtc/issues/detail?id=1253 is fixed.
+ offeringExpectations.expectSetSize(640, 480);
WeakReference<MediaStream> oLMS = addTracksToPC(
factory, offeringPC, videoSource, "oLMS", "oLMSv0", "oLMSa0",
offeringExpectations);
+ offeringExpectations.setDataChannel(offeringPC.createDataChannel(
+ "offeringDC", new DataChannel.Init()));
+
SdpObserverLatch sdpLatch = new SdpObserverLatch();
- offeringPC.createOffer(sdpLatch, constraints);
+ offeringPC.createOffer(sdpLatch, new MediaConstraints());
assertTrue(sdpLatch.await());
SessionDescription offerSdp = sdpLatch.getSdp();
assertEquals(offerSdp.type, SessionDescription.Type.OFFER);
@@ -386,19 +525,20 @@ public class PeerConnectionTest extends TestCase {
answeringExpectations.expectSignalingChange(
SignalingState.HAVE_REMOTE_OFFER);
answeringExpectations.expectAddStream("oLMS");
+ answeringExpectations.expectDataChannel("offeringDC");
answeringPC.setRemoteDescription(sdpLatch, offerSdp);
- answeringExpectations.waitForAllExpectationsToBeSatisfied();
assertEquals(
PeerConnection.SignalingState.STABLE, offeringPC.signalingState());
assertTrue(sdpLatch.await());
assertNull(sdpLatch.getSdp());
+ answeringExpectations.expectSetSize(640, 480);
WeakReference<MediaStream> aLMS = addTracksToPC(
factory, answeringPC, videoSource, "aLMS", "aLMSv0", "aLMSa0",
answeringExpectations);
sdpLatch = new SdpObserverLatch();
- answeringPC.createAnswer(sdpLatch, constraints);
+ answeringPC.createAnswer(sdpLatch, new MediaConstraints());
assertTrue(sdpLatch.await());
SessionDescription answerSdp = sdpLatch.getSdp();
assertEquals(answerSdp.type, SessionDescription.Type.ANSWER);
@@ -407,6 +547,9 @@ public class PeerConnectionTest extends TestCase {
offeringExpectations.expectIceCandidates(2);
answeringExpectations.expectIceCandidates(2);
+ offeringExpectations.expectIceGatheringChange(IceGatheringState.COMPLETE);
+ answeringExpectations.expectIceGatheringChange(IceGatheringState.COMPLETE);
+
sdpLatch = new SdpObserverLatch();
answeringExpectations.expectSignalingChange(SignalingState.STABLE);
answeringPC.setLocalDescription(sdpLatch, answerSdp);
@@ -434,14 +577,12 @@ public class PeerConnectionTest extends TestCase {
assertEquals(answeringPC.getRemoteDescription().type, offerSdp.type);
if (!RENDER_TO_GUI) {
- offeringExpectations.expectSetSize(640, 480);
- offeringExpectations.expectSetSize(640, 480);
- answeringExpectations.expectSetSize(640, 480);
- answeringExpectations.expectSetSize(640, 480);
// Wait for at least some frames to be delivered at each end (number
// chosen arbitrarily).
offeringExpectations.expectFramesDelivered(10);
answeringExpectations.expectFramesDelivered(10);
+ offeringExpectations.expectSetSize(640, 480);
+ answeringExpectations.expectSetSize(640, 480);
}
offeringExpectations.expectIceConnectionChange(
@@ -453,8 +594,8 @@ public class PeerConnectionTest extends TestCase {
answeringExpectations.expectIceConnectionChange(
IceConnectionState.CONNECTED);
- offeringExpectations.expectIceGatheringChange(IceGatheringState.COMPLETE);
- answeringExpectations.expectIceGatheringChange(IceGatheringState.COMPLETE);
+ offeringExpectations.expectStateChange(DataChannel.State.OPEN);
+ answeringExpectations.expectStateChange(DataChannel.State.OPEN);
for (IceCandidate candidate : offeringExpectations.gotIceCandidates) {
answeringPC.addIceCandidate(candidate);
@@ -473,6 +614,38 @@ public class PeerConnectionTest extends TestCase {
assertEquals(
PeerConnection.SignalingState.STABLE, answeringPC.signalingState());
+ // Test send & receive UTF-8 text.
+ answeringExpectations.expectMessage(
+ ByteBuffer.wrap("hello!".getBytes(Charset.forName("UTF-8"))), false);
+ DataChannel.Buffer buffer = new DataChannel.Buffer(
+ ByteBuffer.wrap("hello!".getBytes(Charset.forName("UTF-8"))), false);
+ assertTrue(offeringExpectations.dataChannel.send(buffer));
+ answeringExpectations.waitForAllExpectationsToBeSatisfied();
+
+ // TODO(fischman): add testing of binary messages when SCTP channels are
+ // supported (https://code.google.com/p/webrtc/issues/detail?id=1408).
+ // // Construct this binary message two different ways to ensure no
+ // // shortcuts are taken.
+ // ByteBuffer expectedBinaryMessage = ByteBuffer.allocateDirect(5);
+ // for (byte i = 1; i < 6; ++i) {
+ // expectedBinaryMessage.put(i);
+ // }
+ // expectedBinaryMessage.flip();
+ // offeringExpectations.expectMessage(expectedBinaryMessage, true);
+ // assertTrue(answeringExpectations.dataChannel.send(
+ // new DataChannel.Buffer(
+ // ByteBuffer.wrap(new byte[] { 1, 2, 3, 4, 5 } ), true)));
+ // offeringExpectations.waitForAllExpectationsToBeSatisfied();
+
+ offeringExpectations.expectStateChange(DataChannel.State.CLOSING);
+ answeringExpectations.expectStateChange(DataChannel.State.CLOSING);
+ answeringExpectations.dataChannel.close();
+ offeringExpectations.dataChannel.close();
+ // TODO(fischman): implement a new offer/answer exchange to finalize the
+ // closing of the channel in order to see the CLOSED state reached.
+ // offeringExpectations.expectStateChange(DataChannel.State.CLOSED);
+ // answeringExpectations.expectStateChange(DataChannel.State.CLOSED);
+
if (RENDER_TO_GUI) {
try {
Thread.sleep(3000);
@@ -505,6 +678,8 @@ public class PeerConnectionTest extends TestCase {
private static void shutdownPC(
PeerConnection pc, ObserverExpectations expectations) {
+ expectations.dataChannel.unregisterObserver();
+ expectations.dataChannel.dispose();
expectations.expectStatsCallback();
assertTrue(pc.getStats(expectations, null));
expectations.waitForAllExpectationsToBeSatisfied();
diff --git a/app/webrtc/mediastreamsignaling_unittest.cc b/app/webrtc/mediastreamsignaling_unittest.cc
index 7f87454..8b3dacb 100644
--- a/app/webrtc/mediastreamsignaling_unittest.cc
+++ b/app/webrtc/mediastreamsignaling_unittest.cc
@@ -732,8 +732,9 @@ TEST_F(MediaStreamSignalingTest, AddRemoveTrackFromExistingRemoteMediaStream) {
reference_collection_));
// Remove the extra audio and video tracks again.
- CreateSessionDescriptionAndReference(1, 1, desc_ms1.use());
- signaling_->OnRemoteDescriptionChanged(desc_ms1.get());
+ talk_base::scoped_ptr<SessionDescriptionInterface> desc_ms2;
+ CreateSessionDescriptionAndReference(1, 1, desc_ms2.use());
+ signaling_->OnRemoteDescriptionChanged(desc_ms2.get());
EXPECT_TRUE(CompareStreamCollections(signaling_->remote_streams(),
reference_collection_));
EXPECT_TRUE(CompareStreamCollections(observer_->remote_streams(),
diff --git a/app/webrtc/objc/RTCPeerConnectionFactory.mm b/app/webrtc/objc/RTCPeerConnectionFactory.mm
index b12af9d..84e8c5e 100644
--- a/app/webrtc/objc/RTCPeerConnectionFactory.mm
+++ b/app/webrtc/objc/RTCPeerConnectionFactory.mm
@@ -83,9 +83,11 @@
}
webrtc::RTCPeerConnectionObserver *observer =
new webrtc::RTCPeerConnectionObserver(delegate);
+ webrtc::DTLSIdentityServiceInterface* dummy_dtls_identity_service = NULL;
talk_base::scoped_refptr<webrtc::PeerConnectionInterface> peerConnection =
self.nativeFactory->CreatePeerConnection(
- iceServers, constraints.constraints, observer);
+ iceServers, constraints.constraints, dummy_dtls_identity_service,
+ observer);
RTCPeerConnection *pc =
[[RTCPeerConnection alloc] initWithPeerConnection:peerConnection
observer:observer];
diff --git a/app/webrtc/peerconnection_unittest.cc b/app/webrtc/peerconnection_unittest.cc
index 96a9c1c..eed6936 100644
--- a/app/webrtc/peerconnection_unittest.cc
+++ b/app/webrtc/peerconnection_unittest.cc
@@ -884,6 +884,7 @@ class P2PTestConductor : public testing::Test {
if (receiving_client_) {
receiving_client_->set_signaling_message_receiver(NULL);
}
+ talk_base::CleanupSSL();
}
bool CreateTestClients() {
diff --git a/app/webrtc/portallocatorfactory.cc b/app/webrtc/portallocatorfactory.cc
index 59ac9fb..3ded85a 100644
--- a/app/webrtc/portallocatorfactory.cc
+++ b/app/webrtc/portallocatorfactory.cc
@@ -31,7 +31,7 @@
#include "talk/base/network.h"
#include "talk/base/thread.h"
#include "talk/p2p/base/basicpacketsocketfactory.h"
-#include "talk/p2p/client/httpportallocator.h"
+#include "talk/p2p/client/basicportallocator.h"
static const char kUserAgent[] = "PeerConnection User Agent";
diff --git a/app/webrtc/webrtcsession_unittest.cc b/app/webrtc/webrtcsession_unittest.cc
index 55b2950..e56e8a2 100644
--- a/app/webrtc/webrtcsession_unittest.cc
+++ b/app/webrtc/webrtcsession_unittest.cc
@@ -470,8 +470,8 @@ class WebRtcSessionTest : public testing::Test {
desc_factory_->set_secure(cricket::SEC_ENABLED);
std::string identity_name = "WebRTC" +
talk_base::ToString(talk_base::CreateRandomId());
- tdesc_factory_->set_identity(talk_base::SSLIdentity::Generate(
- identity_name));
+ identity_.reset(talk_base::SSLIdentity::Generate(identity_name));
+ tdesc_factory_->set_identity(identity_.get());
tdesc_factory_->set_digest_algorithm(talk_base::DIGEST_SHA_256);
tdesc_factory_->set_secure(cricket::SEC_REQUIRED);
}
@@ -701,8 +701,8 @@ class WebRtcSessionTest : public testing::Test {
// and answer.
SetLocalDescriptionWithoutError(offer);
- SessionDescriptionInterface* answer = CreateRemoteAnswer(
- session_->local_description());
+ talk_base::scoped_ptr<SessionDescriptionInterface> answer(
+ CreateRemoteAnswer(session_->local_description()));
std::string sdp;
EXPECT_TRUE(answer->ToString(&sdp));
@@ -722,11 +722,9 @@ class WebRtcSessionTest : public testing::Test {
SessionDescriptionInterface* new_answer = CreateSessionDescription(
JsepSessionDescription::kAnswer, sdp, NULL);
- delete answer;
- answer = new_answer;
// SetRemoteDescription to enable rtcp mux.
- SetRemoteDescriptionWithoutError(answer);
+ SetRemoteDescriptionWithoutError(new_answer);
EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
EXPECT_EQ(expected_candidate_num, observer_.mline_0_candidates_.size());
EXPECT_EQ(expected_candidate_num, observer_.mline_1_candidates_.size());
@@ -858,6 +856,7 @@ class WebRtcSessionTest : public testing::Test {
cricket::FakeDeviceManager* device_manager_;
talk_base::scoped_ptr<cricket::ChannelManager> channel_manager_;
talk_base::scoped_ptr<cricket::TransportDescriptionFactory> tdesc_factory_;
+ talk_base::scoped_ptr<talk_base::SSLIdentity> identity_;
talk_base::scoped_ptr<cricket::MediaSessionDescriptionFactory> desc_factory_;
talk_base::scoped_ptr<talk_base::PhysicalSocketServer> pss_;
talk_base::scoped_ptr<talk_base::VirtualSocketServer> vss_;
@@ -1877,8 +1876,8 @@ TEST_F(WebRtcSessionTest, VerifyCryptoParamsInSDP) {
session_->CreateOffer(NULL));
VerifyCryptoParams(offer->description());
SetRemoteDescriptionWithoutError(offer.release());
- const webrtc::SessionDescriptionInterface* answer =
- session_->CreateAnswer(NULL);
+ scoped_ptr<SessionDescriptionInterface> answer(
+ session_->CreateAnswer(NULL));
VerifyCryptoParams(answer->description());
}
@@ -2101,7 +2100,8 @@ TEST_F(WebRtcSessionTest, TestInitiatorGIceInAnswer) {
Init();
mediastream_signaling_.SendAudioVideoStream1();
SessionDescriptionInterface* offer = session_->CreateOffer(NULL);
- SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
+ talk_base::scoped_ptr<SessionDescriptionInterface> answer(
+ CreateRemoteAnswer(offer));
SetLocalDescriptionWithoutError(offer);
std::string sdp;
EXPECT_TRUE(answer->ToString(&sdp));
@@ -2137,7 +2137,8 @@ TEST_F(WebRtcSessionTest, TestReceiverGIceInOffer) {
mediastream_signaling_.SendAudioVideoStream1();
SessionDescriptionInterface* offer = session_->CreateOffer(NULL);
SetRemoteDescriptionWithoutError(offer);
- SessionDescriptionInterface* answer = session_->CreateAnswer(NULL);
+ talk_base::scoped_ptr<SessionDescriptionInterface> answer(
+ session_->CreateAnswer(NULL));
std::string sdp;
EXPECT_TRUE(answer->ToString(&sdp));
// Adding ice-options to the session level.
@@ -2185,15 +2186,16 @@ TEST_F(WebRtcSessionTest, TestIceOfferGIceOnlyAnswer) {
SetLocalDescriptionWithoutError(ice_only_offer);
std::string original_offer_sdp;
EXPECT_TRUE(offer->ToString(&original_offer_sdp));
- SessionDescriptionInterface* pranswer_with_gice =
+ talk_base::scoped_ptr<SessionDescriptionInterface> pranswer_with_gice(
CreateSessionDescription(JsepSessionDescription::kPrAnswer,
- original_offer_sdp, NULL);
+ original_offer_sdp, NULL));
SetRemoteDescriptionExpectError(kPushDownPranswerTDFailed,
- pranswer_with_gice);
- SessionDescriptionInterface* answer_with_gice =
+ pranswer_with_gice.get());
+ talk_base::scoped_ptr<SessionDescriptionInterface> answer_with_gice(
CreateSessionDescription(JsepSessionDescription::kAnswer,
- original_offer_sdp, NULL);
- SetRemoteDescriptionExpectError(kPushDownAnswerTDFailed, answer_with_gice);
+ original_offer_sdp, NULL));
+ SetRemoteDescriptionExpectError(kPushDownAnswerTDFailed,
+ answer_with_gice.get());
}
// Verifing local offer and remote answer have matching m-lines as per RFC 3264.
@@ -2207,13 +2209,13 @@ TEST_F(WebRtcSessionTest, TestIncorrectMLinesInRemoteAnswer) {
cricket::SessionDescription* answer_copy = answer->description()->Copy();
answer_copy->RemoveContentByName("video");
- JsepSessionDescription* modified_answer =
- new JsepSessionDescription(JsepSessionDescription::kAnswer);
+ talk_base::scoped_ptr<JsepSessionDescription> modified_answer(
+ new JsepSessionDescription(JsepSessionDescription::kAnswer));
EXPECT_TRUE(modified_answer->Initialize(answer_copy,
answer->session_id(),
answer->session_version()));
- SetRemoteDescriptionExpectError(kMlineMismatch, modified_answer);
+ SetRemoteDescriptionExpectError(kMlineMismatch, modified_answer.get());
// Modifying content names.
std::string sdp;
@@ -2227,9 +2229,9 @@ TEST_F(WebRtcSessionTest, TestIncorrectMLinesInRemoteAnswer) {
kAudioMidReplaceStr.length(),
&sdp);
- SessionDescriptionInterface* modified_answer1 =
- CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
- SetRemoteDescriptionExpectError(kMlineMismatch, modified_answer1);
+ talk_base::scoped_ptr<SessionDescriptionInterface> modified_answer1(
+ CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL));
+ SetRemoteDescriptionExpectError(kMlineMismatch, modified_answer1.get());
SetRemoteDescriptionWithoutError(answer.release());
}
@@ -2388,9 +2390,9 @@ TEST_F(WebRtcSessionTest, TestSessionContentError) {
video_channel_->set_fail_set_send_codecs(true);
mediastream_signaling_.SendAudioVideoStream2();
- SessionDescriptionInterface* answer =
- CreateRemoteAnswer(session_->local_description());
- SetRemoteDescriptionExpectError("ERROR_CONTENT", answer);
+ talk_base::scoped_ptr<SessionDescriptionInterface> answer(
+ CreateRemoteAnswer(session_->local_description()));
+ SetRemoteDescriptionExpectError("ERROR_CONTENT", answer.get());
}
// Runs the loopback call test with BUNDLE and STUN disabled.
diff --git a/base/httpbase_unittest.cc b/base/httpbase_unittest.cc
index 73ef949..bd1796d 100644
--- a/base/httpbase_unittest.cc
+++ b/base/httpbase_unittest.cc
@@ -73,6 +73,7 @@ public:
virtual void SetUp() { }
virtual void TearDown() {
+ delete http_stream;
// Avoid an ASSERT, in case a test doesn't clean up properly
base.abort(HE_NONE);
}
diff --git a/base/multipart_unittest.cc b/base/multipart_unittest.cc
index 18e3cf9..7266ed5 100644
--- a/base/multipart_unittest.cc
+++ b/base/multipart_unittest.cc
@@ -78,8 +78,8 @@ TEST(MultipartTest, TestAddAndRead) {
EXPECT_TRUE(multipart.GetSize(&size));
EXPECT_EQ(part_size, size);
- talk_base::MemoryStream* stream =
- new talk_base::MemoryStream(kTestStreamContent);
+ talk_base::scoped_ptr<talk_base::MemoryStream> stream(
+ new talk_base::MemoryStream(kTestStreamContent));
size_t stream_size = 0;
EXPECT_TRUE(stream->GetSize(&stream_size));
part_size +=
diff --git a/base/nat_unittest.cc b/base/nat_unittest.cc
index 03b1cd1..03170ca 100644
--- a/base/nat_unittest.cc
+++ b/base/nat_unittest.cc
@@ -247,11 +247,11 @@ void TestPhysicalInternal(const SocketAddress& int_addr) {
SocketAddress(ext_addr2)
};
- PhysicalSocketServer* int_pss = new PhysicalSocketServer();
- PhysicalSocketServer* ext_pss = new PhysicalSocketServer();
+ scoped_ptr<PhysicalSocketServer> int_pss(new PhysicalSocketServer());
+ scoped_ptr<PhysicalSocketServer> ext_pss(new PhysicalSocketServer());
- TestBindings(int_pss, int_addr, ext_pss, ext_addrs);
- TestFilters(int_pss, int_addr, ext_pss, ext_addrs);
+ TestBindings(int_pss.get(), int_addr, ext_pss.get(), ext_addrs);
+ TestFilters(int_pss.get(), int_addr, ext_pss.get(), ext_addrs);
}
TEST(NatTest, TestPhysicalIPv4) {
@@ -269,16 +269,20 @@ TEST(NatTest, TestPhysicalIPv6) {
class TestVirtualSocketServer : public VirtualSocketServer {
public:
explicit TestVirtualSocketServer(SocketServer* ss)
- : VirtualSocketServer(ss) {}
+ : VirtualSocketServer(ss),
+ ss_(ss) {}
// Expose this publicly
IPAddress GetNextIP(int af) { return VirtualSocketServer::GetNextIP(af); }
+
+ private:
+ scoped_ptr<SocketServer> ss_;
};
void TestVirtualInternal(int family) {
- TestVirtualSocketServer* int_vss = new TestVirtualSocketServer(
- new PhysicalSocketServer());
- TestVirtualSocketServer* ext_vss = new TestVirtualSocketServer(
- new PhysicalSocketServer());
+ scoped_ptr<TestVirtualSocketServer> int_vss(new TestVirtualSocketServer(
+ new PhysicalSocketServer()));
+ scoped_ptr<TestVirtualSocketServer> ext_vss(new TestVirtualSocketServer(
+ new PhysicalSocketServer()));
SocketAddress int_addr;
SocketAddress ext_addrs[4];
@@ -288,8 +292,8 @@ void TestVirtualInternal(int family) {
ext_addrs[2].SetIP(ext_addrs[0].ipaddr());
ext_addrs[3].SetIP(ext_addrs[1].ipaddr());
- TestBindings(int_vss, int_addr, ext_vss, ext_addrs);
- TestFilters(int_vss, int_addr, ext_vss, ext_addrs);
+ TestBindings(int_vss.get(), int_addr, ext_vss.get(), ext_addrs);
+ TestFilters(int_vss.get(), int_addr, ext_vss.get(), ext_addrs);
}
TEST(NatTest, TestVirtualIPv4) {
diff --git a/base/network.cc b/base/network.cc
index b32bb09..9351b87 100644
--- a/base/network.cc
+++ b/base/network.cc
@@ -498,6 +498,11 @@ void BasicNetworkManager::DumpNetworks(bool include_ignored) {
<< ((network->ignored()) ? ", Ignored" : "");
}
}
+ // Release the network list created previously.
+ // Do this in a seperated for loop for better readability.
+ for (size_t i = 0; i < list.size(); ++i) {
+ delete list[i];
+ }
}
Network::Network(const std::string& name, const std::string& desc,
diff --git a/base/network_unittest.cc b/base/network_unittest.cc
index 146b785..ee0f0aa 100644
--- a/base/network_unittest.cc
+++ b/base/network_unittest.cc
@@ -128,6 +128,7 @@ TEST_F(NetworkTest, TestCreateNetworks) {
close(fd);
#endif
}
+ delete (*it);
}
}
@@ -480,6 +481,10 @@ TEST_F(NetworkTest, TestIPv6Toggle) {
}
}
EXPECT_TRUE(ipv6_found);
+ for (NetworkManager::NetworkList::iterator it = list.begin();
+ it != list.end(); ++it) {
+ delete (*it);
+ }
#endif
ipv6_found = false;
manager.set_ipv6_enabled(false);
@@ -492,6 +497,10 @@ TEST_F(NetworkTest, TestIPv6Toggle) {
}
}
EXPECT_FALSE(ipv6_found);
+ for (NetworkManager::NetworkList::iterator it = list.begin();
+ it != list.end(); ++it) {
+ delete (*it);
+ }
}
#if defined(POSIX)
diff --git a/base/physicalsocketserver_unittest.cc b/base/physicalsocketserver_unittest.cc
index b7f6848..329cf5d 100644
--- a/base/physicalsocketserver_unittest.cc
+++ b/base/physicalsocketserver_unittest.cc
@@ -287,7 +287,8 @@ TEST_F(PosixSignalDeliveryTest, SignalOnDifferentThread) {
// thread. Our implementation should safely handle it and dispatch
// RecordSignal() on this thread.
scoped_ptr<Thread> thread(new Thread());
- thread->Start(new RaiseSigTermRunnable());
+ scoped_ptr<RaiseSigTermRunnable> runnable(new RaiseSigTermRunnable());
+ thread->Start(runnable.get());
EXPECT_TRUE(ss_->Wait(1500, true));
EXPECT_TRUE(ExpectSignal(SIGTERM));
EXPECT_EQ(Thread::Current(), signaled_thread_);
diff --git a/base/proxydetect.cc b/base/proxydetect.cc
index d3c9983..7292f3b 100644
--- a/base/proxydetect.cc
+++ b/base/proxydetect.cc
@@ -445,7 +445,7 @@ bool GetDefaultFirefoxProfile(Pathname* profile_path) {
// Note: we are looking for the first entry with "Default=1", or the last
// entry in the file
path.SetFilename("profiles.ini");
- FileStream* fs = Filesystem::OpenFile(path, "r");
+ scoped_ptr<FileStream> fs(Filesystem::OpenFile(path, "r"));
if (!fs) {
return false;
}
@@ -510,7 +510,7 @@ bool GetDefaultFirefoxProfile(Pathname* profile_path) {
bool ReadFirefoxPrefs(const Pathname& filename,
const char * prefix,
StringMap* settings) {
- FileStream* fs = Filesystem::OpenFile(filename, "r");
+ scoped_ptr<FileStream> fs(Filesystem::OpenFile(filename, "r"));
if (!fs) {
LOG(LS_ERROR) << "Failed to open file: " << filename.pathname();
return false;
diff --git a/base/signalthread_unittest.cc b/base/signalthread_unittest.cc
index 4ad5961..4458f52 100644
--- a/base/signalthread_unittest.cc
+++ b/base/signalthread_unittest.cc
@@ -127,6 +127,8 @@ class OwnerThread : public Thread, public sigslot::has_slots<> {
signal_thread->Start();
Thread::Current()->socketserver()->Wait(100, false);
signal_thread->Release();
+ // Delete |signal_thread|.
+ signal_thread->Destroy(true);
has_run_ = true;
}
diff --git a/base/socket_unittest.cc b/base/socket_unittest.cc
index dd4b1e5..ad06c1e 100644
--- a/base/socket_unittest.cc
+++ b/base/socket_unittest.cc
@@ -926,6 +926,8 @@ void SocketTest::UdpReadyToSend(const IPAddress& loopback) {
new TestClient(AsyncUDPSocket::Create(ss_, empty)));
int test_packet_size = 1200;
talk_base::scoped_array<char> test_packet(new char[test_packet_size]);
+ // Init the test packet just to avoid memcheck warning.
+ memset(test_packet.get(), 0, test_packet_size);
// Set the send buffer size to the same size as the test packet to have a
// better chance to get EWOULDBLOCK.
int send_buffer_size = test_packet_size;
diff --git a/build/common.gypi b/build/common.gypi
index 28481eb..7775e24 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -102,6 +102,11 @@
'use_nss%': 1,
},
}],
+ ['libjingle_objc==1', {
+ 'defines': [
+ 'CARBON_DEPRECATED=YES',
+ ],
+ }],
['os_posix==1', {
'defines': [
'HASH_NAMESPACE=__gnu_cxx',
diff --git a/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java b/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java
index bd17323..d8bc257 100644
--- a/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java
+++ b/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java
@@ -42,6 +42,7 @@ import android.widget.Toast;
import org.json.JSONException;
import org.json.JSONObject;
+import org.webrtc.DataChannel;
import org.webrtc.IceCandidate;
import org.webrtc.MediaConstraints;
import org.webrtc.MediaStream;
@@ -333,6 +334,16 @@ public class AppRTCDemoActivity extends Activity
}
});
}
+
+ @Override public void onDataChannel(final DataChannel dc) {
+ runOnUiThread(new Runnable() {
+ public void run() {
+ throw new RuntimeException(
+ "AppRTC doesn't use data channels, but got: " + dc.label() +
+ " anyway!");
+ }
+ });
+ }
}
// Implementation detail: handle offer creation/signaling and answer setting,
diff --git a/libjingle.gyp b/libjingle.gyp
index 39ab843..b1d7131 100755
--- a/libjingle.gyp
+++ b/libjingle.gyp
@@ -84,6 +84,7 @@
'peerconnection_java_files': [
'app/webrtc/java/src/org/webrtc/AudioSource.java',
'app/webrtc/java/src/org/webrtc/AudioTrack.java',
+ 'app/webrtc/java/src/org/webrtc/DataChannel.java',
'app/webrtc/java/src/org/webrtc/IceCandidate.java',
'app/webrtc/java/src/org/webrtc/MediaConstraints.java',
'app/webrtc/java/src/org/webrtc/MediaSource.java',
@@ -590,15 +591,7 @@
}],
['OS=="mac"', {
'conditions': [
- [ 'libjingle_objc != 1', {
- 'sources': [
- 'base/macasyncsocket.cc',
- 'base/macasyncsocket.h',
- 'base/maccocoasocketserver.h',
- 'base/maccocoasocketserver.mm',
- 'base/macsocketserver.cc',
- 'base/macsocketserver.h',
- ],
+ ['libjingle_objc != 1', {
'link_settings' :{
'xcode_settings': {
'OTHER_LDFLAGS': [
@@ -606,15 +599,17 @@
],
},
},
- }, {
- 'defines': [
- 'CARBON_DEPRECATED=YES',
- ],
}],
],
'sources': [
+ 'base/macasyncsocket.cc',
+ 'base/macasyncsocket.h',
+ 'base/maccocoasocketserver.h',
+ 'base/maccocoasocketserver.mm',
'base/macconversion.cc',
'base/macconversion.h',
+ 'base/macsocketserver.cc',
+ 'base/macsocketserver.h',
'base/macutils.cc',
'base/macutils.h',
'base/macwindowpicker.cc',
@@ -967,11 +962,11 @@
'libjingle_media',
],
'include_dirs': [
- '<(DEPTH)/third_party/gtest/include',
+ '<(DEPTH)/testing/gtest/include',
],
'direct_dependent_settings': {
'include_dirs': [
- '<(DEPTH)/third_party/gtest/include',
+ '<(DEPTH)/testing/gtest/include',
],
},
'defines': [
diff --git a/libjingle_examples.gyp b/libjingle_examples.gyp
index 3a33740..192ba03 100755
--- a/libjingle_examples.gyp
+++ b/libjingle_examples.gyp
@@ -233,6 +233,7 @@
# (http://crbug.com/225101)
'action_name': 'build_apprtcdemo_apk',
'inputs' : [
+ '<(PRODUCT_DIR)/libjingle_peerconnection.jar',
'<(PRODUCT_DIR)/libjingle_peerconnection_so.so',
'examples/android/AndroidManifest.xml',
'examples/android/README',
@@ -256,7 +257,7 @@
],
'action': [
'bash', '-ec',
- 'rm -f <(_outputs) && '
+ 'rm -fr <(_outputs) examples/android/{bin,libs} && '
'mkdir -p examples/android/libs/<(android_app_abi) && '
'cp <(PRODUCT_DIR)/libjingle_peerconnection.jar examples/android/libs/ &&'
'<(android_strip) -o examples/android/libs/<(android_app_abi)/libjingle_peerconnection_so.so <(PRODUCT_DIR)/libjingle_peerconnection_so.so &&'
diff --git a/libjingle_tests.gyp b/libjingle_tests.gyp
index 72184ec..5a2f3a9 100755
--- a/libjingle_tests.gyp
+++ b/libjingle_tests.gyp
@@ -33,15 +33,15 @@
'target_name': 'gunit',
'type': 'static_library',
'sources': [
- '<(DEPTH)/third_party/gtest/src/gtest-all.cc',
+ '<(DEPTH)/testing/gtest/src/gtest-all.cc',
],
'include_dirs': [
- '<(DEPTH)/third_party/gtest/include',
- '<(DEPTH)/third_party/gtest',
+ '<(DEPTH)/testing/gtest/include',
+ '<(DEPTH)/testing/gtest',
],
'direct_dependent_settings': {
'include_dirs': [
- '<(DEPTH)/third_party/gtest/include',
+ '<(DEPTH)/testing/gtest/include',
],
},
'conditions': [
diff --git a/media/webrtc/fakewebrtcvideoengine.h b/media/webrtc/fakewebrtcvideoengine.h
index 5b7b6cb..886f403 100644
--- a/media/webrtc/fakewebrtcvideoengine.h
+++ b/media/webrtc/fakewebrtcvideoengine.h
@@ -708,10 +708,6 @@ class FakeWebRtcVideoEngine
WEBRTC_STUB(DeregisterDecoderObserver, (const int));
WEBRTC_STUB(SendKeyFrame, (const int));
WEBRTC_STUB(WaitForFirstKeyFrame, (const int, const bool));
-#ifdef USE_WEBRTC_DEV_BRANCH
- WEBRTC_STUB(StartDebugRecording, (int, const char*));
- WEBRTC_STUB(StopDebugRecording, (int));
-#endif
// webrtc::ViECapture
WEBRTC_STUB(NumberOfCaptureDevices, ());
@@ -783,10 +779,12 @@ class FakeWebRtcVideoEngine
// Not using WEBRTC_STUB due to bool return value
virtual bool IsIPv6Enabled(int channel) { return true; }
WEBRTC_STUB(SetMTU, (int, unsigned int));
+#ifndef USE_WEBRTC_DEV_BRANCH
WEBRTC_STUB(SetPacketTimeoutNotification, (const int, bool, int));
WEBRTC_STUB(RegisterObserver, (const int, webrtc::ViENetworkObserver&));
WEBRTC_STUB(SetPeriodicDeadOrAliveStatus, (const int, const bool,
const unsigned int));
+#endif
// webrtc::ViERender
WEBRTC_STUB(RegisterVideoRenderModule, (webrtc::VideoRender&));
diff --git a/media/webrtc/fakewebrtcvoiceengine.h b/media/webrtc/fakewebrtcvoiceengine.h
index 7202e15..65139aa 100644
--- a/media/webrtc/fakewebrtcvoiceengine.h
+++ b/media/webrtc/fakewebrtcvoiceengine.h
@@ -609,6 +609,7 @@ class FakeWebRtcVoiceEngine
}
WEBRTC_STUB(ReceivedRTCPPacket, (int channel, const void* data,
unsigned int length));
+#ifndef USE_WEBRTC_DEV_BRANCH
// Not using WEBRTC_STUB due to bool return value
WEBRTC_STUB(SetPacketTimeoutNotification, (int channel, bool enable,
int timeoutSeconds));
@@ -621,6 +622,7 @@ class FakeWebRtcVoiceEngine
int& sampleTimeSeconds));
WEBRTC_STUB(SetPeriodicDeadOrAliveStatus, (int channel, bool enable,
int sampleTimeSeconds));
+#endif
// webrtc::VoERTP_RTCP
WEBRTC_STUB(RegisterRTPObserver, (int channel,
@@ -741,7 +743,11 @@ class FakeWebRtcVoiceEngine
// webrtc::VoEVideoSync
WEBRTC_STUB(GetPlayoutBufferSize, (int& bufferMs));
WEBRTC_STUB(GetPlayoutTimestamp, (int channel, unsigned int& timestamp));
+#ifdef USE_WEBRTC_DEV_BRANCH
+ WEBRTC_STUB(GetRtpRtcp, (int, webrtc::RtpRtcp**, webrtc::RtpReceiver**));
+#else
WEBRTC_STUB(GetRtpRtcp, (int, webrtc::RtpRtcp*&));
+#endif
WEBRTC_STUB(SetInitTimestamp, (int channel, unsigned int timestamp));
WEBRTC_STUB(SetInitSequenceNumber, (int channel, short sequenceNumber));
WEBRTC_STUB(SetMinimumPlayoutDelay, (int channel, int delayMs));
diff --git a/session/media/channelmanager.cc b/session/media/channelmanager.cc
index 529ceea..063a6c8 100644
--- a/session/media/channelmanager.cc
+++ b/session/media/channelmanager.cc
@@ -43,6 +43,7 @@
#include "talk/media/base/hybriddataengine.h"
#include "talk/media/base/rtpdataengine.h"
#include "talk/media/base/videocapturer.h"
+#include "talk/media/devices/devicemanager.h"
#ifdef HAVE_SCTP
#include "talk/media/sctp/sctpdataengine.h"
#endif
@@ -595,6 +596,14 @@ bool ChannelManager::IsSameCapturer(const std::string& capturer_name,
return capturer->GetId() == device.id;
}
+bool ChannelManager::GetVideoCaptureDevice(Device* device) {
+ std::string device_name;
+ if (!GetCaptureDevice(&device_name)) {
+ return false;
+ }
+ return device_manager_->GetVideoCaptureDevice(device_name, device);
+}
+
bool ChannelManager::GetCaptureDevice(std::string* cam_name) {
if (camera_device_.empty()) {
// Initialize camera_device_ with default.
diff --git a/session/media/channelmanager.h b/session/media/channelmanager.h
index 0c57737..6d53c63 100644
--- a/session/media/channelmanager.h
+++ b/session/media/channelmanager.h
@@ -144,7 +144,12 @@ class ChannelManager : public talk_base::MessageHandler,
bool SetOutputVolume(int level);
bool IsSameCapturer(const std::string& capturer_name,
VideoCapturer* capturer);
+ // TODO(noahric): Nearly everything called "device" in this API is actually a
+ // device name, so this should really be GetCaptureDeviceName, and the
+ // next method should be GetCaptureDevice.
bool GetCaptureDevice(std::string* cam_device);
+ // Gets the current capture Device.
+ bool GetVideoCaptureDevice(Device* device);
// Create capturer based on what has been set in SetCaptureDevice().
VideoCapturer* CreateVideoCapturer();
bool SetCaptureDevice(const std::string& cam_device);