diff --git a/webrtc/sdk/android/BUILD.gn b/webrtc/sdk/android/BUILD.gn index 710d962125..7030824965 100644 --- a/webrtc/sdk/android/BUILD.gn +++ b/webrtc/sdk/android/BUILD.gn @@ -140,6 +140,7 @@ android_library("libjingle_peerconnection_java") { "api/org/webrtc/CameraSession.java", "api/org/webrtc/CameraVideoCapturer.java", "api/org/webrtc/DataChannel.java", + "api/org/webrtc/DtmfSender.java", "api/org/webrtc/EglBase.java", "api/org/webrtc/EglBase10.java", "api/org/webrtc/EglBase14.java", diff --git a/webrtc/sdk/android/api/org/webrtc/DtmfSender.java b/webrtc/sdk/android/api/org/webrtc/DtmfSender.java new file mode 100644 index 0000000000..20fdd2c1ff --- /dev/null +++ b/webrtc/sdk/android/api/org/webrtc/DtmfSender.java @@ -0,0 +1,84 @@ +/* + * Copyright 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +package org.webrtc; + +/** Java wrapper for a C++ DtmfSenderInterface. */ +public class DtmfSender { + final long nativeDtmfSender; + + public DtmfSender(long nativeDtmfSender) { + this.nativeDtmfSender = nativeDtmfSender; + } + + /** + * @return true if this DtmfSender is capable of sending DTMF. Otherwise false. + */ + public boolean canInsertDtmf() { + return nativeCanInsertDtmf(nativeDtmfSender); + } + + /** + * Queues a task that sends the provided DTMF tones. + *
+ * If insertDtmf is called on the same object while an existing task for this
+ * object to generate DTMF is still running, the previous task is canceled.
+ *
+ * @param tones This parameter is treated as a series of characters. The characters 0
+ * through 9, A through D, #, and * generate the associated DTMF tones. The
+ * characters a to d are equivalent to A to D. The character ',' indicates a
+ * delay of 2 seconds before processing the next character in the tones
+ * parameter. Unrecognized characters are ignored.
+ * @param duration Indicates the duration in ms to use for each character passed in the tones
+ * parameter. The duration cannot be more than 6000 or less than 70.
+ * @param interToneGap Indicates the gap between tones in ms. Must be at least 50 ms but should be
+ * as short as possible.
+ * @return true on success and false on failure.
+ */
+ public boolean insertDtmf(String tones, int duration, int interToneGap) {
+ return nativeInsertDtmf(nativeDtmfSender, tones, duration, interToneGap);
+ }
+
+ /**
+ * @return The tones remaining to be played out
+ */
+ public String tones() {
+ return nativeTones(nativeDtmfSender);
+ }
+
+ /**
+ * @return The current tone duration value in ms. This value will be the value last set via the
+ * insertDtmf() method, or the default value of 100 ms if insertDtmf() was never called.
+ */
+ public int duration() {
+ return nativeDuration(nativeDtmfSender);
+ }
+
+ /**
+ * @return The current value of the between-tone gap in ms. This value will be the value last set
+ * via the insertDtmf() method, or the default value of 50 ms if insertDtmf() was never
+ * called.
+ */
+ public int interToneGap() {
+ return nativeInterToneGap(nativeDtmfSender);
+ }
+
+ public void dispose() {
+ free(nativeDtmfSender);
+ }
+
+ private static native boolean nativeCanInsertDtmf(long nativeDtmfSender);
+ private static native boolean nativeInsertDtmf(
+ long nativeDtmfSender, String tones, int duration, int interToneGap);
+ private static native String nativeTones(long nativeDtmfSender);
+ private static native int nativeDuration(long nativeDtmfSender);
+ private static native int nativeInterToneGap(long nativeDtmfSender);
+ private static native void free(long nativeDtmfSender);
+};
diff --git a/webrtc/sdk/android/api/org/webrtc/RtpSender.java b/webrtc/sdk/android/api/org/webrtc/RtpSender.java
index 12df4e2714..358b87dff8 100644
--- a/webrtc/sdk/android/api/org/webrtc/RtpSender.java
+++ b/webrtc/sdk/android/api/org/webrtc/RtpSender.java
@@ -17,11 +17,16 @@ public class RtpSender {
private MediaStreamTrack cachedTrack;
private boolean ownsTrack = true;
+ private final DtmfSender dtmfSender;
+
public RtpSender(long nativeRtpSender) {
this.nativeRtpSender = nativeRtpSender;
long track = nativeGetTrack(nativeRtpSender);
// It may be possible for an RtpSender to be created without a track.
- cachedTrack = (track == 0) ? null : new MediaStreamTrack(track);
+ cachedTrack = (track != 0) ? new MediaStreamTrack(track) : null;
+
+ long nativeDtmfSender = nativeGetDtmfSender(nativeRtpSender);
+ dtmfSender = (nativeDtmfSender != 0) ? new DtmfSender(nativeDtmfSender) : null;
}
// If |takeOwnership| is true, the RtpSender takes ownership of the track
@@ -57,7 +62,14 @@ public class RtpSender {
return nativeId(nativeRtpSender);
}
+ public DtmfSender dtmf() {
+ return dtmfSender;
+ }
+
public void dispose() {
+ if (dtmfSender != null) {
+ dtmfSender.dispose();
+ }
if (cachedTrack != null && ownsTrack) {
cachedTrack.dispose();
}
@@ -70,6 +82,10 @@ public class RtpSender {
// Will be released in dispose() or setTrack().
private static native long nativeGetTrack(long nativeRtpSender);
+ // This should increment the reference count of the DTMF sender.
+ // Will be released in dispose().
+ private static native long nativeGetDtmfSender(long nativeRtpSender);
+
private static native boolean nativeSetParameters(long nativeRtpSender, RtpParameters parameters);
private static native RtpParameters nativeGetParameters(long nativeRtpSender);
diff --git a/webrtc/sdk/android/instrumentationtests/src/org/webrtc/PeerConnectionTest.java b/webrtc/sdk/android/instrumentationtests/src/org/webrtc/PeerConnectionTest.java
index 418b9337f1..8849edd2da 100644
--- a/webrtc/sdk/android/instrumentationtests/src/org/webrtc/PeerConnectionTest.java
+++ b/webrtc/sdk/android/instrumentationtests/src/org/webrtc/PeerConnectionTest.java
@@ -716,14 +716,20 @@ public class PeerConnectionTest {
assertEquals(PeerConnection.SignalingState.STABLE, offeringPC.signalingState());
assertEquals(PeerConnection.SignalingState.STABLE, answeringPC.signalingState());
- // Set a bitrate limit for the outgoing video stream for the offerer.
+ // Test some of the RtpSender API.
RtpSender videoSender = null;
+ RtpSender audioSender = null;
for (RtpSender sender : offeringPC.getSenders()) {
if (sender.track().kind().equals("video")) {
videoSender = sender;
+ } else {
+ audioSender = sender;
}
}
assertNotNull(videoSender);
+ assertNotNull(audioSender);
+
+ // Set a bitrate limit for the outgoing video stream for the offerer.
RtpParameters rtpParameters = videoSender.getParameters();
assertNotNull(rtpParameters);
assertEquals(1, rtpParameters.encodings.size());
@@ -732,6 +738,12 @@ public class PeerConnectionTest {
rtpParameters.encodings.get(0).maxBitrateBps = 300000;
assertTrue(videoSender.setParameters(rtpParameters));
+ // Create a DTMF sender.
+ DtmfSender dtmfSender = audioSender.dtmf();
+ assertNotNull(dtmfSender);
+ assertTrue(dtmfSender.canInsertDtmf());
+ assertTrue(dtmfSender.insertDtmf("123", 300, 100));
+
// Verify that we can read back the updated value.
rtpParameters = videoSender.getParameters();
assertEquals(300000, (int) rtpParameters.encodings.get(0).maxBitrateBps);
diff --git a/webrtc/sdk/android/src/jni/peerconnection_jni.cc b/webrtc/sdk/android/src/jni/peerconnection_jni.cc
index 212fa43c92..91cf5b7880 100644
--- a/webrtc/sdk/android/src/jni/peerconnection_jni.cc
+++ b/webrtc/sdk/android/src/jni/peerconnection_jni.cc
@@ -90,6 +90,7 @@ using webrtc::DataBuffer;
using webrtc::DataChannelInit;
using webrtc::DataChannelInterface;
using webrtc::DataChannelObserver;
+using webrtc::DtmfSenderInterface;
using webrtc::IceCandidateInterface;
using webrtc::LogcatTraceContext;
using webrtc::MediaConstraintsInterface;
@@ -2357,16 +2358,22 @@ JOW(jboolean, RtpSender_nativeSetTrack)(JNIEnv* jni,
->SetTrack(reinterpret_cast