Add factory method to for using TCP streaming.

#minor-release

PiperOrigin-RevId: 377476603
This commit is contained in:
claincly 2021-06-04 11:15:37 +01:00 committed by Oliver Woodman
parent c15acdf0db
commit 74ff9f21f0
3 changed files with 34 additions and 9 deletions

View File

@ -46,6 +46,7 @@
* GL demo app:
* Fix texture transformation to avoid green bars shown on some videos
([#8992](https://github.com/google/ExoPlayer/issues/8992)).
* Add `RtspMediaSource.Factory` option to force using TCP for streaming.
### 2.14.0 (2021-05-13)

View File

@ -84,7 +84,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
private boolean prepared;
private boolean trackSelected;
private int portBindingRetryCount;
private boolean hasRetriedWithRtpTcp;
private boolean isUsingRtpTcp;
/**
* Creates an RTSP media period.
@ -514,12 +514,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
private LoadErrorAction handleSocketTimeout(RtpDataLoadable loadable) {
// TODO(b/172331505) Allow for retry when loading is not ending.
if (getBufferedPositionUs() == Long.MIN_VALUE) {
// Retry playback with TCP if no sample has been received so far.
if (!hasRetriedWithRtpTcp) {
if (!isUsingRtpTcp) {
// Retry playback with TCP if no sample has been received so far, and we are not already
// using TCP. Retrying will setup new loadables, so will not retry with the current
// loadables.
retryWithRtpTcp();
hasRetriedWithRtpTcp = true;
isUsingRtpTcp = true;
}
// Don't retry with the current UDP backed loadables.
return Loader.DONT_RETRY;
}
@ -685,6 +686,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
RtspMediaTrack mediaTrack, int trackId, RtpDataChannel.Factory rtpDataChannelFactory) {
this.mediaTrack = mediaTrack;
// This listener runs on the playback thread, posted by the Loader thread.
RtpDataLoadable.EventListener transportEventListener =
(transport, rtpDataChannel) -> {
RtpLoadInfo.this.transport = transport;
@ -695,8 +697,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
if (interleavedBinaryDataListener != null) {
rtspClient.registerInterleavedDataChannel(
rtpDataChannel.getLocalPort(), interleavedBinaryDataListener);
isUsingRtpTcp = true;
}
maybeSetupTracks();
};

View File

@ -58,6 +58,24 @@ public final class RtspMediaSource extends BaseMediaSource {
*/
public static final class Factory implements MediaSourceFactory {
private boolean forceUseRtpTcp;
/**
* Sets whether to force using TCP as the default RTP transport.
*
* <p>The default value is {@code false}, the source will first try streaming RTSP with UDP. If
* no data is received on the UDP channel (for instance, when streaming behind a NAT) for a
* while, the source will switch to streaming using TCP. If this value is set to {@code true},
* the source will always use TCP for streaming.
*
* @param forceUseRtpTcp Whether force to use TCP for streaming.
* @return This Factory, for convenience.
*/
public Factory setForceUseRtpTcp(boolean forceUseRtpTcp) {
this.forceUseRtpTcp = forceUseRtpTcp;
return this;
}
/** Does nothing. {@link RtspMediaSource} does not support DRM. */
@Override
public Factory setDrmSessionManagerProvider(
@ -122,7 +140,11 @@ public final class RtspMediaSource extends BaseMediaSource {
@Override
public RtspMediaSource createMediaSource(MediaItem mediaItem) {
checkNotNull(mediaItem.playbackProperties);
return new RtspMediaSource(mediaItem);
return new RtspMediaSource(
mediaItem,
forceUseRtpTcp
? new TransferRtpDataChannelFactory()
: new UdpDataSourceRtpDataChannelFactory());
}
}
@ -148,9 +170,9 @@ public final class RtspMediaSource extends BaseMediaSource {
@Nullable private ImmutableList<RtspMediaTrack> rtspMediaTracks;
@Nullable private IOException sourcePrepareException;
private RtspMediaSource(MediaItem mediaItem) {
private RtspMediaSource(MediaItem mediaItem, RtpDataChannel.Factory rtpDataChannelFactory) {
this.mediaItem = mediaItem;
rtpDataChannelFactory = new UdpDataSourceRtpDataChannelFactory();
this.rtpDataChannelFactory = rtpDataChannelFactory;
}
@Override