diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 29d225bda92..e72169a16ee 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -63,8 +63,11 @@ `Player.EVENT_STATIC_METADATA_CHANGED`. Use `Player.getMediaMetadata`, `Player.Listener.onMediaMetadataChanged` and `Player.EVENT_MEDIA_METADATA_CHANGED` for convenient access to - structured metadata, or access the raw static metadata directly from - the `TrackSelection#getFormat()`. + structured metadata, or access the raw static metadata directly from the + `TrackSelection#getFormat()`. +* RTSP: + * Handle when additional spaces are in SDP's RTPMAP atrribute + ([#9379](https://github.com/google/ExoPlayer/issues/9379)). ### 2.15.0 (2021-08-10) diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/MediaDescription.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/MediaDescription.java index 0a7d87436c4..755a32f8a6b 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/MediaDescription.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/MediaDescription.java @@ -43,11 +43,11 @@ public static final class RtpMapAttribute { /** Parses the RTPMAP attribute value (with the part "a=rtpmap:" removed). */ public static RtpMapAttribute parse(String rtpmapString) throws ParserException { - String[] rtpmapInfo = Util.split(rtpmapString, " "); + String[] rtpmapInfo = Util.splitAtFirst(rtpmapString, " "); checkArgument(rtpmapInfo.length == 2); int payloadType = parseInt(rtpmapInfo[0]); - String[] mediaInfo = Util.split(rtpmapInfo[1], "/"); + String[] mediaInfo = Util.split(rtpmapInfo[1].trim(), "/"); checkArgument(mediaInfo.length >= 2); int clockRate = parseInt(mediaInfo[1]); int encodingParameters = C.INDEX_UNSET; diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMediaTrack.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMediaTrack.java index 2f6a3c3c01c..cdd8e0b820c 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMediaTrack.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMediaTrack.java @@ -18,7 +18,6 @@ import static com.google.android.exoplayer2.source.rtsp.MediaDescription.MEDIA_TYPE_AUDIO; import static com.google.android.exoplayer2.source.rtsp.RtpPayloadFormat.getMimeTypeFromRtpMediaType; import static com.google.android.exoplayer2.source.rtsp.SessionDescription.ATTR_CONTROL; -import static com.google.android.exoplayer2.source.rtsp.SessionDescription.ATTR_RTPMAP; import static com.google.android.exoplayer2.util.Assertions.checkArgument; import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import static com.google.android.exoplayer2.util.NalUnitUtil.NAL_START_CODE; @@ -95,13 +94,6 @@ public int hashCode() { formatBuilder.setAverageBitrate(mediaDescription.bitrate); } - // rtpmap is mandatory in an RTSP session with dynamic payload types (RFC2326 Section C.1.3). - checkArgument(mediaDescription.attributes.containsKey(ATTR_RTPMAP)); - String rtpmapAttribute = castNonNull(mediaDescription.attributes.get(ATTR_RTPMAP)); - - // rtpmap string format: RFC2327 Page 22. - String[] rtpmap = Util.split(rtpmapAttribute, " "); - checkArgument(rtpmap.length == 2); int rtpPayloadType = mediaDescription.rtpMapAttribute.payloadType; String mimeType = getMimeTypeFromRtpMediaType(mediaDescription.rtpMapAttribute.mediaEncoding); diff --git a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/SessionDescriptionTest.java b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/SessionDescriptionTest.java index d71976148df..cd2f6c3266f 100644 --- a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/SessionDescriptionTest.java +++ b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/SessionDescriptionTest.java @@ -191,6 +191,25 @@ public void parse_sdpStringWithDuplicatedSessionAttribute_recordsTheMostRecentVa assertThat(sessionDescription.attributes).containsEntry(ATTR_CONTROL, "session1"); } + @Test + public void parse_sdpStringWithExtraSpaceInRtpMapAttribute_succeeds() throws Exception { + String testMediaSdpInfo = + "v=0\r\n" + + "o=MNobody 2890844526 2890842807 IN IP4 192.0.2.46\r\n" + + "s=SDP Seminar\r\n" + + "t=0 0\r\n" + + "a=control:*\r\n" + + "m=audio 3456 RTP/AVP 0\r\n" + + "a=rtpmap:97 AC3/44100 \r\n"; + + SessionDescription sessionDescription = SessionDescriptionParser.parse(testMediaSdpInfo); + MediaDescription.RtpMapAttribute rtpMapAttribute = + sessionDescription.mediaDescriptionList.get(0).rtpMapAttribute; + assertThat(rtpMapAttribute.payloadType).isEqualTo(97); + assertThat(rtpMapAttribute.mediaEncoding).isEqualTo("AC3"); + assertThat(rtpMapAttribute.clockRate).isEqualTo(44100); + } + @Test public void buildMediaDescription_withInvalidRtpmapAttribute_throwsIllegalStateException() { assertThrows(