123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- #include "rtp_header_extension/rtp_header_extensions.h"
- #include <string.h>
- #include <cmath>
- #include <limits>
- #include "rtp_header_extension/byte_io.h"
- // Absolute send time in RTP streams.
- //
- // The absolute send time is signaled to the receiver in-band using the
- // general mechanism for RTP header extensions [RFC8285]. The payload
- // of this extension (the transmitted value) is a 24-bit unsigned integer
- // containing the sender's current time in seconds as a fixed point number
- // with 18 bits fractional part.
- //
- // The form of the absolute send time extension block:
- //
- // 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
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | ID | len=2 | absolute send time |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- bool AbsoluteSendTime::Parse(const uint8_t *data,
- uint32_t* time_24bits) {
- *time_24bits = ByteReader<uint32_t, 3>::ReadBigEndian(data);
- return true;
- }
- bool AbsoluteSendTime::Write(uint8_t *data,
- uint32_t time_24bits) {
- ByteWriter<uint32_t, 3>::WriteBigEndian(data, time_24bits);
- return true;
- }
- const char AbsoluteSendTime::kUri[] =
- "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time";
- // An RTP Header Extension for Client-to-Mixer Audio Level Indication
- //
- // https://datatracker.ietf.org/doc/draft-lennox-avt-rtp-audio-level-exthdr/
- //
- // The form of the audio level extension block:
- //
- // 0 1
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | ID | len=0 |V| level |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- //
- bool AudioLevel::Parse(const uint8_t *data,
- bool* voice_activity,
- uint8_t* audio_level) {
- *voice_activity = (data[0] & 0x80) != 0;
- *audio_level = data[0] & 0x7F;
- return true;
- }
- bool AudioLevel::Write(uint8_t *data,
- bool voice_activity,
- uint8_t audio_level) {
- data[0] = (voice_activity ? 0x80 : 0x00) | audio_level;
- return true;
- }
- const char AudioLevel::kUri[] =
- "urn:ietf:params:rtp-hdrext:ssrc-audio-level";
- // From RFC 5450: Transmission Time Offsets in RTP Streams.
- //
- // The transmission time is signaled to the receiver in-band using the
- // general mechanism for RTP header extensions [RFC8285]. The payload
- // of this extension (the transmitted value) is a 24-bit signed integer.
- // When added to the RTP timestamp of the packet, it represents the
- // "effective" RTP transmission time of the packet, on the RTP
- // timescale.
- //
- // The form of the transmission offset extension block:
- //
- // 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
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | ID | len=2 | transmission offset |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- bool TransmissionOffset::Parse(const uint8_t *data,
- int32_t* rtp_time) {
- *rtp_time = ByteReader<int32_t, 3>::ReadBigEndian(data);
- return true;
- }
- bool TransmissionOffset::Write(uint8_t *data, int32_t rtp_time) {
- ByteWriter<int32_t, 3>::WriteBigEndian(data, rtp_time);
- return true;
- }
- const char TransmissionOffset::kUri[] = "urn:ietf:params:rtp-hdrext:toffset";
- // TransportSequenceNumber
- //
- // 0 1 2
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | ID | L=1 |transport-wide sequence number |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- bool TransportSequenceNumber::Parse(const uint8_t *data,
- uint16_t* transport_sequence_number) {
- *transport_sequence_number = ByteReader<uint16_t>::ReadBigEndian(data);
- return true;
- }
- bool TransportSequenceNumber::Write(uint8_t *data,
- uint16_t transport_sequence_number) {
- ByteWriter<uint16_t>::WriteBigEndian(data, transport_sequence_number);
- return true;
- }
- const char TransportSequenceNumber::kUri[] =
- "http://www.ietf.org/id/"
- "draft-holmer-rmcat-transport-wide-cc-extensions-01";
- // Coordination of Video Orientation in RTP streams.
- //
- // Coordination of Video Orientation consists in signaling of the current
- // orientation of the image captured on the sender side to the receiver for
- // appropriate rendering and displaying.
- //
- // 0 1
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | ID | len=0 |0 0 0 0 C F R R|
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- bool VideoOrientation::Parse(const uint8_t *data,
- VideoRotation* rotation) {
- *rotation = ConvertCVOByteToVideoRotation(data[0]);
- return true;
- }
- bool VideoOrientation::Write(uint8_t *data,
- VideoRotation rotation) {
- data[0] = ConvertVideoRotationToCVOByte(rotation);
- return true;
- }
- bool VideoOrientation::Parse(const uint8_t *data,
- uint8_t* value) {
- *value = data[0];
- return true;
- }
- bool VideoOrientation::Write(uint8_t *data, uint8_t value) {
- data[0] = value;
- return true;
- }
- const char VideoOrientation::kUri[] = "urn:3gpp:video-orientation";
- // 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
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | ID | len=2 | MIN delay | MAX delay |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- bool PlayoutDelayLimits::Parse(const uint8_t *data,
- PlayoutDelay* playout_delay) {
- uint32_t raw = ByteReader<uint32_t, 3>::ReadBigEndian(data);
- uint16_t min_raw = (raw >> 12);
- uint16_t max_raw = (raw & 0xfff);
- if (min_raw > max_raw)
- return false;
- playout_delay->min_ms = min_raw * kGranularityMs;
- playout_delay->max_ms = max_raw * kGranularityMs;
- return true;
- }
- bool PlayoutDelayLimits::Write(uint8_t *data,
- const PlayoutDelay& playout_delay) {
- // Convert MS to value to be sent on extension header.
- uint32_t min_delay = playout_delay.min_ms / kGranularityMs;
- uint32_t max_delay = playout_delay.max_ms / kGranularityMs;
- ByteWriter<uint32_t, 3>::WriteBigEndian(data,
- (min_delay << 12) | max_delay);
- return true;
- }
- const char PlayoutDelayLimits::kUri[] =
- "http://www.webrtc.org/experiments/rtp-hdrext/playout-delay";
- // Video Content Type.
- //
- // E.g. default video or screenshare.
- //
- // 0 1
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | ID | len=0 | Content type |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- bool VideoContentTypeExtension::Parse(const uint8_t *data,
- VideoContentType* content_type) {
- *content_type = static_cast<VideoContentType>(data[0]);
- return true;
- }
- bool VideoContentTypeExtension::Write(uint8_t *data,
- VideoContentType content_type) {
- data[0] = static_cast<uint8_t>(content_type);
- return true;
- }
- const char VideoContentTypeExtension::kUri[] =
- "http://www.webrtc.org/experiments/rtp-hdrext/video-content-type";
- bool BaseRtpStringExtension::Parse(const uint8_t *data,
- std::string* str) {
- if (data[0] == 0) // Valid string extension can't be empty.
- return false;
- const char* cstr = reinterpret_cast<const char*>(data);
- // If there is a \0 character in the middle of the |data|, treat it as end
- // of the string. Well-formed string extensions shouldn't contain it.
- str->assign(cstr, strlen(cstr));
- return true;
- }
- bool BaseRtpStringExtension::Write(uint8_t *data,
- const std::string& str) {
- if (str.size() > kMaxValueSizeBytes) {
- return false;
- }
- memcpy(data, str.data(), str.size());
- return true;
- }
- const char RtpStreamId::kUri[] =
- "urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id";
- const char RepairedRtpStreamId::kUri[] =
- "urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id";
- const char RtpMid::kUri[] = "urn:ietf:params:rtp-hdrext:sdes:mid";
- RTPHeaderExtension::RTPHeaderExtension()
- : hasTransmissionTimeOffset(false),
- transmissionTimeOffset(0),
- hasAbsoluteSendTime(false),
- absoluteSendTime(0),
- hasTransportSequenceNumber(false),
- transportSequenceNumber(0),
- hasAudioLevel(false),
- voiceActivity(false),
- audioLevel(0),
- hasVideoRotation(false),
- videoRotation(kVideoRotation_0),
- hasVideoContentType(false),
- videoContentType(VideoContentType::UNSPECIFIED) {
- playout_delay.max_ms = -1;
- playout_delay.min_ms = -1;
- }
- RtpExtension::RtpExtension(){
- id = 0;
- encrypt = false;
- };
- RtpExtension::RtpExtension(const std::string& uri, int id) : uri(uri), id(id) {RtpExtension();}
- RtpExtension::RtpExtension(const std::string& uri, int id, bool encrypt)
- : uri(uri), id(id), encrypt(encrypt) {RtpExtension();}
- RtpExtension::~RtpExtension(){};
- const char RtpExtension::kAudioLevelUri[] =
- "urn:ietf:params:rtp-hdrext:ssrc-audio-level";
- const char RtpExtension::kTimestampOffsetUri[] =
- "urn:ietf:params:rtp-hdrext:toffset";
- const char RtpExtension::kAbsSendTimeUri[] =
- "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time";
- const char RtpExtension::kVideoRotationUri[] = "urn:3gpp:video-orientation";
- const char RtpExtension::kTransportSequenceNumberUri[] =
- "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01";
- // This extension allows applications to adaptively limit the playout delay
- // on frames as per the current needs. For example, a gaming application
- // has very different needs on end-to-end delay compared to a video-conference
- // application.
- const char RtpExtension::kPlayoutDelayUri[] =
- "http://www.webrtc.org/experiments/rtp-hdrext/playout-delay";
- const char RtpExtension::kVideoContentTypeUri[] =
- "http://www.webrtc.org/experiments/rtp-hdrext/video-content-type";
- const char RtpExtension::kMidUri[] = "urn:ietf:params:rtp-hdrext:sdes:mid";
- const char RtpExtension::kEncryptHeaderExtensionsUri[] =
- "urn:ietf:params:rtp-hdrext:encrypt";
- const char RtpExtension::kRidUri[] =
- "urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id";
- const char RtpExtension::kRepairedRidUri[] =
- "urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id";
- bool RtpExtension::IsSupportedForAudio(const std::string& uri) {
- return uri == RtpExtension::kAudioLevelUri ||
- uri == RtpExtension::kTransportSequenceNumberUri ||
- uri == RtpExtension::kMidUri ||
- uri == RtpExtension::kRidUri ||
- uri == RtpExtension::kRepairedRidUri;
- }
- bool RtpExtension::IsSupportedForVideo(const std::string& uri) {
- return uri == RtpExtension::kTimestampOffsetUri ||
- uri == RtpExtension::kAbsSendTimeUri ||
- uri == RtpExtension::kVideoRotationUri ||
- uri == RtpExtension::kTransportSequenceNumberUri ||
- uri == RtpExtension::kPlayoutDelayUri ||
- uri == RtpExtension::kVideoContentTypeUri ||
- uri == RtpExtension::kMidUri ||
- uri == RtpExtension::kRidUri ||
- uri == RtpExtension::kRepairedRidUri;
- }
- bool RtpExtension::IsEncryptionSupported(const std::string& uri) {
- return uri == RtpExtension::kAudioLevelUri ||
- uri == RtpExtension::kTimestampOffsetUri ||
- #if !defined(ENABLE_EXTERNAL_AUTH)
- // TODO(jbauch): Figure out a way to always allow "kAbsSendTimeUri"
- // here and filter out later if external auth is really used in
- // srtpfilter. External auth is used by Chromium and replaces the
- // extension header value of "kAbsSendTimeUri", so it must not be
- // encrypted (which can't be done by Chromium).
- uri == RtpExtension::kAbsSendTimeUri ||
- #endif
- uri == RtpExtension::kVideoRotationUri ||
- uri == RtpExtension::kTransportSequenceNumberUri ||
- uri == RtpExtension::kPlayoutDelayUri ||
- uri == RtpExtension::kVideoContentTypeUri ||
- uri == RtpExtension::kMidUri ||
- uri == RtpExtension::kRidUri ||
- uri == RtpExtension::kRepairedRidUri;
- }
- const RtpExtension* RtpExtension::FindHeaderExtensionByUri(
- const std::vector<RtpExtension>& extensions,
- const std::string& uri) {
- for(int i = 0; i < extensions.size(); i++){
- if (extensions[i].uri == uri) {
- return &extensions[i];
- }
- }
- return nullptr;
- }
|