From 8e24d290405cd5c10e772eccbe0ed6b11ada1206 Mon Sep 17 00:00:00 2001 From: Sebastian Roth Date: Mon, 25 Oct 2021 13:13:08 +0100 Subject: [PATCH] Make the RTSP SocketFactory configurable --- .../exoplayer2/source/rtsp/RtspClient.java | 13 +++++++-- .../source/rtsp/RtspMediaPeriod.java | 12 +++++--- .../source/rtsp/RtspMediaSource.java | 28 +++++++++++++++++-- .../source/rtsp/RtspClientTest.java | 15 ++++++---- .../source/rtsp/RtspMediaPeriodTest.java | 3 +- .../source/rtsp/RtspPlaybackTest.java | 3 +- 6 files changed, 57 insertions(+), 17 deletions(-) diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspClient.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspClient.java index 715212d211..c1b982634a 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspClient.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspClient.java @@ -124,6 +124,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; private final PlaybackEventListener playbackEventListener; private final String userAgent; private final boolean debugLoggingEnabled; + @Nullable private final SocketFactory socketFactory; private final ArrayDeque pendingSetupRtpLoadInfos; // TODO(b/172331505) Add a timeout monitor for pending requests. private final SparseArray pendingRequests; @@ -161,11 +162,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; PlaybackEventListener playbackEventListener, String userAgent, Uri uri, - boolean debugLoggingEnabled) { + boolean debugLoggingEnabled, + @Nullable SocketFactory socketFactory) { this.sessionInfoListener = sessionInfoListener; this.playbackEventListener = playbackEventListener; this.userAgent = userAgent; this.debugLoggingEnabled = debugLoggingEnabled; + this.socketFactory = socketFactory; this.pendingSetupRtpLoadInfos = new ArrayDeque<>(); this.pendingRequests = new SparseArray<>(); this.messageSender = new MessageSender(); @@ -286,10 +289,14 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } /** Returns a {@link Socket} that is connected to the {@code uri}. */ - private static Socket getSocket(Uri uri) throws IOException { + private Socket getSocket(Uri uri) throws IOException { checkArgument(uri.getHost() != null); int rtspPort = uri.getPort() > 0 ? uri.getPort() : DEFAULT_RTSP_PORT; - return SocketFactory.getDefault().createSocket(checkNotNull(uri.getHost()), rtspPort); + + SocketFactory socketFactory = + this.socketFactory != null ? this.socketFactory : SocketFactory.getDefault(); + + return socketFactory.createSocket(checkNotNull(uri.getHost()), rtspPort); } private void dispatchRtspError(Throwable error) { diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMediaPeriod.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMediaPeriod.java index 435bb59a30..e71f4d72a3 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMediaPeriod.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMediaPeriod.java @@ -55,6 +55,7 @@ import java.io.IOException; import java.net.BindException; import java.util.ArrayList; import java.util.List; +import javax.net.SocketFactory; import org.checkerframework.checker.nullness.compatqual.NullableType; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @@ -96,12 +97,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** * Creates an RTSP media period. - * - * @param allocator An {@link Allocator} from which to obtain media buffer allocations. + * @param allocator An {@link Allocator} from which to obtain media buffer allocations. * @param rtpDataChannelFactory A {@link RtpDataChannel.Factory} for {@link RtpDataChannel}. * @param uri The RTSP playback {@link Uri}. * @param listener A {@link Listener} to receive session information updates. * @param userAgent The user agent. + * @param debugLoggingEnabled Whether to log RTSP messages. + * @param socketFactory A socket factory. */ public RtspMediaPeriod( Allocator allocator, @@ -109,7 +111,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; Uri uri, Listener listener, String userAgent, - boolean debugLoggingEnabled) { + boolean debugLoggingEnabled, + @Nullable SocketFactory socketFactory) { this.allocator = allocator; this.rtpDataChannelFactory = rtpDataChannelFactory; this.listener = listener; @@ -122,7 +125,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /* playbackEventListener= */ internalListener, /* userAgent= */ userAgent, /* uri= */ uri, - debugLoggingEnabled); + debugLoggingEnabled, + socketFactory); rtspLoaderWrappers = new ArrayList<>(); selectedLoadInfos = new ArrayList<>(); diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMediaSource.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMediaSource.java index 63bbeed35c..54145cad9b 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMediaSource.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMediaSource.java @@ -40,6 +40,7 @@ import com.google.android.exoplayer2.upstream.HttpDataSource; import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy; import com.google.android.exoplayer2.upstream.TransferListener; import java.io.IOException; +import javax.net.SocketFactory; /** An Rtsp {@link MediaSource} */ public final class RtspMediaSource extends BaseMediaSource { @@ -70,6 +71,7 @@ public final class RtspMediaSource extends BaseMediaSource { private String userAgent; private boolean forceUseRtpTcp; private boolean debugLoggingEnabled; + private SocketFactory socketFactory; public Factory() { timeoutMs = DEFAULT_TIMEOUT_MS; @@ -117,6 +119,19 @@ public final class RtspMediaSource extends BaseMediaSource { return this; } + /** + * Configures a socket factory to be used for client connections. + * + * When unspecified, {@link SocketFactory#getDefault()} is used. + * + * @param socketFactory A socket factory. + * @return This Factory, for convenience. + */ + public Factory setSocketFactory(SocketFactory socketFactory) { + this.socketFactory = socketFactory; + return this; + } + /** * Sets the timeout in milliseconds, the default value is {@link #DEFAULT_TIMEOUT_MS}. * @@ -202,7 +217,8 @@ public final class RtspMediaSource extends BaseMediaSource { ? new TransferRtpDataChannelFactory(timeoutMs) : new UdpDataSourceRtpDataChannelFactory(timeoutMs), userAgent, - debugLoggingEnabled); + debugLoggingEnabled, + socketFactory); } } @@ -227,6 +243,9 @@ public final class RtspMediaSource extends BaseMediaSource { private final Uri uri; private final boolean debugLoggingEnabled; + @Nullable + private final SocketFactory socketFactory; + private long timelineDurationUs; private boolean timelineIsSeekable; private boolean timelineIsLive; @@ -237,12 +256,14 @@ public final class RtspMediaSource extends BaseMediaSource { MediaItem mediaItem, RtpDataChannel.Factory rtpDataChannelFactory, String userAgent, - boolean debugLoggingEnabled) { + boolean debugLoggingEnabled, + @Nullable SocketFactory socketFactory) { this.mediaItem = mediaItem; this.rtpDataChannelFactory = rtpDataChannelFactory; this.userAgent = userAgent; this.uri = checkNotNull(this.mediaItem.localConfiguration).uri; this.debugLoggingEnabled = debugLoggingEnabled; + this.socketFactory = socketFactory; this.timelineDurationUs = C.TIME_UNSET; this.timelineIsPlaceholder = true; } @@ -281,7 +302,8 @@ public final class RtspMediaSource extends BaseMediaSource { notifySourceInfoRefreshed(); }, userAgent, - debugLoggingEnabled); + debugLoggingEnabled, + socketFactory); } @Override diff --git a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspClientTest.java b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspClientTest.java index 0018c8a9e4..ca239695ad 100644 --- a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspClientTest.java +++ b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspClientTest.java @@ -113,7 +113,8 @@ public final class RtspClientTest { EMPTY_PLAYBACK_LISTENER, /* userAgent= */ "ExoPlayer:RtspClientTest", RtspTestUtils.getTestUri(rtspServer.startAndGetPortNumber()), - /* debugLoggingEnabled= */ false); + /* debugLoggingEnabled= */ false, + /* socketFactory */ null); rtspClient.start(); RobolectricUtil.runMainLooperUntil(() -> tracksInSession.get() != null); @@ -164,7 +165,8 @@ public final class RtspClientTest { EMPTY_PLAYBACK_LISTENER, /* userAgent= */ "ExoPlayer:RtspClientTest", RtspTestUtils.getTestUri(rtspServer.startAndGetPortNumber()), - /* debugLoggingEnabled= */ false); + /* debugLoggingEnabled= */ false, + /* socketFactory */ null); rtspClient.start(); RobolectricUtil.runMainLooperUntil(() -> tracksInSession.get() != null); @@ -207,7 +209,8 @@ public final class RtspClientTest { EMPTY_PLAYBACK_LISTENER, /* userAgent= */ "ExoPlayer:RtspClientTest", RtspTestUtils.getTestUri(rtspServer.startAndGetPortNumber()), - /* debugLoggingEnabled= */ false); + /* debugLoggingEnabled= */ false, + /* socketFactory */ null); rtspClient.start(); RobolectricUtil.runMainLooperUntil(() -> tracksInSession.get() != null); @@ -253,7 +256,8 @@ public final class RtspClientTest { EMPTY_PLAYBACK_LISTENER, /* userAgent= */ "ExoPlayer:RtspClientTest", RtspTestUtils.getTestUri(rtspServer.startAndGetPortNumber()), - /* debugLoggingEnabled= */ false); + /* debugLoggingEnabled= */ false, + /* socketFactory */ null); rtspClient.start(); RobolectricUtil.runMainLooperUntil(() -> failureMessage.get() != null); @@ -299,7 +303,8 @@ public final class RtspClientTest { EMPTY_PLAYBACK_LISTENER, /* userAgent= */ "ExoPlayer:RtspClientTest", RtspTestUtils.getTestUri(rtspServer.startAndGetPortNumber()), - /* debugLoggingEnabled= */ false); + /* debugLoggingEnabled= */ false, + /* socketFactory */ null); rtspClient.start(); RobolectricUtil.runMainLooperUntil(() -> failureCause.get() != null); diff --git a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMediaPeriodTest.java b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMediaPeriodTest.java index da7da55d8e..90594f6ca1 100644 --- a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMediaPeriodTest.java +++ b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMediaPeriodTest.java @@ -84,7 +84,8 @@ public final class RtspMediaPeriodTest { RtspTestUtils.getTestUri(rtspServer.startAndGetPortNumber()), /* listener= */ timing -> refreshedSourceDurationMs.set(timing.getDurationMs()), /* userAgent= */ "ExoPlayer:RtspPeriodTest", - /* debugLoggingEnabled= */ false); + /* debugLoggingEnabled= */ false, + null); mediaPeriod.prepare( new MediaPeriod.Callback() { diff --git a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspPlaybackTest.java b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspPlaybackTest.java index c82f68c0a3..8ebcbbe36d 100644 --- a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspPlaybackTest.java +++ b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspPlaybackTest.java @@ -156,7 +156,8 @@ public final class RtspPlaybackTest { MediaItem.fromUri(RtspTestUtils.getTestUri(serverRtspPortNumber)), rtpDataChannelFactory, "ExoPlayer:PlaybackTest", - /* debugLoggingEnabled= */ false), + /* debugLoggingEnabled= */ false, + null), false); return player; }