mirror of
https://github.com/samsonjs/media.git
synced 2026-03-29 10:05:48 +00:00
Handle RTSP 301/302 redirection.
PiperOrigin-RevId: 396303242
This commit is contained in:
parent
76014cf0e9
commit
ff7dcbd6f2
4 changed files with 82 additions and 9 deletions
|
|
@ -101,8 +101,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||
|
||||
private final SessionInfoListener sessionInfoListener;
|
||||
private final PlaybackEventListener playbackEventListener;
|
||||
private final Uri uri;
|
||||
@Nullable private final RtspAuthUserInfo rtspAuthUserInfo;
|
||||
private final String userAgent;
|
||||
private final boolean debugLoggingEnabled;
|
||||
private final ArrayDeque<RtpLoadInfo> pendingSetupRtpLoadInfos;
|
||||
|
|
@ -110,7 +108,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||
private final SparseArray<RtspRequest> pendingRequests;
|
||||
private final MessageSender messageSender;
|
||||
|
||||
/** RTSP session URI. */
|
||||
private Uri uri;
|
||||
|
||||
private RtspMessageChannel messageChannel;
|
||||
@Nullable private RtspAuthUserInfo rtspAuthUserInfo;
|
||||
@Nullable private String sessionId;
|
||||
@Nullable private KeepAliveMonitor keepAliveMonitor;
|
||||
@Nullable private RtspAuthenticationInfo rtspAuthenticationInfo;
|
||||
|
|
@ -140,15 +142,15 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||
boolean debugLoggingEnabled) {
|
||||
this.sessionInfoListener = sessionInfoListener;
|
||||
this.playbackEventListener = playbackEventListener;
|
||||
this.uri = RtspMessageUtil.removeUserInfo(uri);
|
||||
this.rtspAuthUserInfo = RtspMessageUtil.parseUserInfo(uri);
|
||||
this.userAgent = userAgent;
|
||||
this.debugLoggingEnabled = debugLoggingEnabled;
|
||||
pendingSetupRtpLoadInfos = new ArrayDeque<>();
|
||||
pendingRequests = new SparseArray<>();
|
||||
messageSender = new MessageSender();
|
||||
pendingSeekPositionUs = C.TIME_UNSET;
|
||||
messageChannel = new RtspMessageChannel(new MessageListener());
|
||||
this.pendingSetupRtpLoadInfos = new ArrayDeque<>();
|
||||
this.pendingRequests = new SparseArray<>();
|
||||
this.messageSender = new MessageSender();
|
||||
this.uri = RtspMessageUtil.removeUserInfo(uri);
|
||||
this.messageChannel = new RtspMessageChannel(new MessageListener());
|
||||
this.rtspAuthUserInfo = RtspMessageUtil.parseUserInfo(uri);
|
||||
this.pendingSeekPositionUs = C.TIME_UNSET;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -482,6 +484,20 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||
switch (response.status) {
|
||||
case 200:
|
||||
break;
|
||||
case 301:
|
||||
case 302:
|
||||
// Redirection request.
|
||||
@Nullable String redirectionUriString = response.headers.get(RtspHeaders.LOCATION);
|
||||
if (redirectionUriString == null) {
|
||||
sessionInfoListener.onSessionTimelineRequestFailed(
|
||||
"Redirection without new location.", /* cause= */ null);
|
||||
} else {
|
||||
Uri redirectionUri = Uri.parse(redirectionUriString);
|
||||
RtspClient.this.uri = RtspMessageUtil.removeUserInfo(redirectionUri);
|
||||
RtspClient.this.rtspAuthUserInfo = RtspMessageUtil.parseUserInfo(redirectionUri);
|
||||
messageSender.sendDescribeRequest(RtspClient.this.uri, RtspClient.this.sessionId);
|
||||
}
|
||||
return;
|
||||
case 401:
|
||||
if (rtspAuthUserInfo != null && !receivedAuthorizationRequest) {
|
||||
// Unauthorized.
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ import java.util.Map;
|
|||
public static final String CSEQ = "CSeq";
|
||||
public static final String DATE = "Date";
|
||||
public static final String EXPIRES = "Expires";
|
||||
public static final String LOCATION = "Location";
|
||||
public static final String PROXY_AUTHENTICATE = "Proxy-Authenticate";
|
||||
public static final String PROXY_REQUIRE = "Proxy-Require";
|
||||
public static final String PUBLIC = "Public";
|
||||
|
|
@ -251,6 +252,8 @@ import java.util.Map;
|
|||
return DATE;
|
||||
} else if (Ascii.equalsIgnoreCase(messageHeaderName, EXPIRES)) {
|
||||
return EXPIRES;
|
||||
} else if (Ascii.equalsIgnoreCase(messageHeaderName, LOCATION)) {
|
||||
return LOCATION;
|
||||
} else if (Ascii.equalsIgnoreCase(messageHeaderName, PROXY_AUTHENTICATE)) {
|
||||
return PROXY_AUTHENTICATE;
|
||||
} else if (Ascii.equalsIgnoreCase(messageHeaderName, PROXY_REQUIRE)) {
|
||||
|
|
|
|||
|
|
@ -462,6 +462,10 @@ import java.util.regex.Pattern;
|
|||
switch (statusCode) {
|
||||
case 200:
|
||||
return "OK";
|
||||
case 301:
|
||||
return "Move Permanently";
|
||||
case 302:
|
||||
return "Move Temporarily";
|
||||
case 400:
|
||||
return "Bad Request";
|
||||
case 401:
|
||||
|
|
|
|||
|
|
@ -120,6 +120,56 @@ public final class RtspClientTest {
|
|||
assertThat(tracksInSession.get()).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void connectServerAndClient_describeRedirects_updatesSessionTimeline() throws Exception {
|
||||
class ResponseProvider implements RtspServer.ResponseProvider {
|
||||
@Override
|
||||
public RtspResponse getOptionsResponse() {
|
||||
return new RtspResponse(/* status= */ 200, RtspHeaders.EMPTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RtspResponse getDescribeResponse(Uri requestedUri) {
|
||||
if (!requestedUri.getPath().contains("redirect")) {
|
||||
return new RtspResponse(
|
||||
301,
|
||||
new RtspHeaders.Builder()
|
||||
.add(
|
||||
RtspHeaders.LOCATION,
|
||||
requestedUri.buildUpon().appendEncodedPath("redirect").build().toString())
|
||||
.build());
|
||||
}
|
||||
|
||||
return RtspTestUtils.newDescribeResponseWithSdpMessage(
|
||||
SESSION_DESCRIPTION, rtpPacketStreamDumps, requestedUri);
|
||||
}
|
||||
}
|
||||
rtspServer = new RtspServer(new ResponseProvider());
|
||||
|
||||
AtomicReference<ImmutableList<RtspMediaTrack>> tracksInSession = new AtomicReference<>();
|
||||
rtspClient =
|
||||
new RtspClient(
|
||||
new SessionInfoListener() {
|
||||
@Override
|
||||
public void onSessionTimelineUpdated(
|
||||
RtspSessionTiming timing, ImmutableList<RtspMediaTrack> tracks) {
|
||||
tracksInSession.set(tracks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSessionTimelineRequestFailed(
|
||||
String message, @Nullable Throwable cause) {}
|
||||
},
|
||||
EMPTY_PLAYBACK_LISTENER,
|
||||
/* userAgent= */ "ExoPlayer:RtspClientTest",
|
||||
RtspTestUtils.getTestUri(rtspServer.startAndGetPortNumber()),
|
||||
/* debugLoggingEnabled= */ false);
|
||||
rtspClient.start();
|
||||
RobolectricUtil.runMainLooperUntil(() -> tracksInSession.get() != null);
|
||||
|
||||
assertThat(tracksInSession.get()).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void
|
||||
connectServerAndClient_serverSupportsDescribeNoHeaderInOptions_updatesSessionTimeline()
|
||||
|
|
|
|||
Loading…
Reference in a new issue