File: target_bitrate.cc

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (133 lines) | stat: -rw-r--r-- 5,054 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
 *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "modules/rtp_rtcp/source/rtcp_packet/target_bitrate.h"

#include <cstddef>
#include <cstdint>
#include <vector>

#include "modules/rtp_rtcp/source/byte_io.h"
#include "rtc_base/checks.h"
#include "rtc_base/numerics/safe_conversions.h"

namespace webrtc {
namespace rtcp {
namespace {

constexpr size_t kTargetBitrateHeaderSizeBytes = 4;

}  // namespace

TargetBitrate::BitrateItem::BitrateItem()
    : spatial_layer(0), temporal_layer(0), target_bitrate_kbps(0) {}

TargetBitrate::BitrateItem::BitrateItem(uint8_t spatial_layer,
                                        uint8_t temporal_layer,
                                        uint32_t target_bitrate_kbps)
    : spatial_layer(spatial_layer),
      temporal_layer(temporal_layer),
      target_bitrate_kbps(target_bitrate_kbps) {}

//  RFC 4585: Feedback format.
//
//  Common packet format:
//
//   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
//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//  |     BT=42     |   reserved    |         block length          |
//  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
//  Target bitrate item (repeat as many times as necessary).
//
//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//  |   S   |   T   |                Target Bitrate                 |
//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//  :  ...                                                          :
//
//  Spatial Layer (S): 4 bits
//    Indicates which temporal layer this bitrate concerns.
//
//  Temporal Layer (T): 4 bits
//    Indicates which temporal layer this bitrate concerns.
//
//  Target Bitrate: 24 bits
//    The encoder target bitrate for this layer, in kbps.
//
//  As an example of how S and T are intended to be used, VP8 simulcast will
//  use a separate TargetBitrate message per stream, since they are transmitted
//  on separate SSRCs, with temporal layers grouped by stream.
//  If VP9 SVC is used, there will be only one SSRC, so each spatial and
//  temporal layer combo used shall be specified in the TargetBitrate packet.

TargetBitrate::TargetBitrate() = default;
TargetBitrate::TargetBitrate(const TargetBitrate&) = default;
TargetBitrate& TargetBitrate::operator=(const TargetBitrate&) = default;
TargetBitrate::~TargetBitrate() = default;

void TargetBitrate::Parse(const uint8_t* block, uint16_t block_length) {
  // Validate block header (should already have been parsed and checked).
  RTC_DCHECK_EQ(block[0], kBlockType);
  RTC_DCHECK_EQ(block_length, ByteReader<uint16_t>::ReadBigEndian(&block[2]));

  // Header specifies block length - 1, but since we ignore the header, which
  // occupies exactly on block, we can just treat this as payload length.
  const size_t payload_bytes = block_length * 4;
  const size_t num_items = payload_bytes / kBitrateItemSizeBytes;
  size_t index = kTargetBitrateHeaderSizeBytes;
  bitrates_.clear();
  for (size_t i = 0; i < num_items; ++i) {
    uint8_t layers = block[index];
    uint32_t bitrate_kbps =
        ByteReader<uint32_t, 3>::ReadBigEndian(&block[index + 1]);
    index += kBitrateItemSizeBytes;
    AddTargetBitrate((layers >> 4) & 0x0F, layers & 0x0F, bitrate_kbps);
  }
}

void TargetBitrate::AddTargetBitrate(uint8_t spatial_layer,
                                     uint8_t temporal_layer,
                                     uint32_t target_bitrate_kbps) {
  RTC_DCHECK_LE(spatial_layer, 0x0F);
  RTC_DCHECK_LE(temporal_layer, 0x0F);
  RTC_DCHECK_LE(target_bitrate_kbps, 0x00FFFFFFU);
  bitrates_.push_back(
      BitrateItem(spatial_layer, temporal_layer, target_bitrate_kbps));
}

const std::vector<TargetBitrate::BitrateItem>&
TargetBitrate::GetTargetBitrates() const {
  return bitrates_;
}

size_t TargetBitrate::BlockLength() const {
  return kTargetBitrateHeaderSizeBytes +
         bitrates_.size() * kBitrateItemSizeBytes;
}

void TargetBitrate::Create(uint8_t* buffer) const {
  buffer[0] = kBlockType;
  buffer[1] = 0;  // Reserved.
  uint16_t block_length_words =
      dchecked_cast<uint16_t>((BlockLength() / 4) - 1);
  ByteWriter<uint16_t>::WriteBigEndian(&buffer[2], block_length_words);

  size_t index = kTargetBitrateHeaderSizeBytes;
  for (const BitrateItem& item : bitrates_) {
    buffer[index] = (item.spatial_layer << 4) | item.temporal_layer;
    ByteWriter<uint32_t, 3>::WriteBigEndian(&buffer[index + 1],
                                            item.target_bitrate_kbps);
    index += kBitrateItemSizeBytes;
  }
}

}  // namespace rtcp
}  // namespace webrtc