| /* | 
 |  *  Copyright (c) 2012 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 "common_types.h"  // NOLINT(build/include) | 
 |  | 
 | #include <string.h> | 
 | #include <algorithm> | 
 | #include <limits> | 
 | #include <type_traits> | 
 |  | 
 | #include "rtc_base/checks.h" | 
 | #include "rtc_base/stringutils.h" | 
 |  | 
 | namespace webrtc { | 
 |  | 
 | VideoCodec::VideoCodec() | 
 |     : codecType(kVideoCodecUnknown), | 
 |       plName(), | 
 |       plType(0), | 
 |       width(0), | 
 |       height(0), | 
 |       startBitrate(0), | 
 |       maxBitrate(0), | 
 |       minBitrate(0), | 
 |       targetBitrate(0), | 
 |       maxFramerate(0), | 
 |       active(true), | 
 |       qpMax(0), | 
 |       numberOfSimulcastStreams(0), | 
 |       simulcastStream(), | 
 |       spatialLayers(), | 
 |       mode(kRealtimeVideo), | 
 |       expect_encode_from_texture(false), | 
 |       timing_frame_thresholds({0, 0}), | 
 |       codec_specific_() {} | 
 |  | 
 | VideoCodecVP8* VideoCodec::VP8() { | 
 |   RTC_DCHECK_EQ(codecType, kVideoCodecVP8); | 
 |   return &codec_specific_.VP8; | 
 | } | 
 |  | 
 | const VideoCodecVP8& VideoCodec::VP8() const { | 
 |   RTC_DCHECK_EQ(codecType, kVideoCodecVP8); | 
 |   return codec_specific_.VP8; | 
 | } | 
 |  | 
 | VideoCodecVP9* VideoCodec::VP9() { | 
 |   RTC_DCHECK_EQ(codecType, kVideoCodecVP9); | 
 |   return &codec_specific_.VP9; | 
 | } | 
 |  | 
 | const VideoCodecVP9& VideoCodec::VP9() const { | 
 |   RTC_DCHECK_EQ(codecType, kVideoCodecVP9); | 
 |   return codec_specific_.VP9; | 
 | } | 
 |  | 
 | VideoCodecH264* VideoCodec::H264() { | 
 |   RTC_DCHECK_EQ(codecType, kVideoCodecH264); | 
 |   return &codec_specific_.H264; | 
 | } | 
 |  | 
 | const VideoCodecH264& VideoCodec::H264() const { | 
 |   RTC_DCHECK_EQ(codecType, kVideoCodecH264); | 
 |   return codec_specific_.H264; | 
 | } | 
 |  | 
 | static const char* kPayloadNameVp8 = "VP8"; | 
 | static const char* kPayloadNameVp9 = "VP9"; | 
 | static const char* kPayloadNameH264 = "H264"; | 
 | static const char* kPayloadNameI420 = "I420"; | 
 | static const char* kPayloadNameRED = "RED"; | 
 | static const char* kPayloadNameULPFEC = "ULPFEC"; | 
 | static const char* kPayloadNameFlexfec = "flexfec-03"; | 
 | static const char* kPayloadNameGeneric = "Generic"; | 
 | static const char* kPayloadNameMultiplex = "Multiplex"; | 
 |  | 
 | static bool CodecNamesEq(const char* name1, const char* name2) { | 
 |   return _stricmp(name1, name2) == 0; | 
 | } | 
 |  | 
 | const char* CodecTypeToPayloadString(VideoCodecType type) { | 
 |   switch (type) { | 
 |     case kVideoCodecVP8: | 
 |       return kPayloadNameVp8; | 
 |     case kVideoCodecVP9: | 
 |       return kPayloadNameVp9; | 
 |     case kVideoCodecH264: | 
 |       return kPayloadNameH264; | 
 |     case kVideoCodecI420: | 
 |       return kPayloadNameI420; | 
 |     case kVideoCodecRED: | 
 |       return kPayloadNameRED; | 
 |     case kVideoCodecULPFEC: | 
 |       return kPayloadNameULPFEC; | 
 |     case kVideoCodecFlexfec: | 
 |       return kPayloadNameFlexfec; | 
 |     // Other codecs default to generic. | 
 |     case kVideoCodecMultiplex: | 
 |     case kVideoCodecGeneric: | 
 |     case kVideoCodecUnknown: | 
 |       return kPayloadNameGeneric; | 
 |   } | 
 |   return kPayloadNameGeneric; | 
 | } | 
 |  | 
 | VideoCodecType PayloadStringToCodecType(const std::string& name) { | 
 |   if (CodecNamesEq(name.c_str(), kPayloadNameVp8)) | 
 |     return kVideoCodecVP8; | 
 |   if (CodecNamesEq(name.c_str(), kPayloadNameVp9)) | 
 |     return kVideoCodecVP9; | 
 |   if (CodecNamesEq(name.c_str(), kPayloadNameH264)) | 
 |     return kVideoCodecH264; | 
 |   if (CodecNamesEq(name.c_str(), kPayloadNameI420)) | 
 |     return kVideoCodecI420; | 
 |   if (CodecNamesEq(name.c_str(), kPayloadNameRED)) | 
 |     return kVideoCodecRED; | 
 |   if (CodecNamesEq(name.c_str(), kPayloadNameULPFEC)) | 
 |     return kVideoCodecULPFEC; | 
 |   if (CodecNamesEq(name.c_str(), kPayloadNameFlexfec)) | 
 |     return kVideoCodecFlexfec; | 
 |   if (CodecNamesEq(name.c_str(), kPayloadNameMultiplex)) | 
 |     return kVideoCodecMultiplex; | 
 |   return kVideoCodecGeneric; | 
 | } | 
 |  | 
 | const uint32_t BitrateAllocation::kMaxBitrateBps = | 
 |     std::numeric_limits<uint32_t>::max(); | 
 |  | 
 | BitrateAllocation::BitrateAllocation() : sum_(0), bitrates_{}, has_bitrate_{} {} | 
 |  | 
 | bool BitrateAllocation::SetBitrate(size_t spatial_index, | 
 |                                    size_t temporal_index, | 
 |                                    uint32_t bitrate_bps) { | 
 |   RTC_CHECK_LT(spatial_index, kMaxSpatialLayers); | 
 |   RTC_CHECK_LT(temporal_index, kMaxTemporalStreams); | 
 |   RTC_CHECK_LE(bitrates_[spatial_index][temporal_index], sum_); | 
 |   uint64_t new_bitrate_sum_bps = sum_; | 
 |   new_bitrate_sum_bps -= bitrates_[spatial_index][temporal_index]; | 
 |   new_bitrate_sum_bps += bitrate_bps; | 
 |   if (new_bitrate_sum_bps > kMaxBitrateBps) | 
 |     return false; | 
 |  | 
 |   bitrates_[spatial_index][temporal_index] = bitrate_bps; | 
 |   has_bitrate_[spatial_index][temporal_index] = true; | 
 |   sum_ = static_cast<uint32_t>(new_bitrate_sum_bps); | 
 |   return true; | 
 | } | 
 |  | 
 | bool BitrateAllocation::HasBitrate(size_t spatial_index, | 
 |                                    size_t temporal_index) const { | 
 |   RTC_CHECK_LT(spatial_index, kMaxSpatialLayers); | 
 |   RTC_CHECK_LT(temporal_index, kMaxTemporalStreams); | 
 |   return has_bitrate_[spatial_index][temporal_index]; | 
 | } | 
 |  | 
 | uint32_t BitrateAllocation::GetBitrate(size_t spatial_index, | 
 |                                        size_t temporal_index) const { | 
 |   RTC_CHECK_LT(spatial_index, kMaxSpatialLayers); | 
 |   RTC_CHECK_LT(temporal_index, kMaxTemporalStreams); | 
 |   return bitrates_[spatial_index][temporal_index]; | 
 | } | 
 |  | 
 | // Whether the specific spatial layers has the bitrate set in any of its | 
 | // temporal layers. | 
 | bool BitrateAllocation::IsSpatialLayerUsed(size_t spatial_index) const { | 
 |   RTC_CHECK_LT(spatial_index, kMaxSpatialLayers); | 
 |   for (int i = 0; i < kMaxTemporalStreams; ++i) { | 
 |     if (has_bitrate_[spatial_index][i]) | 
 |       return true; | 
 |   } | 
 |   return false; | 
 | } | 
 |  | 
 | // Get the sum of all the temporal layer for a specific spatial layer. | 
 | uint32_t BitrateAllocation::GetSpatialLayerSum(size_t spatial_index) const { | 
 |   RTC_CHECK_LT(spatial_index, kMaxSpatialLayers); | 
 |   uint32_t sum = 0; | 
 |   for (int i = 0; i < kMaxTemporalStreams; ++i) | 
 |     sum += bitrates_[spatial_index][i]; | 
 |   return sum; | 
 | } | 
 |  | 
 | std::string BitrateAllocation::ToString() const { | 
 |   if (sum_ == 0) | 
 |     return "BitrateAllocation [ [] ]"; | 
 |  | 
 |   // TODO(sprang): Replace this stringstream with something cheaper. | 
 |   std::ostringstream oss; | 
 |   oss << "BitrateAllocation ["; | 
 |   uint32_t spatial_cumulator = 0; | 
 |   for (int si = 0; si < kMaxSpatialLayers; ++si) { | 
 |     RTC_DCHECK_LE(spatial_cumulator, sum_); | 
 |     if (spatial_cumulator == sum_) | 
 |       break; | 
 |  | 
 |     const uint32_t layer_sum = GetSpatialLayerSum(si); | 
 |     if (layer_sum == sum_) { | 
 |       oss << " ["; | 
 |     } else { | 
 |       if (si > 0) | 
 |         oss << ","; | 
 |       oss << std::endl << "  ["; | 
 |     } | 
 |     spatial_cumulator += layer_sum; | 
 |  | 
 |     uint32_t temporal_cumulator = 0; | 
 |     for (int ti = 0; ti < kMaxTemporalStreams; ++ti) { | 
 |       RTC_DCHECK_LE(temporal_cumulator, layer_sum); | 
 |       if (temporal_cumulator == layer_sum) | 
 |         break; | 
 |  | 
 |       if (ti > 0) | 
 |         oss << ", "; | 
 |  | 
 |       uint32_t bitrate = bitrates_[si][ti]; | 
 |       oss << bitrate; | 
 |       temporal_cumulator += bitrate; | 
 |     } | 
 |     oss << "]"; | 
 |   } | 
 |  | 
 |   RTC_DCHECK_EQ(spatial_cumulator, sum_); | 
 |   oss << " ]"; | 
 |   return oss.str(); | 
 | } | 
 |  | 
 | std::ostream& BitrateAllocation::operator<<(std::ostream& os) const { | 
 |   os << ToString(); | 
 |   return os; | 
 | } | 
 |  | 
 | }  // namespace webrtc |