1 /* 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "modules/rtp_rtcp/source/rtcp_packet/dlrr.h" 12 13 #include "modules/rtp_rtcp/source/byte_io.h" 14 #include "rtc_base/checks.h" 15 #include "rtc_base/logging.h" 16 #include "rtc_base/numerics/safe_conversions.h" 17 18 namespace webrtc { 19 namespace rtcp { 20 // DLRR Report Block (RFC 3611). 21 // 22 // 0 1 2 3 23 // 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 24 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 25 // | BT=5 | reserved | block length | 26 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 27 // | SSRC_1 (SSRC of first receiver) | sub- 28 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block 29 // | last RR (LRR) | 1 30 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 31 // | delay since last RR (DLRR) | 32 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 33 // | SSRC_2 (SSRC of second receiver) | sub- 34 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block 35 // : ... : 2 36 37 Dlrr::Dlrr() = default; 38 39 Dlrr::Dlrr(const Dlrr& other) = default; 40 41 Dlrr::~Dlrr() = default; 42 Parse(const uint8_t * buffer,uint16_t block_length_32bits)43bool Dlrr::Parse(const uint8_t* buffer, uint16_t block_length_32bits) { 44 RTC_DCHECK(buffer[0] == kBlockType); 45 // kReserved = buffer[1]; 46 RTC_DCHECK_EQ(block_length_32bits, 47 ByteReader<uint16_t>::ReadBigEndian(&buffer[2])); 48 if (block_length_32bits % 3 != 0) { 49 RTC_LOG(LS_WARNING) << "Invalid size for dlrr block."; 50 return false; 51 } 52 53 size_t blocks_count = block_length_32bits / 3; 54 const uint8_t* read_at = buffer + kBlockHeaderLength; 55 sub_blocks_.resize(blocks_count); 56 for (ReceiveTimeInfo& sub_block : sub_blocks_) { 57 sub_block.ssrc = ByteReader<uint32_t>::ReadBigEndian(&read_at[0]); 58 sub_block.last_rr = ByteReader<uint32_t>::ReadBigEndian(&read_at[4]); 59 sub_block.delay_since_last_rr = 60 ByteReader<uint32_t>::ReadBigEndian(&read_at[8]); 61 read_at += kSubBlockLength; 62 } 63 return true; 64 } 65 BlockLength() const66size_t Dlrr::BlockLength() const { 67 if (sub_blocks_.empty()) 68 return 0; 69 return kBlockHeaderLength + kSubBlockLength * sub_blocks_.size(); 70 } 71 Create(uint8_t * buffer) const72void Dlrr::Create(uint8_t* buffer) const { 73 if (sub_blocks_.empty()) // No subblocks, no need to write header either. 74 return; 75 // Create block header. 76 const uint8_t kReserved = 0; 77 buffer[0] = kBlockType; 78 buffer[1] = kReserved; 79 ByteWriter<uint16_t>::WriteBigEndian( 80 &buffer[2], rtc::dchecked_cast<uint16_t>(3 * sub_blocks_.size())); 81 // Create sub blocks. 82 uint8_t* write_at = buffer + kBlockHeaderLength; 83 for (const ReceiveTimeInfo& sub_block : sub_blocks_) { 84 ByteWriter<uint32_t>::WriteBigEndian(&write_at[0], sub_block.ssrc); 85 ByteWriter<uint32_t>::WriteBigEndian(&write_at[4], sub_block.last_rr); 86 ByteWriter<uint32_t>::WriteBigEndian(&write_at[8], 87 sub_block.delay_since_last_rr); 88 write_at += kSubBlockLength; 89 } 90 RTC_DCHECK_EQ(buffer + BlockLength(), write_at); 91 } 92 93 } // namespace rtcp 94 } // namespace webrtc 95