blob: 6863def2fe9429b73814153ce77e9c21b7a2e520 [file] [log] [blame]
danilchap54999d42015-12-16 01:56:20 -08001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/rtp_rtcp/source/rtcp_packet/dlrr.h"
danilchap54999d42015-12-16 01:56:20 -080012
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "modules/rtp_rtcp/source/byte_io.h"
14#include "rtc_base/checks.h"
15#include "rtc_base/logging.h"
Karl Wiberge40468b2017-11-22 10:42:26 +010016#include "rtc_base/numerics/safe_conversions.h"
danilchap54999d42015-12-16 01:56:20 -080017
18namespace webrtc {
19namespace 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
sprangb84ad632016-11-01 02:50:12 -070036
eladalon8fa21c42017-06-16 07:07:47 -070037Dlrr::Dlrr() = default;
38
39Dlrr::Dlrr(const Dlrr& other) = default;
40
41Dlrr::~Dlrr() = default;
42
danilchap54999d42015-12-16 01:56:20 -080043bool 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) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010049 RTC_LOG(LS_WARNING) << "Invalid size for dlrr block.";
danilchap54999d42015-12-16 01:56:20 -080050 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);
Danil Chapovalovd0c7bba2016-01-26 14:12:46 +010056 for (ReceiveTimeInfo& sub_block : sub_blocks_) {
danilchap54999d42015-12-16 01:56:20 -080057 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
66size_t Dlrr::BlockLength() const {
67 if (sub_blocks_.empty())
68 return 0;
69 return kBlockHeaderLength + kSubBlockLength * sub_blocks_.size();
70}
71
72void 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;
Danil Chapovalov6c170572017-09-15 16:48:14 +020079 ByteWriter<uint16_t>::WriteBigEndian(
80 &buffer[2], rtc::dchecked_cast<uint16_t>(3 * sub_blocks_.size()));
danilchap54999d42015-12-16 01:56:20 -080081 // Create sub blocks.
82 uint8_t* write_at = buffer + kBlockHeaderLength;
Danil Chapovalovd0c7bba2016-01-26 14:12:46 +010083 for (const ReceiveTimeInfo& sub_block : sub_blocks_) {
danilchap54999d42015-12-16 01:56:20 -080084 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
danilchap54999d42015-12-16 01:56:20 -080093} // namespace rtcp
94} // namespace webrtc