blob: 0526d595401c6008e18c3a1b2b6d69a177099236 [file] [log] [blame]
kwiberg@webrtc.orgac2d27d2015-02-26 13:59:22 +00001/*
2 * Copyright (c) 2012 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 Bonadei71207422017-09-15 13:58:09 +020011#include "common_types.h" // NOLINT(build/include)
kwiberg@webrtc.orgac2d27d2015-02-26 13:59:22 +000012
13#include <string.h>
eladalond0244c22017-06-08 04:19:13 -070014#include <algorithm>
danilchapef8d7732017-04-19 02:59:48 -070015#include <limits>
16#include <type_traits>
kwiberg@webrtc.orgac2d27d2015-02-26 13:59:22 +000017
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "rtc_base/checks.h"
19#include "rtc_base/stringutils.h"
magjed10165ab2016-11-22 10:16:57 -080020
kwiberg@webrtc.orgac2d27d2015-02-26 13:59:22 +000021namespace webrtc {
22
kwiberg@webrtc.orgac2d27d2015-02-26 13:59:22 +000023StreamDataCounters::StreamDataCounters() : first_packet_time_ms(-1) {}
24
danilchapef8d7732017-04-19 02:59:48 -070025constexpr size_t StreamId::kMaxSize;
26
eladalond0244c22017-06-08 04:19:13 -070027bool StreamId::IsLegalName(rtc::ArrayView<const char> name) {
28 return (name.size() <= kMaxSize && name.size() > 0 &&
29 std::all_of(name.data(), name.data() + name.size(), isalnum));
30}
31
danilchapef8d7732017-04-19 02:59:48 -070032void StreamId::Set(const char* data, size_t size) {
33 // If |data| contains \0, the stream id size might become less than |size|.
eladalon4a3c9f62017-06-02 03:37:48 -070034 RTC_CHECK_LE(size, kMaxSize);
danilchapef8d7732017-04-19 02:59:48 -070035 memcpy(value_, data, size);
36 if (size < kMaxSize)
37 value_[size] = 0;
38}
39
40// StreamId is used as member of RTPHeader that is sometimes copied with memcpy
41// and thus assume trivial destructibility.
42static_assert(std::is_trivially_destructible<StreamId>::value, "");
43
sprang@webrtc.org30933902015-03-17 14:33:12 +000044RTPHeaderExtension::RTPHeaderExtension()
45 : hasTransmissionTimeOffset(false),
46 transmissionTimeOffset(0),
47 hasAbsoluteSendTime(false),
48 absoluteSendTime(0),
49 hasTransportSequenceNumber(false),
50 transportSequenceNumber(0),
51 hasAudioLevel(false),
Minyue4cee4192015-08-10 15:08:36 +020052 voiceActivity(false),
sprang@webrtc.org30933902015-03-17 14:33:12 +000053 audioLevel(0),
54 hasVideoRotation(false),
ilnik00d802b2017-04-11 10:34:31 -070055 videoRotation(kVideoRotation_0),
56 hasVideoContentType(false),
ilnik04f4d122017-06-19 07:18:55 -070057 videoContentType(VideoContentType::UNSPECIFIED),
58 has_video_timing(false) {}
sprang@webrtc.org30933902015-03-17 14:33:12 +000059
eladalon98b1b7d2017-09-11 08:48:26 -070060RTPHeaderExtension::RTPHeaderExtension(const RTPHeaderExtension& other) =
61 default;
62
63RTPHeaderExtension& RTPHeaderExtension::operator=(
64 const RTPHeaderExtension& other) = default;
65
kwiberg@webrtc.orgac2d27d2015-02-26 13:59:22 +000066RTPHeader::RTPHeader()
67 : markerBit(false),
68 payloadType(0),
69 sequenceNumber(0),
70 timestamp(0),
71 ssrc(0),
72 numCSRCs(0),
tommia6219cc2016-06-15 10:30:14 -070073 arrOfCSRCs(),
kwiberg@webrtc.orgac2d27d2015-02-26 13:59:22 +000074 paddingLength(0),
75 headerLength(0),
76 payload_type_frequency(0),
tommia6219cc2016-06-15 10:30:14 -070077 extension() {}
kwiberg@webrtc.orgac2d27d2015-02-26 13:59:22 +000078
eladalon98b1b7d2017-09-11 08:48:26 -070079RTPHeader::RTPHeader(const RTPHeader& other) = default;
80
81RTPHeader& RTPHeader::operator=(const RTPHeader& other) = default;
82
hta257dc392016-10-25 09:05:06 -070083VideoCodec::VideoCodec()
84 : codecType(kVideoCodecUnknown),
85 plName(),
86 plType(0),
87 width(0),
88 height(0),
89 startBitrate(0),
90 maxBitrate(0),
91 minBitrate(0),
92 targetBitrate(0),
93 maxFramerate(0),
94 qpMax(0),
95 numberOfSimulcastStreams(0),
96 simulcastStream(),
97 spatialLayers(),
98 mode(kRealtimeVideo),
Erik Språng08127a92016-11-16 16:41:30 +010099 expect_encode_from_texture(false),
ilnik04f4d122017-06-19 07:18:55 -0700100 timing_frame_thresholds({0, 0}),
hta527d3472016-11-16 23:23:04 -0800101 codec_specific_() {}
hta257dc392016-10-25 09:05:06 -0700102
103VideoCodecVP8* VideoCodec::VP8() {
104 RTC_DCHECK_EQ(codecType, kVideoCodecVP8);
hta527d3472016-11-16 23:23:04 -0800105 return &codec_specific_.VP8;
hta257dc392016-10-25 09:05:06 -0700106}
107
108const VideoCodecVP8& VideoCodec::VP8() const {
109 RTC_DCHECK_EQ(codecType, kVideoCodecVP8);
hta527d3472016-11-16 23:23:04 -0800110 return codec_specific_.VP8;
hta257dc392016-10-25 09:05:06 -0700111}
112
113VideoCodecVP9* VideoCodec::VP9() {
114 RTC_DCHECK_EQ(codecType, kVideoCodecVP9);
hta527d3472016-11-16 23:23:04 -0800115 return &codec_specific_.VP9;
hta257dc392016-10-25 09:05:06 -0700116}
117
118const VideoCodecVP9& VideoCodec::VP9() const {
119 RTC_DCHECK_EQ(codecType, kVideoCodecVP9);
hta527d3472016-11-16 23:23:04 -0800120 return codec_specific_.VP9;
hta257dc392016-10-25 09:05:06 -0700121}
122
123VideoCodecH264* VideoCodec::H264() {
124 RTC_DCHECK_EQ(codecType, kVideoCodecH264);
hta527d3472016-11-16 23:23:04 -0800125 return &codec_specific_.H264;
hta257dc392016-10-25 09:05:06 -0700126}
127
128const VideoCodecH264& VideoCodec::H264() const {
129 RTC_DCHECK_EQ(codecType, kVideoCodecH264);
hta527d3472016-11-16 23:23:04 -0800130 return codec_specific_.H264;
hta257dc392016-10-25 09:05:06 -0700131}
132
Erik Språng08127a92016-11-16 16:41:30 +0100133static const char* kPayloadNameVp8 = "VP8";
134static const char* kPayloadNameVp9 = "VP9";
135static const char* kPayloadNameH264 = "H264";
136static const char* kPayloadNameI420 = "I420";
137static const char* kPayloadNameRED = "RED";
138static const char* kPayloadNameULPFEC = "ULPFEC";
139static const char* kPayloadNameGeneric = "Generic";
140
magjed10165ab2016-11-22 10:16:57 -0800141static bool CodecNamesEq(const char* name1, const char* name2) {
142 return _stricmp(name1, name2) == 0;
143}
144
kthelgason1cdddc92017-08-24 03:52:48 -0700145const char* CodecTypeToPayloadString(VideoCodecType type) {
Erik Språng08127a92016-11-16 16:41:30 +0100146 switch (type) {
147 case kVideoCodecVP8:
kthelgason1cdddc92017-08-24 03:52:48 -0700148 return kPayloadNameVp8;
Erik Språng08127a92016-11-16 16:41:30 +0100149 case kVideoCodecVP9:
kthelgason1cdddc92017-08-24 03:52:48 -0700150 return kPayloadNameVp9;
Erik Språng08127a92016-11-16 16:41:30 +0100151 case kVideoCodecH264:
kthelgason1cdddc92017-08-24 03:52:48 -0700152 return kPayloadNameH264;
Erik Språng08127a92016-11-16 16:41:30 +0100153 case kVideoCodecI420:
kthelgason1cdddc92017-08-24 03:52:48 -0700154 return kPayloadNameI420;
Erik Språng08127a92016-11-16 16:41:30 +0100155 case kVideoCodecRED:
kthelgason1cdddc92017-08-24 03:52:48 -0700156 return kPayloadNameRED;
Erik Språng08127a92016-11-16 16:41:30 +0100157 case kVideoCodecULPFEC:
kthelgason1cdddc92017-08-24 03:52:48 -0700158 return kPayloadNameULPFEC;
Erik Språng08127a92016-11-16 16:41:30 +0100159 default:
kthelgason1cdddc92017-08-24 03:52:48 -0700160 // Unrecognized codecs default to generic.
161 return kPayloadNameGeneric;
Erik Språng08127a92016-11-16 16:41:30 +0100162 }
163}
164
kthelgason1cdddc92017-08-24 03:52:48 -0700165VideoCodecType PayloadStringToCodecType(const std::string& name) {
magjed10165ab2016-11-22 10:16:57 -0800166 if (CodecNamesEq(name.c_str(), kPayloadNameVp8))
kthelgason1cdddc92017-08-24 03:52:48 -0700167 return kVideoCodecVP8;
magjed10165ab2016-11-22 10:16:57 -0800168 if (CodecNamesEq(name.c_str(), kPayloadNameVp9))
kthelgason1cdddc92017-08-24 03:52:48 -0700169 return kVideoCodecVP9;
magjed10165ab2016-11-22 10:16:57 -0800170 if (CodecNamesEq(name.c_str(), kPayloadNameH264))
kthelgason1cdddc92017-08-24 03:52:48 -0700171 return kVideoCodecH264;
magjed10165ab2016-11-22 10:16:57 -0800172 if (CodecNamesEq(name.c_str(), kPayloadNameI420))
kthelgason1cdddc92017-08-24 03:52:48 -0700173 return kVideoCodecI420;
magjed10165ab2016-11-22 10:16:57 -0800174 if (CodecNamesEq(name.c_str(), kPayloadNameRED))
kthelgason1cdddc92017-08-24 03:52:48 -0700175 return kVideoCodecRED;
magjed10165ab2016-11-22 10:16:57 -0800176 if (CodecNamesEq(name.c_str(), kPayloadNameULPFEC))
kthelgason1cdddc92017-08-24 03:52:48 -0700177 return kVideoCodecULPFEC;
178 return kVideoCodecGeneric;
179}
180
Erik Språng08127a92016-11-16 16:41:30 +0100181const uint32_t BitrateAllocation::kMaxBitrateBps =
182 std::numeric_limits<uint32_t>::max();
183
erikvarga@webrtc.org01f2ec32017-11-15 14:58:23 +0100184BitrateAllocation::BitrateAllocation() : sum_(0), bitrates_{}, has_bitrate_{} {}
Erik Språng08127a92016-11-16 16:41:30 +0100185
186bool BitrateAllocation::SetBitrate(size_t spatial_index,
187 size_t temporal_index,
188 uint32_t bitrate_bps) {
sprang6d314c72016-12-06 06:08:53 -0800189 RTC_CHECK_LT(spatial_index, kMaxSpatialLayers);
190 RTC_CHECK_LT(temporal_index, kMaxTemporalStreams);
191 RTC_CHECK_LE(bitrates_[spatial_index][temporal_index], sum_);
Erik Språng08127a92016-11-16 16:41:30 +0100192 uint64_t new_bitrate_sum_bps = sum_;
193 new_bitrate_sum_bps -= bitrates_[spatial_index][temporal_index];
194 new_bitrate_sum_bps += bitrate_bps;
195 if (new_bitrate_sum_bps > kMaxBitrateBps)
196 return false;
197
198 bitrates_[spatial_index][temporal_index] = bitrate_bps;
erikvarga@webrtc.org01f2ec32017-11-15 14:58:23 +0100199 has_bitrate_[spatial_index][temporal_index] = true;
Erik Språng08127a92016-11-16 16:41:30 +0100200 sum_ = static_cast<uint32_t>(new_bitrate_sum_bps);
201 return true;
202}
203
erikvarga@webrtc.org01f2ec32017-11-15 14:58:23 +0100204bool BitrateAllocation::HasBitrate(size_t spatial_index,
205 size_t temporal_index) const {
206 RTC_CHECK_LT(spatial_index, kMaxSpatialLayers);
207 RTC_CHECK_LT(temporal_index, kMaxTemporalStreams);
208 return has_bitrate_[spatial_index][temporal_index];
209}
210
Erik Språng08127a92016-11-16 16:41:30 +0100211uint32_t BitrateAllocation::GetBitrate(size_t spatial_index,
212 size_t temporal_index) const {
sprang6d314c72016-12-06 06:08:53 -0800213 RTC_CHECK_LT(spatial_index, kMaxSpatialLayers);
214 RTC_CHECK_LT(temporal_index, kMaxTemporalStreams);
Erik Språng08127a92016-11-16 16:41:30 +0100215 return bitrates_[spatial_index][temporal_index];
216}
217
erikvarga@webrtc.org01f2ec32017-11-15 14:58:23 +0100218// Whether the specific spatial layers has the bitrate set in any of its
219// temporal layers.
220bool BitrateAllocation::IsSpatialLayerUsed(size_t spatial_index) const {
221 RTC_CHECK_LT(spatial_index, kMaxSpatialLayers);
222 for (int i = 0; i < kMaxTemporalStreams; ++i) {
223 if (has_bitrate_[spatial_index][i])
224 return true;
225 }
226 return false;
227}
228
Erik Språng08127a92016-11-16 16:41:30 +0100229// Get the sum of all the temporal layer for a specific spatial layer.
230uint32_t BitrateAllocation::GetSpatialLayerSum(size_t spatial_index) const {
sprang6d314c72016-12-06 06:08:53 -0800231 RTC_CHECK_LT(spatial_index, kMaxSpatialLayers);
Erik Språng08127a92016-11-16 16:41:30 +0100232 uint32_t sum = 0;
233 for (int i = 0; i < kMaxTemporalStreams; ++i)
234 sum += bitrates_[spatial_index][i];
235 return sum;
236}
237
sprangd0fc37a2017-06-22 05:40:25 -0700238std::string BitrateAllocation::ToString() const {
239 if (sum_ == 0)
240 return "BitrateAllocation [ [] ]";
241
242 // TODO(sprang): Replace this stringstream with something cheaper.
243 std::ostringstream oss;
244 oss << "BitrateAllocation [";
245 uint32_t spatial_cumulator = 0;
246 for (int si = 0; si < kMaxSpatialLayers; ++si) {
247 RTC_DCHECK_LE(spatial_cumulator, sum_);
248 if (spatial_cumulator == sum_)
249 break;
250
251 const uint32_t layer_sum = GetSpatialLayerSum(si);
252 if (layer_sum == sum_) {
253 oss << " [";
254 } else {
255 if (si > 0)
256 oss << ",";
257 oss << std::endl << " [";
258 }
259 spatial_cumulator += layer_sum;
260
261 uint32_t temporal_cumulator = 0;
262 for (int ti = 0; ti < kMaxTemporalStreams; ++ti) {
263 RTC_DCHECK_LE(temporal_cumulator, layer_sum);
264 if (temporal_cumulator == layer_sum)
265 break;
266
267 if (ti > 0)
268 oss << ", ";
269
270 uint32_t bitrate = bitrates_[si][ti];
271 oss << bitrate;
272 temporal_cumulator += bitrate;
273 }
274 oss << "]";
275 }
276
277 RTC_DCHECK_EQ(spatial_cumulator, sum_);
278 oss << " ]";
279 return oss.str();
280}
281
282std::ostream& BitrateAllocation::operator<<(std::ostream& os) const {
283 os << ToString();
284 return os;
285}
286
kwiberg@webrtc.orgac2d27d2015-02-26 13:59:22 +0000287} // namespace webrtc