diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 5c0148529b..adbc82753a 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -43,8 +43,8 @@ `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()`. * Remove deprecated symbols: * Remove `Player.getPlaybackError`. Use `Player.getPlayerError` instead. * Remove `Player.getCurrentTag`. Use `Player.getCurrentMediaItem` and @@ -115,6 +115,9 @@ * Deprecate `setControlDispatcher` in `LeanbackPlayerAdapter`. * Media2 extension: * Deprecate `setControlDispatcher` in `SessionPlayerConnector`. +* RTSP: + * Use standard RTSP header names. + ([#9182](https://github.com/google/ExoPlayer/issues/9182)). ### 2.14.2 (2021-07-20) diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspHeaders.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspHeaders.java index 13dc5e4b60..12c980a1a3 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspHeaders.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspHeaders.java @@ -34,37 +34,37 @@ import java.util.Map; */ /* package */ final class RtspHeaders { - public static final String ACCEPT = "accept"; - public static final String ALLOW = "allow"; - public static final String AUTHORIZATION = "authorization"; - public static final String BANDWIDTH = "bandwidth"; - public static final String BLOCKSIZE = "blocksize"; - public static final String CACHE_CONTROL = "cache-control"; - public static final String CONNECTION = "connection"; - public static final String CONTENT_BASE = "content-base"; - public static final String CONTENT_ENCODING = "content-encoding"; - public static final String CONTENT_LANGUAGE = "content-language"; - public static final String CONTENT_LENGTH = "content-length"; - public static final String CONTENT_LOCATION = "content-location"; - public static final String CONTENT_TYPE = "content-type"; - public static final String CSEQ = "cseq"; - public static final String DATE = "date"; - public static final String EXPIRES = "expires"; - public static final String PROXY_AUTHENTICATE = "proxy-authenticate"; - public static final String PROXY_REQUIRE = "proxy-require"; - public static final String PUBLIC = "public"; - public static final String RANGE = "range"; - public static final String RTP_INFO = "rtp-info"; - public static final String RTCP_INTERVAL = "rtcp-interval"; - public static final String SCALE = "scale"; - public static final String SESSION = "session"; - public static final String SPEED = "speed"; - public static final String SUPPORTED = "supported"; - public static final String TIMESTAMP = "timestamp"; - public static final String TRANSPORT = "transport"; - public static final String USER_AGENT = "user-agent"; - public static final String VIA = "via"; - public static final String WWW_AUTHENTICATE = "www-authenticate"; + public static final String ACCEPT = "Accept"; + public static final String ALLOW = "Allow"; + public static final String AUTHORIZATION = "Authorization"; + public static final String BANDWIDTH = "Bandwidth"; + public static final String BLOCKSIZE = "Blocksize"; + public static final String CACHE_CONTROL = "Cache-Control"; + public static final String CONNECTION = "Connection"; + public static final String CONTENT_BASE = "Content-Base"; + public static final String CONTENT_ENCODING = "Content-Encoding"; + public static final String CONTENT_LANGUAGE = "Content-Language"; + public static final String CONTENT_LENGTH = "Content-Length"; + public static final String CONTENT_LOCATION = "Content-Location"; + public static final String CONTENT_TYPE = "Content-Type"; + public static final String CSEQ = "CSeq"; + public static final String DATE = "Date"; + public static final String EXPIRES = "Expires"; + public static final String PROXY_AUTHENTICATE = "Proxy-Authenticate"; + public static final String PROXY_REQUIRE = "Proxy-Require"; + public static final String PUBLIC = "Public"; + public static final String RANGE = "Range"; + public static final String RTP_INFO = "RTP-Info"; + public static final String RTCP_INTERVAL = "RTCP-Interval"; + public static final String SCALE = "Scale"; + public static final String SESSION = "Session"; + public static final String SPEED = "Speed"; + public static final String SUPPORTED = "Supported"; + public static final String TIMESTAMP = "Timestamp"; + public static final String TRANSPORT = "Transport"; + public static final String USER_AGENT = "User-Agent"; + public static final String VIA = "Via"; + public static final String WWW_AUTHENTICATE = "WWW-Authenticate"; /** An empty header object. */ public static final RtspHeaders EMPTY = new RtspHeaders.Builder().build(); @@ -96,7 +96,7 @@ import java.util.Map; * @return This builder. */ public Builder add(String headerName, String headerValue) { - namesAndValuesBuilder.put(Ascii.toLowerCase(headerName.trim()), headerValue.trim()); + namesAndValuesBuilder.put(convertToStandardHeaderName(headerName.trim()), headerValue.trim()); return this; } @@ -194,10 +194,77 @@ import java.util.Map; * list is empty if the header name is not recorded. */ public ImmutableList values(String headerName) { - return namesAndValues.get(Ascii.toLowerCase(headerName)); + return namesAndValues.get(convertToStandardHeaderName(headerName)); } private RtspHeaders(Builder builder) { this.namesAndValues = builder.namesAndValuesBuilder.build(); } + + private static String convertToStandardHeaderName(String messageHeaderName) { + if (Ascii.equalsIgnoreCase(messageHeaderName, ACCEPT)) { + return ACCEPT; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, ALLOW)) { + return ALLOW; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, AUTHORIZATION)) { + return AUTHORIZATION; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, BANDWIDTH)) { + return BANDWIDTH; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, BLOCKSIZE)) { + return BLOCKSIZE; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, CACHE_CONTROL)) { + return CACHE_CONTROL; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, CONNECTION)) { + return CONNECTION; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, CONTENT_BASE)) { + return CONTENT_BASE; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, CONTENT_ENCODING)) { + return CONTENT_ENCODING; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, CONTENT_LANGUAGE)) { + return CONTENT_LANGUAGE; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, CONTENT_LENGTH)) { + return CONTENT_LENGTH; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, CONTENT_LOCATION)) { + return CONTENT_LOCATION; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, CONTENT_TYPE)) { + return CONTENT_TYPE; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, CSEQ)) { + return CSEQ; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, DATE)) { + return DATE; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, EXPIRES)) { + return EXPIRES; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, PROXY_AUTHENTICATE)) { + return PROXY_AUTHENTICATE; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, PROXY_REQUIRE)) { + return PROXY_REQUIRE; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, PUBLIC)) { + return PUBLIC; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, RANGE)) { + return RANGE; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, RTP_INFO)) { + return RTP_INFO; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, RTCP_INTERVAL)) { + return RTCP_INTERVAL; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, SCALE)) { + return SCALE; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, SESSION)) { + return SESSION; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, SPEED)) { + return SPEED; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, SUPPORTED)) { + return SUPPORTED; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, TIMESTAMP)) { + return TIMESTAMP; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, TRANSPORT)) { + return TRANSPORT; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, USER_AGENT)) { + return USER_AGENT; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, VIA)) { + return VIA; + } else if (Ascii.equalsIgnoreCase(messageHeaderName, WWW_AUTHENTICATE)) { + return WWW_AUTHENTICATE; + } + return messageHeaderName; + } } diff --git a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspHeadersTest.java b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspHeadersTest.java index 72dc0611e7..9c642729c6 100644 --- a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspHeadersTest.java +++ b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspHeadersTest.java @@ -160,10 +160,10 @@ public final class RtspHeadersTest { .build(); assertThat(headers.asMultiMap()) .containsExactly( - "accept", "application/sdp", - "cseq", "3", - "content-length", "707", - "transport", "RTP/AVP;unicast;client_port=65458-65459"); + "Accept", "application/sdp", + "CSeq", "3", + "Content-Length", "707", + "Transport", "RTP/AVP;unicast;client_port=65458-65459"); } @Test @@ -182,14 +182,16 @@ public final class RtspHeadersTest { .build(); ListMultimap headersMap = headers.asMultiMap(); - assertThat(headersMap.keySet()).containsExactly("accept", "cseq", "transport").inOrder(); + assertThat(headersMap.keySet()) + .containsExactly(RtspHeaders.ACCEPT, RtspHeaders.CSEQ, RtspHeaders.TRANSPORT) + .inOrder(); assertThat(headersMap) - .valuesForKey("accept") + .valuesForKey(RtspHeaders.ACCEPT) .containsExactly("application/sdp", "application/sip") .inOrder(); - assertThat(headersMap).valuesForKey("cseq").containsExactly("3", "5").inOrder(); + assertThat(headersMap).valuesForKey(RtspHeaders.CSEQ).containsExactly("3", "5").inOrder(); assertThat(headersMap) - .valuesForKey("transport") + .valuesForKey(RtspHeaders.TRANSPORT) .containsExactly( "RTP/AVP;unicast;client_port=65456-65457", "RTP/AVP;unicast;client_port=65458-65459") .inOrder(); diff --git a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMessageChannelTest.java b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMessageChannelTest.java index eb1a4d5894..7e559b31a9 100644 --- a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMessageChannelTest.java +++ b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMessageChannelTest.java @@ -149,26 +149,26 @@ public final class RtspMessageChannelTest { assertThat(receivedRtspResponses) .containsExactly( /* optionsResponse */ - ImmutableList.of("RTSP/1.0 200 OK", "cseq: 2", "public: OPTIONS", ""), + ImmutableList.of("RTSP/1.0 200 OK", "CSeq: 2", "Public: OPTIONS", ""), /* describeResponse */ ImmutableList.of( "RTSP/1.0 200 OK", - "cseq: 3", - "content-type: application/sdp", - "content-length: 28", + "CSeq: 3", + "Content-Type: application/sdp", + "Content-Length: 28", "", "v=安卓アンドロイド"), /* describeResponse2 */ ImmutableList.of( "RTSP/1.0 200 OK", - "cseq: 4", - "content-type: application/sdp", - "content-length: 73", + "CSeq: 4", + "Content-Type: application/sdp", + "Content-Length: 73", "", "v=安卓アンドロイド\n" + "o=test 2890844526 2890842807 IN IP4 127.0.0.1"), /* setupResponse */ ImmutableList.of( - "RTSP/1.0 200 OK", "cseq: 5", "transport: RTP/AVP/TCP;unicast;interleaved=0-1", "")) + "RTSP/1.0 200 OK", "CSeq: 5", "Transport: RTP/AVP/TCP;unicast;interleaved=0-1", "")) .inOrder(); assertThat(receivedInterleavedData) .containsExactly( diff --git a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMessageUtilTest.java b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMessageUtilTest.java index d326586844..0e9a3aaf74 100644 --- a/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMessageUtilTest.java +++ b/library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMessageUtilTest.java @@ -147,10 +147,12 @@ public final class RtspMessageUtilTest { assertThat(response.status).isEqualTo(401); - assertThat(headersMap.keySet()).containsExactly("cseq", "www-authenticate").inOrder(); - assertThat(headersMap).valuesForKey("cseq").containsExactly("3"); + assertThat(headersMap.keySet()) + .containsExactly(RtspHeaders.CSEQ, RtspHeaders.WWW_AUTHENTICATE) + .inOrder(); + assertThat(headersMap).valuesForKey(RtspHeaders.CSEQ).containsExactly("3"); assertThat(headersMap) - .valuesForKey("www-authenticate") + .valuesForKey(RtspHeaders.WWW_AUTHENTICATE) .containsExactly("BASIC realm=\"wow\"", "DIGEST realm=\"wow\", nonce=\"nonce\"") .inOrder(); @@ -221,14 +223,14 @@ public final class RtspMessageUtilTest { List expectedLines = Arrays.asList( "SETUP rtsp://127.0.0.1/test.mkv/track1 RTSP/1.0", - "cseq: 4", - "transport: RTP/AVP;unicast;client_port=65458-65459", + "CSeq: 4", + "Transport: RTP/AVP;unicast;client_port=65458-65459", "", ""); String expectedRtspMessage = "SETUP rtsp://127.0.0.1/test.mkv/track1 RTSP/1.0\r\n" - + "cseq: 4\r\n" - + "transport: RTP/AVP;unicast;client_port=65458-65459\r\n" + + "CSeq: 4\r\n" + + "Transport: RTP/AVP;unicast;client_port=65458-65459\r\n" + "\r\n"; assertThat(messageLines).isEqualTo(expectedLines); @@ -254,14 +256,14 @@ public final class RtspMessageUtilTest { List expectedLines = Arrays.asList( "RTSP/1.0 200 OK", - "cseq: 4", - "transport: RTP/AVP;unicast;client_port=65458-65459;server_port=5354-5355", + "CSeq: 4", + "Transport: RTP/AVP;unicast;client_port=65458-65459;server_port=5354-5355", "", ""); String expectedRtspMessage = "RTSP/1.0 200 OK\r\n" - + "cseq: 4\r\n" - + "transport: RTP/AVP;unicast;client_port=65458-65459;server_port=5354-5355\r\n" + + "CSeq: 4\r\n" + + "Transport: RTP/AVP;unicast;client_port=65458-65459;server_port=5354-5355\r\n" + "\r\n"; assertThat(messageLines).isEqualTo(expectedLines); assertThat(RtspMessageUtil.convertMessageToByteArray(messageLines)) @@ -296,10 +298,10 @@ public final class RtspMessageUtilTest { List expectedLines = Arrays.asList( "RTSP/1.0 200 OK", - "cseq: 4", - "content-base: rtsp://127.0.0.1/test.mkv/", - "content-type: application/sdp", - "content-length: 707", + "CSeq: 4", + "Content-Base: rtsp://127.0.0.1/test.mkv/", + "Content-Type: application/sdp", + "Content-Length: 707", "", "v=0\r\n" + "o=- 1606776316530225 1 IN IP4 192.168.2.176\r\n" @@ -313,10 +315,10 @@ public final class RtspMessageUtilTest { String expectedRtspMessage = "RTSP/1.0 200 OK\r\n" - + "cseq: 4\r\n" - + "content-base: rtsp://127.0.0.1/test.mkv/\r\n" - + "content-type: application/sdp\r\n" - + "content-length: 707\r\n" + + "CSeq: 4\r\n" + + "Content-Base: rtsp://127.0.0.1/test.mkv/\r\n" + + "Content-Type: application/sdp\r\n" + + "Content-Length: 707\r\n" + "\r\n" + "v=0\r\n" + "o=- 1606776316530225 1 IN IP4 192.168.2.176\r\n" @@ -340,8 +342,8 @@ public final class RtspMessageUtilTest { /* status= */ 454, new RtspHeaders.Builder().add(RtspHeaders.CSEQ, "4").build()); List messageLines = RtspMessageUtil.serializeResponse(response); - List expectedLines = Arrays.asList("RTSP/1.0 454 Session Not Found", "cseq: 4", "", ""); - String expectedRtspMessage = "RTSP/1.0 454 Session Not Found\r\n" + "cseq: 4\r\n" + "\r\n"; + List expectedLines = Arrays.asList("RTSP/1.0 454 Session Not Found", "CSeq: 4", "", ""); + String expectedRtspMessage = "RTSP/1.0 454 Session Not Found\r\n" + "CSeq: 4\r\n" + "\r\n"; assertThat(RtspMessageUtil.serializeResponse(response)).isEqualTo(expectedLines); assertThat(RtspMessageUtil.convertMessageToByteArray(messageLines))