RFC 7826
Real-Time Streaming Protocol Version 2.0
๐ RFC 7826: Real-Time Streaming Protocol Version 2.0 ๐
okay bestie, so this is the RTSP 2.0 spec, the one that officially replaces RTSP 1.0 from RFC 2326 โจ. RTSP is the protocol for setting up and remote-controlling real-time streams like audio and video, so think play, pause, and seek for media. It's giving "remote control for the internet's streaming" ๐บ๐
Here's the title block, the important bits first ๐ธ:
- Authors: H. Schulzrinne (Columbia University), A. Rao (Cisco), R. Lanphier, M. Westerlund (Ericsson), and M. Stiemerling, Ed. (University of Applied Sciences Darmstadt) ๐
- Category: Standards Track, so this is an official Internet standard ๐ซถ
- Date: December 2016 ๐
- ISSN: 2070-1721
- Obsoletes: RFC 2326 (RTSP 1.0) ๐
- Updates: nothing listed ๐ฆ
The abstract is basically the whole pitch: RTSP 2.0 gives you an extensible framework for controlled, on-demand delivery of real-time data, from live feeds or stored clips. It can handle multiple delivery sessions, lets you pick your transport (UDP, multicast UDP, or TCP), and works with delivery mechanisms built on RTP (RFC 3550) ๐ง
The Status of This Memo section says it's an Internet Standards Track document, reviewed by the community and approved by the IESG. More info on Internet Standards is in Section 2 of RFC 7841, and the current status, errata, and feedback info lives at http://www.rfc-editor.org/info/rfc7826 ๐ฅ
The Copyright Notice is the legal stuff ๐ (ยฉ 2016 IETF Trust and the authors, all rights reserved). It says the doc is subject to BCP 78 and the IETF Trust's Legal Provisions, which you can read at http://trustee.ietf.org/license-info. Code pulled out of the doc has to include Simplified BSD License text (Section 4.e of the Trust Legal Provisions), and it comes with no warranty. It also says some older material from before November 10, 2008 might not be modifiable outside the IETF Standards Process, except to format it as an RFC or translate it into non-English languages ๐
The Table of Contents is next, and we'll get into the sections in the next parts ๐ฆโจ
Part 1 of 67. Keep going, there's more RTSP goodness coming! ๐
Bestie, I can't do part 2 yet ๐ญ The text you sent is the table of contents, and that was already covered in part 1. Part 2 starts at Section 1 (Introduction), and that body text isn't in the message. I'm not going to write it from memory, because the RFC's exact wording, requirement keywords, and section numbers all have to match the original. ๐ซถ
Paste the original text from "1. Introduction" onward and I'll rewrite it with the same numbering, BCP 14 keywords, and code blocks, picking up right where part 1 left off ๐ โจ
okay bestie, the table of contents keeps going, and it's giving a lot of sections ๐ โจ
18.14. Content-Base ...........................................144
18.15. Content-Encoding .......................................145
18.16. Content-Language .......................................145
18.17. Content-Length .........................................146
18.18. Content-Location .......................................146
18.19. Content-Type ...........................................148
18.20. CSeq ...................................................148
18.21. Date ...................................................150
18.22. Expires ................................................151
18.23. From ...................................................151
18.24. If-Match ...............................................152
18.25. If-Modified-Since ......................................152
18.26. If-None-Match ..........................................153
18.27. Last-Modified ..........................................154
18.28. Location ...............................................154
18.29. Media-Properties .......................................154
18.30. Media-Range ............................................156
18.31. MTag ...................................................157
18.32. Notify-Reason ..........................................158
18.33. Pipelined-Requests .....................................158
18.34. Proxy-Authenticate .....................................159
18.35. Proxy-Authentication-Info ..............................159
18.36. Proxy-Authorization ....................................159
18.37. Proxy-Require ..........................................160
18.38. Proxy-Supported ........................................160
18.39. Public .................................................161
18.40. Range ..................................................162
18.41. Referrer ...............................................164
18.42. Request-Status .........................................164
18.43. Require ................................................165
18.44. Retry-After ............................................166
18.45. RTP-Info ...............................................167
18.46. Scale ..................................................169
18.47. Seek-Style .............................................170
18.48. Server .................................................171
18.49. Session ................................................172
18.50. Speed ..................................................173
18.51. Supported ..............................................174
18.52. Terminate-Reason .......................................175
18.53. Timestamp ..............................................175
18.54. Transport ..............................................176
18.55. Unsupported ............................................183
18.56. User-Agent .............................................184
18.57. Via ....................................................184
18.58. WWW-Authenticate .......................................185
19. Security Framework ...........................................185
19.1. RTSP and HTTP Authentication ............................185
19.1.1. Digest Authentication ............................186
19.2. RTSP over TLS ...........................................187
19.3. Security and Proxies ....................................188
19.3.1. Accept-Credentials ...............................189
19.3.2. User-Approved TLS Procedure ......................190
20. Syntax .......................................................192
20.1. Base Syntax .............................................193
20.2. RTSP Protocol Definition ................................195
20.2.1. Generic Protocol Elements ........................195
20.2.2. Message Syntax ...................................198
20.2.3. Header Syntax ....................................201
20.3. SDP Extension Syntax ....................................209
21. Security Considerations ......................................209
21.1. Signaling Protocol Threats ..............................210
21.2. Media Stream Delivery Threats ...........................213
21.2.1. Remote DoS Attack ................................215
21.2.2. RTP Security Analysis ............................216
22. IANA Considerations ..........................................217
22.1. Feature Tags ............................................218
22.1.1. Description ......................................218
22.1.2. Registering New Feature Tags with IANA ...........218
22.1.3. Registered Entries ...............................219
22.2. RTSP Methods ............................................219
22.2.1. Description ......................................219
22.2.2. Registering New Methods with IANA ................219
22.2.3. Registered Entries ...............................220
22.3. RTSP Status Codes .......................................220
22.3.1. Description ......................................220
22.3.2. Registering New Status Codes with IANA ...........220
22.3.3. Registered Entries ...............................221
22.4. RTSP Headers ............................................221
22.4.1. Description ......................................221
22.4.2. Registering New Headers with IANA ................221
22.4.3. Registered Entries ...............................222
22.5. Accept-Credentials ......................................223
22.5.1. Accept-Credentials Policies ......................223
22.5.2. Accept-Credentials Hash Algorithms ...............224
22.6. Cache-Control Cache Directive Extensions ................224
22.7. Media Properties ........................................225
22.7.1. Description ......................................225
22.7.2. Registration Rules ...............................226
22.7.3. Registered Values ................................226
22.8. Notify-Reason Values ....................................226
22.8.1. Description ......................................226
22.8.2. Registration Rules ...............................226
22.8.3. Registered Values ................................227
1. Introduction โจ
okay so bestie, this memo defines version 2.0 of the Real-Time Streaming Protocol (RTSP 2.0) ๐ฌ. RTSP 2.0 is an application-layer protocol for setting up and controlling the delivery of data with real-time properties, which is basically streaming media. Streaming media is things like video on demand or audio live streaming ๐ง. Put simply, RTSP acts as a "network remote control" for multimedia servers ๐บโจ
The protocol operates between RTSP 2.0 clients and servers, but it also supports proxies placed between them ๐ฆ. Clients can ask servers for information about streaming media by requesting a description of the media, or they can use a media description that was provided externally ๐. The media delivery protocol is then used to set up the media streams that the description covers ๐. Clients can request to play the media, pause it, or stop it completely โฏ๏ธ. The requested media can include multiple audio and video streams, delivered from servers to clients as time-synchronized streams ๐ถ๐
RTSP 2.0 is a replacement for RTSP 1.0 [RFC2326], and this document obsoletes that specification ๐ . This protocol is based on RTSP 1.0, but it is not backwards compatible except for the basic version negotiation mechanism ๐. The changes between the two documents are listed in Appendix I ๐. There are many reasons RTSP 2.0 can't be backwards compatible with RTSP 1.0, and some of the big ones are:
- Most headers that needed to be extensible did not define the allowed syntax, which made it unsafe to deploy extensions ๐
- the changed behavior of the
PLAYmethod when received in Play state ๐ - the changed behavior of the extensibility model and its mechanism ๐งฉ, and
- the change of syntax for some headers โ๏ธ
There are so many small updates that changing versions became necessary, so things could be clarified and behave consistently ๐. Anyone implementing RTSP for a new use case where they have not already installed RTSP 1.0 should only implement RTSP 2.0, so they don't have to deal with RTSP 1.0 inconsistencies ๐ซถ
This document is structured like this ๐บ๏ธ. It starts with an overview of the protocol operations and its functions, explained informally ๐ธ. Then it introduces a set of definitions for terms and document conventions ๐. After that comes the actual RTSP 2.0 core protocol specification ๐ฅ. The appendices describe and define functionality that is not part of the core RTSP specification, but is still important for some usages ๐ง. The RTP usage is defined in Appendix C, the Session Description Protocol (SDP) usage with RTSP is defined in Appendix D, and the text/parameters file format is defined in Appendix F. Those three are normative specification appendices ๐. The other appendices contain a bunch of informational parts about the changes, use cases, different considerations, and motivations ๐
2. Protocol Overview
This section gives an informative overview of the different mechanisms in the RTSP 2.0 protocol, so you get a high-level understanding before we dive into all the specific details ๐ฆ. If there's any conflict between this description and the later sections, the later sections take precedence ๐. For more information about use cases considered for RTSP, see Appendix E ๐
RTSP 2.0 is a bidirectional request and response protocol ๐. It first establishes a context that includes content resources (the media), and then it controls the delivery of those content resources from the provider to the consumer โจ. RTSP has three fundamental parts: Session Establishment, Media Delivery Control, and an extensibility model that's described below ๐งฉ. The protocol is built on some assumptions about existing functionality, which together give a complete solution for client-controlled real-time media delivery ๐
RTSP uses text-based messages, requests and responses, that may contain a binary message body ๐. An RTSP request starts with a method line that identifies the method, the protocol and version, and the resource to act on ๐ฏ. The resource is identified by a URI, and the hostname part of the URI is used by the RTSP client to resolve the IPv4 or IPv6 address of the RTSP server ๐. After the method line come a number of RTSP headers ๐. These lines end with two consecutive carriage return line feed (CRLF) character pairs ๐. The message body, if there is one, follows those two CRLF pairs, and the body's length is described by a message header ๐. RTSP responses are similar, but they start with a response line that has the protocol and version, followed by a status code and a reason phrase ๐. RTSP messages are sent over a reliable transport protocol between the client and server ๐. RTSP 2.0 requires clients and servers to implement TCP and TLS over TCP as mandatory transports for RTSP messages ๐ญ๐ฅ
2.1. Presentation Description โจ
okay so RTSP is literally all about getting you into multimedia presentations and content, but it's giving very "I don't care what kind of media you're watching or how it's delivered" ๐ . It's agnostic, bestie. ๐ฆ So to let a client build a whole working system, there's an RTSP-external mechanism for describing the presentation and the delivery protocol(s). RTSP assumes that this description is either delivered completely out of band, or it shows up as a data object in the response to a client's request using the DESCRIBE method (Section 13.2). ๐
the stuff that usually has to be in the presentation description is:
- the number of media streams ๐
- the resource identifier for each media stream/resource that RTSP is supposed to control ๐ธ
- the protocol that will be used to deliver each media stream ๐ง
- the transport protocol parameters that are not negotiated or that vary with each client ๐ซถ
- the media-encoding information so a client can decode the media correctly when it arrives ๐ฅ
- and an aggregate control resource identifier ๐
RTSP uses its own URI schemes ("rtsp" and "rtsps") to reference media resources and aggregates under common control (see Section 4.2). iykyk ๐
and this specification describes in Appendix D how you can use SDP [RFC4566] to describe the presentation. slay, we love a reliable pairing ๐
2.2. Session Establishment โจ
okay so the RTSP client can ask for an RTSP session to be set up once it's used the presentation description to figure out which media streams are available, which delivery protocol is used, and the resource identifiers of those streams. ๐ฆ The RTSP session is a shared context between the client and the server, and it's made up of one or more media resources that are supposed to be under common media delivery control. main character energy ๐
the client makes the session by sending a SETUP request (Section 13.3) to the server. ๐ In the Transport header (Section 18.54) of that SETUP request, the client also includes all the transport parameters needed to get the media delivery protocol working. this covers parameters that were already set up by the presentation description but are still needed so any middlebox can handle the media delivery protocols properly. ๐ซถ A Transport header in a request can hold multiple alternatives for media delivery in a prioritized list, and the server can pick from them. these alternatives are usually based on what's in the presentation description. โจ
when the server gets a SETUP request, it checks whether the media resource is available and whether one or more of the transport parameter specifications are acceptable. ๐ if that works out, an RTSP session context gets created and the relevant parameters and state are stored. ๐ an identifier is made for the RTSP session and goes back in the response, in the Session header (Section 18.49). ๐ธ the SETUP response has a Transport header that says which of the alternatives got selected, plus the relevant parameters. ๐ง
a SETUP request that points at an existing RTSP session but names a new media resource is a request to add that resource under common control with the media resources already in an aggregated session. ngl this is so useful ๐ฅ a client can expect it to work for all media resources under RTSP control inside one multimedia content container. ๐ but a server will likely refuse to aggregate resources from different content containers, so don't be surprised ๐. even if an RTSP session only has a single media stream, it can still be referenced by the aggregate control URI. ๐ฆ
to skip an extra round trip when setting up aggregated RTSP sessions, RTSP 2.0 supports pipelined requests, which means the client can send multiple requests back-to-back without waiting for any of them to finish first. ๐ the client uses a client-selected identifier in the Pipelined-Requests header (Section 18.33) to tell the server to bind multiple requests together as if they included the session identifier. ๐ซถ iconic ๐ญ
the SETUP response also gives extra info about the established session in a couple of different headers. โจ the Media-Properties header (Section 18.29) includes a bunch of properties that apply to the aggregate, which is super valuable for media delivery control and for configuring the user interface. ๐ the Accept-Ranges header (Section 18.5) tells the client which range formats the server supports for these media resources. ๐ and the Media-Range header (Section 18.30) tells the client the time range of the media that's currently available. ๐
2.3. Media Delivery Control โจ
once an RTSP session is established, the client can start controlling the media delivery. ๐ the basic moves are "begin playback" using the PLAY method (Section 13.4), and "suspend (pause) playback" using the PAUSE method (Section 13.6). PLAY also lets you pick the starting media position where the server should begin delivering. ๐ฆ that positioning is done with the Range header (Section 18.40), which supports several time formats: Normal Play Time (NPT) (Section 4.4.2), Society of Motion Picture and Television Engineers (SMPTE) Timestamps (Section 4.4.1), and absolute time (Section 4.4.3). ๐ง the Range header also lets the client say where delivery should end, so you can get one specific interval delivered. ๐
how much you can seek or search within media content depends on the content's media properties. ๐ธ content comes in a bunch of types, like on-demand, live, and live with simultaneous recording. ngl even inside those categories, how the content gets made and distributed is different, and that changes how you can access it for playback. ๐ the server gives the properties that apply to the RTSP session in the SETUP response, using the Media-Properties header (Section 18.29). they're expressed using one or several independent attributes. โจ the first attribute is Random-Access, which says whether positioning is possible and at what granularity. ๐ฅ another thing is whether the content will change during the session. on-demand content is provided in full from the beginning, but a live stream being recorded makes the accessible content grow as the session goes on. ๐ there's also content that gets built dynamically by a protocol other than RTSP, so it changes in steps during the session, but maybe not continuously. ๐ซถ and when content is recorded, sometimes the whole thing isn't kept, and maybe only the last hour sticks around. ๐ all of these properties mean we need mechanisms that get discussed below. ๐
when the client accesses on-demand content that allows random access, it can send a PLAY request for any point between the start and the end. ๐ฆ the server delivers media from the closest random access point before the requested point and says so in its PLAY response. ๐ if the client sends a PAUSE, delivery halts and the point where the server stopped gets reported back in the response. ๐ธ the client can resume later by sending a PLAY request without a Range header. โจ when the server is about to finish the PLAY request by delivering the end of the content or the requested range, it sends a PLAY_NOTIFY request (Section 13.5) to say so. ๐
when you're playing live content with no extra functions, like recording, the client gets the live media from the server after sending a PLAY request. ๐ง seeking in that kind of content isn't possible, because the server doesn't store it and just forwards it from the source of the session. ๐ so delivery keeps going until the client sends a PAUSE request, tears down the session, or the content ends. ๐ญ
for live sessions that are being recorded, the client has to keep track of how the recording is progressing. ๐ฅ when the session is set up, the client learns the current duration of the recording from the Media-Range header. ๐ because the recording is ongoing, the content grows in direct relation to the time that's passed. ๐ซถ so every server response to a PLAY request will contain the current Media-Range header. ๐ the server should also regularly send (approximately every 5 minutes) the current media range in a PLAY_NOTIFY request (Section 13.5.2). โจ if the live transmission ends, the server MUST send a PLAY_NOTIFY request with the updated Media-Properties, saying the content stopped being a recorded live session and became on-demand content instead. ๐ that request also contains the final media range. ๐ฆ while the live delivery continues, the client can ask to play the current live point using the NPT timescale symbol "now", or it can request a specific point in the available content with an explicit range request for that point. ๐ if the requested point is outside the available interval, the server adjusts the position to the closest available point, which means either the beginning or the end. ๐ธ
a special case of recording is when the recording isn't kept longer than a specific time period. so as live delivery continues, the client can access any media inside a moving window that covers, for example, "now" to "now" minus 1 hour. ๐ง a client that pauses on a specific point in the content might not be able to get that content back anymore. ๐ if the client waits too long before resuming from the pause point, the content may no longer be available. ๐ฅบ in that case, the pause point gets adjusted to the closest point in the available media. ๐
2.4. Session Parameter Manipulations โจ
a session can have extra state or functionality that affects how the server or client treats the session or content, how it works, or feedback on how well the session is going. ๐ฆ those extensions aren't defined in this specification, but they might be covered in various extensions. ๐ RTSP has two methods for getting and setting parameter values on either the client or the server: GET_PARAMETER (Section 13.8) and SET_PARAMETER (Section 13.9). ๐ these methods carry the parameters in a message body of the appropriate format. ๐ซถ you can also use headers to query state with the GET_PARAMETER method. ๐ for example, clients that need to know the current media range for a time-progressing session can use GET_PARAMETER and include the media range. ๐ synchronization info can also be requested with a combination of RTP-Info (Section 18.45) and Range (Section 18.40). โจ
RTSP 2.0 doesn't have a strong mechanism for negotiating headers or parameters and their formats. ๐ but responses will indicate request-headers or parameters that aren't supported. ๐ฅ figuring out in advance what features are available has to be done through out-of-band mechanisms, like the session description, or by using feature tags (Section 4.5). ๐ธ
2.5. Media Delivery โจ
Okay so, this section is all about how the actual media gets to the client ๐. RTSP can deliver media over RTP [RFC3550] running on UDP [RFC768], over TCP [RFC793], or straight over the RTSP connection itself ๐ฆ. More protocols might show up later if they're needed, bestie ๐.
RTP needs a little extra help to work well, though ๐ซถ. The PLAY response carries the info a client needs to line up the different sources across the different RTP sessions in a reliable and timely way ๐ . It also gives a mapping between RTP timestamps and the content-time scale โญ. When the server wants to tell the client that the media delivery is done, it sends a PLAY_NOTIFY request ๐ฅ. That PLAY_NOTIFY includes the stream end info, including the last RTP sequence number for each stream, so the client can empty its buffer smoothly ๐ธ. Iconic, honestly ๐ญ.
2.5.1. Media Delivery Manipulations ๐ฆ
Basic RTSP playback delivers the requested content to the client at the pace the creator intended ๐. But RTSP can also mess with the delivery in two ways, and we're gonna talk about both ๐.
Scale: The ratio of media-content time delivered per unit of playback time. โจ
Speed: The ratio of playback time delivered per unit of wallclock time. ๐
Both of these change how much media gets delivered per unit of time ๐. The thing is, they manipulate two independent timescales, so they can be combined ๐ง.
Scale (Section 18.46) is the one for fast-forward or slow-motion, because it changes how much content timescale should be played back per unit of time โญ. Scale > 1.0 means fast forward. Like, scale = 2.0 means 2 seconds of content get played back every second of playback, ngl so fun ๐ . Scale = 1.0 is the default if you don't specify a scale, so it plays at the content's original rate ๐ซถ. Scale values between 0 and 1.0 give you slow motion ๐ข. Scale can also be negative for reverse playback: regular pace (scale = -1.0), fast backwards (scale < -1.0), or slow-motion backwards (-1.0 < scale < 0) ๐ฅ. Scale = 0 would be the same as pause, so it is not allowed ๐.
Realizing scale usually means the server has to manipulate the media itself so the client can actually play it back ๐. How that works, and when it's needed, depends heavily on the media type ๐ธ. Let's look at audio and video, bestie ๐.
Audio is very hard to change the playback rate of ๐ญ. Typically you can't go past a factor of two while keeping it intelligible when you change the pitch and rate of speech ๐. Music goes out of tune if you try to change its playback rate by resampling it ๐ต. This is a well-known problem, so audio is commonly muted or played in short segments with skips to keep up with the current playback point โจ.
For video, you can manipulate the frame rate ๐ฆ, but the rendering capabilities are often limited to certain frame rates ๐. The allowed bitrates in decoding, the structure used in the encoding, and the dependencies between frames and other capabilities of the rendering device all limit what's possible ๐ซ . So the basic fast-forward is often done by selecting certain subsets of frames ๐.
Because of these media restrictions, the possible scale values are commonly limited to the set of realizable scale ratios ๐ . So clients can pick from the possible scale values, RTSP can signal the supported scale ratios for the content โจ. For aggregated or dynamic content, where this can change during the session and depend on where you are in the content, there's a mechanism for updating the media properties and the scale factor currently in use ๐ง.
Speed (Section 18.50) affects how much of the playback timeline gets delivered in a given wallclock period โฐ. The default is Speed = 1, which means deliver at the same rate the media is consumed ๐. Speed > 1 means the receiver gets content faster than it would normally consume it ๐ฅ. Speed < 1 means delivery is slower than the regular media rate ๐ข. Speed values of 0 or lower have no meaning and are not allowed ๐ . This mechanism enables two general functionalities ๐. One is client-side scale operations, where the client receives all the frames and makes the adjustment to playback locally ๐. The other is delivery control for buffering media ๐ซถ. By specifying a speed over 1.0, the client can build up the amount of playback time in its buffers to a level that's sufficient for its needs ๐.
A naive implementation of Speed would only affect the transmission schedule of the media, and that clearly impacts the bandwidth needed ๐. The data rate would end up proportional to the speed factor ๐. Speed = 1.5, meaning 50% faster than normal delivery, would give you a 50% increase in the data-transport rate ๐ญ. Whether that can be supported depends entirely on the underlying network path ๐ฃ๏ธ. Scale can also affect the required bandwidth, because the content gets manipulated for the new playback schedule ๐ฌ. For example, with fast forward where only the independently decodable intra-frames are included in the media stream ๐ผ๏ธ. Using only intra-frames increases the data rate a lot compared to a normal sequence with the same number of frames, where most frames are encoded using prediction ๐.
This potential jump in data rate has to be handled by the media sender ๐ซก. The client asked for the media to be delivered in a specific way, and that should be honored ๐. But the media sender can't ignore it if the network path between sender and receiver can't handle the resulting stream ๐ฌ. In that case, the media stream needs to be adapted to fit what the path can actually handle, and this can mean reduced media quality ๐.
Bitrate adaptation gets especially tricky with Speed semantics ๐ช๏ธ. If the goal is to fill the buffer, the client might not want that to come at the cost of reduced quality ๐ . If the client wants to make local playout changes, it might actually need the requested speed to be honored ๐ฏ. To handle both cases, Speed uses a range ๐. The server is requested to use the highest possible speed value within the range that's compatible with the available bandwidth ๐. As long as the server can keep a speed value within the range, it MUST NOT change the media quality. Instead it modifies the actual delivery rate in response to available bandwidth and reflects that in the Speed value in the response โจ. However, if that isn't possible, the server SHOULD instead modify the media quality to respect the lowest speed value and the available bandwidth ๐ซ.
Wait, I need to fix that: the original says "shall not", and I've rendered it as MUST NOT, so the key word is now wrong. Here is the correct version of that sentence, keeping the force of the original:
As long as the server can keep a speed value within the range, it SHALL NOT change the media quality. Instead it modifies the actual delivery rate in response to available bandwidth and reflects that in the Speed value in the response โจ. However, if that isn't possible, the server SHOULD instead modify the media quality to respect the lowest speed value and the available bandwidth ๐ซ.
This functionality lets the local scaling implementation use a tight range, or even a range where the lower bound equals the upper bound ๐ฏ. That tells the server it needs to deliver the requested amount of media time per delivery time, no matter how much it has to adapt media quality to fit the path bandwidth ๐ช. For buffer filling, a range with a reasonable span and a lower bound at the nominal media rate 1.0 is a good fit, like 1.0 - 2.5 ๐ธ. If the client wants to reduce the buffer, it can specify an upper bound below 1.0 to force the server to deliver slower than the nominal media rate ๐.
2.6. Session Maintenance and Termination ๐ซง
The established session context stays alive because the client shows liveness ๐. There are two main ways it does this ๐ง:
- Media-transport protocol keep-alive. RTP Control Protocol (RTCP) may be used when using RTP ๐ก.
- Any RTSP request referencing the session context ๐.
Section 10.5 goes deeper into the methods for showing liveness ๐. If the client fails to show liveness for more than the established session timeout value (normally 60 seconds), the server may terminate the context โฐ. The server can pick other values by including the timeout parameter in the session header ๐.
The session context is normally terminated by the client sending a TEARDOWN request (Section 13.7) to the server, referencing the aggregated control URI ๐. An individual media resource can be removed from a session context with a TEARDOWN request referencing that particular media resource ๐ฏ. If all media resources are removed from a session context, the session context is terminated ๐.
A client may keep the session alive indefinitely if the server allows it ๐. However, a client is advised to release the session context when an extended period without media delivery activity has passed ๐ซก. The client can re-establish the session context later if it needs to ๐. What counts as an extended period depends on the client, the server, and how they're being used ๐คท. It's recommended that the client terminate the session before ten times the session timeout value has passed โณ. A server may terminate the session after one session timeout period without any client activity beyond keep-alive ๐ชฆ. When a server terminates the session context, it does so by sending a TEARDOWN request indicating the reason ๐.
A server can also ask the client to tear down the session and re-establish it at an alternative server, which might be needed for maintenance ๐ง. This is done with the REDIRECT method (Section 13.10) ๐ฆ. The Terminate-Reason header (Section 18.52) indicates when and why ๐ฐ๏ธ. The Location header says where the client should connect if there's an alternative server available ๐. When the deadline expires, the server simply stops providing the service ๐ฑ. For a clean closure, the client needs to start session termination before the deadline ๐ซถ. If the server has no other server to redirect to and wants to close the session for maintenance, it SHALL use the TEARDOWN method with a Terminate-Reason header ๐ .
2.7. Extending RTSP ๐งฉ
okay so RTSP is literally one of the most versatile protocols ever ๐ it can be extended in a bunch of different directions. Even this core spec has several blocks of functionality that are optional to implement ๐ what you actually build should depend on your use case and what the deployment needs. Extensions let RTSP handle extra use cases โจ but they can mess with interoperability, so they have to be added in a structured way ๐ซถ
The client can figure out what a server can do by using the OPTIONS method (Section 13.1) and the Supported header (Section 18.51) ๐. It can also try something new and possibly fail ๐, or insist that certain features be supported by using the Require (Section 18.43) or Proxy-Require (Section 18.37) header.
RTSP itself can be extended in three ways, listed in increasing order of how big the changes are ๐:
- Existing methods can be extended with new parameters, for example, headers, as long as these parameters can be safely ignored by the recipient. If the client needs a negative acknowledgment when a method extension isn't supported, a tag corresponding to the extension may be added in the field of the
RequireorProxy-Requireheaders. - New methods can be added ๐. If the recipient of the message does not understand the request, it must respond with error code
501(Not Implemented) so that the sender can avoid using this method again. A client may also use theOPTIONSmethod to inquire about methods supported by the server. The server must list the methods it supports using thePublicresponse-header. - A new version of the protocol can be defined, allowing almost all aspects (except the position of the protocol version number) to change. A new version of the protocol must be registered through a Standards Track document ๐.
The basic capability discovery mechanism can be used to both discover support for a certain feature and to ensure that a feature is available when performing a request. For a detailed explanation of this, see Section 11.
New media delivery protocols may be added and negotiated at session establishment, in addition to extensions to the core protocol. Certain types of protocol manipulations can be done through parameter formats using SET_PARAMETER and GET_PARAMETER ๐ฆ
3. Document Conventions ๐
3.1. Notational Conventions ๐
All the mechanisms specified in this document are described in both prose and the Augmented Backus-Naur form (ABNF) described in detail in [RFC5234].
The indented paragraphs are there to give informative background and motivation ๐ญ so that readers who weren't involved in writing the spec can understand why things are the way they are in RTSP.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119] ๐ฅ
The word "unspecified" is used to mean functionality or features that aren't defined in this specification ๐ . That stuff can't be used in a standardized way without more definition in an extension specification to RTSP.
3.2. Terminology ๐
- Aggregate control: controlling multiple streams using a single timeline, usually one the server keeps track of ๐ฐ๏ธ. A client uses aggregate control when it sends a single play or pause message to control the audio and video in a movie at the same time. A session under aggregate control is called an "aggregated session".
- Aggregate control URI: the URI used in an RTSP request to refer to and control an aggregated session. It normally, but not always, matches the presentation URI in the session description. See Section 13.3 for more info.
- Client: the requester of media service from the media server ๐
- Connection: a transport-layer virtual circuit set up between two programs so they can communicate ๐
- Container file: a file that may contain multiple media streams that often make up a presentation when played together. The concept of a container file isn't embedded in the protocol, but RTSP servers may offer aggregate control on the media streams inside these files ๐ฆ
- Continuous media: data with a timing relationship between source and sink, meaning the sink needs to reproduce the timing that existed at the source โฑ๏ธ. The most common examples are audio and motion video. Continuous media can be real time (interactive or conversational), where there's a "tight" timing relationship between source and sink, or it can be streaming, where the relationship is less strict.
- Feature tag: a tag representing a certain set of functionality, i.e., a feature ๐ท๏ธ
- IRI: an Internationalized Resource Identifier is similar to a URI but allows characters from the whole Universal Character Set (Unicode/ISO 10646), rather than US-ASCII only. See [RFC3987] for more information ๐
- Live: a live presentation or session originates media from an event happening at the same time as the media delivery ๐ด. Live sessions often have an unbound or only loosely defined duration, and seek operations may not be possible.
- Media initialization: the datatype- or codec-specific initialization ๐๏ธ. This includes things like clock rates, color tables, etc. Any transport-independent information a client needs for playback of a media stream happens in the media initialization phase of stream setup.
- Media parameter: a parameter specific to a media type that may be changed before or during stream delivery.
- Media server: the server providing media-delivery services for one or more media streams. Different media streams within a presentation may come from different media servers. A media server may reside on the same host or on a different host from the one where the presentation is invoked ๐ฅ๏ธ
- (Media) Stream: a single media instance, e.g., an audio stream or a video stream, as well as a single whiteboard or shared application group ๐ฌ. When using RTP, a stream consists of all RTP and RTCP packets created by a media source within an RTP session.
- Message: the basic unit of RTSP communication, consisting of a structured sequence of octets matching the syntax defined in Section 20 and transmitted over a transport between RTSP agents ๐. A message is either a request or a response.
- Message body: the information transferred as the payload of a message (request or response) ๐ฌ. A message body consists of meta-information in the form of message body headers and content in the form of an arbitrary number of data octets, as described in Section 9.
- Non-aggregated control: control of a single media stream ๐ฏ.
- Presentation: a set of one or more streams presented to the client as a complete media feed, described by a presentation description (more on that below) ๐. Presentations with more than one media stream are often handled in RTSP under aggregate control.
- Presentation description: info about one or more media streams within a presentation, like the set of encodings, network addresses, and information about the content ๐๏ธ. Other IETF protocols, such as SDP ([RFC4566]), use the term "session" for a presentation. The presentation description may take several different formats, including but not limited to SDP format.
- Response: an RTSP response to a request, and one type of RTSP message ๐ฌ. If an HTTP response is meant, it's indicated explicitly.
- Request: an RTSP request, and one type of RTSP message ๐จ. If an HTTP request is meant, it's indicated explicitly.
- Request-URI: the URI used in a request to indicate the resource that the request is to be performed on ๐ฏ.
- RTSP agent: either an RTSP client, an RTSP server, or an RTSP proxy ๐ค. There are lots of capabilities these three share, like sending requests or receiving responses, so this term is used when describing functionality that applies to all of them.
- RTSP session: a stateful abstraction that the main control methods of RTSP operate on ๐ง . It's a common context, created and maintained at a client's request, and it can be destroyed by either the client or the server. An RTSP server establishes it when a
SETUPrequest completes successfully (when a200 OKresponse is sent), and it gets labeled with a session identifier at that time. The session exists until the server times it out or aTEARDOWNrequest explicitly removes it. Because it's stateful, an RTSP server maintains an explicit session state machine (see Appendix B) where most state transitions are triggered by client requests. The existence of a session implies the existence of state about the session's media streams and their respective transport mechanisms. A given session can have one or more media streams associated with it. An RTSP server uses the session to aggregate control over multiple media streams ๐. - Origin server: the server on which a given resource resides ๐ .
- Seeking: requesting playback from a particular point in the content time line โฉ.
- Transport initialization: the negotiation of transport information (e.g., port numbers, transport protocols) between the client and the server ๐ค.
- URI: a Universal Resource Identifier; see [RFC3986]. The URIs used in RTSP are generally URLs, since they give a location for the resource. As URLs are a subset of URIs, they're referred to as URIs too, so that the cases where an RTSP URI wouldn't be a URL are covered ๐.
- URL: a Universal Resource Locator is a URI that identifies the resource through its primary access mechanism, rather than by its name or by some other attribute(s) of that resource ๐.
4. Protocol Parameters ๐
4.1. RTSP Version โจ
okay so this section is all about the version number, and it's giving organization bestie ๐ ๐
RTSP uses a "<major>.<minor>" numbering scheme to show which version of the protocol a message is using ๐ฆ. The whole point of versioning is to tell the other side what format a message is in and how much of the conversation it can actually follow. It is NOT about listing the fancy features you got from talking. Adding message parts that don't change how communication behaves, or that just add more values to extensible fields, does NOT bump the version number ๐ธ
The <minor> number goes up when the changes add features that keep the general message parsing algorithm the same, but might add to the message meaning and show that the sender has extra capabilities ๐ The <major> number goes up when the format of a message in the protocol changes ๐ฅ The version shows up in an RTSP-Version field on the first line of a message ๐ง
Here's the lowkey tricky part: the major and minor numbers MUST be treated as separate integers, and EACH one MAY be incremented to more than a single digit ๐ญ So RTSP/2.4 is a lower version than RTSP/2.13, and RTSP/2.13 is lower than RTSP/12.3 ๐ Don't compare them like they're decimals, bestie!! Leading zeros SHALL NOT be sent, and recipients MUST ignore them if they show up ๐
4.2. RTSP IRI and URI ๐
Okay this one is a whole vibe. RTSP 2.0 defines and registers or updates three URI schemes: "rtsp", "rtsps", and "rtspu" โจ The "rtspu" one is unspecified in RTSP 2.0, but it's defined here so the scheme that was defined in RTSP 1.0 still gets registered ๐ซถ The "rtspu" scheme means the RTSP messages are sent with unspecified transport over unreliable transport (UDP in RTSP 1.0) ๐ฆ An RTSP server MUST respond with error code 501, saying the "rtspu" scheme is not implemented, to any request that carries a "rtspu" URI scheme ๐ญ
The syntax of "rtsp" and "rtsps" URIs changed from RTSP 1.0, and there are two main changes ๐
o Support for an IPv6 literal in the host part, plus future IP literals through a mechanism defined in [RFC3986].
o A new relative format for RTSP elements that does NOT have to start with "/".
Neither of these should really mess with interoperability โจ But if you need IPv6 literals in the RTSP URI, the RTSP server has to be IPv6 capable, and honestly RTSP 1.0 is not fully IPv6 capable ๐ If an RTSP 1.0 client tries to process that URI, it won't match the allowed syntax, it's considered invalid, and processing stops. That's clearly a failure to reach the resource, but it's not a significant issue, because RTSP 2.0 support was needed in both server and client anyway ๐ธ So the failure only shows up later, when there's an RTSP version mismatch between client and server. The second change only happens inside RTSP message headers, because the Request-URI MUST be an absolute URI ๐ง So those relative usages only come up after an agent has accepted and started processing RTSP 2.0 messages, and a RTSP 1.0-only agent doesn't have to parse those relative URIs at all ๐
This spec also defines the format of RTSP IRIs [RFC3987], which you can use as resource identifiers and locators on web pages, user interfaces, on paper, etc. ๐โจ BUT the RTSP request message format only allows the absolute URI format, so the RTSP IRI format MUST use the rules and transformation for IRIs to URIs from [RFC3987] ๐ That way you can make a URI that matches RTSP 2.0 and is good for a request, starting from an RTSP IRI ๐
Both the RTSP IRI and URI are syntax restricted compared to the generic syntax in [RFC3986] and [RFC3987] ๐
o An absolute URI requires the authority part, so a host identity MUST be provided.
o Parameters in the path element are prefixed with the reserved separator ";".
The "scheme" and "host" parts of all URIs [RFC3986] and IRIs [RFC3987] are case insensitive ๐ Everything else in RTSP URIs and IRIs is case sensitive, and they MUST NOT be case mapped ๐ญ
The fragment identifier works as defined in Sections 3.5 and 4.3 of [RFC3986], so the requester MUST strip the fragment from the IRI and not include it in the Request-URI ๐ฆ The user agent needs to interpret the fragment based on the media type the request is about, meaning the media type in the Content-Type header of the response to a DESCRIBE request ๐
The syntax of any URI query string is unspecified and responder (usually the server) specific ๐ง From the requester's point of view, the query is an opaque string, and it has to be handled that way ๐ฎ
Heads up: relative URIs with queries are kinda difficult to handle because of the relative URI handling rules in RFC 3986 โ ๏ธ Any change to the path element using a relative URI strips the query, so the relative part has to contain the query itself ๐
The URI scheme "rtsp" requires that commands be issued over a reliable protocol (within the Internet, that's TCP) ๐ The scheme "rtsps" identifies a reliable transport using secure transport (TLS [RFC5246]), see Section 19 ๐โจ
For "rtsp", if no port number is in the authority part of the URI, port 554 MUST be used ๐ For "rtsps", if no port number is in the authority part of the URI, TCP port 322 MUST be used ๐ธ
A presentation or a stream is identified by a textual media identifier, using the character set and escape conventions of URIs [RFC3986] ๐ฆ URIs can refer to a stream or an aggregate of streams, which is a presentation ๐ So requests described in Section 13 can apply to either the whole presentation or one individual stream inside it. Some request methods only work on streams, not presentations, and vice versa, so keep that in mind ๐ซถ
For example, this RTSP URI:
rtsp://media.example.com:554/twister/audiotrack
may identify the audio stream within the presentation "twister", which you can control with RTSP requests sent over a TCP connection to port 554 of host media.example.com ๐
Also, this RTSP URI:
rtsp://media.example.com:554/twister
identifies the presentation "twister", which may be made of audio and video streams, but could also be something else, like a random media redirector ๐
This does not imply a standard way to reference streams in URIs. The presentation description defines the hierarchical relationships in the presentation and the URIs for the individual streams. A presentation description may name a stream "a.mov" and the whole presentation "b.mov".
The path components of the RTSP URI are opaque to the client and do not imply any particular file system structure for the server ๐ง
This decoupling also allows presentation descriptions to be used with non-RTSP media control protocols simply by replacing the scheme in the URI.
4.3. Session Identifiers ๐
Session identifiers are strings between 8 and 128 characters long ๐ A session identifier MUST be generated with methods that make it cryptographically random (see [RFC4086]) ๐ It is RECOMMENDED that a session identifier contain 128 bits of entropy, which is about 22 characters from a high-quality generator (see Section 21) โจ Heads up though: the session identifier doesn't protect against session hijacking UNLESS it's kept confidential by the client, server, and trusted proxies ๐ญ๐
4.4. Media-Time Formats โฐ
RTSP currently supports three media-time formats, defined below ๐ฆ More time formats might be specified in the future ๐ธ These time formats can be used with the Range header (Section 18.40) to request playback and say at which media position protocol requests will or have actually happened ๐ They're also used to describe the media's properties with the Media-Range header (Section 18.30) ๐ The unqualified format identifier is used on its own in the Accept-Ranges header (Section 18.5) to declare supported time formats, and also in the Range header (Section 18.40) to request the time format used in the response ๐
4.4.1. SMPTE-Relative Timestamps ๐ฌ
A timestamp can use a format derived from a Society of Motion Picture and Television Engineers (SMPTE) specification, and it expresses time offsets anchored at the start of the media clip ๐ฆ Relative timestamps are written as SMPTE time codes [SMPTE-TC] for frame-level access accuracy โจ The time code looks like this:
hours:minutes:seconds:frames.subframes
with the origin at the start of the clip ๐ง The default SMPTE format is "SMPTE 30 drop", with a frame rate of 29.97 frames per second ๐ Other SMPTE codes MAY be supported (such as "SMPTE 25") through the use of "smpte-type" ๐ For SMPTE 30, the "frames" field can be 0 through 29 ๐ The gap between 30 and 29.97 frames per second is handled by dropping the first two frame indices (values 00 and 01) of every minute, EXCEPT every tenth minute ๐ If the frame and subframe values are zero, they MAY be omitted ๐ซถ Subframes are measured in hundredths of a frame ๐
Examples ๐:
smpte=10:12:33:20-
smpte=10:07:33-
smpte=10:07:00-10:07:33:05.01
smpte-25=10:07:00-10:07:33:05.01
Part 8 of 67 is a wrap, bestie! Keep going, we're literally just getting started ๐ง๐
4.4.2. Normal Play Time ๐ฌ
okay so Normal Play Time (NPT) is the stream-absolute position, counted from the very start of the presentation. it's the clock the viewer vibes with ๐ฐ๏ธโจ the timestamp has two parts. the mandatory first part can be seconds only, or hours, minutes, and seconds. the optional second part is a decimal point plus digits for fractions of a second ๐
the beginning of a presentation is 0.0 seconds. negative values are not defined, bestie ๐ โโ๏ธ
the special constant "now" means the current instant of a live event. It MAY only be used for live events and MUST NOT be used for on-demand (i.e., non-live) content. ๐ด
NPT is defined as in Digital Storage Media Command and Control (DSMb;CC) [ISO.13818-6.1995]:
Intuitively, NPT is the clock the viewer associates with a program. It is often digitally displayed on a DVD player. NPT advances normally when in normal play mode (scale = 1), advances at a faster rate when in fast-scan forward (high positive scale ratio), decrements when in scan reverse (negative scale ratio) and is fixed in pause mode. NPT is (logically) equivalent to SMPTE time codes.
examples, iykyk ๐
npt=123.45-125
npt=12:05:35.3-
npt=now-
the syntax is based on ISO 8601 [ISO.8601.2000] and tracks the time elapsed since presentation start. there are two notations you can use ๐ง
- the
npt-hhmmssnotation uses an ISO 8601 extended complete representation of the time of the day format (Section 5.3.1.1 of [ISO.8601.2000]) with colons (":") as separators between hours, minutes, and seconds (hh:mm:ss). the hour counter is not limited to 0-24 hours, and up to nineteen (19) hour digits are allowed ๐ธ- ok this part is strict. following the ISO 8601 time format, the hours, minutes, and seconds MUST all be present. minutes and seconds get two digits, and hours get at least two digits. an NPT of 7 minutes and 0 seconds is
00:07:00, and an NPT of 392 hours, 0 minutes, and 6 seconds is392:00:06๐งฎ - RTSP 1.0 let NPT be written in the npt-hhmmss notation without any leading zeros, so implementations wouldn't fail. for backward compatibility, all RTSP 2.0 implementations are REQUIRED to support receiving NPT values, hours, minutes, or seconds, without leading zeros ๐ซถ
- ok this part is strict. following the ISO 8601 time format, the hours, minutes, and seconds MUST all be present. minutes and seconds get two digits, and hours get at least two digits. an NPT of 7 minutes and 0 seconds is
- the
npt-secnotation expresses the time in seconds, using between one and nineteen (19) digits ๐ข
both notations allow decimal fractions of seconds as specified in Section 5.3.1.3 of [ISO.8601.2000], using at most nine digits. the only allowed decimal separator is "." (full stop) ๐ซ
the npt-sec notation is optimized for automatic generation, and the npt-hhmmss notation is optimized for human readers ๐ค๐ the "now" constant lets clients ask for the live feed instead of the stored or time-delayed version. this is needed because neither absolute time nor zero time works for that case, so "now" is the move ๐
4.4.3. Absolute Time โฐ
absolute time uses a timestamp based on ISO 8601 [ISO.8601.2000]. the date is a complete representation of the calendar date in basic format (YYYYMMDD) with no separators (per Section 5.2.1.1 of [ISO.8601.2000]). the time of day is in the complete representation basic format (hhmmss) from Section 5.3.1.1 of [ISO.8601.2000], and it allows decimal fractions of seconds following Section 5.3.1.3. that section requires "." (full stop) as the decimal separator, and the digits are capped at nine ๐
the time MUST use UTC (GMT), so no time zone offsets are allowed ๐ the full thing is the eight-digit date, then a "T", then the six-digit time value. you can optionally add a full stop and one to nine fractions of a second, and it ends with "Z", like YYYYMMDDThhmmss.ssZ ๐
Why this format and not "Date and Time on the Internet: Timestamps" [RFC3339]? It's historic. we keep using the format from RTSP 1.0. the motivations raised in RFC 3339 apply to why a selection from ISO 8601 was made, but this case applies an even more restrictive selection ๐
three examples of media time formats, all in one spot ๐ first, a clock format range request for a starting time of November 8, 1996 at 14 h 37 min and 20 1/4 seconds UTC, playing for 10 min and 5 seconds. next is a Media-Properties header's "Time-Limited" UTC property for the 24th of December 2014 at 15 hours and 00 minutes. last is a Terminate-Reason header "time" property for the 18th of June 2013 at 16 hours, 12 minutes, and 56 seconds โณ
clock=19961108T143720.25Z-19961108T144725.25Z
Time-Limited=20141224T1500Z
time=20130618T161256Z
4.5. Feature Tags ๐ท๏ธ
feature tags are unique identifiers that designate features in RTSP. they show up in the Require (Section 18.43), Proxy-Require (Section 18.37), Proxy-Supported (Section 18.38), Supported (Section 18.51), and Unsupported (Section 18.55) header fields ๐
a feature tag definition MUST indicate which combination of clients, servers, or proxies it applies to ๐งโ๐ป
if you're creating a new RTSP feature tag, you should either prefix it with a reverse domain name (e.g., "com.example.mynewfeature" is an apt name for a feature whose inventor can be reached at "example.com") or register it with the Internet Assigned Numbers Authority (IANA). (See Section 22, "IANA Considerations".) โจ
how feature tags get used is covered in Section 11, which is all about capability handling ๐งฉ
4.6. Message Body Tags ๐ซถ
message body tags are opaque strings that compare two message bodies from the same resource. they're handy in caches, or for speeding up setup after a redirect ๐ they can ride along in the MTag header (see Section 18.31) or in SDP (see Appendix D.1.9). MTag is kinda like ETag in HTTP/1.1 (see Section 3.11 of [RFC2068]) ๐ฆ
a message body tag MUST be unique across all versions of all message bodies tied to a particular resource. a given tag value MAY be reused for message bodies obtained by requests on different URIs ๐ but using the same tag on bodies from different URIs does not mean those bodies are equivalent. no shortcuts there, babe ๐ โโ๏ธ
message body tags make some methods conditional. you do that by including headers, and see Section 18.24 and Section 18.26 for the If-Match and If-None-Match headers. heads up that RTSP message body tags cover the whole presentation, meaning both the presentation description and the individual media streams ๐ฆ so at setup time after a redirect, you can use If-Match to check that the same session description applies to the media at the new location ๐ต๏ธโโ๏ธ
4.7. Media Properties ๐๏ธ
when an RTSP server handles media, it matters what properties a media instance has for delivery and playback. this spec looks at the media properties below for its protocol operations. they come from the differences between a bunch of supported usages ๐ฅ
- On-demand: media with a fixed (given) duration that doesn't change during the lifetime of the RTSP session, and that's known when the session is created. the content is expected to stay the same, even if the representation (like encoding or quality) changes. usually you can seek, meaning request any range, within the media ๐ฟ
- Dynamic On-demand: a variation of on-demand where external methods manipulate the actual content of the media set up for the RTSP session. the main example is content defined by a playlist ๐
- Live: a progressing content stream (like broadcast TV) where the duration may or may not be known. it's not seekable, so you can only access what's being delivered right now ๐ก
- Live with Recording: a live stream combined with a server-side ability to store and keep the live session's content, allowing random access delivery within the part that's already recorded. how it behaves depends a lot on the retention policy. the server might capture the complete stream, or it might have a limit on how much it keeps. the media range changes as the session goes on. if the server has limited storage for recording, you'll usually see a sliding window that moves forward as new data arrives and older data gets dropped ๐๏ธโช
to cover the usages above, the following media properties come with appropriate values ๐
4.7.1. Random Access and Seeking ๐
random access is the ability to specify and get media delivered starting from any time (instant) within the content. that operation is called "seeking" โฉ the Media-Properties header shows the general capability of a media resource to do random access.
- Random-Access: the media is seekable to any of a large number of points within the media. because of media-encoding limitations, a particular point may not be reachable, but seeking to a point close by is enabled. a floating-point number of seconds may be given to express the worst-case distance between random access points ๐ฏ
- Beginning-Only: seeking is only possible to the beginning of the content โฎ๏ธ
- No-Seeking: seeking is not possible at all ๐
if random access is possible, as the Media-Properties header says, you can control the actual seeking behavior with the Seek-Style header (Section 18.47) ๐๏ธ
4.7.2. Retention โณ
these retention policies limit what protocol operations media can use:
- Unlimited: the media won't be removed as long as the RTSP session exists โพ๏ธ
- Time-Limited: the media won't be removed before the given wallclock time. after that, it may or may not still be available ๐ฐ๏ธ
- Time-Duration: the media (on fragment or unit basis) is retained for the specified duration ๐งบ
4.7.3. Content Modifications ๐
media content and its timeline can be different types. you could have pre-produced on-demand content, a live source being generated as time goes on, or something that gets dynamically altered or recomposed during playback ๐ญ so there's a media property for content modifications, with these initial values:
- Immutable: the content won't change, even if the representation (like encoding or quality) changes ๐ง
- Dynamic: the content can change due to external methods or triggers, like playlists, but explicit updates will announce it ๐ฃ
- Time-Progressing: as time goes on, new content becomes available. if the content is also retained, it gets longer, since everything between the start point and the point currently being made available can be accessed. if the media server uses a sliding-window policy for retention, the start point changes as time goes on too ๐
4.7.4. Supported Scale Factors โจ
okay bestie, not every piece of media can be sped up or slowed down in every way ๐ A particular media content item often supports only a limited set or range of scales when it's delivering media. So the client can know which scale values or ranges the whole content (or the current position) supports, there's a media properties attribute just for that ๐ It's a list of the values or ranges that are supported, and it's named "Scales". The "Scales" attribute may be updated at any point in the content, since content can be made of spliced pieces or be dynamically updated by out-of-band mechanisms ๐งฉ
4.7.5. Mapping to the Attributes ๐บ๏ธ
This section shows examples of how you'd map all the usages above to the properties and their values. Here's the tea ๐ซ
Example of On-Demand:
Random Access: Random-Access=5.0, Content Modifications:
Immutable, Retention: Unlimited or Time-Limited.
Example of Dynamic On-Demand:
Random Access: Random-Access=3.0, Content Modifications: Dynamic,
Retention: Unlimited or Time-Limited.
Example of Live:
Random Access: No-Seeking, Content Modifications: Time-
Progressing, Retention: Time-Duration=0.0
Example of Live with Recording:
Random Access: Random-Access=3.0, Content Modifications: Time-
Progressing, Retention: Time-Duration=7200.0
5. RTSP Message ๐จ
okay so RTSP is a text-based protocol that uses the ISO 10646 character set in UTF-8 encoding per RFC 3629 [RFC3629]. Lines MUST be terminated by a CRLF.
Text-based protocols make it easier to add optional parameters in a self-describing manner. Since the number of parameters and the frequency of commands is low, processing efficiency is not a concern. Text-based protocols, if used carefully, also allow easy implementation of research prototypes in scripting languages such as Python, PHP, Perl and TCL.
The ISO 10646 character set avoids character-set switching, but it's invisible to the application as long as US-ASCII is being used ๐ธ This is also the encoding used for text fields in RTCP [RFC3550].
A request contains a method, the object the method is operating upon, and parameters that further describe the method. Methods are idempotent unless otherwise noted. Methods are also designed to require little or no state maintenance at the media server โจ
5.1. Message Types ๐
RTSP messages are either requests from client to server or from server to client, and responses in the reverse direction. Request (Section 7) and response (Section 8) messages use a format based on the generic message format of RFC 5322 [RFC5322] for transferring bodies (the payload of the message). Both types of messages consist of a start-line, zero or more header fields (also known as "headers"), an empty line (i.e., a line with nothing preceding the CRLF) indicating the end of the headers, and possibly the data of the message body. The ABNF [RFC5234] below is for illustration only; the formal message specification is presented in Section 20.2.2 ๐ฆ
generic-message = start-line
*(rtsp-header CRLF)
CRLF
[ message-body-data ]
start-line = Request-Line / Status-Line
In the interest of robustness, agents MUST ignore any empty line(s) received where a Request-Line or Status-Line is expected. In other words, if the agent is reading the protocol stream at the beginning of a message and receives any number of CRLFs first, it MUST ignore all of the CRLFs ๐
5.2. Message Headers ๐ท๏ธ
RTSP header fields (see Section 18) include general-header, request-header, response-header, and message body header fields.
The order in which header fields with differing field names are received is not significant. However, it is "good practice" to send general-header fields first, followed by a request-header or response-header field, and ending with the message body header fields ๐
Multiple header fields with the same field-name MAY be present in a message if and only if the entire field-value for that header field is defined as a comma-separated list. It MUST be possible to combine the multiple header fields into one field-name: field-value pair, without changing the semantics of the message, by appending each subsequent field-value to the first, each separated by a comma. The order in which header fields with the same field-name are received is therefore significant to the interpretation of the combined field value; thus, a proxy MUST NOT change the order of these field-values when a message is forwarded ๐
Unknown message headers MUST be ignored (skipping over the header to the next protocol element, and not causing an error) by an RTSP server or client. An RTSP proxy MUST forward unknown message headers. Message headers defined outside of this specification that are required to be interpreted by the RTSP agent will need to use feature tags (Section 4.5) and include them in the appropriate Require (Section 18.43) or Proxy-Require (Section 18.37) header ๐
5.3. Message Body ๐ฆ
The message body (if any) of an RTSP message is used to carry further information for a particular resource associated with the request or response. An example of a message body is an SDP message.
The presence of a message body in either a request or a response MUST be signaled by the inclusion of a Content-Length header (see Section 18.17) and Content-Type header (see Section 18.19). A message body MUST NOT be included in a request or response if the specification of the particular method (see Method Definitions (Section 13)) does not allow sending a message body. In case a message body is received in a message when not expected, the message body data SHOULD be discarded. This is to allow future extensions to define optional use of a message body ๐ง
5.4. Message Length ๐
An RTSP message that does not contain any message body is terminated by the first empty line after the header fields (note: an empty line is a line with nothing preceding the CRLF.). In RTSP messages that contain message bodies, the empty line is followed by the message body. The length of that body is determined by the value of the Content-Length header (Section 18.17). The value in the header represents the length of the message body in octets. If this header field is not present, a value of zero is assumed, i.e., no message body present in the message. Unlike an HTTP message, an RTSP message MUST contain a Content-Length header whenever it contains a message body. Note that RTSP does not support the HTTP/1.1 "chunked" transfer coding (see Section 4.1 of [RFC7230]) ๐
โโ๏ธ
Given the moderate length of presentation descriptions returned, the server should always be able to determine its length, even if it is generated dynamically, making the chunked transfer encoding unnecessary.
6. General-Header Fields ๐
General headers are headers that may be used in both requests and responses. The general-headers are listed in Table 1:
+--------------------+----------------+
| Header Name | Defined in |
+--------------------+----------------+
| Accept-Ranges | Section 18.5 |
| | |
| Cache-Control | Section 18.11 |
| | |
| Connection | Section 18.12 |
| | |
| CSeq | Section 18.20 |
| | |
| Date | Section 18.21 |
| | |
| Media-Properties | Section 18.29 |
| | |
| Media-Range | Section 18.30 |
| | |
| Pipelined-Requests | Section 18.33 |
| | |
| Proxy-Supported | Section 18.38 |
| | |
| Range | Section 18.40 |
| | |
| RTP-Info | Section 18.45 |
| | |
| Scale | Section 18.46 |
| | |
| Seek-Style | Section 18.47 |
| | |
| Server | Section 18.48 |
| | |
| Session | Section 18.49 |
| | |
| Speed | Section 18.50 |
| | |
| Supported | Section 18.51 |
| | |
| Timestamp | Section 18.53 |
| | |
| Transport | Section 18.54 |
| | |
| User-Agent | Section 18.56 |
| | |
| Via | Section 18.57 |
+--------------------+----------------+
Table 1: The General Headers Used in RTSP
7. Request ๐
A request message uses the format outlined below regardless of the direction of a request, whether client to server or server to client:
- Request line, containing the method to be applied to the resource, the identifier of the resource, and the protocol version in use;
- Zero or more Header lines, which can be of the following types: general-headers (Section 6), request-headers (Section 7.2), or message body headers (Section 9.1);
- One empty line (CRLF) to indicate the end of the header section;
- Optionally, a message body, consisting of one or more lines. The length of the message body in octets is indicated by the
Content-Lengthmessage header ๐
7.1. Request Line โจ
Okay bestie, the request line is the headline of every request ๐ It tells the server what method you want, on what resource, and which RTSP version you're speaking ๐ฆ Table 2 lists the methods this spec defines ๐
+---------------+----------------+
| Method | Defined in |
+---------------+----------------+
| DESCRIBE | Section 13.2 |
| | |
| GET_PARAMETER | Section 13.8 |
| | |
| OPTIONS | Section 13.1 |
| | |
| PAUSE | Section 13.6 |
| | |
| PLAY | Section 13.4 |
| | |
| PLAY_NOTIFY | Section 13.5 |
| | |
| REDIRECT | Section 13.10 |
| | |
| SETUP | Section 13.3 |
| | |
| SET_PARAMETER | Section 13.9 |
| | |
| TEARDOWN | Section 13.7 |
+---------------+----------------+
Table 2: The RTSP Methods
The request line is shaped like this ๐
<Method> SP <Request-URI> SP <RTSP-Version> CRLF
๐ Heads up: this syntax can't be freely changed in future versions of RTSP. The line has to stay parsable by older RTSP implementations, because it's how they figure out the version of the message.
Here's where RTSP gets its own vibe ๐ธ Compared to HTTP/1.1 [RFC7230], RTSP requests identify the resource with an absolute RTSP URI (scheme, host, and port) (see Section 4.2), not just the absolute path.
๐ Fun backstory: HTTP/1.1 requires servers to understand the absolute URI, but clients are supposed to use the Host request-header instead. That's purely there for backward compatibility with HTTP/1.0 servers, and that concern doesn't apply to RTSP. Not our problem, bestie!
An asterisk "*" can be used in place of an absolute URI in the Request-URI part. It means the request isn't about one particular resource, but about the server or proxy itself. It's only allowed when the method doesn't necessarily apply to a resource ๐ง
Example:
OPTIONS * RTSP/2.0
An OPTIONS request in this form tells you the capabilities of the server or proxy that first receives it โจ If you want the capabilities of one specific server, without caring about an in-between proxy, you should address that server explicitly with an absolute URI that contains its address ๐
Example:
OPTIONS rtsp://example.com RTSP/2.0
7.2. Request-Header Fields
The RTSP headers in Table 3 can show up in a request as request-headers, and they're how you tweak the specifics of what you're asking for ๐ฆ
+---------------------+----------------+
| Header | Defined in |
+---------------------+----------------+
| Accept | Section 18.1 |
| | |
| Accept-Credentials | Section 18.2 |
| | |
| Accept-Encoding | Section 18.3 |
| | |
| Accept-Language | Section 18.4 |
| | |
| Authorization | Section 18.8 |
| | |
| Bandwidth | Section 18.9 |
| | |
| Blocksize | Section 18.10 |
| | |
| From | Section 18.23 |
| | |
| If-Match | Section 18.24 |
| | |
| If-Modified-Since | Section 18.25 |
| | |
| If-None-Match | Section 18.26 |
| | |
| Notify-Reason | Section 18.32 |
| | |
| Proxy-Authorization | Section 18.36 |
| | |
| Proxy-Require | Section 18.37 |
| | |
| Referrer | Section 18.41 |
| | |
| Request-Status | Section 18.42 |
| | |
| Require | Section 18.43 |
| | |
| Terminate-Reason | Section 18.52 |
+---------------------+----------------+
Table 3: The RTSP Request-Headers
Detailed header definitions live in Section 18 ๐
New request-headers may be defined ๐ If the receiver of the request is required to understand the request-header, the request MUST include a corresponding feature tag in a Require or Proxy-Require header, so the header actually gets processed ๐ซถ
8. Response ๐
After receiving and interpreting a request message, the recipient responds with an RTSP response message ๐ Normally there's only one response, and it's the final one. Responses using the response code class 1xx are the only class for which there MAY be sent one or more responses before the final response message โญ
The valid response codes, and the methods they can be used with, are listed in Table 4 ๐
8.1. Status-Line
The first line of a response message is the Status-Line ๐ฆ It's made up of the protocol version, then a numeric status code, then the textual phrase that goes with that code, all separated by SP characters. No CR or LF is allowed except in the final CRLF sequence ๐
<RTSP-Version> SP <Status-Code> SP <Reason Phrase> CRLF
8.1.1. Status Code and Reason Phrase โจ
okay so the Status-Code is a 3-digit integer that tells you how the server did at understanding and satisfying your request ๐ These codes are fully defined in Section 17. The reason phrase is just a short textual description of the Status-Code ๐ The Status-Code is meant for automata (machines), and the reason phrase is meant for the human user ๐ค The client is not required to examine or display the reason phrase ๐
The first digit of the Status-Code tells you the class of the response ๐ The last two digits don't do any categorizing, so they're just vibes ๐ There are five values for the first digit:
1xx: Informational - Request received, continuing process ๐ธ2xx: Success - The action was successfully received, understood, and accepted โจ3rr: Redirection - Further action needs to be taken in order to complete the request (3rr rather than 3xx is used as 304 is excluded; see Section 17.3) ๐ฆ4xx: Client Error - The request contains bad syntax or cannot be fulfilled ๐ญ5xx: Server Error - The server failed to fulfill an apparently valid request ๐
The individual values of the numeric status codes defined for RTSP 2.0, plus an example set of matching reason phrases, are presented in Table 4 ๐ The reason phrases listed there are only recommended, so they can be swapped out for local equivalents without affecting the protocol ๐ Also, RTSP adopted most HTTP/1.1 [RFC2068] status codes, then added its own RTSP-specific ones starting at x50 so it wouldn't clash with future HTTP codes that are desirable to import into RTSP ๐ง All of these codes are RTSP specific, and RTSP has its own registry for status codes, separate from HTTP ๐
RTSP status codes are extensible โญ RTSP applications aren't required to understand the meaning of every registered status code, though obviously it's desirable ๐ซถ However, applications MUST understand the class of any status code, as indicated by the first digit. They also MUST treat any unrecognized response as equivalent to the x00 status code of that class, with one exception for unknown 3xx codes, which MUST be treated as a 302 (Found) ๐ฅ The reason for that exception is that the status code 300 (Multiple Choices in HTTP) isn't defined for RTSP ๐ A response with an unrecognized status code MUST NOT be cached ๐ซ For example, if a client gets an unrecognized status code of 431, it can safely assume something was wrong with its request and treat the response as if it had received a 400 status code ๐ In cases like this, user agents SHOULD present the message body returned with the response to the user, since that body is likely to include human-readable info that explains the unusual status ๐
+------+---------------------------------+--------------------------+
| Code | Reason | Method |
+------+---------------------------------+--------------------------+
| 100 | Continue | all |
| | | |
| 200 | OK | all |
| | | |
| 301 | Moved Permanently | all |
| | | |
| 302 | Found | all |
| | | |
| 303 | See Other | n/a |
| | | |
| 304 | Not Modified | all |
| | | |
| 305 | Use Proxy | all |
| | | |
| 400 | Bad Request | all |
| | | |
| 401 | Unauthorized | all |
| | | |
| 402 | Payment Required | all |
| | | |
| 403 | Forbidden | all |
| | | |
| 404 | Not Found | all |
| | | |
| 405 | Method Not Allowed | all |
| | | |
| 406 | Not Acceptable | all |
| | | |
| 407 | Proxy Authentication Required | all |
| | | |
| 408 | Request Timeout | all |
| | | |
| 410 | Gone | all |
| | | |
| 412 | Precondition Failed | DESCRIBE, SETUP |
| | | |
| 413 | Request Message Body Too Large | all |
| | | |
| 414 | Request-URI Too Long | all |
| | | |
| 415 | Unsupported Media Type | all |
| | | |
| 451 | Parameter Not Understood | SET_PARAMETER, |
| | | GET_PARAMETER |
| | | |
| 452 | reserved | n/a |
| | | |
| 453 | Not Enough Bandwidth | SETUP |
| | | |
| 454 | Session Not Found | all |
| | | |
| 455 | Method Not Valid in This State | all |
| | | |
| 456 | Header Field Not Valid for | all |
| | Resource | |
| | | |
| 457 | Invalid Range | PLAY, PAUSE |
| | | |
| 458 | Parameter Is Read-Only | SET_PARAMETER |
| | | |
| 459 | Aggregate Operation Not Allowed | all |
| | | |
| 460 | Only Aggregate Operation | all |
| | Allowed | |
| | | |
| 461 | Unsupported Transport | all |
| | | |
| 462 | Destination Unreachable | all |
| | | |
| 463 | Destination Prohibited | SETUP |
| | | |
| 464 | Data Transport Not Ready Yet | PLAY |
| | | |
| 465 | Notification Reason Unknown | PLAY_NOTIFY |
| | | |
| 466 | Key Management Error | all |
| | | |
| 470 | Connection Authorization | all |
| | Required | |
| | | |
| 471 | Connection Credentials Not | all |
| | Accepted | |
| | | |
| 472 | Failure to Establish Secure | all |
| | Connection | |
| | | |
| 500 | Internal Server Error | all |
| | | |
| 501 | Not Implemented | all |
| | | |
| 502 | Bad Gateway | all |
| | | |
| 503 | Service Unavailable | all |
| | | |
| 504 | Gateway Timeout | all |
| | | |
| 505 | RTSP Version Not Supported | all |
| | | |
| 551 | Option Not Supported | all |
| | | |
| 553 | Proxy Unavailable | all |
+------+---------------------------------+--------------------------+
Table 4: Status Codes and Their Usage with RTSP Methods
8.2. Response Headers โจ
okay so response-headers are the bonus notes the server tucks in with its reply when they don't fit in the Status-Line ๐ They tell the requester about the server itself and how to get further access to the resource named in the Request-URI. Every header that counts as a response-header is listed in Table 5 ๐
+------------------------+----------------+
| Header | Defined in |
+------------------------+----------------+
| Authentication-Info | Section 18.7 |
| | |
| Connection-Credentials | Section 18.13 |
| | |
| Location | Section 18.28 |
| | |
| MTag | Section 18.31 |
| | |
| Proxy-Authenticate | Section 18.34 |
| | |
| Public | Section 18.39 |
| | |
| Retry-After | Section 18.44 |
| | |
| Unsupported | Section 18.55 |
| | |
| WWW-Authenticate | Section 18.58 |
+------------------------+----------------+
Table 5: The RTSP Response Headers
ngl the rules for adding new response-headers are kinda strict ๐ Response-header names can only be extended reliably together with a change in the protocol version. BUT the feature tags in a request let the responder figure out what the receiver can handle, which is so smart ๐ง A new or experimental header can get response-header semantics once every party in the conversation agrees it's a response-header. And headers in responses that nobody recognizes MUST be ignored ๐ซถ
9. Message Body ๐
Some request and response messages carry a message body, unless the request method or the response status code says otherwise. The body is made up of the content data itself (see also Section 5.3) ๐ธ
The SET_PARAMETER and GET_PARAMETER requests and responses, plus the DESCRIBE response as this spec defines it, can have a message body. Each of those cases has its own defined purpose for the body โจ All 4xx and 5xx responses MAY also have a message body to carry extra response info. In general, a message body MAY be attached to any RTSP 2.0 request or response, but the receiver MAY ignore what's in it ๐ Extensions to this specification can define what message bodies are for and what goes in them, and they can even require that a body be included ๐ฆ
In this section, sender and recipient both mean either the client or the server, depending on who's sending and who's receiving the message body ๐
9.1. Message Body Header Fields
Message body header fields hold meta-information about the content data inside the body ๐ The full list is in Table 6.
+------------------+----------------+
| Header | Defined in |
+------------------+----------------+
| Allow | Section 18.6 |
| | |
| Content-Base | Section 18.14 |
| | |
| Content-Encoding | Section 18.15 |
| | |
| Content-Language | Section 18.16 |
| | |
| Content-Length | Section 18.17 |
| | |
| Content-Location | Section 18.18 |
| | |
| Content-Type | Section 18.19 |
| | |
| Expires | Section 18.22 |
| | |
| Last-Modified | Section 18.27 |
+------------------+----------------+
Table 6: The RTSP Message Body Headers
The extension-header mechanism lets people define extra message body header fields without changing the protocol ๐ง But those fields can't be assumed to be recognizable by the recipient. Unrecognized header fields MUST be ignored by the recipient and forwarded by proxies ๐ซถ
9.2. Message Body
An RTSP message with a message body MUST include the Content-Type and Content-Length headers ๐ When a body is included, the data type of that content is worked out from the Content-Type and Content-Encoding header fields.
Content-Type says what media type the underlying data is. There is no default media format, so the format used in the body is required to be explicitly stated in the Content-Type header ๐ Being explicit and always including a Content-Type header with accurate info avoids a whole pile of pitfalls from guessing based on the body's contents. HTTP and email users have been burned by that kind of heuristic guessing, so this is a glow-up ๐
Content-Encoding may be used to indicate any extra content-codings applied to the data, usually for compression, that are a property of the requested resource. The default encoding is 'identity', which means no transformation of the message body ๐
The Content-Length of a message is the length of the content, measured in octets ๐
9.3. Message Body Format Negotiation
The content format of the message body is given using the Content-Type header (Section 18.19). So the responder of a request knows which media type to use, the requester may include the Accept header (Section 18.1) in a request to list supported media types or media type ranges that suit the response ๐ฆ If the responder doesn't support any of the formats listed, the response will be a 406 (Not Acceptable) error code ๐ญ
The media types that may be used on requests with message bodies need to be figured out through feature tags, specification requirements, or trial and error ๐ Trial and error works because when the responder doesn't support the media type of the body, it responds with a 415 (Unsupported Media Type) ๐
Format support and negotiation happen individually for each method and each direction (request body or response body) ๐ Requirements for supporting particular media types as message bodies in requests and responses SHALL also be specified on a per-method and per-direction basis โจ
10. Connections ๐ธ
RTSP messages travel between RTSP agents and proxies over a transport connection. That transport connection uses TCP or TCP/TLS, and this document calls it the "connection" or "RTSP connection" ๐
RTSP requests can be sent using the two connection scenarios below:
- persistent - a transport connection is used for several request/response transactions;
- transient - a transport connection is used for each single request/response transaction.
Okay, so RFC 2326 tried to define an optional way to send RTSP messages in connectionless mode over a transport like UDP ๐ But it wasn't specified in enough detail for implementations to actually interoperate. To cut down on complexity and scope, and because there wasn't much interest, RTSP 2.0 doesn't try to define a mechanism for RTSP over UDP or other connectionless transports. One consequence is that RTSP requests MUST NOT be sent to multicast groups, since no connection can be set up with a specific receiver in multicast environments ๐ซ
Certain RTSP headers, like the CSeq header (Section 18.20), might look like they only matter for connectionless transport scenarios, but they're still kept and MUST be implemented according to this specification ๐ซถ For CSeq, it's super useful for matching responses to requests when requests are pipelined (see Section 12). Proxies also use it to keep track of the different requests they bundle together from several clients on a single TCP connection ๐ง
10.1. Reliability and Acknowledgements
Since RTSP messages are sent over reliable transport protocols, they MUST NOT be retransmitted at the RTSP level ๐ก๏ธ Instead, the implementation must rely on the underlying transport to provide reliability. The RTSP implementation may use any reception acknowledgment indication from the underlying transport protocols to optimize RTSP behavior โจ
If both the underlying reliable transport, such as TCP, and the RTSP application retransmit requests, each packet loss or message loss may result in two retransmissions. The receiver typically cannot take advantage of the application-layer retransmission since the transport stack will not deliver the application-layer retransmission before the first attempt has reached the receiver. If the packet loss is caused by congestion, multiple retransmissions at different layers will exacerbate the congestion. ๐ญ
Lack of acknowledgment of an RTSP request should be handled within the constraints of the connection timeout considerations described below (Section 10.4) ๐ฆ
10.2. Using Connections ๐ฅ
okay bestie, so a TCP transport can do persistent connections (for several message exchanges) AND transient connections (for just one message exchange) ๐ . Implementations of this specification MUST support RTSP over TCP ๐ซถ. The scheme of the RTSP URI (Section 4.2) tells the client which port to knock on at the server, and it also picks the default port if nobody writes one in โจ.
Besides the registered default ports, which are 554 (rtsp) and 322 (rtsps), there's also an alternative port, 8554, that's registered too ๐ธ. It can be lowkey useful if an RTSP server can't use the defaults. The perks might include preconfigured security policies and classifiers in network monitoring tools ๐.
When an RTSP client opens a TCP connection to reach a particular resource (identified by a URI), it uses the IP address and port that come from the host and port parts of the URI ๐ฆ. The IP address is either the explicit address written in the URI, or any of the addresses you get back from A and AAAA record DNS lookups of the hostname in the URI ๐ง.
A server MUST handle both persistent and transient connections.
Transient connections are giving fault tolerance energy ๐. They also allow application-layer mobility ๐ง. A server-and-client pair that uses transient connections can survive losing a TCP connection, e.g., because of a NAT timeout ๐. Once the client notices the TCP connection is gone, it can open a fresh one whenever it needs to talk again โจ.
A persistent connection is RECOMMENDED to be used for all transactions between the server and client, including messages for multiple RTSP sessions ๐. However, a persistent connection MAY be closed after a few message exchanges. For example, a client may use a persistent connection for the initial SETUP and PLAY message exchanges in a session and then close the connection. Later, when the client wants to send a new request, such as a PAUSE for the session, a new connection gets opened. That connection may be either transient or persistent ๐.
An RTSP agent MAY use one connection to handle multiple RTSP sessions on the same server. The RTSP agent SHALL NOT use more than one connection per RTSP session at any given point.
Only having one connection in use at a time means zero confusion about which connection the server-to-client requests get sent on ๐. Using one connection for multiple RTSP sessions also saves complexity, since the server has less connection state to keep track of. And not using more than one connection at a time for a session stops connection resources from getting wasted, so the server only tracks the most recently used client-to-server connection for each RTSP session as the currently valid server-to-client connection ๐ .
RTSP allows a server to send requests to a client. However, this only works if the client has set up a persistent connection with the server ๐ญ. When there's no persistent connection between a server and its client (because there's no signaling channel), the server may be forced to silently discard RTSP messages, and it may even drop an RTSP session without telling the client. An example is when the server wants to send a REDIRECT request for an RTSP session to the client but can't, because it can't reach the client. A server that attempts to send a request to a client that has no connection to the server at the moment SHALL discard the request ๐.
Without a persistent connection between client and server, the media server has no reliable way of reaching the client. Since server-to-client connections will probably fail, the server won't even try to set one up ๐.
Queuing server-to-client requests was considered too ๐. The problem is a security issue: how could you authorize a client that's opening a new connection as a legit receiver of a request for a particular RTSP session, when the client hasn't issued any requests related to that pending request yet? So queuing would likely make those requests even more delayed and less useful ๐ฅ.
Client and server requests can be sent asynchronously ๐. To avoid deadlock situations, both client and server MUST be able to send and receive requests simultaneously. Since an RTSP response may get queued up for transmission, reception or processing behind the peer RTSP agent's own requests, all RTSP agents are required to have a certain capability for handling outstanding messages. A potential issue is that outstanding requests may time out even though the peer has processed them. That can happen when the response gets stuck in the queue behind a bunch of requests the RTSP agent is working through, which take a while to finish. To avoid this problem, an RTSP agent should buffer incoming messages locally, so any response messages can be processed right away when they arrive. If responses get separated from requests and forwarded straight for processing, the result can be used immediately, and the state tied to that outstanding request can be released too ๐ง .
Buffering a bunch of requests on the receiving RTSP agent eats up resources and opens the door to a resource exhaustion attack on the agent ๐จ. So this buffer should be limited, meaning an unreasonable number of requests or total message size isn't allowed to eat the receiving agent's resources. In most APIs, if the receiving agent stops reading from the TCP socket, TCP's window gets clamped, which forces the buffering onto the sending agent when the load is bigger than expected. But since RTSP message sizes and frequency might change in the future through protocol extensions, an agent should be careful about taking harsher measures against a potential attack ๐ก๏ธ. When it's under attack, an RTSP agent can close TCP connections and release the state associated with that TCP connection ๐ค.
To give some guidance on what's reasonable, here are some guidelines. It is RECOMMENDED that:
- an RTSP agent should not have more than 10 outstanding requests per RTSP session;
- an RTSP agent should not have more than 10 outstanding requests that are not related to an RTSP session or that are requesting to create an RTSP session.
In light of the above, it is RECOMMENDED that clients use persistent connections whenever possible ๐ธ. A client that supports persistent connections MAY "pipeline" its requests (see Section 12).
RTSP agents can send requests to multiple different destinations, either server or client contexts, over the same connection to a proxy ๐. Then the proxy forks the message to the different destinations over proxy-to-agent connections. When multiple requests are outstanding in these cases, the requesting agent MUST be ready to receive the responses out of order compared to the order they were sent on the connection ๐ณ. The order between multiple messages for each destination will be maintained, but the order between responses from different destinations can be different ๐ซ.
This is all about avoiding head-of-line blocking ๐ง. In a sequence of requests, an early outstanding request might take a while to process at one destination. Meanwhile, a response from a different destination that was later in the sequence might already have reached the proxy. Allowing out-of-order responses means the proxy doesn't have to buffer that response and can deliver it ASAP โก. Just note that this doesn't change the order the messages sent to each separate destination get processed in at the request destination.
This scenario can happen in two proxy cases. The first is a client issuing requests for sessions on different servers over a common client-to-proxy connection. The second is server-to-client requests, like REDIRECT being sent by the server over a common transport connection that the proxy created for its different connecting clients ๐.
10.3. Closing Connections ๐ฆ
The client MAY close a connection at any point when there are no outstanding request/response transactions for any RTSP session being managed through the connection ๐. The server, however, SHOULD NOT close a connection until all RTSP sessions being managed through it have timed out (Section 18.49). A server SHOULD NOT close a connection right after responding to a session-level TEARDOWN request for the last RTSP session being controlled through the connection ๐ฌ. Instead, the server should wait a reasonable amount of time for the client to receive and act on the TEARDOWN response, and only then start closing the connection. The server SHOULD wait at least 10 seconds after sending the TEARDOWN response before closing the connection โณ.
This gives the client time to issue a SETUP for a new session on the existing connection after tearing the last one down ๐ง. Ten seconds should be plenty of opportunity for the client to get its message to the server ๐.
A server SHOULD NOT close the connection directly as a result of responding to a request with an error code ๐ โโ๏ธ.
Some error responses, like 460 (Only Aggregate Operation Allowed) (Section 17.4.24), are used to negotiate what a server can do with respect to content or other factors ๐งฉ. In those cases, closing the connection on an error response is inefficient. It would also block advanced or special types of requests from being implemented, and it would add extra overhead for the client when it's testing for new features. On the other hand, keeping connections open after sending an error response opens up a Denial-of-Service (DoS) security risk (Section 21) ๐จ.
The server MAY close a connection if it receives an incomplete message and the message isn't completed within a reasonable amount of time. It is RECOMMENDED that the server wait at least 10 seconds for the message to be completed, or for the next part of the message to arrive (which signals that the transport and the client are still alive) ๐. Servers that believe they're under attack, or are otherwise starved for resources during that event, MAY consider using a shorter timeout ๐ก๏ธ.
If a server closes a connection while the client is trying to send a new request, the client will have to close its current connection, establish a new connection, and send its request over the new connection ๐.
An RTSP message SHOULD NOT be terminated by closing the connection. Such a message MAY be considered incomplete by the receiver and discarded ๐ฅฒ. An RTSP message is properly terminated as defined in Section 5 โจ.
10.4. Timing Out Connections and RTSP Messages
okay so responders (the ones getting a request) SHOULD respond in a timely manner ๐ even when a reliable transport like TCP is doing the carrying ๐ Same energy for the requester (the one who sent it): they SHOULD wait a sufficient amount of time for a response before deciding the responder isn't going to act on the request ๐ซถ
A responder SHOULD respond to all requests within 5 seconds โฐ If the responder realizes its processing is going to take longer than 5 seconds, it SHOULD send a 100 (Continue) response as soon as possible ๐ฆ Then it SHOULD keep sending a 100 response every 5 seconds after that until it's ready to send the final response to the requester ๐ Once it has sent a 100 response, the responder MUST send a final response that says whether the request succeeded or failed. No skipping that part, bestie ๐
โโ๏ธ
A requester SHOULD wait at least 10 seconds for a response before deciding the responder isn't responding to its request โณ After getting a 100 response, the requester SHOULD keep waiting for more responses ๐ธ If more than 10 seconds go by without any response at all, the requester MAY assume the responder is unresponsive and abort the connection by closing the TCP connection ๐
Okay, this part is lowkey important. Multiple RTSP sessions can share the same transport connection, so abandoning a request and closing the connection can seriously affect those other sessions ๐ญ First of all, other RTSP requests may have gotten queued up because this one took forever to process. Secondly, those sessions also lose their chance to receive server-to-client requests. To fix that, the RTSP client or server SHOULD establish a new connection and send any requests that are queued up or that haven't gotten a response on this new connection ๐ง Thirdly, so the RTSP server knows which connection is valid for a particular RTSP session, the RTSP agent SHOULD send a keep-alive request for each RTSP session on the old connection, but only if no other request is going to be sent immediately for that RTSP session. The keep-alive request will normally be a SET_PARAMETER with a Session header, which tells the server that this agent still cares about this RTSP session ๐
A requester SHOULD wait longer than 10 seconds for a response if it's dealing with significant transport delays on its connection to the responder ๐ข The requester can figure out the Round-Trip Time (RTT) of the request/response cycle by using the Timestamp header (Section 18.53) in any RTSP request ๐ฐ๏ธ
The 10-second wait was chosen for a few reasons, okay? ๐ It gives TCP time to do a couple of retransmissions, even when it's running on default values. It's short enough that users may not abandon the process themselves. However, it should be noted that 10 seconds can be aggressive on certain types of networks. The 5-second value for 1xx messages is half the timeout, giving a reasonable chance of successful delivery before the timeout happens on the requester side. Main character logic ๐
10.5. Showing Liveness
RTSP requires the client to periodically show its liveness to the server, or the server may terminate any session state ๐ฑ Several different protocol mechanisms include a liveness proof from the client as part of how they work. These mechanisms are RTSP requests with a Session header sent to the server; if RTP & RTCP is used for media data transport and the transport is established, the RTCP message proves liveness; or any other media-transport protocol in use that's capable of indicating the liveness of the RTSP client ๐ It is RECOMMENDED that a client not wait until the last second of the timeout before trying to send a liveness message ๐โโ๏ธ The RTSP message may take some time to arrive safely at the receiver, because of packet loss and TCP retransmissions. To show liveness between RTSP requests that are being issued to get other stuff done, the following mechanisms can be used, in descending order of preference:
RTCP: If RTP is used for media transport, RTCP SHOULD be used. If RTCP is used to report transport statistics, it will necessarily also function as a keep-alive โจ The server can figure out the client by network address and port, together with the fact that the client is reporting on the server's RTP sender sources (synchronization source (SSRCs)). A downside of using RTCP is that it only gives statistical guarantees of reaching the server. However, the probability of a false client timeout is so low that it can be ignored in most cases ๐ค For example, assume a session with a 60-second timeout and enough bitrate assigned to RTCP messages to send a message from client to server on average every 5 seconds. For a network with 5% packet loss, that client has a probability of failing to confirm liveness within the timeout interval for that session of2.4*E-16. Sessions with shorter timeouts, much higher packet loss, or small RTCP bandwidths SHOULD also implement one or more of the mechanisms below ๐ฅSET_PARAMETER: When usingSET_PARAMETERfor keep-alives, a body SHOULD NOT be included ๐ This method is the RECOMMENDED RTSP method to use for a request intended only to perform keep-alives ๐ RTSP servers MUST support theSET_PARAMETERmethod, so clients can always use this mechanism ๐ซถGET_PARAMETER: When usingGET_PARAMETERfor keep-alives, a body SHOULD NOT be included, depending on implementation support in the server ๐คทโโ๏ธ Use theOPTIONSmethod to find out whether there's method support, or just try it.OPTIONS: This method is also usable, but it makes the server do more unnecessary processing and results in bigger responses than the task needs ๐ The reason is that the server has to figure out the capabilities associated with the media resource so it can correctly fill in thePublicandAllowheaders.
The timeout parameter of the Session header (Section 18.49) MAY be included in a SETUP response and MUST NOT be included in requests ๐ The server uses it to tell the client how long it's prepared to wait between RTSP commands or other signs of life before closing the session due to lack of activity (see Appendix B) ๐ The timeout is measured in seconds, with a default of 60 seconds. The length of the session timeout MUST NOT be changed in an established session ๐
10.6. Use of IPv6
Explicit IPv6 [RFC2460] support was not present in RTSP 1.0 ๐ RTSP 2.0 has been updated for explicit IPv6 support, so it's giving growth ๐ฑ Implementations of RTSP 2.0 MUST understand literal IPv6 addresses in URIs and RTSP headers. Although the general URI format envisages potential future new versions of the literal IP address, using any such new version would require other modifications to the RTSP specification (e.g., address fields in the Transport header (Section 18.54)) ๐ฎ
10.7. Overload Control
Overload in RTSP can happen when servers and proxies don't have enough resources to finish processing a request ๐ฅต If servers and proxies handle that overload badly, it can mess up the whole RTSP deployment and probably make things worse ๐ RTSP defines the 503 (Service Unavailable) response (Section 17.5.4) to let servers and proxies tell requesting proxies and RTSP clients about an overload situation. Together with the Retry-After header (Section 18.44), the server or proxy can indicate the time after which the requesting entity can send another request to the proxy or server โณ
There are two scopes for these 503 answers. The first scope is for an established RTSP session. Here, the request that caused the 503 response, as well as the response itself, carries a Session header identifying the session that's suffering overload ๐ This response only applies to that particular session. The other scope is the general RTSP server, identified by the host in the Request-URI. A 503 answer with any Retry-After header applies to all requests that aren't session specific to that server, including a SETUP request meant to create a new RTSP session ๐
There's another scope for overload situations too: the RTSP proxy ๐ฆ To let an RTSP proxy signal that it's overloaded, or otherwise unavailable and unable to handle the request, a 553 response code has been defined with the meaning "Proxy Unavailable". Just like with servers, there's a separation in response scopes between requests tied to existing RTSP sessions and requests to create new sessions or general proxy requests ๐งฉ
Simply implementing and using the 503 (Service Unavailable) and 553 (Proxy Unavailable) response codes is NOT enough for properly handling overload situations ๐
โโ๏ธ Wait, I mean, it's not sufficient, bestie ๐ค For instance, a simplistic approach would be to send the 503 response with a Retry-After header set to a fixed value. However, this can cause a situation where multiple RTSP clients all send requests to a proxy or server at roughly the same time, which may cause another overload ๐ฉ Another problem would be if the "old" overload situation isn't resolved yet, i.e., the length indicated in the Retry-After header was too short for the overload to calm down.
An RTSP server or proxy in an overload situation must select the value of the Retry-After header carefully, keeping its current load situation in mind ๐ง It is REQUIRED to increase the timeout period in proportion to the current load on the server, i.e., an increasing workload should result in an increased length of the indicated unavailability. It is REQUIRED not to send the same value in the Retry-After header to all requesting proxies and clients, but to add a variation to the mean value of the Retry-After header ๐ฒ Spread that love out ๐
A more complex case can come up when a load-balancing RTSP proxy is in use ๐ก This is when an RTSP proxy is used to select among a set of RTSP servers to handle requests, or when multiple server addresses are available for a given server name. The proxy or client may receive a 503 (Service Unavailable) or 553 (Proxy Unavailable) response code from one of its RTSP servers or proxies, or a TCP timeout (if the server is even unable to handle the request message). The proxy or client simply retries the other addresses or configured proxies, but it may also get a 503 (Service Unavailable) or 553 (Proxy Unavailable) response, or TCP timeouts, from those addresses too ๐ต In a situation where none of the RTSP servers, proxies, or addresses can handle the request, the RTSP agent has to wait before it can send any new requests to the RTSP server. Any additional request to a specific address MUST be delayed according to the Retry-After headers received. For addresses where no response was received or a TCP timeout occurred, an initial wait timer SHOULD be set to 5 seconds. That timer MUST be doubled for each additional failure to connect or receive a response, until the value exceeds 30 minutes, at which point the timer's mean value may be set to 30 minutes โฑ๏ธ It is REQUIRED not to set the same value in the timer for each scheduling, but instead to add a variation to the mean value, resulting in picking a random value within the range of 0.5 to 1.5 times the mean value ๐
11. Capability Handling โจ
okay so this section is all about how RTSP gets extended ๐ง Basically there are two ways to add new stuff: you can add new headers, or you can add new methods. The capability-handling mechanism is built to handle both, and honestly it's giving very organized energy ๐
When a new method shows up, the parties can use OPTIONS to check whether the other side supports it. You just send an OPTIONS request to the other party ๐จ Depending on the URI, the answer might be about one specific media resource, the whole server, or just the next hop. The OPTIONS response MUST contain a Public header that lists every method supported for the resource you asked about ๐ฆ
You don't actually need OPTIONS to check for a method, though. You can just try it! If the receiver doesn't support the method, it'll reply with either 501 (Not Implemented) or 405 (the method doesn't apply to that resource) ๐ Which way you go depends on what your service needs, so pick what works for you ๐ธ
Now, feature tags are for functionality additions that aren't brand-new methods ๐ Each feature tag stands for one block of functionality, and the size can vary a LOT. A feature tag could cover the functionality of one single RTSP header, or it could cover something huge, like the "play.basic" feature tag (see Section 11.1), which covers the minimal media delivery you'd need for a playback implementation ๐
Feature tags are how you figure out whether the client, server, or proxy can do what you need for the service you want. There are a few different headers for this, and here's the tea on each one ๐
Supported: This one tells you the full set of functionality that the client and server have in general. It doesn't depend on any specific resource ๐ The point is to check before you use a feature that it's actually supported. It can go in any method, but OPTIONS is the most suitable one, because it tells you every method that's implemented at the same time โจ When you send a request, you declare all your capabilities by listing every feature tag you support. That way the receiver learns what you can do, and then it includes its own feature set in the response ๐ซถ
Proxy-Supported: This works kind of like Supported, but instead of showing the client or server's features, it gives both the requester and the responder a view of the functionality that's common to every member of the proxy chain between client and server ๐ It doesn't depend on the resource either. Proxies are required to add this header whenever Supported is present, but proxies can also add it on their own, without the requester asking ๐
Require: This one can go in any request where the endpoint (the client or server) has to understand a feature to do the request correctly ๐ฅ For example, in a SETUP request, the server might need to understand a certain parameter so it can set up media delivery properly. Ignoring that parameter wouldn't give the desired result, so it's just not acceptable ๐ญ That's why the endpoint that gets a request containing Require MUST negatively acknowledge any feature it doesn't understand, and it must not perform the request. The response for unsupported features is 551 (Option Not Supported), and the features that weren't supported are listed in the Unsupported header in that response ๐
Proxy-Require: Same purpose and behaviour as Require, except it only applies to proxies and not the endpoints ๐ง If a feature needs to be supported by both proxies and endpoints, you have to put it in both the Require and Proxy-Require headers. Double up, bestie ๐
Unsupported: This header shows up in a 551 (Option Not Supported) error response, to tell you which features weren't supported ๐ A 551 only happens because of Require or Proxy-Require, when one or more features aren't supported. The info is super useful, because the requester knows exactly which features are missing and can make the best of the situation โจ
11.1. Feature Tag: play.basic ๐
An implementation that supports all the normative parts of this specification for setting up and controlling media playback uses the feature tag "play.basic" to say so ๐ฆ The appendices (the ones starting with letters) aren't part of what this feature tag covers, unless an appendix is explicitly specified in a main section as a required appendix ๐
Note: This feature tag doesn't mandate any media delivery protocol, like RTP ๐ธ
Further note: RTSP 1.0 had a minimal implementation section, but it wasn't consistent with the rest of the spec ๐ฌ So instead of trying to list out the features for play.basic one by one, this specification has to be taken as a whole, and the necessary features that are normatively defined as required get included ๐
12. Pipelining Support ๐
Pipelining is a general way to make request/response protocols faster. It lets the requesting agent have more than one request outstanding and send them all over the same persistent connection ๐โโ๏ธ For RTSP, the relative order of requests matters a lot, so keeping them in order is super important ๐ That's why the responding agent MUST process incoming requests in their sending order. You can tell that order from the sequence number in the CSeq header ๐ข For TCP, the delivery order between two agents is the same as the sending order, so that part lines up nicely โจ Also, processing of a request MUST be finished before the next request from the same agent gets processed. And the responses MUST be sent in the order the requests were processed ๐
RTSP 2.0 pushed pipelining support way further than RTSP 1.0 did ๐ฅ The big upgrade is that all the requests involved in setting up and starting media delivery can now be pipelined. You indicate that with the Pipelined-Request header (see Section 18.33) ๐ฆ This header lets a client ask for two or more requests to be processed in the same RTSP session context that the first request creates. In other words, a client can ask for two or more media streams to be set up and then played, without waiting for a response in between ๐ This speeds up the start-up time of an RTSP session by at least one RTT โก
Now, if a pipelined request depends on one or more earlier requests succeeding, the requester has to verify that everything actually ran as expected ๐ง A classic example is two SETUP requests followed by a PLAY request. If one of the SETUP requests fails unexpectedly, the PLAY request can still run successfully ๐ณ But the result won't be what the client expected, because only one media stream gets played instead of two. In that case, the client can send a PAUSE request, fix the failing SETUP request, and then ask for it to be played ๐
13. Method Definitions ๐
The method says what should be done to the resource identified by the Request-URI ๐ฏ Method names are case sensitive, and new methods may be defined in the future ๐ฎ Method names MUST NOT start with a $ character (decimal 36), and they MUST be a token, as defined by the ABNF [RFC5234] in Section 20 ๐งพ The methods are summarized in Table 7 below ๐
+---------------+-----------+--------+-------------+-------------+
| method | direction | object | Server req. | Client req. |
+---------------+-----------+--------+-------------+-------------+
| DESCRIBE | C -> S | P,S | recommended | recommended |
| | | | | |
| GET_PARAMETER | C -> S | P,S | optional | optional |
| | | | | |
| | S -> C | P,S | optional | optional |
| | | | | |
| OPTIONS | C -> S | P,S | required | required |
| | | | | |
| | S -> C | P,S | optional | optional |
| | | | | |
| PAUSE | C -> S | P,S | required | required |
| | | | | |
| PLAY | C -> S | P,S | required | required |
| | | | | |
| PLAY_NOTIFY | S -> C | P,S | required | required |
| | | | | |
| REDIRECT | S -> C | P,S | optional | required |
| | | | | |
| SETUP | C -> S | S | required | required |
| | | | | |
| SET_PARAMETER | C -> S | P,S | required | optional |
| | | | | |
| | S -> C | P,S | optional | optional |
| | | | | |
| TEARDOWN | C -> S | P,S | required | required |
| | | | | |
| | S -> C | P | required | required |
+---------------+-----------+--------+-------------+-------------+
Table 7: Overview of RTSP Methods
Note on Table 7: This table covers RTSP methods, their direction, and the objects they operate on (P: presentation, S: stream) ๐๏ธ It also shows whether a server or client implementation is required (mandatory), recommended, or optional ๐
Further note on Table 7: GET_PARAMETER is optional ๐ For example, a fully functional server can be built to deliver media without any parameters at all. SET_PARAMETER, though, is required, meaning mandatory to implement for the server, because it's used for keep-alive ๐ PAUSE is required too, because it's the only way to leave the Play state without terminating the whole session ๐
If an RTSP agent doesn't support a particular method, it MUST return a 501 (Not Implemented) response code. The requesting RTSP agent, in turn, SHOULD NOT try that method again for the given agent/resource combination ๐
โโ๏ธ An RTSP proxy whose main function is to log or audit, and which doesn't modify transport or media handling in any way, MAY forward RTSP messages with unknown methods ๐ต๏ธโโ๏ธ Just note that the proxy still needs to do the minimal required processing, like adding the Via header ๐ซถ
13.1. OPTIONS ๐
okay bestie, the RTSP OPTIONS method is giving major HTTP OPTIONS energy, see Section 4.3.7 of [RFC7231] ๐ธ but here's the twist: in RTSP, OPTIONS is bidirectional, so a client can send the request to a server and vice versa ๐โจ. A client MUST implement the capability to send an OPTIONS request, and a server or a proxy MUST implement the capability to respond to an OPTIONS request. On top of that "MUST-implement" stuff, clients, servers and proxies MAY provide support both for sending OPTIONS requests and for generating responses to the requests ๐.
an OPTIONS request can be issued at any time ๐ฐ๏ธ and it does not modify the session state ๐ โโ๏ธ. It may prolong the session lifespan though (see below) ๐ฆ. The URI in an OPTIONS request decides the scope of the request and the matching response, and the vibes depend on what you point at:
- If the Request-URI refers to a specific media resource on a given host, the scope is limited to the set of methods supported for that media resource by the indicated RTSP agent ๐ฌ.
- A Request-URI with only the host address limits the scope to the specified RTSP agent's general capabilities, without regard to any specific media ๐ง.
- If the Request-URI is an asterisk ("*"), the scope is limited to the general capabilities of the next hop (i.e., the RTSP agent in direct communication with the request sender) ๐.
no matter what the scope is, the Public header MUST always be included in the OPTIONS response, listing the methods that are supported by the responding RTSP agent ๐. Also, if the scope of the request is limited to a media resource, the Allow header MUST be included in the response to enumerate the set of methods that are allowed for that resource, unless the set of methods completely matches the set in the Public header ๐. If the given resource is not available, the RTSP agent SHOULD return an appropriate response code, such as 3rr or 4xx ๐. The Supported header MAY be included in the request to query the set of features that are supported by the responding RTSP agent ๐ซถ.
the OPTIONS method can be used to keep an RTSP session alive, BUT this is not the preferred way of session keep-alive signaling, so see Section 18.49 ๐. An OPTIONS request intended for keeping alive an RTSP session MUST include the Session header with the associated session identifier ๐. Such a request SHOULD also use the media or the aggregated control URI as the Request-URI ๐.
Example:
C->S: OPTIONS rtsp://server.example.com RTSP/2.0
CSeq: 1
User-Agent: PhonyClient/1.2
Proxy-Require: gzipped-messages
Supported: play.basic
S->C: RTSP/2.0 200 OK
CSeq: 1
Public: DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, OPTIONS
Supported: play.basic, setup.rtp.rtcp.mux, play.scale
Server: PhonyServer/1.1
Note that the "gzipped-messages" feature tag in the Proxy-Require is a fictitious feature ๐งธ.
13.2. DESCRIBE ๐ง
the DESCRIBE method is used to retrieve the description of a presentation or media object from a server ๐. The Request-URI of the DESCRIBE request identifies the media resource of interest ๐ฏ. The client MAY include the Accept header in the request to list the description formats that it understands ๐. The server MUST respond with a description of the requested resource and return the description in the message body of the response, if the DESCRIBE method request can be successfully fulfilled โ . The DESCRIBE reply-response pair constitutes the media initialization phase of RTSP ๐.
The DESCRIBE response SHOULD contain all media initialization information for the resource(s) that it describes ๐. Servers SHOULD NOT use the DESCRIBE response as a means of media indirection by having the description point at another server ๐ โโ๏ธ. Instead, using the 3rr responses is RECOMMENDED ๐ .
By forcing a DESCRIBE response to contain all media initialization information for the set of streams that it describes, and discouraging the use of DESCRIBE for media indirection, any looping problems can be avoided that might have resulted from other approaches ๐โจ.
Example:
C->S: DESCRIBE rtsp://server.example.com/fizzle/foo RTSP/2.0
CSeq: 312
User-Agent: PhonyClient/1.2
Accept: application/sdp, application/example
S->C: RTSP/2.0 200 OK
CSeq: 312
Date: Thu, 23 Jan 1997 15:35:06 GMT
Server: PhonyServer/1.1
Content-Base: rtsp://server.example.com/fizzle/foo/
Content-Type: application/sdp
Content-Length: 358
v=0
o=MNobody 2890844526 2890842807 IN IP4 192.0.2.46
s=SDP Seminar
i=A Seminar on the session description protocol
u=http://www.example.com/lectures/sdp.ps
e=seminar@example.com (Seminar Management)
c=IN IP4 0.0.0.0
a=control:*
t=2873397496 2873404696
m=audio 3456 RTP/AVP 0
a=control:audio
m=video 2232 RTP/AVP 31
a=control:video
Media initialization is a requirement for any RTSP-based system, but the RTSP specification does not dictate that this is required to be done via the DESCRIBE method ๐ค. There are three ways that an RTSP client may receive initialization information ๐:
- via an RTSP DESCRIBE request ๐จ
- via some other protocol (HTTP, email attachment, etc.) ๐
- via some form of user interface ๐ฅ๏ธ
If a client obtains a valid description from an alternate source, the client MAY use this description for initialization purposes without issuing a DESCRIBE request for the same media ๐. The client should use any MTag to either validate the presentation description or make the session establishment conditional on being valid ๐.
It is RECOMMENDED that minimal servers support the DESCRIBE method, and highly recommended that minimal clients support the ability to act as "helper applications" that accept a media initialization file from a user interface, or other means that are appropriate to the operating environment of the clients ๐ ๏ธ๐.
13.3. SETUP โจ
okay so bestie, SETUP is where the whole session gets born ๐ฆ Before we dig in, here are the states we're tracking for a session once it exists. The state changes are driven by what the protocol messages do. (More state machine details live in Appendix B, go look if you're curious ๐)
Init: Initial state. No session exists. ๐คReady: Session is ready to start playing. ๐ฌPlay: Session is playing, i.e., sending media-stream data in the directionS->C. ๐ถ
A SETUP request for a URI says which transport mechanism the streamed media should use ๐ SETUP can do two jobs: creating an RTSP session, and changing the transport parameters of media streams that are already set up. It works in all three states (Init, Ready, and Play) for changing transport parameters. On top of that, Init and Ready are the states where you can create the session. Using SETUP in the Play state to add a media resource to the session? That one is left unspecified, so no promises there ๐
The Transport header (see Section 18.54) carries the media-transport parameters the client is okay with for data transmission. The server's response then has the transport parameters it actually picked. The client lists its acceptable mechanisms and parameters in descending order of preference, so the server can choose the best fit ๐ The session description format is expected to let the client narrow things down to a handful of configurations to offer the server, which is so iconic. All transport-related parameters SHALL be included in the Transport header. Putting this info in other headers instead is NOT RECOMMENDED, because of middleboxes like firewalls or NATs ๐งฑ
For the benefit of any intervening firewalls, a client MUST indicate the known transport parameters, even if it has no say over them. For example, the server might advertise a fixed multicast address as the destination ๐ก
Since SETUP carries all the transport initialization info, firewalls and other intermediate network devices (which need this info) don't have to do the super tedious job of parsing the DESCRIBE response, which is saved for media initialization. Lowkey genius ๐ง โจ
The client MUST include the Accept-Ranges header in the request, listing all supported unit formats in the Range header. This lets the server know which formats it can use in future session-related responses, like a PLAY response with no range in the request ๐ If the client doesn't support a time format the presentation needs, the server MUST respond with 456 (Header Field Not Valid for Resource) and include the Accept-Ranges header listing the range unit formats supported for the resource ๐ โโ๏ธ
In a SETUP response, the server MUST include the Accept-Ranges header (see Section 18.5) to say which time formats are acceptable for this media resource ๐ฐ๏ธ
The SETUP 200 OK response MUST include the Media-Properties header (see Section 18.29). The combination of its parameters shows what kind of content is in the session (see also Section 4.7) ๐ For example, a live stream with time shifting looks like this:
- Random access set to
Random-Access, - Content Modifications set to
Time-Progressing, and - Retention set to
Time-Duration(with a specific recording window time value).
The SETUP 200 OK response MUST include the Media-Range header (see Section 18.30) if the media is Time-Progressing โฉ
Here's a basic SETUP example, bestie ๐
C->S: SETUP rtsp://example.com/foo/bar/baz.rm RTSP/2.0
CSeq: 302
Transport: RTP/AVP;unicast;dest_addr=":4588"/":4589",
RTP/AVP/TCP;unicast;interleaved=0-1
Accept-Ranges: npt, clock
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 200 OK
CSeq: 302
Date: Thu, 23 Jan 1997 15:35:06 GMT
Server: PhonyServer/1.1
Session: QKyjN8nt2WqbWw4tIYof52;timeout=60
Transport: RTP/AVP;unicast;dest_addr="192.0.2.53:4588"/
"192.0.2.53:4589"; src_addr="198.51.100.241:6256"/
"198.51.100.241:6257"; ssrc=2A3F93ED
Accept-Ranges: npt
Media-Properties: Random-Access=3.2, Time-Progressing,
Time-Duration=3600.0
Media-Range: npt=0-2893.23
So in this one, the client wants a session for the media resource rtsp://example.com/foo/bar/baz.rm ๐๏ธ Its acceptable transport options are either RTP/AVP/UDP (UDP is the default), received on client ports 4588 and 4589 at the address the RTSP setup connection comes from, or RTP/AVP interleaved over the RTSP control channel. The server goes with RTP/AVP/UDP, and it adds the addresses and ports it'll send and receive RTP and RTCP on, plus the RTP SSRC it'll use ๐ซถ
The server MUST generate a session identifier in response to a successful SETUP request, unless the SETUP request to the server includes a session identifier or a Pipelined-Requests header referencing an existing session context. In that second case, the server MUST either bundle this SETUP request into the existing session (an aggregated session) or return error code 459 (Aggregate Operation Not Allowed) (see Section 17.4.23) ๐งฉ An aggregate control URI MUST be used to control an aggregated session. This URI MUST be different from the stream control URIs of the individual media streams in the aggregate (see Section 13.4.2 for aggregated sessions, and Appendix D.1.1 for the actual URIs) ๐ The session description specifies the aggregate control URI if the server supports aggregated control and the session wants it.
Even if aggregated control is offered, the client MAY choose not to set up the session with aggregated control. If the session description doesn't specify an aggregate control URI, that normally means non-aggregated control should be used ๐คทโโ๏ธ
Setting up media streams inside an aggregate that doesn't have an aggregated control URI is unspecified. ๐
While the session ID sometimes has enough info for aggregate control of a session, the aggregate control URI still matters for some methods, like SET_PARAMETER, where the control URI makes it easy to figure out which resource is in question. It's also useful for proxies, which use it to route requests to the right server, and for logging, since it's handy to see the actual resource a request was working on ๐
A session sticks around until either a TEARDOWN request removes it or the server times it out โณ The server MAY remove a session that hasn't shown signs of liveness from the client(s) within a certain timeout period. The default timeout is 60 seconds, but the server MAY set a different value and show that in the timeout field of the Session header in the SETUP response. For more on this, see Section 18.49 ๐ Signs of liveness for an RTSP session include any RTSP requests from a client that contain a Session header with that session's ID, plus RTCP sender or receiver reports if RTP carries the underlying media stream. RTCP sender reports might, for example, show up in a session where the server has been invited into a conference session, which means they count as a liveness indicator too ๐ถ
If a SETUP request on a session fails for any reason, the session state, plus the transport and other parameters for the associated streams, MUST stay unchanged from what they were as if the SETUP request had never reached the server ๐ก๏ธ
13.3.1. Changing Transport Parameters
A client MAY send a SETUP request for a stream that's already set up or playing in the session to change its transport parameters, and a server MAY allow that ๐ If the server doesn't allow changing the parameters, it MUST respond with error 455 (Method Not Valid in This State). Why bother changing transport parameters? It lets you have application-layer mobility and flexibility to use the best available transport as it shows up ๐ If a client gets a 455 error when trying to change transport parameters while the server is in the Play state, it MAY try to put the server into the Ready state using PAUSE before sending the SETUP request again. If that fails too, changing the transport parameters means the client has to TEARDOWN the affected media and set it up again. For an aggregated session, not tearing down all the media at the same time avoids creating a new session ๐ซง
All transport parameters MAY be changed. The main usage expected, though, is either swapping the transport protocol completely (like going from Interleaved TCP mode to UDP or the other way around), or changing the delivery address ๐ฎ
In a SETUP response to a request that changes transport parameters while in the Play state, the server MUST include the Range header to show the point at which the new transport parameters take effect ๐ฏ Also, if RTP is used for delivery, the server MUST include the RTP-Info header to show the timestamp and RTP sequence number where the change happens. If both RTP-Info and Range are in the response, the "rtp_time" parameter and the start point in the Range header MUST refer to the same time, meaning they're used the same way as for PLAY, so the sync info stays correct ๐ต
If a transport-parameter change made in the Play state changes sync-related info (for example, changing the RTP SSRC), the server MUST include the necessary sync info in the SETUP response. However, the server SHOULD avoid changing the sync info if it can ๐
13.4. PLAY โจ
This section explains how the PLAY method is used in general, for aggregated sessions, and in different usage scenarios. Let's get into it, bestie ๐
13.4.1. General Usage โจ
Okay bestie, PLAY is the request that tells the server to start sending data through whatever mechanism SETUP set up, and it also says which part of the media should get played out ๐. PLAY requests are only valid when the session is in Ready or Play state ๐. A PLAY request MUST include a Session header so the server knows which session the request is for ๐ซถ.
Okay so when the server gets a PLAY request, it MUST move the normal play time to the start of the range in the Range header ๐ฆ. That only works within the limits of the media resource, and it has to follow the Seek-Style header (Section 18.47) ๐ . The server MUST keep delivering stream data until the end of the range (if there is one), until a new PLAY request shows up, until a PAUSE request (Section 13.5) shows up, or until the end of the media is reached ๐ญ. If there's no Range header in the PLAY request, the server SHALL play from the current pause point until the end of the media ๐.
The pause point starts out at the beginning of the media when the session starts ๐. For media that's time-progressing with no retention, the pause point always gets set to NPT "now", i.e., the current delivery point โฐ. The pause point can also be set to a specific spot in the media with the PAUSE method, see Section 13.6 ๐ง. For media that's currently playing, the pause point is the current media position ๐. And for time-progressing media with time-limited retention, if the pause point is older than what the server still keeps, it gets moved up to the oldest retained position ๐ฅบ.
What range values are valid depends on the type of content ๐ญ. For content that isn't time-progressing, a range value is valid if it's part of any media in the aggregate. Basically, the valid media range for the aggregate is the union of all the media components in it ๐งฉ. If a range points outside the media, the response MUST be 457 (Invalid Range) and include the Media-Range header (Section 18.30) with the valid range for the media ๐ .
Except for time-progressing content where the client asks for a start point before what's retained, the start point gets adjusted to the oldest retained content. If the start point is past the media front edge (aka beyond the current value for "now"), the server SHALL adjust the start value to the current front edge โฉ. The stop point in the Range header may point beyond the current media edge. In that case, the server SHALL deliver media from the requested (and possibly adjusted) start point until whichever comes first: the provided stop point or the end of the media ๐. PSA: if you just want to play from a start point until the end of the media, a Range header with an implicit stop point is RECOMMENDED ๐.
If a client asks to start playing at the end of the media, whether explicitly with a Range header or implicitly through a pause point sitting at the end, a 457 (Invalid Range) error MUST be sent and include the Media-Range header (Section 18.30) ๐. The Range header also must be included in the response, and it carries the pause point in the media when the session is in Ready State. This also applies if the pause point or requested start point is at the beginning of the media and a Scale header (Section 18.46) is included with a negative value (playing backwards) ๐.
For media with random access properties, a client may say which start point selection policy the server should use. It does that by including the Seek-Style header (Section 18.47) in the PLAY request ๐ฏ. The Seek-Style applied changes the Range header, since that's how it shows where the media is actually delivered from ๐ง.
If a client wants the media from the very beginning, it MUST send a PLAY request with a Range header pointing at the beginning, like "npt=0-" ๐ผ. If a PLAY request has no Range header and delivery already stopped at the end, the server SHOULD respond with a 457 (Invalid Range) error response. In that response, the current pause point MUST be included in a Range header ๐ฆ.
Every range specifier here allows an implicit start point (like "npt=-30") ๐. In a PLAY request, the server reads that as "start or resume from the current pause point and end at the end time in the Range header" โฏ๏ธ. If the pause point is later than the given end value, a 457 (Invalid Range) response MUST be returned ๐ซ.
Here's an example that plays seconds 10 through 25 ๐ฌ. It also asks the server to deliver media starting from the first random access point before the indicated start point ๐๏ธ.
C->S: PLAY rtsp://audio.example.com/audio RTSP/2.0
CSeq: 835
Session: ULExwZCXh2pd0xuFgkgZJW
Range: npt=10-25
Seek-Style: RAP
User-Agent: PhonyClient/1.2
Servers MUST include a Range header in any PLAY response, even if the request didn't have one ๐ฃ. The response MUST use the same format as the Range header in the request. If the request had no Range header, the format from any earlier PLAY request in the session SHOULD be used ๐. If no format was indicated in a previous request, the server MAY use any time format the media supports that's listed in the Accept-Ranges header in the SETUP request ๐จ. It is RECOMMENDED that NPT is used if the media supports it ๐.
For any error response to a PLAY request, what the server sends back depends on the session state ๐ง . In Ready state, the current pause point comes back in a Range header, with the pause point as the explicit start and an implicit stop point ๐. For time-progressing content where the pause point moves in real time because retention is limited, the current pause point comes back ๐ฐ๏ธ. In Play state, the current playout point and the remaining parts of the range request come back instead ๐ถ. And for any media with retention longer than 0 seconds, the currently valid Media-Range header SHALL also be included in the response ๐งพ.
A PLAY response MAY include a header carrying synchronization information ๐ค. Since what's needed depends on the media-transport format, further rules specifying the header and its usage are needed. For RTP, the RTP-Info header is specified (see Section 18.45), and the example below uses it ๐ง.
Here's a simple one for a single audio stream where the client asks for the media from 3.52 seconds to the end ๐ต. The server sends back a 200 OK with the actual play time, which is 10 ms earlier (3.51), plus the RTP-Info header with the parameters the RTP stack needs ๐ฅฐ.
C->S: PLAY rtsp://example.com/audio RTSP/2.0
CSeq: 836
Session: ULExwZCXh2pd0xuFgkgZJW
Range: npt=3.52-
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 200 OK
CSeq: 836
Date: Thu, 23 Jan 1997 15:35:06 GMT
Server: PhonyServer/1.0
Range: npt=3.51-324.39
Seek-Style: First-Prior
Session: ULExwZCXh2pd0xuFgkgZJW
RTP-Info:url="rtsp://example.com/audio"
ssrc=0D12F123:seq=14783;rtptime=2345962545
S->C: RTP Packet TS=2345962545 => NPT=3.51
Media duration=0.16 seconds
The server replies with the actual start point it'll deliver ๐ซง. That can differ from the requested range if the requested range has to line up with valid frame boundaries for the media source ๐. Heads up that some media streams in an aggregate may need to be delivered from even earlier points ๐. Also, some media formats have a really long duration per data unit, so the client might need to parse the data unit and pick where to start โ๏ธ. The server SHALL also indicate which policy it used to pick the actual start point, by including a Seek-Style header ๐.
In the next example, the client gets the first media packet that stretches all the way up to and past the requested playtime ๐ฅน. So it's the client's call whether to render the time between 3.52 and 7.05 to the user or skip it. Most of the time, it's probably most suitable not to render that stretch ๐.
C->S: PLAY rtsp://example.com/audio RTSP/2.0
CSeq: 836
Session: ZGGyCJOs8xaLkdNK2dmxQO
Range: npt=7.05-
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 200 OK
CSeq: 836
Date: Thu, 23 Jan 1997 15:35:06 GMT
Server: PhonyServer/1.0
Session: ZGGyCJOs8xaLkdNK2dmxQO
Range: npt=3.52-
Seek-Style: First-Prior
RTP-Info:url="rtsp://example.com/audio"
ssrc=0D12F123:seq=14783;rtptime=2345962545
S->C: RTP Packet TS=2345962545 => NPT=3.52
Duration=4.15 seconds
After playing the range you wanted, the presentation does not change to Ready state, and media delivery just stops ๐. If you need the stream back in Ready state, a PAUSE request MUST be issued ๐. A PLAY request while the stream is still in Play state is legal and can be sent without a PAUSE request in between ๐. That request MUST replace the current PLAY action with the new one, i.e., it's handled the same way it would be if it arrived in Ready state ๐. If the range in the Range header has an implicit start time ("-endtime"), the server MUST keep playing from where it currently is until the specified endpoint ๐. This is handy for changing the end to a different point than the previous request ๐ซถ.
The following example plays the whole presentation starting at SMPTE time code 0:10:20 until the end of the clip ๐๏ธ. Heads up: the RTP-Info headers are broken into several lines here, and the continuation lines start with whitespace, which the syntax allows ๐.
C->S: PLAY rtsp://audio.example.com/twister.en RTSP/2.0
CSeq: 833
Session: N465Wvsv0cjUy6tLqINkcf
Range: smpte=0:10:20-
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 200 OK
CSeq: 833
Date: Thu, 23 Jan 1997 15:35:06 GMT
Session: N465Wvsv0cjUy6tLqINkcf
Server: PhonyServer/1.0
Range: smpte=0:10:22-0:15:45
Seek-Style: Next
RTP-Info:url="rtsp://example.com/twister.en"
ssrc=0D12F123:seq=14783;rtptime=2345962545
For playing back a recording of a live presentation, it may be handy to use clock units โฑ๏ธ.
C->S: PLAY rtsp://audio.example.com/meeting.en RTSP/2.0
CSeq: 835
Session: N465Wvsv0cjUy6tLqINkcf
Range: clock=19961108T142300Z-19961108T143520Z
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 200 OK
CSeq: 835
Date: Thu, 23 Jan 1997 15:35:06 GMT
Session: N465Wvsv0cjUy6tLqINkcf
Server: PhonyServer/1.0
Range: clock=19961108T142300Z-19961108T143520Z
Seek-Style: Next
RTP-Info:url="rtsp://example.com/meeting.en"
ssrc=0D12F123:seq=53745;rtptime=484589019
13.4.2. Aggregated Sessions โจ
okay so PLAY requests can work on sessions that control one single media stream, OR on aggregated sessions that control a bunch of media streams at once ๐
in an aggregated session, the PLAY request MUST contain an aggregated control URI ๐ and if the client's PLAY Request-URI points at just one single media, the server MUST respond with a 460 error (Only Aggregate Operation Allowed) ๐ the media in an aggregate MUST be played in sync ๐ซถ and if a client wants to control each media separately, it needs separate RTSP sessions for each one. no shortcuts, bestie ๐
for aggregated sessions where the very first SETUP request (the one that creates the session) is followed by one or more extra SETUP requests, a PLAY request MAY be pipelined (Section 12) after those extra SETUP requests without waiting for their responses ๐ฆ this can cut the delay from the start of session setup until media playout begins by one RTT, which is iconic โจ but ngl, the client needs to be aware that this means the playout uses the server state at the moment the PLAY gets processed, i.e., after all the requests ahead of the PLAY in the pipeline have been processed ๐ that state might not be the one you actually wanted if any of those earlier requests failed ๐ the client can easily check this from the responses to those requests. and if something failed, the client can halt playout with PAUSE and try to set up the intended state again before sending another PLAY request ๐ธ
13.4.3. Updating Current PLAY Requests ๐ฆ
clients can send PLAY requests while the stream is already in Play state, and that's how they update their request ๐
the big difference compared to a PLAY request in Ready state is how the current play point gets handled and how the Range header is built ๐ the session is actively playing and the play point keeps moving, so it's hard to predict exactly when a request will take effect ๐ญ depending on how the PLAY header looks, there are two cases: total replacement or continuation ๐ฅ
a total replacement is signaled when the first range specification has an explicit start value, like "npt=45-" or "npt=45-60" ๐ซถ in that case, the server stops playout at the current play point and then starts delivering media according to the Range header. it's basically the same as the client sending a PAUSE first and then a new PLAY that isn't based on the pause point โจ
in the case of continuation, the first range specifier has an implicit start point and an explicit stop value (Z), like "npt=-60" ๐ this tells the server it MUST convert the range specifier being played before this PLAY request (X to Y) into (X to Z), and continue as if this was the request originally played ๐ if the current delivery point is already beyond the stop point, the server SHALL immediately pause delivery ๐ since the request completed successfully, it gets a 200 OK response ๐ a PLAY_NOTIFY with end-of-stream is also sent to show the actual stop point ๐ and the pause point is set to the requested stop point ๐ฅ
here's an example. the server got requests to play ranges 10 to 15 ๐ if the new PLAY request shows up 4 seconds after the previous one, it takes effect while the server is still playing the first range (10-15) ๐ญ the server changes the current play to continue to 25 seconds, so the equivalent single request would be PLAY with "range: npt=10-25" ๐
C->S: PLAY rtsp://example.com/fizzle/foo RTSP/2.0
CSeq: 834
Session: apzA8LnjQ5KWTdw0kUkiRh
Range: npt=10-15
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 200 OK
CSeq: 834
Date: Thu, 23 Jan 1997 15:35:06 GMT
Session: apzA8LnjQ5KWTdw0kUkiRh
Server: PhonyServer/1.0
Range: npt=10-15
Seek-Style: Next
RTP-Info:url="rtsp://example.com/fizzle/audiotrack"
ssrc=0D12F123:seq=5712;rtptime=934207921,
url="rtsp://example.com/fizzle/videotrack"
ssrc=789DAF12:seq=57654;rtptime=2792482193
C->S: PLAY rtsp://example.com/fizzle/foo RTSP/2.0
CSeq: 835
Session: apzA8LnjQ5KWTdw0kUkiRh
Range: npt=-25
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 200 OK
CSeq: 835
Date: Thu, 23 Jan 1997 15:35:09 GMT
Session: apzA8LnjQ5KWTdw0kUkiRh
Server: PhonyServer/1.0
Range: npt=14-25
Seek-Style: Next
RTP-Info:url="rtsp://example.com/fizzle/audiotrack"
ssrc=0D12F123:seq=5712;rtptime=934239921,
url="rtsp://example.com/fizzle/videotrack"
ssrc=789DAF12:seq=57654;rtptime=2792842193
a super common use of PLAY while in Play state is changing the scale of the media, like entering or leaving fast forward or fast rewind โญ the client can send an updating PLAY that's either a continuation or a complete replacement, as discussed above in this section ๐ง below, a client requests fast forward (scale = 2) without a stop point, and then switches from fast forward back to regular playout (scale = 1) ๐ in the second PLAY request, the time is set explicitly to wherever the server is currently playing (npt=now-), and the server responds with the actual playback point where the new scale actually takes effect (npt=02:17:27.144-) ๐
C->S: PLAY rtsp://example.com/fizzle/foo RTSP/2.0
CSeq: 2034
Session: apzA8LnjQ5KWTdw0kUkiRh
Range: npt=now-
Scale: 2.0
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 200 OK
CSeq: 2034
Date: Thu, 23 Jan 1997 15:35:06 GMT
Session: apzA8LnjQ5KWTdw0kUkiRh
Server: PhonyServer/1.0
Range: npt=02:17:21.394-
Seek-Style: Next
Scale: 2.0
RTP-Info:url="rtsp://example.com/fizzle/audiotrack"
ssrc=0D12F123:seq=5712;rtptime=934207921,
url="rtsp://example.com/fizzle/videotrack"
ssrc=789DAF12:seq=57654;rtptime=2792482193
[playing in fast forward and now returning to scale = 1]
C->S: PLAY rtsp://example.com/fizzle/foo RTSP/2.0
CSeq: 2035
Session: apzA8LnjQ5KWTdw0kUkiRh
Range: npt=now-
Scale: 1.0
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 200 OK
CSeq: 2035
Date: Thu, 23 Jan 1997 15:35:09 GMT
Session: apzA8LnjQ5KWTdw0kUkiRh
Server: PhonyServer/1.0
Range: npt=02:17:27.144-
Seek-Style: Next
Scale: 1.0
RTP-Info:url="rtsp://example.com/fizzle/audiotrack"
ssrc=0D12F123:seq=5712;rtptime=934239921,
url="rtsp://example.com/fizzle/videotrack"
ssrc=789DAF12:seq=57654;rtptime=2792842193
13.4.4. Playing On-Demand Media ๐
on-demand media is indicated by the content of the Media-Properties header in the SETUP response when (see also Section 18.29):
- the Random Access property is set to Random-Access ๐
- the Content Modifications property is set to Immutable ๐
- the Retention property is set to Unlimited or Time-Limited ๐ซถ
playing on-demand media follows the general usage described in Section 13.4.1 โจ
13.4.5. Playing Dynamic On-Demand Media ๐
dynamic on-demand media is indicated by the content of the Media-Properties header in the SETUP response when (see also Section 18.29):
- the Random Access property is set to Random-Access ๐
- the Content Modifications property is set to Dynamic ๐ฆ
- the Retention property is set to Unlimited or Time-Limited ๐
playing on-demand media follows the general usage described in Section 13.4.1 as long as the media has not been changed ๐
there are two ways for the client to find out about changes to media resources while in Play state ๐ the first is that the client receives a PLAY_NOTIFY request with the Notify-Reason header set to media-properties-update (see Section 13.5.2) ๐ฅ the client can use the value of the Media-Range header to decide what to do next, if the Media-Range header is present in the PLAY_NOTIFY request ๐ the second way is that the client sends a GET_PARAMETER request with no body but including a Media-Range header ๐ง the 200 OK response MUST include the current Media-Range header (see Section 18.30) ๐ซถ
13.4.6. Playing Live Media ๐ธ
live media is indicated by the content of the Media-Properties header in the SETUP response when (see also Section 18.29):
- the Random Access property is set to No-Seeking ๐
- the Content Modifications property is set to Time-Progressing ๐
- the Retention property's Time-Duration is set to 0.0 ๐
for live media, the SETUP 200 OK response MUST include the Media-Range header (see Section 18.30) โจ
a client MAY send PLAY requests without the Range header ๐ฆ if the request includes the Range header, it MUST use a symbolic value representing "now" ๐ for NPT, that range specification is "npt=now-" ๐ the server MUST include the Range header in the response, and it MUST indicate an explicit time value and not a symbolic value ๐ญ in other words, "npt=now-" cannot be used in the response ๐ โโ๏ธ instead, the time since session start is recommended, expressed as an open interval, e.g., "npt=96.23-" ๐ an absolute time value (clock) for the corresponding time MAY be given, i.e., "clock=20030213T143205Z-" ๐ฐ๏ธ the Absolute Time format can only be used if the client has shown support for it using the Accept-Ranges header ๐ฅ
13.4.7. Playing Live with Recording ๐
certain media servers may offer recording services of live sessions to their clients ๐ผ this recording would normally be from the beginning of the media session ๐ clients can randomly access the media between now and the beginning of the media session ๐ this live media with recording is indicated by the content of the Media-Properties header in the SETUP response when (see also Section 18.29):
- the Random Access property is set to Random-Access ๐ฆ
- the Content Modifications property is set to Time-Progressing ๐ซถ
- the Retention property is set to Time-Limited or Unlimited ๐
the SETUP 200 OK response MUST include the Media-Range header (see Section 18.30) for this type of media ๐ธ for live media with recording, the Range header indicates the current delivery point in the media, and the Media-Range header indicates the currently available media window around the current time โญ this window can cover recorded content in the past (seen from current time in the media) or recorded content in the future (seen from current time in the media) ๐ง the server adjusts the delivery point to the requested border of the window ๐ if the client requests a delivery point outside the recording window, e.g., if the requested point is too far in the past, the server selects the oldest point in the recording ๐ the considerations in Section 13.5.3 apply if a client requests delivery with scale (Section 18.46) values other than 1.0 (normal playback rate) while delivering live media with recording ๐ฅ
13.4.8. Playing Live with Time-Shift โชโจ
okay so some media servers offer time-shift to their clients, which is basically DVR energy ๐ผ. The server records a fixed interval in the past (a sliding window, bestie), but it won't record anything older than that interval. Clients can randomly jump to any point between now and the start of that window ๐ฆ. This live-with-recording setup shows up in the Media-Properties header of the SETUP response when (see also Section 18.29):
- the Random Access property is set to
Random-Access; - the Content Modifications property is set to
Time-Progressing; - the Retention property is set to
Time-Durationand a value indicating the recording interval (>0).
The SETUP 200 OK response MUST include the Media-Range header (see Section 18.30) for this type of media ๐. For live media with recording, the Range header tells you the current time in the media, and the Media-Range header shows a window around that current time ๐ฐ๏ธ. That window can cover recorded content in the past (seen from the current media time) or in the future (also seen from the current media time) ๐ฎ. If a client asks for a play point outside the recording window, like way too far in the past, the server adjusts the play point to the requested border of the window. e.g., the server selects the oldest range in the recording ๐ซ . The considerations in Section 13.5.3 apply if a client requests delivery using a scale (Section 18.46) value other than 1.0 (normal playback rate) while delivering live media with time-shift ๐ฌ.
13.5. PLAY_NOTIFY ๐ฃ
The PLAY_NOTIFY method is how a server lets a client know about an asynchronous event for a session that's in Play state ๐. The Session header MUST be presented in a PLAY_NOTIFY request, and it indicates the scope of the request. Sending PLAY_NOTIFY requests requires a persistent connection between server and client, because otherwise there's no way for the server to send this request method to the client ๐.
PLAY_NOTIFY requests have an end-to-end (that is, server-to-client) scope, since they carry the Session header and only apply to the given session ๐ . The client SHOULD immediately return a response to the server.
PLAY_NOTIFY requests MAY use both an aggregate control URI and individual media resource URIs, depending on the scope of the notification ๐งฉ. This scope can matter a lot for aggregated sessions, so each reason for a PLAY_NOTIFY request needs to spell out how it's interpreted, and whether aggregated control URIs or individual URIs may be used in requests.
PLAY_NOTIFY requests can carry a message body, depending on the value of the Notify-Reason header. Each Notify-Reason section says whether a message body is used. Right now, though, there's no Notify-Reason that allows a message body ๐. So when people add new Notify-Reasons that want a message body, there are some limits to keep in mind: the server can send any type of message body, but there's no guarantee the client can understand it. DESCRIBE has a similar issue (see Section 13.2), but in this case the client can state which message bodies it accepts by using the Accept header. With PLAY_NOTIFY, the server doesn't know which message bodies the client understands.
The Notify-Reason header (see Section 18.32) explains why the server is sending the PLAY_NOTIFY request ๐. This list is extensible, and new reasons can be added in the future (see Section 22.8). If the client doesn't understand the reason for the notification, it MUST respond with a 465 (Notification Reason Unknown) (Section 17.4.29) error code ๐. This document defines how servers can send PLAY_NOTIFY with these Notify-Reason values:
- end-of-stream (see Section 13.5.1);
- media-properties-update (see Section 13.5.2);
- scale-change (see Section 13.5.3).
13.5.1. End-of-Stream ๐
A PLAY_NOTIFY request with the Notify-Reason header set to end-of-stream says that the PLAY request is complete or almost complete, and that the media stream delivery is ending ๐๏ธ. The request MUST NOT be issued unless the server is in the Play state. This notification can mean either a successful finish to the PLAY request being served, or some error that stopped the request from completing. The Request-Status header (Section 18.42) MUST be included to show which request the notification is for and its completion status. The message response status codes (Section 8.1.1) show how the PLAY request ended. The sender of a PLAY_NOTIFY MAY issue an updated PLAY_NOTIFY if the earlier one had wrong information. For example, a PLAY_NOTIFY might go out before the end of the stream, but then an error means the stream actually ends at a different time. In that case, a new PLAY_NOTIFY MUST be sent with the correct completion status and all the additional information ๐.
PLAY_NOTIFY requests with the Notify-Reason header set to end-of-stream MUST include a Range header, and the Scale header if the scale value is not 1. The Range header shows the point in the stream (or streams) where delivery ends, using the timescale the server used in the PLAY response for the request being fulfilled โฑ๏ธ. The server MUST NOT use the "now" constant in the Range header. It MUST use the actual numeric end position in the proper timescale. When end-of-stream notifications go out before the last media packets have been sent, you can tell because the end time in the Range header is past the current time in the media the client is receiving, e.g., "npt=-15" if npt is currently at 14.2 seconds ๐. The Scale header is to be included so it's obvious if the media timescale is moving backwards or has a non-default pace. An end-of-stream notification doesn't stop the client from sending a new PLAY request ๐ซถ.
If RTP is used as the media transport, an RTP-Info header MUST be included, and the RTP-Info header MUST indicate the last sequence number in the sequence parameter ๐ฏ.
For an RTSP session where media resources are under aggregated control, the resources will usually end at about the same time, though there can be small differences on the scale of a few hundred milliseconds โณ. In those cases, an RTSP session under aggregated control SHOULD send only a single PLAY_NOTIFY request. By using the aggregate control URI in the PLAY_NOTIFY request, the RTSP server shows that it applies to all media resources within the session. When RTP is used for media delivery, the corresponding RTP-Info needs to be included for all media resources. When one or more media resources are significantly shorter than others in the aggregated session, the server MAY send end-of-stream notifications using individual media resource URIs. That tells agents there will be no more media for that particular resource related to the current active PLAY request. Then, when the remaining media resources reach the end of the stream, they MUST send a PLAY_NOTIFY request using the aggregate control URI to show that no more resources remain ๐.
A PLAY_NOTIFY request with the Notify-Reason header set to end-of-stream MUST NOT carry a message body ๐ซ.
This example request tells the client about a future end-of-stream event:
S->C: PLAY_NOTIFY rtsp://example.com/fizzle/foo RTSP/2.0
CSeq: 854
Notify-Reason: end-of-stream
Request-Status: cseq=853 status=200 reason="OK"
Range: npt=-145
RTP-Info:url="rtsp://example.com/fizzle/foo/audio"
ssrc=0D12F123:seq=14783;rtptime=2345962545,
url="rtsp://example.com/fizzle/video"
ssrc=789DAF12:seq=57654;rtptime=2792482193
Session: CDtUJfDQXJWtJ7Iqua2xOi
Date: Mon, 08 Mar 2010 13:37:16 GMT
C->S: RTSP/2.0 200 OK
CSeq: 854
User-Agent: PhonyClient/1.2
Session: CDtUJfDQXJWtJ7Iqua2xOi
13.5.2. Media-Properties-Update ๐ช
A PLAY_NOTIFY request with a Notify-Reason header set to media-properties-update tells the client that the media properties for the session have changed (see Section 18.29), or that the available media range it can play has changed, as shown by the Media-Range header (Section 18.30) ๐ซ. PLAY_NOTIFY requests with the Notify-Reason header set to media-properties-update MUST include a Media-Properties and Date header, and SHOULD include a Media-Range header. The Media-Properties header has session scope, so for aggregated sessions, the PLAY_NOTIFY request MUST use the aggregated control URI ๐ง .
This notification MUST be sent for time-progressing media every time an event changes the basis for estimating how the available media range will progress with wall clock time โฐ. On top of that, it is RECOMMENDED that the server send these notifications approximately every 5 minutes for time-progressing content. This keeps the client's estimates stable over the long run and lets the client detect clock skew ๐ง. The time between notifications should be greater than 1 minute and less than 2 hours. For the reasons just explained, requests MUST include a Media-Range header to give the current media duration, and a Range header to show the current playing point and any remaining parts of the requested range ๐.
The recommendation to send updates every 5 minutes is about clock skew. Within 5 minutes, the clock skew shouldn't become too significant, since this isn't used for media playback and synchronization. It's only used to figure out which content is available to the user ๐.
A PLAY_NOTIFY request with the Notify-Reason header set to media-properties-update MUST NOT carry a message body ๐ซ.
Here's what that looks like:
S->C: PLAY_NOTIFY rtsp://example.com/fizzle/foo RTSP/2.0
Date: Tue, 14 Apr 2008 15:48:06 GMT
CSeq: 854
Notify-Reason: media-properties-update
Session: CDtUJfDQXJWtJ7Iqua2xOi
Media-Properties: Time-Progressing,
Time-Limited=20080415T153919.36Z, Random-Access=5.0
Media-Range: npt=00:00:00-01:37:21.394
Range: npt=01:15:49.873-
C->S: RTSP/2.0 200 OK
CSeq: 854
User-Agent: PhonyClient/1.2
Session: CDtUJfDQXJWtJ7Iqua2xOi
13.5.3. Scale-Change โจ
okay bestie, so the server might have to change how fast media time moves compared to playback time ๐ that happens when a client asks for a scale (Section 18.46) that isn't 1.0, which is normal playback speed. ๐ฆ for time-progressing media with some retention (so the server keeps stuff it already sent), a client going at a scale larger than 1 can literally catch up to the front end of the media ๐ญ and then the server can't keep up at scale larger than 1, because content only gets made available at scale = 1. ๐
another case is when scale < 1 and the retention is Time-Duration limited ๐ the delivery point can reach the oldest media unit available, and then playback at that scale is impossible because there's nothing left to play. to keep the client from losing any media, the scale has to get adjusted to the same rate the media is being removed from the storage buffer, which is commonly scale = 1.0 ๐
another case is when the content is made of spliced pieces or gets dynamically updated โจ here the server might have to switch from one supported scale value (not scale = 1.0) to a different one. in that situation the server picks the closest value and tells the client what it picked ๐ซถ the media properties get sent too, which updates the supported scale values, so the client can adjust the scale it's using. iconic, right? ๐
to keep playback smooth in any of the cases above, the server MUST change the playback properties, set scale to a value it can actually support, and keep delivering the media ๐ while doing that, it MUST send a PLAY_NOTIFY message with the Notify-Reason header set to "scale-change" ๐ฅ that request MUST contain a Range header with the media time when the change took effect, a Scale header with the new value in use, a Session header with the identifier for the session it applies to, and a Date header with the server wallclock time of the change ๐ธ for time-progressing content, the Media-Range and Media-Properties headers at that point in time MUST also be included. the Media-Properties header MUST be included if the scale change happened because the content changed which scale values ("Scales") are supported ๐ง
for media streams delivered with RTP, an RTP-Info header MUST also be included ๐ it MUST have the rtptime parameter with a value matching the point of change in that media, and it can optionally have the sequence number too โจ
PLAY_NOTIFY requests for aggregated sessions MUST use the aggregated control URI in the request ๐ฆ and the scale change for any aggregated session applies to every media stream in the aggregate. main character energy ๐
a PLAY_NOTIFY request with Notify-Reason set to "Scale-Change" MUST NOT carry a message body ๐ โโ๏ธ no body allowed, periodt ๐
Here's the example ๐
S->C: PLAY_NOTIFY rtsp://example.com/fizzle/foo RTSP/2.0
Date: Tue, 14 Apr 2008 15:48:06 GMT
CSeq: 854
Notify-Reason: scale-change
Session: CDtUJfDQXJWtJ7Iqua2xOi
Media-Properties: Time-Progressing,
Time-Limited=20080415T153919.36Z, Random-Access=5.0
Media-Range: npt=00:00:00-01:37:21.394
Range: npt=01:37:21.394-
Scale: 1
RTP-Info: url="rtsp://example.com/fizzle/foo/audio"
ssrc=0D12F123:rtptime=2345962545,
url="rtsp://example.com/fizzle/foo/videotrack"
ssrc=789DAF12:seq=57654;rtptime=2792482193
C->S: RTSP/2.0 200 OK
CSeq: 854
User-Agent: PhonyClient/1.2
Session: CDtUJfDQXJWtJ7Iqua2xOi
13.6. PAUSE ๐
okay so PAUSE is the request that immediately interrupts (halts) stream delivery ๐ฆ a PAUSE request MUST be made either with the aggregated control URI for aggregated sessions (which halts all the media) or with the media URI for non-aggregated sessions ๐ trying to mute a single media with PAUSE in an aggregated session MUST get a 460 (Only Aggregate Operation Allowed) error, no exceptions ๐ โโ๏ธ after resuming playback, track synchronization MUST be maintained ๐ซถ the server keeps its resources, but servers MAY close the session and free resources after being paused for as long as the timeout parameter of the Session header in the SETUP message says ๐ฅบ
Example ๐ธ
C->S: PAUSE rtsp://example.com/fizzle/foo RTSP/2.0
CSeq: 834
Session: OoOUPyUwt0VeY9fFRHuZ6L
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 200 OK
CSeq: 834
Date: Thu, 23 Jan 1997 15:35:06 GMT
Session: OoOUPyUwt0VeY9fFRHuZ6L
Range: npt=45.76-75.00
so when PAUSE comes in, delivery stops right away on receipt and the pause point gets set to wherever the presentation currently is ๐ง that pause point has to be kept around โจ a PLAY request later with no Range header picks up from the pause point and plays until the media ends ๐
the pause point after any PAUSE request MUST be sent back to the client by adding a Range header with whatever is still unplayed from the PLAY request's range ๐ for media with random access properties, if you want to resume a ranged request, just include the Range header from the PAUSE response and add the Seek-Style header with the Next policy in your PLAY request ๐ฆ for time-progressing media with retention duration=0, the follow-up PLAY request to start delivery again MUST use "npt=now-" and NOT the answer from the PAUSE response ๐
Example ๐
C->S: PLAY rtsp://example.com/fizzle/foo RTSP/2.0
CSeq: 834
Session: OccldOFFq23KwjYpAnBbUr
Range: npt=10-30
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 200 OK
CSeq: 834
Date: Thu, 23 Jan 1997 15:35:06 GMT
Server: PhonyServer/1.0
Range: npt=10-30
Seek-Style: First-Prior
RTP-Info:url="rtsp://example.com/fizzle/audiotrack"
ssrc=0D12F123:seq=5712;rtptime=934207921,
url="rtsp://example.com/fizzle/videotrack"
ssrc=4FAD8726:seq=57654;rtptime=2792482193
Session: OccldOFFq23KwjYpAnBbUr
after 11 seconds, aka 21 seconds into the presentation ๐
C->S: PAUSE rtsp://example.com/fizzle/foo RTSP/2.0
CSeq: 835
Session: OccldOFFq23KwjYpAnBbUr
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 200 OK
CSeq: 835
Date: 23 Jan 1997 15:35:17 GMT
Server: PhonyServer/1.0
Range: npt=21-30
Session: OccldOFFq23KwjYpAnBbUr
if a client sends a PAUSE and the server acknowledges it and goes into the Ready state, the right server response to another PAUSE is still 200 OK ๐ the 200 OK response MUST include the Range header with the current pause point ๐ see below ๐
C->S: PAUSE rtsp://example.com/fizzle/foo RTSP/2.0
CSeq: 834
Session: OccldOFFq23KwjYpAnBbUr
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 200 OK
CSeq: 834
Session: OccldOFFq23KwjYpAnBbUr
Date: Thu, 23 Jan 1997 15:35:06 GMT
Range: npt=45.76-98.36
C->S: PAUSE rtsp://example.com/fizzle/foo RTSP/2.0
CSeq: 835
Session: OccldOFFq23KwjYpAnBbUr
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 200 OK
CSeq: 835
Session: OccldOFFq23KwjYpAnBbUr
Date: 23 Jan 1997 15:35:07 GMT
Range: npt=45.76-98.36
13.7. TEARDOWN ๐
13.7.1. Client to Server ๐ซง
okay so TEARDOWN is the client-to-server request that stops stream delivery for the given URI and frees up the resources tied to it ๐ it can be sent to either an aggregated or a media control URI, but some restrictions depend on the current state ๐ the TEARDOWN request MUST contain a Session header saying which session it applies to ๐ซถ the TEARDOWN request MUST NOT include a Terminate-Reason header ๐ โโ๏ธ
a TEARDOWN using the aggregated control URI, or the media URI in a session under non-aggregated control (single media session), MAY be done in any state (Ready and Play) ๐ฆ a successful request MUST result in that media delivery being halted immediately and the session state being destroyed โจ this MUST be indicated by the lack of a Session header in the response ๐
a TEARDOWN using a media URI in an aggregated session can only be done in Ready state ๐ธ this kind of request only removes the indicated media stream and its resources from the session ๐ that might leave the session back under non-aggregated control, since it only has one media after the request is done ๐ง a session that still exists after processing the TEARDOWN MUST include a Session header in the response to that TEARDOWN ๐ฅ
so basically, the presence of the Session header tells the receiver whether the session is still around or has been removed ๐
Example ๐
C->S: TEARDOWN rtsp://example.com/fizzle/foo RTSP/2.0
CSeq: 892
Session: OccldOFFq23KwjYpAnBbUr
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 200 OK
CSeq: 892
Server: PhonyServer/1.0
13.7.2. Server to Client ๐
okay so the server can send TEARDOWN requests in the server-to-client direction too ๐ซถ this is the server going "sorry bestie, I gotta end this session" โจ it can happen for a few reasons, like server maintenance with no backup around, or the session just sitting idle for ages ๐ญ the reason goes in the Terminate-Reason header (Section 18.52) ๐
When an RTSP client has kept a session open while basically doing nothing for a long time, the server may reclaim the resources ๐ง it does that by sending a TEARDOWN with Terminate-Reason set to "Session-Timeout". This MAY be done when the client has been inactive in the RTSP session for more than one Session Timeout period (Section 18.49). BUT the server is NOT RECOMMENDED to do this until an extended period of inactivity of 10 times the Session-Timeout period has passed ๐ the operator of the RTSP server is the one who actually sets how long that extended period is. when they're setting it up, they should think about what content is being served and what that means for how long is too long to be idle ๐
In case the server needs to stop providing service to the established sessions and there is no server to point at in a REDIRECT request, then TEARDOWN SHALL be used to terminate the session ๐ฅ this method can also be used when non-recoverable internal errors have happened and the server has no other option than to terminate the sessions ๐ญ
The TEARDOWN request MUST be made only on the session aggregate control URI. It is not allowed to terminate individual media streams if it is a session aggregate. The TEARDOWN request MUST also include the following headers: Session and Terminate-Reason. The request only applies to the session identified in the Session header. The server may include a message to the client's user with the "user-msg" parameter.
The TEARDOWN request may alternatively be done on the wildcard URI "*" and without any session header ๐ the scope of that kind of request is limited to the next-hop (the RTSP agent in direct communication with the server), and it applies to the RTSP connection between that next-hop agent and the server too. this request basically says that all sessions and pending requests being managed via the connection are terminated ๐ any intervening proxies SHOULD do all of the following, in this order:
- respond to the TEARDOWN request
- disconnect the control channel from the requesting server
- pass the TEARDOWN request to each applicable client (typically those clients with an active session or an unanswered request)
Note: The proxy is responsible for accepting TEARDOWN responses from its clients. These responses MUST NOT be passed on to either the original server or the target server in the redirect. ๐ โโ๏ธ
13.8. GET_PARAMETER ๐
okay the GET_PARAMETER request is how you grab the value of any parameter (or a bunch of them) for a presentation or stream named in the URI ๐ฆ if the Session header is in the request, the value of a parameter MUST be retrieved in that specified session context ๐ there are two ways to say which parameters you want.
The first way is to use headers that were defined for this purpose. Headers like this should allow empty or stripped value parts, so you don't have to send bogus data just to ask for a value ๐ซถ a successful completion should also be obvious from any filled-out values in the response โจ the headers in this spec that MAY be used to get their current value with GET_PARAMETER are below, and more headers MAY be added in the future ๐ธ
- Accept-Ranges
- Media-Range
- Media-Properties
- Range
- RTP-Info
The other way is to put a message body in the request that lists the parameter(s) you want back ๐ the Content-Type header (Section 18.19) says which format that body is in. If the receiver doesn't support the media type used for the message body, it SHALL respond with the error code 415 (Unsupported Media Type) ๐ the responder to a GET_PARAMETER request MUST use the media type of the request for its response ๐ for more on negotiating message bodies, check out Section 9.3.
RTSP agents that support responding to GET_PARAMETER requests SHALL implement the "text/parameters" format (Appendix F) ๐ง this makes sure at least one known format for parameters is always implemented, so nobody gets stuck in a parameter format negotiation fail ๐ญ
Parameters inside the message body must all be understood by the agent receiving the request ๐ณ if one or more parameters aren't understood, a 451 (Parameter Not Understood) MUST be sent, with a body listing the parameters that weren't understood ๐ if all of them are understood, their values get filled in and returned in the response message body โจ
The method can also be used with no message body and no header that asks for parameters, just for keep-alive purposes ๐ฆ the keep-alive timer gets updated for any request that succeeds (a 200 OK response is received). Any non-required header in a request like that may or may not have been processed. Normally, filled-out values in the header are a sign that it was processed. But when that's hard to tell, it's recommended to use a feature tag and the Require header ๐ that's why it's usually easier to send the parameters you want in the body instead of using a header ๐
Example:
S->C: GET_PARAMETER rtsp://example.com/fizzle/foo RTSP/2.0
CSeq: 431
User-Agent: PhonyClient/1.2
Session: OccldOFFq23KwjYpAnBbUr
Content-Length: 26
Content-Type: text/parameters
packets_received
jitter
C->S: RTSP/2.0 200 OK
CSeq: 431
Session: OccldOFFq23KwjYpAnBbUr
Server: PhonyServer/1.1
Date: Mon, 08 Mar 2010 13:43:23 GMT
Content-Length: 38
Content-Type: text/parameters
packets_received: 10
jitter: 0.3838
13.9. SET_PARAMETER ๐ธ
this method requests setting the value of a parameter (or a set of them) for a presentation or stream specified by the URI ๐ฆ if the Session header is present, the value of a parameter MUST be retrieved in the specified session context ๐ the method MAY also be used with no message body ๐ซถ it is the RECOMMENDED method to use for a request sent purely to update the keep-alive timer โจ if the request succeeds (a 200 OK response is received), the keep-alive timer has been updated ๐ฅ any non-required header in such a request may or may not have been processed. so to let a client figure out whether a header got processed, it's necessary to use a feature tag and the Require header ๐ for that reason, it is RECOMMENDED that any parameters get sent in the body rather than in a header ๐
When you use a message body to list the parameter(s) you want to set, the Content-Type header (Section 18.19) says which format the body is in ๐ if the receiver doesn't support the media type used for the message body, it SHALL respond with the error code 415 (Unsupported Media Type) ๐ for more on negotiating message bodies, see Section 9.3. The responder to a SET_PARAMETER request MUST use the media type of the request for its response ๐ for additional considerations regarding message body negotiation, see Section 9.3 again ๐
RTSP agents that support responding to SET_PARAMETER requests SHALL implement the text/parameters format (Appendix F) ๐ง this makes sure at least one known format for parameters is implemented, so there's no parameter format negotiation failure ๐ญ
A request is RECOMMENDED to contain only a single parameter, so the client can tell why a particular request failed ๐ซถ if the request has several parameters, the server MUST only act on it if all of the parameters can be set successfully ๐ฅ a server MUST allow a parameter to be set repeatedly to the same value, but it MAY disallow changing parameter values ๐ if the receiver doesn't understand or can't locate a parameter, error 451 (Parameter Not Understood) MUST be used ๐ when a parameter isn't allowed to change, the error code is 458 (Parameter Is Read-Only) ๐ โโ๏ธ the response body MUST contain only the parameters that have errors. Otherwise, a body MUST NOT be returned ๐ and the response body MUST use the media type of the request โจ
Note: transport parameters for the media stream MUST only be set with the SETUP command. ๐ง
Restricting setting transport parameters to SETUP is for the benefit of firewalls connected to border RTSP proxies. ๐งฑ
The parameters are split up finely so there can be more meaningful error indications. It may make sense to allow setting several parameters at once if an atomic setting is wanted. Imagine device control where the client does not want the camera to pan unless it can also tilt to the right angle at the same time. ๐ท
Example:
C->S: SET_PARAMETER rtsp://example.com/fizzle/foo RTSP/2.0
CSeq: 421
User-Agent: PhonyClient/1.2
Session: iixT43KLc
Date: Mon, 08 Mar 2010 14:45:04 GMT
Content-length: 20
Content-type: text/parameters
barparam: barstuff
S->C: RTSP/2.0 451 Parameter Not Understood
CSeq: 421
Session: iixT43KLc
Server: PhonyServer/1.0
Date: Mon, 08 Mar 2010 14:44:56 GMT
Content-length: 20
Content-type: text/parameters
barparam: barstuff
13.10. REDIRECT ๐ฆ
okay so REDIRECT is the method a server uses to tell a client "hey, I'm about to stop serving this, go connect somewhere else" ๐ It can happen for different reasons, but the big one is that the server is being administered and has to stop providing service. So the client is required to connect to another server location to get the resource named in the Request-URI ๐
The REDIRECT request SHALL contain a Terminate-Reason header (Section 18.52) to tell the client why it's happening ๐ง You can add extra parameters related to the reason too. The whole point is to let a server admin do a controlled shutdown of the RTSP server. That takes enough time to tell every entity with state tied to the server, and for them to migrate smoothly from this server to a fall-back one. Main character energy, honestly ๐
A REDIRECT request with a Session header has end-to-end (server-to-client) scope and only applies to that one session ๐ Any intervening proxies SHOULD NOT disconnect the control channel while there are other end-to-end sessions still going. The REQUIRED Location header MUST contain a complete absolute URI pointing to the resource the client SHOULD reconnect to. And the Location MUST NOT contain just the host and port, bestie, I need the whole thing ๐ A client may receive a REDIRECT request with a Session header if and only if an end-to-end session has already been established.
A client may also get a REDIRECT request without a Session header at any time it has communication or a connection set up with a server ๐ธ The scope here is the next-hop (the RTSP agent that's directly talking to the server). It applies to all sessions being controlled, plus the connection between that next-hop agent and the server. A REDIRECT without a Session header means that all sessions and pending requests managed over that connection MUST be redirected. The Location header, if it's included, SHOULD contain an absolute URI with only the host address and the OPTIONAL port number of the server the RTSP agent SHOULD reconnect to. Any intervening proxies SHOULD do all of the following, in this order:
- respond to the REDIRECT request
- disconnect the control channel from the requesting server
- connect to the server at the given host address
- pass the REDIRECT request to each applicable client (typically those clients with an active session or an unanswered request)
Note: The proxy is responsible for accepting REDIRECT responses from its clients. Those responses MUST NOT be passed on to either the original server or the redirected server. Keep that straight, it matters ๐ซถ
A server that needs to terminate a session (or all of its sessions) and doesn't have an alternative server to redirect to SHALL use TEARDOWN requests instead ๐
When there's no Terminate-Reason time parameter in a REDIRECT request, the client SHALL perform the redirection immediately and send a response back to the server โก The server shall consider the session terminated and can free any associated state once it gets the successful (2xx) response. The server MAY close the signaling connection when it receives the response, and the client SHOULD close the signaling connection after sending the 2xx response. The exception is when the client has several sessions on the server managed by that signaling connection. Then the client SHOULD close the connection once it has received and responded to REDIRECT requests for all of the sessions managed by it ๐ง
The Terminate-Reason header time parameter MAY be used to indicate the wallclock time by which the redirection MUST have taken place โฐ To let a client figure out that redirect time without being time synchronized with the server, the server MUST include a Date header in the request. The client should have terminated the session and closed the connection before the redirection timeline ran out. When the deadline is reached, the server MAY simply stop providing service, or it can issue TEARDOWN requests to the remaining sessions.
If the REDIRECT request times out following the rules in Section 10.4, the server MAY terminate the session or transport connection that would have been redirected by the request ๐ โโ๏ธ This is a safeguard against misbehaving clients that refuse to respond to a REDIRECT request. It also takes away any incentive for not acknowledging a REDIRECT request, which is iconic of it honestly.
After a REDIRECT request has been processed, a client that still wants to receive media for the resource named in the Request-URI will have to set up a new session with the designated host ๐ If the URI in the Location header is a valid resource URI, a client SHOULD issue a DESCRIBE request for that URI.
Note: The media resource indicated by the Location header can be identical, slightly different, or totally different. That's exactly why a new DESCRIBE request SHOULD be issued ๐
If the Location header only contains a host address, the client may assume the media on the new server is identical to the media on the old server. That means all the media configuration information from the old session is still valid except for the host address ๐ฆ However, using conditional SETUP with MTag identifiers is RECOMMENDED as a way to verify that assumption. Verify your vibes, babe โจ
This example request redirects traffic for this session to the new server at the given absolute time:
S->C: REDIRECT rtsp://example.com/fizzle/foo RTSP/2.0
CSeq: 732
Location: rtsp://s2.example.com:8001/fizzle/foo
Terminate-Reason: Server-Admin ;time=19960213T143205Z
Session: uZ3ci0K+Ld-M
Date: Thu, 13 Feb 1996 14:30:43 GMT
C->S: RTSP/2.0 200 OK
CSeq: 732
User-Agent: PhonyClient/1.2
Session: uZ3ci0K+Ld-M
14. Embedded (Interleaved) Binary Data ๐ง
okay so sometimes the network side forces your hand ๐ Like when a network address translator blocks RTP traffic over UDP, you might have to interleave RTSP messages with the media-stream data. This should generally be avoided though, because it makes client and server operation way more complicated and adds overhead. Head-of-line blocking can also cause problems, which is so not it ๐ญ So interleaved binary data SHOULD only be used if RTSP is carried over TCP. And interleaved data is not allowed inside RTSP messages. Stay in your lane, data ๐
Stream data, like RTP packets, gets wrapped up like this: an ASCII dollar sign (36 decimal), then a one-octet channel identifier, then the length of the encapsulated binary data as a two-octet unsigned integer in network octet order (Appendix B of [RFC791]) ๐ The stream data follows right after, with no CRLF, but it still includes the upper-layer protocol headers. Each dollar sign block MUST contain exactly one upper-layer protocol data unit, for example one RTP packet. One block, one PDU, no sharing ๐ซถ
Note: This mechanism can't handle PDUs larger than 65535 octets. That matches the maximum payload size of regular, non-jumbo IPv4 and IPv6 packets. If the media delivery protocol you want to use has bigger PDUs than that, you'll need to define a PDU fragmentation mechanism before embedded binary data can support it ๐
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| "$" = 36 | Channel ID | Length in octets |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: Binary data (Length according to Length field) :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 1: Embedded Interleaved Binary Data Format
The channel identifier is defined in the Transport header with the interleaved parameter (Section 18.54) ๐
When the transport choice is RTP, the server also interleaves RTCP messages over the TCP connection ๐ Using RTCP is indicated by including a second channel in the interleaved parameter of the Transport header (see Section 18.54). If RTCP is used, packets MUST be sent on the first available channel higher than the RTP channel. The channels are bidirectional and use the same Channel ID in both directions, so RTCP traffic goes on the second channel both ways ๐ฅ
RTCP is sometimes needed for synchronization when two or more streams are interleaved like this. It's also a convenient way to tunnel RTP/RTCP packets through the RTSP connection (TCP or TCP/TLS) when the network configuration needs it, and to move them onto UDP when that's possible โจ
Here's the vibe in action:
C->S: SETUP rtsp://example.com/bar.file RTSP/2.0
CSeq: 2
Transport: RTP/AVP/TCP;unicast;interleaved=0-1
Accept-Ranges: npt, smpte, clock
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 200 OK
CSeq: 2
Date: Thu, 05 Jun 1997 18:57:18 GMT
Transport: RTP/AVP/TCP;unicast;interleaved=5-6
Session: OccldOFFq23KwjYpAnBbUr
Accept-Ranges: npt
Media-Properties: Random-Access=0.2, Immutable, Unlimited
C->S: PLAY rtsp://example.com/bar.file RTSP/2.0
CSeq: 3
Session: OccldOFFq23KwjYpAnBbUr
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 200 OK
CSeq: 3
Session: OccldOFFq23KwjYpAnBbUr
Date: Thu, 05 Jun 1997 18:57:19 GMT
RTP-Info: url="rtsp://example.com/bar.file"
ssrc=0D12F123:seq=232433;rtptime=972948234
Range: npt=0-56.8
Seek-Style: RAP
S->C: $005{2 octet length}{"length" octets data, w/RTP header}
S->C: $005{2 octet length}{"length" octets data, w/RTP header}
S->C: $006{2 octet length}{"length" octets RTCP packet}
15. Proxies โจ
okay bestie, so RTSP proxies are the agents chilling in between a client and a server ๐ซถ A proxy can act as a client or a server depending on what it's trying to pull off ๐ RTSP proxies use two transport-layer connections: one from the RTSP client to the RTSP proxy, and a second from the RTSP proxy to the RTSP server ๐ฆ Proxies get introduced for lots of different reasons, and the ones below are often mixed together ๐
- Caching Proxy: this one is all about lightening the load on servers and connections ๐ It caches the description and the media streams (aka the presentation), so once something is cached and hasn't gone stale, it can serve the client without asking the server again ๐ See Section 16. This type is also expected to understand RTSP endpoint functionality, meaning whatever is listed in the Require header, on top of what Proxy-Require demands โจ
- Translator Proxy: this one makes sure an RTSP client can reach servers and content on an external network, or use content encodings the client doesn't support ๐ง It does the necessary translation of addresses, protocols, or encodings. It's expected to understand RTSP endpoint functionality too, which again means whatever is in the Require header, in addition to what Proxy-Require demands ๐
- Access Proxy: this one gets a client access to servers on an external network ๐ธ It sits on the border between two domains, like a private address space and the public Internet. It does the necessary translation, usually of addresses ๐ฅ This type is required to redirect the media to itself or to a controlled gateway that does the translation before the media can reach the client ๐ซถ
- Security Proxy: this one helps with security stuff around RTSP ๐ For example, on a firewalled network, the security proxy asks for the necessary pinholes in the firewall to be opened when a client on the protected side wants to reach media streams on the external side ๐ฆ It can do its job without redirecting the media between server and client. But in deployments with private address spaces, it's likely to be combined with the access proxy ๐ Its functionality is usually tightly tied to understanding every aspect of the media transport ๐
- Auditing Proxy: RTSP proxies can also give network owners a logging and auditing point for RTSP sessions, like for corporations that keep track of how their employees use the network ๐ This type can do its job without inserting itself, or any other node, into the media transport ๐ It can also accept unknown methods, since it doesn't interfere with the clients' requests โจ
All types of proxies can also be used with secured communication over TLS, because RTSP 2.0 lets the client approve certificate chains used for connection establishment from a proxy; see Section 19.3.2 ๐ That trust model might not be suitable for every type of deployment, though ๐ค In those cases, the secured sessions bypass the proxies ๐ โโ๏ธ
Access proxies SHOULD NOT be used in equipment like NATs and firewalls that aren't expected to be regularly maintained, like home or small office equipment ๐ญ For these cases, it's better to use the NAT traversal procedures defined for RTSP 2.0 [RFC7825] ๐ The reason is that any extensions of RTSP that result in new media-transport protocols or profiles, new parameters, and so on, may fail in a proxy that isn't maintained ๐ That would hold back RTSP's future development and usage ๐ฅบ
15.1. Proxies and Protocol Extensions
okay this part is so important, the existence of proxies must always be considered when developing new RTSP extensions ๐ง Most types of proxies will need to implement any new method so they can keep working correctly with that extension ๐ ๏ธ New headers can be introduced and older proxies won't block them ๐ But you have to think about whether the header and its function need to be understood by the proxy, or if it can just be forwarded ๐ If the header needs to be understood, a feature tag representing that functionality MUST be included in the Proxy-Require header ๐จ Below are some guidelines for figuring out whether a header needs to be understood ๐ The Transport header and its parameters are extensible, which means proxies need handling rules so they interpret them correctly ๐ฆ
Whether or not a proxy needs to understand a header is honestly not easy to figure out, since proxies do a huge variety of jobs ๐ตโ๐ซ When you're evaluating whether a header needs to be understood, you can split the functionality into three main categories ๐ฐ
- Media modifying: the caching and translator proxies actually modify the media, so they also need to understand the requests sent to the server that affect how the media is rendered ๐ฌ That means this type of proxy also needs to understand the server-side functionality ๐
- Transport modifying: the access and security proxies both need to understand how the media transport is performed, whether that's for opening pinholes or translating the outer headers, like IP and UDP or TCP ๐
- Non-modifying: the auditing proxy is special because it doesn't modify messages beyond inserting the Via header ๐ง That's what makes it possible for this type to forward RTSP messages containing all sorts of unknown methods, headers, or header parameters ๐
An extension has to be classified as mandatory to be implemented for a proxy if that extension has to be understood by a "Transport modifying" type of proxy ๐จ
15.2. Multiplexing and Demultiplexing of Messages
RTSP proxies may have to multiplex several RTSP sessions from their clients towards RTSP servers ๐ This means RTSP requests from multiple clients get multiplexed onto a common connection for requests going out to an RTSP server, and on the way back, the responses get demultiplexed from the server into per-client responses ๐ฌ On the protocol level, request and response messages have to be handled in both directions, so there needs to be a mechanism to correlate which request/response pair exchanged between proxy and server maps to which client (or client request) ๐งฉ
This multiplexing of requests and demultiplexing of responses is done using the CSeq header field ๐ข The proxy has to rewrite the CSeq in requests to the server and in responses from the server, and remember which CSeq maps to which client ๐ง The proxy also needs to make sure the order of messages for each client is maintained ๐ซถ Section 18.20 defines how requests and responses are rewritten ๐
16. Caching โจ
okay so in HTTP, request/response pairs get cached ๐ RTSP is very different about this ๐ Responses are not cacheable, with one exception: the presentation description returned by DESCRIBE ๐ (Since the responses for anything but DESCRIBE and GET_PARAMETER don't return any data, caching isn't really an issue for those requests ๐คทโโ๏ธ) However, it's desirable for the continuous media data, which is typically delivered out-of-band with respect to RTSP, to be cached, as well as the session description ๐
When a proxy receives a SETUP or PLAY request, it figures out whether it has an up-to-date copy of the continuous media content and its description ๐ It can check whether the copy is up to date by issuing a SETUP or DESCRIBE request, respectively, and comparing the Last-Modified header with that of the cached copy ๐ต๏ธโโ๏ธ If the copy isn't up to date, it modifies the SETUP transport parameters as appropriate and forwards the request to the origin server ๐ Later control commands like PLAY or PAUSE then pass through the proxy unmodified ๐ซถ The proxy delivers the continuous media data to the client, and it might make a local copy for later reuse โป๏ธ The exact behavior the cache is allowed to have is given by the cache-response directives described in Section 18.11 ๐ A cache MUST answer any DESCRIBE requests if it is currently serving the stream to the requester, because low-level details of the stream description may have changed on the origin server ๐ฑ
Note that an RTSP cache is of the "cut-through" variety โก Rather than retrieving the whole resource from the origin server, the cache simply copies the streaming data as it passes by on its way to the client ๐โโ๏ธ So it doesn't add any extra latency ๐จ
To the client, an RTSP proxy cache looks like a regular media server ๐ฅ To the media origin server, an RTSP proxy cache looks like a client ๐งโ๐ป Just like an HTTP cache has to store the content type, content language, and so on for the objects it caches, a media cache has to store the presentation description ๐ Typically, a cache eliminates all transport references (e.g., multicast information) from the presentation description, since those are independent of the data delivery from the cache to the client ๐ Information on the encodings stays the same ๐ถ If the cache is able to translate the cached media data, it would create a new presentation description with all the encoding possibilities it can offer ๐
16.1. Validation Model ๐ฆ
okay bestie, so when a cache has a stale entry it wants to use to answer a client's request, it first has to check with the origin server (or maybe an intermediate cache that has a fresh response) to see if that entry is still usable ๐ . This is called "validating" the cache entry. We don't want to pay for retransmitting the whole full response if the cached entry is still good, but we also don't want to pay for an extra round trip if it's actually invalid ๐ญ. So RTSP supports conditional methods, and honestly they're iconic ๐ธ.
The key features that make conditional methods work are the ones about "cache validators" โจ. When an origin server generates a full response, it attaches some sort of validator to it, and that validator is kept with the cache entry. When a client (a user agent or a proxy cache) makes a conditional request for a resource it has a cache entry for, it includes the associated validator in the request ๐.
The server then checks that validator against the current validator for the requested resource. If they match (see Section 16.1.3), it responds with a special status code (usually, 304 (Not Modified)) and no message body. Otherwise, it returns a full response (including message body). So we skip sending the full response when the validator matches, and we skip an extra round trip when it doesn't. Main character efficiency ๐.
In RTSP, a conditional request looks exactly the same as a normal request for the same resource, except that it carries a special header (which includes the validator) that implicitly turns the method (usually DESCRIBE or SETUP) into a conditional ๐ง.
The protocol includes both positive and negative senses of cache-validating conditions. That means you can request that a method be performed either if and only if a validator matches, or if and only if no validators match ๐.
Note: a response that lacks a validator may still be cached, and served from cache until it expires, unless this is explicitly prohibited by a cache directive (see Section 18.11). However, a cache cannot perform a conditional retrieval if it does not have a validator for the resource, which means it will not be refreshable after it expires.
Media streams that are being adapted based on the transport capacity between the server and the cache make caching more difficult ๐. A server needs to think about how it views the caching of media streams that it adapts, and it can potentially instruct any caches not to cache those streams.
16.1.1. Last-Modified Dates
The Last-Modified header (Section 18.27) value is often used as a cache validator ๐. In simple terms, a cache entry is considered valid if the cache entry was created after the Last-Modified time.
16.1.2. Message Body Tag Cache Validators
The MTag response-header field-value, a message body tag, gives us an "opaque" cache validator ๐. This might allow more reliable validation in situations where it's inconvenient to store modification dates, where the one-second resolution of RTSP-date values isn't sufficient, or where the origin server wants to avoid certain paradoxes that might come up from using modification dates ๐.
Message body tags are described in Section 4.6
16.1.3. Weak and Strong Validators
Since both origin servers and caches compare two validators to decide whether they represent the same or different entities, you'd normally expect that if the message body (i.e., the presentation description) or any associated message body headers change in any way, the associated validator would change too ๐ค. If that's true, then the validator is a "strong validator". The message body (i.e., the presentation description) or any associated message body headers is called an entity, to make things easier to understand.
However, there might be cases where a server prefers to change the validator only on semantically significant changes, and not when insignificant aspects of the entity change. A validator that does not always change when the resource changes is a "weak validator" ๐ซถ.
Message body tags are normally strong validators, but the protocol gives us a way to tag a message body tag as "weak" ๐ . You can think of a strong validator as one that changes whenever the bits of an entity change, while a weak validator changes whenever the meaning of an entity changes. Or, another way to see it: a strong validator is part of an identifier for one specific entity, while a weak validator is part of an identifier for a set of semantically equivalent entities.
Note: One example of a strong validator is an integer that is incremented in stable storage every time an entity is changed.
An entity's modification time, if represented with one-second resolution, could be a weak validator, since it is possible that the resource might be modified twice during a single second.
Support for weak validators is optional. However, weak validators allow for more efficient caching of equivalent objects.
A "use" of a validator is either when a client generates a request and includes the validator in a validating header field, or when a server compares two validators ๐ฅ.
Strong validators are usable in any context. Weak validators are only usable in contexts that don't depend on exact equality of an entity. For example, either kind is usable for a conditional DESCRIBE of a full entity. However, only a strong validator is usable for a subrange retrieval, because otherwise the client might end up with an internally inconsistent entity ๐ญ.
Clients MAY issue DESCRIBE requests with either weak or strong validators. Clients MUST NOT use weak validators in other forms of requests ๐ โโ๏ธ.
The only function RTSP defines on validators is comparison. There are two validator comparison functions, depending on whether or not the comparison context allows the use of weak validators:
- The strong comparison function: in order to be considered equal, both validators MUST be identical in every way, and both MUST NOT be weak.
- The weak comparison function: in order to be considered equal, both validators MUST be identical in every way, but either or both of them MAY be tagged as "weak" without affecting the result.
A message body tag is strong unless it is explicitly tagged as weak ๐.
A Last-Modified time, when used as a validator in a request, is implicitly weak unless it's possible to deduce that it's strong, using the following rules:
- The validator is being compared by an origin server to the actual current validator for the entity, and
- That origin server reliably knows that the associated entity did not change more than once during the second covered by the presented validator.
OR
- The validator is about to be used by a client in an If-Modified-Since, because the client has a cache entry for the associated entity, and
- That cache entry includes a Date value, which gives the time when the origin server sent the original response, and
- The presented Last-Modified time is at least 60 seconds before the Date value.
OR
- The validator is being compared by an intermediate cache to the validator stored in its cache entry for the entity, and
- That cache entry includes a Date value, which gives the time when the origin server sent the original response, and
- The presented Last-Modified time is at least 60 seconds before the Date value.
This method relies on the fact that if two different responses were sent by the origin server during the same second, but both had the same Last-Modified time, then at least one of those responses would have a Date value equal to its Last-Modified time ๐ง . The arbitrary 60-second limit guards against the possibility that the Date and Last-Modified values are generated from different clocks, or at somewhat different times during the preparation of the response. An implementation MAY use a value larger than 60 seconds, if it is believed that 60 seconds is too short โจ.
If a client wants to perform a subrange retrieval on a value for which it has only a Last-Modified time and no opaque validator, it MAY do this only if the Last-Modified time is strong in the sense described here ๐ฆ.
16.1.4. Rules for When to Use Message Body Tags and Last-Modified Dates
This document adopts a set of rules and recommendations for origin servers, clients, and caches about when each validator type ought to be used, and for what purposes ๐.
RTSP origin servers:
- SHOULD send a message body tag validator unless it is not feasible to generate one.
- MAY send a weak message body tag instead of a strong message body tag, if performance considerations support the use of weak message body tags, or if it is unfeasible to send a strong message body tag.
- SHOULD send a Last-Modified value if it is feasible to send one, unless the risk of a breakdown in semantic transparency that could result from using this date in an If-Modified-Since header would lead to serious problems.
In other words, the preferred behavior for an RTSP origin server is to send both a strong message body tag and a Last-Modified value ๐ธ.
In order to be legal, a strong message body tag MUST change whenever the associated entity value changes in any way. A weak message body tag SHOULD change whenever the associated entity changes in a semantically significant way ๐.
Note: in order to provide semantically transparent caching, an origin server MUST avoid reusing a specific strong message body tag value for two different entities, or reusing a specific weak message body tag value for two semantically different entities. Cache entries might persist for arbitrarily long periods, regardless of expiration times, so it might be inappropriate to expect that a cache will never again attempt to validate an entry using a validator that it obtained at some point in the past.
RTSP clients:
- If a message body tag has been provided by the origin server, MUST use that message body tag in any cache-conditional request (using If-Match or If-None-Match).
- If only a Last-Modified value has been provided by the origin server, SHOULD use that value in non-subrange cache-conditional requests (using If-Modified-Since).
- If both a message body tag and a Last-Modified value have been provided by the origin server, SHOULD use both validators in cache-conditional requests.
An RTSP origin server, upon receiving a conditional request that includes both a Last-Modified date (e.g., in an If-Modified-Since header) and one or more message body tags (e.g., in an If-Match, If-None-Match, or If-Range header field) as cache validators, MUST NOT return a response status of 304 (Not Modified) unless doing so is consistent with all of the conditional header fields in the request ๐ซ.
Note: The general principle behind these rules is that RTSP servers and clients should transmit as much non-redundant information as is available in their responses and requests. RTSP systems receiving this information will make the most conservative assumptions about the validators they receive ๐.
16.1.5. Non-validating Conditionals ๐
okay so the big idea here is that only the service author really knows what a resource means, so only they can pick a good cache validation method ๐ง . if you tried comparing validators with anything fancier than plain octet equality, you'd open up a whole can of worms ๐ชฑ. so comparing any other headers is never used for validating a cache entry ๐ โโ๏ธ
16.2. Invalidation after Updates or Deletions
ngl this section is so real ๐. certain methods run on a resource at the origin server can make existing cache entries non-transparently invalid. like, they might still count as "fresh" ๐ฅถ, but they no longer match what the origin server would return for a brand-new request on that resource ๐ญ
there's no way for RTSP to guarantee that every one of those cache entries gets marked invalid ๐. for example, the request that caused the change at the origin server might never have gone through the proxy where the cache entry is stored. still, a few rules help cut down on the weird behavior ๐ซถ
in this section, the phrase "invalidate an entity" means the cache either removes every instance of that entity from its storage, or marks them as "invalid" and in need of a mandatory revalidation before they can be returned for a later request โจ
Some RTSP methods MUST cause a cache to invalidate an entity. This is either the entity referred to by the Request-URI or by the Location or Content-Location headers (if present). These methods are:
- DESCRIBE
- SETUP
In order to prevent DoS attacks, an invalidation based on the URI in a Location or Content-Location header MUST only be performed if the host part is the same as in the Request-URI. ๐ก๏ธ this one's giving security queen energy, bestie ๐
A cache that passes through requests for methods it does not understand SHOULD invalidate any entities referred to by the Request-URI. ๐งน
17. Status Code Definitions ๐
okay so wherever it makes sense, HTTP status codes (see Section 6 of [RFC7231]) get reused, no need to reinvent the wheel ๐. check Table 4 in Section 8.1 to see which status codes each request can return ๐. all error messages, 4xx and 5xx, MAY return a body with more info about the error ๐ค
17.1. Informational 1xx ๐ธ
17.1.1. 100 Continue
the requesting agent SHOULD continue with its request ๐โโ๏ธ. this interim response tells the requesting agent that the start of the request has arrived and hasn't been rejected by the responding agent yet ๐ฌ. the requesting agent SHOULD keep going by sending the rest of the request or, if it's already complete, keep waiting for a final response (see Section 10.4) โณ. the responding agent MUST send a final response once the request has been completed ๐
17.2. Success 2xx ๐ฆ
this class of status code means the agent's request was successfully received, understood, and accepted ๐ฅณ
17.2.1. 200 OK โจ
the request has succeeded ๐. what comes back in the response depends on the method used in the request ๐งฉ
17.3. Redirection 3xx ๐ง
the notation "3xx" covers response codes from 300 to 399 inclusive that are meant for redirection ๐บ๏ธ. we use "3rr" to mean all the 3xx codes used for redirection, so everything except 304 ๐ โโ๏ธ. 304 shows up here instead of in the 2xx range, which would've been the more logical spot ๐คทโโ๏ธ. it's also been used in RTSP 1.0 [RFC2326] ๐
within RTSP, redirection can be used for load-balancing, or for sending stream requests to a server that's topologically closer to the agent ๐. how to figure out topological proximity is beyond the scope of this specification, so that's a different mystery for another day ๐ฎ
a 3rr code MAY be used to respond to any request ๐. the Location header MUST be included in any 3rr response ๐. it is RECOMMENDED that they're used, if needed, before a session is established, i.e., in response to DESCRIBE or SETUP ๐ . however, if a server can't send a REDIRECT request to the agent, the server MAY need to fall back on 3rr responses to tell an agent with an established session that the session needs to be redirected ๐ซ . if a 3rr response arrives for a request related to an established session, the agent SHOULD send a TEARDOWN request for the session, and MAY re-establish the session using the resource indicated by the Location ๐
if the Location header is used in a response, it MUST contain an absolute URI pointing to the media resource the agent is being redirected to ๐ฏ. the URI MUST NOT contain only the hostname, bestie ๐ โโ๏ธ that's a no-go
if an unknown 3rr status code shows up, the agent SHOULD behave as if a 302 response code had been received (Section 17.3.3) ๐ค
17.3.1. 300 ๐ซฅ
the 300 response code is not used in RTSP 2.0 ๐ซ
17.3.2. 301 Moved Permanently ๐
the requested resource has moved permanently and now lives at the URI given by the Location header ๐ฆ. the user agent SHOULD redirect automatically to the given URI ๐. this response MUST NOT contain a message body ๐ โโ๏ธ. the Location header MUST be included in the response ๐
17.3.3. 302 Found ๐
the requested resource is temporarily at the URI given by the Location header โบ. this response is meant for lots of kinds of temporary redirects, e.g., load balancing โ๏ธ. it is RECOMMENDED that the server set the reason phrase to something more meaningful than "Found" in these cases, because "Found" is giving nothing ๐ญ. the Location header MUST be included in the response ๐. the user agent SHOULD redirect automatically to the given URI ๐. this response MUST NOT contain a message body ๐ โโ๏ธ
here's an example of a client getting redirected to a different server ๐:
C->S: SETUP rtsp://example.com/fizzle/foo RTSP/2.0
CSeq: 2
Transport: RTP/AVP/TCP;unicast;interleaved=0-1
Accept-Ranges: npt, smpte, clock
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 302 Try Other Server
CSeq: 2
Location: rtsp://s2.example.com:8001/fizzle/foo
17.3.4. 303 See Other ๐
this status code MUST NOT be used in RTSP 2.0 ๐ซ. it was allowed in RTSP 1.0 [RFC2326], though, so it's a bit of a throwback ๐ผ
17.3.5. 304 Not Modified ๐ง
if the agent has done a conditional DESCRIBE or SETUP (see Sections 18.25 and 18.26) and the requested resource hasn't been modified, the server SHOULD send a 304 response ๐. this response MUST NOT contain a message body ๐ โโ๏ธ
the response MUST include the following header fields ๐:
- Date
- MTag or Content-Location, if the headers would have been sent in a 200 response to the same request
- Expires and Cache-Control if the field-value might differ from that sent in any previous response for the same variant
this response is independent for the DESCRIBE and SETUP requests ๐ง. so a 304 response to DESCRIBE does not imply the resource content is unchanged (only the session description is), and a 304 response to SETUP does not imply the resource description is unchanged ๐. the MTag and If-Match header (Section 18.24) may be used to link the DESCRIBE and SETUP in this way ๐
17.3.6. 305 Use Proxy ๐ฃ๏ธ
the requested resource MUST be accessed through the proxy given by the Location header, which MUST be included ๐. the Location header field-value gives the URI of the proxy ๐. the recipient is expected to repeat this single request via the proxy ๐. 305 responses MUST only be generated by origin servers ๐ so only the big boss can send these
17.4. Client Error 4xx ๐
17.4.1. 400 Bad Request ๐
the request couldn't be understood by the agent because of malformed syntax ๐ซ . the agent SHOULD NOT repeat the request without modifications ๐ โโ๏ธ. if the request doesn't have a CSeq header, the agent MUST NOT include a CSeq in the response ๐ซ
17.4.2. 401 Unauthorized ๐
the request needs user authentication using the HTTP authentication mechanism [RFC7235] ๐. the usage of this error code is defined in [RFC7235] and any applicable HTTP authentication scheme, such as Digest [RFC7616] ๐. the response is to include a WWW-Authenticate header (Section 18.58) field containing a challenge that applies to the requested resource ๐งฉ. the agent can repeat the request with a suitable Authorization header field ๐. if the request already included authorization credentials, then the 401 response means authorization has been refused for those credentials ๐ค. if the 401 response contains the same challenge as the prior response, and the user agent has already tried authentication at least once, then the user SHOULD be shown the message body that came with the response, since that body might include useful diagnostic info ๐ฉบ
17.4.3. 402 Payment Required ๐ธ
this code is reserved for future use ๐ฎ
17.4.4. 403 Forbidden ๐ท
the agent understood the request but is refusing to fulfill it ๐ โโ๏ธ. authorization won't help, and the request SHOULD NOT be repeated ๐. if the agent wants to make public why the request wasn't fulfilled, it SHOULD describe the reason for the refusal in the message body ๐ฃ. if the agent doesn't want to make this information available to the agent, the status code 404 (Not Found) can be used instead ๐ซฃ
17.4.5. 404 Not Found ๐ป
the agent hasn't found anything matching the Request-URI ๐. there's no indication of whether the condition is temporary or permanent ๐คทโโ๏ธ. the 410 (Gone) status code SHOULD be used if the agent knows, through some internally configurable mechanism, that an old resource is permanently gone and has no forwarding address ๐ชฆ
this status code is commonly used when the agent doesn't want to reveal exactly why the request was refused, or when no other response fits ๐
17.4.6. 405 Method Not Allowed ๐ซ
the method in the request isn't allowed for the resource identified by the Request-URI ๐ โโ๏ธ. the response MUST include an Allow header listing the valid methods for the requested resource ๐. this status code is also used if a request tries to use a method that wasn't indicated during SETUP ๐ง
17.4.7. 406 Not Acceptable ๐ โโ๏ธ
the resource identified by the request can only generate response message bodies with content characteristics that aren't acceptable according to the Accept headers sent in the request ๐ฌ
the response SHOULD include a message body with a list of available message body characteristics and locations the user or user agent can choose from, so they can pick the most appropriate one ๐. the message body format is specified by the media type in the Content-Type header field ๐ท๏ธ. depending on the format and the user agent's capabilities, picking the most appropriate choice MAY be done automatically ๐ค. however, this specification doesn't define any standard for that automatic selection ๐ซค
if the response could be unacceptable, a user agent SHOULD temporarily stop receiving more data and ask the user for a decision on what to do next โ
17.4.8. 407 Proxy Authentication Required ๐ก๏ธ
this code is similar to 401 (Unauthorized) (Section 17.4.2), but it means the client must first authenticate itself with the proxy ๐งโ๐ป. the usage of this error code is defined in [RFC7235] and any applicable HTTP authentication scheme, such as Digest [RFC7616] ๐. the proxy MUST return a Proxy-Authenticate header field (Section 18.34) containing a challenge that applies to the proxy for the requested resource ๐๏ธ
17.4.9. 408 Request Timeout โฐ
the agent didn't produce a request within the time it was prepared to wait โ. the agent MAY repeat the request without modifications at any later time ๐ no stress, bestie ๐ซถ
17.4.10. 410 Gone ๐
okay so the resource is just gone from the server now, and nobody's leaving a forwarding address ๐ชฆ The server is basically saying this is permanent. If the server doesn't know (or has no way to figure out) whether it's permanent, it SHOULD use 404 (Not Found) instead ๐ This response is cacheable unless indicated otherwise ๐
The 410 is mostly there for repository maintenance ๐งน It tells the other side the resource is unavailable on purpose and that the server owners want remote links to it removed ๐ This happens a lot with limited-time promos ๐๏ธ and with stuff belonging to people who don't work at the site anymore ๐ซถ You don't have to mark every dead resource as "gone," and you don't have to keep that mark forever ๐ฆ That's totally up to the owner of the server ๐
17.4.11. 412 Precondition Failed ๐ง
one or more of the if- request-header fields had a precondition that came out false when the agent tested it ๐ญ For those headers, check out If-Match (Section 18.24), If-Modified-Since (Section 18.25), and If-None-Match (Section 18.26). This status code lets the agent put preconditions on the current resource's meta-information (the header field data), so the requested method can't accidentally land on some other resource than the one intended ๐ก๏ธ
17.4.12. 413 Request Message Body Too Large ๐ฆ
the agent is refusing to process the request because the request body is bigger than the agent is willing or able to handle. The agent MAY close the connection to stop the requesting agent from continuing the request ๐ช
If the problem is temporary, the agent SHOULD include a Retry-After header field to say it's temporary and after what time the requesting agent MAY try again โฐ
17.4.13. 414 Request-URI Too Long ๐
the responding agent won't service the request because the Request-URI is longer than it's willing to interpret. This is a rare one ๐ It mostly shows up when the request has really long query info, when an agent gets stuck in a URI "black hole" of redirection (like a redirected URI prefix that points to a suffix of itself), or when an agent is under attack from something trying to exploit security holes in agents that use fixed-length buffers for reading or manipulating the Request-URI ๐จ That last one is seriously not cute, bestie.
17.4.14. 415 Unsupported Media Type ๐๏ธ
the server is refusing to service the request because the request's message body is in a format the requested resource doesn't support for that method ๐
17.4.15. 451 Parameter Not Understood ๐คท
the recipient doesn't support one or more parameters in the request. When returning this error, the agent SHOULD return a message body containing the offending parameter(s) ๐
17.4.16. 452 Illegal Conference Identifier ๐ซ
This status code MUST NOT be used in RTSP 2.0. However, it was allowed in RTSP 1.0 [RFC2326] ๐ฐ๏ธ
17.4.17. 453 Not Enough Bandwidth ๐
the request got refused because there wasn't enough bandwidth. This could happen, for example, as the result of a resource reservation failure ๐ซ
17.4.18. 454 Session Not Found ๐ซฅ
the RTSP session identifier in the Session header is missing, invalid, or has timed out โ
17.4.19. 455 Method Not Valid in This State ๐
the agent can't process this request in its current state. The response MUST contain an Allow header so error recovery is possible ๐
17.4.20. 456 Header Field Not Valid for Resource ๐
the targeted agent couldn't act on a required request-header. For example, a PLAY request has the Range header field, but the stream doesn't allow seeking ๐ฌ This error message may also be used for specifying when the time format in Range is impossible for the resource. In that case, the Accept-Ranges header MUST be returned to tell the agent which formats are allowed ๐งพ
17.4.21. 457 Invalid Range ๐
the Range value is out of bounds, like going past the end of the presentation ๐
17.4.22. 458 Parameter Is Read-Only ๐
the parameter that SET_PARAMETER is supposed to set can be read but not modified. When returning this error, the sender SHOULD return a message body containing the offending parameter(s) ๐
17.4.23. 459 Aggregate Operation Not Allowed ๐ท
the requested method can't be applied to the URI in question because it's an aggregate (presentation) URI. The method can be applied to a media URI instead ๐๏ธ
17.4.24. 460 Only Aggregate Operation Allowed โ๏ธ
the requested method can't be applied to the URI in question because it isn't an aggregate control (presentation) URI. The method can be applied to the aggregate control URI ๐ฏ
17.4.25. 461 Unsupported Transport ๐
the Transport field didn't contain a supported transport specification ๐
17.4.26. 462 Destination Unreachable ๐
the data transmission channel couldn't be established because the agent's address couldn't be reached. This will most likely be the result of the agent trying to put an invalid dest_addr parameter in the Transport field ๐บ๏ธ
17.4.27. 463 Destination Prohibited ๐
the data transmission channel wasn't established because the server prohibited access to the agent's address. This is most likely the result of the agent trying to redirect media traffic to another destination with a dest_addr parameter in the Transport header ๐ง
17.4.28. 464 Data Transport Not Ready Yet โณ
the data transmission channel to the media destination isn't ready for carrying data yet. The responding agent still expects that the channel will be established at some point ๐ค Heads up though: this could turn into a permanent failure like 462 (Destination Unreachable) ๐ฌ
An example: a client sends a PLAY request before making sure the TCP connections negotiated for carrying media data were successfully established (which is in violation of this specification ๐ ). The server would use this error code to say the requested action couldn't be performed because connection establishment failed ๐
17.4.29. 465 Notification Reason Unknown ๐
this means the client got a PLAY_NOTIFY (Section 13.5) with a Notify-Reason header (Section 18.32) that the client doesn't recognize ๐ค
17.4.30. 466 Key Management Error ๐
there's been an error in a Key Management function used along with a request. For example, using Multimedia Internet KEYing (MIKEY) [RFC3830] according to Appendix C.1.4.1 may result in this error ๐๏ธ
17.4.31. 470 Connection Authorization Required ๐ชช
the secured connection attempt needs user or client authorization before it can go on. The next hop's certificate is included in this response, in the Accept-Credentials header ๐
17.4.32. 471 Connection Credentials Not Accepted ๐ซ
when a secure connection is being set up over multiple connections, an intermediary refused to connect to the next hop and carry out the request because the credentials weren't acceptable for the policy being used ๐ง
17.4.33. 472 Failure to Establish Secure Connection ๐
a proxy fails to establish a secure connection to the next-hop RTSP agent. This is mainly caused by a fatal failure at the TLS handshake, for example, because the agent isn't accepting any cipher suites ๐ฅ
17.5. Server Error 5xx ๐ฅ
status codes starting with the digit "5" mean the server knows it has erred or can't perform the request ๐ต The server SHOULD include a message body explaining the error situation and whether it's a temporary or permanent condition. User agents SHOULD display any included message body to the user ๐ฃ These response codes apply to any request method โจ
17.5.1. 500 Internal Server Error ๐ฅ
the agent ran into an unexpected condition that stopped it from fulfilling the request ๐ซจ
17.5.2. 501 Not Implemented ๐งฉ
the agent doesn't support the functionality needed to fulfill the request. This is the right response when the agent doesn't recognize the request method and can't support it for any resource ๐
17.5.3. 502 Bad Gateway ๐
the agent, while acting as a gateway or proxy, got an invalid response from the upstream agent it reached out to while trying to fulfill the request ๐ซค
17.5.4. 503 Service Unavailable ๐ ๏ธ
the server can't handle the request right now because of temporary overloading or maintenance ๐งน The idea is that this is a temporary condition that will get better after some delay. If known, the length of the delay MAY be indicated in a Retry-After header. If no Retry-After is given, the agent SHOULD handle the response the same way it would a 500 response. The agent MUST honor the length, if given, in the Retry-After header โฑ๏ธ
Note: The existence of the 503 status code does not imply that a server must use it when becoming overloaded. Some servers may wish to simply refuse the transport connection.
The response scope depends on the request. If the request was related to an existing RTSP session, the overload response applies only to that individual RTSP session ๐ฏ If the request wasn't session specific or wasn't meant to form an RTSP session, it applies to the RTSP server identified by the hostname in the Request-URI ๐
17.5.5. 504 Gateway Timeout โฐ
the agent, while acting as a proxy, didn't get a timely response from the upstream agent specified by the URI, or from some other auxiliary server (like DNS) it needed to reach while trying to complete the request ๐ข
17.5.6. 505 RTSP Version Not Supported ๐
the agent doesn't support, or refuses to support, the RTSP version used in the request message. The agent is saying it's unable or unwilling to complete the request using the same major version, other than with this error message ๐ The response SHOULD contain a message body describing why that version isn't supported and what other protocols that agent does support ๐
17.5.7. 551 Option Not Supported ๐
a feature tag given in the Require or the Proxy-Require fields wasn't supported. The Unsupported header MUST be returned, stating the feature that has no support ๐ท๏ธ
17.5.8. 553 Proxy Unavailable ๐ง
the proxy can't handle the request right now due to temporary overloading or maintenance. The idea is that this is a temporary condition that will get better after some delay. If known, the length of the delay MAY be indicated in a Retry-After header. If no Retry-After is given, the agent SHOULD handle the response the same way it would a 500 response. The agent MUST honor the length, if given in the Retry-After header ๐ซก
Note: The existence of the 553 status code does not imply that a proxy must use it when becoming overloaded. Some proxies may wish to simply refuse the connection.
The response scope depends on the Request. If the request was related to an existing RTSP session, the overload response applies to that individual RTSP session ๐ If the request was non-session specific or was intended to form an RTSP session, it applies to all such requests to this proxy ๐ธ
18. Header Field Definitions ๐
This table is your cheat sheet ๐
for RTSP methods. It shows which way each one flies (client to server, server to client, or both), what it touches (P for presentation, S for stream), and its acronym. The Body column says whether a method can carry a body and in which direction, where R = request and r = response. Also, all error messages for 4xx and 5xx statuses are allowed to carry a body ๐ซถ
+---------------+----------------+--------+---------+------+
| method | direction | object | acronym | Body |
+---------------+----------------+--------+---------+------+
| DESCRIBE | C -> S | P,S | DES | r |
| | | | | |
| GET_PARAMETER | C -> S, S -> C | P,S | GPR | R,r |
| | | | | |
| OPTIONS | C -> S, S -> C | P,S | OPT | |
| | | | | |
| PAUSE | C -> S | P,S | PSE | |
| | | | | |
| PLAY | C -> S | P,S | PLY | |
| | | | | |
| PLAY_NOTIFY | S -> C | P,S | PNY | R |
| | | | | |
| REDIRECT | S -> C | P,S | RDR | |
| | | | | |
| SETUP | C -> S | S | STP | |
| | | | | |
| SET_PARAMETER | C -> S, S -> C | P,S | SPR | R,r |
| | | | | |
| TEARDOWN | C -> S | P,S | TRD | |
| | | | | |
| | S -> C | P | TRD | |
+---------------+----------------+--------+---------+------+
Table 8: Overview of RTSP Methods ๐
Okay, so the general syntax for header fields lives in Section 5.2. This section is where you get the full set of header fields, plus notes on what they mean and how to use them, with examples for each one ๐ฆ The syntax definitions are in Section 20.2.3. Info about how header fields relate to methods and proxy processing is summarized in Figures 2, 3, 4, and 5 โจ
The "where" column tells you which request and response types a header field can show up in. The values are:
R: header field may only appear in requests;r: header field may only appear in responses;2xx,4xx, etc.: a numerical value or range showing which response codes the header field can be used with;c: header field is copied from the request to the response;G: header field is a general-header and may be present in both requests and responses.
Note: General headers don't always use the G value in the "where" column ๐ That's because the rules change depending on whether the header is being applied in a request or a response. When that happens, the header gets two rows: one with "where" set to R and one set to r.
The "proxy" column describes what a proxy is allowed to do to a header field. An empty proxy column means the proxy MUST NOT make any changes to that header, so anything that's allowed has to be spelled out explicitly ๐ญ The options are:
a: A proxy can add or concatenate the header field if not present.m: A proxy can modify an existing header field value.d: A proxy can delete a header field-value.r: A proxy needs to be able to read the header field; thus, this header field cannot be encrypted.
The rest of the columns are about whether a header field shows up in a given method. The method names, when abbreviated, follow Table 8:
c: Conditional; requirements on the header field depend on the context of the message.m: The header field is mandatory.m*: The header field SHOULD be sent, but agents need to be prepared to receive messages without that header field.o: The header field is optional.*: The header field MUST be present if the message body is not empty. See Sections 18.17, 18.19 and 5.3 for details.-: The header field is not applicable.
"Optional" means an agent MAY include the header field in a request or response. How an agent treats these headers when it receives them varies, and some agents may just ignore them. Other times, the header is a request to process it. The method and header descriptions decide which one applies. Examples of headers that need processing are the Require and Proxy-Require header fields, covered in Sections 18.43 and 18.37 ๐ A "mandatory" header field MUST be present in a request, and it MUST be understood by the agent receiving the request. A mandatory response-header field MUST be present in the response, and the header field MUST be understood by the processing the response. "Not applicable" means the header field MUST NOT be present in a request. If one shows up in a request by mistake, it MUST be ignored by the agent receiving the request. Similarly, a header field labeled "not applicable" for a response means the agent MUST NOT place that header field in the response, and the agent MUST ignore the header field in the response. Main character energy for header rules ๐
An RTSP agent MUST ignore extension headers that it doesn't understand. ๐ง
The From and Location header fields contain a URI. If the URI contains a comma (') or semicolon (;), the URI MUST be enclosed in double quotes ("). Any URI parameters are contained within these quotes. If the URI is not enclosed in double quotes, any semicolon-delimited parameters are header-parameters, not URI parameters. It's a whole thing, but it matters ๐
+-------------------+------+------+----+----+-----+-----+-----+-----+
| Header |Where |Proxy |DES | OPT| STP | PLY | PSE | TRD |
+-------------------+------+------+----+----+-----+-----+-----+-----+
| Accept | R | | o | - | - | - | - | - |
| Accept- | R | rm | o | o | o | o | o | o |
| Credentials | | | | | | | | |
| Accept-Encoding | R | r | o | - | - | - | - | - |
| Accept-Language | R | r | o | - | - | - | - | - |
| Accept-Ranges | G | r | - | - | m | - | - | - |
| Accept-Ranges | 456 | r | - | - | - | m | - | - |
| Allow | r | am | c | c | c | - | - | - |
| Allow | 405 | am | m | m | m | m | m | m |
| Authentication- | r | | o | o | o | o | o | o/- |
| Info | | | | | | | | |
| Authorization | R | | o | o | o | o | o | o/- |
| Bandwidth | R | | o | o | o | o | - | - |
| Blocksize | R | | o | - | o | o | - | - |
| Cache-Control | G | r | o | - | o | - | - | - |
| Connection | G | ad | o | o | o | o | o | o |
| Connection- | 470, | ar | o | o | o | o | o | o |
| Credentials | 407 | | | | | | | |
| Content-Base | r | | o | - | - | - | - | - |
| Content-Base | 4xx, | | o | o | o | o | o | o |
| | 5xx | | | | | | | |
| Content-Encoding | R | r | - | - | - | - | - | - |
| Content-Encoding | r | r | o | - | - | - | - | - |
| Content-Encoding | 4xx, | r | o | o | o | o | o | o |
| | 5xx | | | | | | | |
| Content-Language | R | r | - | - | - | - | - | - |
| Content-Language | r | r | o | - | - | - | - | - |
| Content-Language | 4xx, | r | o | o | o | o | o | o |
| | 5xx | | | | | | | |
| Content-Length | r | r | * | - | - | - | - | - |
| Content-Length | 4xx, | r | * | * | * | * | * | * |
| | 5xx | | | | | | | |
| Content-Location | r | r | o | - | - | - | - | - |
| Content-Location | 4xx, | r | o | o | o | o | o | o |
| | 5xx | | | | | | | |
| Content-Type | r | r | * | - | - | - | - | - |
| Content-Type | 4xx, | ar | * | * | * | * | * | * |
| | 5xx | | | | | | | |
| CSeq | Gc | rm | m | m | m | m | m | m |
| Date | G | am | o/*| o/*| o/* | o/* | o/* | o/* |
| Expires | r | r | o | - | o | - | - | - |
| From | R | r | o | o | o | o | o | o |
| If-Match | R | r | - | - | o | - | - | - |
| If-Modified-Since | R | r | o | - | o | - | - | - |
| If-None-Match | R | r | o | - | o | - | - | - |
| Last-Modified | r | r | o | - | o | - | - | - |
| Location | 3rr | | m | m | m | m | m | m |
+-------------------+------+------+----+----+-----+-----+-----+-----+
| Header |Where |Proxy |DES | OPT| STP | PLY | PSE | TRD |
+-------------------+------+------+----+----+-----+-----+-----+-----+
Figure 2: Overview of RTSP Header Fields (A-L) Related to Methods DESCRIBE, OPTIONS, SETUP, PLAY, PAUSE, and TEARDOWN ๐ธ
Okay bestie, these are the BIG grids that show which RTSP header fields hang out with which methods ๐ฆ๐ Figure 3 is the method crew (DESCRIBE, OPTIONS, SETUP, PLAY, PAUSE, TEARDOWN), and Figures 4 and 5 cover the GET_PARAMETER, SET_PARAMETER, REDIRECT, and PLAY_NOTIFY squad โจ Every column is a little checklist, so read the codes literally ๐ง
Figure 3 is first, and it's giving main character energy ๐
+------------------+---------+-----+----+----+----+-----+-----+-----+
| Header | Where |Proxy|DES |OPT |STP | PLY | PSE | TRD |
+------------------+---------+-----+----+----+----+-----+-----+-----+
| Media-Properties | r | | - | - | m | o | o | - |
| Media-Range | r | | - | - | c | c | c | - |
| MTag | r | r | o | - | o | - | - | - |
| Pipelined- | G | amd | - | o | o | o | o | o |
| Requests | | r | | | | | | |
| Proxy- | 407 | amr | m | m | m | m | m | m |
| Authenticate | | | | | | | | |
| Proxy- | r | amd | o | o | o | o | o | o/- |
| Authentication- | | r | | | | | | |
| Info | | | | | | | | |
| Proxy- | R | rd | o | o | o | o | o | o |
| Authorization | | | | | | | | |
| Proxy-Require | R | ar | o | o | o | o | o | o |
| Proxy-Require | r | r | c | c | c | c | c | c |
| Proxy-Supported | R | amr | c | c | c | c | c | c |
| Proxy-Supported | r | | c | c | c | c | c | c |
| Public | r | amr | - | m | - | - | - | - |
| Public | 501 | amr | m | m | m | m | m | m |
| Range | R | | - | - | - | o | - | - |
| Range | r | | - | - | c | m | m | - |
| Referrer | R | | o | o | o | o | o | o |
| Request-Status | R | | - | - | - | - | - | - |
| Require | R | | o | o | o | o | o | o |
| Retry-After | 3rr,503 | | o | o | o | o | o | - |
| | ,553 | | | | | | | |
| Retry-After | 413 | | o | - | - | - | - | - |
| RTP-Info | r | | - | - | c | c | - | - |
| Scale | R | r | - | - | - | o | - | - |
| Scale | r | amr | - | - | c | c | c | - |
| Seek-Style | R | | - | - | - | o | - | - |
| Seek-Style | r | | - | - | - | m | - | - |
| Server | R | r | - | o | - | - | - | o |
| Server | r | r | o | o | o | o | o | o |
| Session | R | r | - | o | o | m | m | m |
| Session | r | r | - | c | m | m | m | o |
| Speed | R | admr| - | - | - | o | - | - |
| Speed | r | admr| - | - | - | c | - | - |
| Supported | R | r | o | o | o | o | o | o |
| Supported | r | r | c | c | c | c | c | c |
| Terminate-Reason | R | r | - | - | - | - | - | -/o |
| Timestamp | R | admr| o | o | o | o | o | o |
| Timestamp | c | admr| m | m | m | m | m | m |
| Transport | G | mr | - | - | m | - | - | - |
| Unsupported | r | | c | c | c | c | c | c |
| User-Agent | R | | m* | m* | m* | m* | m* | m* |
| Via | R | amr | c | c | c | c | c | c |
| Via | r | amr | c | c | c | c | c | c |
| WWW-Authenticate | 401 | | m | m | m | m | m | m |
+------------------+---------+-----+----+----+----+-----+-----+-----+
| Header | Where |Proxy|DES |OPT |STP | PLY | PSE | TRD |
+------------------+---------+-----+----+----+----+-----+-----+-----+
Figure 3: Overview of RTSP Header Fields (M-W) Related to Methods DESCRIBE, OPTIONS, SETUP, PLAY, PAUSE, and TEARDOWN
Next up is Figure 4, which covers the A-L fields ๐ธ Slay the alphabet ๐
+---------------------------+-------+-------+-----+-----+-----+-----+
| Header | Where | Proxy | GPR | SPR | RDR | PNY |
+---------------------------+-------+-------+-----+-----+-----+-----+
| Accept-Credentials | R | rm | o | o | o | - |
| Accept-Encoding | R | r | o | o | o | - |
| Accept-Language | R | r | o | o | o | - |
| Accept-Ranges | G | rm | o | - | - | - |
| Allow | 405 | amr | m | m | m | m |
| Authentication-Info | r | | o/- | o/- | - | - |
| Authorization | R | | o | o | o | - |
| Bandwidth | R | | - | o | - | - |
| Blocksize | R | | - | o | - | - |
| Cache-Control | G | r | o | o | - | - |
| Connection | G | | o | o | o | o |
| Connection-Credentials | 470, | ar | o | o | o | - |
| | 407 | | | | | |
| Content-Base | R | | o | o | - | o |
| Content-Base | r | | o | o | - | - |
| Content-Base | 4xx, | | o | o | o | o |
| | 5xx | | | | | |
| Content-Encoding | R | r | o | o | - | o |
| Content-Encoding | r | r | o | o | - | - |
| Content-Encoding | 4xx, | r | o | o | o | o |
| | 5xx | | | | | |
| Content-Language | R | r | o | o | - | o |
| Content-Language | r | r | o | o | - | - |
| Content-Language | 4xx, | r | o | o | o | o |
| | 5xx | | | | | |
| Content-Length | R | r | * | * | - | * |
| Content-Length | r | r | * | * | - | - |
| Content-Length | 4xx, | r | * | * | * | * |
| | 5xx | | | | | |
| Content-Location | R | | o | o | - | o |
| Content-Location | r | | o | o | - | - |
| Content-Location | 4xx, | | o | o | o | o |
| | 5xx | | | | | |
| Content-Type | R | | * | * | - | * |
| Content-Type | r | | * | * | - | - |
| Content-Type | 4xx, | | * | * | * | * |
| | 5xx | | | | | |
| CSeq | R,c | mr | m | m | m | m |
| Date | R | a | o/* | o/* | m | o/* |
| Date | r | am | o/* | o/* | o/* | o/* |
| Expires | r | r | - | - | - | - |
| From | R | r | o | o | o | - |
| If-Match | R | r | - | - | - | - |
| If-Modified-Since | R | am | o | - | - | - |
| If-None-Match | R | am | o | - | - | - |
| Last-Modified | R | r | - | - | - | - |
| Last-Modified | r | r | o | - | - | - |
| Location | 3rr | | m | m | m | - |
| Location | R | | - | - | m | - |
+---------------------------+-------+-------+-----+-----+-----+-----+
| Header | Where | Proxy | GPR | SPR | RDR | PNY |
+---------------------------+-------+-------+-----+-----+-----+-----+
Figure 4: Overview of RTSP Header Fields (A-L) Related to Methods GET_PARAMETER, SET_PARAMETER, REDIRECT, and PLAY_NOTIFY
And last but not least, Figure 5 brings back the M-W fields for the same four methods, so we get the full picture ๐๐ง
+---------------------------+---------+-------+-----+-----+-----+-----+
| Header | Where | Proxy | GPR | SPR | RDR | PNY |
+---------------------------+---------+-------+-----+-----+-----+-----+
| Media-Properties | R | amr | o | - | - | c |
| Media-Properties | r | mr | c | - | - | - |
| Media-Range | R | | o | - | - | c |
| Media-Range | r | | c | - | - | - |
| MTag | r | r | o | - | - | - |
| Notify-Reason | R | | - | - | - | m |
| Pipelined-Requests | R | amdr | o | o | - | - |
| Proxy-Authenticate | 407 | amdr | m | m | m | - |
| Proxy-Authentication-Info | r | amdr | o/- | o/- | - | - |
| Proxy-Authorization | R | amdr | o | o | o | - |
| Proxy-Require | R | ar | o | o | o | - |
| Proxy-Supported | R | amr | c | c | c | - |
| Proxy-Supported | r | | c | c | c | - |
| Public | 501 | admr | m | m | m | - |
| Range | R | | o | - | - | m |
| Range | r | | c | - | - | - |
| Referrer | R | | o | o | o | - |
| Request-Status | R | mr | - | - | - | c |
| Require | R | r | o | o | o | o |
| Retry-After | 3rr,503,| | o | o | - | - |
| | 553 | | | | | |
| Retry-After | 413 | | o | o | - | - |
| RTP-Info | R | r | o | - | - | C |
| RTP-Info | r | r | c | - | - | - |
| Scale | G | | c | - | c | c |
| Seek-Style | G | | - | - | - | - |
| Server | R | r | o | o | o | o |
| Server | r | r | o | o | - | - |
| Session | R | r | o | o | o | m |
| Session | r | r | c | c | o | m |
| Speed | G | | - | - | - | - |
| Supported | R | r | o | o | o | - |
| Supported | r | r | c | c | c | - |
| Terminate-Reason | R | r | - | - | m | - |
| Timestamp | R | adrm | o | o | o | o |
| Timestamp | c | adrm | m | m | m | m |
| Transport | G | mr | - | - | - | - |
| Unsupported | r | arm | c | c | c | c |
| User-Agent | R | r | m* | m* | - | - |
| User-Agent | r | r | m* | m* | m* | m* |
| Via | R | amr | c | c | c | c |
| Via | r | amr | c | c | c | c |
| WWW-Authenticate | 401 | | m | m | m | - |
+---------------------------+---------+-------+-----+-----+-----+-----+
| Header | Where | Proxy | GPR | SPR | RDR | PNY |
+---------------------------+---------+-------+-----+-----+-----+-----+
Figure 5: Overview of RTSP Header Fields (M-W) Related to Methods GET_PARAMETER, SET_PARAMETER, REDIRECT, and PLAY_NOTIFY
18.1. Accept โจ
okay bestie, so the Accept request-header field is how you tell the server which presentation description and parameter media types [RFC6838] you're cool with getting back in the response to a DESCRIBE request ๐
check out Section 20.2.3 for the syntax, it's giving very precise vibes ๐
the asterisk "" character groups media types into ranges ๐ so "/" means literally every media type, and "type/" means every subtype of that type. the range MAY include media type parameters that are generally applicable to that range ๐ฆ
each media type or range MAY be followed by one or more accept-params, and the first "q" parameter (if there is one) is what separates the media type's parameters from the accept-params ๐ the q is a relative quality factor, so you can show how much you prefer something ๐ซถ it uses the qvalue scale from 0 to 1 (Section 5.3.1 of [RFC7231]) and the default is q=1 โจ
example time ๐
Accept: application/example ;q=0.7, application/sdp
so this is saying the requester really likes application/sdp (default 1.0 rating) but is also okay with application/example at a 0.7 quality rating ๐ฅน
if there's no Accept header at all, the client is assumed to accept all media types ๐ but if there IS one, and the server can't send back something that fits the combined Accept field-value, then the server SHOULD send a 406 (Not Acceptable) response ๐
18.2. Accept-Credentials ๐
the Accept-Credentials header is a request-header that tells any trusted intermediary how to handle further secured connections to proxies or servers ๐ก๏ธ it MUST NOT be included in server-to-client requests ๐ โโ๏ธ see Section 19 for how this header gets used ๐
in a request, the header MUST contain the method (User, Proxy, or Any) for approving credentials that the requester picked ๐ the method MUST NOT be changed by any proxy, unless it's "Proxy", in which case a proxy MAY change it to "user" so it takes the role of user approving each further hop ๐ฆ
if the method is "User", the header holds zero or more of the credentials the client accepts ๐ it's totally fine to have zero credentials in the very first RTSP request to an RTSP server via a proxy when using "User", because the client hasn't received any credentials to accept yet ๐ธ
each credential MUST consist of one URI identifying the proxy or server, the hash algorithm identifier, and the hash over that agent's ASN.1 DER-encoded certificate [RFC5280] in Base64, following Section 4 of [RFC4648] with the padding bits set to zero ๐ all RTSP clients and proxies MUST implement the SHA-256 [FIPS180-4] algorithm for computing the hash of the DER-encoded certificate ๐ฅ SHA-256 is identified by the token "sha-256" ๐
so, the intention behind allowing other hash algorithms is to let future retirement of algorithms that aren't implemented anywhere else happen smoothly ๐ that means defining future algorithms for this purpose is meant to be extremely limited ๐ a feature tag can be used to make sure support for the replacement algorithm exists โจ
example ๐ง
Accept-Credentials:User
"rtsps://proxy2.example.com/";sha-256;exaIl9VMbQMOFGClx5rXnPJKVNI=,
"rtsps://server.example.com/";sha-256;lurbjj5khhB0NhIuOXtt4bBRH1M=
18.3. Accept-Encoding ๐
okay so Accept-Encoding is basically like Accept, but it narrows things down to the content-codings (see Section 18.15) ๐ง those are transformation codings of the message body, like gzip compression, that are acceptable in the response ๐๏ธ
a server checks whether a content-coding is acceptable using these rules, and it's lowkey a whole vibe ๐
- if the content-coding is one of the ones listed in the Accept-Encoding field, then it's acceptable, unless it comes with a qvalue of 0. (as defined in Section 5.3.1 of [RFC7231], a qvalue of 0 means "not acceptable.") ๐ โโ๏ธ
- the special "*" symbol matches any available content-coding that isn't explicitly listed in the header field ๐
- if multiple content-codings are acceptable, the one with the highest non-zero qvalue wins ๐
- the "identity" content-coding is always acceptable, meaning no transformation at all, unless it's specifically refused because the Accept-Encoding field includes "identity;q=0", or because the field includes "*;q=0" and doesn't explicitly include "identity" ๐ if the Accept-Encoding field-value is empty, then only "identity" is acceptable ๐ซถ
if an Accept-Encoding field is in a request and the server can't send back something acceptable according to it, then the server SHOULD send an error response with the 406 (Not Acceptable) status code ๐ญ
if there's no Accept-Encoding field in a request, the server MAY assume the client will accept any content-coding ๐ in that case, if "identity" is one of the available content-codings, the server SHOULD use "identity", unless it has extra info that a different content-coding is meaningful to the client ๐ฆ
18.4. Accept-Language ๐
the Accept-Language request-header field is like Accept, but it restricts the set of natural languages that are preferred for the response to the request ๐ heads up: the language specified applies to the presentation description (response message body) and any reason phrases, but NOT the media content ๐
a language tag identifies a natural language that's spoken, written, or otherwise conveyed by human beings to share info with other human beings ๐ computer languages are explicitly excluded, sorry coders ๐ the syntax and registry of RTSP 2.0 language tags are the same as the ones defined by [RFC5646] โจ
each language-range MAY be given an associated quality value that estimates the user's preference for the languages in that range ๐ the quality value defaults to "q=1" ๐ for example ๐ง
Accept-Language: da, en-gb;q=0.8, en;q=0.7
this would mean: "I prefer Danish, but will accept British English and other types of English." ๐ฉ๐ฐ๐ฌ๐ง
a language-range matches a language tag if it exactly equals the full tag, or if it exactly equals a prefix of the tag (the primary-tag in the ABNF), where the character right after primary-tag is "-" ๐ the special range "*", if it's present in the Accept-Language field, matches every tag that isn't matched by any other range in that field ๐ธ
Note: this prefix matching rule does NOT mean that language tags are assigned so that if a user understands a language with a certain tag, they'll also understand every language whose tag has that tag as a prefix. The prefix rule just lets you use prefix tags if that's the case. ๐
when a server is selecting a language, each language tag gets a qualification factor, which tells whether a language the client supports is also supported by the server, and what "preference" level it reaches ๐ง the quality value (q-value) of the longest language-range in the field that matches the language tag becomes the qualification factor for that tag โจ if no language-range in the field matches the tag, the qualification factor is 0 ๐ โโ๏ธ if there's no Accept-Language header in the request, the server SHOULD assume all languages are equally acceptable ๐ if an Accept-Language header is present, then every language with a qualification factor greater than 0 is acceptable ๐
18.5. Accept-Ranges ๐
the Accept-Ranges general-header field lets you indicate the format supported in the Range header ๐ฌ the client MUST include this header in SETUP requests to show which formats are acceptable when received in PLAY and PAUSE responses and REDIRECT requests ๐ the server MUST include it in SETUP responses and in 456 (Header Field Not Valid for Resource) error responses, to show the formats supported for the resource indicated by the Request-URI ๐ซถ the header MAY be included in GET_PARAMETER request and response pairs ๐ฆ the GET_PARAMETER request MUST contain a Session header to identify the session context the request is related to ๐ the requester and responder each indicate their capabilities regarding Range formats ๐ง
Accept-Ranges: npt, smpte, clock
the syntax is defined in Section 20.2.3 โจ
18.6. Allow ๐ช
the Allow message body header field lists the methods supported by the resource identified by the Request-URI ๐ the point is to tell the recipient the complete set of valid methods for that resource ๐ฏ an Allow header field MUST be present in a 405 (Method Not Allowed) response ๐ โโ๏ธ the Allow header MUST also be present in all OPTIONS responses where the header's content won't include exactly the same methods as listed in the Public header ๐ค
the Allow message body header MUST also be included in SETUP and DESCRIBE responses, if the methods allowed for the resource are different from the complete set of methods defined in this memo ๐
example of use ๐
Allow: SETUP, PLAY, SET_PARAMETER, DESCRIBE
18.7. Authentication-Info ๐
the Authentication-Info response-header is how the server shares some info about a successful HTTP authentication [RFC7235] in the response message โ the definition of the header is in [RFC7615], and any applicable HTTP authentication schemes live in other RFCs, like Digest [RFC7616] ๐ this header MUST only be used in response messages related to client-to-server requests ๐ซถ
18.8. Authorization โจ
Okay bestie, so an RTSP client that wants to prove who it is to a server can use the HTTP authentication mechanism from [RFC7235] ๐. It usually does this after getting a 401 response, though it doesn't have to. To do it, the client adds an Authorization request-header field to the request. The field value is the credentials, which are basically the user agent's login info for the realm of the resource being requested ๐. The header itself is defined in [RFC7235], and the actual HTTP auth schemes live in other RFCs, like Digest [RFC7616] and Basic [RFC7617] ๐
. This header MUST only be used in client-to-server requests.
If a request is authenticated and a realm is specified, the same credentials SHOULD be valid for all the other requests in that realm ๐ฆ. The one catch is that this assumes the auth scheme doesn't require something different, like credentials that change with a challenge value or that depend on synchronized clocks. Even so, each client-to-server request MUST be individually authorized by including the Authorization header with the information. No freeloading on someone else's login ๐ โโ๏ธ.
Now the caching drama ๐ญ. When a shared cache (see Section 16) gets a request with an Authorization field, it MUST NOT return the matching response as a reply to any other request. The only exceptions are these:
- If the response includes the "max-age" cache directive, the cache MAY use that response to reply to a later request. But once the maximum age has passed, a proxy cache MUST first revalidate it with the origin server, using the request-headers from the new request so the origin server can authenticate the new request. (This is the defined behavior for max-age.) If the response includes "max-age=0", the proxy MUST always revalidate it before reusing it ๐.
- If the response includes the "must-revalidate" cache-control directive, the cache MAY use that response to reply to a later request. But if the response is stale, all caches MUST first revalidate it with the origin server, using the request-headers from the new request so the origin server can authenticate it ๐ฅ.
- If the response includes the "public" cache directive, it MAY be returned in reply to any later request ๐.
18.9. Bandwidth ๐ฆ
The Bandwidth request-header field tells the server how much bandwidth the client thinks it has available. It's a positive integer, measured in kilobits per second. This can change during an RTSP session because of things like mobility or congestion ๐ธ.
Clients often can't measure this accurately. For example, the first hop might not be the bottleneck. Picture a LAN that isn't the problem, because the real choke point is the LAN's Internet access link, and the server is not on the same LAN. So the link speed of a WLAN or Ethernet network is normally NOT a good basis for estimating available bandwidth ๐. Cellular devices, or other devices plugged directly into a modem or connection-enabling device, can usually estimate the bottleneck bandwidth and a reasonable share of it for RTSP-controlled media much better. The client also has to account for other traffic sharing that bottleneck, for example by only assigning a certain fraction to RTSP and its media streams ๐ง .
It is RECOMMENDED that only clients with accurate and explicit information about bandwidth bottlenecks use this header. And this header is NOT a substitute for proper congestion control. It just gives an initial estimate and roughly tells whether the selected content can be delivered at all ๐.
Example:
Bandwidth: 62360
18.10. Blocksize ๐ง
The Blocksize request-header field goes from the client to the media server, asking for a particular media packet size. This size does not include lower-layer headers like IP, UDP, or RTP. The server is free to use a blocksize smaller than the one requested โจ. If needed, the server MAY truncate the packet size to the closest multiple of the minimum media-specific block size, or override it with the media-specific size. The block size MUST be a positive decimal number, measured in octets. And the server only returns an error (4xx) if the value is syntactically invalid. Only then, bestie ๐ .
18.11. Cache-Control ๐
The Cache-Control general-header field specifies directives that MUST be obeyed by all caching mechanisms along the request/response chain. It's serious business ๐ค.
Cache directives MUST be passed through by a proxy or gateway application, regardless of whether they matter to that application, since the directives may apply to every recipient along the chain. You also can't target a cache-directive at one specific cache ๐ .
Cache-Control should only be specified in a DESCRIBE, GET_PARAMETER, SET_PARAMETER, and SETUP request and its response. Heads up: Cache-Control doesn't only govern caching of responses to RTSP messages. It also applies to the media stream identified by the SETUP request ๐ฌ. RTSP requests are generally not cacheable, so for more on that, see Section 16 ๐ท.
Here are the cache directives you can put in the Cache-Control header:
no-cache: Indicates that the media stream or RTSP response MUST NOT be cached anywhere. This lets an origin server stop caching even by caches that have been set up to return stale responses to clients. Note: there is no security function preventing the caching of content ๐.public: Indicates that the media stream or RTSP response is cacheable by any cache ๐.private: Indicates that the media stream or RTSP response is meant for a single user and MUST NOT be cached by a shared cache. A private (non-shared) cache MAY cache the media streams ๐.no-transform: An intermediate cache (proxy) might find it useful to convert the media type of a stream. For example, a proxy might convert between video formats to save cache space or cut down traffic on a slow link. But serious operational problems can happen when these transformations are applied to streams meant for certain kinds of applications. Medical imaging, scientific data analysis, and anything using end-to-end authentication all depend on getting a stream that is bit-for-bit identical to the original media stream or RTSP response. So if a response includes the no-transform directive, an intermediate cache or proxy MUST NOT change the encoding of the stream or response. Unlike HTTP, RTSP doesn't allow partial transformation at this point, like translating into a different language ๐ญ.only-if-cached: In some cases, like times of extremely poor network connectivity, a client may want a cache to return only the media streams or RTSP responses it already has stored, and not get anything from the origin server. To do this, the client MAY include the only-if-cached directive in a request. If the cache gets this directive, it SHOULD either respond with a cached media stream or response that is consistent with the other constraints of the request, or respond with a 504 (Gateway Timeout) status. However, if a group of caches is run as a unified system with good internal connectivity, such a request MAY be forwarded within that group of caches ๐งโโ๏ธ.max-stale: Indicates that the client is willing to accept a media stream or RTSP response that has passed its expiration time. If max-stale is given a value, the client will accept a response that is past its expiration time by no more than that many seconds. If no value is assigned to max-stale, the client will accept a stale response of any age ๐ฐ๏ธ.min-fresh: Indicates that the client is willing to accept a media stream or RTSP response whose freshness lifetime is no less than its current age plus the specified time in seconds. In other words, the client wants a response that will still be fresh for at least that many seconds ๐.must-revalidate: When the must-revalidate directive is present in a SETUP response that a cache receives, that cache MUST NOT use the cache entry after it becomes stale to respond to a later request without first revalidating it with the origin server. Basically, the cache has to do an end-to-end revalidation every time, if the cached response is stale based solely on the origin server's Expires ๐.proxy-revalidate: The proxy-revalidate directive means the same thing as must-revalidate, except it does not apply to non-shared user agent caches. It can be used on a response to an authenticated request so the user's cache can store and later return the response without revalidating it, since that user has already been authenticated once. Meanwhile, proxies that serve many users still have to revalidate each time, to make sure each user has been authenticated. Note that such authenticated responses also need the "public" cache directive before they can be cached at all ๐.max-age: When an intermediate cache is forced, through a max-age=0 directive, to revalidate its own cache entry, and the client has supplied its own validator in the request, the supplied validator might differ from the one currently stored with the cache entry. In that case, the cache MAY use either validator when making its own request without affecting semantic transparency.
However, the choice of validator might affect performance. The best approach is for the intermediate cache to use its own validator when making its request. If the server replies with 304 (Not Modified), the cache can return its now-validated copy to the client with a 200 (OK) response. If the server replies with a new message body and cache validator instead, the intermediate cache can compare the returned validator with the one in the client's request, using the strong comparison function. If the client's validator is equal to the origin server's, the intermediate cache simply returns 304 (Not Modified). Otherwise, it returns the new message body with a 200 (OK) response ๐โจ.
18.12. Connection ๐
okay bestie, the Connection general-header field is how a sender tells the other side which options it wants for this particular connection ๐ And it's strictly a this-hop thing: proxies MUST NOT pass it along over further connections ๐ โโ๏ธ
RTSP 2.0 proxies MUST parse the Connection header before forwarding a message. For every connection-token listed there, they remove any header field in the message with the same name as that token โ๏ธ The option itself is signaled just by the token showing up in Connection, not by some extra header. Why? Because that extra header might not even get sent if the option has no parameters, so the token is the whole signal ๐ง
Headers listed in Connection MUST NOT include end-to-end headers, and Cache-Control is the example they give. Absolutely iconic of them to call that out ๐
RTSP 2.0 defines a "close" connection option. The sender uses it to say "hey, this connection is closing once this response is done" ๐ฆ For example, "Connection: close in either the request or the response-header fields" means the connection SHOULD NOT be considered "persistent" (Section 10.2) after the current request/response is complete.
Now the tea โ The "close" option SHOULD be limited to error messages, specifically when the server can't recover and feels it has to shut things down. The reason is that the client gets to decide how long it keeps using a connection, as long as it keeps sending valid messages. So the server shouldn't just slam the door unless it really has to ๐ธ
18.13. Connection-Credentials ๐
The Connection-Credentials response-header carries the chain of credentials for a next hop that the requester needs to approve ๐ It MUST only be used in server-to-client responses. Not in requests, not anywhere else, periodt ๐
When it's included in an RTSP response, the header MUST contain the credential info for the next hop an intermediary needs to connect to securely. That info is a list of certificates forming the chain of certification. The header MUST also include the URI of that next hop (a proxy or a server) ๐ซถ The credential data itself is a binary structure, Base64-encoded according to Section 4 of [RFC4648] with the padding bits set to zero. Inside are DER-encoded X.509v3 certificates [RFC5280] โจ
Here's how the binary structure is laid out, step by step ๐ง First comes the number of certificates (NR_CERTS) as a 16-bit unsigned integer. Next is an NR_CERTS list of 16-bit unsigned integers, one per certificate, giving its size in octets. After that come the NR_CERTS DER-encoded X.509v3 certificates, lined up in a sequence called the chain. Figure 6 shows it visually, and it's giving very organized energy ๐
A few chain rules: the certificate of the proxy or server must come first in the structure. Each certificate after that must directly certify the one before it ๐ And here's a fun little trick: the self-signed certificate that defines the root certificate authority MAY be left out of the chain, because the remote end already has to have it in order to validate anything anyway ๐ง Root keys have to be distributed independently, so that's the assumption.
Example:
Connection-Credentials:"rtsps://proxy2.example.com/";MIIDNTCC...
Where MIIDNTCC... is a Base64 encoding of the following structure:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Number of certificates | Size of certificate #1 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of certificate #2 | Size of certificate #3 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: DER Encoding of Certificate #1 :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: DER Encoding of Certificate #2 :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: DER Encoding of Certificate #3 :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 6: Format Example of Connection-Credentials Header Certificate
18.14. Content-Base ๐
The Content-Base message body header lets you set the base URI for resolving relative URIs inside the message body ๐บ๏ธ
Content-Base: rtsp://media.example.com/movie/twister/
If there's no Content-Base field, the base URI of a message body comes from either its Content-Location (but only if that Content-Location is an absolute URI) or the URI used to start the request, checked in that order of precedence ๐ช Heads up though: the base URI of the stuff inside the message body can be redefined within that body, so keep your eyes open ๐
18.15. Content-Encoding ๐ฆ
The Content-Encoding message body header is a modifier on the media-type โจ When it shows up, its value tells you which extra content-codings were applied to the message body. That tells you what decoding steps you need to take to get back to the media-type named in the Content-Type header ๐ It's mainly there so a document can be compressed without losing the identity of its underlying media type ๐๏ธ
The content-coding is a characteristic of the message body identified by the Request-URI ๐ฏ Usually the body gets stored with that encoding and only gets decoded right before rendering or something similar. An RTSP proxy MAY modify the content-coding, but only if the new coding is known to be acceptable to the recipient, and only when the message doesn't carry the "no-transform" cache directive ๐ โโ๏ธ
If the content-coding of a message body is not "identity", the message MUST include a Content-Encoding message body header listing the non-identity content-coding(s) that were used ๐
If a request's content-coding isn't acceptable to the origin server, the server SHOULD respond with status code 415 (Unsupported Media Type) ๐ซ
If multiple encodings were applied, the content-codings MUST be listed in the order they were applied, first to last, from left to right ๐ข Extra info about the encoding parameters MAY be provided by other header fields that this specification doesn't define ๐
18.16. Content-Language ๐
The Content-Language message body header describes the natural language(s) of the intended audience for the enclosed message body ๐ฃ๏ธ Heads up that it might not match every language used inside the body, so don't read too much into it ๐
Language tags were already covered in Section 18.4 ๐ The main job of Content-Language is to let a user tell entities apart based on their own preferred language. So if the body is only meant for Danish-literate people, the right header is:
Content-Language: da
If there's no Content-Language, the default is that the content is meant for all language audiences ๐ That could mean the sender doesn't see it as tied to any particular natural language, or that the sender just doesn't know who it's for ๐คทโโ๏ธ
Multiple languages MAY be listed for content meant for multiple audiences. For example, a rendition of the "Treaty of Waitangi" presented at the same time in the original Maori and English versions would use:
Content-Language: mi, en
But having several languages in a body doesn't automatically mean it's for several linguistic audiences ๐ง Take a beginner's language primer like "A First Lesson in Latin". That's clearly for English-literate readers, so its Content-Language should just be "en" ๐
Content-Language MAY be applied to any media type. It isn't limited to text documents, so go wild ๐จ
18.17. Content-Length ๐
The Content-Length message body header gives the length of the RTSP message's body (that's everything after the double CRLF following the last header), in octets of bits ๐ข Unlike HTTP, it MUST be included in every message that carries a body beyond the header portion of the RTSP message ๐ซต If it's missing, a default value of zero gets assumed. And honestly, any Content-Length greater than or equal to zero is a valid value, so zero is totally welcome here ๐ฅฐ
18.18. Content-Location โจ
okay so the Content-Location message body header field is how you tell someone where the body you're holding actually lives ๐. It's a MAY thing, for when that body can be grabbed from a location separate from the URI you originally asked for ๐ฆ. Servers SHOULD be giving you a Content-Location for the variant that's in the response body ๐ . Like, especially when a resource has a bunch of variants and each one has its own address you can fetch it from, the server SHOULD point you at the specific variant that actually came back ๐ญ.
Say an RTSP client sends a DESCRIBE request for a resource like rtsp://a.example.com/movie/Plan9FromOuterSpace ๐ฌ. The server might peek at stuff like the User-Agent header to figure out what kind of agent it's talking to. Then it sends back a media description that's tailored to that class of RTSP agents โจ. To show which exact description you got, the resource identifier rtsp://a.example.com/movie/Plan9FromOuterSpace/FullHD.sdp goes in Content-Location. The description is still a valid answer for the generic resource identifier, so you get debugging and cache operation, which is honestly so iconic ๐ (more on the cache stuff below).
The Content-Location value is NOT a replacement for the URI you originally requested ๐ โโ๏ธ. It's just a statement of where the resource for this particular variant lived at the time of the request. Future requests MAY use the Content-Location URI as the Request-URI if you want to identify the source of that specific variant ๐. This is super handy if the RTSP agent wants to double-check that its variant is still current with a conditional request ๐.
A cache cannot assume that a message body whose Content-Location is different from the URI used to retrieve it can be used to answer later requests on that Content-Location URI ๐. BUT, the Content-Location can be used to tell apart multiple variants retrieved from one requested resource ๐ง.
If the Content-Location is a relative URI, it gets interpreted relative to the Request-URI ๐ธ.
Note that Content-Location can sometimes be used to derive the base-URI for relative URI(s) inside session description formats. You have to take that into account when you use Content-Location. The easiest way to skip having to think about that whole issue is to include the Content-Base whenever you include the Content-Location ๐.
Also, when you use Media Tags together with Content-Location, the different versions MUST have different MTags, even if they're provided under different Content-Location URIs. Why? Because all those content variants were still provided in response to the same request URI ๐ .
Note also, and this is true in most cases, that the URIs used in DESCRIBE and SETUP requests are different ๐ฅบ: the URI you get in a DESCRIBE Content-Location response can't just be used directly in a SETUP request. You have to go through the steps of deriving the media resource URIs instead ๐. This usually means combining the media description's relative URIs (for example, from the SDP's a=control attribute) with the base-URI, so you end up with the absolute URIs you need for SETUP ๐ฆ.
18.19. Content-Type ๐
The Content-Type message body header tells the recipient what media type the message body is ๐. Quick heads up though: the content types that are suitable for RTSP are probably going to be limited, in practice, to presentation descriptions and parameter-value types โจ.
18.20. CSeq ๐ข
The CSeq general-header field holds the sequence number (an integer) for an RTSP request/response pair ๐. This field MUST be present in all requests and responses ๐ซถ. RTSP agents keep a sequence number series for each responder they have an open message transport channel with ๐ธ. Every time an agent starts a new RTSP request on a particular RTSP message transport, the CSeq value MUST be incremented by one ๐. The initial sequence number can be any number ๐ฒ, but it is RECOMMENDED to start at 0 ๐ .
Each sequence number series is unique between each requester and responder ๐. So the client has one series for requests to a server, and the server has a different one when it sends requests to the client ๐ฆ. Each requester and responder is identified by its socket address (IP address and port number), meaning it's per direction of a TCP connection ๐. Any retransmitted request MUST contain the same sequence number as the original ๐ โโ๏ธ. The sequence number doesn't go up for retransmissions of the same request ๐.
The RTSP agent receiving requests MUST process the requests arriving on a particular transport in the order of the sequence numbers ๐. Responses, on the other hand, are sent in the order they're generated โจ. The RTSP response MUST have the same sequence number that was in the corresponding request ๐. An RTSP agent receiving a response MAY get the responses out of order compared to the order it sent its requests ๐. So the agent MUST use the sequence number in the response to pair it with the right request ๐.
The main purpose of the sequence number is to map responses to requests ๐บ๏ธ.
The requirement to use a sequence-number increment of one for each new request is there to support any future specification of RTSP message transport over a protocol that doesn't provide in-order delivery or is unreliable ๐ง.
The rules about the initial sequence number might look kinda loose ๐. The reason is to cater to some common behavior in existing implementations: when you're using multiple reliable connections in sequence, it may still be easiest to use a single sequence-number series for a client connecting to a particular server. So the initial sequence number can be arbitrary, depending on how many previous requests there were. For any unreliable transport, a stricter definition or some other solution will be needed to detect loss of the first request ๐ฌ.
When you're using multiple sequential transport connections, there's no protocol mechanism to make sure things get processed in order, because the sequence number is scoped to the individual transport connection and its five tuple ๐. So there can be potential issues when you open a new transport connection to the same host while another one already has outstanding requests and previously dispatched requests for the same RTSP session ๐ตโ๐ซ.
RTSP Proxies need to follow the above rules too ๐ซถ. That means proxies that combine requests from multiple clients onto a single transport toward a server or a next-hop proxy need to renumber those requests so they form one unified sequence on that transport ๐. A proxy that can fulfill an agent's request without sending its own request (like a caching proxy answering from its cache) also needs to renumber, since the number of received requests for a particular target might not match the number of requests it emitted toward that target agent ๐ง . A proxy that renumbers needs to do the matching renumbering back to the original sequence number for any response it receives before forwarding it to the originator of the request ๐.
A client connected to a proxy, and using that transport to send requests to multiple servers, is pretty likely to get responses out of order ๐ช๏ธ. That's because the proxy sets up separate transports from itself to each of the servers it forwards the client's requests to. When the responses come back from the different servers, the proxy forwards them to the client in the order they arrive at the proxy and can be processed, not in the order of the client's original sequence numbers. That's intentional, so one session's requests don't get stuck waiting on another server's slow processing ๐โโ๏ธ๐จ.
18.21. Date ๐
The Date general-header field represents the date and time when the message was originated โฐ. Here's how the Date header works in an RTSP message ๐ :
- An RTSP message, sent by either the client or the server, that contains a body MUST include a Date header, if the sending host has a clock ๐ฆ;
- Clients and servers are RECOMMENDED to include a Date header in all other RTSP messages, if the sending host has a clock โจ;
- If the server doesn't have a clock that can give a reasonable approximation of the current time, its responses MUST NOT include a Date header field ๐ โโ๏ธ. In that case, this rule MUST be followed too: some origin-server implementations might not have a clock available ๐ซ . An origin server without a clock MUST NOT assign Expires or Last-Modified values to a response, unless those values were associated with the resource by a system or user with a reliable clock โณ. It MAY assign an Expires value that is known, at or before server-configuration time, to be in the past ๐. (This lets you do "pre-expiration" of responses without storing separate Expires values for each resource, which is lowkey genius ๐ง .)
A received message that doesn't have a Date header field MUST be assigned one by the recipient if the message is going to be cached by that recipient ๐ฅ. An RTSP implementation without a clock MUST NOT cache responses without revalidating them on every use ๐. An RTSP cache, especially a shared cache, SHOULD use a mechanism, like the Network Time Protocol (NTP) [RFC5905], to sync its clock with a reliable external standard โฑ๏ธ.
The RTSP-date, which is a full date as specified by Section 3.3 of [RFC5322], sent in a Date header SHOULD NOT represent a date and time after the message was generated ๐ซ. It SHOULD represent the best available approximation of the date and time of message generation, unless the implementation has no means of generating a reasonably accurate date and time ๐งญ. In theory, the date ought to represent the moment just before the message body is generated ๐ญ. In practice, though, the date can be generated at any time during message origination without affecting its semantic value ๐คทโโ๏ธ.
Note: The RTSP 2.0 date format is defined to be the full-date format in RFC 5322 ๐. This format is more flexible than the date format in RFC 1123 that RTSP 1.0 used. So implementations should use single spaces as separators, as recommended by RFC 5322, and support receiving the obsolete format ๐.
Further, the syntax allows for a comment to be added at the end of the date ๐ฌ.
18.22. Expires โจ
Okay bestie, the Expires message body header field tells everyone a date and time after which the description or media-stream should be considered stale ๐ฐ๏ธ๐ . What it means depends on the method:
- DESCRIBE response: the Expires header says the presentation description (body) SHOULD be considered stale after that date and time ๐
- SETUP response: the Expires header says the media stream SHOULD be considered stale after that date and time ๐
A stale cache entry should not be returned by a cache (either a proxy cache or a user agent cache) unless it gets validated first with the origin server, or with an intermediate cache that has a fresh copy of the message body ๐ง. For more on the whole expiration model, check out Section 16 ๐ฆ.
Having an Expires field does not mean the original resource will change or disappear at, before, or after that time ๐. Totally separate things!
The format is an absolute date and time as defined by RTSP-date. Here's an example of how it looks:
Expires: Wed, 23 Jan 2013 15:36:52 +0000
RTSP 2.0 clients and caches MUST treat other invalid date formats, especially ones including the value "0", as having occurred in the past (aka already expired) ๐. Not a vibe.
To mark a response as "already expired," an origin server should use an Expires date that is equal to the Date header value ๐. To mark a response as "never expires," an origin server SHOULD use an Expires date about one year from the time the response is sent โจ. And RTSP 2.0 servers SHOULD NOT send Expires dates more than one year in the future ๐, because that's just too much future bestie ๐ญ.
18.23. From ๐ธ
The From request-header field, if given, SHOULD contain an Internet email address for the human user who controls the requesting user agent ๐. That address SHOULD be machine usable, as defined by "mailbox" in [RFC1123] ๐ค.
This header field MAY be used for logging purposes and as a way to identify where invalid or unwanted requests came from ๐ต๏ธโโ๏ธ. It SHOULD NOT be used as an insecure form of access protection ๐, because that's not how security works, babe. The idea is that the request is being performed on behalf of the person listed, who takes responsibility for the method performed ๐ซถ. Robot agents SHOULD include this header so the person running the robot can be contacted if something goes wrong on the receiving end ๐ค๐.
The Internet email address in this field MAY be different from the Internet host that issued the request ๐ง. For example, when a request goes through a proxy, the original issuer's address SHOULD be used ๐.
Now the consent part, which is very important ๐ฅบ. The client SHOULD NOT send the From header field without the user's approval, since it might clash with the user's privacy interests or their site's security policy ๐ โโ๏ธ. It is strongly recommended that the user can disable, enable, and modify the value of this field at any time before a request ๐.
18.24. If-Match ๐
The If-Match request-header field is super useful for making sure the presentation description is intact, no matter how the description was received ๐งโจ. The description can be fetched outside of RTSP (like over HTTP) or through the DESCRIBE message ๐. When you get the presentation description through RTSP, the server implementation is guaranteeing the description's integrity from the DESCRIBE message until the SETUP message ๐.
So the client includes the MTag given in or with the session description in an If-Match header on the SETUP request, and that makes sure the resources set up actually match the description ๐ซถ. A SETUP request with the If-Match header for which the MTag validation check fails MUST generate a response using 412 (Precondition Failed). No exceptions, iykyk ๐ .
This validation check is also really handy if a session got redirected from one server to another ๐ฆ.
18.25. If-Modified-Since ๐ท
The If-Modified-Since request-header field is used with the DESCRIBE and SETUP methods to make them conditional ๐ฏ. If the requested variant hasn't been modified since the time given in this field, then the description won't be returned from the server (DESCRIBE), or the stream won't be set up (SETUP) ๐. Instead, a 304 (Not Modified) response MUST be returned without any message body. Iconic energy, honestly ๐.
Here's an example of the field:
If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
18.26. If-None-Match ๐
This request-header can be used with one or several message body tags to make DESCRIBE requests conditional ๐ซ. A client that already has one or more message bodies from the resource can check that none of those entities are current by putting their message body tags in the If-None-Match header field ๐. The whole point is to update cached info efficiently with minimal transaction overhead โญ. As a special case, the value "*" matches any current entity of the resource ๐ฆ.
Now the big rule ๐. If any of the message body tags match the one on the message body that would have come back in response to a similar DESCRIBE request (without the If-None-Match header) on that resource, or if "*" is given and any current entity exists for that resource, then the server MUST NOT perform the requested method, unless it's required to do so because the resource's modification date doesn't match the one in an If-Modified-Since header field in the request ๐ซฃ. Instead, if the request method was DESCRIBE, the server SHOULD respond with a 304 (Not Modified) response, including the cache-related header fields (especially MTag) of one of the message bodies that matched ๐. For all other request methods, the server MUST respond with a status of 412 (Precondition Failed). Plot twist ๐ญ.
Check out Section 16.1.3 for the rules on figuring out whether two message body tags match ๐.
If none of the message body tags match, then the server MAY perform the requested method as if the If-None-Match header field didn't exist ๐ธ. But it MUST also ignore any If-Modified-Since header field(s) in the request. So if no message body tags match, the server MUST NOT return a 304 (Not Modified) response. Totally different outcome, bestie ๐ญ.
If the request would, without the If-None-Match header field, end up with anything other than a 2xx or 304 status, then the If-None-Match header MUST be ignored. (For how the server behaves when both If-Modified-Since and If-None-Match show up in the same request, see Section 16.1.4 ๐ง .)
Last one, and it's a biggie ๐จ. The result of a request that has both an If-None-Match header field and an If-Match header field is unspecified, and it MUST be considered an illegal request. Don't do it ๐ โโ๏ธ๐.
18.27. Last-Modified ๐
The Last-Modified message body header field tells you the date and time the origin server believes the presentation description or media stream was last modified ๐๐. For the DESCRIBE method, the field shows the last modification date and time of the description. For SETUP, it's about the media stream ๐ฌ.
An origin server MUST NOT send a Last-Modified date that is later than the server's time of message origination. If the resource's last modification would point to some time in the future, the server MUST replace that date with the message origination date. No time traveling allowed ๐ซโณ.
An origin server SHOULD get the Last-Modified value of the message body as close as possible to when it generates the Date value of its response โฐ. That way, a recipient can make an accurate guess about when the message body was modified, especially if the body changes right around when the response gets made ๐ง.
RTSP servers SHOULD send Last-Modified whenever it's feasible ๐.
18.28. Location ๐
The Location response-header field is used to redirect the recipient to a location other than the Request-URI, so they can finish the request or find a new resource ๐บ๏ธโจ. For 3rr responses, the location SHOULD indicate the server's preferred URI for automatic redirection to the resource ๐ฆ. The field-value is a single absolute URI ๐ .
Note: the Content-Location header field (Section 18.18) is different from Location. Content-Location identifies the original location of the message body enclosed in the request. So a response is allowed to contain header fields for both Location and Content-Location ๐ซถ. Also, see Section 16.2 for the cache requirements of some methods ๐.
18.29. Media-Properties โจ
okay bestie, this general-header shows up in SETUP responses or PLAY_NOTIFY requests to tell you which media properties are currently true for the RTSP session ๐ PLAY_NOTIFY MAY be used to change these properties at any point ๐ but the client SHOULD have received the update before anything related to the new properties kicks in ๐ For aggregated sessions, the Media-Properties header comes back in every SETUP response ๐ง The one from the latest response is the one that counts for the whole session until there's another update ๐ The header MAY be sent with no value in GET_PARAMETER requests to the server, as long as a Session header is there too, so you can check what the session's Media-Properties are right now ๐ The responder MUST include the current session's media properties ๐
The media properties in this header apply to all the media in the RTSP session ๐ For aggregated sessions, the header shows the combined media properties โจ Because of that, aggregating media MAY change the media properties, which means the Media-Properties header in later SETUP responses might look different ๐ฆ
The header is a list of property values that apply to the media that was just set up, or the aggregate of media, based on the RTSP URI in the request ๐ The order doesn't matter inside the header ๐ Property values should go into one group per orthogonal property ๐ Values or groups that express multiple properties SHOULD NOT be used ๐ โโ๏ธ The list of properties MAY be extended at any time ๐ธ and any unknown property values MUST be ignored ๐ซถ
This specification defines four groups and their property values, and they're giving organized ๐
Random Access:
- Random-Access: random access is possible ๐ฏ It can optionally include a floating-point value in seconds for the longest gap between any two random access points in the media โฑ๏ธ
- Beginning-Only: seeking is limited to the beginning only โฎ๏ธ
- No-Seeking: no seeking is possible ๐ซ
Content Modifications:
- Immutable: the content won't change during the lifetime of the RTSP session ๐ง
- Dynamic: the content may change based on external methods or triggers โก
- Time-Progressing: the media that's accessible moves forward as wallclock time moves forward โฐ
Retention:
- Unlimited: content is kept for the whole lifetime of the RTSP session โพ๏ธ
- Time-Limited: content is kept at least until the specified wallclock time ๐ The time has to be given in the absolute time format from Section 4.4.3 ๐๏ธ
- Time-Duration: each individual media unit is kept for at least the specified Time-Duration โณ This lets you keep data with a time-based sliding window ๐ช The duration is a floating-point number in seconds ๐ข 0.0 is a valid value, and it means no data is kept in a time-progressing session ๐ซ
Supported Scale:
- Scales: a quoted, comma-separated list of one or more decimal values or ranges of scale values that the content supports, in any order ๐ฌ A range has a start and stop value separated by a colon ๐ A range means the content supports fine-grained selection of scale values ๐ฌ Fine-graining allows steps at least as small as one tenth of a scale value ๐ค Content counts as supporting fine-grained selection when, for a given scale value, the server can produce content with an actual scale less than one tenth of a scale unit (that's 0.1) away from the requested value ๐ฏ Negative values are supported ๐ The value 0 has no meaning and MUST NOT be used ๐ซ
Here are examples of this header for on-demand content and for a live stream with no recording ๐ฅ
On-demand:
Media-Properties: Random-Access=2.5, Unlimited, Immutable,
Scales="-20, -10, -4, 0.5:1.5, 4, 8, 10, 15, 20"
Live stream without recording/timeshifting:
Media-Properties: No-Seeking, Time-Progressing, Time-Duration=0.0
18.30. Media-Range โจ
The Media-Range general-header tells you the range of the media at the moment the RTSP message is sent ๐ This header MUST be included in the SETUP response ๐โโ๏ธ and in PLAY and PAUSE responses for media that is time-progressing โฉ It also has to show up in PLAY and PAUSE responses after any change for media that is Dynamic โก and in PLAY_NOTIFY requests that get sent because of Media-Property-Update ๐ฃ A Media-Range header with no range specifications MAY be included in GET_PARAMETER requests to the server if you want to ask for the current range ๐ In that case, the server MUST include the current range at the time it sends the response โฑ๏ธ
The header MUST include range specifications for every time format the media supports, as shown in the Accept-Ranges header (Section 18.5) when the media was set up ๐ฐ๏ธ The server MAY include more than one range specification for any given time format, so it can show media that isn't continuous ๐งฉ The range specifications SHALL be ordered with the lowest value or earliest start time first, then ranges with increasingly higher values or later start times, in that order ๐ถ
For media with the time-progressing property, the Media-Range values are only valid for the exact point in time when they were issued โ As the wallclock moves on, the media range moves on too ๐โโ๏ธ But it shall be assumed that media time moves in direct relationship to wallclock time (except for clock skew), so you can work out a reasonably accurate estimate of the media range ๐งฎโจ
18.31. MTag โจ
The MTag response-header MAY be included in DESCRIBE, GET_PARAMETER, or SETUP responses ๐ท๏ธ The message body tags from Section 4.6 that come back in a DESCRIBE response, and the one in SETUP, both refer to the presentation, meaning both the returned session description and the media stream ๐ This lets you check that you've got the right session description for a media resource at the time of the SETUP request ๐ The catch is that a change in any part of it invalidates all the parts ๐ญ
If the MTag shows up both inside the message body, for example in the "a=mtag" attribute in SDP, and in the response message, then both tags MUST be identical ๐ฏโโ๏ธ It is RECOMMENDED that the MTag mainly go in the RTSP response message, so caches can use it without inspecting the content ๐๏ธ But for session descriptions that get distributed outside of RTSP, like over HTTP, the message body tag has to be included in the session description as specified in Appendix D.1.9 ๐ฆ
SETUP and DESCRIBE requests can be made conditional on the MTag by using the If-Match (Section 18.24) and If-None-Match (Section 18.26) headers ๐ซถ
18.32. Notify-Reason โจ
The Notify-Reason response-header is used only in the PLAY_NOTIFY method ๐ฃ It tells you why the server sent the asynchronous PLAY_NOTIFY request (see Section 13.5) ๐ฌ
18.33. Pipelined-Requests โจ
The Pipelined-Requests general-header says a request should run in the context created by a previous request (or requests) ๐งต The main use is pipelining SETUP requests, so any SETUP request after the first one doesn't have to wait for the session ID to come back ๐ The header holds a unique identifier that's scoped to the persistent connection the requests were sent on ๐
When a request has the Pipelined-Requests header, the responding agent MUST check whether a binding already exists between this Pipelined-Requests identifier for the current persistent connection and an RTSP session ID ๐ต๏ธโโ๏ธ If the binding exists, the request gets processed exactly as if it had a Session header with the session ID that was found ๐ฏ If there's no mapping and no Session header in the request, the responding agent MUST create a binding once a session-creating request, meaning SETUP, finishes successfully ๐ A binding MUST NOT be created if the request failed to create an RTSP session ๐ โโ๏ธ If a request has both a Session header and the Pipelined-Requests header, the Pipelined-Requests header MUST be ignored ๐ซฅ
Note: based on the above, at least the first request with a new unique Pipelined-Requests header has to be a SETUP request (unless the protocol gets extended with new ways of creating a session) ๐ง After that first one, more SETUP requests, or requests of any type that use the RTSP session context, may include the Pipelined-Requests header ๐ท
When the server responds to any request that had the Pipelined-Requests header, it MUST also include the Session header whenever a binding to a session context exists ๐ An RTSP agent that already knows the session identifier SHOULD NOT use the Pipelined-Requests header in any request, and should only use the Session header ๐ That's because the Session identifier sticks around across transport contexts, like TCP connections, while the Pipelined-Requests identifier doesn't ๐ง
The RTSP agent that sends a request with a Pipelined-Requests header is responsible for using an identifier that's unique and hasn't been used before within the transport context ๐ซก Right now, only a TCP connection is defined as that kind of transport context ๐ฃ๏ธ A server MUST delete the Pipelined-Requests identifier and its binding to a session when that session terminates ๐งน Even with that rule, RTSP agents are RECOMMENDED not to reuse identifiers, since that makes error handling and logging way easier ๐
RTSP Proxies may need to translate Pipelined-Requests identifier values from incoming requests to outgoing ones, so requests can be aggregated onto a persistent connection ๐
18.34. Proxy-Authenticate โจ
The Proxy-Authenticate response-header field MUST be included as part of a 407 (Proxy Authentication Required) response ๐ Its field-value is a challenge that says which authentication scheme and parameters the proxy uses for this Request-URI ๐๏ธ The header is defined in [RFC7235], and any applicable HTTP authentication schemes are defined in other RFCs, like Digest [RFC7616] and Basic [RFC7617] ๐
The HTTP access authentication process is described in [RFC7235] ๐ This header MUST only be used in response messages related to client-to-server requests ๐ โโ๏ธ
18.35. Proxy-Authentication-Info โจ
The Proxy-Authentication-Info response-header is how the proxy shares some information about a successful authentication in the message response, for certain authentication schemes like the Digest scheme [RFC7616] ๐ค The header is defined in [RFC7615], and any applicable HTTP authentication schemes are defined in other RFCs ๐ This header MUST only be used in response messages related to client-to-server requests ๐ฌ It also has hop-by-hop scope ๐ฆ
18.36. Proxy-Authorization โจ
okay so Proxy-Authorization is the request header that lets the client show who it is (or who its user is) to a proxy that's asking for auth ๐. The value is the credentials with the user agent's auth info for that proxy, or for the realm of the resource being requested ๐. The header's definition is in [RFC7235], and the actual auth schemes live in other RFCs, like Digest [RFC7616] and Basic [RFC7617] ๐.
The whole HTTP access auth process is explained in [RFC7235] ๐ฆ. Here's the twist: unlike Authorization, this one only applies to the next-hop proxy ๐. And it MUST only be used in client-to-server requests ๐
โโ๏ธ (anything else is a hard no ๐).
18.37. Proxy-Require โจ
Proxy-Require is how you flag proxy-sensitive features that the proxy MUST support ๐ซถ. If the proxy doesn't support one of them, it MUST negatively acknowledge that to the client using the Unsupported header, and it MUST use the 551 (Option Not Supported) status code in the response ๐ญ. Also, a feature tag in Proxy-Require does not apply to the endpoint (server or client). So if you want both the proxies and the servers to be on board, the tag needs to be in a Require header too ๐
.
See Section 18.43 for the mechanics of this message and a usage example ๐ง. The proxies section (Section 15.1) covers when a feature needs proxy support in the first place ๐.
Example of use:
Proxy-Require: play.basic
18.38. Proxy-Supported โจ
Proxy-Supported is a general header that lists every extension the proxy supports, using feature tags ๐. It carries the intersection of the extensions supported by the forwarding proxies. The header MAY be included in any request by a proxy. Any proxy MUST add it if the Supported header is present in a request. And when it shows up in a request, the receiver MUST copy the received Proxy-Supported header into the response ๐.
The Proxy-Supported header holds a list of feature tags that apply to proxies, as described in Section 4.5. That list is the intersection of all the feature tags the proxies understand. To get that intersection, the proxy adding the header includes every proxy feature tag it understands. Any proxy that receives a request with the header MUST check the list and remove any feature tag it doesn't support. A Proxy-Supported header in the response MUST NOT be modified by proxies. These tags describe what the proxy chain supports in general and aren't specific to the request resource โจ.
Example:
C->P1: OPTIONS rtsp://example.com/ RTSP/2.0
Supported: foo, bar, blech
User-Agent: PhonyClient/1.2
P1->P2: OPTIONS rtsp://example.com/ RTSP/2.0
Supported: foo, bar, blech
Proxy-Supported: proxy-foo, proxy-bar, proxy-blech
Via: 2.0 pro.example.com
P2->S: OPTIONS rtsp://example.com/ RTSP/2.0
Supported: foo, bar, blech
Proxy-Supported: proxy-foo, proxy-blech
Via: 2.0 pro.example.com, 2.0 prox2.example.com
S->C: RTSP/2.0 200 OK
Supported: foo, bar, baz
Proxy-Supported: proxy-foo, proxy-blech
Public: OPTIONS, SETUP, PLAY, PAUSE, TEARDOWN
Via: 2.0 pro.example.com, 2.0 prox2.example.com
18.39. Public ๐ธ
Public is a response header that lists the methods the response sender supports ๐. It's about the sender's general capabilities, and its only job is to tell the recipient what the sender can do. The listed methods might or might not work for the Request-URI. If you want to say which methods are allowed for one specific URI, the Allow header (Section 18.6) MAY be used for that ๐ฏ.
Example of use:
Public: OPTIONS, SETUP, PLAY, PAUSE, TEARDOWN
If there are proxies between the sender and the recipient of a response, each intervening proxy MUST modify the Public header field to remove any methods it doesn't allow through. What's left is the intersection of the sender's methods and the methods the intervening proxies let through ๐ง.
In general, proxies should let all methods pass through transparently from the sending RTSP agent to the receiving RTSP agent. Some proxies might have a reason to block certain methods, though. Editing Public along the way means the request sender gets an accurate picture of which methods actually work on the target agent through that proxy chain ๐ซถ.
18.40. Range ๐
Range is a general header that specifies a time range in PLAY (Section 13.4), PAUSE (Section 13.6), SETUP (Section 13.3), and PLAY_NOTIFY (Section 13.5) requests and responses โฏ๏ธ. It MAY be included in GET_PARAMETER requests from the client to the server with only a Range format and no value, which asks for the current media position. This works whether the session is in Play or Ready state, in the format that was included. The server SHALL, if it supports the range format, reply with the current playing point or pause point as the start of the range. If an explicit stop point was used in the previous PLAY request, then that value shall be included as the stop point. And if the server is under any kind of media playback manipulation that changes how Range gets interpreted (like a scale value other than 1), that fact is also required to be included in any GET_PARAMETER response, by including the Scale header so the info is complete ๐ผ.
Ranges can be written in a few units. This spec defines smpte (Section 4.4.1), npt (Section 4.4.2), and clock (Section 4.4.3) range units ๐ฐ๏ธ. Octet ranges (Byte Ranges) (see Section 2.1 of [RFC7233]) and other extended units MAY be used, but their behavior is unspecified because they aren't normally meaningful in RTSP ๐คทโโ๏ธ. Servers that support the Range header MUST understand the NPT range format and SHOULD understand the SMPTE range format. If a Range header comes in a time format that isn't understood, the recipient SHOULD return 456 (Header Field Not Valid for Resource) and include an Accept-Ranges header that lists the time formats supported for that resource ๐ต.
Example:
Range: clock=19960213T143205Z-
A Range header contains a range of one single range format โจ. A range is a half-open interval, with a start point and an end point. It includes the start point but excludes the end point. A range can be fully specified with explicit start and end values, or either the start or the end can be implicit. An implicit start point means the session's pause point, and if no pause point is set, the start of the content. An implicit end point means the end of the content. Using both an implicit start and an implicit end in the same Range header is not allowed. But leaving the Range header out entirely means that same thing: from the pause point (or start) until the end of the content ๐.
As noted, Range headers define half-open intervals. A range of A-B starts exactly at time A, but ends just before B. Only the start time of a media unit, like a video or audio frame, is relevant. For example, say video frames are generated every 40 ms. A range of 10.0-10.1 would include a video frame starting at 10.0 or later, and it would include a video frame starting at 10.08, even though that frame lasts past the interval. A range of 10.0-10.08, on the other hand, would exclude the frame at 10.08 ๐๏ธ. Also, note the difference between the NPT timescale's "now" and an implicit start value. Implicit values reference the current pause-point, while "now" is the current time. In a time-progressing session with recording (retention for some or all of the time), the pause point may be 2 min into the session while "now" could be 1 hour into it โณ.
By default, range intervals go up, meaning the second point is larger than the first ๐.
Example:
Range: npt=10-15
Range intervals can also go down, though, if the Scale header (see Section 18.46) has a negative scale value. This would be the case for something like playing in reverse ๐.
Example:
Scale: -1
Range: npt=15-10
Decreasing ranges are still half-open intervals as described above. So for range A-B, A is closed and B is open. In the example above, 15 is closed and 10 is open. There's one exception: when B=0 is in a decreasing range. In that case the range is closed on both ends, because otherwise there would be no way to reach 0 on a reverse playback, for formats that have that notion, like NPT and SMPTE ๐ฅน.
Example:
Scale: -1
Range: npt=15-0
In this range, both 15 and 0 are closed ๐.
A decreasing range interval without a matching negative value in the Scale header is not valid ๐ซ.
18.41. Referrer ๐ฆ
Referrer lets the client tell the server, for the server's benefit, the address (URI) of the resource the Request-URI was obtained from ๐. That URI refers to the presentation description, which is typically retrieved over HTTP. The header lets a server build lists of back-links to resources, which helps with interest tracking, logging, optimized caching, and so on. It also helps trace obsolete or mistyped links so they can be fixed ๐ ๏ธ. The Referrer field MUST NOT be sent if the Request-URI came from a source that doesn't have its own URI, like input typed on a user's keyboard โจ๏ธ.
If the field-value is a relative URI, it SHOULD be interpreted relative to the Request-URI. The URI MUST NOT include a fragment identifier ๐ โโ๏ธ.
Here's a privacy thing: the source of a link might be private information, or it might reveal a private information source. So it's strongly recommended that the user can choose whether or not the Referrer field gets sent ๐. For example, a streaming client could have an open/anonymous toggle, where each setting turns sending Referrer and From info on or off ๐๏ธ.
Clients SHOULD NOT include a Referrer header field in a (non-secure) RTSP request if the referring page was transferred with a secure protocol ๐ซฃ.
18.42. Request-Status ๐
This request header tells you the end result for requests that take a while to finish, like PLAY (Section 13.4) โฑ๏ธ. It's sent in PLAY_NOTIFY (Section 13.5) with the end-of-stream reason, so it can report whether the PLAY request ended in success or failure ๐ฌ. The header points back to the request it's reporting on, using the CSeq number and the Session ID that was used in that request. This isn't guaranteed to be unambiguous, because the CSeq number is scoped to the transport connection. Agents that originate requests can cut down on that confusion by using a counter that keeps going up across all the sequential transports they use ๐ข. The header gives both a numerical status code (according to Section 8.1.1) and a human-readable reason phrase ๐.
Example:
Request-Status: cseq=63 status=500 reason="Media data unavailable"
Proxies that renumber the CSeq header need to remap the cseq parameter in this header when they forward the request to the next-hop agent ๐งโโ๏ธ.
18.43. Require โจ
okay so the Require request-header field is how agents make sure the other endpoint can actually handle the features this request needs ๐ซถ it can also poke around and ask if the other side supports certain features, but honestly the Supported general-header (Section 18.51) is way more effective for that vibe ๐ if the server or client that gets the request doesn't support any of the feature tags in Require, it MUST respond with error code 551 (Option Not Supported) and include the Unsupported header listing the feature tags that are NOT supported ๐ญ this header doesn't apply to proxies. for the proxy version of the same thing, check out the Proxy-Require header (Section 18.37), except for media-modifying proxies ๐ those ones handle media kinda like a server does, so they do need to understand the server's features too so they can serve the client properly ๐ง
the whole point is that the client-server chat goes smoothly when both sides understand everything, and only slows down when a feature isn't understood (like the example below) ๐ธ when the pair is well matched, things move fast and you skip the round trip that negotiation mechanisms usually need ๐โโ๏ธ it also clears up state confusion when the client needs features the server doesn't get. no cap, that's iconic ๐
Example (Not complete):
C->S: SETUP rtsp://server.com/foo/bar/baz.rm RTSP/2.0
CSeq: 302
Require: funky-feature
Funky-Parameter: funkystuff
S->C: RTSP/2.0 551 Option not supported
CSeq: 302
Unsupported: funky-feature
in this example, "funky-feature" is the feature tag that tells the client the fictional Funky-Parameter field is required ๐ฆ the connection between "funky-feature" and Funky-Parameter isn't shared over the RTSP exchange, because that relationship is an immutable property of "funky-feature" and so it shouldn't get sent with every single exchange ๐ literally the definition of not repeating yourself.
Proxies and other intermediary devices MUST ignore this header. ๐ if a particular extension needs intermediate devices to support it, the extension should be tagged in the Proxy-Require field instead (see Section 18.37) ๐ for the deets on when a feature actually needs proxy support, peep the proxies section (Section 15.1) ๐
18.44. Retry-After ๐
okay bestie, Retry-After is a response-header field that can show up with a 503 (Service Unavailable) or 553 (Proxy Unavailable) response to say how long the service is expected to be down for the requesting client ๐ญ it MAY also be used with any 3rr (Redirection) response to tell the user agent the minimum time it's asked to wait before sending the redirected request โณ and a 413 (Request Message Body Too Large) response MAY also include Retry-After, but only when the restriction is temporary ๐ซถ the value can be either an RTSP-date or a whole number of seconds (in decimal) counting from when the response was sent โจ
Example:
Retry-After: Fri, 31 Dec 1999 23:59:59 GMT
Retry-After: 120
in the second example, the delay is 2 minutes ๐
18.45. RTP-Info ๐ฆ
the RTP-Info general-header field sets RTP-specific parameters in the PLAY and GET_PARAMETER responses, or in PLAY_NOTIFY and GET_PARAMETER requests ๐ for streams that use RTP as the transport protocol, the RTP-Info header SHOULD be part of a 200 response to PLAY ๐
not including RTP-Info in a PLAY response for RTP-transported media means the client has to sync the media streams using RTCP ๐ฅบ that can be kinda risky, because RTCP can get lost and doesn't need to arrive super on time. also, the stuff that tells the client which packet a seek happened at gets affected ๐ญ
the RTP-Info MAY be included in SETUP responses to give synchronization info when transport parameters change, see Section 13.3 ๐ธ the RTP-Info header and the Range header MAY be included in a GET_PARAMETER request from client to server with no values, to ask for the current playback point and matching RTP sync info ๐ง when RTP-Info shows up in a Request, the Range header MUST also be included ๐ the server's response SHALL include both the Range header and the RTP-Info header ๐ if the session is in Play state, the Range header value SHALL be filled in with the current playback point and the matching RTP-Info values ๐ฅ if the server is in any other state, no values go in the RTP-Info header ๐ซ the header is included in PLAY_NOTIFY requests with the Notify-Reason of the end of stream, to share RTP info about the end of the stream ๐
the header can carry these parameters:
url: Indicates the stream URI that the following RTP parameters belong to. This URI MUST be the same as the one used in the SETUP request for this media stream. Any relative URI MUST use the Request-URI as base URI. This parameter MUST be present. ๐ssrc: The SSRC that the RTP timestamp and sequence number provided apply to. This parameter MUST be present. ๐seq: Indicates the sequence number of the first packet of the stream that is the direct result of the request. This lets clients deal with packets gracefully when seeking. The client uses this value to tell apart packets from before the seek and packets from after it. Note that a client may not receive the packet with the expressed sequence number, and may instead receive packets with a higher sequence number because of packet loss or reordering. This parameter is RECOMMENDED to be present. โจrtptime: MUST indicate the RTP timestamp value that matches the start time value in the Range response-header or, if it isn't explicitly given, the implied start point. The client uses this value to work out the mapping of RTP time to NPT or another media timescale. This parameter SHOULD be present to make sure inter-media synchronization is achieved. There's no requirement that any received RTP packet has the same RTP timestamp value as the one in the parameter used to set up synchronization. ๐ฆ
a mapping from RTP timestamps to NTP-format (wallclock) timestamps is available via RTCP ๐ฐ๏ธ but that info isn't enough to make a mapping from RTP timestamps to media clock time (NPT, etc.). plus, to make sure this info is there when it's needed (right at startup or after a seek) and arrives reliably, the mapping goes in the RTSP control channel ๐
for long, uninterrupted presentations, RTSP clients should also map NPT to NTP to fight drift ๐ they use the initial RTCP sender reports to do the mapping, and later reports to check drift against it ๐ซถ
Example:
Range:npt=3.25-15
RTP-Info:url="rtsp://example.com/foo/audio" ssrc=0A13C760:seq=45102;
rtptime=12345678,url="rtsp://example.com/foo/video"
ssrc=9A9DE123:seq=30211;rtptime=29567112
let's assume Audio uses a 16 kHz RTP timestamp clock and Video uses a 90 kHz RTP timestamp clock ๐ง then the media sync looks like this:
NPT 3.0---3.1---3.2-X-3.3---3.4---3.5---3.6
Audio PA A
Video V PV
- X: NPT time value = 3.25, from the Range header. โฑ๏ธ
- A: RTP timestamp value for Audio from the RTP-Info header (12345678). ๐ถ
- V: RTP timestamp value for Video from the RTP-Info header (29567112). ๐ฌ
- PA: RTP audio packet carrying an RTP timestamp of 12344878, which corresponds to NPT = (12344878 - A) / 16000 + 3.25 = 3.2 ๐
- PV: RTP video packet carrying an RTP timestamp of 29573412, which corresponds to NPT = (29573412 - V) / 90000 + 3.25 = 3.32 ๐ธ
18.46. Scale ๐๏ธ
the Scale general-header shows the requested or used view rate for the media resource being played back โฉ a scale value of 1 means normal play at the normal forward viewing rate ๐ if it's not 1, the value is relative to the normal viewing rate. like, 2 means twice the normal viewing rate ("fast forward") and 0.5 means half the normal viewing rate ๐ข so a value of 2 has content time moving at twice the playback time, meaning for every second of elapsed (wallclock) time, 2 seconds of content get delivered ๐คฏ a negative value means reverse direction โช for some media transports, this might need certain considerations to work consistently, so check Appendix C.1 for how RTP handles it ๐
the transmitted-data rate SHOULD NOT be changed by picking a different scale value ๐ญ the resulting bitrate should be reasonably close to the content's nominal bitrate for scale = 1 ๐ the server has to actively manipulate the data when needed to meet the bitrate constraints ๐ ๏ธ how scale changes work depends on the server and the media type ๐ for video, a server may, for example, deliver only key frames or selected frames ๐ฌ for audio, it may time-scale the audio while keeping the pitch, or, less desirably, deliver fragments of audio, or just completely mute it ๐
the server and content may restrict the range of scale values they support ๐ง the supported values are shown by the Media-Properties header (Section 18.29) ๐ the client SHOULD only request values that are supported ๐ but since the values can change as the content goes on, a requested value might not be valid by the time the request arrives ๐ so an unsupported value in a request doesn't cause an error. it just forces the server to pick the closest value ๐ง the response MUST always contain the actual scale value the server chose โจ
if the server can't scale, it won't return a Scale header ๐ a server that supports scale operations for PLAY MUST indicate this with the "play.scale" feature tag ๐ท๏ธ
when indicating a negative scale for reverse playback, the Range header MUST indicate a decreasing range as described in Section 18.40 โช๐ฅ
Example of playing in reverse at 3.5 times the normal rate:
Scale: -3.5
Range: npt=15-10
18.47. Seek-Style โจ
okay so picture this ๐ you send a PLAY request with a Range header to jump to a random spot in the media, but you have NO idea if the server will start you at the first media samples or the first random access point before your range. ๐ญ depending on what you're doing, you might have a strong preference, so Seek-Style is the general-header that lets you say what you want AND lets the server tell you what it actually did. it's giving communication ๐
Seek-Style is a general-header that MAY be included in any PLAY request to show your preference for any media stream with random access properties. the server MUST always include the header in any PLAY response for media with random access properties so you know which policy got applied ๐ซถ if the server gets a Seek-Style policy it doesn't recognise, it MUST ignore it and just pick its own default policy. and if a client gets a policy it doesn't recognise, it MUST ignore it too and figure out what happened using the Range header plus any media synchronization info ๐
these are the seek policies this spec defines that you can request (see also Section 4.7.1) ๐
- RAP: Random Access Point (RAP) means you ask the server to find the closest previous random access point in the media aggregate and deliver from there ๐ฆ since every media unit is delivered from a point where the decoder can fully set up its media state, the media quality is the best it can possibly be. literally chef's kiss ๐
- CoRAP: Conditional Random Access Point (CoRAP) is a lowkey cousin of RAP ๐ธ it's mostly for when random access points are spaced really far apart. CoRAP uses the RAP policy only IF a Random Access Point is closer to the requested start point than it is to the current pause point. if not, no seeking happens and playback just keeps going from the pause point. this policy assumes the media state from before the pause is still usable once delivery continues. if the client or server knows that's NOT the case, the RAP policy should be used instead. basically, when the client asks for a start point before the current pause point, a valid decoding dependency chain from the media delivered before the pause to the requested unit usually won't exist ๐ญ if the server searches and lands on a random access point, it MUST return the CoRAP policy in the Seek-Style header and adjust the Range header to match the position of the RAP it picked. if the random access point is way farther away and the server decides to just keep going from the pause point instead, it MUST include the "Next" policy in the Seek-Style header and set the Range header start point to the current pause point โจ
- First-Prior: First-prior starts delivery with the media unit whose playout time is first prior to the requested time. for discrete media, that's only units that would still be rendered at the requested time. for continuous media, it's media that will be rendered during the requested start time of the range ๐ง
- Next: this one gives you the media units right after the provided start time of the range. for continuous framed media, that's the first next frame after the time you gave, and for discrete media it's the first unit that gets rendered after that time. the main use is when the client already has everything up to a certain point and wants delivery to continue so playback stays totally uninterrupted ๐ for example, switching from broadcast/multicast delivery over to unicast delivery. ๐ this policy MUST only be used on the client's explicit request, so don't just spam it, bestie ๐
Please note these preferences are all about optimizing startup time or media quality ๐ the "Next" policy kind of bends the normal Range header definition so a client can ask for media with minimal overlap, though some overlap may still happen in aggregated sessions. RAP and First-Prior both give you media from the requested range and forward โ๏ธ but unless you use RAP, the media quality for lots of codecs that rely on predictive methods can get seriously wrecked ๐ญ unless extra data is already available, like already buffered, or through other side channels.
18.48. Server ๐ฅ๏ธ
The Server general-header field tells you about the software the origin server used to create or handle the request ๐ it can list multiple product tokens and comments that identify the server and any important subproducts. the product tokens are listed in order of how much they matter for identifying the application.
Example:
Server: PhonyServer/1.0
If the response gets forwarded through a proxy, the proxy application MUST NOT modify the Server response-header. instead, it SHOULD include a Via field (Section 18.57) ๐ซถ and if the response is generated by the proxy itself, the proxy application MUST return the Server response-header exactly as the server previously returned it ๐ฅ
18.49. Session ๐
The Session general-header field identifies an RTSP session ๐ฆ the server creates an RTSP session when a SETUP request succeeds, and it hands the session identifier back to the client in the response. the session lasts until it's destroyed by a TEARDOWN or a REDIRECT, or until the server times it out โฐ
The session identifier is chosen by the server (see Section 4.3) and MUST be returned in the SETUP response ๐ once a client has a session identifier, it MUST be included in any request related to that session. so the Session header MUST be included in requests using these methods: PLAY, PAUSE, PLAY_NOTIFY and TEARDOWN. it MAY be included in SETUP, OPTIONS, SET_PARAMETER, GET_PARAMETER, and REDIRECT, and it MUST NOT be included in DESCRIBE ๐ also, the Session header MUST NOT be included in these methods if the requests are pipelined and the session identifier isn't known yet: PLAY, PAUSE, TEARDOWN, SETUP, OPTIONS, SET_PARAMETER, and GET_PARAMETER.
In an RTSP response, the session header MUST be included in SETUP, PLAY, PAUSE, and PLAY_NOTIFY responses, and it MAY be included in TEARDOWN and REDIRECT responses โจ if it's in the request for any of these methods, it MUST also be in the response: OPTIONS, GET_PARAMETER, and SET_PARAMETER. and it MUST NOT be included in DESCRIBE responses ๐
Note that a session identifier identifies an RTSP session across transport sessions or connections ๐ธ RTSP requests for a given session can use different URIs (Presentation and media URIs). there are restrictions, depending on the session, about which URIs are acceptable for a given method. still, multiple "user" sessions for the same URI from the same client will need different session identifiers, iykyk ๐
The session identifier is needed to distinguish several delivery requests for the same URI coming from the same client.
The response 454 (Session Not Found) MUST be returned if the session identifier is invalid ๐
The header MAY include a parameter for the session timeout period. if it isn't explicitly provided, the value is set to 60 seconds โฐ since this affects how often session keep-alives are needed, values smaller than 30 seconds are not recommended ๐ โโ๏ธ larger-than-default values can still be useful for RTSP applications with inactive but established sessions that stick around for longer periods ๐ฆ
The 60-second value was picked because it gives keep-alive messages that aren't too frequent and stays low-sensitivity to variations in request/response timing ๐ if you cut the timeout below 30 seconds, the request/response timeout turns into a big chunk of the session timeout, which is not it. the 60-second value also lets committed server resources get recovered reasonably quickly if a client fails ๐ซถ
18.50. Speed ๐
The Speed general-header field asks the server to deliver specific amounts of nominal media time per unit of delivery time ๐โโ๏ธ this depends on whether the server can and wants to serve the stream at that speed. the client asks for the delivery speed to fall within a range, with a lower and an upper bound. the server SHALL deliver at the highest possible speed within the range, but never faster than the upper bound, and only as fast as the underlying network path can support the resulting transport data rates ๐ as long as any speed value in the given range can be provided, the server SHALL NOT modify the media quality. only if the server can't deliver at the lower-bound speed does it shall reduce the media quality ๐ญ
Implementation of the Speed functionality by the server is OPTIONAL ๐ the server can show it supports this through a feature tag, play.speed. if there's no Speed header in the response, that means the server doesn't support this functionality โจ
The speed parameter values are positive decimal values, e.g., 2.0 means data is delivered twice as fast as normal ๐ง a speed value of zero is invalid ๐ โโ๏ธ the range is written as "lower bound - upper bound". the lower-bound value may be smaller than or equal to the upper bound. not every speed can be supported, so the server MAY change the requested values to the closest supported ones ๐ซถ the actual supported speed MUST be included in the response. but honestly, use cases vary, and Speed ranges like 0.7-0.8, 0.3-2.0, 1.0-2.5, and 2.5-2.5 all have their own moments ๐
Example:
Speed: 1.0-2.5
Using this header changes the bandwidth used for data delivery ๐ฆ it's meant for specific situations where you want the presentation delivered at a higher or lower rate. the main use cases are buffer operations or local scale operations ๐ implementers should keep in mind that bandwidth for the session may have been negotiated beforehand (by means other than RTSP), so renegotiation might be necessary ๐ to do Speed operations, the server needs to make sure the network path can support the resulting bitrate. that means the media transport needs to support feedback so the server can react and adapt to the available bitrate ๐ฅ
18.51. Supported ๐
The Supported general-header lists all the extensions the client or server supports, using feature tags ๐ the header carries the extensions supported by whichever client or server is sending the message. the Supported header MAY be included in any request. when it's present in a request, the receiver MUST respond with its matching Supported header ๐ and yes, the Supported header also shows up in 4xx and 5xx responses โจ
The Supported header contains a list of feature tags, described in Section 4.5, that the client or server understands ๐ซถ these feature tags are what the server or client supports in general, and they aren't specific to the request resource ๐ธ
Example:
C->S: OPTIONS rtsp://example.com/ RTSP/2.0
Supported: foo, bar, blech
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 200 OK
Supported: bar, blech, baz
18.52. Terminate-Reason ๐
okay so the Terminate-Reason request-header is literally the server's way of saying "bye bestie, here's why" ๐ฅบ๐ when it sends a REDIRECT or TEARDOWN request. It lets the server give a reason for ending the session, plus some extra info. This spec defines three reasons for Redirections, and it's giving "we might add more later" energy โจ:
Server-Admin: The server needs to be shut down for some administrative reason.
Session-Timeout: A client's session has been kept alive for extended periods of time and the server has determined that it needs to reclaim the resources associated with this session.
Internal-Error An internal error that is impossible to recover from has occurred, forcing the server to terminate the session.
The Server may also attach extra parameters with info about the redirect ๐ฆ. Two are defined here:
time: Provides a wallclock time when the server will stop providing any service.
user-msg: A UTF-8 text string with a message from the server to the user. This message SHOULD be displayed to the user. ๐ซถ
18.53. Timestamp โฐ
okay the Timestamp general-header is the agent's way of saying "I sent this at THIS moment" ๐ฐ๏ธ. The value only matters to the agent that sent it, and it can use any timescale it likes ๐. The responding agent MUST echo the exact same value back ๐. If it actually has accurate info about it, it MAY also add a floating-point number showing how many seconds have passed since it got the request ๐ธ.
Why does this matter? The sender can use the timestamp to figure out the round-trip time to the responder, so it can tune its retransmission timeout when it's running over an unreliable protocol ๐ง. It also helps sort out retransmission ambiguities for unreliable transport of RTSP ๐.
ngl though, this spec only covers reliable transport of RTSP messages ๐ . The Timestamp general-header is only here in case the protocol gets extended to use unreliable transport later on ๐.
18.54. Transport ๐โจ
the Transport general-header is giving "pick your delivery vehicle" ๐. It says which transport protocol to use and configures stuff like destination address, compression, multicast time-to-live, and destination port for a single stream ๐. It only sets the values that aren't already figured out by a presentation description ๐.
A Transport request-header MAY contain a list of transport options the client is cool with, as multiple transport specification entries ๐. They're comma separated and listed in decreasing order of preference, so the first one is the fave ๐. Each one starts with a transport protocol identifier, then any number of parameters separated by semicolons ๐. A Transport request-header MAY contain multiple transport specifications using the same transport protocol identifier ๐ฆ.
The server MUST return a Transport response-header in the response to say which values it actually picked, if any ๐ . If no transport specification is supported, there's no transport header in the response, and the response MUST use status code 461 (Unsupported Transport) (Section 17.4.25) ๐. If the request had more than one transport specification, the server MUST return the single transport specification (transport-spec) that it actually chose, if any โจ. The number of transport-spec entries is expected to stay limited, since the client gets hints about what's possible from the presentation description ๐ซถ.
The Transport header MAY also show up in later SETUP requests to change transport parameters ๐. A server MAY refuse to change parameters of an existing stream ๐.
The transport protocol identifier decides, for each transport specification, which transport protocol to use and what rules come with it ๐ฅ. Each identifier defines the parameters that are required to occur, and extra optional parameters MAY occur too ๐ธ. That flexibility exists because parameters can be different and offer different options to the RTSP agent ๐ฆ. A transport specification may only contain one of any given parameter ๐ . A parameter is a name plus, optionally, a value string ๐. Parameters MAY be given in any order ๐. A transport specification may also only contain either the unicast or the multicast transport type parameter, not both ๐ .
Everything in a transport specification has to be understood: the transport protocol identifier and all of the parameters ๐ง . If any of it isn't understood, the transport specification MUST be ignored ๐. An RTSP proxy of any type that uses or modifies the transport specification (like an access proxy or security proxy) MUST remove specifications with unknown parameters before forwarding the RTSP message ๐ก๏ธ. If that leaves no transport specification at all, the proxy SHALL send a 461 (Unsupported Transport) (Section 17.4.25) response without any Transport header ๐ญ.
The Transport header is restricted to describing a single media stream. RTSP can control multiple streams as one entity, but making the Transport header only about one stream is what keeps firewall designs so much simpler ๐งฑ.
The general syntax for the transport protocol identifier is a list of slash-separated tokens:
Value1/Value2/Value3...
For RTP transports, that takes the form:
RTP/profile/lower-transport
The default for the "lower-transport" parameter depends on the profile. For RTP/AVP, the default is UDP ๐.
There are two ways to say where the media should go for unicast transport ๐ฏ:
dest_addr: The presence of this parameter and its values gives the destination address or addresses (host address and port pairs for IP flows) needed for the media transport.
No dest_addr: Without the dest_addr parameter, the server MUST send media to the same address the RTSP messages came from ๐.
Which one to use depends on the use case. Sometimes the only allowed option is no explicit address, so the server just delivers media back to whoever sent the RTSP messages ๐.
Multicast has several ways to specify addresses too, but they work differently than unicast ๐:
dest_addr with client picked address: The address and relevant parameters, like TTL (scope), for the actual multicast group to deliver the media to. There are security implications (Section 21) with this method that need to be addressed because an RTSP server can be used as a DoS attacker on an existing multicast group.
dest_addr using Session Description Information: The information included in the transport header can all come from the session description, e.g., the SDP "c=" and "m=" lines. This mitigates some of the security issues of the previous methods as it is the session provider that picks the multicast group and scope. The client MUST include the information if it is available in the session description.
No dest_addr: The behavior when no explicit multicast group is present in a request is not defined.
An RTSP proxy will need to take care here ๐ง. If the media shouldn't be routed through the proxy, the proxy will need to add the destination indication itself ๐ฆ.
Here are the configuration parameters associated with transport ๐ ๏ธ:
General parameters:
unicast / multicast: This is a mutually exclusive indication of whether unicast or multicast delivery will be attempted. One of the two values MUST be specified. Clients that can handle both unicast and multicast transmission need to indicate that by including two full transport-specs with separate parameters for each. ๐
layers: The number of multicast layers to be used for this media stream. The layers are sent to consecutive addresses starting at the dest_addr address. If the parameter is not included, it defaults to a single layer. ๐ฐ
dest_addr: A general destination address parameter that can contain one or more address specifications. Each combination of protocol/profile/lower transport needs to have the format and interpretation of its address specification defined. For RTP/AVP/UDP and RTP/AVP/TCP, the address specification is a tuple containing a host address and port. Note, only a single destination parameter per transport spec is intended. The usage of multiple destinations to distribute a single media to multiple entities is unspecified. ๐ฎ
The client originating the RTSP request MAY specify the destination address of the stream recipient with the host address as part of the tuple. When the destination address is specified, the recipient may be a different party than the originator of the request. To avoid becoming the unwitting perpetrator of a remote-controlled DoS attack, a server MUST perform security checks (see Section 21.2.1) and SHOULD log such attempts before allowing the client to direct a media stream to a recipient address not chosen by the server. Implementations cannot rely on TCP as a reliable means of client identification. If the server does not allow the host address part of the tuple to be set, it MUST return 463 (Destination Prohibited). ๐ซ
The host address part of the tuple MAY be empty, for example ":58044", in cases when it is desired to specify only the destination port. Responses to requests including the Transport header with a dest_addr parameter SHOULD include the full destination address that is actually used by the server. The server MUST NOT remove address information that is already present in the request when responding, unless the protocol requires it. ๐
src_addr: A general source address parameter that can contain one or more address specifications. Each combination of protocol/profile/lower transport needs to have the format and interpretation of its address specification defined. For RTP/AVP/UDP and RTP/AVP/TCP, the address specification is a tuple containing a host address and port. ๐
This parameter MUST be specified by the server if it transmits media packets from an address other than the one RTSP messages are sent to. This lets the client verify the source address and gives it a destination address for its RTCP feedback packets, if RTP is used. The address or addresses indicated in the src_addr parameter SHOULD be used both for sending and receiving the media stream's data packets. The main reasons are threefold: First, indicating the port and source address(s) lets the receiver know where the packets are expected to come from. Second, traversal of NATs is greatly simplified when traffic flows symmetrically over a NAT binding. Third, certain NAT traversal mechanisms need to know which address and port to send so-called "binding packets" to from the receiver to the sender, thus creating an address binding in the NAT that the sender-to-receiver packet flow can use. ๐
The Transport header is also where the setup parameters live ๐ In case the vibe needs a reminder, this part keeps going straight into the parameter list.
This info can also show up in SDP ๐ but honestly, transport is more of a transport thing than a media-initialization thing, so the real source of truth should be the SETUP response ๐
mode: okay so mode tells us which methods are supported for this session ๐ฆ The only valid value right now is "PLAY", and if it's not there, the default is "PLAY" โจ "RECORD" was defined in RFC 2326, but in this spec it's unspecified but reserved ๐ธ RECORD and other values may be specified in the future ๐
interleaved: this one is giving mixing ๐งฉ It means mixing the media stream with the control stream, in whatever protocol the control stream is using, using the mechanism from Section 14. The argument gives the channel number for the $ block (see Section 14), and it MUST be present ๐ This parameter MAY be specified as an interval, like interleaved=4-5, when the transport choice for the media stream needs it, e.g., RTP with RTCP ๐ง The channel number in the request is only guidance from the client to the server about which channel number(s) to use ๐ก The server MAY set any valid channel number in the response ๐ The declared channels are bidirectional, so both end parties MAY send data on the given channel ๐ฌ One example is the second channel used for RTCP, where both server and client send RTCP packets on the same channel.
This allows RTP/RTCP to be handled similarly to how it's done with UDP, i.e., one channel for RTP and the other for RTCP ๐ซถ
MIKEY: this parameter is used with transport specs that can use MIKEY [RFC3830] for security context establishment ๐ So far, only the SRTP-based RTP profiles SAVP and SAVPF can use MIKEY, and that's defined in Appendix C.1.4.1 ๐ This parameter can be included in both request and response messages. The binary MIKEY message SHALL be Base64-encoded [RFC4648] before it goes into the value part of the parameter, where the encoding adheres to the definition in Section 4 of RFC 4648 and the padding bits are set to zero ๐ง
Multicast-specific:
ttl: multicast time-to-live for IPv4 ๐ก In requests, the value is the TTL the client asks the server to use. In a response, it's the value the server is actually using ๐ A server will need to consider what values are reasonable, and also the authority of the user to set this value ๐ง Corresponding functions aren't needed for IPv6, since scoping is part of the IPv6 multicast address [RFC4291] โจ
RTP-specific:
These parameters MAY only be used if the media-transport protocol is RTP. ๐ถ
ssrc: if it's included in a SETUP response, the ssrc param shows the RTP SSRC [RFC3550] value(s) the media server will use for RTP packets within the stream ๐ค The values are a slash-separated sequence, with each SSRC written as an eight-digit hexadecimal value.
The ssrc parameter MUST NOT be specified in requests ๐ซ Specifying it in a SETUP request is deprecated, since it's incompatible with the RTP specification [RFC3550] ๐ If it's in the Transport header of a SETUP request, the server SHOULD ignore it and choose appropriate SSRCs for the stream โจ The server SHOULD set the ssrc parameter in the Transport header of the response ๐ซง
RTCP-mux: used to negotiate RTP and RTCP multiplexing [RFC5761] on a single underlying transport stream/flow ๐ง If this param is in a SETUP request, it means the client supports it and requires the server to use RTP and RTCP multiplexing ๐ The client SHALL only include one transport stream in the Transport header specification ๐ To give the server a choice between RTP/RTCP multiplexing or not, two different transport header specifications must be included.
The parameters setup and connection defined below MAY only be used if the media-transport protocol of the lower-level transport is connection oriented (such as TCP) ๐งต However, these parameters MUST NOT be used when interleaving data over the RTSP connection ๐
setup: clients use the setup param on the Transport line in a SETUP request to indicate the roles they wish to play in a TCP connection ๐
This parameter is adapted from [RFC4145]. Its use in RTP/AVP/TCP non-interleaved transport is discussed in Appendix C.2.2, and the discussion below is limited to syntactic issues ๐ค Clients may specify the following values for setup:
- active: The client will initiate an outgoing connection.
- passive: The client will accept an incoming connection.
- actpass: The client is willing to accept an incoming connection or to initiate an outgoing connection.
If a client does not specify a setup value, "active" is assumed ๐ซ
In response to a client SETUP request where the setup parameter is set to "active", a server's 2xx reply MUST assign the setup parameter to "passive" on the Transport header line ๐
In response to a client SETUP request where the setup parameter is set to "passive", a server's 2xx reply MUST assign the setup parameter to "active" on the Transport header line ๐
In response to a client SETUP request where the setup parameter is set to "actpass", a server's 2xx reply MUST assign the setup parameter to "active" or "passive" on the Transport header line ๐ฏ
Note that the "holdconn" value for setup is not defined for RTSP use, and MUST NOT appear on a Transport line ๐
connection: clients use the connection param in a transport specification part of the Transport header in a SETUP request to say whether they prefer reusing an existing connection between client and server (in which case they set "existing") or requesting a new connection between client and server (in which case they set "new") ๐ Typically, clients use "new" for the first SETUP request for a URL, and "existing" for subsequent SETUP requests for a URL ๐
If a client SETUP request assigns "new" to connection, the server response MUST also assign "new" to connection on the Transport line ๐
If a client SETUP request assigns "existing" to connection, the server response MUST assign a value of "existing" or "new" to connection on the Transport line, at its discretion ๐ซ
The default value of connection is "existing", for all SETUP requests (initial and subsequent) โจ
The combination of transport protocol, profile and lower transport needs to be defined. A number of combinations are defined in Appendix C ๐
Here's a usage example. A client is advertising that it can handle multicast or unicast, preferring multicast ๐ Since this is a unicast-only stream, the server responds with the proper transport parameters for unicast ๐ง
C->S: SETUP rtsp://example.com/foo/bar/baz.rm RTSP/2.0
CSeq: 302
Transport: RTP/AVP;multicast;mode="PLAY",
RTP/AVP;unicast;dest_addr="192.0.2.5:3456"/
"192.0.2.5:3457";mode="PLAY"
Accept-Ranges: npt, smpte, clock
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 200 OK
CSeq: 302
Date: Fri, 20 Dec 2013 10:20:32 +0000
Session: rQi1hBrGlFdiYld241FxUO
Transport: RTP/AVP;unicast;dest_addr="192.0.2.5:3456"/
"192.0.2.5:3457";src_addr="192.0.2.224:6256"/
"192.0.2.224:6257";mode="PLAY"
Accept-Ranges: npt
Media-Properties: Random-Access=0.6, Dynamic,
Time-Limited=20081128T165900
18.55. Unsupported โจ
The Unsupported response-header lists the features that aren't supported by the responding RTSP agent ๐
If the feature was specified via the Proxy-Require field (Section 18.37), and there's a proxy on the path between the client and the server, the proxy MUST send a response message with a status code of 551 (Option Not Supported) ๐ง The request MUST NOT be forwarded ๐
See Section 18.43 for a usage example ๐
18.56. User-Agent โจ
The User-Agent general-header field contains info about the user agent that originated the request or produced a response ๐ต๏ธ It's for statistical purposes, tracing protocol violations, and automated recognition of user agents, so responses can be tailored to avoid particular user agent limitations ๐ User agents SHOULD include this field with requests ๐
The field can contain multiple product tokens and comments identifying the agent and any subproducts that form a significant part of the user agent. By convention, the product tokens are listed in order of their significance for identifying the application ๐
Example:
User-Agent: PhonyClient/1.2
18.57. Via โจ
The Via general-header field MUST be used by proxies to indicate the intermediate protocols and recipients between the user agent and the server on requests, and between the origin server and the client on responses ๐ค๏ธ It's for tracking message forwards, avoiding request loops, and identifying the protocol capabilities of all senders along the request/response chain ๐
Each of multiple values in the Via field represents each proxy that has forwarded the message. Each recipient MUST append its information, so the end result is ordered according to the sequence of forwarding applications ๐ So messages originating with the client or server don't include the Via header. The first proxy or other intermediate adds the header and its information into the field. Any additional intermediate adds additional field-values ๐งฉ That way the server sees the chain of intermediates in a client-to-server request, and the client sees the full chain in the response message ๐
Proxies (e.g., Access Proxy or Translator Proxy) SHOULD NOT, by default, forward the names and ports of hosts within the private/protected region ๐ This information SHOULD only be propagated if explicitly enabled. If not enabled, the via-received of any host behind the firewall/NAT SHOULD be replaced by an appropriate pseudonym for that host ๐ฅท
For organizations that have strong privacy requirements for hiding internal structures, a proxy MAY combine an ordered subsequence of Via header field entries with identical sent-protocol values into a single such entry ๐ซฃ Applications MUST NOT combine entries that have different received-protocol values ๐ซ
18.58. WWW-Authenticate ๐
okay bestie, the WWW-Authenticate header is specced in [RFC7235] ๐
, but how you actually use it depends on which auth schemes you're running, like Digest [RFC7616] and Basic [RFC7617] โจ. The WWW-Authenticate response-header field MUST be included in 401 (Unauthorized) response messages ๐
โโ๏ธ, no skipping it! The field-value has at least one challenge that tells the client which authentication scheme(s) and parameters apply to the Request-URI ๐. This header MUST only be used in response messages related to client to server requests ๐.
The HTTP access authentication process is described in [RFC7235], with some clarification in Section 19.1 ๐ง. User agents are advised to take special care when parsing the WWW-Authenticate field-value ๐, because it might contain more than one challenge. Or, if more than one WWW-Authenticate header field is provided, the contents of a challenge itself can contain a comma-separated list of authentication parameters ๐. It's giving parsing chaos, so be careful!
19. Security Framework ๐ก๏ธ
The RTSP security framework has two high-level components ๐: the pure authentication mechanisms based on HTTP authentication, and the message transport protection based on TLS, which is independent of RTSP. Because RTSP servers and HTTP servers are so similar in syntax and usage, the security for HTTP gets reused to a large extent ๐ซถ. Main character energy, literally.
19.1. RTSP and HTTP Authentication ๐
RTSP and HTTP share common authentication schemes, so they follow the same framework as specified in [RFC7235] โจ. RTSP uses the corresponding RTSP error codes (401 and 407) and headers (WWW-Authenticate, Authorization, Proxy-Authenticate, Proxy-Authorization) by importing the definitions from [RFC7235] ๐ฆ. Servers SHOULD implement both the Basic [RFC7617] and the Digest [RFC7616] authentication schemes. Clients MUST implement both the Basic and the Digest authentication schemes, so that a server that requires the client to authenticate can trust that the capability is present ๐ค. If you're implementing the Digest authentication scheme, then the additional considerations specified below in Section 19.1.1 MUST be followed ๐.
It should be stressed that using HTTP authentication alone does not provide full RTSP message security ๐จ. Therefore, TLS SHOULD be used; see Section 19.2. Any RTSP message containing an Authorization header using the Basic authentication scheme MUST be using a TLS connection with confidentiality protection enabled, i.e., no NULL encryption ๐. No NULL encryption, bestie, I'm serious!
In cases where there's a chain of proxies between the client and the server, each proxy may individually request the client or previous proxy to authenticate itself ๐. This is done using the Proxy-Authenticate (Section 18.34), the Proxy-Authorization (Section 18.36), and the Proxy-Authentication-Info (Section 18.35) headers. These headers are hop-by-hop headers and are only scoped to the current connection and hop ๐ฆ. So if a proxy chain exists, a proxy connecting to another proxy will have to act as a client to authorize itself towards the next proxy ๐ง. The WWW-Authenticate (Section 18.58), Authorization (Section 18.8), and Authentication-Info (Section 18.7) headers are end-to-end and MUST NOT be modified by proxies ๐
โโ๏ธ. Hands off!
This authentication mechanism only works for client-to-server requests as currently defined ๐ฌ. That leaves server-to-client requests outside of the context of TLS-based communication, which makes them more vulnerable to message-injection attacks on the client ๐. Based on the server-to-client methods that exist, the potential risks are various: hijacking (REDIRECT), denial of service (TEARDOWN and PLAY_NOTIFY), or attacks with uncertain results (SET_PARAMETER) โ ๏ธ. Not me getting hijacked by a REDIRECT ๐ญ.
19.1.1. Digest Authentication ๐งฉ
This section describes the modifications and clarifications required to apply the HTTP Digest authentication scheme to RTSP ๐ซ. The RTSP scheme usage is almost completely identical to that for HTTP [RFC7616]. These modifications are based on the procedures defined for SIP 2.0 [RFC3261] (in Section 22.4), but updated to use RFC 7235, RFC 7616, and RFC 7615 instead of RFC 2617 ๐.
Digest authentication uses two additional headers, Authentication-Info and Proxy-Authentication-Info, that are defined as in [RFC7615] ๐. The rules for Digest authentication follow those defined in [RFC7616], with "HTTP/1.1" replaced by "RTSP/2.0", in addition to the following differences:
- Use the ABNF specified in the referenced documents, with the difference that the URI parameter uses the request URI format for RTSP, i.e., the ABNF element
Request-URI(see Section 20.2.1). The domain parameter uses theRTSP-URI-Refelement for absolute and relative URIs ๐. - If MTags are used, then the example procedure for choosing a nonce based on ETag can work, based on replacing the ETag with the MTag ๐ท๏ธ.
- As a clarification to the calculation of the A2 value for message integrity assurance in the Digest authentication scheme, implementers should assume, when the entity-body is empty (that is, when the RTSP messages have no message body), that the hash of the message body resolves to the hash of an empty string, or
H(entity-body). For example,MD5("") = "d41d8cd98f00b204e9800998ecf8427e"๐งฎ. Ngl, that hash is iconic.
19.2. RTSP over TLS ๐โจ
RTSP agents MUST implement RTSP over TLS as defined in this section and the next, Section 19.3 ๐. RTSP MUST follow the same guidelines with regard to TLS [RFC5246] usage as specified for HTTP; see [RFC2818] ๐. RTSP over TLS is separated from unsecured RTSP on both the URI level and the port level ๐ช. Instead of using the rtsp scheme identifier in the URI, the rtsps scheme identifier MUST be used to signal RTSP over TLS ๐ค. If no port is given in a URI with the rtsps scheme, port 322 MUST be used for TLS over TCP/IP ๐ข.
When a client tries to set up an insecure channel to the server (using the rtsp URI), and the policy for the resource requires a secure channel, the server MUST redirect the client to the secure service by sending a 301 redirect response code together with the correct Location URI (using the rtsps scheme) ๐โโ๏ธ๐จ. A user or client MAY upgrade a non-secured URI to a secured one by changing the scheme from rtsp to rtsps ๐. A server implementing support for rtsps MUST allow this ๐ซถ.
It should be noted that TLS allows for mutual authentication (when using both server and client certificates) ๐ค. Still, one of the more common ways TLS is used is to provide only server-side authentication, often to avoid client certificates ๐. TLS is then used in addition to HTTP authentication, providing transport security and server authentication, while HTTP authentication is used to authenticate the client ๐งโ๐คโ๐ง.
RTSP includes the possibility to keep a TCP session up between the client and server throughout the RTSP session lifetime ๐งต. It may be convenient to keep the TCP session, not only to save the extra setup time for TCP, but also the extra setup time for TLS (even if TLS uses the resume function, there will be almost two extra round trips) โฑ๏ธ. Still, when TLS is used, such behavior introduces extra active state in the server, not only for TCP and RTSP, but also for TLS ๐ง . This may increase the vulnerability to DoS attacks ๐ฐ.
There's a potential security vulnerability when reusing TCP and TLS state for different resources (URIs) ๐จ. If two different hostnames point at the same IP address, it can be desirable to reuse the TCP/TLS connection to that server. In that case, the RTSP agent having the TCP/TLS connection MUST verify that the server certificate associated with the connection has a SubjectAltName matching the hostname present in the URI for the resource an RTSP request is to be issued ๐. Verify, verify, verify!
In addition to these recommendations, Section 19.3 gives further recommendations of TLS usage with proxies ๐ฆโจ.
19.3. Security and Proxies ๐ง
okay so proxies are literally the ultimate "man in the middle" ๐ญ, and security is all about making sure there is NOT one ๐. This section is about letting clients still use proxies even when the RTSP agents are talking over a secure transport (TLS) ๐. The TLS proxy mechanism lets the server and the proxy identify themselves with certificates โจ. The client, though, can't be identified based on certificates ๐. So the client has to pick: either follow the procedure below, or go straight to the server with TLS and skip the proxies entirely ๐ฆ. That choice may depend on policies.
In general there are two kinds of proxies ๐ . There are transparent proxies, which the client has no idea exist, and non-transparent proxies, which the client knows about. This memo only specifies non-transparent RTSP proxies, meaning proxies that are visible to both the RTSP client and the RTSP server ๐. A proxy setup needs a trust model where both client and server can trust the proxies to handle RTSP messages correctly ๐ซถ. To trust a proxy, the client and server also have to be aware of it. So transparent proxies generally can't be seen as trusted and won't work well with security (unless they only work at the transport layer) ๐ฌ. For the rest of this section, "proxy" means a non-transparent one that inspects or manipulates RTSP messages.
HTTP Authentication is built on the assumption that proxies exist ๐ธ. On top of client-server authentication, it can also provide user-proxy authentication and proxy-proxy/server authentication ๐.
When TLS is applied and a proxy is used, the client connects to the proxy's address whenever it talks to any RTSP server ๐. That means that with TLS, the client authenticates the proxy server and NOT the end server, which is a big deal ๐ณ. Note that when the client checks the server certificate in TLS, it MUST check the proxy's identity (URI or possibly other known identity) against the proxy's identity as presented in the proxy's Certificate message ๐.
Here's the tricky part ๐ฅบ. For a proxy the client has accepted, the proxy needs to know on what grounds it should accept the next-hop certificate. Both the proxy and the user may have rules for this, and the user should be able to pick the behaviour they want โจ. To handle this, the Accept-Credentials header (see Section 18.2) is used, and the client can ask the proxy or proxies to relay back the chain of certificates used to authenticate any intermediate proxies as well as the server ๐งพ. Because the proxies are viewed as trusted, the user gets to enforce policies on each trusted proxy about whether it should accept the next agent in the chain ๐. However, it should be noted that not all deployments will return that chain. An operator might want to hide its topology from the client, and that's a valid reason ๐ต๏ธโโ๏ธ. It should also be noted well that the client has no insight into the proxy's operation. Even a trusted proxy can still return an incomplete chain of certificates ๐.
Heads up bestie: the client has zero visibility into what the proxy is doing, so a trusted proxy can still hand back an incomplete chain. ๐ฌ
Now the big rules ๐. A proxy MUST use TLS for the next hop if the RTSP request includes an "rtsps" URI ๐. TLS MAY be applied on intermediate links (for example, between client and proxy, or between proxy and proxy) even when the resource and the end server are not required to use it ๐งฆ. The chain of proxies a client uses to reach a server, along with its TLS sessions, MUST have commensurate security โ๏ธ. So a proxy MUST, when initiating the next-hop TLS connection, use the incoming TLS connection's cipher-suite list, only modified by removing any cipher suites that the proxy doesn't support ๐ง. If a proxy fails to set up a TLS connection because of a cipher-suite mismatch between itself and the next-hop proxy or server, that gets reported with error code 472 (Failure to Establish Secure Connection) ๐.
19.3.1. Accept-Credentials
The Accept-Credentials header lets the client hand out simple authorization policies to intermediate proxies ๐. The client includes it to dictate how the proxy treats the server's or next proxy's certificate ๐ซก. There are currently three methods defined โจ:
- Any: With "any", the proxy (or proxies) MUST accept whatever certificate is presented. Of course, this is not a recommended option to use, but it may be useful in certain circumstances (such as testing) ๐งช.
- Proxy: For the "proxy" method, the proxy (or proxies) MUST use its own policies to validate the certificate and decide whether or not to accept it. This is convenient when the user has a strong trust relation with the proxy. Reasons a strong trust relation may exist include a personal or company proxy, or a proxy that has an out-of-band policy configuration mechanism ๐ข.
- User: For the "user" method, the proxy (or proxies) MUST send credential information about the next hop to the client for authorization. The client can then decide whether or not the proxy should accept the certificate. See Section 19.3.2 for further details ๐โโ๏ธ.
If the Accept-Credentials header isn't in the RTSP request from the client, then the "Proxy" method MUST be used as the default ๐ซ . If a method other than "Proxy" is going to be used, then the Accept-Credentials header MUST be included in all of the RTSP requests from the client. This is because you can't assume the proxy always keeps the TLS state or the user's previous preference between different RTSP messages, especially if a long time passes between the messages โณ.
With the "Any" and "Proxy" methods, the proxy applies the policy as defined for each method ๐ง . If the policy does NOT accept the credentials of the next hop, the proxy MUST respond with a message using status code 471 (Connection Credentials Not Accepted) ๐ซ.
An RTSP request going from server to client MUST NOT include the Accept-Credentials header ๐ โโ๏ธ. Just like with non-secured communication, whether these requests are possible depends on the presence of a client-established connection. However, if the server-to-client request relates to a session set up over a TLS-secured channel, it MUST be sent over a TLS-secured connection ๐. That secured connection MUST also be the one used by the last client-to-server request. If no such transport connection exists when the server wants to send the request, the server MUST discard the message ๐๏ธ.
Further policies MAY be defined and registered, but this should be done with caution ๐ง.
19.3.2. User-Approved TLS Procedure
For the "User" method, each proxy MUST perform the following procedure for each RTSP request ๐:
- Set up the TLS session to the next hop if it isn't already there (so run the TLS handshake, but do NOT send the RTSP request yet) ๐ค.
- Extract the peer certificate chain for the TLS session ๐.
- Check whether a matching identity and hash of the peer certificate are present in the Accept-Credentials header. If they are, send the message to the next hop and wrap up these procedures ๐. If not, move on to the next step.
- The proxy responds to the RTSP request with a 470 or 407 response code. The 407 response code MAY be used when the proxy requires both user and connection authorization from the user or client ๐ชช. In this message the proxy MUST include a Connection-Credentials header (see Section 18.13) with the next hop's identity and certificate ๐ซ.
The client MUST, upon receiving a 470 (Connection Authorization Required) or 407 (Proxy Authentication Required) response with a Connection-Credentials header, decide whether or not to accept the certificate. If it can't make that decision itself, the user SHOULD be consulted ๐. Using IP addresses in the next-hop URI and certificates, rather than domain names, makes it really hard for a user to figure out whether they should approve the next hop ๐ตโ๐ซ. So proxies are RECOMMENDED to use domain names to identify themselves in URIs and in the certificates ๐. If the certificate is accepted, the client has to send the RTSP request again. In that request, the client has to include the Accept-Credentials header with the hash over the DER-encoded certificate for all trusted proxies in the chain ๐งฉ.
Example ๐:
C->P: SETUP rtsps://test.example.org/secret/audio RTSP/2.0
CSeq: 2
Transport: RTP/AVP;unicast;dest_addr="192.0.2.5:4588"/
"192.0.2.5:4589"
Accept-Ranges: npt, smpte, clock
Accept-Credentials: User
P->C: RTSP/2.0 470 Connection Authorization Required
CSeq: 2
Connection-Credentials: "rtsps://test.example.org";
MIIDNTCCAp...
C->P: SETUP rtsps://test.example.org/secret/audio RTSP/2.0
CSeq: 3
Transport: RTP/AVP;unicast;dest_addr="192.0.2.5:4588"/
"192.0.2.5:4589"
Accept-Credentials: User "rtsps://test.example.org";sha-256;
dPYD7txpoGTbAqZZQJ+vaeOkyH4=
Accept-Ranges: npt, smpte, clock
P->S: SETUP rtsps://test.example.org/secret/audio RTSP/2.0
CSeq: 3
Transport: RTP/AVP;unicast;dest_addr="192.0.2.5:4588"/
"192.0.2.5:4589"
Via: RTSP/2.0 proxy.example.org
Accept-Credentials: User "rtsps://test.example.org";sha-256;
dPYD7txpoGTbAqZZQJ+vaeOkyH4=
Accept-Ranges: npt, smpte, clock
One implication of this process is that the connection for secured RTSP messages may take significantly more round-trip times for the first message โฑ๏ธ. A complete extra message exchange happens between the proxy connecting to the next hop and the client, because each hop needs its own approval ๐ฉ. However, if each message contains the chain of proxies that the requester accepts, the rest of the message exchange should not be delayed ๐โโ๏ธ. Including the credentials in each request, rather than building state into each proxy, also avoids the need for revocation procedures ๐.
20. Syntax ๐
The RTSP syntax is described in Augmented Backus-Naur Form (ABNF) as defined in RFC 5234 [RFC5234]. It uses the basic definitions present in RFC 5234 ๐ง .
Please note that ABNF strings, e.g., "Accept", are case insensitive as specified in Section 2.3 of RFC 5234 ๐ค.
The RTSP syntax makes use of the ISO 10646 character set in UTF-8 encoding [RFC3629] ๐โจ.
20.1. Base Syntax
okay so header values can get folded onto multiple lines, bestie ๐, as long as the continuation line starts with a space or a horizontal tab โจ. Any linear whitespace counts, folding included, and it all means the same thing as SP ๐ . A recipient MAY swap any linear whitespace for one single SP before it reads the field-value or passes the message along downstream ๐ฆ. SWS is the construct for when whitespace is optional, usually between tokens and separators ๐ธ.
To split the header name from the rest of the value, we use a colon ๐. By the rule above, you can put whitespace before it (but no line break ๐), and whitespace after it, line break included ๐ซถ. HCOLON is the construct that defines all of this ๐.
OCTET = %x00-FF ; any 8-bit sequence of data
CHAR = %x01-7F ; any US-ASCII character (octets 1 - 127)
UPALPHA = %x41-5A ; any US-ASCII uppercase letter "A".."Z"
LOALPHA = %x61-7A ; any US-ASCII lowercase letter "a".."z"
ALPHA = UPALPHA / LOALPHA
DIGIT = %x30-39 ; any US-ASCII digit "0".."9"
CTL = %x00-1F / %x7F ; any US-ASCII control character
; (octets 0 - 31) and DEL (127)
CR = %x0D ; US-ASCII CR, carriage return (13)
LF = %x0A ; US-ASCII LF, linefeed (10)
SP = %x20 ; US-ASCII SP, space (32)
HT = %x09 ; US-ASCII HT, horizontal-tab (9)
BACKSLASH = %x5C ; US-ASCII backslash (92)
CRLF = CR LF
LWS = [CRLF] 1*( SP / HT ) ; Line-breaking whitespace
SWS = [LWS] ; Separating whitespace
HCOLON = *( SP / HT ) ":" SWS
TEXT = %x20-7E / %x80-FF ; any OCTET except CTLs
tspecials = "(" / ")" / "<" / ">" / "@"
/ "," / ";" / ":" / BACKSLASH / DQUOTE
/ "/" / "[" / "]" / "?" / "="
/ "{" / "}" / SP / HT
token = 1*(%x21 / %x23-27 / %x2A-2B / %x2D-2E / %x30-39
/ %x41-5A / %x5E-7A / %x7C / %x7E)
; 1*<any CHAR except CTLs or tspecials>
quoted-string = ( DQUOTE *qdtext DQUOTE )
qdtext = %x20-21 / %x23-5B / %x5D-7E / quoted-pair
/ UTF8-NONASCII
; No DQUOTE and no "\"
quoted-pair = "\\" / ( "\" DQUOTE )
ctext = %x20-27 / %x2A-7E
/ %x80-FF ; any OCTET except CTLs, "(" and ")"
generic-param = token [ EQUAL gen-value ]
gen-value = token / host / quoted-string
safe = "$" / "-" / "_" / "." / "+"
extra = "!" / "*" / "'" / "(" / ")" / ","
rtsp-extra = "!" / "*" / "'" / "(" / ")"
HEX = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
/ "a" / "b" / "c" / "d" / "e" / "f"
LHEX = DIGIT / "a" / "b" / "c" / "d" / "e" / "f"
; lowercase "a-f" Hex
reserved = ";" / "/" / "?" / ":" / "@" / "&" / "="
unreserved = ALPHA / DIGIT / safe / extra
rtsp-unreserved = ALPHA / DIGIT / safe / rtsp-extra
base64 = *base64-unit [base64-pad]
base64-unit = 4base64-char
base64-pad = (2base64-char "==") / (3base64-char "=")
base64-char = ALPHA / DIGIT / "+" / "/"
SLASH = SWS "/" SWS ; slash
EQUAL = SWS "=" SWS ; equal
LPAREN = SWS "(" SWS ; left parenthesis
RPAREN = SWS ")" SWS ; right parenthesis
COMMA = SWS "," SWS ; comma
SEMI = SWS ";" SWS ; semicolon
COLON = SWS ":" SWS ; colon
MINUS = SWS "-" SWS ; minus/dash
LDQUOT = SWS DQUOTE ; open double quotation mark
RDQUOT = DQUOTE SWS ; close double quotation mark
RAQUOT = ">" SWS ; right angle quote
LAQUOT = SWS "<" ; left angle quote
TEXT-UTF8char = %x21-7E / UTF8-NONASCII
UTF8-NONASCII = UTF8-2 / UTF8-3 / UTF8-4
UTF8-1 = <As defined in RFC 3629>
UTF8-2 = <As defined in RFC 3629>
UTF8-3 = <As defined in RFC 3629>
UTF8-4 = <As defined in RFC 3629>
UTF8-tail = <As defined in RFC 3629>
POS-FLOAT = 1*12DIGIT ["." 1*9DIGIT]
FLOAT = ["-"] POS-FLOAT
20.2. RTSP Protocol Definition
20.2.1. Generic Protocol Elements
Here's the big grammar pile for the generic protocol bits ๐ง๐ Every rule is copied exactly, so nothing gets lost in translation!
RTSP-IRI = schemes ":" IRI-rest
IRI-rest = ihier-part [ "?" iquery ]
ihier-part = "//" iauthority ipath-abempty
RTSP-IRI-ref = RTSP-IRI / irelative-ref
irelative-ref = irelative-part [ "?" iquery ]
irelative-part = "//" iauthority ipath-abempty
/ ipath-absolute
/ ipath-noscheme
/ ipath-empty
iauthority = < As defined in RFC 3987>
ipath = ipath-abempty ; begins with "/" or is empty
/ ipath-absolute ; begins with "/" but not "//"
/ ipath-noscheme ; begins with a non-colon segment
/ ipath-rootless ; begins with a segment
/ ipath-empty ; zero characters
ipath-abempty = *( "/" isegment )
ipath-absolute = "/" [ isegment-nz *( "/" isegment ) ]
ipath-noscheme = isegment-nz-nc *( "/" isegment )
ipath-rootless = isegment-nz *( "/" isegment )
ipath-empty = 0<ipchar>
isegment = *ipchar [";" *ipchar]
isegment-nz = 1*ipchar [";" *ipchar]
/ ";" *ipchar
isegment-nz-nc = (1*ipchar-nc [";" *ipchar-nc])
/ ";" *ipchar-nc
; non-zero-length segment without any colon ":"
; No parameter (; delimited) inside path.
ipchar = iunreserved / pct-encoded / sub-delims / ":" / "@"
ipchar-nc = iunreserved / pct-encoded / sub-delims / "@"
; sub-delims is different from RFC 3987
; not including ";"
iquery = < As defined in RFC 3987>
iunreserved = < As defined in RFC 3987>
pct-encoded = < As defined in RFC 3987>
RTSP-URI = schemes ":" URI-rest
RTSP-REQ-URI = schemes ":" URI-req-rest
RTSP-URI-Ref = RTSP-URI / RTSP-Relative
RTSP-REQ-Ref = RTSP-REQ-URI / RTSP-REQ-Rel
schemes = "rtsp" / "rtsps" / scheme
scheme = < As defined in RFC 3986>
URI-rest = hier-part [ "?" query ]
URI-req-rest = hier-part [ "?" query ]
; Note fragment part not allowed in requests
hier-part = "//" authority path-abempty
RTSP-Relative = relative-part [ "?" query ]
RTSP-REQ-Rel = relative-part [ "?" query ]
relative-part = "//" authority path-abempty
/ path-absolute
/ path-noscheme
/ path-empty
authority = < As defined in RFC 3986>
query = < As defined in RFC 3986>
path = path-abempty ; begins with "/" or is empty
/ path-absolute ; begins with "/" but not "//"
/ path-noscheme ; begins with a non-colon segment
/ path-rootless ; begins with a segment
/ path-empty ; zero characters
path-abempty = *( "/" segment )
path-absolute = "/" [ segment-nz *( "/" segment ) ]
path-noscheme = segment-nz-nc *( "/" segment )
path-rootless = segment-nz *( "/" segment )
path-empty = 0<pchar>
segment = *pchar [";" *pchar]
segment-nz = ( 1*pchar [";" *pchar]) / (";" *pchar)
segment-nz-nc = ( 1*pchar-nc [";" *pchar-nc]) / (";" *pchar-nc)
; non-zero-length segment without any colon ":"
; No parameter (; delimited) inside path.
pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
pchar-nc = unreserved / pct-encoded / sub-delims / "@"
sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
/ "*" / "+" / "," / "="
; sub-delims is different from RFC 3986/3987
; not including ";"
smpte-range = smpte-type [EQUAL smpte-range-spec]
; See section 4.4
smpte-range-spec = ( smpte-time "-" [ smpte-time ] )
/ ( "-" smpte-time )
smpte-type = "smpte" / "smpte-30-drop"
/ "smpte-25" / smpte-type-extension
; other timecodes may be added
smpte-type-extension = "smpte" token
smpte-time = 1*2DIGIT ":" 1*2DIGIT ":" 1*2DIGIT
[ ":" 1*2DIGIT [ "." 1*2DIGIT ] ]
npt-range = "npt" [EQUAL npt-range-spec]
npt-range-spec = ( npt-time "-" [ npt-time ] ) / ( "-" npt-time )
npt-time = "now" / npt-sec / npt-hhmmss / npt-hhmmss-comp
npt-sec = 1*19DIGIT [ "." 1*9DIGIT ]
npt-hhmmss = npt-hh ":" npt-mm ":" npt-ss [ "." 1*9DIGIT ]
npt-hh = 2*19DIGIT ; any positive number
npt-mm = 2*2DIGIT ; 0-59
npt-ss = 2*2DIGIT ; 0-59
npt-hhmmss-comp = npt-hh-comp ":" npt-mm-comp ":" npt-ss-comp
[ "." 1*9DIGIT ] ; Compatibility format
npt-hh-comp = 1*19DIGIT ; any positive number
npt-mm-comp = 1*2DIGIT ; 0-59
npt-ss-comp = 1*2DIGIT ; 0-59
utc-range = "clock" [EQUAL utc-range-spec]
utc-range-spec = ( utc-time "-" [ utc-time ] ) / ( "-" utc-time )
utc-time = utc-date "T" utc-clock "Z"
utc-date = 8DIGIT
utc-clock = 6DIGIT [ "." 1*9DIGIT ]
feature-tag = token
session-id = 1*256( ALPHA / DIGIT / safe )
extension-header = header-name HCOLON header-value
header-name = token
header-value = *(TEXT-UTF8char / LWS)
20.2.2. Message Syntax โจ
okay so this is where the whole message shape comes together ๐ every RTSP/2.0 message is either a request or a response, and the grammar below lays out the parts in order ๐
RTSP-message = Request / Response ; RTSP/2.0 messages
Request = Request-Line
*((general-header
/ request-header
/ message-body-header) CRLF)
CRLF
[ message-body-data ]
Response = Status-Line
*((general-header
/ response-header
/ message-body-header) CRLF)
CRLF
[ message-body-data ]
Request-Line = Method SP Request-URI SP RTSP-Version CRLF
Status-Line = RTSP-Version SP Status-Code SP Reason-Phrase CRLF
Method = "DESCRIBE"
/ "GET_PARAMETER"
/ "OPTIONS"
/ "PAUSE"
/ "PLAY"
/ "PLAY_NOTIFY"
/ "REDIRECT"
/ "SETUP"
/ "SET_PARAMETER"
/ "TEARDOWN"
/ extension-method
extension-method = token
Request-URI = "*" / RTSP-REQ-URI
RTSP-Version = "RTSP/" 1*DIGIT "." 1*DIGIT
message-body-data = 1*OCTET
Status-Code = "100" ; Continue
/ "200" ; OK
/ "301" ; Moved Permanently
/ "302" ; Found
/ "303" ; See Other
/ "304" ; Not Modified
/ "305" ; Use Proxy
/ "400" ; Bad Request
/ "401" ; Unauthorized
/ "402" ; Payment Required
/ "403" ; Forbidden
/ "404" ; Not Found
/ "405" ; Method Not Allowed
/ "406" ; Not Acceptable
/ "407" ; Proxy Authentication Required
/ "408" ; Request Timeout
/ "410" ; Gone
/ "412" ; Precondition Failed
/ "413" ; Request Message Body Too Large
/ "414" ; Request-URI Too Long
/ "415" ; Unsupported Media Type
/ "451" ; Parameter Not Understood
/ "452" ; reserved
/ "453" ; Not Enough Bandwidth
/ "454" ; Session Not Found
/ "455" ; Method Not Valid In This State
/ "456" ; Header Field Not Valid for Resource
/ "457" ; Invalid Range
/ "458" ; Parameter Is Read-Only
/ "459" ; Aggregate Operation Not Allowed
/ "460" ; Only Aggregate Operation Allowed
/ "461" ; Unsupported Transport
/ "462" ; Destination Unreachable
/ "463" ; Destination Prohibited
/ "464" ; Data Transport Not Ready Yet
/ "465" ; Notification Reason Unknown
/ "466" ; Key Management Error
/ "470" ; Connection Authorization Required
/ "471" ; Connection Credentials Not Accepted
/ "472" ; Failure to Establish Secure Connection
/ "500" ; Internal Server Error
/ "501" ; Not Implemented
/ "502" ; Bad Gateway
/ "503" ; Service Unavailable
/ "504" ; Gateway Timeout
/ "505" ; RTSP Version Not Supported
/ "551" ; Option Not Supported
/ "553" ; Proxy Unavailable
/ extension-code
extension-code = 3DIGIT
Reason-Phrase = 1*(TEXT-UTF8char / HT / SP)
rtsp-header = general-header
/ request-header
/ response-header
/ message-body-header
general-header = Accept-Ranges
/ Cache-Control
/ Connection
/ CSeq
/ Date
/ Media-Properties
/ Media-Range
/ Pipelined-Requests
/ Proxy-Supported
/ Range
/ RTP-Info
/ Scale
/ Seek-Style
/ Server
/ Session
/ Speed
/ Supported
/ Timestamp
/ Transport
/ User-Agent
/ Via
/ extension-header
request-header = Accept
/ Accept-Credentials
/ Accept-Encoding
/ Accept-Language
/ Authorization
/ Bandwidth
/ Blocksize
/ From
/ If-Match
/ If-Modified-Since
/ If-None-Match
/ Notify-Reason
/ Proxy-Authorization
/ Proxy-Require
/ Referrer
/ Request-Status
/ Require
/ Terminate-Reason
/ extension-header
response-header = Authentication-Info
/ Connection-Credentials
/ Location
/ MTag
/ Proxy-Authenticate
/ Proxy-Authentication-Info
/ Public
/ Retry-After
/ Unsupported
/ WWW-Authenticate
/ extension-header
message-body-header = Allow
/ Content-Base
/ Content-Encoding
/ Content-Language
/ Content-Length
/ Content-Location
/ Content-Type
/ Expires
/ Last-Modified
/ extension-header
20.2.3. Header Syntax โจ
and now the fun part, the actual shape of every header ๐ฆ these are the building blocks that all the header names above are made from ๐ง
Accept = "Accept" HCOLON
[ accept-range *(COMMA accept-range) ]
accept-range = media-type-range [SEMI accept-params]
media-type-range = ( "*/*"
/ ( m-type SLASH "*" )
/ ( m-type SLASH m-subtype )
) *( SEMI m-parameter )
accept-params = "q" EQUAL qvalue *(SEMI generic-param )
qvalue = ( "0" [ "." *3DIGIT ] )
/ ( "1" [ "." *3("0") ] )
Accept-Credentials = "Accept-Credentials" HCOLON cred-decision
cred-decision = ("User" [LWS cred-info])
/ "Proxy"
/ "Any"
/ (token [LWS 1*header-value])
; For future extensions
cred-info = cred-info-data *(COMMA cred-info-data)
cred-info-data = DQUOTE RTSP-REQ-URI DQUOTE SEMI hash-alg
SEMI base64
hash-alg = "sha-256" / extension-alg
extension-alg = token
Accept-Encoding = "Accept-Encoding" HCOLON
[ encoding *(COMMA encoding) ]
encoding = codings [SEMI accept-params]
codings = content-coding / "*"
content-coding = "identity" / token
Accept-Language = "Accept-Language" HCOLON
language *(COMMA language)
language = language-range [SEMI accept-params]
language-range = language-tag / "*"
language-tag = primary-tag *( "-" subtag )
primary-tag = 1*8ALPHA
subtag = 1*8ALPHA
Accept-Ranges = "Accept-Ranges" HCOLON acceptable-ranges
acceptable-ranges = (range-unit *(COMMA range-unit))
range-unit = "npt" / "smpte" / "smpte-30-drop" / "smpte-25"
/ "clock" / extension-format
extension-format = token
Allow = "Allow" HCOLON Method *(COMMA Method)
Authentication-Info = "Authentication-Info" HCOLON auth-param-list
auth-param-list = <As the Authentication-Info element in RFC 7615>
Authorization = "Authorization" HCOLON credentials
credentials = <As defined by RFC 7235>
Bandwidth = "Bandwidth" HCOLON 1*19DIGIT
Blocksize = "Blocksize" HCOLON 1*9DIGIT
Cache-Control = "Cache-Control" HCOLON cache-directive
*(COMMA cache-directive)
cache-directive = cache-rqst-directive
/ cache-rspns-directive
cache-rqst-directive = "no-cache"
/ "max-stale" [EQUAL delta-seconds]
/ "min-fresh" EQUAL delta-seconds
/ "only-if-cached"
/ cache-extension
cache-rspns-directive = "public"
/ "private"
/ "no-cache"
/ "no-transform"
/ "must-revalidate"
/ "proxy-revalidate"
/ "max-age" EQUAL delta-seconds
/ cache-extension
cache-extension = token [EQUAL (token / quoted-string)]
delta-seconds = 1*19DIGIT
Connection = "Connection" HCOLON connection-token
*(COMMA connection-token)
connection-token = "close" / token
Connection-Credentials = "Connection-Credentials" HCOLON cred-chain
cred-chain = DQUOTE RTSP-REQ-URI DQUOTE SEMI base64
Content-Base = "Content-Base" HCOLON RTSP-URI
Content-Encoding = "Content-Encoding" HCOLON
content-coding *(COMMA content-coding)
Content-Language = "Content-Language" HCOLON
language-tag *(COMMA language-tag)
Content-Length = "Content-Length" HCOLON 1*19DIGIT
Content-Location = "Content-Location" HCOLON RTSP-REQ-Ref
Content-Type = "Content-Type" HCOLON media-type
media-type = m-type SLASH m-subtype *(SEMI m-parameter)
m-type = discrete-type / composite-type
discrete-type = "text" / "image" / "audio" / "video"
/ "application" / extension-token
composite-type = "message" / "multipart" / extension-token
extension-token = ietf-token / x-token
ietf-token = token
x-token = "x-" token
m-subtype = extension-token / iana-token
iana-token = token
m-parameter = m-attribute EQUAL m-value
m-attribute = token
m-value = token / quoted-string
CSeq = "CSeq" HCOLON cseq-nr
cseq-nr = 1*9DIGIT
Date = "Date" HCOLON RTSP-date
RTSP-date = date-time ;
date-time = <As defined in RFC 5322>
Expires = "Expires" HCOLON RTSP-date
From = "From" HCOLON from-spec
from-spec = ( name-addr / addr-spec ) *( SEMI from-param )
name-addr = [ display-name ] LAQUOT addr-spec RAQUOT
addr-spec = RTSP-REQ-URI / absolute-URI
absolute-URI = < As defined in RFC 3986>
display-name = *(token LWS) / quoted-string
from-param = tag-param / generic-param
tag-param = "tag" EQUAL token
If-Match = "If-Match" HCOLON ("*" / message-tag-list)
message-tag-list = message-tag *(COMMA message-tag)
message-tag = [ weak ] opaque-tag
weak = "W/"
opaque-tag = quoted-string
If-Modified-Since = "If-Modified-Since" HCOLON RTSP-date
If-None-Match = "If-None-Match" HCOLON ("*" / message-tag-list)
Last-Modified = "Last-Modified" HCOLON RTSP-date
Location = "Location" HCOLON RTSP-REQ-URI
Media-Properties = "Media-Properties" HCOLON [media-prop-list]
media-prop-list = media-prop-value *(COMMA media-prop-value)
media-prop-value = ("Random-Access" [EQUAL POS-FLOAT])
/ "Beginning-Only"
/ "No-Seeking"
/ "Immutable"
/ "Dynamic"
/ "Time-Progressing"
/ "Unlimited"
/ ("Time-Limited" EQUAL utc-time)
/ ("Time-Duration" EQUAL POS-FLOAT)
/ ("Scales" EQUAL scale-value-list)
/ media-prop-ext
media-prop-ext = token [EQUAL (1*rtsp-unreserved / quoted-string)]
scale-value-list = DQUOTE scale-entry *(COMMA scale-entry) DQUOTE
scale-entry = scale-value / (scale-value COLON scale-value)
scale-value = FLOAT
Media-Range = "Media-Range" HCOLON [ranges-list]
ranges-list = ranges-spec *(COMMA ranges-spec)
MTag = "MTag" HCOLON message-tag
Notify-Reason = "Notify-Reason" HCOLON Notify-Reas-val
Notify-Reas-val = "end-of-stream"
/ "media-properties-update"
/ "scale-change"
/ Notify-Reason-extension
Notify-Reason-extension = token
Pipelined-Requests = "Pipelined-Requests" HCOLON startup-id
startup-id = 1*8DIGIT
Proxy-Authenticate = "Proxy-Authenticate" HCOLON challenge-list
challenge-list = <As defined by the WWW-Authenticate in RFC 7235>
Proxy-Authentication-Info = "Proxy-Authentication-Info" HCOLON
auth-param-list
Proxy-Authorization = "Proxy-Authorization" HCOLON credentials
Proxy-Require = "Proxy-Require" HCOLON feature-tag-list
feature-tag-list = feature-tag *(COMMA feature-tag)
Proxy-Supported = "Proxy-Supported" HCOLON [feature-tag-list]
Public = "Public" HCOLON Method *(COMMA Method)
Range = "Range" HCOLON ranges-spec
ranges-spec = npt-range / utc-range / smpte-range
/ range-ext
range-ext = extension-format [EQUAL range-value]
range-value = 1*(rtsp-unreserved / quoted-string / ":" )
Referrer = "Referrer" HCOLON (absolute-URI / RTSP-URI-Ref)
Request-Status = "Request-Status" HCOLON req-status-info
req-status-info = cseq-info LWS status-info LWS reason-info
cseq-info = "cseq" EQUAL cseq-nr
status-info = "status" EQUAL Status-Code
reason-info = "reason" EQUAL DQUOTE Reason-Phrase DQUOTE
Require = "Require" HCOLON feature-tag-list
RTP-Info = "RTP-Info" HCOLON [rtsp-info-spec
*(COMMA rtsp-info-spec)]
rtsp-info-spec = stream-url 1*ssrc-parameter
stream-url = "url" EQUAL DQUOTE RTSP-REQ-Ref DQUOTE
ssrc-parameter = LWS "ssrc" EQUAL ssrc HCOLON
ri-parameter *(SEMI ri-parameter)
ri-parameter = ("seq" EQUAL 1*5DIGIT)
/ ("rtptime" EQUAL 1*10DIGIT)
/ generic-param
Retry-After = "Retry-After" HCOLON (RTSP-date / delta-seconds)
Scale = "Scale" HCOLON scale-value
Seek-Style = "Seek-Style" HCOLON Seek-S-values
Seek-S-values = "RAP"
/ "CoRAP"
/ "First-Prior"
/ "Next"
/ Seek-S-value-ext
Seek-S-value-ext = token
Server = "Server" HCOLON ( product / comment )
*(LWS (product / comment))
product = token [SLASH product-version]
product-version = token
comment = LPAREN *( ctext / quoted-pair) RPAREN
Session = "Session" HCOLON session-id
[ SEMI "timeout" EQUAL delta-seconds ]
Speed = "Speed" HCOLON lower-bound MINUS upper-bound
lower-bound = POS-FLOAT
upper-bound = POS-FLOAT
Supported = "Supported" HCOLON [feature-tag-list]
Terminate-Reason = "Terminate-Reason" HCOLON TR-Info
TR-Info = TR-Reason *(SEMI TR-Parameter)
TR-Reason = "Session-Timeout"
/ "Server-Admin"
/ "Internal-Error"
/ token
TR-Parameter = TR-time / TR-user-msg / generic-param
TR-time = "time" EQUAL utc-time
TR-user-msg = "user-msg" EQUAL quoted-string
Timestamp = "Timestamp" HCOLON timestamp-value [LWS delay]
timestamp-value = *19DIGIT [ "." *9DIGIT ]
delay = *9DIGIT [ "." *9DIGIT ]
Transport = "Transport" HCOLON transport-spec
*(COMMA transport-spec)
transport-spec = transport-id *trns-parameter
transport-id = trans-id-rtp / other-trans
trans-id-rtp = "RTP/" profile ["/" lower-transport]
; no LWS is allowed inside transport-id
other-trans = token *("/" token)
profile = "AVP" / "SAVP" / "AVPF" / "SAVPF" / token
lower-transport = "TCP" / "UDP" / token
trns-parameter = (SEMI ( "unicast" / "multicast" ))
/ (SEMI "interleaved" EQUAL channel ["-" channel])
/ (SEMI "ttl" EQUAL ttl)
/ (SEMI "layers" EQUAL 1*DIGIT)
/ (SEMI "ssrc" EQUAL ssrc *(SLASH ssrc))
/ (SEMI "mode" EQUAL mode-spec)
/ (SEMI "dest_addr" EQUAL addr-list)
/ (SEMI "src_addr" EQUAL addr-list)
/ (SEMI "setup" EQUAL contrans-setup)
/ (SEMI "connection" EQUAL contrans-con)
/ (SEMI "RTCP-mux")
/ (SEMI "MIKEY" EQUAL MIKEY-Value)
/ (SEMI trn-param-ext)
contrans-setup = "active" / "passive" / "actpass"
contrans-con = "new" / "existing"
trn-param-ext = par-name [EQUAL trn-par-value]
par-name = token
trn-par-value = *(rtsp-unreserved / quoted-string)
ttl = 1*3DIGIT ; 0 to 255
ssrc = 8HEX
channel = 1*3DIGIT ; 0 to 255
MIKEY-Value = base64
mode-spec = ( DQUOTE mode *(COMMA mode) DQUOTE )
mode = "PLAY" / token
addr-list = quoted-addr *(SLASH quoted-addr)
quoted-addr = DQUOTE (host-port / extension-addr) DQUOTE
host-port = ( host [":" port] )
/ ( ":" port )
extension-addr = 1*qdtext
host = < As defined in RFC 3986>
port = < As defined in RFC 3986>
Unsupported = "Unsupported" HCOLON feature-tag-list
User-Agent = "User-Agent" HCOLON ( product / comment )
*(LWS (product / comment))
Via = "Via" HCOLON via-parm *(COMMA via-parm)
via-parm = sent-protocol LWS sent-by *( SEMI via-params )
via-params = via-ttl / via-maddr
/ via-received / via-extension
via-ttl = "ttl" EQUAL ttl
via-maddr = "maddr" EQUAL host
via-received = "received" EQUAL (IPv4address / IPv6address)
IPv4address = < As defined in RFC 3986>
IPv6address = < As defined in RFC 3986>
via-extension = generic-param
sent-protocol = protocol-name SLASH protocol-version
SLASH transport-prot
protocol-name = "RTSP" / token
protocol-version = token
transport-prot = "UDP" / "TCP" / "TLS" / other-transport
other-transport = token
sent-by = host [ COLON port ]
WWW-Authenticate = "WWW-Authenticate" HCOLON challenge-list
20.3. SDP Extension Syntax โจ
Okay, bestie, time for the SDP extras ๐ This bit lays out, in ABNF, the SDP extensions that RTSP defines. If you want those extensions explained in plain text instead, jump to Appendix D ๐
control-attribute = "a=control:" *SP RTSP-REQ-Ref CRLF
a-range-def = "a=range:" ranges-spec CRLF
a-mtag-def = "a=mtag:" message-tag CRLF
21. Security Considerations ๐๐
Okay, this section is serious, so grab a snack and pay attention ๐
Security stuff around RTSP splits into two buckets: the signaling protocol itself, and the problems that come with delivering the media stream. Here's the twist, though ๐ a threat that lives in media delivery can sometimes be handled by a mechanism in the signaling protocol. So the buckets overlap more than you'd think โจ
The document has several chapters and an appendix that define security solutions for the protocol. When we talk about threats below, we'll point back to those sections. But the reader should take special notice of the Security Framework (Section 19), and of how to use SRTP and its key management (Appendix C.1.4) to get certain aspects of media security. Don't skip these, bestie ๐๐ซถ
21.1. Signaling Protocol Threats ๐ฆ
okay bestie, this section is all about the signaling protocol (aka the RTSP messages themselves) ๐. RTSP servers and HTTP servers are sooo similar in syntax and usage, so the security considerations in [RFC7230], [RFC7231], [RFC7232], [RFC7233], [RFC7234], and [RFC7235] apply here too ๐ . Here's what to watch out for:
Abuse of Server Log Information: A server is in the position to save personal data about a user's requests, and that could reveal their media consumption patterns or subjects of interest ๐. This info is clearly confidential, and some countries have laws about how it gets handled. Log info needs to be stored securely, and appropriate guidelines need to be followed when analyzing it. See Section 9.8 of [RFC7230] for additional guidelines ๐.
Transfer of Sensitive Information: there's no reason to think that info sent in RTSP messages, like the URI and the content of headers (especially the Server, Via, Referrer, and From headers), is any less sensitive than when it's used in HTTP ๐ญ. So all the precautions for protecting data privacy and user privacy apply to implementers of RTSP clients, servers, and proxies ๐. See Sections 9.3-9.6 of [RFC7231] for the full details.
The RTSP methods defined in this document are mainly used to set up and control the delivery of the media data represented by the URI, so RTSP message bodies are generally less sensitive than the ones in HTTP ๐ธ. Where HTTP bodies could hold stuff like your medical records, in RTSP the sensitive video of your medical operation would be in the media stream over the media-transport protocol, not in the RTSP message ๐ฅ. Still, you have to keep an eye on what potentially sensitive info is included in RTSP ๐. The protection of the media data is separate, can be applied directly between client and server, and depends on the media-transport protocol in use. See Section 21.2 for further discussion. This split between the security of the media-resource content and the signaling protocol is a big deal, because it lowers the risk of exposing the media content when you use hop-by-hop security for RTSP signaling with proxies (Section 19.3) ๐ง.
Attacks Based On File and Path Names: RTSP URIs are opaque handles that don't necessarily have file-system semantics, but it's expected that lots of implementations will translate parts of the Request-URIs directly into file-system calls ๐. In those cases, file systems SHOULD follow the precautions outlined in Section 9.1 of [RFC7231], like checking for .. in path components ๐.
Personal Information: RTSP clients are often privy to the same info that HTTP clients are (username, location, etc.), so they should be just as sensitive about it ๐ซถ. See Section 9.8 of [RFC7230], Sections 9.3-9.7 of [RFC7231], and Section 8 of [RFC7234] for more recommendations ๐.
Privacy Issues Connected to Accept Headers: since RTSP has similar usages of the "Accept" headers as HTTP, the same caveats from Section 9.4 of [RFC7231] about how to use them should be followed ๐.
Establishing Authority: RTSP shares with HTTP the question of how a client talks to the authoritative source for media streams (Section 9.1 of [RFC7230]) ๐. The DNS servers being used, how secure the communication is, any chance of a man in the middle, and how much you trust any RTSP proxies all affect whether a client has gotten a non-authoritative response to a request ๐ฌ. Making sure a client gets an authoritative response is challenging, but using secure communication for RTSP signaling (rtsps) makes it way easier, since the server can provide a hostname identity assertion in the TLS handshake โจ.
Location Headers and Spoofing: if a single server supports multiple organizations that don't trust each other, then it MUST check the values of the Content-Location header fields in responses generated under control of those organizations ๐จ. It needs to make sure they don't try to invalidate resources they have no authority over (see Section 15.4 of [RFC2616]) ๐
โโ๏ธ.
In addition to the recommendations in the current HTTP specifications ([RFC7230], [RFC7231], [RFC7232], [RFC7233], [RFC7234], and [RFC7235] as of this writing) and the ones from the previous relevant RFCs [RFC2068] [RFC2616], future HTTP specifications may give additional guidance on security issues ๐ฎ.
The following are added considerations for RTSP implementations ๐.
Session Hijacking: since there is no or little relation between a transport-layer connection and an RTSP session, a malicious client could issue requests with random session identifiers that affect other clients of an unsuspecting server ๐. To mitigate this, the server SHALL use a large, random, and non-sequential session identifier to minimize the chance of this kind of attack ๐ฒ. However, unless RTSP signaling is always confidentiality protected (e.g., using TLS), an on-path attacker will be able to hijack a session ๐. Another option for preventing session hijacking is to use client authentication and only allow the authenticated client that created the session to access that session ๐.
Authentication: servers SHOULD implement both basic and Digest [RFC2617] authentication ๐. In environments that need tighter security for control messages, the transport-layer mechanism TLS [RFC5246] SHOULD be used ๐ก๏ธ.
Suspicious Behavior: when servers spot behavior that's a security risk, RTSP servers SHOULD return error code 403 (Forbidden) ๐ซ. RTSP servers SHOULD also be aware of attempts to probe the server for weaknesses and entry points, and they MAY arbitrarily disconnect and ignore further requests from clients that are deemed to be violating local security policy ๐.
TLS through Proxies: if you use the option to connect TLS in multiple legs (Section 19.3), you really need to be aware of the trust model ๐ง. This procedure requires trust in all proxies that are part of the path to the server ๐ค. The proxies you connect through are identified, assuming the proxies connected through so far are well behaved and holding up their end of the trust ๐. The accepted proxies are men in the middle and have access to everything that goes on over the TLS connection ๐ฑ. So it's important to figure out whether that trust model is acceptable for your actual application โญ. Further discussion of the actual trust model is in Section 19.3. It's also important to note what difference in security properties, if any, may exist with the media-transport protocol and its security mechanism ๐ถ. Using SRTP and the MIKEY-based key establishment defined in Appendix C.1.4.1 lets media key establishment happen end-to-end without revealing the keys to the proxies ๐๏ธ.
Resource Exhaustion: RTSP is a stateful protocol and it sets up resource usage on the server, so there's a clear possibility of attacking the server by trying to overbook those resources for a DoS attack ๐. This can target ongoing sessions, and it can also stop others from setting up sessions ๐ . RTSP agents will need mechanisms to stop single peers from eating up huge amounts of resources ๐ฝ๏ธ. The ways of guarding against this vary and depend on the agent's role, capabilities, and policies ๐งฉ. Each implementation has to think carefully about its methods and policies to mitigate this threat ๐ง . There are recommendations about handling connections in Section 10.7 ๐.
The threats and considerations above have led to a set of security functions and mechanisms that are built into or used by the protocol ๐. The signaling protocol relies on two security features defined in the Security Framework (Section 19): client authentication using HTTP authentication, and TLS-based transport protection of the signaling messages ๐ซง. Both of these mechanisms are required to be implemented by any RTSP agent ๐.
A bunch of different security mitigations have been designed into the protocol, and they'll be put in place if the specification is implemented as written ๐ ๏ธ. For example, you get sufficient entropy in the randomly generated session identifiers when client authentication isn't used, which lowers the risk of session hijacking ๐ฒ. When client authentication is used, protection against hijacking gets a lot better by scoping the accessible sessions to the ones that client identity created ๐. Some of the threats above need the RTSP implementation itself to decide which policy and strategy it uses to mitigate them ๐ฆ.
21.2. Media Stream Delivery Threats โจ
okay so, RTSP is the one setting up and running the media delivery ๐ฌ, which means the media streams come with their own pile of security issues ๐ญ. This section tries to map out the general threats, but ngl the media transport you pick (like RTP) changes which threats show up and which tools you have to stop them ๐ซถ. So every new media-stream transport and delivery protocol that works with RTSP needs its own security analysis, and this section includes one for RTP ๐ฆ.
The general threats coming from or through the media-stream delivery itself are:
- Concentrated Denial-of-Service Attack: the protocol gives an attacker a remote-controlled DoS option, and the media stream is the hammer ๐จ. See Section 21.2.1.
- Media Confidentiality: the media can be any type of content, and in general you can't tell how sensitive it is from a confidentiality point of view ๐. That makes it a big deal that any media delivery protocol gives a way to keep the actual media content private. On top of that, resource identifiers used in the signaling shouldn't be exposed to an attacker, since they might have names people can actually read or be visible to the attacker, which would let them figure out what content the user got ๐. So the signaling protocol must also provide confidentiality protection for any info about the media resource.
- Media Integrity and Authentication: there are plenty of reasons an attacker would want to swap the media stream coming out of the RTSP server for one they made or picked, like discrediting the target or spreading misinformation about them ๐ โโ๏ธ. So it's important that the media protocol has ways to verify the source's authentication and integrity, and to stop replay attacks on the media stream ๐ก๏ธ.
- Scope of Multicast: if RTSP is used to control sending media onto a multicast network, the scope of the delivery must be considered ๐ก. RTSP supports the
TTLTransport header parameter to set this scope for IPv4. IPv6 uses a different mechanism for the scope boundary. Scope control has its own risks though, because it can be set too large and push media past where it was meant to go ๐ฌ.
Below (Section 21.2.2) there's a protocol-specific analysis of security considerations for RTP-based media transport. That section makes clear what RTSP agents supporting media delivery over RTP have to do to implement security functions ๐.
21.2.1. Remote DoS Attack
the attacker can start traffic flows to one or more IP addresses just by naming them as the destination in SETUP requests ๐. Even if the attacker's IP is known, that doesn't always help you stop more attacks or figure out who they are, so it's not a silver bullet ๐คทโโ๏ธ. So an RTSP server MUST only allow client-specified destinations for RTSP-initiated traffic flows if the server has made sure the specified destination address accepts receiving media through different security mechanisms. The ones that count, from least to most general, are:
- Verification of the client's identity against a database of known users using RTSP authentication mechanisms (preferably Digest authentication or stronger)
- A list of addresses that have consented to be media destinations, especially considering user identity
- Verification based on media path
The server SHOULD NOT allow the destination field to be set unless there's a mechanism in the system to authorize the request originator to direct streams to the recipient ๐ฆ. It's preferred that the media recipient (the destination) does this authorization itself and passes the credentials along to the server ๐. But sometimes that just isn't possible, like when the recipient address is a multicast group or when the recipient can't talk to the server out-of-band. In those cases, the server may choose another method, such as a server-resident authorization list, to make sure the request originator really has the right credentials to request stream delivery to the recipient ๐งพ.
One solution that does the verification needed to accept media for unicast-based delivery is the NAT traversal method based on Interactive Connectivity Establishment (ICE) [RFC5245], described in [RFC7825] ๐. It uses random passwords and a username, so the chance of something accidentally showing up as a valid media destination is very low ๐ฒ. The server also puts a cookie (made of random material) in its Session Traversal Utilities for NAT (STUN) [RFC5389] requests, and the destination echoes it back. So this solution also protects against an off-path attacker spoofing the STUN checks ๐ก๏ธ. The only thing left is on-path attackers who can see the STUN requests going to the target and forge a response, which is the one gap here ๐.
For delivery to multicast addresses, there's a need for another solution, and it's not specified in this memo ๐ธ.
21.2.2. RTP Security Analysis
RTP is a commonly used media-transport protocol and has been the most popular choice for RTSP 1.0 implementations ๐. The core RTP protocol has been around for ages, so it has well-known security properties, and the RTP security considerations (Section 9 of [RFC3550]) needs to be reviewed ๐. Looking at how RTP gets used with RTSP, these properties should be noted:
- Stream Additions: RTP supports multiple simultaneous media streams in each RTP session. Some use cases need non-synchronized adding and removal of media streams and their identifiers, so an attacker can easily insert extra media streams into a session that's supposed to be played out as designed ๐ค. Another threat is DoS by exhausting the resources of the RTP session receiver, for example by using a huge number of SSRC identifiers at once ๐. The strong fix is to cryptographically authenticate any incoming packet flow to the RTP session ๐. Weak fixes, like blocking additional media streams in session contexts, easily lead to a DoS vulnerability too. They also stop certain RTP extensions or use cases that rely on multiple media streams from working, such as RTP retransmission [RFC4588] ๐ โโ๏ธ.
- Forged Feedback: the built-in RTCP also has a big attack surface with a couple of different attack types ๐ฏ. One is sending RTCP feedback to the media sender that claims large amounts of packet loss, which triggers a media bitrate adaptation response from the sender. That can lower the media quality and possibly shut the stream down ๐. Another is a resource-exhaustion attack on the receiver, using many SSRC identifiers to build large state tables and push up the RTCP processing demands ๐.
- RTP/RTCP Extensions: RTP and RTCP extensions often bring extra-powerful tools, and those can be used for DoS attacks or service disruption โก. For example, the Code Control Message [RFC5104] RTCP extensions can lock the bitrate down to low values, or wreck the video quality by requesting intra-frames ๐บ.
Taking the general discussion in Section 21.2 and the RTP-specific discussion in this section together, it's clear that a strong security mechanism has to be supported to protect RTP ๐ฅ. So this specification has the following requirements on RTP security functions for all RTSP agents that handle media streams and complete media-stream transport using RTP ๐.
RTSP agents supporting RTP MUST implement Secure RTP (SRTP) [RFC3711] and, thus, SAVP. In addition, SAVPF [RFC5124] MUST also be supported if AVPF is implemented ๐ง. This specification requires no extra cryptographic transforms or configuration values beyond the ones marked mandatory to implement in RFC 3711, i.e., AES-CM and HMAC-SHA1 ๐. The default key-management mechanism that MUST be implemented is the one defined in MIKEY Key Establishment (Appendix C.1.4.1) ๐๏ธ. The MIKEY implementation MUST implement the functions needed for MIKEY-RSA-R mode [RFC4738], plus the SRTP parameter negotiation needed to negotiate the supported SRTP transforms and parameters โจ.
22. IANA Considerations ๐
This section describes a bunch of registries for RTSP 2.0 that IANA has set up and maintains ๐๏ธ. These registries are separate from any registries that already exist for RTSP 1.0. Each registry gets a description of the required content, the registration procedures, and the entries this document registers. For more on extending RTSP, see Section 2.7. This document also registers three SDP attributes ๐.
Registries, or entries in registries, made for RTSP 1.0 do not move over to RTSP 2.0. The RTSP 1.0 and RTSP 2.0 registries and entries are independent of each other ๐ โโ๏ธ. If any registry or entry in a registry is also needed in RTSP 2.0, it MUST follow the procedure defined below to allocate the registry or entry ๐.
The sections about registering an item use some of the registration policies from [RFC5226], namely "First Come First Served", "Expert Review", "Specification Required", and "Standards Action" ๐ง.
If a registry needs a contact person, the authors (with Magnus Westerlund <magnus.westerlund@ericsson.com> as primary) are the contact persons for any entries created by this document ๐.
IANA will ask for the following info on any registration request:
- A name of the item to register, following the rules of the intended registry
- Who has change control over the feature (for example, the IETF, ISO, ITU-T, other international standardization bodies, a consortium, a particular company or group of companies, or an individual)
- A reference to a further description, if there is one, for example (in decreasing order of preference), an RFC, a published standard, a published paper, a patent filing, a technical report, documented source code, or a computer manual ๐
- For proprietary features, contact information (postal and email address) ๐ฎ
22.1. Feature Tags ๐ท๏ธ
22.1.1. Description
When a client and server are trying to figure out which parts and functionality of the RTSP specification (and any future extensions) their counterpart implements, they need a namespace ๐งญ. This registry holds named entries that represent certain functionality ๐ .
The usage of feature tags is explained in Section 11 and Section 13.1 ๐ซถ.
22.1.2. Registering New Feature Tags with IANA ๐
okay so feature tags get handed out on a First Come, First Served [RFC5226] basis, bestie. whoever shows up first gets the spot ๐
The registry entry for a feature tag has the following info:
- The name of the feature tag
- If the registrant says the feature is proprietary, IANA should request a vendor "prefix" portion of the name. The name will then be the vendor prefix, followed by a "." and then the rest of the feature name they gave.
- If the feature is not proprietary, then IANA need not collect a prefix for the name.
- A one-paragraph description of what the feature tag represents
- The applicability (server, client, proxy, or some combination)
- A reference to a specification, if applicable
Feature tag names (including the vendor prefix) may contain any non-space and non-control characters. There is no length limit on feature tags. no cap, that's so freeing ๐ฆ
Examples for a vendor tag describing a proprietary feature look like this:
vendorA.specfeat01
vendorA.specfeat02
22.1.3. Registered Entries ๐ธ
the following feature tags are defined in this specification and officially registered here. the change control belongs to the IETF, so they're the ones in charge of it ๐
play.basic: The implementation for delivery and playback operations according to the core RTSP specification, as defined in this memo. Applies for clients, servers, and proxies. See Section 11.1.play.scale: Support of scale operations for media playback. Applies only for servers. See Section 18.46.play.speed: Support of the speed functionality for media delivery. Applies only for servers. See Section 18.50.setup.rtp.rtcp.mux: Support of the RTP and RTCP multiplexing as discussed in Appendix C.1.6.4. Applies for both client and servers and any media caching proxy.
The IANA registry is a table with the name, description, and reference for each feature tag. โจ
22.2. RTSP Methods
22.2.1. Description ๐
Methods are described in Section 13. Extending the protocol with new methods unlocks totally new functionality, which is honestly iconic ๐ง
22.2.2. Registering New Methods with IANA
a new method gets registered through a Standards Action [RFC5226], because new methods can radically change the protocol's behavior and purpose. that's a big deal, so it gets a big process ๐ญ
A specification for a new RTSP method has to cover the following items:
- A method name that follows the ABNF rules for methods.
- A clear specification of what a request using the method does and what responses are expected. Note the directions the method is used in:
C->S,S->C, or both. Also explain how the use of headers, if any, modifies the behavior and effect of the method. - A list or table specifying which of the IANA-registered headers are allowed to be used with the method in the request or/and response. The list or table SHOULD follow the format of tables in Section 18.
- Describe how the method relates to network proxies.
22.2.3. Registered Entries ๐
This specification, RFC 7826, registers 10 methods: DESCRIBE, GET_PARAMETER, OPTIONS, PAUSE, PLAY, PLAY_NOTIFY, REDIRECT, SETUP, SET_PARAMETER, and TEARDOWN. The initial table of the registry is below. โจ
Method Directionality Reference
-----------------------------------------------------
DESCRIBE C->S RFC 7826
GET_PARAMETER C->S, S->C RFC 7826
OPTIONS C->S, S->C RFC 7826
PAUSE C->S RFC 7826
PLAY C->S RFC 7826
PLAY_NOTIFY S->C RFC 7826
REDIRECT S->C RFC 7826
SETUP C->S RFC 7826
SET_PARAMETER C->S, S->C RFC 7826
TEARDOWN C->S, S->C RFC 7826
22.3. RTSP Status Codes ๐
22.3.1. Description
a status code is the three-digit number used to convey information in RTSP response messages (see Section 8). the number space is limited, so care should be taken not to fill it up. literally just don't waste the good numbers ๐
22.3.2. Registering New Status Codes with IANA
a new status code registration follows the policy of IETF Review [RFC5226]. new RTSP functionality that needs Status Codes should first be registered in the range of x50-x99. only when that range is full should registrations be made in the x00-x49 range, unless the code is to adopt an HTTP extension to RTSP. this way any HTTP extension can be adopted to RTSP without renumbering any related status codes, which is so smart ๐ง
A specification for a new status code must include the following:
- The registered number.
- A description of what the status code means and the expected behavior of the sender and receiver of the code.
22.3.3. Registered Entries ๐
RFC 7826 (this document) registers the numbered status code defined in the ABNF entry Status-Code, except extension-code (which defines the syntax allowed for future extensions), in Section 20.2.2.
22.4. RTSP Headers ๐ฆ
22.4.1. Description
by specifying new headers, one or more methods can be enhanced in lots of different ways. an unknown header will be ignored by the receiving agent. if a new header is vital for certain functionality, a feature tag for that functionality can be created, and the counterpart can be required to use it by including a Require header that carries the feature tag. it's giving organized ๐
22.4.2. Registering New Headers with IANA
registrations can be made following the Expert Review policy [RFC5226]. a specification is recommended, preferably an RFC or other specification from a Standards Developing Organization. the minimal information in a registration request is the header name and the contact information. ๐
The expert reviewer verifies that the registration request contains the following information:
- The name of the header.
- An ABNF specification of the header syntax.
- A list or table specifying when the header may be used, covering all methods, their request or response, and the direction (
C->SorS->C). - How the header is to be handled by proxies.
- A description of the purpose of the header.
22.4.3. Registered Entries ๐
All headers specified in Section 18 in RFC 7826 have been registered. The registry includes the header name and reference.
Furthermore, the following legacy RTSP headers defined in other specifications are registered with their header name and reference, according to the list below. heads up though: these references may not fulfill all of the above rules for registrations, because they're legacy ๐ฐ๏ธ
x-wap-profiledefined in [TS-26234]. Thex-wap-profilerequest-header contains one or more absolute URLs to the requesting agent's device-capability profile.x-wap-profile-diffdefined in [TS-26234]. Thex-wap-profile-diffrequest-header contains a subset of a device-capability profile.x-wap-profile-warningdefined in [TS-26234]. Thex-wap-profile-warningis a response-header that contains error codes explaining to what extent the server has been able to match the terminal request in regard to device-capability profiles, as described usingx-wap-profileandx-wap-profile-diffheaders.x-predecbufsizedefined in [TS-26234]. This response-header provides an RTSP agent with the TS 26.234 Annex G hypothetical pre-decoder buffer size.x-initpredecbufperioddefined in [TS-26234]. This response-header provides an RTSP agent with the TS 26.234 Annex G hypothetical pre-decoder buffering period.x-initpostdecbufperioddefined in [TS-26234]. This response-header provides an RTSP agent with the TS 26.234 Annex G post-decoder buffering period.3gpp-videopostdecbufsizedefined in [TS-26234]. This response-header provides an RTSP agent with the TS 26.234 defined post-decoder buffer size usable for H.264 (AVC) video streams.3GPP-Link-Chardefined in [TS-26234]. This request-header provides the RTSP server with the RTSP client's link characteristics as determined from the radio interface. The information that can be provided is guaranteed bitrate, maximum bitrate, and maximum transfer delay.3GPP-Adaptationdefined in [TS-26234]. This general-header is part of the bitrate adaptation solution specified for the Packet-switched Streaming Service (PSS). It provides the RTSP client's buffer sizes and target buffer levels to the server, and responses are used to acknowledge the support and values.3GPP-QoE-Metricsdefined in [TS-26234]. This general-header is used by PSS RTSP agents to negotiate the quality of experience metrics that a client should gather and report to the server.3GPP-QoE-Feedbackdefined in [TS-26234]. This request-header is used by RTSP clients supporting PSS to report the actual values of the metrics gathered in their quality of experience metering.
The use of "x-" is NOT RECOMMENDED, but the headers above were defined before that clarification was made. ๐
22.5. Accept-Credentials ๐ฅ
The security framework's TLS connection mechanism has two registerable entities. two whole things, bestie ๐
22.5.1. Accept-Credentials Policies
This registry is for policies covering an RTSP proxy's handling and verification of TLS certificates when it establishes an outbound TLS connection on behalf of a client. Section 19.3.1 specifies three policies for how to handle certificates. Further policies may be defined, and registration is made through Standards Action [RFC5226]. A registration request is required to contain the following information:
- Name of the policy.
- Text that describes how the policy works for handling the certificates.
- A contact person.
This specification registers the following values:
- Any: A policy requiring the proxy to accept any received certificate.
- Proxy: A policy where the proxy applies its own policies to determine which certificates are accepted.
- User: A policy where the certificate is required to be forwarded down the proxy chain to the client, thus allowing the user to decide to accept or refuse a certificate. ๐
22.5.2. Accept-Credentials Hash Algorithms
The Accept-Credentials header (see Section 18.2) allows for the use of other algorithms for hashing the DER records of accepted entities. registering a future algorithm is expected to be extremely rare, and it could also cause interoperability problems. so the bar for registering new algorithms is intentionally set high ๐ง
Any registration of a new hash algorithm requires Standards Action [RFC5226]. the registration needs to fulfill the following requirements:
- The algorithm's identifier meets the
tokenABNF requirement. - Provide a definition of the algorithm.
The registered value is:
Hash Alg. ID Reference
------------------------
sha-256 RFC 7826
22.6. Cache-Control Cache Directive Extensions โจ
okay so there's a whole bunch of cache directives that can ride along in the Cache-Control header, and IANA keeps a registry for them ๐ง new entries need Standards Action or IESG Approval [RFC5226], which is very much a "big energy only" club ๐ . a registration request needs to bring:
- The name of the cache directive.
- A definition of the parameter value, if any is allowed.
- The specification if it is a request or response directive.
- Text that explains how the cache directive is used for RTSP-controlled media streams.
- A contact person.
this specification registers these values:
no-cache:public:private:no-transform:only-if-cached:max-stale:min-fresh:must-revalidate:proxy-revalidate:max-age:
the registry keeps the directive name and the reference, so you can always trace it back ๐
22.7. Media Properties ๐
22.7.1. Description
okay, RTSP-controlled media streams can have SO many different properties ๐ฆ the media properties needed for the use cases the spec authors had in mind are defined here. but innovation is gonna keep happening, so there will definitely be new use cases or streams with properties that aren't covered yet. that's why new media properties can be specified! ๐ BUT a new one usually needs a big pile of fresh definitions to describe its behavior properly, so the bar is intended to be high. no free passes here ๐ค
22.7.2. Registration Rules
registering a new media property follows the Specification Required policy [RFC5226]. the expert reviewer checks that the registration request fulfills these requirements:
- An ABNF definition of the media property value name that meets the
media-prop-extdefinition is included. - A definition of which media property group it belongs to, or a definition of a new group, is included.
- A description of all changes to the behavior of RTSP as a result of these changes is included.
- A contact person for the registration is listed.
22.7.3. Registered Values
this specification registers the ten values listed in Section 18.29. โจ the registry holds the property group, the name of the media property, and the reference.
22.8. Notify-Reason Values ๐
22.8.1. Description
Notify-Reason values tell everyone why a notification was sent ๐จ every reason comes with its own rules about which headers and information may or must be included in the notification. so new notification behaviors need to be specified for interoperability to work, which means every new value needs its own spec ๐ซถ
22.8.2. Registration Rules
registrations for new Notify-Reason values follow the Specification Required policy [RFC5226]. the expert reviewer checks that the request fulfills these requirements:
- An ABNF definition of the Notify-Reason value name that meets the
Notify-Reason-extensiondefinition is included. - A description of which headers shall be included in the request and response, when it should be sent, and any effect it has on the server client state is made clear.
- A contact person for the registration is listed.
22.8.3. Registered Values
this specification registers three values defined in the Notify-Reasval ABNF, Section 20.2.3: ๐ฅฐ
end-of-stream: this Notify-Reason value indicates the end of a media stream. bye bye stream ๐media-properties-update: this Notify-Reason value allows the server to indicate that the properties of the media have changed during the playout. plot twist mid-playback ๐ณscale-change: this Notify-Reason value allows the server to notify the client about a change in the scale of the media. speed-up/slow-down alert ๐๏ธ
the registry holds the name, description, and reference.
22.9. Range Header Formats ๐
22.9.1. Description
the Range header (Section 18.40) supports different range formats ๐ธ those formats also need an identifier that can be used in the Accept-Ranges header (Section 18.5). new range formats may be registered, but moderation should be applied, because too many of them makes interoperability harder ๐
22.9.2. Registration Rules
a registration follows the Specification Required policy [RFC5226]. the expert reviewer checks that the request fulfills these requirements:
- An ABNF definition of the range format that fulfills the
range-extdefinition is included. - The range format identifier used in the Accept-Ranges header according to the
extension-formatdefinition is defined. - Rules for how one handles the range when using a negative Scale are included.
- A contact person for the registration is listed.
22.9.3. Registered Values
the registry holds the Range header format identifier, the name of the range format, and the reference. this specification registers the following values: โฑ๏ธ
npt: Normal Play Timeclock: UTC Absolute Time formatsmpte: SMPTE Timestampssmpte-30-drop: SMPTE Timestamps 29.97 Frames/sec (30 Hz with Drop)smpte-25: SMPTE Timestamps 25 Frames/sec
22.10. Terminate-Reason Header ๐ช
The Terminate-Reason header (Section 18.52) has two registries for extensions ๐
22.10.1. Redirect Reasons
this registry holds reasons for session termination that can be included in a Terminate-Reason header (Section 18.52) ๐ registrations follow the Expert Review policy [RFC5226]. the expert reviewer checks that the registration request contains this information:
- That the value follows the Terminate-Reason ABNF, i.e., be a token.
- That the specification provides a definition of what procedures are to be followed when a client receives this redirect reason.
- A contact person.
this specification registers three values: ๐จ
- Session-Timeout
- Server-Admin
- Internal-Error
the registry holds the name of the Redirect Reason and the reference.
22.10.2. Terminate-Reason Header Parameters
this registry holds parameters that can be included in the Terminate-Reason header (Section 18.52) alongside a reason โจ registrations are made under the Specification Required policy [RFC5226]. the expert reviewer checks that the registration request contains the following:
- A parameter name.
- A parameter following the syntax allowed by the RTSP 2.0 specification.
- A reference to the specification.
- A contact person.
this specification registers:
timeuser-msg
the registry holds the name of the Terminate Reason and the reference.
22.11. RTP-Info Header Parameters ๐ต
22.11.1. Description
the RTP-Info header (Section 18.45) carries one or more parameter value pairs with information about a particular point in the RTP stream ๐ซ RTP extensions or new usages may need new types of information. since the RTP information that could be needed is likely to be generic enough, and to maximize interoperability, new registrations are made under the Specification Required policy ๐ฆ
22.11.2. Registration Rules
registrations for new RTP-Info values follow the Specification Required policy [RFC5226]. the expert reviewer checks that the registration request contains the following information:
- An ABNF definition that meets the
generic-paramdefinition. - A reference to the specification.
- A contact person for the registration.
22.11.3. Registered Values
this specification registers the following parameter value pairs:
urlssrcseqrtptime
the registry holds the name of the parameter and the reference.
22.12. Seek-Style Policies โฉ
22.12.1. Description
the Seek-Style policy defines how the RTSP agent seeks in media content when it's given a position within that content ๐ฏ new seek policies may be registered, but a large number of them will complicate implementation a lot. the impact of unknown policies is that the server won't honor the unknown one and will use the server default policy instead ๐คทโโ๏ธ
22.12.2. Registration Rules
registrations of new Seek-Style policies follow the Specification Required policy [RFC5226]. the expert reviewer checks that the registration request fulfills these requirements:
- Has an ABNF definition of the Seek-Style policy name that meets the
Seek-S-value-extdefinition. - Includes a short description.
- Lists a contact person for the registration.
- Includes a description of which headers shall be included in the request and response, when it should be sent, and any effect it has on the server-client state.
22.12.3. Registered Values
this specification registers four values (Name - Short Description): ๐
RAP- Using the closest Random Access Point prior to or at the requested start position.CoRAP- Conditional Random Access Point is like RAP, but only if the RAP is closer prior to the requested start position than the current pause point.First-Prior- The first-prior policy will start delivery with the media unit that has a playout time first prior to the requested start position.Next- The next media units after the provided start position.
the registry holds the name of the Seek-Style policy, the description, and the reference.
22.13. Transport Header Registries ๐
The transport header (Section 18.54) contains a number of parameters that have possibilities for future extensions ๐ so registries for these are defined below. ๐ซถ
22.13.1. Transport Protocol Identifier โจ
Okay so a Transport Protocol spec is basically built from a transport protocol identifier ๐ that stands for some combo of transport protocols, plus any number of transport header parameters that are required or optional to use with that identified spec. ๐ This registry is where the identifiers used by registered transport protocol identifiers live ๐ธ
Registering the parameter transport protocol identifier follows the Specification Required policy [RFC5226]. The expert reviewer double-checks the request by making sure:
- There's a contact person or organization with an address and email ๐ฌ
- The value definition matches the ABNF syntax definition of
transport-id(Section 20.2.3) ๐ง - There's a descriptive text explaining how the registered values get used in RTSP, which underlying transport protocols are used, and any required Transport header parameters ๐
The registry stores the protocol ID string and the reference ๐ฆ
Here's what this spec registers:
RTP/AVP: Use of the RTP [RFC3550] protocol for media transport, paired with the "RTP Profile for Audio and Video Conferences with Minimal Control" [RFC3551], over UDP. The usage is explained in RFC 7826, Appendix C.1. ๐งRTP/AVP/UDP: literally the same asRTP/AVP๐RTP/AVPF: Use of the RTP [RFC3550] protocol for media transport, paired with the "Extended RTP Profile for RTCP-based Feedback (RTP/AVPF)" [RFC4585], over UDP. The usage is explained in RFC 7826, Appendix C.1. ๐RTP/AVPF/UDP: the same asRTP/AVPF๐RTP/SAVP: Use of the RTP [RFC3550] protocol for media transport, paired with "The Secure Real-time Transport Protocol (SRTP)" [RFC3711], over UDP. The usage is explained in RFC 7826, Appendix C.1. ๐RTP/SAVP/UDP: the same asRTP/SAVP๐ซถRTP/SAVPF: Use of the RTP [RFC3550] protocol for media transport, paired with the "Extended Secure RTP Profile for Real-time Transport Control Protocol (RTCP)-Based Feedback (RTP/SAVPF)" [RFC5124], over UDP. The usage is explained in RFC 7826, Appendix C.1. ๐ก๏ธRTP/SAVPF/UDP: the same asRTP/SAVPF๐RTP/AVP/TCP: Use of the RTP [RFC3550] protocol for media transport, paired with the "RTP profile for audio and video conferences with minimal control" [RFC3551], over TCP. The usage is explained in RFC 7826, Appendix C.2.2. ๐RTP/AVPF/TCP: Use of the RTP [RFC3550] protocol for media transport, paired with the "Extended RTP Profile for Real-time Transport Control Protocol (RTCP)-Based Feedback (RTP/AVPF)" [RFC4585], over TCP. The usage is explained in RFC 7826, Appendix C.2.2. ๐RTP/SAVP/TCP: Use of the RTP [RFC3550] protocol for media transport, paired with "The Secure Real-time Transport Protocol (SRTP)" [RFC3711], over TCP. The usage is explained in RFC 7826, Appendix C.2.2. ๐งRTP/SAVPF/TCP: Use of the RTP [RFC3550] protocol for media transport, paired with the "Extended Secure RTP Profile for Real-time Transport Control Protocol (RTCP)-Based Feedback (RTP/SAVPF)" [RFC5124], over TCP. The usage is explained in RFC 7826, Appendix C.2.2. ๐ฅน
22.13.2. Transport Modes โจ
The Transport Mode is a Transport header (Section 18.54) parameter ๐ It's used to identify the general mode of media transport. The PLAY value registered defines a PLAYBACK mode, where media flows from server to client ๐ฌ
A registration for the transport parameter mode follows the Standards Action policy [RFC5226]. The registration request needs to meet the following requirements:
- A value definition that follows the ABNF "token" definition in Section 20.2.3 ๐งฉ
- Text that explains how the registered value is used in RTSP ๐
This specification registers one value:
PLAY: See RFC 7826. โถ๏ธ
The registry contains the transport mode value and the reference ๐ท
22.13.3. Transport Parameters โจ
Transport Parameters are the different parameters used in a Transport header's transport specification (Section 18.54) ๐ They give extra info, beyond the transport protocol identifier, that's needed to set up a working transport ๐ง
A registration for parameters that may be included in the Transport header follows the Specification Required policy [RFC5226]. The expert reviewer checks that the request meets these requirements:
- A Transport Parameter Name following the "token" ABNF definition ๐ท๏ธ
- A value definition, if the parameter takes a value, that follows the ABNF definition of
trn-par-value(Section 20.2.3) ๐ง - Text that explains how the registered value is used in RTSP ๐
This specification registers all the transport parameters defined in Section 18.54. Here's a copy of that list:
unicastmulticastinterleavedttllayersssrcmodedest_addrsrc_addrsetupconnectionRTCP-muxMIKEY
The registry contains the transport parameter name and the reference ๐ฆ
22.14. URI Schemes โจ
This spec updates two URI schemes ๐ One is already registered, rtsp, and the other, rtspu, was missing from the registry (it was only defined back in RTSP 1.0 [RFC2326]). A brand-new one, rtsps, is registered here too ๐ These go into an existing registry called "Uniform Resource Identifier (URI) Schemes" that this memo didn't create. Registrations follow [RFC7595] ๐ซถ
22.14.1. The "rtsp" URI Scheme โจ
URI scheme name:rtspStatus:PermanentURI scheme syntax:See Section 20.2.1 of RFC 7826.URI scheme semantics:Okay so thertspscheme is for resources you can reach through the Real-Time Streaming Protocol (RTSP) ๐ฌ RTSP can do lots of different things with the resource, but the main event is streaming it to a client. The operations defined right now areDESCRIBE,GET_PARAMETER,OPTIONS,PLAY,PLAY_NOTIFY,PAUSE,REDIRECT,SETUP,SET_PARAMETER, andTEARDOWN. ๐Encoding considerations:IRIs in this scheme are defined, and they need to be encoded as RTSP URIs when used inside RTSP. That encoding is done according to RFC 3987 ๐งพApplications/protocols that use this URI scheme name:RTSP 1.0 (RFC 2326), RTSP 2.0 (RFC 7826) ๐ฑInteroperability considerations:The extensions in the URI syntax between RTSP 1.0 and 2.0 can create interoperability issues. The changes are:- Support for IPv6 literals in the host part, plus future IP literals through a mechanism as defined in RFC 3986 ๐
- A new relative format for RTSP elements that doesn't have to start with "/" ๐งญ
The above changes should have no impact on interoperability, as discussed in detail in Section 4.2 of RFC 7826. โจ
Security considerations:> ๐จ Serious bestie moment: all the security threats identified in Section 7 of RFC 3986 also apply to this scheme. They need to be reviewed and considered in any implementation that uses this scheme. Do not skip this part ๐ญContact:Magnus Westerlund, magnus.westerlund@ericsson.com ๐งAuthor/Change controller:IETF ๐ธReferences:RFC 2326, RFC 3986, RFC 3987, and RFC 7826 ๐
22.14.2. The "rtsps" URI Scheme โจ
URI scheme name:rtspsStatus:PermanentURI scheme syntax:See Section 20.2.1 of RFC 7826.URI scheme semantics:Thertspsscheme is for resources you can reach through RTSP over TLS ๐ RTSP can do lots of things with the resource, but the main event is streaming it to a client. The operations defined right now areDESCRIBE,GET_PARAMETER,OPTIONS,PLAY,PLAY_NOTIFY,PAUSE,REDIRECT,SETUP,SET_PARAMETER, andTEARDOWN. ๐ฅEncoding considerations:IRIs in this scheme are defined, and they need to be encoded as RTSP URIs when used inside RTSP. That encoding is done according to RFC 3987 ๐งพApplications/protocols that use this URI scheme name:RTSP 1.0 (RFC 2326), RTSP 2.0 (RFC 7826) ๐ฑInteroperability considerations:Thertspsscheme was never officially defined for RTSP 1.0, but it's seen widespread use in real deployments of RTSP 1.0 ๐ So this section talks about the believed changes between the unspecified RTSP 1.0rtspsscheme and the RTSP 2.0 definition. The extensions in the URI syntax between RTSP 1.0 and 2.0 can create interoperability issues. The changes are:- Support for IPv6 literals in the host part, plus future IP literals through a mechanism as defined by RFC 3986 ๐
- A new relative format for RTSP elements that doesn't have to start with "/" ๐งญ
The above changes should have no impact on interoperability, as discussed in detail in Section 4.2 of RFC 7826. โจ
Security considerations:> ๐จ Serious bestie moment: all the security threats identified in Section 7 of RFC 3986 also apply to this scheme. They need to be reviewed and considered in any implementation that uses this scheme. Do not skip this part ๐ญContact:Magnus Westerlund, magnus.westerlund@ericsson.com ๐งAuthor/Change controller:IETF ๐ธReferences:RFC 2326, RFC 3986, RFC 3987, and RFC 7826 ๐
22.14.3. The "rtspu" URI Scheme โจ
URI scheme name:rtspuStatus:PermanentURI scheme syntax:See Section 3.2 of RFC 2326.URI scheme semantics:Thertspuscheme is for resources you can reach through RTSP over an unreliable datagram transport ๐ก RTSP can do lots of things with the resource, but the main event is streaming it to a client. The operations defined right now areDESCRIBE,GET_PARAMETER,OPTIONS,REDIRECT,PLAY,PLAY_NOTIFY,PAUSE,SETUP,SET_PARAMETER, andTEARDOWN. ๐๏ธEncoding considerations:This scheme isn't meant to be used with characters outside the US-ASCII repertoire ๐คApplications/protocols that use this URI scheme name:RTSP 1.0 (RFC 2326) ๐ฑInteroperability considerations:The way RTSP over UDP defines its transport mechanism has interoperability issues, and that makes using this scheme problematic ๐ฌSecurity considerations:> ๐จ Serious bestie moment: all the security threats identified in Section 7 of RFC 3986 also apply to this scheme. They need to be reviewed and considered in any implementation that uses this scheme. Do not skip this part ๐ญContact:Magnus Westerlund, magnus.westerlund@ericsson.com ๐งAuthor/Change controller:IETF ๐ธReferences:RFC 2326 ๐
22.15. SDP Attributes ๐
okay so this bit is about SDP attributes, which are the little labels that go inside session descriptions ๐ this spec registers three of them with IANA, and they're all both session and media level, so they can show up in either spot. no cap, that's a lot of power for three tiny names โจ
First up is range, the Media Range Attribute. Its values are defined by the ABNF, so go check there when you want the exact shape ๐ฆ
Attribute name: range
Long form: Media Range Attribute
Type of name: att-field
Type of attribute: both session and media level
Subject to charset: No
Purpose: RFC 7826
Reference: RFC 2326, RFC 7826
Values: See ABNF definition.
Next is control, the RTSP control URI ๐ธ this one's values are absolute or relative URIs, so it's giving flexibility, periodt.
Attribute name: control
Long form: RTSP control URI
Type of name: att-field
Type of attribute: both session and media level
Subject to charset: No
Purpose: RFC 7826
Reference: RFC 2326, RFC 7826
Values: Absolute or Relative URIs.
Last one is mtag, the Message Tag ๐ง it's only referenced by RFC 7826 (not RFC 2326), and its values also come from the ABNF.
Attribute name: mtag
Long form: Message Tag
Type of name: att-field
Type of attribute: both session and media level
Subject to charset: No
Purpose: RFC 7826
Reference: RFC 7826
Values: See ABNF definition
22.16. Media Type Registration for text/parameters ๐
okay this is the registration form for a media type called text/parameters ๐ it's the one that RTSP GET_PARAMETER and SET_PARAMETER use when apps want to read and set their own extra parameters. the form is kinda long, so here it is in full, exactly as registered. the security and interop notes are super important, so don't skip them, bestie ๐
Type name: text
Subtype name: parameters
Required parameters:
Optional parameters: charset: The charset parameter is applicable to
the encoding of the parameter values. The default charset is
UTF-8, if the 'charset' parameter is not present.
Encoding considerations: 8bit
Security considerations: This format may carry any type of
parameters. Some can have security requirements, like privacy,
confidentiality, or integrity requirements. The format has no
built-in security protection. For the usage, the transport can be
protected between server and client using TLS. However, care must
be taken to consider if the proxies are also trusted with the
parameters in case hop-by-hop security is used. If stored as a
file in a file system, the necessary precautions need to be taken
in relation to the parameter requirements including object
security such as S/MIME [RFC5751].
Interoperability considerations: This media type was mentioned as a
fictional example in [RFC2326], but was not formally specified.
This has resulted in usage of this media type that may not match
its formal definition.
Published specification: RFC 7826, Appendix F.
Applications that use this media type: Applications that use RTSP
and have additional parameters they like to read and set using the
RTSP GET_PARAMETER and SET_PARAMETER methods.
Additional information:
Magic number(s): N/A
File extension(s): N/A
Macintosh file type code(s): N/A
Person & email address to contact for further information:
Magnus Westerlund (magnus.westerlund@ericsson.com)
Intended usage: Common
Restrictions on usage: None
Author: Magnus Westerlund (magnus.westerlund@ericsson.com)
Change controller: IETF
Addition Notes:
the TL;DR on the security side: this format has no built-in protection ๐ญ so TLS between server and client helps, but if you've got proxies in the middle using hop-by-hop security, you have to make sure those proxies are trusted with the parameters too. and if you store it as a file, you still need to handle the parameter requirements, object security like S/MIME included ๐ฅ the interop bit is the tea, too: it was only a fictional example in RFC 2326, so real-world usage might not match the formal definition. iykyk ๐
23. References โจ
23.1. Normative References ๐โจ
okay bestie, these are the receipts ๐งพ๐ every single source the spec leans on, listed in the original order so nothing gets lost ๐ซถ
[FIPS180-4]National Institute of Standards and Technology (NIST), "Federal Information Processing Standards Publication: Secure Hash Standard (SHS)", DOI 10.6028/NIST.FIPS.180-4, August 2015,<http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf>.[RFC768]Postel, J., "User Datagram Protocol", STD 6, RFC 768, DOI 10.17487/RFC0768, August 1980,<http://www.rfc-editor.org/info/rfc768>.[RFC793]Postel, J., "Transmission Control Protocol", STD 7, RFC 793, DOI 10.17487/RFC0793, September 1981,<http://www.rfc-editor.org/info/rfc793>.[RFC2119]Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997,<http://www.rfc-editor.org/info/rfc2119>.[RFC2460]Deering, S. and R. Hinden, "Internet Protocol, Version 6 (IPv6) Specification", RFC 2460, DOI 10.17487/RFC2460, December 1998,<http://www.rfc-editor.org/info/rfc2460>.[RFC2616]Fielding, R., Gettys, J., Mogul, J., Frystyk, H., Masinter, L., Leach, P., and T. Berners-Lee, "Hypertext Transfer Protocol -- HTTP/1.1", RFC 2616, DOI 10.17487/RFC2616, June 1999,<http://www.rfc-editor.org/info/rfc2616>.[RFC2617]Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence, S., Leach, P., Luotonen, A., and L. Stewart, "HTTP Authentication: Basic and Digest Access Authentication", RFC 2617, DOI 10.17487/RFC2617, June 1999,<http://www.rfc-editor.org/info/rfc2617>.[RFC2818]Rescorla, E., "HTTP Over TLS", RFC 2818, DOI 10.17487/RFC2818, May 2000,<http://www.rfc-editor.org/info/rfc2818>.[RFC3550]Schulzrinne, H., Casner, S., Frederick, R., and V. Jacobson, "RTP: A Transport Protocol for Real-Time Applications", STD 64, RFC 3550, DOI 10.17487/RFC3550, July 2003,<http://www.rfc-editor.org/info/rfc3550>.[RFC3551]Schulzrinne, H. and S. Casner, "RTP Profile for Audio and Video Conferences with Minimal Control", STD 65, RFC 3551, DOI 10.17487/RFC3551, July 2003,<http://www.rfc-editor.org/info/rfc3551>.[RFC3629]Yergeau, F., "UTF-8, a transformation format of ISO 10646", STD 63, RFC 3629, DOI 10.17487/RFC3629, November 2003,<http://www.rfc-editor.org/info/rfc3629>.[RFC3711]Baugher, M., McGrew, D., Naslund, M., Carrara, E., and K. Norrman, "The Secure Real-time Transport Protocol (SRTP)", RFC 3711, DOI 10.17487/RFC3711, March 2004,<http://www.rfc-editor.org/info/rfc3711>.[RFC3830]Arkko, J., Carrara, E., Lindholm, F., Naslund, M., and K. Norrman, "MIKEY: Multimedia Internet KEYing", RFC 3830, DOI 10.17487/RFC3830, August 2004,<http://www.rfc-editor.org/info/rfc3830>.[RFC3986]Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, DOI 10.17487/RFC3986, January 2005,<http://www.rfc-editor.org/info/rfc3986>.[RFC3987]Duerst, M. and M. Suignard, "Internationalized Resource Identifiers (IRIs)", RFC 3987, DOI 10.17487/RFC3987, January 2005,<http://www.rfc-editor.org/info/rfc3987>.[RFC4086]Eastlake 3rd, D., Schiller, J., and S. Crocker, "Randomness Requirements for Security", BCP 106, RFC 4086, DOI 10.17487/RFC4086, June 2005,<http://www.rfc-editor.org/info/rfc4086>.[RFC4291]Hinden, R. and S. Deering, "IP Version 6 Addressing Architecture", RFC 4291, DOI 10.17487/RFC4291, February 2006,<http://www.rfc-editor.org/info/rfc4291>.[RFC7595]Thaler, D., Ed., Hansen, T., and T. Hardie, "Guidelines and Registration Procedures for URI Schemes", BCP 35, RFC 7595, DOI 10.17487/RFC7595, June 2015,<http://www.rfc-editor.org/info/rfc7595>.[RFC4566]Handley, M., Jacobson, V., and C. Perkins, "SDP: Session Description Protocol", RFC 4566, DOI 10.17487/RFC4566, July 2006,<http://www.rfc-editor.org/info/rfc4566>.[RFC4571]Lazzaro, J., "Framing Real-time Transport Protocol (RTP) and RTP Control Protocol (RTCP) Packets over Connection-Oriented Transport", RFC 4571, DOI 10.17487/RFC4571, July 2006,<http://www.rfc-editor.org/info/rfc4571>.[RFC4585]Ott, J., Wenger, S., Sato, N., Burmeister, C., and J. Rey, "Extended RTP Profile for Real-time Transport Control Protocol (RTCP)-Based Feedback (RTP/AVPF)", RFC 4585, DOI 10.17487/RFC4585, July 2006,<http://www.rfc-editor.org/info/rfc4585>.[RFC4648]Josefsson, S., "The Base16, Base32, and Base64 Data Encodings", RFC 4648, DOI 10.17487/RFC4648, October 2006,<http://www.rfc-editor.org/info/rfc4648>.[RFC4738]Ignjatic, D., Dondeti, L., Audet, F., and P. Lin, "MIKEY-RSA-R: An Additional Mode of Key Distribution in Multimedia Internet KEYing (MIKEY)", RFC 4738, DOI 10.17487/RFC4738, November 2006,<http://www.rfc-editor.org/info/rfc4738>.[RFC5124]Ott, J. and E. Carrara, "Extended Secure RTP Profile for Real-time Transport Control Protocol (RTCP)-Based Feedback (RTP/SAVPF)", RFC 5124, DOI 10.17487/RFC5124, February 2008,<http://www.rfc-editor.org/info/rfc5124>.[RFC5226]Narten, T. and H. Alvestrand, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 5226, DOI 10.17487/RFC5226, May 2008,<http://www.rfc-editor.org/info/rfc5226>.[RFC5234]Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", STD 68, RFC 5234, DOI 10.17487/RFC5234, January 2008,<http://www.rfc-editor.org/info/rfc5234>.[RFC5246]Dierks, T. and E. Rescorla, "The Transport Layer Security (TLS) Protocol Version 1.2", RFC 5246, DOI 10.17487/RFC5246, August 2008,<http://www.rfc-editor.org/info/rfc5246>.[RFC5280]Cooper, D., Santesson, S., Farrell, S., Boeyen, S., Housley, R., and W. Polk, "Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile", RFC 5280, DOI 10.17487/RFC5280, May 2008,<http://www.rfc-editor.org/info/rfc5280>.[RFC5322]Resnick, P., Ed., "Internet Message Format", RFC 5322, DOI 10.17487/RFC5322, October 2008,<http://www.rfc-editor.org/info/rfc5322>.[RFC5646]Phillips, A., Ed. and M. Davis, Ed., "Tags for Identifying Languages", BCP 47, RFC 5646, DOI 10.17487/RFC5646, September 2009,<http://www.rfc-editor.org/info/rfc5646>.[RFC5751]Ramsdell, B. and S. Turner, "Secure/Multipurpose Internet Mail Extensions (S/MIME) Version 3.2 Message Specification", RFC 5751, DOI 10.17487/RFC5751, January 2010,<http://www.rfc-editor.org/info/rfc5751>.[RFC5761]Perkins, C. and M. Westerlund, "Multiplexing RTP Data and Control Packets on a Single Port", RFC 5761, DOI 10.17487/RFC5761, April 2010,<http://www.rfc-editor.org/info/rfc5761>.[RFC5888]Camarillo, G. and H. Schulzrinne, "The Session Description Protocol (SDP) Grouping Framework", RFC 5888, DOI 10.17487/RFC5888, June 2010,<http://www.rfc-editor.org/info/rfc5888>.[RFC6838]Freed, N., Klensin, J., and T. Hansen, "Media Type Specifications and Registration Procedures", BCP 13, RFC 6838, DOI 10.17487/RFC6838, January 2013,<http://www.rfc-editor.org/info/rfc6838>.[RFC7230]Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing", RFC 7230, DOI 10.17487/RFC7230, June 2014,<http://www.rfc-editor.org/info/rfc7230>.[RFC7231]Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content", RFC 7231, DOI 10.17487/RFC7231, June 2014,<http://www.rfc-editor.org/info/rfc7231>.[RFC7232]Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Conditional Requests", RFC 7232, DOI 10.17487/RFC7232, June 2014,<http://www.rfc-editor.org/info/rfc7232>.[RFC7233]Fielding, R., Ed., Lafon, Y., Ed., and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Range Requests", RFC 7233, DOI 10.17487/RFC7233, June 2014,<http://www.rfc-editor.org/info/rfc7233>.[RFC7234]Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Caching", RFC 7234, DOI 10.17487/RFC7234, June 2014,<http://www.rfc-editor.org/info/rfc7234>.[RFC7235]Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Authentication", RFC 7235, DOI 10.17487/RFC7235, June 2014,<http://www.rfc-editor.org/info/rfc7235>.[RFC7615]Reschke, J., "HTTP Authentication-Info and Proxy-Authentication-Info Response Header Fields", RFC 7615, DOI 10.17487/RFC7615, September 2015,<http://www.rfc-editor.org/info/rfc7615>.[RFC7616]Shekh-Yusef, R., Ed., Ahrens, D., and S. Bremer, "HTTP Digest Access Authentication", RFC 7616, DOI 10.17487/RFC7616, September 2015,<http://www.rfc-editor.org/info/rfc7616>.[RFC7617]Reschke, J., "The 'Basic' HTTP Authentication Scheme", RFC 7617, DOI 10.17487/RFC7617, September 2015,<http://www.rfc-editor.org/info/rfc7617>.[RFC7825]Goldberg, J., Westerlund, M., and T. Zeng, "A Network Address Translator (NAT) Traversal Mechanism for Media Controlled by Real-Time Streaming Protocol (RTSP)", RFC 7825, DOI 10.17487/RFC7825, December 2016,<http://www.rfc-editor.org/info/rfc7825>.[RTP-CIRCUIT-BREAKERS]Perkins, C. and V. Singh, "Multimedia Congestion Control: Circuit Breakers for Unicast RTP Sessions", Work in Progress, draft-ietf-avtcore-rtp-circuit-breakers-13, February 2016.[SMPTE-TC]Society of Motion Picture and Television Engineers, "ST 12-1:2008 For Television -- Time and Control Code", DOI 10.5594/SMPTE.ST12-1.2008, February 2008,<http://ieeexplore.ieee.org/servlet/opac?punumber=7289818>.[TS-26234]3rd Generation Partnership Project (3GPP), "Transparent end-to-end Packet-switched Streaming Service (PSS); Protocols and codecs", Technical Specification 26.234, Release 13, September 2015,<http://www.3gpp.org/DynaReport/26234.htm>.
23.2. Informative References โจ
okay bestie, these are the informative refs, the extra reading that helps you understand the vibe but isn't required to implement ๐ง ๐
- [ISO.13818-6.1995] International Organization for Standardization, "Information technology -- Generic coding of moving pictures and associated audio information - part 6: Extension for DSM-CC", ISO Draft Standard 13818-6:1998, October 1998,
<http://www.iso.org/iso/home/store/catalogue_tc/catalogue_detail.htm?csnumber=25039>. ๐ฌ - [ISO.8601.2000] International Organization for Standardization, "Data elements and interchange formats - Information interchange - Representation of dates and times", ISO/IEC Standard 8601, December 2000. ๐๏ธ
- [RFC791] Postel, J., "Internet Protocol", STD 5, RFC 791, DOI 10.17487/RFC0791, September 1981,
<http://www.rfc-editor.org/info/rfc791>. ๐ - [RFC1123] Braden, R., Ed., "Requirements for Internet Hosts - Application and Support", STD 3, RFC 1123, DOI 10.17487/RFC1123, October 1989,
<http://www.rfc-editor.org/info/rfc1123>. ๐ฅ๏ธ - [RFC2068] Fielding, R., Gettys, J., Mogul, J., Frystyk, H., and T. Berners-Lee, "Hypertext Transfer Protocol -- HTTP/1.1", RFC 2068, DOI 10.17487/RFC2068, January 1997,
<http://www.rfc-editor.org/info/rfc2068>. ๐ - [RFC2326] Schulzrinne, H., Rao, A., and R. Lanphier, "Real Time Streaming Protocol (RTSP)", RFC 2326, DOI 10.17487/RFC2326, April 1998,
<http://www.rfc-editor.org/info/rfc2326>. ๐ฅ this is the one we're literally obsessed with - [RFC2663] Srisuresh, P. and M. Holdrege, "IP Network Address Translator (NAT) Terminology and Considerations", RFC 2663, DOI 10.17487/RFC2663, August 1999,
<http://www.rfc-editor.org/info/rfc2663>. ๐ - [RFC2974] Handley, M., Perkins, C., and E. Whelan, "Session Announcement Protocol", RFC 2974, DOI 10.17487/RFC2974, October 2000,
<http://www.rfc-editor.org/info/rfc2974>. ๐ฃ - [RFC3261] Rosenberg, J., Schulzrinne, H., Camarillo, G., Johnston, A., Peterson, J., Sparks, R., Handley, M., and E. Schooler, "SIP: Session Initiation Protocol", RFC 3261, DOI 10.17487/RFC3261, June 2002,
<http://www.rfc-editor.org/info/rfc3261>. ๐ - [RFC3264] Rosenberg, J. and H. Schulzrinne, "An Offer/Answer Model with Session Description Protocol (SDP)", RFC 3264, DOI 10.17487/RFC3264, June 2002,
<http://www.rfc-editor.org/info/rfc3264>. ๐ค - [RFC3339] Klyne, G. and C. Newman, "Date and Time on the Internet: Timestamps", RFC 3339, DOI 10.17487/RFC3339, July 2002,
<http://www.rfc-editor.org/info/rfc3339>. โฐ - [RFC4145] Yon, D. and G. Camarillo, "TCP-Based Media Transport in the Session Description Protocol (SDP)", RFC 4145, DOI 10.17487/RFC4145, September 2005,
<http://www.rfc-editor.org/info/rfc4145>. ๐งฆ - [RFC4567] Arkko, J., Lindholm, F., Naslund, M., Norrman, K., and E. Carrara, "Key Management Extensions for Session Description Protocol (SDP) and Real Time Streaming Protocol (RTSP)", RFC 4567, DOI 10.17487/RFC4567, July 2006,
<http://www.rfc-editor.org/info/rfc4567>. ๐ - [RFC4588] Rey, J., Leon, D., Miyazaki, A., Varsa, V., and R. Hakenberg, "RTP Retransmission Payload Format", RFC 4588, DOI 10.17487/RFC4588, July 2006,
<http://www.rfc-editor.org/info/rfc4588>. ๐ - [RFC4855] Casner, S., "Media Type Registration of RTP Payload Formats", RFC 4855, DOI 10.17487/RFC4855, February 2007,
<http://www.rfc-editor.org/info/rfc4855>. ๐ท๏ธ - [RFC4856] Casner, S., "Media Type Registration of Payload Formats in the RTP Profile for Audio and Video Conferences", RFC 4856, DOI 10.17487/RFC4856, February 2007,
<http://www.rfc-editor.org/info/rfc4856>. ๐ท๏ธ - [RFC5104] Wenger, S., Chandra, U., Westerlund, M., and B. Burman, "Codec Control Messages in the RTP Audio-Visual Profile with Feedback (AVPF)", RFC 5104, DOI 10.17487/RFC5104, February 2008,
<http://www.rfc-editor.org/info/rfc5104>. ๐๏ธ - [RFC5245] Rosenberg, J., "Interactive Connectivity Establishment (ICE): A Protocol for Network Address Translator (NAT) Traversal for Offer/Answer Protocols", RFC 5245, DOI 10.17487/RFC5245, April 2010,
<http://www.rfc-editor.org/info/rfc5245>. ๐งญ - [RFC5389] Rosenberg, J., Mahy, R., Matthews, P., and D. Wing, "Session Traversal Utilities for NAT (STUN)", RFC 5389, DOI 10.17487/RFC5389, October 2008,
<http://www.rfc-editor.org/info/rfc5389>. ๐ณ๏ธ - [RFC5583] Schierl, T. and S. Wenger, "Signaling Media Decoding Dependency in the Session Description Protocol (SDP)", RFC 5583, DOI 10.17487/RFC5583, July 2009,
<http://www.rfc-editor.org/info/rfc5583>. ๐งฉ - [RFC5905] Mills, D., Martin, J., Ed., Burbank, J., and W. Kasch, "Network Time Protocol Version 4: Protocol and Algorithms Specification", RFC 5905, DOI 10.17487/RFC5905, June 2010,
<http://www.rfc-editor.org/info/rfc5905>. ๐ฐ๏ธ - [RFC6298] Paxson, V., Allman, M., Chu, J., and M. Sargent, "Computing TCP's Retransmission Timer", RFC 6298, DOI 10.17487/RFC6298, June 2011,
<http://www.rfc-editor.org/info/rfc6298>. โณ - [Stevens98] Stevens, W., Fenner, B., and A. Rudoff, "Unix Networking Programming, Volume 1: The Sockets Networking API (3rd Edition)", 1998. ๐
Appendix A. Examples ๐
okay so this section is literally a bunch of examples showing different ways to use RTSP, and they help you see how its functions actually work in practice ๐ but real talk, the examples are just examples ๐ซถ the normative and syntax bits in the other sections always win if they disagree ๐
also heads up, a lot of these examples got split across several lines, and the follow-up lines start with whitespace, which the syntax allows ๐งโจ
A.1. Media on Demand (Unicast) ๐ฌ
okay so this example is all about media-on-demand streaming of stuff stored in a container file ๐ฆ. For our purposes, a container file is a storage entity where multiple continuous media types for the same end-user presentation all live together. Basically the container file is an RTSP presentation, and each of its components is an RTSP-controlled media stream ๐๏ธ. Container files are a super popular way to store these presentations, and even though the components get transported as independent streams, it's giving "keep them in one shared context" on the server end ๐ .
This lets the server keep a single storage handle open easily. It also means every stream gets treated equally if the server ever prioritizes some streams over others. ๐ซถ
the presentation author might also want to stop the client from picking out individual streams, so the combined artistic effect stays intact ๐ญ. And in a presentation that's this tightly bound, it's so useful to control everything with one single control message using an aggregate URI ๐.
This example shows a single RTSP session controlling multiple streams, and it shows off aggregate URIs too โจ. Also, in a container file you don't want to write any URI parts that won't survive distribution (like the host and most of the path element), so this example uses the "*" and a relative URI in the delivered SDP ๐ง.
Also, the SDP here is not cacheable, bestie ๐. The Expires header is set to an equal value with the date, which signals immediate expiration of its validity ๐.
Okay, the storyline: Client C requests a presentation from media server M. The movie is stored in a container file, and the client already has an RTSP URI pointing to that container file ๐ฟ.
C->M: DESCRIBE rtsp://example.com/twister.3gp RTSP/2.0
CSeq: 1
User-Agent: PhonyClient/1.2
M->C: RTSP/2.0 200 OK
CSeq: 1
Server: PhonyServer/1.0
Date: Fri, 20 Dec 2013 10:20:32 +0000
Content-Type: application/sdp
Content-Length: 271
Content-Base: rtsp://example.com/twister.3gp/
Expires: Fri, 20 Dec 2013 12:20:32 +0000
v=0
o=- 2890844256 2890842807 IN IP4 198.51.100.5
s=RTSP Session
i=An Example of RTSP Session Usage
e=adm@example.com
c=IN IP4 0.0.0.0
a=control: *
a=range:npt=00:00:00-00:10:34.10
t=0 0
m=audio 0 RTP/AVP 0
a=control: trackID=1
m=video 0 RTP/AVP 26
a=control: trackID=4
Next up, the client sets up the first track ๐ง.
C->M: SETUP rtsp://example.com/twister.3gp/trackID=1 RTSP/2.0
CSeq: 2
User-Agent: PhonyClient/1.2
Require: play.basic
Transport: RTP/AVP;unicast;dest_addr=":8000"/":8001"
Accept-Ranges: npt, smpte, clock
M->C: RTSP/2.0 200 OK
CSeq: 2
Server: PhonyServer/1.0
Transport: RTP/AVP;unicast; ssrc=93CB001E;
dest_addr="192.0.2.53:8000"/"192.0.2.53:8001";
src_addr="198.51.100.5:9000"/"198.51.100.5:9001"
Session: OccldOFFq23KwjYpAnBbUr
Expires: Fri, 20 Dec 2013 12:20:33 +0000
Date: Fri, 20 Dec 2013 10:20:33 +0000
Accept-Ranges: npt
Media-Properties: Random-Access=0.02, Immutable, Unlimited
Then the second track gets set up in the same session ๐ฌ.
C->M: SETUP rtsp://example.com/twister.3gp/trackID=4 RTSP/2.0
CSeq: 3
User-Agent: PhonyClient/1.2
Require: play.basic
Transport: RTP/AVP;unicast;dest_addr=":8002"/":8003"
Session: OccldOFFq23KwjYpAnBbUr
Accept-Ranges: npt, smpte, clock
M->C: RTSP/2.0 200 OK
CSeq: 3
Server: PhonyServer/1.0
Transport: RTP/AVP;unicast; ssrc=A813FC13;
dest_addr="192.0.2.53:8002"/"192.0.2.53:8003";
src_addr="198.51.100.5:9002"/"198.51.100.5:9003";
Session: OccldOFFq23KwjYpAnBbUr
Expires: Fri, 20 Dec 2013 12:20:33 +0000
Date: Fri, 20 Dec 2013 10:20:33 +0000
Accept-Range: NPT
Media-Properties: Random-Access=0.8, Immutable, Unlimited
Now the client hits PLAY on the aggregate URI, starting from 30 seconds in โถ๏ธ.
C->M: PLAY rtsp://example.com/twister.3gp/ RTSP/2.0
CSeq: 4
User-Agent: PhonyClient/1.2
Range: npt=30-
Seek-Style: RAP
Session: OccldOFFq23KwjYpAnBbUr
M->C: RTSP/2.0 200 OK
CSeq: 4
Server: PhonyServer/1.0
Date: Fri, 20 Dec 2013 10:20:34 +0000
Session: OccldOFFq23KwjYpAnBbUr
Range: npt=30-634.10
Seek-Style: RAP
RTP-Info: url="rtsp://example.com/twister.3gp/trackID=4"
ssrc=0D12F123:seq=12345;rtptime=3450012,
url="rtsp://example.com/twister.3gp/trackID=1"
ssrc=4F312DD8:seq=54321;rtptime=2876889
Then the client pauses ๐. This happens 0.87 seconds after playback starts.
C->M: PAUSE rtsp://example.com/twister.3gp/ RTSP/2.0
CSeq: 5
User-Agent: PhonyClient/1.2
Session: OccldOFFq23KwjYpAnBbUr
# Pause happens 0.87 seconds after starting to play
M->C: RTSP/2.0 200 OK
CSeq: 5
Server: PhonyServer/1.0
Date: Fri, 20 Dec 2013 10:20:35 +0000
Session: OccldOFFq23KwjYpAnBbUr
Range: npt=30.87-634.10
Resuming playback from that exact spot, using the Next seek style ๐.
C->M: PLAY rtsp://example.com/twister.3gp/ RTSP/2.0
CSeq: 6
User-Agent: PhonyClient/1.2
Range: npt=30.87-634.10
Seek-Style: Next
Session: OccldOFFq23KwjYpAnBbUr
M->C: RTSP/2.0 200 OK
CSeq: 6
Server: PhonyServer/1.0
Date: Fri, 20 Dec 2013 10:22:13 +0000
Session: OccldOFFq23KwjYpAnBbUr
Range: npt=30.87-634.10
Seek-Style: Next
RTP-Info: url="rtsp://example.com/twister.3gp/trackID=4"
ssrc=0D12F123:seq=12555;rtptime=6330012,
url="rtsp://example.com/twister.3gp/trackID=1"
ssrc=4F312DD8:seq=55021;rtptime=3132889
And finally the client tears the whole session down ๐.
C->M: TEARDOWN rtsp://example.com/twister.3gp/ RTSP/2.0
CSeq: 7
User-Agent: PhonyClient/1.2
Session: OccldOFFq23KwjYpAnBbUr
M->C: RTSP/2.0 200 OK
CSeq: 7
Server: PhonyServer/1.0
Date: Fri, 20 Dec 2013 10:31:53 +0000
A.2. Media on Demand Using Pipelining ๐
this one is basically the A.1 example, just with pipelining added to speed up the setup ๐๏ธ. It only needs two round-trip times before the media starts flowing ๐. Step one: grab the session description so the client knows which media resources need setting up. Step two: fire off the necessary SETUP requests plus the PLAY request, all to start media delivery.
Same storyline as before: Client C requests a presentation from media server M. The movie is stored in a container file, and the client has an RTSP URI for that container file ๐ฅ.
C->M: DESCRIBE rtsp://example.com/twister.3gp RTSP/2.0
CSeq: 1
User-Agent: PhonyClient/1.2
M->C: RTSP/2.0 200 OK
CSeq: 1
Server: PhonyServer/1.0
Date: Fri, 20 Dec 2013 10:20:32 +0000
Content-Type: application/sdp
Content-Length: 271
Content-Base: rtsp://example.com/twister.3gp/
Expires: Fri, 20 Dec 2013 12:20:32 +0000
v=0
o=- 2890844256 2890842807 IN IP4 192.0.2.5
s=RTSP Session
i=An Example of RTSP Session Usage
e=adm@example.com
c=IN IP4 0.0.0.0
a=control: *
a=range:npt=00:00:00-00:10:34.10
t=0 0
m=audio 0 RTP/AVP 0
a=control: trackID=1
m=video 0 RTP/AVP 26
a=control: trackID=4
Now for the pipelined bit ๐ง. The client sends both SETUP requests and the PLAY request back to back, each tagged with Pipelined-Requests: 7654, without waiting for individual responses ๐จ.
C->M: SETUP rtsp://example.com/twister.3gp/trackID=1 RTSP/2.0
CSeq: 2
User-Agent: PhonyClient/1.2
Require: play.basic
Transport: RTP/AVP;unicast;dest_addr=":8000"/":8001"
Accept-Ranges: npt, smpte, clock
Pipelined-Requests: 7654
C->M: SETUP rtsp://example.com/twister.3gp/trackID=4 RTSP/2.0
CSeq: 3
User-Agent: PhonyClient/1.2
Require: play.basic
Transport: RTP/AVP;unicast;dest_addr=":8002"/":8003"
Accept-Ranges: npt, smpte, clock
Pipelined-Requests: 7654
C->M: PLAY rtsp://example.com/twister.3gp/ RTSP/2.0
CSeq: 4
User-Agent: PhonyClient/1.2
Range: npt=0-
Seek-Style: RAP
Pipelined-Requests: 7654
The server answers each of those pipelined requests in turn ๐ฌ.
M->C: RTSP/2.0 200 OK
CSeq: 2
Server: PhonyServer/1.0
Transport: RTP/AVP;unicast;
dest_addr="192.0.2.53:8000"/"192.0.2.53:8001";
src_addr="198.51.100.5:9000"/"198.51.100.5:9001";
ssrc=93CB001E
Session: OccldOFFq23KwjYpAnBbUr
Expires: Fri, 20 Dec 2013 12:20:32 +0000
Date: Fri, 20 Dec 2013 10:20:32 +0000
Accept-Ranges: npt
Pipelined-Requests: 7654
Media-Properties: Random-Access=0.2, Immutable, Unlimited
M->C: RTSP/2.0 200 OK
CSeq: 3
Server: PhonyServer/1.0
Transport: RTP/AVP;unicast;
dest_addr="192.0.2.53:8002"/"192.0.2.53:8003;
src_addr="198.51.100.5:9002"/"198.51.100.5:9003";
ssrc=A813FC13
Session: OccldOFFq23KwjYpAnBbUr
Expires: Sat, 21 Dec 2013 10:20:32 +0000
Date: Fri, 20 Dec 2013 10:20:32 +0000
Accept-Range: NPT
Pipelined-Requests: 7654
Media-Properties: Random-Access=0.8, Immutable, Unlimited
M->C: RTSP/2.0 200 OK
CSeq: 4
Server: PhonyServer/1.0
Date: Fri, 20 Dec 2013 10:20:32 +0000
Session: OccldOFFq23KwjYpAnBbUr
Range: npt=0-623.10
Seek-Style: RAP
RTP-Info: url="rtsp://example.com/twister.3gp/trackID=4"
ssrc=0D12F123:seq=12345;rtptime=3450012,
url="rtsp://example.com/twister.3gp/trackID=1"
ssrc=4F312DD8:seq=54321;rtptime=2876889
Pipelined-Requests: 7654
A.3. Secured Media Session for On-Demand Content โจ
Okay so this one is basically the A.2 example, but make it secure ๐ (see Appendix A.2). The client first tries to fetch the presentation insecurely, but the server is like "nah, go secure" and redirects it to a URI that requires a secure connection for the RTSP messages ๐ โโ๏ธ. The client sets up a TCP/TLS connection, then grabs the session description to figure out which media resources to set up. That session description says the media is secure (SRTP) ๐. Next, the client sends the SETUP requests with MIKEY messages, pipelined with a PLAY request so media delivery kicks off right away ๐ฌ. Slay.
Client C wants a presentation from media server M ๐. The movie is stored in a container file, and the client already has an RTSP URI pointing at that container file ๐๏ธ.
Heads up bestie: the MIKEY messages below are not real valid MIKEY messages ๐. They're just Base64-encoded random data holding the spot where the real ones would go.
C->M: DESCRIBE rtsp://example.com/twister.3gp RTSP/2.0
CSeq: 1
User-Agent: PhonyClient/1.2
M->C: RTSP/2.0 301 Moved Permanently
CSeq: 1
Server: PhonyServer/1.0
Date: Fri, 20 Dec 2013 10:25:32 +0000
Location: rtsps://example.com/twister.3gp
C->M: Establish TCP/TLS connection and verify server's
certificate that represents example.com.
Used for all below RTSP messages.
C->M: DESCRIBE rtsps://example.com/twister.3gp RTSP/2.0
CSeq: 2
User-Agent: PhonyClient/1.2
M->C: RTSP/2.0 200 OK
CSeq: 2
Server: PhonyServer/1.0
Date: Fri, 20 Dec 2013 10:25:33 +0000
Content-Type: application/sdp
Content-Length: 271
Content-Base: rtsps://example.com/twister.3gp/
Expires: Fri, 20 Dec 2013 12:25:33 +0000
v=0
o=- 2890844256 2890842807 IN IP4 192.0.2.5
s=RTSP Session
i=An Example of RTSP Session Usage
e=adm@example.com
c=IN IP4 0.0.0.0
a=control: *
a=range:npt=00:00:00-00:10:34.10
t=0 0
m=audio 0 RTP/SAVP 0
a=control: trackID=1
m=video 0 RTP/SAVP 26
a=control: trackID=4
C->M: SETUP rtsps://example.com/twister.3gp/trackID=1 RTSP/2.0
CSeq: 3
User-Agent: PhonyClient/1.2
Require: play.basic
Transport: RTP/SAVP;unicast;dest_addr=":8000"/":8001";
MIKEY=VGhpcyBpcyB0aGUgZmlyc3Qgc3RyZWFtcyBNSUtFWSBtZXNzYWdl
Accept-Ranges: npt, smpte, clock
Pipelined-Requests: 7654
C->M: SETUP rtsps://example.com/twister.3gp/trackID=4 RTSP/2.0
CSeq: 4
User-Agent: PhonyClient/1.2
Require: play.basic
Transport: RTP/SAVP;unicast;dest_addr=":8002"/":8003";
MIKEY=TUlLRVkgZm9yIHN0cmVhbSB0d2lzdGVyLjNncC90cmFja0lEPTQ=
Accept-Ranges: npt, smpte, clock
Pipelined-Requests: 7654
C->M: PLAY rtsps://example.com/twister.3gp/ RTSP/2.0
CSeq: 5
User-Agent: PhonyClient/1.2
Range: npt=0-
Seek-Style: RAP
Pipelined-Requests: 7654
M->C: RTSP/2.0 200 OK
CSeq: 3
Server: PhonyServer/1.0
Transport: RTP/SAVP;unicast;
dest_addr="192.0.2.53:8000"/"192.0.2.53:8001";
src_addr="198.51.100.5:9000"/"198.51.100.5:9001";
ssrc=93CB001E;
MIKEY=TUlLRVkgUmVzcG9uc2UgdHdpc3Rlci4zZ3AvdHJhY2tJRD0x
Session: OccldOFFq23KwjYpAnBbUr
Expires: Fri, 20 Dec 2013 12:25:34 +0000
Date: Fri, 20 Dec 2013 10:25:34 +0000
Accept-Ranges: npt
Pipelined-Requests: 7654
Media-Properties: Random-Access=0.2, Immutable, Unlimited
M->C: RTSP/2.0 200 OK
CSeq: 4
Server: PhonyServer/1.0
Transport: RTP/SAVP;unicast;
dest_addr="192.0.2.53:8002"/"192.0.2.53:8003;
src_addr="198.51.100.5:9002"/"198.51.100.5:9003";
ssrc=A813FC13;
MIKEY=TUlLRVkgUmVzcG9uc2UgdHdpc3Rlci4zZ3AvdHJhY2tJRD00
Session: OccldOFFq23KwjYpAnBbUr
Expires: Fri, 20 Dec 2013 12:25:34 +0000
Date: Fri, 20 Dec 2013 10:25:34 +0000
Accept-Range: NPT
Pipelined-Requests: 7654
Media-Properties: Random-Access=0.8, Immutable, Unlimited
M->C: RTSP/2.0 200 OK
CSeq: 5
Server: PhonyServer/1.0
Date: Fri, 20 Dec 2013 10:25:34 +0000
Session: OccldOFFq23KwjYpAnBbUr
Range: npt=0-623.10
Seek-Style: RAP
RTP-Info: url="rtsps://example.com/twister.3gp/trackID=4"
ssrc=0D12F123:seq=12345;rtptime=3450012,
url="rtsps://example.com/twister.3gp/trackID=1"
ssrc=4F312DD8:seq=54321;rtptime=2876889;
Pipelined-Requests: 7654
A.4. Media on Demand (Unicast) ๐ฟ
Here's another media-on-demand example with a few more tweaks ๐. Client C wants a movie that's split across two media servers: audio lives on A (audio.example.com) and video lives on V (video.example.com) ๐ง๐บ. The media description is stored on a web server W, and it describes the whole presentation and all its streams, including the codecs that are available and the protocol stack ๐.
In this example, the client only cares about the last part of the movie ๐ฅน.
C->W: GET /twister.sdp HTTP/1.1
Host: www.example.com
Accept: application/sdp
W->C: HTTP/1.1 200 OK
Date: Wed, 23 Jan 2013 15:35:06 GMT
Content-Type: application/sdp
Content-Length: 278
Expires: Thu, 24 Jan 2013 15:35:06 GMT
v=0
o=- 2890844526 2890842807 IN IP4 198.51.100.5
s=RTSP Session
e=adm@example.com
c=IN IP4 0.0.0.0
a=range:npt=00:00:00-01:49:34
t=0 0
m=audio 0 RTP/AVP 0
a=control:rtsp://audio.example.com/twister/audio.en
m=video 0 RTP/AVP 31
a=control:rtsp://video.example.com/twister/video
C->A: SETUP rtsp://audio.example.com/twister/audio.en RTSP/2.0
CSeq: 1
User-Agent: PhonyClient/1.2
Transport: RTP/AVP/UDP;unicast;dest_addr=":3056"/":3057",
RTP/AVP/TCP;unicast;interleaved=0-1
Accept-Ranges: npt, smpte, clock
A->C: RTSP/2.0 200 OK
CSeq: 1
Session: OccldOFFq23KwjYpAnBbUr
Transport: RTP/AVP/UDP;unicast;
dest_addr="192.0.2.53:3056"/"192.0.2.53:3057";
src_addr="198.51.100.5:5000"/"198.51.100.5:5001"
Date: Wed, 23 Jan 2013 15:35:12 +0000
Server: PhonyServer/1.0
Expires: Thu, 24 Jan 2013 15:35:12 +0000
Cache-Control: public
Accept-Ranges: npt, smpte
Media-Properties: Random-Access=0.02, Immutable, Unlimited
C->V: SETUP rtsp://video.example.com/twister/video RTSP/2.0
CSeq: 1
User-Agent: PhonyClient/1.2
Transport: RTP/AVP/UDP;unicast;
dest_addr="192.0.2.53:3058"/"192.0.2.53:3059",
RTP/AVP/TCP;unicast;interleaved=0-1
Accept-Ranges: npt, smpte, clock
V->C: RTSP/2.0 200 OK
CSeq: 1
Session: P5it3pMo6xHkjUcDrNkBjf
Transport: RTP/AVP/UDP;unicast;
dest_addr="192.0.2.53:3058"/"192.0.2.53:3059";
src_addr="198.51.100.5:5002"/"198.51.100.5:5003"
Date: Wed, 23 Jan 2013 15:35:12 +0000
Server: PhonyServer/1.0
Cache-Control: public
Expires: Thu, 24 Jan 2013 15:35:12 +0000
Accept-Ranges: npt, smpte
Media-Properties: Random-Access=1.2, Immutable, Unlimited
C->V: PLAY rtsp://video.example.com/twister/video RTSP/2.0
CSeq: 2
User-Agent: PhonyClient/1.2
Session: P5it3pMo6xHkjUcDrNkBjf
Range: smpte=0:10:00-
V->C: RTSP/2.0 200 OK
CSeq: 2
Session: P5it3pMo6xHkjUcDrNkBjf
Range: smpte=0:10:00-1:49:23
Seek-Style: First-Prior
RTP-Info: url="rtsp://video.example.com/twister/video"
ssrc=A17E189D:seq=12312232;rtptime=78712811
Server: PhonyServer/2.0
Date: Wed, 23 Jan 2013 15:35:13 +0000
C->A: PLAY rtsp://audio.example.com/twister/audio.en RTSP/2.0
CSeq: 2
User-Agent: PhonyClient/1.2
Session: OccldOFFq23KwjYpAnBbUr
Range: smpte=0:10:00-
A->C: RTSP/2.0 200 OK
CSeq: 2
Session: OccldOFFq23KwjYpAnBbUr
Range: smpte=0:10:00-1:49:23
Seek-Style: First-Prior
RTP-Info: url="rtsp://audio.example.com/twister/audio.en"
ssrc=3D124F01:seq=876655;rtptime=1032181
Server: PhonyServer/1.0
Date: Wed, 23 Jan 2013 15:35:13 +0000
C->A: TEARDOWN rtsp://audio.example.com/twister/audio.en RTSP/2.0
CSeq: 3
User-Agent: PhonyClient/1.2
Session: OccldOFFq23KwjYpAnBbUr
A->C: RTSP/2.0 200 OK
CSeq: 3
Server: PhonyServer/1.0
Date: Wed, 23 Jan 2013 15:36:52 +0000
C->V: TEARDOWN rtsp://video.example.com/twister/video RTSP/2.0
CSeq: 3
User-Agent: PhonyClient/1.2
Session: P5it3pMo6xHkjUcDrNkBjf
V->C: RTSP/2.0 200 OK
CSeq: 3
Server: PhonyServer/2.0
Date: Wed, 23 Jan 2013 15:36:52 +0000
Even though the audio and video tracks live on two different servers, they might start at slightly different times and drift apart over time ๐. Don't panic though, the client can do the initial sync of the two media using RTP-Info and Range from the PLAY responses ๐ซถ. And if the two servers are time synchronized, the RTCP packets can keep everything lined up too ๐โจ.
A.5. Single-Stream Container Files ๐
Okay so some RTSP servers treat all files like "container files," but other servers don't really do that concept at all ๐. Because of this, clients need to follow the rules in the session description for Request-URIs instead of assuming one consistent URI works everywhere ๐ . Here's how a multi-stream server might expect a single-stream file to be served ๐:
C->S: DESCRIBE rtsp://foo.example.com/test.wav RTSP/2.0
Accept: application/x-rtsp-mh, application/sdp
CSeq: 1
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 200 OK
CSeq: 1
Content-base: rtsp://foo.example.com/test.wav/
Content-type: application/sdp
Content-length: 163
Server: PhonyServer/1.0
Date: Wed, 23 Jan 2013 15:36:52 +0000
Expires: Thu, 24 Jan 2013 15:36:52 +0000
v=0
o=- 872653257 872653257 IN IP4 192.0.2.5
s=mu-law wave file
i=audio test
c=IN IP4 0.0.0.0
t=0 0
a=control: *
m=audio 0 RTP/AVP 0
a=control:streamid=0
C->S: SETUP rtsp://foo.example.com/test.wav/streamid=0 RTSP/2.0
Transport: RTP/AVP/UDP;unicast;
dest_addr=":6970"/":6971";mode="PLAY"
CSeq: 2
User-Agent: PhonyClient/1.2
Accept-Ranges: npt, smpte, clock
S->C: RTSP/2.0 200 OK
Transport: RTP/AVP/UDP;unicast;
dest_addr="192.0.2.53:6970"/"192.0.2.53:6971";
src_addr="198.51.100.5:6970"/"198.51.100.5:6971";
mode="PLAY";ssrc=EAB98712
CSeq: 2
Session: NYkqQYKk0bb12BY3goyoyO
Expires: Thu, 24 Jan 2013 15:36:52 +0000
Server: PhonyServer/1.0
Date: Wed, 23 Jan 2013 15:36:52 +0000
Accept-Ranges: npt
Media-Properties: Random-Access=0.5, Immutable, Unlimited
C->S: PLAY rtsp://foo.example.com/test.wav/ RTSP/2.0
CSeq: 3
User-Agent: PhonyClient/1.2
Session: NYkqQYKk0bb12BY3goyoyO
S->C: RTSP/2.0 200 OK
CSeq: 3
Server: PhonyServer/1.0
Date: Wed, 23 Jan 2013 15:36:52 +0000
Session: NYkqQYKk0bb12BY3goyoyO
Range: npt=0-600
Seek-Style: RAP
RTP-Info: url="rtsp://foo.example.com/test.wav/streamid=0"
ssrc=0D12F123:seq=981888;rtptime=3781123
Note the different URI in the SETUP command and then the switch back to the aggregate URI in the PLAY command ๐. This makes complete sense when there are multiple streams with aggregate control, but it's less than intuitive in the special case where the number of streams is one. However, the server has declared the aggregated control URI in the SDP, so this is legal โ .
In this case, it is also required that servers accept implementations that use the non-aggregated interpretation and use the individual media URI, like this:
C->S: PLAY rtsp://example.com/test.wav/streamid=0 RTSP/2.0
CSeq: 3
User-Agent: PhonyClient/1.2
Session: NYkqQYKk0bb12BY3goyoyO
A.6. Live Media Presentation Using Multicast ๐ถ
The media server M chooses the multicast address and port ๐ธ. Here, it is assumed that the web server only contains a pointer to the full description, while the media server M maintains the full description ๐ง.
C->W: GET /sessions.html HTTP/1.1
Host: www.example.com
W->C: HTTP/1.1 200 OK
Content-Type: text/html
<html>
...
<a href "rtsp://live.example.com/concert/audio">
Streamed Live Music performance </a>
...
</html>
C->M: DESCRIBE rtsp://live.example.com/concert/audio RTSP/2.0
CSeq: 1
Supported: play.basic, play.scale
User-Agent: PhonyClient/1.2
M->C: RTSP/2.0 200 OK
CSeq: 1
Content-Type: application/sdp
Content-Length: 183
Server: PhonyServer/1.0
Date: Wed, 23 Jan 2013 15:36:52 +0000
Supported: play.basic
v=0
o=- 2890844526 2890842807 IN IP4 192.0.2.5
s=RTSP Session
t=0 0
m=audio 3456 RTP/AVP 0
c=IN IP4 233.252.0.54/16
a=control: rtsp://live.example.com/concert/audio
a=range:npt=0-
C->M: SETUP rtsp://live.example.com/concert/audio RTSP/2.0
CSeq: 2
Transport: RTP/AVP;multicast;
dest_addr="233.252.0.54:3456"/"233.252.0.54:3457";ttl=16
Accept-Ranges: npt, smpte, clock
User-Agent: PhonyClient/1.2
M->C: RTSP/2.0 200 OK
CSeq: 2
Server: PhonyServer/1.0
Date: Wed, 23 Jan 2013 15:36:52 +0000
Transport: RTP/AVP;multicast;
dest_addr="233.252.0.54:3456"/"233.252.0.54:3457";ttl=16
;ssrc=4D12AB92/0DF876A3
Session: qHj4jidpmF6zy9v9tNbtxr
Accept-Ranges: npt, clock
Media-Properties: No-Seeking, Time-Progressing, Time-Duration=0
C->M: PLAY rtsp://live.example.com/concert/audio RTSP/2.0
CSeq: 3
Session: qHj4jidpmF6zy9v9tNbtxr
User-Agent: PhonyClient/1.2
M->C: RTSP/2.0 200 OK
CSeq: 3
Server: PhonyServer/1.0
Date: Wed, 23 Jan 2013 15:36:52 +0000
Session: qHj4jidpmF6zy9v9tNbtxr
Seek-Style: Next
Range:npt=1256-
RTP-Info: url="rtsp://live.example.com/concert/audio"
ssrc=0D12F123:seq=1473; rtptime=80000
A.7. Capability Negotiation ๐ง
This example shows how the client and server figure out whether they can support a special feature, in this case, "play.scale" โฉ. The server, through the client request and the included Supported header, learns that the client supports RTSP 2.0 and also supports the playback time scaling feature of RTSP. The server's response contains the following feature-related information for the client: it supports the basic media delivery functions (play.basic), the extended functionality of time scaling of content (play.scale), and one "example.com" proprietary feature (com.example.flight) ๐ฆ. The client also learns the methods supported (Public header) by the server for the indicated resource ๐.
C->S: OPTIONS rtsp://media.example.com/movie/twister.3gp RTSP/2.0
CSeq: 1
Supported: play.basic, play.scale
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 200 OK
CSeq: 1
Public:OPTIONS,SETUP,PLAY,PAUSE,TEARDOWN,DESCRIBE,GET_PARAMETER
Allow: OPTIONS, SETUP, PLAY, PAUSE, TEARDOWN, DESCRIBE
Server: PhonyServer/2.0
Supported: play.basic, play.scale, com.example.flight
When the client sends its SETUP request, it tells the server that it requires support of the play.scale feature for this session by including the Require header ๐.
C->S: SETUP rtsp://media.example.com/twister.3gp/trackID=1 RTSP/2.0
CSeq: 3
User-Agent: PhonyClient/1.2
Transport: RTP/AVP/UDP;unicast;
dest_addr="192.0.2.53:3056"/"192.0.2.53:3057",
RTP/AVP/TCP;unicast;interleaved=0-1
Require: play.scale
Accept-Ranges: npt, smpte, clock
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 200 OK
CSeq: 3
Session: OccldOFFq23KwjYpAnBbUr
Transport: RTP/AVP/UDP;unicast;
dest_addr="192.0.2.53:3056"/"192.0.2.53:3057";
src_addr="198.51.100.5:5000"/"198.51.100.5:5001"
Server: PhonyServer/2.0
Accept-Ranges: npt, smpte
Media-Properties: Random-Access=0.8, Immutable, Unlimited
Appendix B. RTSP Protocol State Machine ๐ค
The RTSP session state machine describes how the protocol behaves, from RTSP session initialization all the way through RTSP session termination ๐ฌ. It's probably easiest to think of this as the server's state, and then view the client as needing to track what it believes the server's state will be, based on the RTSP messages it sends or receives ๐งฉ. So in most cases, the state tables below can be read as: if the client does X, and assuming it fulfills any prerequisite(s), the (server) state will move to the new state and the indicated response will be returned. There are also server-to-client notifications or requests, though. For those, the action describes what notification or request will occur, its requisites, what new state will result after the server has received the response, and how the client should respond to the action ๐ฌ.
The State machine is defined on a per-session basis, which is uniquely identified by the RTSP session identifier ๐. The session may contain one or more media streams, depending on state. If a single media stream is part of the session, it is in non-aggregated control. If two or more are part of the session, it is in aggregated control.
The below state machine is an informative description of the protocol's behavior. In case of ambiguity with the earlier parts of this specification, the description in the earlier parts takes precedence ๐.
B.1. States ๐ฆ
The state machine contains three states, described below. For each state, there's a table that shows which requests and events are allowed and whether they will result in a state change ๐ .
- Init: Initial state, no session exists.
- Ready: Session is ready to start playing.
- Play: Session is playing, i.e., sending media-stream data in the direction
S->C.
B.2. State Variables ๐งฎ
This representation of the state machine needs more than its state to work. A small number of variables are also needed, and they're explained below.
- NRM: The number of media streams that are part of this session.
- RP: Resume point, the point in the presentation time line at which a request to continue playing will resume from. A time format for the variable is not mandated.
B.3. Abbreviations ๐ค
To make the state tables more compact, a number of abbreviations are used, which are explained below.
- IFI: IF Implemented.
- md: Media.
- PP: Pause Point, the point in the presentation timeline at which the presentation was paused.
- Prs: Presentation, the complete multimedia presentation.
- RedP: Redirect Point, the point in the presentation timeline at which a REDIRECT was specified to occur.
- SES: Session.
B.4. State Tables ๐
This section contains a table for each state. Each table contains all the requests and events on which that state is allowed to act. The events that are method names are, unless noted, requests with the given method in the direction client to server (C->S). In some cases, there exist one or more requisites. The response column tells what type of response actions should be performed. Possible actions that are requested for an event include: response codes (e.g., 200), headers that need to be included in the response, setting of state variables, or settings of other session-related parameters. The new state column tells which state the state machine changes to ๐.
Okay bestie, so a valid request that meets its requisites normally gets a 2xx (SUCCESS) ๐ , unless the response column says something different for that event. Those exceptions get whatever the column lists ๐. If a request doesn't meet its requisite, is erroneous, or runs into some other kind of error, the right response code gets sent ๐.
A 4xx leaves the session state alone โจ. A 3rr response ends the session and moves its state to Init ๐, but there are restrictions on when a 3rr can be used, so no throwing it around ๐ญ. A 304 means zero state change ๐ซถ. A 5xx also doesn't change the session state, unless the error is impossible to recover from, and then the session ends ๐ฅ. If it's unclear whether an error was unrecoverable, the client is required to test ๐งช. If the next request after a 5xx gets a 454 (Session Not Found), the client knows the session has ended ๐. Any request that can't be answered within the time defined in Section 10.4 must get a 100 response ๐ธ.
The server times the session out after the period given in the SETUP response, if it doesn't detect any activity from the client โฐ. So every state except Init has a timeout event ๐ฆ.
When NRM = 1, the presentation URI is the same as the media URI or a specified presentation URI ๐. When NRM > 1, the presentation URI must be something other than any of the media in the session ๐. This applies to all states ๐.
Now the non-state-machine-changing events, which are the ones that don't touch the state machine or the state variables at all ๐ง:
+---------------+-----------------+---------------------------------+
| Event | Prerequisite | Response |
+---------------+-----------------+---------------------------------+
| DESCRIBE | Needs REDIRECT | 3rr, Redirect |
| | | |
| DESCRIBE | | 200, Session description |
| | | |
| OPTIONS | Session ID | 200, Reset session timeout |
| | | timer |
| | | |
| OPTIONS | | 200 |
| | | |
| SET_PARAMETER | Valid parameter | 200, change value of parameter |
| | | |
| GET_PARAMETER | Valid parameter | 200, return value of parameter |
+---------------+-----------------+---------------------------------+
Table 9: Non-State-Machine Changing Events
These methods don't mess with the state machine or the state variables ๐ โโ๏ธ. BUT some of them do change other session-related parameters ๐. For example, SET_PARAMETER sets whatever parameter(s) are listed in its body ๐ฏ. Also, every one of these methods that allows the Session header will also refresh the keep-alive timer for the session โฒ๏ธ.
Next up is the Init state, which is the starting point of the whole state machine ๐ช. Table 10 shows it:
+------------------+----------------+-----------+-------------------+
| Action | Requisite | New State | Response |
+------------------+----------------+-----------+-------------------+
| SETUP | | Ready | NRM=1, RP=0.0 |
| | | | |
| SETUP | Needs Redirect | Init | 3rr Redirect |
| | | | |
| S -> C: REDIRECT | No Session hdr | Init | Terminate all SES |
+------------------+----------------+-----------+-------------------+
Table 10: State: Init
Init can only be left by processing a correct SETUP request ๐. As you can see in the table, a correct request also sets the two state variables ๐ง . The table also shows that a correct SETUP can sometimes get redirected to another URI or server with a 3rr response ๐.
Now the Ready state, where things get spicy ๐ถ๏ธ. Table 11 has it all:
+-------------+------------------------+---------+------------------+
| Action | Requisite | New | Response |
| | | State | |
+-------------+------------------------+---------+------------------+
| SETUP | New URI | Ready | NRM +=1 |
| | | | |
| SETUP | URI Setup prior | Ready | Change transport |
| | | | param |
| | | | |
| TEARDOWN | Prs URI, | Init | No session hdr, |
| | | | NRM = 0 |
| | | | |
| TEARDOWN | md URI,NRM=1 | Init | No Session hdr, |
| | | | NRM = 0 |
| | | | |
| TEARDOWN | md URI,NRM>1 | Ready | Session hdr, NRM |
| | | | -= 1 |
| | | | |
| PLAY | Prs URI, No range | Play | Play from RP |
| | | | |
| PLAY | Prs URI, Range | Play | According to |
| | | | range |
| | | | |
| PLAY | md URI, NRM=1, Range | Play | According to |
| | | | range |
| | | | |
| PLAY | md URI, NRM=1 | Play | Play from RP |
| | | | |
| PAUSE | Prs URI | Ready | Return PP |
| | | | |
| SC:REDIRECT | Terminate-Reason | Ready | Set RedP |
| | | | |
| SC:REDIRECT | No Terminate-Reason | Init | Session is |
| | time parameter | | removed |
| | | | |
| Timeout | | Init | |
| | | | |
| RedP | | Init | TEARDOWN of |
| reached | | | session |
+-------------+------------------------+---------+------------------+
Table 11: State: Ready
In Ready, a bunch of actions depend on how many media streams (NRM) are in the session, which is basically aggregated vs. non-aggregated control ๐ญ. A SETUP here can either add one more media stream to the session, or, if that media stream (same URI) is already part of the session, change its transport parameters ๐ง. TEARDOWN is picky: it depends on both the Request-URI and the number of media streams in the session ๐ง. If the Request-URI is the presentation URI, the whole session gets torn down ๐ฅ. If a media URI is used in a TEARDOWN and more than one media stream exists, the session sticks around and a session header comes back in the response ๐. If only a single media stream is left and you TEARDOWN with a media URI, the session is removed ๐. And whatever number of media streams is left after a teardown decides the new state ๐ฏ.
Last but not least, the Play state, Table 12 ๐ฌ:
+----------------+-----------------------+--------+-----------------+
| Action | Requisite | New | Response |
| | | State | |
+----------------+-----------------------+--------+-----------------+
| PAUSE | Prs URI | Ready | Set RP to |
| | | | present point |
| | | | |
| End of media | All media | Play | Set RP = End of |
| | | | media |
| | | | |
| End of range | | Play | Set RP = End of |
| | | | range |
| | | | |
| PLAY | Prs URI, No range | Play | Play from |
| | | | present point |
| | | | |
| PLAY | Prs URI, Range | Play | According to |
| | | | range |
| | | | |
| SC:PLAY_NOTIFY | | Play | 200 |
| | | | |
| SETUP | New URI | Play | 455 |
| | | | |
| SETUP | md URI | Play | 455 |
| | | | |
| SETUP | md URI, IFI | Play | Change |
| | | | transport param.|
| | | | |
| TEARDOWN | Prs URI | Init | No session hdr |
| | | | |
| TEARDOWN | md URI,NRM=1 | Init | No Session hdr, |
| | | | NRM=0 |
| | | | |
| TEARDOWN | md URI | Play | 455 |
| | | | |
| SC:REDIRECT | Terminate Reason with | Play | Set RedP |
| | Time parameter | | |
| | | | |
| SC:REDIRECT | | Init | Session is |
| | | | removed |
| | | | |
| RedP reached | | Init | TEARDOWN of |
| | | | session |
| | | | |
| Timeout | | Init | Stop Media |
| | | | playout |
+----------------+-----------------------+--------+-----------------+
Table 12: State: Play
The Play state table (Table 12) has a bunch of requests that need a presentation URI (labeled as Prs URI) to work on ๐. The presentation URI has to be used as the Request-URI ๐
, and that's because non-aggregated stream control is excluded in sessions with more than one media stream ๐ฆ.
To avoid inconsistencies between the client and server, automatic state transitions are avoided ๐ซถ. You can see this with, like, an "End of media" event when all the media is done playing but the session is still chilling in Play state ๐ญ. An explicit PAUSE request needs to be sent to change the state to Ready. It may appear that there exist automatic transitions in "RedP reached" and "PP reached" ๐. However, they are requested and acknowledged before they take place โจ. The time at which the transition will happen is known by looking at the Terminate-Reason header's time parameter and Range header, respectively. If the client sends a request close in time to these transitions, it needs to be prepared for receiving error messages, as the state may or may not have changed ๐.
Appendix C. Media-Transport Alternatives ๐ฆ
This section defines how certain combinations of protocols, profiles, and lower transports are used ๐. This includes the usage of the Transport header's source and destination address parameters: src_addr and dest_addr ๐.
C.1. RTP ๐
This section defines the interaction of RTSP with respect to the RTP protocol [RFC3550]. It also defines any necessary media-transport signaling with regard to RTP ๐ง.
The available RTP profiles and lower-layer transports are described below, along with rules on signaling the available combinations ๐ .
C.1.1. AVP ๐ธ
The usage of the "RTP Profile for Audio and Video Conferences with Minimal Control" [RFC3551] when using RTP for media transport over different lower-layer transport protocols is defined below in regard to RTSP โจ.
One such case is defined within this document: the use of embedded (interleaved) binary data as defined in Section 14. The usage of this method is indicated by including the interleaved parameter ๐ซถ.
When using embedded binary data, src_addr and dest_addr MUST NOT be used. This addressing and multiplexing is used as defined with use of channel numbers and the interleaved parameter ๐.
C.1.2. AVP/UDP ๐ฆ
This part describes the sending of RTP [RFC3550] over lower-transport-layer UDP [RFC768] according to the profile "RTP Profile for Audio and Video Conferences with Minimal Control" defined in [RFC3551]. Implementations of RTP/AVP/UDP MUST implement RTCP (Appendix C.1.6). This profile requires one or two unidirectional or bidirectional UDP flows per media stream. The first UDP flow is for RTP and the second is for RTCP. Multiplexing of RTP and RTCP (Appendix C.1.6.4) MAY be used, in which case, a single UDP flow is used for both parts ๐ฅ. Embedding of RTP data with the RTSP messages, in accordance with Section 14, SHOULD NOT be performed when RTSP messages are transported over unreliable transport protocols, like UDP [RFC768] ๐ฌ.
The RTP/UDP and RTCP/UDP flows can be established using the Transport header's src_addr and dest_addr parameters ๐.
In RTSP PLAY mode, the transmission of RTP packets from client to server is unspecified. The behavior in regard to such RTP packets MAY be defined in future ๐ฎ.
The src_addr and dest_addr parameters are used in the following way for media delivery and playback mode, i.e., Mode=PLAY:
- The
src_addranddest_addrparameters MUST contain either 1 or 2 address specifications. Note that two address specifications MAY be provided even if RTP and RTCP multiplexing is negotiated ๐. - Each address specification for RTP/AVP/UDP or RTP/AVP/TCP MUST contain either:
- both an address and a port number, or
- a port number without an address.
- The first address specification given in either of the parameters applies to the RTP stream. The second specification, if present, applies to the RTCP stream, unless in the case RTP and RTCP multiplexing is negotiated where both RTP and RTCP will use the first specification ๐ท.
- The RTP/UDP packets from the server to the client MUST be sent to the address and port given by the first address specification of the
dest_addrparameter ๐. - The RTCP/UDP packets from the server to the client MUST be sent to the address and port given by the second address specification of the
dest_addrparameter, unless RTP and RTCP multiplexing has been negotiated, in which case RTCP MUST be sent to the first address specification. If no second pair is specified and RTP and RTCP multiplexing has not been negotiated, RTCP MUST NOT be sent ๐ซ . - The RTCP/UDP packets from the client to the server MUST be sent to the address and port given by the second address specification of the
src_addrparameter, unless RTP and RTCP multiplexing has been negotiated, in which case RTCP MUST be sent to the first address specification. If no second pair is specified and RTP and RTCP multiplexing has not been negotiated, RTCP MUST NOT be sent ๐. - The RTP/UDP packets from the client to the server MUST be sent to the address and port given by the first address specification of the
src_addrparameter ๐ . - RTP and RTCP packets SHOULD be sent from the corresponding receiver port, i.e., RTCP packets from the server should be sent from the
src_addrparameters second address port pair, unless RTP and RTCP multiplexing has been negotiated in which case the first address port pair is used ๐ฅน.
C.1.3. AVPF/UDP ๐
The RTP profile "Extended RTP Profile for RTCP-based Feedback (RTP/AVPF)" [RFC4585] MAY be used as RTP profiles in sessions using RTP. All that is defined for AVP MUST also apply for AVPF โจ.
The usage of AVPF is indicated by the media initialization protocol used. In the case of SDP, it is indicated by media lines (m=) containing the profile RTP/AVPF. That SDP MAY also contain further AVPF-related SDP attributes configuring the AVPF session regarding reporting interval and feedback messages to be used [RFC4585]. This configuration MUST be followed ๐.
C.1.4. SAVP/UDP ๐
The RTP profile "The Secure Real-time Transport Protocol (SRTP)" [RFC3711] is an RTP profile (SAVP) that MAY be used in RTSP sessions using RTP. All that is defined for AVP MUST also apply for SAVP ๐.
The usage of SRTP requires that a security context be established. The default key-management unless otherwise signaled SHALL be MIKEY in RSA-R mode as defined in Appendix C.1.4.1 and not according to the procedure defined in "Key Management Extensions for Session Description Protocol (SDP) and Real Time Streaming Protocol (RTSP)" [RFC4567]. The reason is that RFC 4567 sends the initial MIKEY message in SDP, thus, both requiring the usage of the DESCRIBE method and forcing the server to keep state for clients performing DESCRIBE in anticipation that they might require key management ๐ง .
MIKEY is selected as the default method for establishing SRTP cryptographic context within an RTSP session, as it can be embedded in the RTSP messages while still ensuring confidentiality of content of the keying material, even when using hop-by-hop TLS security for the RTSP messages ๐ก๏ธ. This method also supports pipelining of the RTSP messages ๐.
C.1.4.1. MIKEY Key Establishment โจ
okay so this is the bit where we set up the SRTP crypto context, and it happens inside the client's SETUP request ๐. the server's reply to that SETUP carries the MIKEY response back, so the keys and the media stream get set up at the same time, which is so efficient, bestie ๐ . using MIKEY's RSA-R mode [RFC4738] means the client gets to be the initiator, but the server still gets to pick the parameters to match the actual media stream ๐
the whole crypto setup goes down in this order:
- the client figures out that SAVP or SAVPF is the way to go, based on the media-description format (like SDP). if no other key-management method is explicitly signaled, then MIKEY SHALL be used as defined here. RTSP only defines SRTP with MIKEY keys set up the way this section describes. future documents might explain how an RTSP implementation handles SDP that signals some other key mechanism. that includes [RFC4567], which is NOT defined for use in RTSP 2.0 in this document ๐ง
- the client SHALL set up a TLS connection for RTSP messages, either directly or hop-by-hop with the server. if hop-by-hop TLS is used, the User method SHALL be indicated in the Accept-Credentials header. heads up, though: going hop-by-hop lets a proxy slide in as a man in the middle ๐ณ. the proxy could also do that during the MIKEY exchange by handing over its own certificate instead of the server's, in the Connection-Credentials header. so the client SHALL validate the server certificate. no skipping this one, periodt ๐
- the client grabs the server's certificate, either from a direct TLS connection or hop-by-hop from a Connection-Credentials header. then it checks that the certificate is valid and actually belongs to the server ๐
- the client builds the MIKEY Initiator message using RSA-R mode in unicast mode, as specified in [RFC4738]. the client SHOULD use the same certificate for TLS and MIKEY so the server can bind the two together ๐ซถ. the client's certificate SHALL be included in the MIKEY message, and the client SHALL indicate its SRTP capabilities in it too โจ
- the MIKEY message from the step before gets base64-encoded [RFC4648] and becomes the value of the MIKEY parameter. that parameter goes in the transport specification(s) that use an SRTP-based profile (SAVP, SAVPF) in the SETUP request ๐
- any proxy that sees the MIKEY parameter SHALL forward it without changing it ๐. a proxy that has to understand the Transport specifications will need to get SAVP/SAVPF with MIKEY so the default keying for SRTP-protected media streams works. if a proxy doesn't support SAVP/SAVPF with MIKEY, it will throw out the whole transport specification ๐ญ. most proxies can easily support SAVP and SAVPF with MIKEY, tbh. and if a client runs into a proxy that doesn't support SAVP/SAVPF with MIKEY, the client should try bypassing that proxy ๐ฆ
- when the server gets the SETUP request, it has to decide which transport specification to use if the client included more than one ๐. when it's figuring out which ones it supports and prefers, the server SHOULD decode the MIKEY message so it can take the embedded SRTP parameters into account. and if every transport spec requires SRTP but there's no MIKEY parameter or other supported keying method included, the server SHALL respond with 403 (Forbidden) ๐
- once the server is generating a response, one of these outcomes can happen:
- a transport spec that doesn't use SRTP and MIKEY gets selected. so the response will NOT contain any MIKEY parameters ๐ธ
- a transport spec that uses SRTP and MIKEY gets selected, but there's an error in the MIKEY processing. then an RTSP error response code of 466 (Key Management Error) SHALL be used. a MIKEY message describing the error MAY be included ๐
- a transport spec that uses SRTP and MIKEY gets selected, and a MIKEY response message can be created. the server SHOULD use the same certificate for TLS and in MIKEY so the client can bind the two together. if a different certificate is used, it SHALL be included in the MIKEY message. it is RECOMMENDED that the envelope key-cache type be set to 'Cache' and that a single envelope key gets reused for all MIKEY messages to the client ๐. that message goes in the MIKEY parameter part of the single selected transport specification in the SETUP response. the server sets the SRTP parameters as it prefers for this media stream, as long as they stay within the range the client supports โจ
- the server sends the SETUP response back to the client ๐ฎ
- the client gets the SETUP response. if the response code says the request succeeded, it decodes the MIKEY message and sets up the SRTP cryptographic context from the parameters in the MIKEY response ๐
in the method above, the client's certificate can be self-signed, as long as the client's identity doesn't need to be authenticated ๐ง. the only goal in that case is making sure that the RTSP signaling client is the same one receiving the SRTP security context. that's it, that's the whole vibe ๐
C.1.5. SAVPF/UDP ๐ฆ
the RTP profile "Extended Secure RTP Profile for Real-time Transport Control Protocol (RTCP)-Based Feedback (RTP/SAVPF)" [RFC5124] is an RTP profile (SAVPF) that MAY be used in RTSP sessions using RTP. everything that's defined for AVPF MUST also apply to SAVPF, so no exceptions, bestie ๐
using SRTP means a cryptographic context has to be set up first ๐. the default way to set up that security association is MIKEY [RFC3830] with RTSP, the way it's laid out in Appendix C.1.4.1 ๐
C.1.6. RTCP Usage with RTSP ๐
RTCP has a few different jobs when RTP is used for media transport, as explained below. so if an RTSP agent handles RTP, RTCP MUST be supported. no way around it ๐
C.1.6.1. Media Synchronization โฑ๏ธ
RTCP handles media synchronization and clock-drift compensation ๐. the initial media synchronization is available from the RTP-Info header. but to deal with any clock drift between the media streams, RTCP is needed. so the RTP-Info header gets you started, and RTCP keeps everything in sync after that โจ
C.1.6.2. RTSP Session Keep-Alive ๐ซง
RTCP traffic from the RTSP client to the RTSP server MUST function as a keep-alive ๐. this means an RTSP server that supports RTP uses the RTCP packets it receives as a sign that the client wants the related RTSP session kept alive ๐
C.1.6.3. Bitrate Adaption ๐
RTCP Receiver reports and any other feedback from the client MUST be used to adapt the bitrate used over the transport in all cases where RTP is sent over UDP ๐ซถ. an RTP sender without reserved resources MUST NOT use more than its fair share of the available resources. one way to tell is to compare, over the short-to-medium term (a few seconds), the bitrate being used, and then adjust it so the RTP sender lands at a bitrate that's comparable to what a TCP sender would average over the same path ๐ฆ
to make sure the implementation's adaptation mechanism has a well-defined outer envelope, every implementation using a non-congestion-controlled unicast transport protocol, like UDP, MUST implement "Multimedia Congestion Control: Circuit Breakers for Unicast RTP Sessions" [RTP-CIRCUIT-BREAKERS] ๐. no skipping the circuit breakers, iykyk ๐ฅ
C.1.6.4. RTP and RTCP Multiplexing ๐ง
RTSP can be used to negotiate RTP and RTCP multiplexing, as described in [RFC5761] ๐. this lets servers and clients use fewer resources in the session, because each media stream only needs one underlying transport stream instead of two for RTP and RTCP. that cuts down on server-port consumption, and it also lowers the state and keep-alive work when you're going across NATs [RFC2663] ๐ธ
content has to be prepared with a little thought for RTP and RTCP multiplexing ๐. the main thing is making sure the RTP payload types don't collide with the RTCP packet types. this option will probably need explicit support from the content, unless the server can remap the RTP payload types and that's correctly reflected in the session description. beyond that, supporting this feature should come at little cost and give a lot back ๐
it is recommended that, if the content and server support RTP and RTCP multiplexing, this gets indicated in the session description. for example, you could use the SDP attribute "a=rtcp-mux" โจ. if the SDP message contains the "a=rtcp-mux" attribute for a media stream, the server MUST support RTP and RTCP multiplexing ๐. if it's indicated or the client just wants it, the client can include the Transport parameter "RTCP-mux" in any transport specification where it wants to use "RTCP-mux". the server will indicate whether it supports "RTCP-mux". and Servers and Clients SHOULD support RTP and RTCP multiplexing ๐ซถ
for capability exchange, there's an RTSP feature tag for RTP and RTCP multiplexing: "setup.rtp.rtcp.mux" ๐
now, to lower the risk of negotiation failing while using RTP and RTCP multiplexing, here are some recommendations ๐. if the session description explicitly says it supports this ("a=rtcp-mux" in SDP), then an RTSP agent can safely create a SETUP request with a transport specification that has only a single "dest_addr" parameter address specification ๐ . but if there's no explicit indication, then even if the server puts the feature tag "setup.rtp.rtcp.mux" in a Supported header, or the client puts it in the Required header of the SETUP request, the media resource might still not support RTP and RTCP multiplexing ๐ณ. so to boost the odds of a successful negotiation, the RTSP agent is recommended to include two "dest_addr" parameter address specifications in the first SETUP request, or the first set of them if pipelining is used, for any media resource aggregate ๐ฆ. that way the RTSP server can accept RTP and RTCP multiplexing and only use the first address specification, or, if it can't, use both. once the RTSP agent gets the response for a successful RTP and RTCP multiplexing negotiation, it can release the resources tied to the second address specification ๐ง
C.2. RTP over TCP ๐
transporting RTP over TCP can be done in two ways: over independent TCP connections using [RFC4571], or interleaved in the RTSP connection ๐. either way, the protocol MUST be "rtp" and the lower layer MUST be TCP. the profile can be any of the ones specified above: AVP, AVPF, SAVP, or SAVPF โจ
C.2.1. Interleaved RTP over TCP ๐ซง
embedded (interleaved) binary data can be carried on the RTSP connection, as specified in Section 14 ๐. when you use this declared combination of interleaved binary data, the RTSP messages MUST be transported over TCP. TLS may or may not be used. if TLS is used, both the RTSP messages and the binary data get protected by TLS ๐
one thing to keep in mind, though: this means all the media streams will go through any proxy ๐. using independent TCP connections can avoid that issue ๐ฆ
C.2.2. RTP over Independent TCP ๐ฆโจ
okay so this section is all about sending RTP [RFC3550] over TCP [RFC793] using the framing from [RFC4571], which is literally the "Framing Real-time Transport Protocol (RTP) and RTP Control Protocol (RTCP) Packets over Connection-Oriented Transport" doc ๐ . It takes the RTP/AVP/TCP idea from SIP/SDP [RFC4145] and makes it work with RTSP, and bestie, it's giving clean adaptation energy ๐ธ
A client says it can do RTP over independent TCP by putting an RTP/AVP/TCP transport option with no interleaved parameter in the Transport line of a SETUP request. That option MUST include the "unicast" parameter. No cap, this is non-negotiable ๐ซถ
If the client wants RTP with RTCP, it needs two address specs in the "dest_addr" parameter. If it only wants RTP without RTCP, one address spec is enough. If the client wants to multiplex RTP and RTCP on a single transport flow (see Appendix C.1.6.4) ๐, it includes the "RTCP-mux" transport parameter, and then it's one or two address specs in "dest_addr". Two address specs are allowed so negotiation still works when the server or content can't handle RTP and RTCP multiplexing. Ordering of dest_addr ports follows the RTP/AVP/UDP rules, so no dramatic reshuffling needed ๐ง
Now the client might want to be the active party when it starts the TCP connection. It MAY set the setup parameter (see Section 18.54) to "active" on the Transport line, or it MAY just leave setup out, since active is the default. If the client goes active, the ports in its "dest_addr" address specs MUST be 9 (the discard port) ๐
If the client wants the passive role instead, it MUST set setup to "passive". If it can do either role, it MUST set setup to "actpass" ๐. Either way, the "dest_addr" port for RTP MUST be the TCP port the client is waiting on for the RTP connection, and the port for RTCP MUST be the TCP port the client is waiting on for the RTCP connection. If the client is multiplexing RTP and RTCP on one flow, it includes "RTCP-mux" with one or two "dest_addr" address specs, same as above ๐ฆ
When a server gets a non-interleaved RTP/AVP/TCP SETUP and decides to accept it, the 2xx reply MUST include a Transport option saying RTP/AVP/TCP, without interleaved and with unicast. The "dest_addr" value MUST be echoed from the client's request, unless the destination address (only the port) wasn't provided. In that case the server MAY put in the source address of the RTSP TCP connection with the port number unchanged โจ
The server reply MUST also set setup on the Transport line to show its role. "active" is allowed if the client said "passive" or "actpass", and "passive" is allowed if the client said "active" or "actpass" ๐
If the server goes passive, the "src_addr" in the reply MUST show the ports it's willing to receive TCP connections on for RTP, and also for RTCP if the client asked for two dest_addr specs. If the server goes active, the ports in its "src_addr" address specs MUST be 9 ๐. The server MAY use the "ssrc" parameter, following Section 18.54. It only sets one address spec if the client sent just one, or if RTP and RTCP multiplexing was requested and the server accepted it. Port ordering for "src_addr" follows the RTP/AVP/UDP rules ๐
Servers MUST support the passive role and MAY support the active role. Servers with a public IP take the passive role, which gives clients behind NATs and firewalls a better shot at connecting by reaching out to the server themselves. So clients are RECOMMENDED to take the active role ๐ซถ๐ฅ
After a 2xx reply to a SETUP for a non-interleaved RTP/AVP/TCP stream, the active party SHOULD start the TCP connection as soon as possible ๐. The client MUST NOT send PLAY until all the TCP connections negotiated with SETUP for the session are established. If the server gets a PLAY while some TCP connections still aren't up, it MUST reply with 464 (Data Transport Not Ready Yet) (Section 17.4.28) ๐
Once PLAY happens for media over non-interleaved RTP/AVP/TCP, media flows from server to client over the RTP TCP connection, and RTCP goes both ways over the RTCP TCP connection. Unless RTP and RTCP multiplexing was negotiated, in which case they share one common TCP connection ๐ธ. Just like RTP/UDP, client-to-server traffic on an RTP-only TCP session is unspecified by this memo. The packets on these connections MUST be framed using [RFC4571], NOT the interleaving framing over the RTSP connection from Section 14 ๐ โโ๏ธ
A successful PAUSE for media on RTP/AVP/TCP pauses the packet flow but keeps the connections open ๐. A successful TEARDOWN means the RTSP client should close the RTP and RTCP TCP connections as soon as possible ๐
Now here's a sticky one. A later SETUP for a URI already set up in the session with RTP/AVP/TCP is kinda ambiguous. Does the client want fresh TCP connections for RTP or RTCP, or does it want to keep using the existing ones? ๐ค The client SHOULD use the "connection" parameter (Section 18.54) on the Transport line to clear this up: "new" if it needs new connections, "existing" if it wants the old ones. After a 2xx reply to a SETUP for new connections, parties should close the old connections, but only after waiting a suitable period for stray RTP or RTCP packets to arrive ๐ฆ
SRTP is a whole different vibe. Using SAVP or SAVPF profiles requires a security association to be set up first. The default way to do that is MIKEY [RFC3830] with RTSP, as defined in Appendix C.1.4.1 ๐โจ
Here's a rewritten version of the "Media on Demand" example (Appendix A.1) showing RTP/AVP/TCP non-interleaved in action ๐ฌ๐ฟ
C->M: DESCRIBE rtsp://example.com/twister.3gp RTSP/2.0
CSeq: 1
User-Agent: PhonyClient/1.2
M->C: RTSP/2.0 200 OK
CSeq: 1
Server: PhonyServer/1.0
Date: Wed, 23 Jan 2013 15:36:52 +0000
Content-Type: application/sdp
Content-Length: 227
Content-Base: rtsp://example.com/twister.3gp/
Expires: Thu, 24 Jan 2013 15:36:52 +0000
v=0
o=- 2890844256 2890842807 IN IP4 198.51.100.34
s=RTSP Session
i=An Example of RTSP Session Usage
e=adm@example.com
c=IN IP4 0.0.0.0
a=control: *
a=range:npt=00:00:00-00:10:34.10
t=0 0
m=audio 0 RTP/AVP 0
a=control: trackID=1
C->M: SETUP rtsp://example.com/twister.3gp/trackID=1 RTSP/2.0
CSeq: 2
User-Agent: PhonyClient/1.2
Require: play.basic
Transport: RTP/AVP/TCP;unicast;dest_addr=":9"/":9";
setup=active;connection=new
Accept-Ranges: npt, smpte, clock
M->C: RTSP/2.0 200 OK
CSeq: 2
Server: PhonyServer/1.0
Transport: RTP/AVP/TCP;unicast;
dest_addr=":9"/":9";
src_addr="198.51.100.5:53478"/"198.51.100:54091";
setup=passive;connection=new;ssrc=93CB001E
Session: OccldOFFq23KwjYpAnBbUr
Expires: Thu, 24 Jan 2013 15:36:52 +0000
Date: Wed, 23 Jan 2013 15:36:52 +0000
Accept-Ranges: npt
Media-Properties: Random-Access=0.8, Immutable, Unlimited
C->M: TCP Connection Establishment x2
C->M: PLAY rtsp://example.com/twister.3gp/ RTSP/2.0
CSeq: 4
User-Agent: PhonyClient/1.2
Range: npt=30-
Session: OccldOFFq23KwjYpAnBbUr
M->C: RTSP/2.0 200 OK
CSeq: 4
Server: PhonyServer/1.0
Date: Wed, 23 Jan 2013 15:36:54 +0000
Session: OccldOFFq23KwjYpAnBbUr
Range: npt=30-623.10
Seek-Style: First-Prior
RTP-Info: url="rtsp://example.com/twister.3gp/trackID=1"
ssrc=4F312DD8:seq=54321;rtptime=2876889
That's the end of this bit, and the story keeps going, bestie! ๐๐
C.3. Handling Media-Clock Time Jumps in the RTP Media Layer ๐
okay so RTSP lets media clients jump around and play selected, non-contiguous sections of a presentation, and all of that gets rendered by an RTP media layer [RFC3550] ๐ฌ. There are two cases here. In the first, a new PLAY request replaces an ongoing one and the new request causes a jump in the media. That should still produce a continuous media stream at the RTP layer ๐ . In the second, a client immediately follows a completed PLAY request with a new PLAY request, and that leaves a gap in the media layer. The text below covers both, bestie ๐ซถ.
A PLAY request that replaces an ongoing PLAY request lets the media layer keep rendering the RTP stream continuously, without getting thrown off by jumps in media-clock time โจ. The RTP timestamps for the new media range are set so they continue smoothly from the previous range in the previous request. The RTP sequence number of the first packet in the new range is the one right after the last packet in the previous range, so it keeps going up, i.e., monotonically increasing. The goal is for the media-rendering layer to keep working without interruption or reconfiguration across the jumps in media clock. This should be possible in all cases of replaced PLAY requests for media that has random access properties. Here you do need to be careful to line up frames or similar media-dependent structures ๐ง.
In cases where jumps in media-clock time come from RTSP signaling that arrives after a completed PLAY operation, the timing of the request makes the media non-continuous ๐ญ. The server can't send the media so it arrives on time and still carries timestamps that make the stream continuous. So in these situations, the server produces RTP streams with gaps in the RTP timeline for the media. If the media has frame structure, lining up the timestamp for the next frame with the previous structure makes it much easier to render ๐. The gap should represent the time the server wasn't serving media, e.g., the time between the end of the media stream or a PAUSE request and the new PLAY request. In these cases, the RTP sequence number would normally keep increasing across the gap ๐.
For RTSP sessions with media that lacks random access properties, like live streams, any media-clock jump is usually the result of a correspondingly long pause in delivery โธ๏ธ. The RTP timestamp will have gone up in direct proportion to how long the paused delivery lasted. Also note that, in this case, the RTP sequence number should be the next packet number. If it isn't, the RTCP packet loss reporting will count every packet not received between the point of pausing and the later resume as lost ๐. That can trigger congestion avoidance mechanisms, and nobody wants that drama. There is one allowed exception to the above recommendation on monotonically increasing RTP sequence numbers: live media streams, which are likely being relayed. In this case, when the client resumes delivery, it gets the media that is currently being delivered to the server itself ๐บ. For this kind of basic delivery of live streams to multiple users over unicast, rewriting RTP sequence numbers one by one becomes quite a burden ๐ฉ. For solutions that already cache media or do time shifting, the rewriting should only be a minor burden.
The goal when handling jumps in media-clock time is a provided stream that's continuous, with no gaps in the RTP timestamp or sequence number ๐ . However, when delivery has been halted for some reason, the RTP timestamp MUST represent the duration that delivery was halted when it resumes ๐ฐ๏ธ. An RTP sequence number MUST generally be the next number, i.e., monotonically increasing modulo 65536. For media resources with the properties Time-Progressing and Time-Duration=0.0, the server MAY create RTP media streams with RTP sequence number jumps in them, because the client first halted delivery and later resumed it (PAUSE and then later PLAY). However, servers using this exception must take into consideration the resulting RTCP receiver reports, which likely contain loss reports for all the packets that were part of the discontinuity ๐. A client cannot rely on the server aligning things when play resumes, even if it is RECOMMENDED. The RTP-Info header will tell the client how the server acts in each case ๐.
One cannot assume that the RTSP client can communicate with the RTP media agent, as the two may be independent processes. If the RTP timestamp shows the same gap as the NPT, the media agent will assume that there is a pause in the presentation. If the jump in NPT is large enough, the RTP timestamp may roll over and the media agent may believe later packets to be duplicates of packets just played out ๐ฑ. Having the RTP timestamp jump will also affect the RTCP measurements based on this.
As an example, assume an RTP timestamp frequency of 8000 Hz, a packetization interval of 100 ms, and an initial sequence number and timestamp of zero ๐ฆ.
C->S: PLAY rtsp://example.com/fizzle RTSP/2.0
CSeq: 4
Session: ymIqLXufHkMHGdtENdblWK
Range: npt=10-15
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 200 OK
CSeq: 4
Session: ymIqLXufHkMHGdtENdblWK
Range: npt=10-15
RTP-Info: url="rtsp://example.com/fizzle/audiotrack"
ssrc=0D12F123:seq=0;rtptime=0
The RTP data stream that follows looks like this ๐
S -> C: RTP packet - seq = 0, rtptime = 0, NPT time = 10s
S -> C: RTP packet - seq = 1, rtptime = 800, NPT time = 10.1s
. . .
S -> C: RTP packet - seq = 49, rtptime = 39200, NPT time = 14.9s
Once the requested delivery is done, the server sends a PLAY_NOTIFY ๐.
S->C: PLAY_NOTIFY rtsp://example.com/fizzle RTSP/2.0
CSeq: 5
Notify-Reason: end-of-stream
Request-Status: cseq=4 status=200 reason="OK"
Range: npt=-15
RTP-Info:url="rtsp://example.com/fizzle/audiotrack"
ssrc=0D12F123:seq=49;rtptime=39200
Session: ymIqLXufHkMHGdtENdblWK
C->S: RTSP/2.0 200 OK
CSeq: 5
User-Agent: PhonyClient/1.2
Once the play range is finished, the client follows up with a PLAY request from a new NPT ๐ธ.
C->S: PLAY rtsp://example.com/fizzle RTSP/2.0
CSeq: 6
Session: ymIqLXufHkMHGdtENdblWK
Range: npt=18-20
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 200 OK
CSeq: 6
Session: ymIqLXufHkMHGdtENdblWK
Range: npt=18-20
RTP-Info: url="rtsp://example.com/fizzle/audiotrack"
ssrc=0D12F123:seq=50;rtptime=40100
The RTP data stream that follows looks like this ๐
S->C: RTP packet - seq = 50, rtptime = 40100, NPT time = 18s
S->C: RTP packet - seq = 51, rtptime = 40900, NPT time = 18.1s
. . .
S->C: RTP packet - seq = 69, rtptime = 55300, NPT time = 19.9s
In this example, NPT 10 through 15 plays first, then the client asks the server to skip ahead and play NPT 18 through 20 โฉ. The first segment is sent as RTP packets with sequence numbers 0 through 49 and timestamps 0 through 39,200. The second segment consists of RTP packets with sequence numbers 50 through 69, with timestamps 40,100 through 55,200. So while there's a gap in the NPT, there's no gap in the sequence-number space of the RTP data stream ๐.
The RTP timestamp gap in the example above comes from the time it takes to handle the second play request, which in this case is 12.5 ms (100/8000) โฑ๏ธ.
C.4. Handling RTP Timestamps after PAUSE ๐
During a PAUSE/PLAY interaction in an RTSP session, the duration for which RTP transmission was halted MUST be reflected in the RTP timestamp of each RTP stream ๐. You can work out that duration for each RTP stream as the time elapsed between when the last RTP packet was sent before the PAUSE request was received and when the first RTP packet was sent after the subsequent PLAY request was received. The duration includes all the latency and processing time it takes to complete the request โ.
RFC 3550 [RFC3550] states that: "the RTP timestamp for each unit [packet] would be related to the wallclock time at which the unit becomes current on the virtual presentation timeline". In order to satisfy the requirements of [RFC3550], the RTP timestamp space needs to increase continuously with real time. While this is not optimal for stored media, it is required for RTP and RTCP to function as intended. Using a continuous RTP timestamp space allows the same timestamp model for both stored and live media, and allows better opportunity to integrate both types of media under a single control ๐ง .
As an example, assume a clock frequency of 8000 Hz, a packetization interval of 100 ms, and an initial sequence number and timestamp of zero ๐ฆ.
C->S: PLAY rtsp://example.com/fizzle RTSP/2.0
CSeq: 4
Session: ymIqLXufHkMHGdtENdblWK
Range: npt=10-15
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 200 OK
CSeq: 4
Session: ymIqLXufHkMHGdtENdblWK
Range: npt=10-15
RTP-Info: url="rtsp://example.com/fizzle/audiotrack"
ssrc=0D12F123:seq=0;rtptime=0
The RTP data stream that follows looks like this ๐
S -> C: RTP packet - seq = 0, rtptime = 0, NPT time = 10s
S -> C: RTP packet - seq = 1, rtptime = 800, NPT time = 10.1s
S -> C: RTP packet - seq = 2, rtptime = 1600, NPT time = 10.2s
S -> C: RTP packet - seq = 3, rtptime = 2400, NPT time = 10.3s
Then the client sends a PAUSE request โธ๏ธ.
C->S: PAUSE rtsp://example.com/fizzle RTSP/2.0
CSeq: 5
Session: ymIqLXufHkMHGdtENdblWK
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 200 OK
CSeq: 5
Session: ymIqLXufHkMHGdtENdblWK
Range: npt=10.4-15
20 seconds go by, and then the client sends a PLAY request. On top of that, the server needs 15 ms to process the request ๐.
C->S: PLAY rtsp://example.com/fizzle RTSP/2.0
CSeq: 6
Session: ymIqLXufHkMHGdtENdblWK
User-Agent: PhonyClient/1.2
S->C: RTSP/2.0 200 OK
CSeq: 6
Session: ymIqLXufHkMHGdtENdblWK
Range: npt=10.4-15
RTP-Info: url="rtsp://example.com/fizzle/audiotrack"
ssrc=0D12F123:seq=4;rtptime=164400
The RTP data stream that follows looks like this ๐
S -> C: RTP packet - seq = 4, rtptime = 164400, NPT time = 10.4s
S -> C: RTP packet - seq = 5, rtptime = 165200, NPT time = 10.5s
S -> C: RTP packet - seq = 6, rtptime = 166000, NPT time = 10.6s
First, NPT 10 through 10.3 plays, and then the server receives a PAUSE. After 20 seconds, the server receives a PLAY that takes 15 ms to process. The duration the session was paused for shows up in the RTP timestamp of the RTP packets sent after that PLAY request ๐ท.
A client can use the RTSP Range header and the RTP-Info header to map the NPT time of a presentation to the RTP timestamp ๐บ๏ธ.
Note: in RFC 2326 [RFC2326], this matter was not clearly defined and was commonly misunderstood. However, for RTSP 2.0, it is expected that this will be handled correctly and no exception handling will be required. Note further: it may be required to reset some of the state to ensure the correct media decoding and the usual jitter-buffer handling when issuing a PLAY request ๐ง.
C.5. RTSP/RTP Integration โจ
okay so for certain data types, the RTSP layer and the RTP layer have to be tightly integrated, no cap ๐ and that doesn't cancel out the restrictions above, bestie. Combined RTSP/RTP media clients should use the RTP-Info field to figure out whether incoming RTP packets were sent before or after a seek, or before or after a PAUSE ๐
C.6. Scaling with RTP ๐๏ธ
for scaling (see Section 18.46), RTP timestamps should line up with the rendering timing ๐ example time: say you're playing video recorded at 30 frames per second, at a scale of two, with a speed (Section 18.50) of one. The server drops every second frame, but it still keeps the normal timestamp spacing of 3,000 per frame so the packets stay on schedule. Meanwhile NPT goes up by 1/15 second for each video frame you see. iconic math, fr ๐ฆ
Note: the scaling above puts requirements on the media codec or the media stream to support it ๐ For example, motion JPEG or other non-predictive video coding can handle the example above more easily ๐ธ
C.7. Maintaining NPT Synchronization with RTP Timestamps โฑ๏ธ
the client can keep the NPT display accurate by noting the RTP timestamp of the first packet that shows up after repositioning ๐ง And the sequence parameter of the RTP-Info (Section 18.45) header hands you the first sequence number of the next segment. main character sync energy ๐
C.8. Continuous Audio ๐ง
for continuous audio, the server SHOULD set the RTP marker bit at the start of serving a new PLAY request, or at jumps in the timeline ๐ซถ that's what lets the client do its playout delay adaptation, so it's lowkey important
C.9. Multiple Sources in an RTP Session ๐
more than one SSRC MAY be sent in the media stream ๐ฏ and if that happens, all the sources are expected to be rendered at the same time. a whole group project, periodt ๐
C.10. Usage of SSRCs and the RTCP BYE Message during an RTSP Session ๐
the RTCP BYE message says "this SSRC is done" ๐ญ If all the sources leave an RTP session, it can, in most cases, be assumed to have ended. So a client or server MUST NOT send an RTCP BYE message until it has finished using an SSRC. A server SHOULD keep using an SSRC until the RTP session is terminated ๐ฅ Keeping the SSRC alive means the synchronization context tied to it can still be used to sync later PLAY requests, even if the PLAY response shows up late.
an SSRC collision with the one that's sending media is also a big deal ๐ฅบ It will normally force the media sender to change its SSRC, following the RTP specification [RFC3550]. An RTSP server can wait and see whether the client changes first, which resolves the conflict and keeps the damage small โจ But if the media sender switches SSRC, it loses its synchronization context, and every receiver then has to wait for RTCP sender reports for all the media that needs syncing before it can play out in sync. So a client joining a session should be careful not to pick the same SSRC(s) the server lists in the ssrc Transport header parameter. Any SSRC signaled in the Transport header MUST be avoided. And a client that detects a collision before sending any RTP or RTCP messages SHALL also pick a new SSRC ๐
C.11. Future Additions ๐
it's the goal that any future protocol or profile for media delivery and lower transport can be added to RTSP easily โจ this section lists the steps you need to go through.
When adding a new protocol or profile for use with RTSP, you need to think about the following things:
- the protocol or profile needs a name tag that represents it. This tag is required to be an ABNF "token", so it can be used in the Transport header specification ๐ท๏ธ
- the useful combinations of protocol, profile, and lower-layer transport for this extension need to be defined. For each combination, declare the parameters needed to use it in the Transport header ๐งฉ
- for new media protocols, the interaction with RTSP needs to be addressed. Media synchronization is a big factor here. It may be necessary to add new headers, similar to RTP-Info, to carry this information ๐ถ
- congestion control for media needs discussion, especially if transport without built-in congestion control is used ๐
See the IANA Considerations section (Section 22) for information on how to register new attributes ๐
Appendix D. Use of SDP for RTSP Session Descriptions ๐
The Session Description Protocol (SDP, [RFC4566]) can be used to describe streams or presentations in RTSP ๐ฆ This description usually comes back in reply to a DESCRIBE request on a URI, going from server to client, or it's received over HTTP from a server to a client.
this appendix explains how an SDP file decides how an RTSP session operates ๐ง so it's worth knowing that the SDP gets interpreted in the context of the SDP receiver, which is the one being configured. That's the same as in SAP [RFC2974] ๐ฏ It's different from SDP Offer/Answer [RFC3264], where each SDP is interpreted in the context of the agent that provided it.
plain SDP has no way for a client to tell, without a human's help, the difference between several media streams that should play at the same time and a set of alternatives (like two audio streams in different languages) ๐ The SDP extension in "The Session Description Protocol (SDP) Grouping Framework" [RFC5888] helps with that to some degree. Appendix D.4 covers how SDP media line grouping is used for RTSP ๐
D.1. Definitions ๐
The terms "session-level", "media-level", and other key/attribute names and values used in this appendix mean what they mean in SDP [RFC4566]:
D.1.1. Control URI ๐
The a=control attribute carries the control URI. This attribute is used for both the session and media descriptions. If it's used for an individual media, it points to the URI used to control that particular media stream. If it's found at the session level, the attribute gives the URI for aggregate control (the presentation URI). The session-level URI MUST be different from any media-level URI. The presence of a session-level control attribute MUST be interpreted as support for aggregated control. The control attribute MUST be present on the media level, unless the presentation only has a single media stream. In that case the attribute MAY be present only on the session level, and it then also applies to that single media stream ๐ญ
the ABNF for the attribute is defined in Section 20.3 ๐
Example:
a=control:rtsp://example.com/foo
This attribute MAY contain either relative or absolute URIs, following the rules and conventions set out in RFC 3986 [RFC3986]. Implementations MUST look for a base URI in this order:
- the RTSP Content-Base field;
- the RTSP Content-Location field;
- the RTSP Request-URI.
If this attribute contains only an asterisk (*), the URI MUST be treated as if it were an empty embedded URI. So it inherits the entire base URI ๐ธ
Note: RFC 2326 was very unclear on how relative URIs get processed, and several RTSP 1.0 implementations at the time this document was published did not do RFC 3986 processing to work out the resulting URI. Plain concatenation was common instead ๐ To avoid this issue completely, it is recommended to use absolute URIs in the SDP.
the URI handling for SDPs from container files needs special thought ๐ฆ Say a container file has the URI rtsp://example.com/container.mp4. Let's also say that's the base URI, and there's an absolute media-level URI rtsp://example.com/container.mp4/trackID=2. A relative media-level URI that resolves to that media URI under RFC 3986 [RFC3986] is "container.mp4/trackID=2". It's usually not desirable to include or modify the SDP stored in the container file with the server's local name for the container file. To avoid that, you can change the base URI to include a trailing slash, e.g., "rtsp://example.com/container.mp4/". Then the relative URI for the media only needs to be "trackID=2". However, this also means that using "*" in the SDP makes the control URI include the trailing slash, i.e., "rtsp://example.com/container.mp4/" โจ
Note: TrackID in the above is not a standardized form. It's one example out of several similar strings, such as TrackID, Track_ID, and StreamID, that different server vendors use to indicate a particular piece of media inside a container file ๐
D.1.2. Media Streams ๐ฌ
the "m=" field is used to list the streams. All the specified streams are expected to be rendered with appropriate synchronization ๐ซถ If the session is over multicast, the port number indicated SHOULD be used for reception. The client MAY try to override the destination port through the Transport header. The servers MAY allow this, and the response will say whether or not it's allowed. If the session is unicast, the port numbers are the ones RECOMMENDED by the server to the client, about which receiver ports to use. The client MUST still include its receiver ports in its SETUP request. The client MAY ignore this recommendation. If the server has no preference, it SHOULD set the port number value to zero ๐
the "m=" lines say which transport protocol, profile, and possibly lower layer are used for the media stream. The combination of transport, profile, and lower layer, like RTP/AVP/UDP, needs to be defined for how it's used with RTSP. The combinations currently defined are discussed in Appendix C, and further combinations MAY be specified ๐งฉ
Example:
m=audio 0 RTP/AVP 31
D.1.3. Payload Type(s) ๐ต
The payload type or types are specified in the "m=" line. If the payload type is a static payload type from RFC 3551 [RFC3551], no other information may be required. If it's a dynamic payload type, the media attribute "rtpmap" says what the media is. The "encoding name" in the "rtpmap" attribute may be one of those specified in [RFC4856], a media type registered with IANA according to [RFC4855], or an experimental encoding as specified in SDP [RFC4566]). Codec-specific parameters aren't specified in this field. They go in the "fmtp" attribute described below ๐
the selection of RTP payload type numbers may be required to consider RTP and RTCP Multiplexing [RFC5761], if the server is going to support that ๐
D.1.4. Format-Specific Parameters ๐
Format-specific parameters are carried using the "fmtp" media attribute. The syntax of the "fmtp" attribute depends on the encoding(s) it refers to. Some format-specific parameters may be specified outside of the "fmtp" parameters, for example, like the "ptime" attribute for most audio encodings ๐ฆ
D.1.5. Directionality of Media Stream โจ
okay so the SDP attributes a=sendrecv, a=recvonly, and a=sendonly tell you which way the media streams flow inside a session ๐ฆ. when you're using RTSP, the SDP can reach a client through RTSP DESCRIBE or through a bunch of RTSP external methods, like HTTP, FTP, and email ๐. so the SDP applies to how the RTSP client sees the whole session, and media streams going from the RTSP server to the client get the a=recvonly attribute ๐.
a=recvonly in an SDP given to the RTSP client means media only goes from the RTSP server to the client, no cap ๐. an SDP given to the RTSP client that doesn't have any of the directionality attributes (a=recvonly, a=sendonly, a=sendrecv) gets read as a=sendrecv ๐ธ. at the time of writing, there's no RTSP mode for media going from the RTSP client to the server, so all RTSP SDP SHOULD have an a=recvonly attribute when you're using the PLAY mode defined in this document ๐
. if future modes get defined for client-to-server media, then a=sendonly or a=sendrecv may become suitable to show the intended directions โจ.
D.1.6. Range of Presentation ๐
the a=range attribute defines the total time range of the stored session or of an individual media ๐๏ธ. live sessions that aren't seekable can be marked the way described below, while the length of a live session can be figured out from the t= and r= SDP parameters โฐ.
this attribute works at both the session level and the media level ๐ซ. for presentations where all the media streams are the same length, the range attribute SHOULD only be used at the session level. if the lengths are different, the range attribute MUST be given at the media level for all media and SHOULD NOT be given at the session level ๐. if it shows up at both levels, the media-level values MUST be used, no debate ๐.
Note: usually one will specify the same length for all media, even if there isn't media available for the full duration on all media. However, that requires that the server accept PLAY requests within that range.
servers MUST take care to provide RTSP Range (see Section 18.40) values that match what the SDP says about the content ๐ซถ. there's no good reason for non-dynamic content, like on-demand media clips, to have values that don't line up. if they don't match what's actually on the server, the client is likely to hit a failure like 457 "Invalid Range" when it sends PLAY requests with a Range header ๐ญ. if the content's length is dynamic and it's impossible to put a correct value in the SDP, the server is recommended to describe it as content that isn't seekable (see below). the server MAY override that property in the response to a PLAY request by using the correct values in the Range header ๐ฆ.
the unit comes first, followed by the value range ๐. the units and their values are defined in Section 4.4.1, Section 4.4.2, and Section 4.4.3, and MAY be extended with further formats ๐ธ. any open-ended range (start-), so one with no stop range, has an unspecified duration and MUST be considered content that isn't seekable, unless this property gets overridden ๐. multiple instances carrying different clock formats MAY be included at either the session level or the media level ๐.
ABNF for the attribute is defined in Section 20.3 ๐.
Examples:
a=range:npt=0-34.4368
a=range:clock=19971113T211503Z-19971113T220300Z
Non-seekable stream of unknown duration:
a=range:npt=0-
D.1.7. Time of Availability โณ
the t= field defines when the SDP is valid ๐
. for on-demand content, the server SHOULD indicate a stop time value where it guarantees the description is valid, and a start time that's equal to or before the moment the DESCRIBE request came in ๐
. it MAY also indicate start and stop times of 0, which means the session is always available ๐.
for live sessions (so a specific start time, an unknown stop time, and likely not seekable) the t= and r= fields SHOULD be used to show the start time of the event ๐ค. the stop time SHOULD be given so the live event will have ended by then, while still not being unnecessarily far into the future ๐ง.
D.1.8. Connection Information ๐ก
in SDP used with RTSP, the c= field holds the destination address for the media stream ๐. if a multicast address is specified, the client SHOULD use that address in any SETUP request as the destination address, including any additional parameters, like TTL ๐ฃ. for on-demand unicast streams and some multicast streams, the client MAY specify the destination address via the SETUP request, which overrides any specified address ๐ฆ. to identify streams without a fixed destination address, where the client is required to specify one, the c= field SHOULD be set to a null value ๐ซง. for addresses of type "IP4", that null value MUST be "0.0.0.0", and for type "IP6", it MUST be "0:0:0:0:0:0:0:0" (which can also be written as "::"). that's the unspecified address according to RFC 4291 [RFC4291], so it's giving "nobody's home yet" ๐ โจ.
D.1.9. Message Body Tag ๐ท๏ธ
the optional a=mtag attribute identifies a version of the session description ๐. it's opaque to the client, which means the client doesn't get to peek inside it ๐. SETUP requests may include this identifier in the If-Match field (see Section 18.24) so that session establishment only happens if the attribute value still matches the current description ๐. the attribute value is opaque and may contain any character allowed within SDP attribute values ๐.
ABNF for the attribute is defined in Section 20.3 ๐.
Example:
a=mtag:"158bb3e7c7fd62ce67f12b533f06b83a"
One could argue that the "o=" field provides identical functionality. However, it does so in a manner that would put constraints on servers that need to support multiple session description types other than SDP for the same piece of media content. ๐ค
D.2. Aggregate Control Not Available ๐ โโ๏ธ
if a presentation doesn't support aggregate control, there's no session-level a=control attribute ๐ธ. for an SDP with multiple media sections, each section gets its own control URI through the a=control attribute ๐.
Example:
v=0
o=- 2890844256 2890842807 IN IP4 192.0.2.56
s=I came from a web page
e=adm@example.com
c=IN IP4 0.0.0.0
t=0 0
m=video 8002 RTP/AVP 31
a=control:rtsp://audio.example.com/movie.aud
m=audio 8004 RTP/AVP 3
a=control:rtsp://video.example.com/movie.vid
the position of the control URI in the description implies that the client sets up separate RTSP control sessions to the servers audio.example.com and video.example.com ๐โจ.
it is recommended that an SDP file contain the complete media-initialization information, even if it's delivered to the media client through non-RTSP means ๐ฆ. this is necessary because there's no mechanism to indicate that the client should request more detailed media stream information via DESCRIBE ๐ญ.
D.3. Aggregate Control Available ๐๏ธ
in this scenario, the server has multiple streams that can be controlled as a whole ๐. here there's both a media-level a=control attribute, used to specify the stream URIs, and a session-level a=control attribute, used as the Request-URI for aggregate control ๐ง . if the media-level URI is relative, it gets resolved to absolute URIs according to Appendix D.1.1 above ๐.
Example:
C->M: DESCRIBE rtsp://example.com/movie RTSP/2.0
CSeq: 1
User-Agent: PhonyClient/1.2
M->C: RTSP/2.0 200 OK
CSeq: 1
Date: Wed, 23 Jan 2013 15:36:52 +0000
Expires: Wed, 23 Jan 2013 16:36:52 +0000
Content-Type: application/sdp
Content-Base: rtsp://example.com/movie/
Content-Length: 227
v=0
o=- 2890844256 2890842807 IN IP4 192.0.2.211
s=I contain
i=<more info>
e=adm@example.com
c=IN IP4 0.0.0.0
a=control:*
t=0 0
m=video 8002 RTP/AVP 31
a=control:trackID=1
m=audio 8004 RTP/AVP 3
a=control:trackID=2
in this example, the client is recommended to set up a single RTSP session to the server ๐ฌ. it uses the URIs rtsp://example.com/movie/trackID=1 and rtsp://example.com/movie/trackID=2 to set up the video and audio streams, respectively ๐ฅ๐. the URI rtsp://example.com/movie/, which comes from the "*", controls the whole presentation (movie) ๐.
a client is not required to issue SETUP requests for all streams within an aggregate object ๐. servers should allow the client to ask for only a subset of the streams ๐.
D.4. Grouping of Media Lines in SDP ๐งฉ
for some types of media, it's desirable to express a relationship between various media components, like for lip synchronization or Scalable Video Codec (SVC) [RFC5583] ๐๐ถ. this relationship gets expressed at the SDP level by grouping media lines, as described in [RFC5888], and it can be exposed to RTSP ๐.
for RTSP, the main thing to know is how to handle grouped media received through SDP, meaning whether the media are under aggregate control (see Appendix D.3) or whether aggregate control isn't available (see Appendix D.2) ๐ค.
it is RECOMMENDED that grouped media are handled by aggregate control, so the client can control either the whole presentation or single media ๐ซถโจ.
D.5. RTSP External SDP Delivery ๐ฌ
there are some things to think about when the session description gets delivered to the client outside of RTSP, like through HTTP or email ๐.
first of all, the SDP needs to contain absolute URIs, since relative ones will, in most cases, not work, because the delivery won't correctly forward the base URI ๐ โโ๏ธ.
the writing of the SDP session availability information (the t= and r= fields) needs to be carefully considered ๐ฅบ. when the SDP is fetched with the DESCRIBE method, the chance that it's valid is very high ๐ฏ. that's much less certain for SDPs distributed through other methods ๐ฌ. so the publisher of the SDP should take care to follow the recommendations about availability in the SDP specification [RFC4566] in Section 4.2 ๐๐.
Appendix E. RTSP Use Cases ๐
this appendix covers the most important use cases for RTSP that were considered ๐ฏ. they're listed in descending order of importance, based on making sure all the necessary functionality is present ๐. this specification only fully supports the first two ๐ฅ๐ฅ. in those first two cases there are special cases or exceptions that aren't supported without extensions, like redirecting media delivery to an address other than the controlling agent's (client's) ๐๐ .
E.1. On-Demand Playback of Stored Content โจ
Okay bestie, so an RTSP-capable server stores content that's ready to be streamed to a client ๐ฌ. A client who wants to play any of that stored content uses RTSP to set up the media transport needed to deliver it ๐. Then RTSP is used to start, halt, and manipulate the actual transmission (playout) of the content โถ๏ธ. RTSP is also required to provide the necessary description and synchronization information for the content ๐.
The high-level picture above breaks down into a few functions RTSP needs to be capable of ๐งฉ.
Presentation Description: Provide initialization information about the presentation (content), like which media codecs are needed for the content ๐๏ธ. Other important info includes the number of media streams the presentation contains, the transport protocols used for the media streams, and identifiers for these media streams ๐. This info is required before setup of the content is possible, and to determine if the client is even capable of using the content ๐.
This information need not be sent using RTSP, since other external protocols can be used to transmit the transport presentation descriptions. Two good examples are the use of HTTP [RFC7230] or email to fetch or receive presentation descriptions like SDP [RFC4566].
Setup: Set up some or all of the media streams in a presentation. The setup itself consists of selecting the protocol for media transport and the necessary parameters for the protocol, like addresses and ports ๐ฎ.
Control of Transmission: After the necessary media streams have been established, the client can request the server to start transmitting the content. The client must be allowed to start or stop the transmission of the content at arbitrary times. The client must also be able to start the transmission at any point in the timeline of the presentation โฏ๏ธ.
Synchronization: For media-transport protocols like RTP [RFC3550], it might be beneficial to carry synchronization information within RTSP. This may be due to either the lack of inter-media synchronization within the protocol itself or the potential delay before the synchronization is established (which is the case for RTP when using RTCP) ๐ถ.
Termination: Terminate the established contexts ๐.
For this use case, there are a few assumptions about how it works. These are:
- On-Demand content: The content is stored at the server and can be accessed at any time during a time period when it is intended to be available.
- Independent sessions: A server is capable of serving a number of clients simultaneously, including from the same piece of content at different points in that presentation's timeline.
- Unicast Transport: Content for each individual client is transmitted to them using unicast traffic.
It is also possible to redirect the media traffic to a different destination than that of the agent controlling the traffic. However, allowing this without appropriate mechanisms for checking that the destination approves of this allows for Distributed DoS (DDoS).
๐จ Seriously, this one is a big deal. Redirecting media to a destination that never agreed to receive it can turn your server into a weapon against someone else. Only allow redirection together with a way to check that the destination approves. ๐จ
E.2. Unicast Distribution of Live Content ๐ก
This use case is similar to the on-demand content case above (see Appendix E.1). The difference is the nature of the content itself. Live content is continuously distributed as it becomes available from a source, so the main difference from on-demand is that one starts distributing content before the end of it has become available to the server ๐ด.
In many cases, the consumer of live content is only interested in consuming what actually happens "now", i.e., very similar to broadcast TV ๐บ. However, in this case, it is assumed that there exists no broadcast or multicast channel to the users. Instead, the server functions as a distribution node, sending the same content to multiple receivers using unicast traffic between server and client. This unicast traffic and the transport parameters are individually negotiated for each receiving client ๐ค.
Another aspect of live content is that it often has a very limited time of availability, since it is only available for the duration of the event the content covers. An example of such live content could be a music concert that lasts two hours and starts at a predetermined time ๐ธ. Thus, there is a need to announce when and for how long the live content is available โฐ.
In some cases, the server providing live content may be saving some or all of the content. This allows clients to pause the stream and resume it from the paused point, or to "rewind" and play continuously from a point earlier than the live point โช. Hence, this use case does not necessarily exclude playing from other than the live point of the stream, playing with scales other than 1.0, etc. ๐ฆ
E.3. On-Demand Playback Using Multicast ๐ฃ
It is possible to use RTSP to request that media be delivered to a multicast group. The entity setting up the session (the controller) will then control when and what media is delivered to the group ๐๏ธ. This use case has some potential for DoS attacks by flooding a multicast group. Therefore, a mechanism is needed to indicate that the group actually accepts the traffic from the RTSP server ๐ก๏ธ.
An open issue in this use case is how one ensures that all receivers listening to the multicast or broadcast receive the session presentation configuring the receivers. This specification has to rely on an external solution to solve this issue ๐ง.
E.4. Inviting an RTSP Server into a Conference ๐
If one has an established conference or group session, it is possible to have an RTSP server distribute media to the whole group. Transmission to the group is simplest when controlled by a single participant or leader of the conference. Shared control might be possible, but would require further investigation and possibly extensions ๐.
This use case assumes that there exists either a multicast or a conference focus that redistributes media to all participants.
This use case is intended to be able to handle the following scenario: a conference leader or participant (hereafter called the "controller") has some pre-stored content on an RTSP server that he wants to share with the group. The controller sets up an RTSP session at the streaming server for this content and retrieves the session description for the content. The destination for the media content is set to the shared multicast group or conference focus. When desired by the controller, he/she can start and stop the transmission of the media to the conference group ๐ฟ.
There are several issues with this use case that are not solved by this core specification for RTSP:
DoS: To avoid an RTSP server from being an unknowing participant in a DoS attack, the server needs to be able to verify the destination's acceptance of the media. Such a mechanism to verify the approval of received media does not yet exist. Instead, only policies can be used, which can be made to work in controlled environments ๐ซ.
Distributing the presentation description to all participants in the group: To enable a media receiver to correctly decode the content, the media configuration information needs to be distributed reliably to all participants. This will most likely require support from an external protocol ๐ฌ.
Passing control of the session: If it is desired to pass control of the RTSP session between the participants, some support will be required by an external protocol to exchange state information and possibly floor control of who is controlling the RTSP session ๐ค.
E.5. Live Content Using Multicast ๐
This use case in its simplest form does not require any use of RTSP at all. This is what multicast conferences being announced with SAP [RFC2974] and SDP are intended to handle. However, in use cases where more advanced features like access control to the multicast session are desired, RTSP could be used for session establishment ๐.
A client desiring to join a live multicasted media session with cryptographic (encryption) access control could use RTSP in the following way. The source of the session announces the session and gives all interested parties an RTSP URI. The client connects to the server and requests the presentation description, allowing configuration for reception of the media. In this step, it is possible for the client to use secured transport and any desired level of authentication, for example for billing or access control. An RTSP link also allows for load balancing between multiple servers โ๏ธ.
If these were the only goals, they could be achieved by simply using HTTP. However, for cases where the sender likes to keep track of each individual receiver of a session, and possibly use the session as a side channel for distributing key-updates or other information on a per-receiver basis, and the full set of receivers is not known prior to the session start, the state establishment that RTSP provides can be beneficial ๐. In this case, a client would establish an RTSP session for this multicast group with the RTSP server. The RTSP server will not transmit any media, but instead will point to the multicast group. The client and server will be able to keep the session alive for as long as the receiver participates in the session, thus enabling, for example, the server to push updates to the client ๐.
This use case will most likely not be able to be implemented without some extensions to the server-to-client push mechanism. Here the PLAY_NOTIFY method (see Section 13.5) with a suitable extension could provide clear benefits ๐ง.
Appendix F. Text Format for Parameters ๐งพ
A resource of type "text/parameters" consists of either 1) a list of parameters (for a query) or 2) a list of parameters and associated values (for a response or setting of the parameter). Each entry of the list is a single line of text. Parameters are separated from values by a colon. The parameter name MUST only use US-ASCII visible characters while the values are UTF-8 text strings. The media type registration form is in Section 22.16 ๐.
There is a potential interoperability issue for this format. It was named in RFC 2326 but never defined, even if used in examples that hint at the syntax. This format matches the purpose and its syntax supports the examples provided. However, it goes further by allowing UTF-8 in the value part, so usage of UTF-8 strings may not be supported. Also, as individual parameters are not defined, the implementing application needs to have out-of-band agreement or use a feature tag anyway to determine if the endpoint supports the parameters ๐ซถ.
The ABNF [RFC5234] grammar for "text/parameters" content is:
file = *((parameter / parameter-value) CRLF)
parameter = 1*visible-except-colon
parameter-value = parameter *WSP ":" value
visible-except-colon = %x21-39 / %x3B-7E ; VCHAR - ":"
value = *(TEXT-UTF8char / WSP)
TEXT-UTF8char = <as defined in Section 20.1>
WSP = <See RFC 5234> ; Space or HTAB
VCHAR = <See RFC 5234>
CRLF = <See RFC 5234>
Appendix G. Requirements for Unreliable Transport of RTSP ๐ฆ
Okay bestie, this appendix is for anyone who wants to send RTSP messages over unreliable transports ๐ธ RTSP 1.0 [RFC2326] already defined the rtspu URI scheme and gave some basic info about carrying RTSP messages over UDP. We're keeping this around because there's at least one commercial implementation out there, and staying compatible with it matters ๐ซถ
Here's what to think about for an interoperable implementation โจ
- Requests shall be acknowledged by the receiver. If there's no acknowledgement, the sender may resend the same message after a timeout of one round-trip time (RTT). Any retransmissions caused by a lack of acknowledgement must carry the same sequence number as the original request. ๐
- The RTT can be estimated the same way TCP does it (RFC 6298) [RFC6298], starting from an initial round-trip value of 500 ms. An implementation may cache the last RTT measurement and use it as the initial value for future connections. ๐ง
- The Timestamp header (Section 18.53) is used to dodge the retransmission ambiguity problem [Stevens98]. ๐
- The registered default port for RTSP over UDP on the server is
554. ๐ - RTSP messages can ride on any lower-layer transport protocol that is 8-bit clean. ๐
- RTSP messages are vulnerable to bit errors and should not be subjected to them. ๐
- Source authentication, or at the very least checking that RTSP messages come from the same entity, becomes extremely important. Session hijacking may be substantially easier for RTSP over an unreliable protocol like UDP than over TCP. ๐ญ
Bestie, this one's serious. Hijacking is way easier over UDP than TCP, so don't skip the authentication step!
There are two RTSP headers that are mainly meant for handling RTSP messages over unreliable transports, and they're staying around:
CSeq: See Section 18.20. TheCSeqheader is also required to match requests and responses, no matter whether a reliable or an unreliable transport is in use. ๐ฆTimestamp: See Section 18.53 โญ
Appendix H. Backwards-Compatibility Considerations ๐ธ
Okay, this section is all about backwards compatibility with clients and servers built to RFC 2326 [RFC2326] ๐ Quick reality check: there's no requirement to implement RTSP 1.0. Honestly, this document recommends against it, since it's hard to do in an interoperable way ๐
A server implementing RTSP 2.0 MUST include an RTSP-Version of RTSP/2.0 in all responses to requests whose RTSP-Version value is RTSP/2.0. If a server gets an RTSP 1.0 request, it MAY respond with an RTSP 1.0 response if it chooses to support RFC 2326. If the server chooses not to support RFC 2326, it MUST respond with a 505 (RTSP Version Not Supported) status code. A server MUST NOT respond to an RTSP 1.0 request with an RTSP 2.0 response. ๐
Clients implementing RTSP 2.0 MAY use an OPTIONS request with an RTSP-Version of RTSP/2.0 to figure out whether a server supports RTSP 2.0 ๐ If the server responds with either an RTSP-Version of RTSP/1.0 or a status code of 505 (RTSP Version Not Supported), the client will have to use RTSP 1.0 requests if it chooses to support RFC 2326. ๐ซถ
H.1. Play Request in Play State ๐
The server's behavior when a Play is received in Play state has changed (Section 13.4). In RFC 2326, a new PLAY request would get queued until the current Play completed. Now, any new PLAY request takes effect immediately and replaces the previous request. โจ
H.2. Using Persistent Connections ๐ง
Some server implementations of RFC 2326 keep a one-to-one relationship between a connection and an RTSP session. Those implementations require clients to use a persistent connection to talk to the server, and when a client closes its connection, the server may remove the RTSP session. This is worth noting if an RTSP 2.0 client that also supports 1.0 connects to a 1.0 server. ๐
Appendix I. Changes ๐
This appendix gives a quick rundown of the differences between RTSP 1.0 [RFC2326] and RTSP 2.0, just for info ๐ If you're implementing RTSP 2.0, it's recommended that you read this memo carefully instead of relying on the list below to adapt from RTSP 1.0 to RTSP 2.0. RTSP 2.0 is not meant to be backwards compatible with RTSP 1.0 [RFC2326], apart from the version negotiation mechanism. ๐ซถ
I.1. Brief Overview ๐
These protocol elements were removed in RTSP 2.0 compared to RTSP 1.0:
- the RECORD and ANNOUNCE methods and all related functionality (including 201 (Created) and 250 (Low On Storage Space) status codes); ๐
- the use of UDP for RTSP message transport (due to missing interest and to broken specification); ๐
- the use of PLAY method for keep-alive in Play state. ๐ญ
These protocol elements were added or changed in RTSP 2.0 compared to RTSP 1.0:
- RTSP session TEARDOWN from the server to the client; ๐ฆ
- IPv6 support; ๐ธ
- extended IANA registries (e.g., transport headers parameters, transport-protocol, profile, lower-transport, and mode); ๐
- request pipelining for quick session start-up; โญ
- fully reworked state machine; ๐ฅ
- RTSP messages now use URIs rather than URLs; ๐
- much of the related HTTP text ([RFC2616]) has been incorporated into this memo, instead of just referencing the sections in HTTP, to avoid ambiguities; ๐ง
- the REDIRECT method was expanded and diversified for different situations; ๐
- a new section has been included about how to set up different media-transport alternatives and their profiles, in addition to lower-layer protocols. This meant the appendix on RTP interaction moved into the new section, instead of living in the part that describes RTP. The section also covers what to consider when writing usage guidelines for new protocols and profiles; ๐
- an asynchronous notification method, PLAY_NOTIFY, was added. The RTSP server uses it to asynchronously notify clients about session changes while in Play state. To a limited extent, it's comparable with some implementations of ANNOUNCE in RTSP 1.0 that weren't intended for Recording. ๐
I.2. Detailed List of Changes ๐ธ
These changes were made to RTSP 1.0 (RFC 2326) when defining RTSP 2.0. Heads up: this list doesn't include minor wording changes or typo fixes ๐
- The section on minimal implementation was deleted. Instead, the main part of the specification defines the core of RTSP 2.0. ๐ง
- The Transport header changed in these ways:
- The ABNF was changed to define that extensions are possible and that unknown parameters result in servers ignoring the transport specification. ๐ฆ
- To prevent backwards compatibility issues, any extension or new parameter requires the use of a feature tag combined with the
Requireheader. ๐ - Syntax ambiguities with the Mode parameter were resolved. โจ
- A syntax error with ";" for multicast and unicast was resolved. ๐
- Two new addressing parameters were defined:
src_addranddest_addr. These replace the parametersport,client_port,server_port,destination, andsource. ๐ - Support for IPv6 explicit addresses was included in all address fields. ๐
- To handle URI definitions that contain ";" or ",", a quoted-URI format was introduced and is required. ๐
- IANA registries for the Transport header parameters, transport-protocol, profile, lower-transport, and mode were defined. ๐
- The text on the Transport header's interleaved parameter was made more strict and uses formal requirements levels. It was also clarified that the interleaved channels are symmetric and that the server is the one that sets the channel numbers. ๐ฅ
- It was clarified that the client can't ask the server to use a certain RTP SSRC, using a request with the transport parameter
SSRC. ๐ - The syntax definition for
SSRCwas clarified to require 8HEX. It was also extended to allow multiple values for clients supporting this version. โญ - The text on the Transport header's
dest_addrparameter was clarified regarding what security precautions the server is required to perform. ๐
- The Range formats changed in these ways:
- The NPT format was given an initial NPT identifier that must now be used. ๐
- All formats now support initial open-ended formats of the type
npt=-10, and also support format-onlyRange: smpteranges for use with GET_PARAMETER requests. ๐ง - The npt-hhmmss notation now follows ISO 8601 more strictly. ๐ฆ
- RTSP message handling changed in these ways:
- RTSP messages now use URIs rather than URLs. ๐
- It was clarified that a 4xx message due to a missing
CSeqheader shall be returned without aCSeqheader. ๐ - The 300 (Multiple Choices) response code was removed. ๐
- Rules for handling timed-out RTSP messages were added. โฐ
- Extended pipelining rules were added, allowing for quick session startup. ๐
- Sequence numbering and proxy handling of sequence numbers were defined, including cases where responses arrive out of order. ๐ธ
- The HTTP references were updated, first to RFCs 2616 and 2617 and then to RFC 7230-7235. Most of the text was copied and then altered to fit RTSP into this specification. The
PublicandContent-Baseheaders were also imported from RFC 2068, so they're defined in the RTSP specification. Known effects on RTSP from HTTP clarifications include: ๐- The
Content-Encodingheader can include encoding of type "identity". โจ
- The
- The state machine section was completely rewritten. It now includes more details and is clearer about the model it uses. ๐ฅ
- An IANA section was included with a number of registries and their rules. This lets us use IANA to keep track of RTSP extensions. ๐
- The transport of RTSP messages saw these changes:
- The use of UDP for RTSP message transport was deprecated, due to missing interest and to broken specification. ๐
- The rules for handling TCP connections were clarified. It's now made clear that servers should not close the TCP connection unless they've been unused for a significant time. ๐ง
- Strong recommendations on why servers and clients should use persistent connections were added. ๐
- Servers now have a requirement to handle non-persistent connections, since this provides fault tolerance. ๐ก๏ธ
- Wording on the usage of
Connection:Closefor RTSP was added. ๐ - The usage of TLS for RTSP messages was specified, including a scheme to approve a proxy's TLS connection to the next hop. ๐
- The following header-related changes were made:
- The
Accept-Rangesresponse header was added. It clarifies which range formats can be used for a resource. ๐ฆ - The missing definitions for the
Cache-Controlheader were fixed. The syntax definition also got the missing delta-seconds for the max-stale and min-fresh parameters. ๐
- The
- Okay so the CSeq header has to go up by one for every single new RTSP request ๐ข A recommendation to start at 0 got added too, which is lowkey adorable.
- Bestie, the Date header is now a must for every message with a message body, and the Server should always include it ๐
- The Range header can't be used with Scale to say when scaling kicks in anymore, because it literally couldn't work as defined ๐ Also, if a response has no Scale header, that means the server doesn't support it. Feature tags for scaled playback got defined too โจ
- The Speed header has to get a response now, so the server can say it supports it and what speed it's actually going to use ๐๏ธ There's a feature tag for it, and congestion control notes got added too.
- The Supported header was borrowed from SIP [RFC3261] to help with feature negotiation in RTSP ๐ค
- The Timestamp header can be used to clear up retransmission ambiguities. Iconic ๐
- The Session header text got a whole glow-up with an explanation of keep-alive and which methods to use. SET_PARAMETER is now the recommended pick if you only want keep-alive inside RTSP ๐ธ
- It's now clear how the Range header formats are used to show pause points in the PAUSE response โธ๏ธ
- RTP-Info URIs that are relative use the Request-URI as the base URI. The URI also has to be the one that was used in the SETUP request. The URIs must be quoted now, and the header shows the SSRC for the RTP timestamp and sequence number values ๐
- Added text that says the Range must always be present in PLAY responses. It's also clear what gets sent for live streams ๐ฆ
- The headers table got updated using a structure borrowed from SIP. Those tables hold way more info and give you a great overview of the available headers ๐
- Any message with a message body is required to have a Content-Length header. This was already the case in RFC 2326, but people could misread it ๐
- ETag changed its name to MTag ๐ท๏ธ
- To make MTag work properly, the MTag and If-None-Match headers got imported from HTTP, with clarifications for how RTSP uses them ๐
- The Public header got imported from HTTP (RFC 2068 [RFC2068]). HTTP dropped it because nobody used it, but RTSP uses it constantly ๐ฃ
- The rules for filling in Public got clarified. It's now the intersection of what all the RTSP agents in a chain can do ๐
- The Media-Range header is new! It lists what the media range currently has available ๐
- The Notify-Reason header is new too. It tells you why a PLAY_NOTIFY request was sent ๐
- Meet the new Seek-Style header, which says how a seek operation should be done, or how it was done ๐ฏ
- The Protocol Syntax got a glow-up too:
- All the ABNF definitions now follow RFC 5234 [RFC5234] and live together in their own section (Section 20) ๐
- The ABNF for the User-Agent and Server headers got fixed ๐ ๏ธ
- Some intro definitions about the RTSP session got changed ๐ญ
- The protocol is now fully IPv6 capable ๐
- The CHAR rule now excludes NULL ๐ซ
- The Status codes got some changes:
- Status code 303 (See Other) is deprecated, since it makes no sense in RTSP ๐
- The never-defined status code 411 "Length Required" got removed completely ๐
- When you send 451 (Parameter Not Understood) or 458 (Parameter Is Read-Only), the response body should contain the offending parameters ๐งพ
- It's now clear when a 3rr redirect status code can be received, including when it comes back from a request inside an established session. This clears up behaviour that wasn't specified before ๐
- 201 (Created) and 250 (Low On Storage Space) got removed, since they only mattered for recording, which is deprecated ๐ผ
- Several new status codes got defined: 464 (Data Transport Not Ready Yet), 465 (Notification Reason Unknown), 470 (Connection Authorization Required), 471 (Connection Credentials Not Accepted), and 472 (Failure to Establish Secure Connection) โจ
- Some stuff got deprecated, and honestly it's giving retirement ๐ง
- Queued Play is deprecated ๐ซ
- Using the PLAY method for keep-alive in Play state is deprecated ๐ซ
- RECORD and ANNOUNCE and all related functionality are deprecated. Some of the syntax got removed too ๐ผ
- Timed execution of methods with the time parameter in the Range header is deprecated โณ
- How rtspu works isn't part of the core spec anymore. The spec only says it exists and gives some requirements for the transport, and it'll need outside docs ๐
- The method changes are a whole mood ๐ฌ
- OPTIONS got clarified for how to use the Public and Allow headers ๐
- There's new text on using SET_PARAMETER for keep-alive, including when there's no body ๐
- PLAY can now be pipelined with one or more SETUP requests that come after the first one that creates the session, for aggregated control ๐
- REDIRECT got expanded and split up for different situations ๐งญ
- A brand new method, PLAY_NOTIFY, was added. The RTSP server uses it to asynchronously tell clients about session changes ๐
- A brand new section explains how to set up different media-transport alternatives, their profiles, and the lower-layer protocols. The appendix on RTP interaction got moved into this new section instead of living in the RTP part. The new section also has guidelines for what to think about when writing usage guidelines for new protocols and profiles ๐บ๏ธ
- Setup and use of independent TCP connections for transporting RTP is now specified ๐
- There's a new section called "Capability Handling" that covers the ways to figure out if something is supported. Option-tags got renamed to feature tags ๐ท๏ธ
- There's a Contributors section now, for people who wrote actual text for the spec ๐ซถ
- There's a "Use Cases" section that covers the major RTSP use cases ๐ฅ
- The usage of a=range got clarified, including how to show live content that can't be seeked with this header ๐ป
- There's special PLAY behaviour for live content, and it's written down now ๐ด
- Security got tightened up, and it's serious business ๐
- HTTP-based authorization is clarified, and it requires both Basic and Digest support ๐
- TLS support is mandated ๐ก๏ธ
- If you implement RTP, then SRTP and the defined MIKEY-based key-exchange must be supported ๐๏ธ
- Various minor mitigations got discussed, and some of them caused protocol changes ๐งฑ
Acknowledgements ๐
This memorandum defines RTSP version 2.0, which is a revision of the Proposed Standard RTSP version 1.0 defined in [RFC2326]. The authors of RFC 2326 are Henning Schulzrinne, Anup Rao, and Robert Lanphier ๐
Both RTSP version 1.0 and RTSP version 2.0 borrow format and descriptions from HTTP/1.1 ๐ค
Robert Sparks and especially Elwyn Davies gave super valuable and detailed reviews in the IETF Last Call. They made the document way better and fixed a ton of issues, especially around consistency ๐
This document has benefited a lot from comments by everyone in the MMUSIC WG ๐ฅฐ Besides the people already mentioned, these individuals also contributed to this specification:
Rahul Agarwal, Claudio Allocchio, Jeff Ayars, Milko Boic, Torsten Braun, Brent Browning, Bruce Butterfield, Steve Casner, Maureen Chesire, Jinhang Choi, Francisco Cortes, Elwyn Davies, Spencer Dawkins, Kelly Djahandari, Martin Dunsmuir, Adrian Farrel, Stephen Farrell, Ross Finlayson, Eric Fleischman, Jay Geagan, Andy Grignon, Christian Groves, V. Guruprasad, Peter Haight, Mark Handley, Brad Hefta-Gaub, Volker Hilt, John K. Ho, Patrick Hoffman, Go Hori, Philipp Hoschka, Anne Jones, Ingemar Johansson, Jae-Hwan Kim, Anders Klemets, Ruth Lang, Barry Leiba, Stephanie Leif, Jonathan Lennox, Eduardo F. Llach, Chris Lonvick, Xavier Marjou, Thomas Marshall, Rob McCool, Martti Mela, David Oran, Joerg Ott, Joe Pallas, Maria Papadopouli, Sujal Patel, Ema Patki, Alagu Periyannan, Colin Perkins, Pekka Pessi, Igor Plotnikov, Pete Resnick, Peter Saint-Andre, Holger Schmidt, Jonathan Sergent, Pinaki Shah, David Singer, Lior Sion, Jeff Smith, Alexander Sokolsky, Dale Stammen, John Francis Stracke, Geetha Srikantan, Scott Taylor, David Walker, Stephan Wenger, Dale R. Worley, and Byungjo Yoon, and especially Flemming Andreasen ๐
Contributors ๐
The following people made written contributions that got included in the specification:
- Tom Marshall contributed text on the usage of 3rr status codes.
- Thomas Zheng contributed text on the usage of the Range in PLAY responses and proposed an earlier version of the PLAY_NOTIFY method.
- Sean Sheedy contributed text on the timeout behavior of RTSP messages and connections, the 463 (Destination Prohibited) status code, and proposed an earlier version of the PLAY_NOTIFY method.
- Greg Sherwood proposed an earlier version of the PLAY_NOTIFY method.
- Fredrik Lindholm contributed text about the RTSP security framework.
- John Lazzaro contributed the text for RTP over Independent TCP.
- Aravind Narasimhan contributed by rewriting "Media-Transport Alternatives" (Appendix C) and making editorial improvements in a number of places in the specification.
- Torbjorn Einarsson has done some editorial improvements of the text.
Authors' Addresses ๐
Henning Schulzrinne
Columbia University
1214 Amsterdam Avenue
New York, NY 10027
United States of America
Email: schulzrinne@cs.columbia.edu
Anup Rao
Cisco
United States of America
Email: anrao@cisco.com
Rob Lanphier
San Francisco, CA
United States of America
Email: robla@robla.net
Magnus Westerlund
Ericsson
Faeroegatan 2
Stockholm SE-164 80
Sweden
Email: magnus.westerlund@ericsson.com
Martin Stiemerling (editor)
University of Applied Sciences Darmstadt
Haardtring 100
64295 Darmstadt
Germany
Email: mls.ietf@gmail.com
URI: http://www.stiemerling.org
๐ฆ where this page comes from
- ietf: rfc7826 2016-12
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms