Implement JNI and objc implementation for Ice Candidate Pair Change event surfacing

Bug: webrtc:10419
Change-Id: I18528bf2526e933568bf052de76a434f012161da
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/148320
Commit-Queue: Alex Drake <alexdrake@google.com>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Reviewed-by: Anders Carlsson <andersc@webrtc.org>
Reviewed-by: Qingsi Wang <qingsi@webrtc.org>
Reviewed-by: Alex Glaznev <glaznev@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28838}
This commit is contained in:
Alex Drake
2019-08-12 16:27:34 -07:00
committed by Commit Bot
parent 519fc4454a
commit 43faee09e5
12 changed files with 116 additions and 9 deletions

View File

@ -40,6 +40,7 @@ import org.appspot.apprtc.RecordedAudioToFileController;
import org.webrtc.AudioSource; import org.webrtc.AudioSource;
import org.webrtc.AudioTrack; import org.webrtc.AudioTrack;
import org.webrtc.CameraVideoCapturer; import org.webrtc.CameraVideoCapturer;
import org.webrtc.CandidatePairChangeEvent;
import org.webrtc.DataChannel; import org.webrtc.DataChannel;
import org.webrtc.DefaultVideoDecoderFactory; import org.webrtc.DefaultVideoDecoderFactory;
import org.webrtc.DefaultVideoEncoderFactory; import org.webrtc.DefaultVideoEncoderFactory;
@ -1214,6 +1215,11 @@ public class PeerConnectionClient {
Log.d(TAG, "IceConnectionReceiving changed to " + receiving); Log.d(TAG, "IceConnectionReceiving changed to " + receiving);
} }
@Override
public void onSelectedCandidatePairChanged(CandidatePairChangeEvent event) {
Log.d(TAG, "Selected candidate pair changed because: " + event);
}
@Override @Override
public void onAddStream(final MediaStream stream) {} public void onAddStream(final MediaStream stream) {}

View File

@ -433,6 +433,14 @@ static int const kKbpsMultiplier = 1000;
}); });
} }
- (void)peerConnection:(RTCPeerConnection *)peerConnection
didChangeLocalCandidate:(RTCIceCandidate *)local
didChangeRemoteCandidate:(RTCIceCandidate *)remote
lastReceivedMs:(int)lastDataReceivedMs
didHaveReason:(NSString *)reason {
RTCLog(@"ICE candidate pair changed because: %@", reason);
}
- (void)peerConnection:(RTCPeerConnection *)peerConnection - (void)peerConnection:(RTCPeerConnection *)peerConnection
didOpenDataChannel:(RTCDataChannel *)dataChannel { didOpenDataChannel:(RTCDataChannel *)dataChannel {
} }

View File

@ -940,6 +940,7 @@ class PeerConnectionWrapper : public webrtc::PeerConnectionObserver,
const cricket::CandidatePairChangeEvent& event) { const cricket::CandidatePairChangeEvent& event) {
ice_candidate_pair_change_history_.push_back(event); ice_candidate_pair_change_history_.push_back(event);
} }
void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) override { void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) override {
RTC_LOG(LS_INFO) << debug_name_ << ": OnIceCandidate"; RTC_LOG(LS_INFO) << debug_name_ << ": OnIceCandidate";

View File

@ -266,6 +266,7 @@ if (is_android) {
"api/org/webrtc/AudioSource.java", "api/org/webrtc/AudioSource.java",
"api/org/webrtc/AudioTrack.java", "api/org/webrtc/AudioTrack.java",
"api/org/webrtc/CallSessionFileRotatingLogSink.java", "api/org/webrtc/CallSessionFileRotatingLogSink.java",
"api/org/webrtc/CandidatePairChangeEvent.java",
"api/org/webrtc/CryptoOptions.java", "api/org/webrtc/CryptoOptions.java",
"api/org/webrtc/DataChannel.java", "api/org/webrtc/DataChannel.java",
"api/org/webrtc/DtmfSender.java", "api/org/webrtc/DtmfSender.java",
@ -1263,6 +1264,7 @@ if (current_os == "linux" || is_android) {
sources = [ sources = [
"api/org/webrtc/AudioTrack.java", "api/org/webrtc/AudioTrack.java",
"api/org/webrtc/CallSessionFileRotatingLogSink.java", "api/org/webrtc/CallSessionFileRotatingLogSink.java",
"api/org/webrtc/CandidatePairChangeEvent.java",
"api/org/webrtc/CryptoOptions.java", "api/org/webrtc/CryptoOptions.java",
"api/org/webrtc/DataChannel.java", "api/org/webrtc/DataChannel.java",
"api/org/webrtc/DtmfSender.java", "api/org/webrtc/DtmfSender.java",

View File

@ -0,0 +1,31 @@
/*
* Copyright 2013 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;
/**
* Representation of a change in selected ICE candidate pair.
* {@code CandidatePairChangeEvent} in the C++ API.
*/
public final class CandidatePairChangeEvent {
public final IceCandidate local;
public final IceCandidate remote;
public final int lastDataReceivedMs;
public final String reason;
@CalledByNative
CandidatePairChangeEvent(
IceCandidate local, IceCandidate remote, int lastDataReceivedMs, String reason) {
this.local = local;
this.remote = remote;
this.lastDataReceivedMs = lastDataReceivedMs;
this.reason = reason;
}
}

View File

@ -15,6 +15,7 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import org.webrtc.CandidatePairChangeEvent;
import org.webrtc.DataChannel; import org.webrtc.DataChannel;
import org.webrtc.MediaStreamTrack; import org.webrtc.MediaStreamTrack;
import org.webrtc.RtpTransceiver; import org.webrtc.RtpTransceiver;
@ -118,6 +119,10 @@ public class PeerConnection {
/** Triggered when some ICE candidates have been removed. */ /** Triggered when some ICE candidates have been removed. */
@CalledByNative("Observer") void onIceCandidatesRemoved(IceCandidate[] candidates); @CalledByNative("Observer") void onIceCandidatesRemoved(IceCandidate[] candidates);
/** Triggered when the ICE candidate pair is changed. */
@CalledByNative("Observer")
default void onSelectedCandidatePairChanged(CandidatePairChangeEvent event) {}
/** Triggered when media is received on a new stream from remote peer. */ /** Triggered when media is received on a new stream from remote peer. */
@CalledByNative("Observer") void onAddStream(MediaStream stream); @CalledByNative("Observer") void onAddStream(MediaStream stream);

View File

@ -143,6 +143,9 @@ public class PeerConnectionTest {
@Override @Override
public void onIceCandidatesRemoved(IceCandidate[] candidates) {} public void onIceCandidatesRemoved(IceCandidate[] candidates) {}
@Override
public void onSelectedCandidatePairChanged(CandidatePairChangeEvent event) {}
// TODO(bugs.webrtc.org/8491): Remove NoSynchronizedMethodCheck suppression. // TODO(bugs.webrtc.org/8491): Remove NoSynchronizedMethodCheck suppression.
@SuppressWarnings("NoSynchronizedMethodCheck") @SuppressWarnings("NoSynchronizedMethodCheck")
public synchronized void setExpectedResolution(int width, int height) { public synchronized void setExpectedResolution(int width, int height) {

View File

@ -41,6 +41,7 @@
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "rtc_base/logging.h" #include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_conversions.h" #include "rtc_base/numerics/safe_conversions.h"
#include "sdk/android/generated_peerconnection_jni/CandidatePairChangeEvent_jni.h"
#include "sdk/android/generated_peerconnection_jni/PeerConnection_jni.h" #include "sdk/android/generated_peerconnection_jni/PeerConnection_jni.h"
#include "sdk/android/native_api/jni/java_types.h" #include "sdk/android/native_api/jni/java_types.h"
#include "sdk/android/src/jni/jni_helpers.h" #include "sdk/android/src/jni/jni_helpers.h"
@ -120,6 +121,16 @@ SdpSemantics JavaToNativeSdpSemantics(JNIEnv* jni,
return SdpSemantics::kPlanB; return SdpSemantics::kPlanB;
} }
ScopedJavaLocalRef<jobject> NativeToJavaCandidatePairChange(
JNIEnv* env,
const cricket::CandidatePairChangeEvent& event) {
return Java_CandidatePairChangeEvent_Constructor(
env, NativeToJavaCandidate(env, event.local_candidate),
NativeToJavaCandidate(env, event.remote_candidate),
static_cast<int>(event.last_data_received_ms),
NativeToJavaString(env, event.reason));
}
} // namespace } // namespace
void JavaToNativeRTCConfiguration( void JavaToNativeRTCConfiguration(
@ -325,6 +336,13 @@ void PeerConnectionObserverJni::OnIceConnectionReceivingChange(bool receiving) {
receiving); receiving);
} }
void PeerConnectionObserverJni::OnIceSelectedCandidatePairChanged(
const cricket::CandidatePairChangeEvent& event) {
JNIEnv* env = AttachCurrentThreadIfNeeded();
Java_Observer_onSelectedCandidatePairChanged(
env, j_observer_global_, NativeToJavaCandidatePairChange(env, event));
}
void PeerConnectionObserverJni::OnIceGatheringChange( void PeerConnectionObserverJni::OnIceGatheringChange(
PeerConnectionInterface::IceGatheringState new_state) { PeerConnectionInterface::IceGatheringState new_state) {
JNIEnv* env = AttachCurrentThreadIfNeeded(); JNIEnv* env = AttachCurrentThreadIfNeeded();

View File

@ -58,6 +58,8 @@ class PeerConnectionObserverJni : public PeerConnectionObserver {
void OnIceConnectionReceivingChange(bool receiving) override; void OnIceConnectionReceivingChange(bool receiving) override;
void OnIceGatheringChange( void OnIceGatheringChange(
PeerConnectionInterface::IceGatheringState new_state) override; PeerConnectionInterface::IceGatheringState new_state) override;
void OnIceSelectedCandidatePairChanged(
const cricket::CandidatePairChangeEvent& event) override;
void OnAddStream(rtc::scoped_refptr<MediaStreamInterface> stream) override; void OnAddStream(rtc::scoped_refptr<MediaStreamInterface> stream) override;
void OnRemoveStream(rtc::scoped_refptr<MediaStreamInterface> stream) override; void OnRemoveStream(rtc::scoped_refptr<MediaStreamInterface> stream) override;
void OnDataChannel(rtc::scoped_refptr<DataChannelInterface> channel) override; void OnDataChannel(rtc::scoped_refptr<DataChannelInterface> channel) override;

View File

@ -50,6 +50,8 @@ class PeerConnectionDelegateAdapter : public PeerConnectionObserver {
void OnIceCandidatesRemoved(const std::vector<cricket::Candidate> &candidates) override; void OnIceCandidatesRemoved(const std::vector<cricket::Candidate> &candidates) override;
void OnIceSelectedCandidatePairChanged(const cricket::CandidatePairChangeEvent &event) override;
void OnAddTrack(rtc::scoped_refptr<RtpReceiverInterface> receiver, void OnAddTrack(rtc::scoped_refptr<RtpReceiverInterface> receiver,
const std::vector<rtc::scoped_refptr<MediaStreamInterface>> &streams) override; const std::vector<rtc::scoped_refptr<MediaStreamInterface>> &streams) override;

View File

@ -147,6 +147,13 @@ RTC_OBJC_EXPORT
- (void)peerConnection:(RTCPeerConnection *)peerConnection - (void)peerConnection:(RTCPeerConnection *)peerConnection
didRemoveReceiver:(RTCRtpReceiver *)rtpReceiver; didRemoveReceiver:(RTCRtpReceiver *)rtpReceiver;
/** Called when the selected ICE candidate pair is changed. */
- (void)peerConnection:(RTCPeerConnection *)peerConnection
didChangeLocalCandidate:(RTCIceCandidate *)local
remoteCandidate:(RTCIceCandidate *)remote
lastReceivedMs:(int)lastDataReceivedMs
changeReason:(NSString *)reason;
@end @end
RTC_OBJC_EXPORT RTC_OBJC_EXPORT

View File

@ -233,20 +233,43 @@ void PeerConnectionDelegateAdapter::OnIceCandidatesRemoved(
didRemoveIceCandidates:ice_candidates]; didRemoveIceCandidates:ice_candidates];
} }
void PeerConnectionDelegateAdapter::OnIceSelectedCandidatePairChanged(
const cricket::CandidatePairChangeEvent &event) {
std::unique_ptr<JsepIceCandidate> local_candidate_wrapper(
new JsepIceCandidate(event.local_candidate.transport_name(), -1, event.local_candidate));
RTCIceCandidate *local_candidate =
[[RTCIceCandidate alloc] initWithNativeCandidate:local_candidate_wrapper.get()];
std::unique_ptr<JsepIceCandidate> remote_candidate_wrapper(
new JsepIceCandidate(event.remote_candidate.transport_name(), -1, event.remote_candidate));
RTCIceCandidate *remote_candidate =
[[RTCIceCandidate alloc] initWithNativeCandidate:remote_candidate_wrapper.get()];
RTCPeerConnection *peer_connection = peer_connection_;
NSString *nsstr_reason = [NSString stringForStdString:event.reason];
if ([peer_connection.delegate
respondsToSelector:@selector
(peerConnection:didChangeLocalCandidate:remoteCandidate:lastReceivedMs:changeReason:)]) {
[peer_connection.delegate peerConnection:peer_connection
didChangeLocalCandidate:local_candidate
remoteCandidate:remote_candidate
lastReceivedMs:event.last_data_received_ms
changeReason:nsstr_reason];
}
}
void PeerConnectionDelegateAdapter::OnAddTrack( void PeerConnectionDelegateAdapter::OnAddTrack(
rtc::scoped_refptr<RtpReceiverInterface> receiver, rtc::scoped_refptr<RtpReceiverInterface> receiver,
const std::vector<rtc::scoped_refptr<MediaStreamInterface>> &streams) { const std::vector<rtc::scoped_refptr<MediaStreamInterface>> &streams) {
RTCPeerConnection *peer_connection = peer_connection_; RTCPeerConnection *peer_connection = peer_connection_;
if ([peer_connection.delegate if ([peer_connection.delegate respondsToSelector:@selector(peerConnection:
respondsToSelector:@selector(peerConnection:didAddReceiver:streams:)]) { didAddReceiver:streams:)]) {
NSMutableArray *mediaStreams = [NSMutableArray arrayWithCapacity:streams.size()]; NSMutableArray *mediaStreams = [NSMutableArray arrayWithCapacity:streams.size()];
for (const auto &nativeStream : streams) { for (const auto &nativeStream : streams) {
RTCMediaStream *mediaStream = [[RTCMediaStream alloc] initWithFactory:peer_connection.factory RTCMediaStream *mediaStream = [[RTCMediaStream alloc] initWithFactory:peer_connection.factory
nativeMediaStream:nativeStream]; nativeMediaStream:nativeStream];
[mediaStreams addObject:mediaStream]; [mediaStreams addObject:mediaStream];
} }
RTCRtpReceiver *rtpReceiver = RTCRtpReceiver *rtpReceiver = [[RTCRtpReceiver alloc] initWithFactory:peer_connection.factory
[[RTCRtpReceiver alloc] initWithFactory:peer_connection.factory nativeRtpReceiver:receiver]; nativeRtpReceiver:receiver];
[peer_connection.delegate peerConnection:peer_connection [peer_connection.delegate peerConnection:peer_connection
didAddReceiver:rtpReceiver didAddReceiver:rtpReceiver
@ -258,15 +281,14 @@ void PeerConnectionDelegateAdapter::OnRemoveTrack(
rtc::scoped_refptr<RtpReceiverInterface> receiver) { rtc::scoped_refptr<RtpReceiverInterface> receiver) {
RTCPeerConnection *peer_connection = peer_connection_; RTCPeerConnection *peer_connection = peer_connection_;
if ([peer_connection.delegate respondsToSelector:@selector(peerConnection:didRemoveReceiver:)]) { if ([peer_connection.delegate respondsToSelector:@selector(peerConnection:didRemoveReceiver:)]) {
RTCRtpReceiver *rtpReceiver = RTCRtpReceiver *rtpReceiver = [[RTCRtpReceiver alloc] initWithFactory:peer_connection.factory
[[RTCRtpReceiver alloc] initWithFactory:peer_connection.factory nativeRtpReceiver:receiver]; nativeRtpReceiver:receiver];
[peer_connection.delegate peerConnection:peer_connection didRemoveReceiver:rtpReceiver]; [peer_connection.delegate peerConnection:peer_connection didRemoveReceiver:rtpReceiver];
} }
} }
} // namespace webrtc } // namespace webrtc
@implementation RTCPeerConnection { @implementation RTCPeerConnection {
RTCPeerConnectionFactory *_factory; RTCPeerConnectionFactory *_factory;
NSMutableArray<RTCMediaStream *> *_localStreams; NSMutableArray<RTCMediaStream *> *_localStreams;