1*3f982cf4SFabien Sanglard // Copyright 2019 The Chromium Authors. All rights reserved. 2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be 3*3f982cf4SFabien Sanglard // found in the LICENSE file. 4*3f982cf4SFabien Sanglard 5*3f982cf4SFabien Sanglard #ifndef CAST_STREAMING_RTP_DEFINES_H_ 6*3f982cf4SFabien Sanglard #define CAST_STREAMING_RTP_DEFINES_H_ 7*3f982cf4SFabien Sanglard 8*3f982cf4SFabien Sanglard #include <stdint.h> 9*3f982cf4SFabien Sanglard 10*3f982cf4SFabien Sanglard #include "cast/streaming/constants.h" 11*3f982cf4SFabien Sanglard 12*3f982cf4SFabien Sanglard namespace openscreen { 13*3f982cf4SFabien Sanglard namespace cast { 14*3f982cf4SFabien Sanglard 15*3f982cf4SFabien Sanglard // Note: Cast Streaming uses a subset of the messages in the RTP/RTCP 16*3f982cf4SFabien Sanglard // specification, but also adds some of its own extensions. See: 17*3f982cf4SFabien Sanglard // https://tools.ietf.org/html/rfc3550 18*3f982cf4SFabien Sanglard 19*3f982cf4SFabien Sanglard // Uniquely identifies one packet within a frame. These are sequence numbers, 20*3f982cf4SFabien Sanglard // starting at 0. Each Cast RTP packet also includes the "last ID" so that a 21*3f982cf4SFabien Sanglard // receiver always knows the range of valid FramePacketIds for a given frame. 22*3f982cf4SFabien Sanglard using FramePacketId = uint16_t; 23*3f982cf4SFabien Sanglard 24*3f982cf4SFabien Sanglard // A special FramePacketId value meant to represent "all packets lost" in Cast 25*3f982cf4SFabien Sanglard // RTCP Feedback messages. 26*3f982cf4SFabien Sanglard constexpr FramePacketId kAllPacketsLost = 0xffff; 27*3f982cf4SFabien Sanglard constexpr FramePacketId kMaxAllowedFramePacketId = kAllPacketsLost - 1; 28*3f982cf4SFabien Sanglard 29*3f982cf4SFabien Sanglard // The maximum size of any RTP or RTCP packet, in bytes. The calculation below 30*3f982cf4SFabien Sanglard // is: Standard Ethernet MTU bytes minus IP header bytes minus UDP header bytes. 31*3f982cf4SFabien Sanglard // The remainder is available for RTP/RTCP packet data (header + payload). 32*3f982cf4SFabien Sanglard // 33*3f982cf4SFabien Sanglard // A nice explanation of this: https://jvns.ca/blog/2017/02/07/mtu/ 34*3f982cf4SFabien Sanglard // 35*3f982cf4SFabien Sanglard // Constants are provided here for UDP over IPv4 and IPv6 on Ethernet. Other 36*3f982cf4SFabien Sanglard // transports and network mediums will need additional consideration, alternate 37*3f982cf4SFabien Sanglard // calculations. Note that MTU is dynamic, depending on the path the packets 38*3f982cf4SFabien Sanglard // take between two endpoints (the 1500 here is just a commonly-used value for 39*3f982cf4SFabien Sanglard // LAN Ethernet). 40*3f982cf4SFabien Sanglard constexpr int kMaxRtpPacketSizeForIpv4UdpOnEthernet = 1500 - 20 - 8; 41*3f982cf4SFabien Sanglard constexpr int kMaxRtpPacketSizeForIpv6UdpOnEthernet = 1500 - 40 - 8; 42*3f982cf4SFabien Sanglard 43*3f982cf4SFabien Sanglard // The Cast RTP packet header: 44*3f982cf4SFabien Sanglard // 45*3f982cf4SFabien Sanglard // 0 1 2 3 46*3f982cf4SFabien Sanglard // 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 47*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ^ 48*3f982cf4SFabien Sanglard // |V=2|P|X| CC=0 |M| PT | sequence number | | 49*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+RTP 50*3f982cf4SFabien Sanglard // + RTP timestamp |Spec 51*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 52*3f982cf4SFabien Sanglard // + synchronization source (SSRC) identifier | v 53*3f982cf4SFabien Sanglard // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 54*3f982cf4SFabien Sanglard // |K|R| EXT count | FID | PID | ^ 55*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+Cast 56*3f982cf4SFabien Sanglard // | Max PID | optional fields, extensions, Spec 57*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ then payload... v 58*3f982cf4SFabien Sanglard // 59*3f982cf4SFabien Sanglard // Byte 0: Version 2, no padding, no RTP extensions, no CSRCs. 60*3f982cf4SFabien Sanglard // Byte 1: Marker bit indicates whether this is the last packet, followed by a 61*3f982cf4SFabien Sanglard // 7-bit payload type. 62*3f982cf4SFabien Sanglard // Byte 12: Key Frame bit, followed by "RFID will be provided" bit, followed by 63*3f982cf4SFabien Sanglard // 6 bits specifying the number of extensions that will be provided. 64*3f982cf4SFabien Sanglard 65*3f982cf4SFabien Sanglard // The minimum-possible valid size of a Cast RTP packet (i.e., no optional 66*3f982cf4SFabien Sanglard // fields, extensions, nor payload). 67*3f982cf4SFabien Sanglard constexpr int kRtpPacketMinValidSize = 18; 68*3f982cf4SFabien Sanglard 69*3f982cf4SFabien Sanglard // All Cast RTP packets must carry the version 2 flag, not use padding, not use 70*3f982cf4SFabien Sanglard // RTP extensions, and have zero CSRCs. 71*3f982cf4SFabien Sanglard constexpr uint8_t kRtpRequiredFirstByte = 0b10000000; 72*3f982cf4SFabien Sanglard 73*3f982cf4SFabien Sanglard // Bitmasks to isolate fields within byte 2 of the Cast RTP header. 74*3f982cf4SFabien Sanglard constexpr uint8_t kRtpMarkerBitMask = 0b10000000; 75*3f982cf4SFabien Sanglard constexpr uint8_t kRtpPayloadTypeMask = 0b01111111; 76*3f982cf4SFabien Sanglard 77*3f982cf4SFabien Sanglard // Describes the content being transported over RTP streams. These are Cast 78*3f982cf4SFabien Sanglard // Streaming specific assignments, within the "dynamic" range provided by 79*3f982cf4SFabien Sanglard // IANA. Note that this Cast Streaming implementation does not manipulate 80*3f982cf4SFabien Sanglard // already-encoded data, and so these payload types are only "informative" in 81*3f982cf4SFabien Sanglard // purpose and can be used to check for corruption while parsing packets. 82*3f982cf4SFabien Sanglard enum class RtpPayloadType : uint8_t { 83*3f982cf4SFabien Sanglard kNull = 0, 84*3f982cf4SFabien Sanglard 85*3f982cf4SFabien Sanglard kAudioFirst = 96, 86*3f982cf4SFabien Sanglard kAudioOpus = 96, 87*3f982cf4SFabien Sanglard kAudioAac = 97, 88*3f982cf4SFabien Sanglard kAudioPcm16 = 98, 89*3f982cf4SFabien Sanglard kAudioVarious = 99, // Codec being used is not fixed. 90*3f982cf4SFabien Sanglard 91*3f982cf4SFabien Sanglard kVideoFirst = 100, 92*3f982cf4SFabien Sanglard kVideoVp8 = 100, 93*3f982cf4SFabien Sanglard kVideoH264 = 101, 94*3f982cf4SFabien Sanglard kVideoVarious = 102, // Codec being used is not fixed. 95*3f982cf4SFabien Sanglard kVideoVp9 = 103, 96*3f982cf4SFabien Sanglard kVideoAv1 = 104, 97*3f982cf4SFabien Sanglard kVideoLast = kVideoAv1, 98*3f982cf4SFabien Sanglard 99*3f982cf4SFabien Sanglard // Some AndroidTV receivers require the payload type for audio to be 127, and 100*3f982cf4SFabien Sanglard // video to be 96; regardless of the codecs actually being used. This is 101*3f982cf4SFabien Sanglard // definitely out-of-spec, and inconsistent with the audio versus video range 102*3f982cf4SFabien Sanglard // of values, but must be taken into account for backwards-compatibility. 103*3f982cf4SFabien Sanglard kAudioHackForAndroidTV = 127, 104*3f982cf4SFabien Sanglard kVideoHackForAndroidTV = 96, 105*3f982cf4SFabien Sanglard }; 106*3f982cf4SFabien Sanglard 107*3f982cf4SFabien Sanglard // Setting |use_android_rtp_hack| to true means that we match the legacy Chrome 108*3f982cf4SFabien Sanglard // sender's behavior of always sending the audio and video hacks for AndroidTV, 109*3f982cf4SFabien Sanglard // as some legacy android receivers require these. 110*3f982cf4SFabien Sanglard // TODO(issuetracker.google.com/184438154): we need to figure out what receivers 111*3f982cf4SFabien Sanglard // need this still, if any. The hack should be removed when possible. 112*3f982cf4SFabien Sanglard RtpPayloadType GetPayloadType(AudioCodec codec, bool use_android_rtp_hack); 113*3f982cf4SFabien Sanglard RtpPayloadType GetPayloadType(VideoCodec codec, bool use_android_rtp_hack); 114*3f982cf4SFabien Sanglard 115*3f982cf4SFabien Sanglard // Returns true if the |raw_byte| can be type-casted to a RtpPayloadType, and is 116*3f982cf4SFabien Sanglard // also not RtpPayloadType::kNull. The caller should mask the byte, to select 117*3f982cf4SFabien Sanglard // the lower 7 bits, if applicable. 118*3f982cf4SFabien Sanglard bool IsRtpPayloadType(uint8_t raw_byte); 119*3f982cf4SFabien Sanglard 120*3f982cf4SFabien Sanglard // Bitmasks to isolate fields within byte 12 of the Cast RTP header. 121*3f982cf4SFabien Sanglard constexpr uint8_t kRtpKeyFrameBitMask = 0b10000000; 122*3f982cf4SFabien Sanglard constexpr uint8_t kRtpHasReferenceFrameIdBitMask = 0b01000000; 123*3f982cf4SFabien Sanglard constexpr uint8_t kRtpExtensionCountMask = 0b00111111; 124*3f982cf4SFabien Sanglard 125*3f982cf4SFabien Sanglard // Cast extensions. This implementation supports only the Adaptive Latency 126*3f982cf4SFabien Sanglard // extension, and ignores all others: 127*3f982cf4SFabien Sanglard // 128*3f982cf4SFabien Sanglard // 0 1 2 3 129*3f982cf4SFabien Sanglard // 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 130*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 131*3f982cf4SFabien Sanglard // | TYPE = 1 | Ext data SIZE = 2 |Playout Delay (unsigned millis)| 132*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 133*3f982cf4SFabien Sanglard // 134*3f982cf4SFabien Sanglard // The Adaptive Latency extension permits changing the fixed end-to-end playout 135*3f982cf4SFabien Sanglard // delay of a single RTP stream. 136*3f982cf4SFabien Sanglard constexpr uint8_t kAdaptiveLatencyRtpExtensionType = 1; 137*3f982cf4SFabien Sanglard constexpr int kNumExtensionDataSizeFieldBits = 10; 138*3f982cf4SFabien Sanglard 139*3f982cf4SFabien Sanglard // RTCP Common Header: 140*3f982cf4SFabien Sanglard // 141*3f982cf4SFabien Sanglard // 0 1 2 3 142*3f982cf4SFabien Sanglard // 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 143*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 144*3f982cf4SFabien Sanglard // |V=2|P|RC/Subtyp| Packet Type | Length | 145*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 146*3f982cf4SFabien Sanglard constexpr int kRtcpCommonHeaderSize = 4; 147*3f982cf4SFabien Sanglard // All RTCP packets must carry the version 2 flag and not use padding. 148*3f982cf4SFabien Sanglard constexpr uint8_t kRtcpRequiredVersionAndPaddingBits = 0b100; 149*3f982cf4SFabien Sanglard constexpr int kRtcpReportCountFieldNumBits = 5; 150*3f982cf4SFabien Sanglard 151*3f982cf4SFabien Sanglard // https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml 152*3f982cf4SFabien Sanglard enum class RtcpPacketType : uint8_t { 153*3f982cf4SFabien Sanglard kNull = 0, 154*3f982cf4SFabien Sanglard 155*3f982cf4SFabien Sanglard kSenderReport = 200, 156*3f982cf4SFabien Sanglard kReceiverReport = 201, 157*3f982cf4SFabien Sanglard kSourceDescription = 202, 158*3f982cf4SFabien Sanglard kApplicationDefined = 204, 159*3f982cf4SFabien Sanglard kPayloadSpecific = 206, 160*3f982cf4SFabien Sanglard kExtendedReports = 207, 161*3f982cf4SFabien Sanglard }; 162*3f982cf4SFabien Sanglard 163*3f982cf4SFabien Sanglard // Returns true if the |raw_byte| can be type-casted to a RtcpPacketType, and is 164*3f982cf4SFabien Sanglard // also not RtcpPacketType::kNull. 165*3f982cf4SFabien Sanglard bool IsRtcpPacketType(uint8_t raw_byte); 166*3f982cf4SFabien Sanglard 167*3f982cf4SFabien Sanglard // Supported subtype values in the RTCP Common Header when the packet type is 168*3f982cf4SFabien Sanglard // kApplicationDefined or kPayloadSpecific. 169*3f982cf4SFabien Sanglard enum class RtcpSubtype : uint8_t { 170*3f982cf4SFabien Sanglard kNull = 0, 171*3f982cf4SFabien Sanglard 172*3f982cf4SFabien Sanglard kPictureLossIndicator = 1, 173*3f982cf4SFabien Sanglard kReceiverLog = 2, 174*3f982cf4SFabien Sanglard kFeedback = 15, 175*3f982cf4SFabien Sanglard }; 176*3f982cf4SFabien Sanglard 177*3f982cf4SFabien Sanglard // RTCP Sender Report: 178*3f982cf4SFabien Sanglard // 179*3f982cf4SFabien Sanglard // 0 1 2 3 180*3f982cf4SFabien Sanglard // 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 181*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 182*3f982cf4SFabien Sanglard // | SSRC of Sender | 183*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 184*3f982cf4SFabien Sanglard // | | 185*3f982cf4SFabien Sanglard // | NTP Timestamp | 186*3f982cf4SFabien Sanglard // | | 187*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 188*3f982cf4SFabien Sanglard // | RTP Timestamp | 189*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 190*3f982cf4SFabien Sanglard // | Sender's Packet Count | 191*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 192*3f982cf4SFabien Sanglard // | Sender's Octet Count | 193*3f982cf4SFabien Sanglard // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 194*3f982cf4SFabien Sanglard // ...Followed by zero or more "Report Blocks"... 195*3f982cf4SFabien Sanglard constexpr int kRtcpSenderReportSize = 24; 196*3f982cf4SFabien Sanglard 197*3f982cf4SFabien Sanglard // RTCP Receiver Report: 198*3f982cf4SFabien Sanglard // 199*3f982cf4SFabien Sanglard // 0 1 2 3 200*3f982cf4SFabien Sanglard // 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 201*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 202*3f982cf4SFabien Sanglard // | SSRC of Receiver | 203*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 204*3f982cf4SFabien Sanglard // ...Followed by zero or more "Report Blocks"... 205*3f982cf4SFabien Sanglard constexpr int kRtcpReceiverReportSize = 4; 206*3f982cf4SFabien Sanglard 207*3f982cf4SFabien Sanglard // RTCP Report Block. For Cast Streaming, zero or one of these accompanies a 208*3f982cf4SFabien Sanglard // Sender or Receiver Report, which is different than the RTCP spec (which 209*3f982cf4SFabien Sanglard // allows zero or more). 210*3f982cf4SFabien Sanglard // 211*3f982cf4SFabien Sanglard // 0 1 2 3 212*3f982cf4SFabien Sanglard // 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 213*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 214*3f982cf4SFabien Sanglard // | "To" SSRC | 215*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 216*3f982cf4SFabien Sanglard // | Fraction Lost | Cumulative Number of Packets Lost | 217*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 218*3f982cf4SFabien Sanglard // | [32-bit extended] Highest Sequence Number Received | 219*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 220*3f982cf4SFabien Sanglard // | Interarrival Jitter Mean Absolute Deviation (in RTP Timebase) | 221*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 222*3f982cf4SFabien Sanglard // | Middle 32-bits of NTP Timestamp from last Sender Report | 223*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 224*3f982cf4SFabien Sanglard // | Delay since last Sender Report (1/65536 sec timebase) | 225*3f982cf4SFabien Sanglard // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 226*3f982cf4SFabien Sanglard constexpr int kRtcpReportBlockSize = 24; 227*3f982cf4SFabien Sanglard constexpr int kRtcpCumulativePacketsFieldNumBits = 24; 228*3f982cf4SFabien Sanglard 229*3f982cf4SFabien Sanglard // Cast Feedback Message: 230*3f982cf4SFabien Sanglard // 231*3f982cf4SFabien Sanglard // 0 1 2 3 232*3f982cf4SFabien Sanglard // 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 233*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 234*3f982cf4SFabien Sanglard // | SSRC of Receiver | 235*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 236*3f982cf4SFabien Sanglard // | SSRC of Sender | 237*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 238*3f982cf4SFabien Sanglard // | Unique identifier 'C' 'A' 'S' 'T' | 239*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 240*3f982cf4SFabien Sanglard // | CkPt Frame ID | # Loss Fields | Current Playout Delay (msec) | 241*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 242*3f982cf4SFabien Sanglard constexpr int kRtcpFeedbackHeaderSize = 16; 243*3f982cf4SFabien Sanglard constexpr uint32_t kRtcpCastIdentifierWord = 244*3f982cf4SFabien Sanglard (uint32_t{'C'} << 24) | (uint32_t{'A'} << 16) | (uint32_t{'S'} << 8) | 245*3f982cf4SFabien Sanglard uint32_t{'T'}; 246*3f982cf4SFabien Sanglard // 247*3f982cf4SFabien Sanglard // "Checkpoint Frame ID" indicates that all frames prior to and including this 248*3f982cf4SFabien Sanglard // one have been fully received. Unfortunately, the Frame ID is truncated to its 249*3f982cf4SFabien Sanglard // lower 8 bits in the packet, and 8 bits is not really enough: If a RTCP packet 250*3f982cf4SFabien Sanglard // is received very late (e.g., more than 1.2 seconds late for 100 FPS audio), 251*3f982cf4SFabien Sanglard // the Checkpoint Frame ID here will be mis-interpreted as representing a 252*3f982cf4SFabien Sanglard // higher-numbered frame than what was intended. This could make the sender's 253*3f982cf4SFabien Sanglard // tracking of "completely received" frames inconsistent, and Cast Streaming 254*3f982cf4SFabien Sanglard // would live-lock. However, this design issue has been baked into the spec and 255*3f982cf4SFabien Sanglard // millions of deployments over several years, and so there's no changing it 256*3f982cf4SFabien Sanglard // now. See kMaxUnackedFrames in constants.h. 257*3f982cf4SFabien Sanglard // 258*3f982cf4SFabien Sanglard // "# Loss fields" indicates the number of packet-level NACK words, 0 to 255: 259*3f982cf4SFabien Sanglard // 260*3f982cf4SFabien Sanglard // 0 1 2 3 261*3f982cf4SFabien Sanglard // 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 262*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 263*3f982cf4SFabien Sanglard // | w/in Frame ID | Lost Frame Packet ID | PID BitVector | 264*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 265*3f982cf4SFabien Sanglard constexpr int kRtcpFeedbackLossFieldSize = 4; 266*3f982cf4SFabien Sanglard // 267*3f982cf4SFabien Sanglard // "Within Frame ID" is a truncated-to-8-bits frame ID field and, when 268*3f982cf4SFabien Sanglard // bit-expanded should always be interpreted to represent a value greater than 269*3f982cf4SFabien Sanglard // the Checkpoint Frame ID. "Lost Frame Packet ID" is either a specific packet 270*3f982cf4SFabien Sanglard // (within the frame) that has not been received, or kAllPacketsLost to indicate 271*3f982cf4SFabien Sanglard // none the packets for the frame have been received yet. In the former case, 272*3f982cf4SFabien Sanglard // "PID Bit Vector" then represents which of the next 8 packets are also 273*3f982cf4SFabien Sanglard // missing. 274*3f982cf4SFabien Sanglard // 275*3f982cf4SFabien Sanglard // Finally, all of the above is optionally followed by a frame-level ACK bit 276*3f982cf4SFabien Sanglard // vector: 277*3f982cf4SFabien Sanglard // 278*3f982cf4SFabien Sanglard // 0 1 2 3 279*3f982cf4SFabien Sanglard // 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 280*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 281*3f982cf4SFabien Sanglard // | Unique identifier 'C' 'S' 'T' '2' | 282*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 283*3f982cf4SFabien Sanglard // |Feedback Count | # BVectOctets | ACK BitVect (2 to 254 bytes)... 284*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ → zero-padded to word boundary 285*3f982cf4SFabien Sanglard constexpr int kRtcpFeedbackAckHeaderSize = 6; 286*3f982cf4SFabien Sanglard constexpr uint32_t kRtcpCst2IdentifierWord = 287*3f982cf4SFabien Sanglard (uint32_t{'C'} << 24) | (uint32_t{'S'} << 16) | (uint32_t{'T'} << 8) | 288*3f982cf4SFabien Sanglard uint32_t{'2'}; 289*3f982cf4SFabien Sanglard constexpr int kRtcpMinAckBitVectorOctets = 2; 290*3f982cf4SFabien Sanglard constexpr int kRtcpMaxAckBitVectorOctets = 254; 291*3f982cf4SFabien Sanglard // 292*3f982cf4SFabien Sanglard // "Feedback Count" is a wrap-around counter indicating the number of Cast 293*3f982cf4SFabien Sanglard // Feedbacks that have been sent before this one. "# Bit Vector Octets" 294*3f982cf4SFabien Sanglard // indicates the number of bytes of ACK bit vector following. Cast RTCP 295*3f982cf4SFabien Sanglard // alignment/padding requirements (to 4-byte boundaries) dictates the following 296*3f982cf4SFabien Sanglard // rules for generating the ACK bit vector: 297*3f982cf4SFabien Sanglard // 298*3f982cf4SFabien Sanglard // 1. There must be at least 2 bytes of ACK bit vector, if only to pad the 6 299*3f982cf4SFabien Sanglard // byte header with two more bytes. 300*3f982cf4SFabien Sanglard // 2. If more than 2 bytes are needed, they must be added 4 at a time to 301*3f982cf4SFabien Sanglard // maintain the 4-byte alignment of the overall RTCP packet. 302*3f982cf4SFabien Sanglard // 3. The total number of octets may not exceed 255; but, because of #2, 254 303*3f982cf4SFabien Sanglard // is effectively the limit. 304*3f982cf4SFabien Sanglard // 4. The first bit in the first octet represents "Checkpoint Frame ID" plus 305*3f982cf4SFabien Sanglard // two. "Plus two" and not "plus one" because otherwise the "Checkpoint 306*3f982cf4SFabien Sanglard // Frame ID" should have been a greater value! 307*3f982cf4SFabien Sanglard 308*3f982cf4SFabien Sanglard // RTCP Extended Report: 309*3f982cf4SFabien Sanglard // 310*3f982cf4SFabien Sanglard // 0 1 2 3 311*3f982cf4SFabien Sanglard // 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 312*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 313*3f982cf4SFabien Sanglard // | SSRC of Report Author | 314*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 315*3f982cf4SFabien Sanglard constexpr int kRtcpExtendedReportHeaderSize = 4; 316*3f982cf4SFabien Sanglard // 317*3f982cf4SFabien Sanglard // ...followed by zero or more Blocks: 318*3f982cf4SFabien Sanglard // 319*3f982cf4SFabien Sanglard // 0 1 2 3 320*3f982cf4SFabien Sanglard // 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 321*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 322*3f982cf4SFabien Sanglard // | Block Type | Reserved = 0 | Block Length | 323*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 324*3f982cf4SFabien Sanglard // | ..."Block Length" words of report data... | 325*3f982cf4SFabien Sanglard // + + 326*3f982cf4SFabien Sanglard // + + 327*3f982cf4SFabien Sanglard constexpr int kRtcpExtendedReportBlockHeaderSize = 4; 328*3f982cf4SFabien Sanglard // 329*3f982cf4SFabien Sanglard // Cast Streaming only uses Receiver Reference Time Reports: 330*3f982cf4SFabien Sanglard // https://tools.ietf.org/html/rfc3611#section-4.4. So, the entire block would 331*3f982cf4SFabien Sanglard // be: 332*3f982cf4SFabien Sanglard // 333*3f982cf4SFabien Sanglard // 0 1 2 3 334*3f982cf4SFabien Sanglard // 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 335*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 336*3f982cf4SFabien Sanglard // | Block Type=4 | Reserved = 0 | Block Length = 2 | 337*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 338*3f982cf4SFabien Sanglard // | NTP Timestamp | 339*3f982cf4SFabien Sanglard // | | 340*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 341*3f982cf4SFabien Sanglard constexpr uint8_t kRtcpReceiverReferenceTimeReportBlockType = 4; 342*3f982cf4SFabien Sanglard constexpr int kRtcpReceiverReferenceTimeReportBlockSize = 8; 343*3f982cf4SFabien Sanglard 344*3f982cf4SFabien Sanglard // Cast Picture Loss Indicator Message: 345*3f982cf4SFabien Sanglard // 346*3f982cf4SFabien Sanglard // 0 1 2 3 347*3f982cf4SFabien Sanglard // 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 348*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 349*3f982cf4SFabien Sanglard // | SSRC of Receiver | 350*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 351*3f982cf4SFabien Sanglard // | SSRC of Sender | 352*3f982cf4SFabien Sanglard // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 353*3f982cf4SFabien Sanglard constexpr int kRtcpPictureLossIndicatorHeaderSize = 8; 354*3f982cf4SFabien Sanglard 355*3f982cf4SFabien Sanglard } // namespace cast 356*3f982cf4SFabien Sanglard } // namespace openscreen 357*3f982cf4SFabien Sanglard 358*3f982cf4SFabien Sanglard #endif // CAST_STREAMING_RTP_DEFINES_H_ 359