From 24af66397e3e1919b801c8d56926263f90808ea1 Mon Sep 17 00:00:00 2001 From: deadbeef Date: Wed, 1 Feb 2017 21:53:09 -0800 Subject: [PATCH] Adding Java wrapper for DtmfSender. BUG=webrtc:4180 Review-Url: https://codereview.webrtc.org/2666873002 Cr-Commit-Position: refs/heads/master@{#16410} --- webrtc/sdk/android/BUILD.gn | 1 + .../android/api/org/webrtc/DtmfSender.java | 84 +++++++++++++++++++ .../sdk/android/api/org/webrtc/RtpSender.java | 18 +++- .../src/org/webrtc/PeerConnectionTest.java | 14 +++- .../sdk/android/src/jni/peerconnection_jni.cc | 56 ++++++++++++- 5 files changed, 167 insertions(+), 6 deletions(-) create mode 100644 webrtc/sdk/android/api/org/webrtc/DtmfSender.java 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(j_track_pointer)); } -JOW(jlong, RtpSender_nativeGetTrack)(JNIEnv* jni, - jclass, - jlong j_rtp_sender_pointer, - jlong j_track_pointer) { +JOW(jlong, RtpSender_nativeGetTrack) +(JNIEnv* jni, jclass, jlong j_rtp_sender_pointer) { return jlongFromPointer( reinterpret_cast(j_rtp_sender_pointer) ->track() .release()); } +JOW(jlong, RtpSender_nativeGetDtmfSender) +(JNIEnv* jni, jclass, jlong j_rtp_sender_pointer) { + return jlongFromPointer( + reinterpret_cast(j_rtp_sender_pointer) + ->GetDtmfSender() + .release()); +} + static void JavaRtpParametersToJsepRtpParameters( JNIEnv* jni, jobject j_parameters, @@ -2615,4 +2622,45 @@ JOW(void, RtpReceiver_nativeUnsetObserver) } } +JOW(jboolean, DtmfSender_nativeCanInsertDtmf) +(JNIEnv* jni, jclass, jlong j_dtmf_sender_pointer) { + return reinterpret_cast(j_dtmf_sender_pointer) + ->CanInsertDtmf(); +} + +JOW(jboolean, DtmfSender_nativeInsertDtmf) +(JNIEnv* jni, + jclass, + jlong j_dtmf_sender_pointer, + jstring tones, + jint duration, + jint inter_tone_gap) { + return reinterpret_cast(j_dtmf_sender_pointer) + ->InsertDtmf(JavaToStdString(jni, tones), duration, inter_tone_gap); +} + +JOW(jstring, DtmfSender_nativeTones) +(JNIEnv* jni, jclass, jlong j_dtmf_sender_pointer) { + return JavaStringFromStdString( + jni, + reinterpret_cast(j_dtmf_sender_pointer)->tones()); +} + +JOW(jint, DtmfSender_nativeDuration) +(JNIEnv* jni, jclass, jlong j_dtmf_sender_pointer) { + return reinterpret_cast(j_dtmf_sender_pointer) + ->duration(); +} + +JOW(jint, DtmfSender_nativeInterToneGap) +(JNIEnv* jni, jclass, jlong j_dtmf_sender_pointer) { + return reinterpret_cast(j_dtmf_sender_pointer) + ->inter_tone_gap(); +} + +JOW(void, DtmfSender_free) +(JNIEnv* jni, jclass, jlong j_dtmf_sender_pointer) { + reinterpret_cast(j_dtmf_sender_pointer)->Release(); +} + } // namespace webrtc_jni