diff --git a/RELEASENOTES.md b/RELEASENOTES.md index c08799302d..6b28d6b1ba 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -116,6 +116,8 @@ ([#9416](https://github.com/google/ExoPlayer/issues/9416)). * Fix RTSP WWW-Authenticate header parsing ([#9428](https://github.com/google/ExoPlayer/issues/9428)). + * Support RFC4566 SDP attribute field grammar + ([#9430](https://github.com/google/ExoPlayer/issues/9430)). * Extractors: * ID3: Fix issue decoding ID3 tags containing UTF-16 encoded strings ([#9087](https://github.com/google/ExoPlayer/issues/9087)). diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/SessionDescriptionParser.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/SessionDescriptionParser.java index 6d37b12c89..d85dd216db 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/SessionDescriptionParser.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/SessionDescriptionParser.java @@ -34,8 +34,11 @@ import java.util.regex.Pattern; // under the given tag follows an optional space. private static final Pattern SDP_LINE_PATTERN = Pattern.compile("([a-z])=\\s?(.+)"); // Matches an attribute line (with a= sdp tag removed. Example: range:npt=0-50.0). - // Attribute can also be a flag, i.e. without a value, like recvonly. - private static final Pattern ATTRIBUTE_PATTERN = Pattern.compile("([0-9A-Za-z-]+)(?::(.*))?"); + // Attribute can also be a flag, i.e. without a value, like recvonly. Reference RFC4566 Section 9 + // Page 43, under "token-char". + private static final Pattern ATTRIBUTE_PATTERN = + Pattern.compile( + "([\\x21\\x23-\\x27\\x2a\\x2b\\x2d\\x2e\\x30-\\x39\\x41-\\x5a\\x5e-\\x7e]+)(?::(.*))?"); // SDP media description line: // For instance: audio 0 RTP/AVP 97 private static final Pattern MEDIA_DESCRIPTION_PATTERN = 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 cd2f6c3266..d28b0b902e 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 @@ -170,6 +170,24 @@ public class SessionDescriptionTest { .containsEntry(ATTR_CONTROL, "audio"); } + @Test + public void parse_sdpStringWithSpecialAttributeField_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" + + "i=A Seminar on the session description protocol\r\n" + + "m=audio 3456 RTP/AVP 0\r\n" + + "a=rtpmap:97 AC3/44100\r\n" + + "a=A!#$%&'*+-.^_`{|}~:special\r\n"; + + SessionDescription sessionDescription = SessionDescriptionParser.parse(testMediaSdpInfo); + + assertThat(sessionDescription.mediaDescriptionList.get(0).attributes) + .containsEntry("A!#$%&'*+-.^_`{|}~", "special"); + } + @Test public void parse_sdpStringWithDuplicatedSessionAttribute_recordsTheMostRecentValue() throws Exception {