Make the RTSP SocketFactory configurable

This commit is contained in:
Sebastian Roth 2021-10-25 13:13:08 +01:00
parent 1f9241a552
commit 8e24d29040
6 changed files with 57 additions and 17 deletions

View File

@ -124,6 +124,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
private final PlaybackEventListener playbackEventListener; private final PlaybackEventListener playbackEventListener;
private final String userAgent; private final String userAgent;
private final boolean debugLoggingEnabled; private final boolean debugLoggingEnabled;
@Nullable private final SocketFactory socketFactory;
private final ArrayDeque<RtpLoadInfo> pendingSetupRtpLoadInfos; private final ArrayDeque<RtpLoadInfo> pendingSetupRtpLoadInfos;
// TODO(b/172331505) Add a timeout monitor for pending requests. // TODO(b/172331505) Add a timeout monitor for pending requests.
private final SparseArray<RtspRequest> pendingRequests; private final SparseArray<RtspRequest> pendingRequests;
@ -161,11 +162,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
PlaybackEventListener playbackEventListener, PlaybackEventListener playbackEventListener,
String userAgent, String userAgent,
Uri uri, Uri uri,
boolean debugLoggingEnabled) { boolean debugLoggingEnabled,
@Nullable SocketFactory socketFactory) {
this.sessionInfoListener = sessionInfoListener; this.sessionInfoListener = sessionInfoListener;
this.playbackEventListener = playbackEventListener; this.playbackEventListener = playbackEventListener;
this.userAgent = userAgent; this.userAgent = userAgent;
this.debugLoggingEnabled = debugLoggingEnabled; this.debugLoggingEnabled = debugLoggingEnabled;
this.socketFactory = socketFactory;
this.pendingSetupRtpLoadInfos = new ArrayDeque<>(); this.pendingSetupRtpLoadInfos = new ArrayDeque<>();
this.pendingRequests = new SparseArray<>(); this.pendingRequests = new SparseArray<>();
this.messageSender = new MessageSender(); 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}. */ /** 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); checkArgument(uri.getHost() != null);
int rtspPort = uri.getPort() > 0 ? uri.getPort() : DEFAULT_RTSP_PORT; 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) { private void dispatchRtspError(Throwable error) {

View File

@ -55,6 +55,7 @@ import java.io.IOException;
import java.net.BindException; import java.net.BindException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.net.SocketFactory;
import org.checkerframework.checker.nullness.compatqual.NullableType; import org.checkerframework.checker.nullness.compatqual.NullableType;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
@ -96,12 +97,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/** /**
* Creates an RTSP media period. * 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 rtpDataChannelFactory A {@link RtpDataChannel.Factory} for {@link RtpDataChannel}.
* @param uri The RTSP playback {@link Uri}. * @param uri The RTSP playback {@link Uri}.
* @param listener A {@link Listener} to receive session information updates. * @param listener A {@link Listener} to receive session information updates.
* @param userAgent The user agent. * @param userAgent The user agent.
* @param debugLoggingEnabled Whether to log RTSP messages.
* @param socketFactory A socket factory.
*/ */
public RtspMediaPeriod( public RtspMediaPeriod(
Allocator allocator, Allocator allocator,
@ -109,7 +111,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
Uri uri, Uri uri,
Listener listener, Listener listener,
String userAgent, String userAgent,
boolean debugLoggingEnabled) { boolean debugLoggingEnabled,
@Nullable SocketFactory socketFactory) {
this.allocator = allocator; this.allocator = allocator;
this.rtpDataChannelFactory = rtpDataChannelFactory; this.rtpDataChannelFactory = rtpDataChannelFactory;
this.listener = listener; this.listener = listener;
@ -122,7 +125,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/* playbackEventListener= */ internalListener, /* playbackEventListener= */ internalListener,
/* userAgent= */ userAgent, /* userAgent= */ userAgent,
/* uri= */ uri, /* uri= */ uri,
debugLoggingEnabled); debugLoggingEnabled,
socketFactory);
rtspLoaderWrappers = new ArrayList<>(); rtspLoaderWrappers = new ArrayList<>();
selectedLoadInfos = new ArrayList<>(); selectedLoadInfos = new ArrayList<>();

View File

@ -40,6 +40,7 @@ import com.google.android.exoplayer2.upstream.HttpDataSource;
import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy; import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
import com.google.android.exoplayer2.upstream.TransferListener; import com.google.android.exoplayer2.upstream.TransferListener;
import java.io.IOException; import java.io.IOException;
import javax.net.SocketFactory;
/** An Rtsp {@link MediaSource} */ /** An Rtsp {@link MediaSource} */
public final class RtspMediaSource extends BaseMediaSource { public final class RtspMediaSource extends BaseMediaSource {
@ -70,6 +71,7 @@ public final class RtspMediaSource extends BaseMediaSource {
private String userAgent; private String userAgent;
private boolean forceUseRtpTcp; private boolean forceUseRtpTcp;
private boolean debugLoggingEnabled; private boolean debugLoggingEnabled;
private SocketFactory socketFactory;
public Factory() { public Factory() {
timeoutMs = DEFAULT_TIMEOUT_MS; timeoutMs = DEFAULT_TIMEOUT_MS;
@ -117,6 +119,19 @@ public final class RtspMediaSource extends BaseMediaSource {
return this; 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}. * 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 TransferRtpDataChannelFactory(timeoutMs)
: new UdpDataSourceRtpDataChannelFactory(timeoutMs), : new UdpDataSourceRtpDataChannelFactory(timeoutMs),
userAgent, userAgent,
debugLoggingEnabled); debugLoggingEnabled,
socketFactory);
} }
} }
@ -227,6 +243,9 @@ public final class RtspMediaSource extends BaseMediaSource {
private final Uri uri; private final Uri uri;
private final boolean debugLoggingEnabled; private final boolean debugLoggingEnabled;
@Nullable
private final SocketFactory socketFactory;
private long timelineDurationUs; private long timelineDurationUs;
private boolean timelineIsSeekable; private boolean timelineIsSeekable;
private boolean timelineIsLive; private boolean timelineIsLive;
@ -237,12 +256,14 @@ public final class RtspMediaSource extends BaseMediaSource {
MediaItem mediaItem, MediaItem mediaItem,
RtpDataChannel.Factory rtpDataChannelFactory, RtpDataChannel.Factory rtpDataChannelFactory,
String userAgent, String userAgent,
boolean debugLoggingEnabled) { boolean debugLoggingEnabled,
@Nullable SocketFactory socketFactory) {
this.mediaItem = mediaItem; this.mediaItem = mediaItem;
this.rtpDataChannelFactory = rtpDataChannelFactory; this.rtpDataChannelFactory = rtpDataChannelFactory;
this.userAgent = userAgent; this.userAgent = userAgent;
this.uri = checkNotNull(this.mediaItem.localConfiguration).uri; this.uri = checkNotNull(this.mediaItem.localConfiguration).uri;
this.debugLoggingEnabled = debugLoggingEnabled; this.debugLoggingEnabled = debugLoggingEnabled;
this.socketFactory = socketFactory;
this.timelineDurationUs = C.TIME_UNSET; this.timelineDurationUs = C.TIME_UNSET;
this.timelineIsPlaceholder = true; this.timelineIsPlaceholder = true;
} }
@ -281,7 +302,8 @@ public final class RtspMediaSource extends BaseMediaSource {
notifySourceInfoRefreshed(); notifySourceInfoRefreshed();
}, },
userAgent, userAgent,
debugLoggingEnabled); debugLoggingEnabled,
socketFactory);
} }
@Override @Override

View File

@ -113,7 +113,8 @@ public final class RtspClientTest {
EMPTY_PLAYBACK_LISTENER, EMPTY_PLAYBACK_LISTENER,
/* userAgent= */ "ExoPlayer:RtspClientTest", /* userAgent= */ "ExoPlayer:RtspClientTest",
RtspTestUtils.getTestUri(rtspServer.startAndGetPortNumber()), RtspTestUtils.getTestUri(rtspServer.startAndGetPortNumber()),
/* debugLoggingEnabled= */ false); /* debugLoggingEnabled= */ false,
/* socketFactory */ null);
rtspClient.start(); rtspClient.start();
RobolectricUtil.runMainLooperUntil(() -> tracksInSession.get() != null); RobolectricUtil.runMainLooperUntil(() -> tracksInSession.get() != null);
@ -164,7 +165,8 @@ public final class RtspClientTest {
EMPTY_PLAYBACK_LISTENER, EMPTY_PLAYBACK_LISTENER,
/* userAgent= */ "ExoPlayer:RtspClientTest", /* userAgent= */ "ExoPlayer:RtspClientTest",
RtspTestUtils.getTestUri(rtspServer.startAndGetPortNumber()), RtspTestUtils.getTestUri(rtspServer.startAndGetPortNumber()),
/* debugLoggingEnabled= */ false); /* debugLoggingEnabled= */ false,
/* socketFactory */ null);
rtspClient.start(); rtspClient.start();
RobolectricUtil.runMainLooperUntil(() -> tracksInSession.get() != null); RobolectricUtil.runMainLooperUntil(() -> tracksInSession.get() != null);
@ -207,7 +209,8 @@ public final class RtspClientTest {
EMPTY_PLAYBACK_LISTENER, EMPTY_PLAYBACK_LISTENER,
/* userAgent= */ "ExoPlayer:RtspClientTest", /* userAgent= */ "ExoPlayer:RtspClientTest",
RtspTestUtils.getTestUri(rtspServer.startAndGetPortNumber()), RtspTestUtils.getTestUri(rtspServer.startAndGetPortNumber()),
/* debugLoggingEnabled= */ false); /* debugLoggingEnabled= */ false,
/* socketFactory */ null);
rtspClient.start(); rtspClient.start();
RobolectricUtil.runMainLooperUntil(() -> tracksInSession.get() != null); RobolectricUtil.runMainLooperUntil(() -> tracksInSession.get() != null);
@ -253,7 +256,8 @@ public final class RtspClientTest {
EMPTY_PLAYBACK_LISTENER, EMPTY_PLAYBACK_LISTENER,
/* userAgent= */ "ExoPlayer:RtspClientTest", /* userAgent= */ "ExoPlayer:RtspClientTest",
RtspTestUtils.getTestUri(rtspServer.startAndGetPortNumber()), RtspTestUtils.getTestUri(rtspServer.startAndGetPortNumber()),
/* debugLoggingEnabled= */ false); /* debugLoggingEnabled= */ false,
/* socketFactory */ null);
rtspClient.start(); rtspClient.start();
RobolectricUtil.runMainLooperUntil(() -> failureMessage.get() != null); RobolectricUtil.runMainLooperUntil(() -> failureMessage.get() != null);
@ -299,7 +303,8 @@ public final class RtspClientTest {
EMPTY_PLAYBACK_LISTENER, EMPTY_PLAYBACK_LISTENER,
/* userAgent= */ "ExoPlayer:RtspClientTest", /* userAgent= */ "ExoPlayer:RtspClientTest",
RtspTestUtils.getTestUri(rtspServer.startAndGetPortNumber()), RtspTestUtils.getTestUri(rtspServer.startAndGetPortNumber()),
/* debugLoggingEnabled= */ false); /* debugLoggingEnabled= */ false,
/* socketFactory */ null);
rtspClient.start(); rtspClient.start();
RobolectricUtil.runMainLooperUntil(() -> failureCause.get() != null); RobolectricUtil.runMainLooperUntil(() -> failureCause.get() != null);

View File

@ -84,7 +84,8 @@ public final class RtspMediaPeriodTest {
RtspTestUtils.getTestUri(rtspServer.startAndGetPortNumber()), RtspTestUtils.getTestUri(rtspServer.startAndGetPortNumber()),
/* listener= */ timing -> refreshedSourceDurationMs.set(timing.getDurationMs()), /* listener= */ timing -> refreshedSourceDurationMs.set(timing.getDurationMs()),
/* userAgent= */ "ExoPlayer:RtspPeriodTest", /* userAgent= */ "ExoPlayer:RtspPeriodTest",
/* debugLoggingEnabled= */ false); /* debugLoggingEnabled= */ false,
null);
mediaPeriod.prepare( mediaPeriod.prepare(
new MediaPeriod.Callback() { new MediaPeriod.Callback() {

View File

@ -156,7 +156,8 @@ public final class RtspPlaybackTest {
MediaItem.fromUri(RtspTestUtils.getTestUri(serverRtspPortNumber)), MediaItem.fromUri(RtspTestUtils.getTestUri(serverRtspPortNumber)),
rtpDataChannelFactory, rtpDataChannelFactory,
"ExoPlayer:PlaybackTest", "ExoPlayer:PlaybackTest",
/* debugLoggingEnabled= */ false), /* debugLoggingEnabled= */ false,
null),
false); false);
return player; return player;
} }