Ignore mandatory SDP fields as ExoPlayer doesn't use them

Issue: google/ExoPlayer#10049
PiperOrigin-RevId: 444833508
This commit is contained in:
claincly 2022-04-27 13:56:01 +01:00 committed by Ian Baker
parent e414f0d2ac
commit 7af91fc9d5
4 changed files with 61 additions and 22 deletions

View File

@ -77,6 +77,8 @@
([#56](https://github.com/androidx/media/pull/56)). ([#56](https://github.com/androidx/media/pull/56)).
* Fix RTSP basic authorization header. * Fix RTSP basic authorization header.
([#9544](https://github.com/google/ExoPlayer/issues/9544)). ([#9544](https://github.com/google/ExoPlayer/issues/9544)).
* Stop checking mandatory SDP fields as ExoPlayer doesn't need them
([#10049](https://github.com/google/ExoPlayer/issues/10049)).
* Throw checked exception when parsing RTSP timing * Throw checked exception when parsing RTSP timing
([#10165](https://github.com/google/ExoPlayer/issues/10165)). ([#10165](https://github.com/google/ExoPlayer/issues/10165)).
* Session: * Session:

View File

@ -201,13 +201,8 @@ import java.util.HashMap;
* Builds a new {@link SessionDescription} instance. * Builds a new {@link SessionDescription} instance.
* *
* @return The newly built {@link SessionDescription} instance. * @return The newly built {@link SessionDescription} instance.
* @throws IllegalStateException When one or more of {@link #sessionName}, {@link #timing} and
* {@link #origin} is not set.
*/ */
public SessionDescription build() { public SessionDescription build() {
if (sessionName == null || origin == null || timing == null) {
throw new IllegalStateException("One of more mandatory SDP fields are not set.");
}
return new SessionDescription(this); return new SessionDescription(this);
} }
} }
@ -239,11 +234,11 @@ import java.util.HashMap;
*/ */
public final ImmutableList<MediaDescription> mediaDescriptionList; public final ImmutableList<MediaDescription> mediaDescriptionList;
/** The name of a session. */ /** The name of a session. */
public final String sessionName; @Nullable public final String sessionName;
/** The origin sender info. */ /** The origin sender info. */
public final String origin; @Nullable public final String origin;
/** The timing info. */ /** The timing info. */
public final String timing; @Nullable public final String timing;
/** The estimated bitrate in bits per seconds. */ /** The estimated bitrate in bits per seconds. */
public final int bitrate; public final int bitrate;
/** The uri of a linked content. */ /** The uri of a linked content. */
@ -287,9 +282,9 @@ import java.util.HashMap;
return bitrate == that.bitrate return bitrate == that.bitrate
&& attributes.equals(that.attributes) && attributes.equals(that.attributes)
&& mediaDescriptionList.equals(that.mediaDescriptionList) && mediaDescriptionList.equals(that.mediaDescriptionList)
&& origin.equals(that.origin) && Util.areEqual(origin, that.origin)
&& sessionName.equals(that.sessionName) && Util.areEqual(sessionName, that.sessionName)
&& timing.equals(that.timing) && Util.areEqual(timing, that.timing)
&& Util.areEqual(sessionInfo, that.sessionInfo) && Util.areEqual(sessionInfo, that.sessionInfo)
&& Util.areEqual(uri, that.uri) && Util.areEqual(uri, that.uri)
&& Util.areEqual(emailAddress, that.emailAddress) && Util.areEqual(emailAddress, that.emailAddress)
@ -303,9 +298,9 @@ import java.util.HashMap;
int result = 7; int result = 7;
result = 31 * result + attributes.hashCode(); result = 31 * result + attributes.hashCode();
result = 31 * result + mediaDescriptionList.hashCode(); result = 31 * result + mediaDescriptionList.hashCode();
result = 31 * result + origin.hashCode(); result = 31 * result + (origin == null ? 0 : origin.hashCode());
result = 31 * result + sessionName.hashCode(); result = 31 * result + (sessionName == null ? 0 : sessionName.hashCode());
result = 31 * result + timing.hashCode(); result = 31 * result + (timing == null ? 0 : timing.hashCode());
result = 31 * result + bitrate; result = 31 * result + bitrate;
result = 31 * result + (sessionInfo == null ? 0 : sessionInfo.hashCode()); result = 31 * result + (sessionInfo == null ? 0 : sessionInfo.hashCode());
result = 31 * result + (uri == null ? 0 : uri.hashCode()); result = 31 * result + (uri == null ? 0 : uri.hashCode());

View File

@ -19,7 +19,6 @@ import static com.google.common.truth.Truth.assertThat;
import android.net.Uri; import android.net.Uri;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.media3.common.ParserException;
import androidx.media3.common.util.Util; import androidx.media3.common.util.Util;
import androidx.media3.exoplayer.rtsp.RtspClient.PlaybackEventListener; import androidx.media3.exoplayer.rtsp.RtspClient.PlaybackEventListener;
import androidx.media3.exoplayer.rtsp.RtspClient.SessionInfoListener; import androidx.media3.exoplayer.rtsp.RtspClient.SessionInfoListener;
@ -345,7 +344,7 @@ public final class RtspClientTest {
} }
@Test @Test
public void connectServerAndClient_malformedSdpInDescribeResponse_doesNotUpdateTimeline() public void connectServerAndClient_sdpInDescribeResponseHasNoTracks_doesNotUpdateTimeline()
throws Exception { throws Exception {
class ResponseProvider implements RtspServer.ResponseProvider { class ResponseProvider implements RtspServer.ResponseProvider {
@Override @Override
@ -357,14 +356,16 @@ public final class RtspClientTest {
@Override @Override
public RtspResponse getDescribeResponse(Uri requestedUri, RtspHeaders headers) { public RtspResponse getDescribeResponse(Uri requestedUri, RtspHeaders headers) {
// This session description misses required the o, t and s tags.
return RtspTestUtils.newDescribeResponseWithSdpMessage( return RtspTestUtils.newDescribeResponseWithSdpMessage(
/* sessionDescription= */ "v=0\r\n", rtpPacketStreamDumps, requestedUri); /* sessionDescription= */ "v=0\r\n",
// This session description has no tracks.
/* rtpPacketStreamDumps= */ ImmutableList.of(),
requestedUri);
} }
} }
rtspServer = new RtspServer(new ResponseProvider()); rtspServer = new RtspServer(new ResponseProvider());
AtomicReference<Throwable> failureCause = new AtomicReference<>(); AtomicBoolean timelineRequestFailed = new AtomicBoolean();
rtspClient = rtspClient =
new RtspClient( new RtspClient(
new SessionInfoListener() { new SessionInfoListener() {
@ -375,7 +376,7 @@ public final class RtspClientTest {
@Override @Override
public void onSessionTimelineRequestFailed( public void onSessionTimelineRequestFailed(
String message, @Nullable Throwable cause) { String message, @Nullable Throwable cause) {
failureCause.set(cause); timelineRequestFailed.set(true);
} }
}, },
EMPTY_PLAYBACK_LISTENER, EMPTY_PLAYBACK_LISTENER,
@ -385,8 +386,7 @@ public final class RtspClientTest {
/* debugLoggingEnabled= */ false); /* debugLoggingEnabled= */ false);
rtspClient.start(); rtspClient.start();
RobolectricUtil.runMainLooperUntil(() -> failureCause.get() != null); RobolectricUtil.runMainLooperUntil(timelineRequestFailed::get);
assertThat(failureCause.get()).hasCauseThat().isInstanceOf(ParserException.class);
assertThat(rtspClient.getState()).isEqualTo(RtspClient.RTSP_STATE_UNINITIALIZED); assertThat(rtspClient.getState()).isEqualTo(RtspClient.RTSP_STATE_UNINITIALIZED);
} }
} }

View File

@ -85,6 +85,48 @@ public class SessionDescriptionTest {
assertThat(sessionDescription).isEqualTo(expectedSession); assertThat(sessionDescription).isEqualTo(expectedSession);
} }
@Test
public void parse_sdpStringWithoutMandatoryFields_succeeds() throws Exception {
// This SDP string is similar to the one in parse_sdpString_succeeds(), it doesn't include the
// mandatory SDP fields origin, session name, session info and timing.
String testMediaSdpInfo =
"v=0\r\n"
+ "u=http://www.example.com/lectures/sdp.ps\r\n"
+ "e=seminar@example.com (Seminar Management)\r\n"
+ "c=IN IP4 0.0.0.0\r\n"
+ "a=control:*\r\n"
+ "m=audio 3456 RTP/AVP 0\r\n"
+ "a=control:audio\r\n"
+ "a=rtpmap:0 PCMU/8000\r\n"
+ "a=3GPP-Adaption-Support:1\r\n"
+ "m=video 2232 RTP/AVP 31\r\n"
+ "a=control:video\r\n"
+ "a=rtpmap:31 H261/90000\r\n";
SessionDescription sessionDescription = SessionDescriptionParser.parse(testMediaSdpInfo);
SessionDescription expectedSession =
new SessionDescription.Builder()
.setUri(Uri.parse("http://www.example.com/lectures/sdp.ps"))
.setEmailAddress("seminar@example.com (Seminar Management)")
.setConnection("IN IP4 0.0.0.0")
.addAttribute(ATTR_CONTROL, "*")
.addMediaDescription(
new MediaDescription.Builder(MEDIA_TYPE_AUDIO, 3456, RTP_AVP_PROFILE, 0)
.addAttribute(ATTR_CONTROL, "audio")
.addAttribute(ATTR_RTPMAP, "0 PCMU/8000")
.addAttribute("3GPP-Adaption-Support", "1")
.build())
.addMediaDescription(
new MediaDescription.Builder(MEDIA_TYPE_VIDEO, 2232, RTP_AVP_PROFILE, 31)
.addAttribute(ATTR_CONTROL, "video")
.addAttribute(ATTR_RTPMAP, "31 H261/90000")
.build())
.build();
assertThat(sessionDescription).isEqualTo(expectedSession);
}
@Test @Test
public void parse_sdpString2_succeeds() throws Exception { public void parse_sdpString2_succeeds() throws Exception {
String testMediaSdpInfo = String testMediaSdpInfo =