blob: 82307ce52b37393837d79bde3938ba101ab60c0c [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
11#include "webrtc/common_types.h"
12
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
Edward Lemurc20978e2017-07-06 19:44:34 +020018#include "webrtc/rtc_base/checks.h"
19#include "webrtc/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
kwiberg@webrtc.orgac2d27d2015-02-26 13:59:22 +000060RTPHeader::RTPHeader()
61 : markerBit(false),
62 payloadType(0),
63 sequenceNumber(0),
64 timestamp(0),
65 ssrc(0),
66 numCSRCs(0),
tommia6219cc2016-06-15 10:30:14 -070067 arrOfCSRCs(),
kwiberg@webrtc.orgac2d27d2015-02-26 13:59:22 +000068 paddingLength(0),
69 headerLength(0),
70 payload_type_frequency(0),
tommia6219cc2016-06-15 10:30:14 -070071 extension() {}
kwiberg@webrtc.orgac2d27d2015-02-26 13:59:22 +000072
hta257dc392016-10-25 09:05:06 -070073VideoCodec::VideoCodec()
74 : codecType(kVideoCodecUnknown),
75 plName(),
76 plType(0),
77 width(0),
78 height(0),
79 startBitrate(0),
80 maxBitrate(0),
81 minBitrate(0),
82 targetBitrate(0),
83 maxFramerate(0),
84 qpMax(0),
85 numberOfSimulcastStreams(0),
86 simulcastStream(),
87 spatialLayers(),
88 mode(kRealtimeVideo),
Erik Språng08127a92016-11-16 16:41:30 +010089 expect_encode_from_texture(false),
ilnik04f4d122017-06-19 07:18:55 -070090 timing_frame_thresholds({0, 0}),
hta527d3472016-11-16 23:23:04 -080091 codec_specific_() {}
hta257dc392016-10-25 09:05:06 -070092
93VideoCodecVP8* VideoCodec::VP8() {
94 RTC_DCHECK_EQ(codecType, kVideoCodecVP8);
hta527d3472016-11-16 23:23:04 -080095 return &codec_specific_.VP8;
hta257dc392016-10-25 09:05:06 -070096}
97
98const VideoCodecVP8& VideoCodec::VP8() const {
99 RTC_DCHECK_EQ(codecType, kVideoCodecVP8);
hta527d3472016-11-16 23:23:04 -0800100 return codec_specific_.VP8;
hta257dc392016-10-25 09:05:06 -0700101}
102
103VideoCodecVP9* VideoCodec::VP9() {
104 RTC_DCHECK_EQ(codecType, kVideoCodecVP9);
hta527d3472016-11-16 23:23:04 -0800105 return &codec_specific_.VP9;
hta257dc392016-10-25 09:05:06 -0700106}
107
108const VideoCodecVP9& VideoCodec::VP9() const {
109 RTC_DCHECK_EQ(codecType, kVideoCodecVP9);
hta527d3472016-11-16 23:23:04 -0800110 return codec_specific_.VP9;
hta257dc392016-10-25 09:05:06 -0700111}
112
113VideoCodecH264* VideoCodec::H264() {
114 RTC_DCHECK_EQ(codecType, kVideoCodecH264);
hta527d3472016-11-16 23:23:04 -0800115 return &codec_specific_.H264;
hta257dc392016-10-25 09:05:06 -0700116}
117
118const VideoCodecH264& VideoCodec::H264() const {
119 RTC_DCHECK_EQ(codecType, kVideoCodecH264);
hta527d3472016-11-16 23:23:04 -0800120 return codec_specific_.H264;
hta257dc392016-10-25 09:05:06 -0700121}
122
Erik Språng08127a92016-11-16 16:41:30 +0100123static const char* kPayloadNameVp8 = "VP8";
124static const char* kPayloadNameVp9 = "VP9";
125static const char* kPayloadNameH264 = "H264";
126static const char* kPayloadNameI420 = "I420";
127static const char* kPayloadNameRED = "RED";
128static const char* kPayloadNameULPFEC = "ULPFEC";
129static const char* kPayloadNameGeneric = "Generic";
130
magjed10165ab2016-11-22 10:16:57 -0800131static bool CodecNamesEq(const char* name1, const char* name2) {
132 return _stricmp(name1, name2) == 0;
133}
134
kthelgason1cdddc92017-08-24 03:52:48 -0700135const char* CodecTypeToPayloadString(VideoCodecType type) {
Erik Språng08127a92016-11-16 16:41:30 +0100136 switch (type) {
137 case kVideoCodecVP8:
kthelgason1cdddc92017-08-24 03:52:48 -0700138 return kPayloadNameVp8;
Erik Språng08127a92016-11-16 16:41:30 +0100139 case kVideoCodecVP9:
kthelgason1cdddc92017-08-24 03:52:48 -0700140 return kPayloadNameVp9;
Erik Språng08127a92016-11-16 16:41:30 +0100141 case kVideoCodecH264:
kthelgason1cdddc92017-08-24 03:52:48 -0700142 return kPayloadNameH264;
Erik Språng08127a92016-11-16 16:41:30 +0100143 case kVideoCodecI420:
kthelgason1cdddc92017-08-24 03:52:48 -0700144 return kPayloadNameI420;
Erik Språng08127a92016-11-16 16:41:30 +0100145 case kVideoCodecRED:
kthelgason1cdddc92017-08-24 03:52:48 -0700146 return kPayloadNameRED;
Erik Språng08127a92016-11-16 16:41:30 +0100147 case kVideoCodecULPFEC:
kthelgason1cdddc92017-08-24 03:52:48 -0700148 return kPayloadNameULPFEC;
Erik Språng08127a92016-11-16 16:41:30 +0100149 default:
kthelgason1cdddc92017-08-24 03:52:48 -0700150 // Unrecognized codecs default to generic.
151 return kPayloadNameGeneric;
Erik Språng08127a92016-11-16 16:41:30 +0100152 }
153}
154
kthelgason1cdddc92017-08-24 03:52:48 -0700155VideoCodecType PayloadStringToCodecType(const std::string& name) {
magjed10165ab2016-11-22 10:16:57 -0800156 if (CodecNamesEq(name.c_str(), kPayloadNameVp8))
kthelgason1cdddc92017-08-24 03:52:48 -0700157 return kVideoCodecVP8;
magjed10165ab2016-11-22 10:16:57 -0800158 if (CodecNamesEq(name.c_str(), kPayloadNameVp9))
kthelgason1cdddc92017-08-24 03:52:48 -0700159 return kVideoCodecVP9;
magjed10165ab2016-11-22 10:16:57 -0800160 if (CodecNamesEq(name.c_str(), kPayloadNameH264))
kthelgason1cdddc92017-08-24 03:52:48 -0700161 return kVideoCodecH264;
magjed10165ab2016-11-22 10:16:57 -0800162 if (CodecNamesEq(name.c_str(), kPayloadNameI420))
kthelgason1cdddc92017-08-24 03:52:48 -0700163 return kVideoCodecI420;
magjed10165ab2016-11-22 10:16:57 -0800164 if (CodecNamesEq(name.c_str(), kPayloadNameRED))
kthelgason1cdddc92017-08-24 03:52:48 -0700165 return kVideoCodecRED;
magjed10165ab2016-11-22 10:16:57 -0800166 if (CodecNamesEq(name.c_str(), kPayloadNameULPFEC))
kthelgason1cdddc92017-08-24 03:52:48 -0700167 return kVideoCodecULPFEC;
168 return kVideoCodecGeneric;
169}
170
171// TODO(kthelgason): Remove these methods once upstream projects
172// have been updated.
173rtc::Optional<const char*> CodecTypeToPayloadName(VideoCodecType type) {
174 return rtc::Optional<const char*>(CodecTypeToPayloadString(type));
175}
176
177rtc::Optional<VideoCodecType> PayloadNameToCodecType(const std::string& name) {
178 return rtc::Optional<VideoCodecType>(PayloadStringToCodecType(name));
Erik Språng08127a92016-11-16 16:41:30 +0100179}
180
181const uint32_t BitrateAllocation::kMaxBitrateBps =
182 std::numeric_limits<uint32_t>::max();
183
184BitrateAllocation::BitrateAllocation() : sum_(0), bitrates_{} {}
185
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;
199 sum_ = static_cast<uint32_t>(new_bitrate_sum_bps);
200 return true;
201}
202
203uint32_t BitrateAllocation::GetBitrate(size_t spatial_index,
204 size_t temporal_index) const {
sprang6d314c72016-12-06 06:08:53 -0800205 RTC_CHECK_LT(spatial_index, kMaxSpatialLayers);
206 RTC_CHECK_LT(temporal_index, kMaxTemporalStreams);
Erik Språng08127a92016-11-16 16:41:30 +0100207 return bitrates_[spatial_index][temporal_index];
208}
209
210// Get the sum of all the temporal layer for a specific spatial layer.
211uint32_t BitrateAllocation::GetSpatialLayerSum(size_t spatial_index) const {
sprang6d314c72016-12-06 06:08:53 -0800212 RTC_CHECK_LT(spatial_index, kMaxSpatialLayers);
Erik Språng08127a92016-11-16 16:41:30 +0100213 uint32_t sum = 0;
214 for (int i = 0; i < kMaxTemporalStreams; ++i)
215 sum += bitrates_[spatial_index][i];
216 return sum;
217}
218
sprangd0fc37a2017-06-22 05:40:25 -0700219std::string BitrateAllocation::ToString() const {
220 if (sum_ == 0)
221 return "BitrateAllocation [ [] ]";
222
223 // TODO(sprang): Replace this stringstream with something cheaper.
224 std::ostringstream oss;
225 oss << "BitrateAllocation [";
226 uint32_t spatial_cumulator = 0;
227 for (int si = 0; si < kMaxSpatialLayers; ++si) {
228 RTC_DCHECK_LE(spatial_cumulator, sum_);
229 if (spatial_cumulator == sum_)
230 break;
231
232 const uint32_t layer_sum = GetSpatialLayerSum(si);
233 if (layer_sum == sum_) {
234 oss << " [";
235 } else {
236 if (si > 0)
237 oss << ",";
238 oss << std::endl << " [";
239 }
240 spatial_cumulator += layer_sum;
241
242 uint32_t temporal_cumulator = 0;
243 for (int ti = 0; ti < kMaxTemporalStreams; ++ti) {
244 RTC_DCHECK_LE(temporal_cumulator, layer_sum);
245 if (temporal_cumulator == layer_sum)
246 break;
247
248 if (ti > 0)
249 oss << ", ";
250
251 uint32_t bitrate = bitrates_[si][ti];
252 oss << bitrate;
253 temporal_cumulator += bitrate;
254 }
255 oss << "]";
256 }
257
258 RTC_DCHECK_EQ(spatial_cumulator, sum_);
259 oss << " ]";
260 return oss.str();
261}
262
263std::ostream& BitrateAllocation::operator<<(std::ostream& os) const {
264 os << ToString();
265 return os;
266}
267
kwiberg@webrtc.orgac2d27d2015-02-26 13:59:22 +0000268} // namespace webrtc