blob: 6c9a59554abeed57c5b458beab1e59f36bec19aa [file] [log] [blame]
kwiberg@webrtc.orgac2d27d2015-02-26 13:59:221/*
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 11:58:0911#include "common_types.h" // NOLINT(build/include)
kwiberg@webrtc.orgac2d27d2015-02-26 13:59:2212
13#include <string.h>
eladalond0244c22017-06-08 11:19:1314#include <algorithm>
danilchapef8d7732017-04-19 09:59:4815#include <limits>
16#include <type_traits>
kwiberg@webrtc.orgac2d27d2015-02-26 13:59:2217
Mirko Bonadei92ea95e2017-09-15 04:47:3118#include "rtc_base/checks.h"
Erik Språngbb60a3a2018-03-19 17:25:1019#include "rtc_base/strings/string_builder.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3120#include "rtc_base/stringutils.h"
magjed10165ab2016-11-22 18:16:5721
kwiberg@webrtc.orgac2d27d2015-02-26 13:59:2222namespace webrtc {
23
Niels Möllerdef1ef52018-03-19 12:48:4424bool VideoCodecVP8::operator==(const VideoCodecVP8& other) const {
25 // Doesn't compare the tl_factory pointers, which are constructed
26 // based on other members.
27 return (complexity == other.complexity &&
28 resilience == other.resilience &&
29 numberOfTemporalLayers == other.numberOfTemporalLayers &&
30 denoisingOn == other.denoisingOn &&
31 automaticResizeOn == other.automaticResizeOn &&
32 frameDroppingOn == other.frameDroppingOn &&
33 keyFrameInterval == other.keyFrameInterval);
34}
35
36bool VideoCodecVP9::operator==(const VideoCodecVP9& other) const {
37 return (complexity == other.complexity &&
38 resilienceOn == other.resilienceOn &&
39 numberOfTemporalLayers == other.numberOfTemporalLayers &&
40 denoisingOn == other.denoisingOn &&
41 frameDroppingOn == other.frameDroppingOn &&
42 keyFrameInterval == other.keyFrameInterval &&
43 adaptiveQpMode == other.adaptiveQpMode &&
44 automaticResizeOn == other.automaticResizeOn &&
45 numberOfSpatialLayers == other.numberOfSpatialLayers &&
46 flexibleMode == other.flexibleMode);
47}
48
49bool VideoCodecH264::operator==(const VideoCodecH264& other) const {
50 return (frameDroppingOn == other.frameDroppingOn &&
51 keyFrameInterval == other.keyFrameInterval &&
52 spsLen == other.spsLen &&
53 ppsLen == other.ppsLen &&
54 profile == other.profile &&
55 (spsLen == 0 || memcmp(spsData, other.spsData, spsLen) == 0) &&
56 (ppsLen == 0 || memcmp(ppsData, other.ppsData, ppsLen) == 0));
57}
58
59bool SpatialLayer::operator==(const SpatialLayer& other) const {
60 return (width == other.width &&
61 height == other.height &&
62 numberOfTemporalLayers == other.numberOfTemporalLayers &&
63 maxBitrate == other.maxBitrate &&
64 targetBitrate == other.targetBitrate &&
65 minBitrate == other.minBitrate &&
66 qpMax == other.qpMax &&
67 active == other.active);
68}
69
hta257dc392016-10-25 16:05:0670VideoCodec::VideoCodec()
71 : codecType(kVideoCodecUnknown),
hta257dc392016-10-25 16:05:0672 plType(0),
73 width(0),
74 height(0),
75 startBitrate(0),
76 maxBitrate(0),
77 minBitrate(0),
78 targetBitrate(0),
79 maxFramerate(0),
Seth Hampsonf6464c92018-01-17 21:55:1480 active(true),
hta257dc392016-10-25 16:05:0681 qpMax(0),
82 numberOfSimulcastStreams(0),
83 simulcastStream(),
84 spatialLayers(),
85 mode(kRealtimeVideo),
Erik Språng08127a92016-11-16 15:41:3086 expect_encode_from_texture(false),
ilnik04f4d122017-06-19 14:18:5587 timing_frame_thresholds({0, 0}),
hta527d3472016-11-17 07:23:0488 codec_specific_() {}
hta257dc392016-10-25 16:05:0689
90VideoCodecVP8* VideoCodec::VP8() {
91 RTC_DCHECK_EQ(codecType, kVideoCodecVP8);
hta527d3472016-11-17 07:23:0492 return &codec_specific_.VP8;
hta257dc392016-10-25 16:05:0693}
94
95const VideoCodecVP8& VideoCodec::VP8() const {
96 RTC_DCHECK_EQ(codecType, kVideoCodecVP8);
hta527d3472016-11-17 07:23:0497 return codec_specific_.VP8;
hta257dc392016-10-25 16:05:0698}
99
100VideoCodecVP9* VideoCodec::VP9() {
101 RTC_DCHECK_EQ(codecType, kVideoCodecVP9);
hta527d3472016-11-17 07:23:04102 return &codec_specific_.VP9;
hta257dc392016-10-25 16:05:06103}
104
105const VideoCodecVP9& VideoCodec::VP9() const {
106 RTC_DCHECK_EQ(codecType, kVideoCodecVP9);
hta527d3472016-11-17 07:23:04107 return codec_specific_.VP9;
hta257dc392016-10-25 16:05:06108}
109
110VideoCodecH264* VideoCodec::H264() {
111 RTC_DCHECK_EQ(codecType, kVideoCodecH264);
hta527d3472016-11-17 07:23:04112 return &codec_specific_.H264;
hta257dc392016-10-25 16:05:06113}
114
115const VideoCodecH264& VideoCodec::H264() const {
116 RTC_DCHECK_EQ(codecType, kVideoCodecH264);
hta527d3472016-11-17 07:23:04117 return codec_specific_.H264;
hta257dc392016-10-25 16:05:06118}
119
Erik Språng08127a92016-11-16 15:41:30120static const char* kPayloadNameVp8 = "VP8";
121static const char* kPayloadNameVp9 = "VP9";
122static const char* kPayloadNameH264 = "H264";
123static const char* kPayloadNameI420 = "I420";
124static const char* kPayloadNameRED = "RED";
125static const char* kPayloadNameULPFEC = "ULPFEC";
Danil Chapovalov3c706972018-01-30 10:11:08126static const char* kPayloadNameFlexfec = "flexfec-03";
Erik Språng08127a92016-11-16 15:41:30127static const char* kPayloadNameGeneric = "Generic";
Emircan Uysalerd7ae3c32018-01-25 21:01:09128static const char* kPayloadNameMultiplex = "Multiplex";
Erik Språng08127a92016-11-16 15:41:30129
magjed10165ab2016-11-22 18:16:57130static bool CodecNamesEq(const char* name1, const char* name2) {
131 return _stricmp(name1, name2) == 0;
132}
133
kthelgason1cdddc92017-08-24 10:52:48134const char* CodecTypeToPayloadString(VideoCodecType type) {
Erik Språng08127a92016-11-16 15:41:30135 switch (type) {
136 case kVideoCodecVP8:
kthelgason1cdddc92017-08-24 10:52:48137 return kPayloadNameVp8;
Erik Språng08127a92016-11-16 15:41:30138 case kVideoCodecVP9:
kthelgason1cdddc92017-08-24 10:52:48139 return kPayloadNameVp9;
Erik Språng08127a92016-11-16 15:41:30140 case kVideoCodecH264:
kthelgason1cdddc92017-08-24 10:52:48141 return kPayloadNameH264;
Erik Språng08127a92016-11-16 15:41:30142 case kVideoCodecI420:
kthelgason1cdddc92017-08-24 10:52:48143 return kPayloadNameI420;
Erik Språng08127a92016-11-16 15:41:30144 case kVideoCodecRED:
kthelgason1cdddc92017-08-24 10:52:48145 return kPayloadNameRED;
Erik Språng08127a92016-11-16 15:41:30146 case kVideoCodecULPFEC:
kthelgason1cdddc92017-08-24 10:52:48147 return kPayloadNameULPFEC;
Danil Chapovalov3c706972018-01-30 10:11:08148 case kVideoCodecFlexfec:
149 return kPayloadNameFlexfec;
Emircan Uysaler0a375472017-12-11 06:51:02150 // Other codecs default to generic.
Emircan Uysalerd7ae3c32018-01-25 21:01:09151 case kVideoCodecMultiplex:
Emircan Uysaler0a375472017-12-11 06:51:02152 case kVideoCodecGeneric:
153 case kVideoCodecUnknown:
kthelgason1cdddc92017-08-24 10:52:48154 return kPayloadNameGeneric;
Erik Språng08127a92016-11-16 15:41:30155 }
Emircan Uysaler0a375472017-12-11 06:51:02156 return kPayloadNameGeneric;
Erik Språng08127a92016-11-16 15:41:30157}
158
kthelgason1cdddc92017-08-24 10:52:48159VideoCodecType PayloadStringToCodecType(const std::string& name) {
magjed10165ab2016-11-22 18:16:57160 if (CodecNamesEq(name.c_str(), kPayloadNameVp8))
kthelgason1cdddc92017-08-24 10:52:48161 return kVideoCodecVP8;
magjed10165ab2016-11-22 18:16:57162 if (CodecNamesEq(name.c_str(), kPayloadNameVp9))
kthelgason1cdddc92017-08-24 10:52:48163 return kVideoCodecVP9;
magjed10165ab2016-11-22 18:16:57164 if (CodecNamesEq(name.c_str(), kPayloadNameH264))
kthelgason1cdddc92017-08-24 10:52:48165 return kVideoCodecH264;
magjed10165ab2016-11-22 18:16:57166 if (CodecNamesEq(name.c_str(), kPayloadNameI420))
kthelgason1cdddc92017-08-24 10:52:48167 return kVideoCodecI420;
magjed10165ab2016-11-22 18:16:57168 if (CodecNamesEq(name.c_str(), kPayloadNameRED))
kthelgason1cdddc92017-08-24 10:52:48169 return kVideoCodecRED;
magjed10165ab2016-11-22 18:16:57170 if (CodecNamesEq(name.c_str(), kPayloadNameULPFEC))
kthelgason1cdddc92017-08-24 10:52:48171 return kVideoCodecULPFEC;
Danil Chapovalov3c706972018-01-30 10:11:08172 if (CodecNamesEq(name.c_str(), kPayloadNameFlexfec))
173 return kVideoCodecFlexfec;
Emircan Uysalerd7ae3c32018-01-25 21:01:09174 if (CodecNamesEq(name.c_str(), kPayloadNameMultiplex))
175 return kVideoCodecMultiplex;
kthelgason1cdddc92017-08-24 10:52:48176 return kVideoCodecGeneric;
177}
178
Erik Språng08127a92016-11-16 15:41:30179const uint32_t BitrateAllocation::kMaxBitrateBps =
180 std::numeric_limits<uint32_t>::max();
181
erikvarga@webrtc.org01f2ec32017-11-15 13:58:23182BitrateAllocation::BitrateAllocation() : sum_(0), bitrates_{}, has_bitrate_{} {}
Erik Språng08127a92016-11-16 15:41:30183
184bool BitrateAllocation::SetBitrate(size_t spatial_index,
185 size_t temporal_index,
186 uint32_t bitrate_bps) {
sprang6d314c72016-12-06 14:08:53187 RTC_CHECK_LT(spatial_index, kMaxSpatialLayers);
188 RTC_CHECK_LT(temporal_index, kMaxTemporalStreams);
189 RTC_CHECK_LE(bitrates_[spatial_index][temporal_index], sum_);
Erik Språng08127a92016-11-16 15:41:30190 uint64_t new_bitrate_sum_bps = sum_;
191 new_bitrate_sum_bps -= bitrates_[spatial_index][temporal_index];
192 new_bitrate_sum_bps += bitrate_bps;
193 if (new_bitrate_sum_bps > kMaxBitrateBps)
194 return false;
195
196 bitrates_[spatial_index][temporal_index] = bitrate_bps;
erikvarga@webrtc.org01f2ec32017-11-15 13:58:23197 has_bitrate_[spatial_index][temporal_index] = true;
Erik Språng08127a92016-11-16 15:41:30198 sum_ = static_cast<uint32_t>(new_bitrate_sum_bps);
199 return true;
200}
201
erikvarga@webrtc.org01f2ec32017-11-15 13:58:23202bool BitrateAllocation::HasBitrate(size_t spatial_index,
203 size_t temporal_index) const {
204 RTC_CHECK_LT(spatial_index, kMaxSpatialLayers);
205 RTC_CHECK_LT(temporal_index, kMaxTemporalStreams);
206 return has_bitrate_[spatial_index][temporal_index];
207}
208
Erik Språng08127a92016-11-16 15:41:30209uint32_t BitrateAllocation::GetBitrate(size_t spatial_index,
210 size_t temporal_index) const {
sprang6d314c72016-12-06 14:08:53211 RTC_CHECK_LT(spatial_index, kMaxSpatialLayers);
212 RTC_CHECK_LT(temporal_index, kMaxTemporalStreams);
Erik Språng08127a92016-11-16 15:41:30213 return bitrates_[spatial_index][temporal_index];
214}
215
erikvarga@webrtc.org01f2ec32017-11-15 13:58:23216// Whether the specific spatial layers has the bitrate set in any of its
217// temporal layers.
218bool BitrateAllocation::IsSpatialLayerUsed(size_t spatial_index) const {
219 RTC_CHECK_LT(spatial_index, kMaxSpatialLayers);
220 for (int i = 0; i < kMaxTemporalStreams; ++i) {
221 if (has_bitrate_[spatial_index][i])
222 return true;
223 }
224 return false;
225}
226
Erik Språng08127a92016-11-16 15:41:30227// Get the sum of all the temporal layer for a specific spatial layer.
228uint32_t BitrateAllocation::GetSpatialLayerSum(size_t spatial_index) const {
sprang6d314c72016-12-06 14:08:53229 RTC_CHECK_LT(spatial_index, kMaxSpatialLayers);
Erik Språng08127a92016-11-16 15:41:30230 uint32_t sum = 0;
231 for (int i = 0; i < kMaxTemporalStreams; ++i)
232 sum += bitrates_[spatial_index][i];
233 return sum;
234}
235
Erik Språngbb60a3a2018-03-19 17:25:10236std::vector<uint32_t> BitrateAllocation::GetTemporalLayerAllocation(
237 size_t spatial_index) const {
238 RTC_CHECK_LT(spatial_index, kMaxSpatialLayers);
239 std::vector<uint32_t> temporal_rates;
240
241 // Find the highest temporal layer with a defined bitrate in order to
242 // determine the size of the temporal layer allocation.
243 for (size_t i = kMaxTemporalStreams; i > 0; --i) {
244 if (has_bitrate_[spatial_index][i - 1]) {
245 temporal_rates.resize(i);
246 break;
247 }
248 }
249
250 for (size_t i = 0; i < temporal_rates.size(); ++i) {
251 temporal_rates[i] = bitrates_[spatial_index][i];
252 }
253
254 return temporal_rates;
255}
256
sprangd0fc37a2017-06-22 12:40:25257std::string BitrateAllocation::ToString() const {
258 if (sum_ == 0)
259 return "BitrateAllocation [ [] ]";
260
Erik Språngbb60a3a2018-03-19 17:25:10261 // Max string length in practice is 260, but let's have some overhead and
262 // round up to nearest power of two.
263 char string_buf[512];
264 rtc::SimpleStringBuilder ssb(string_buf);
265
266 ssb << "BitrateAllocation [";
sprangd0fc37a2017-06-22 12:40:25267 uint32_t spatial_cumulator = 0;
268 for (int si = 0; si < kMaxSpatialLayers; ++si) {
269 RTC_DCHECK_LE(spatial_cumulator, sum_);
270 if (spatial_cumulator == sum_)
271 break;
272
273 const uint32_t layer_sum = GetSpatialLayerSum(si);
274 if (layer_sum == sum_) {
Erik Språngbb60a3a2018-03-19 17:25:10275 ssb << " [";
sprangd0fc37a2017-06-22 12:40:25276 } else {
277 if (si > 0)
Erik Språngbb60a3a2018-03-19 17:25:10278 ssb << ",";
279 ssb << '\n' << " [";
sprangd0fc37a2017-06-22 12:40:25280 }
281 spatial_cumulator += layer_sum;
282
283 uint32_t temporal_cumulator = 0;
284 for (int ti = 0; ti < kMaxTemporalStreams; ++ti) {
285 RTC_DCHECK_LE(temporal_cumulator, layer_sum);
286 if (temporal_cumulator == layer_sum)
287 break;
288
289 if (ti > 0)
Erik Språngbb60a3a2018-03-19 17:25:10290 ssb << ", ";
sprangd0fc37a2017-06-22 12:40:25291
292 uint32_t bitrate = bitrates_[si][ti];
Erik Språngbb60a3a2018-03-19 17:25:10293 ssb << bitrate;
sprangd0fc37a2017-06-22 12:40:25294 temporal_cumulator += bitrate;
295 }
Erik Språngbb60a3a2018-03-19 17:25:10296 ssb << "]";
sprangd0fc37a2017-06-22 12:40:25297 }
298
299 RTC_DCHECK_EQ(spatial_cumulator, sum_);
Erik Språngbb60a3a2018-03-19 17:25:10300 ssb << " ]";
301 return ssb.str();
sprangd0fc37a2017-06-22 12:40:25302}
303
kwiberg@webrtc.orgac2d27d2015-02-26 13:59:22304} // namespace webrtc