video_codec.cc (6693B)
1 /* 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 "api/video_codecs/video_codec.h" 12 13 #include <cstring> 14 #include <optional> 15 #include <string> 16 17 #include "absl/strings/match.h" 18 #include "api/video/video_codec_type.h" 19 #include "api/video_codecs/scalability_mode.h" 20 #include "api/video_codecs/sdp_video_format.h" 21 #include "api/video_codecs/simulcast_stream.h" 22 #include "rtc_base/checks.h" 23 #include "rtc_base/strings/string_builder.h" 24 25 namespace webrtc { 26 namespace { 27 constexpr char kPayloadNameVp8[] = "VP8"; 28 constexpr char kPayloadNameVp9[] = "VP9"; 29 constexpr char kPayloadNameAv1[] = "AV1"; 30 // TODO(bugs.webrtc.org/13166): Remove AV1X when backwards compatibility is not 31 // needed. 32 constexpr char kPayloadNameAv1x[] = "AV1X"; 33 constexpr char kPayloadNameH264[] = "H264"; 34 constexpr char kPayloadNameGeneric[] = "Generic"; 35 constexpr char kPayloadNameH265[] = "H265"; 36 } // namespace 37 38 bool VideoCodecVP8::operator==(const VideoCodecVP8& other) const { 39 return (numberOfTemporalLayers == other.numberOfTemporalLayers && 40 denoisingOn == other.denoisingOn && 41 automaticResizeOn == other.automaticResizeOn && 42 keyFrameInterval == other.keyFrameInterval); 43 } 44 45 bool VideoCodecVP9::operator==(const VideoCodecVP9& other) const { 46 return (numberOfTemporalLayers == other.numberOfTemporalLayers && 47 denoisingOn == other.denoisingOn && 48 keyFrameInterval == other.keyFrameInterval && 49 adaptiveQpMode == other.adaptiveQpMode && 50 automaticResizeOn == other.automaticResizeOn && 51 numberOfSpatialLayers == other.numberOfSpatialLayers && 52 flexibleMode == other.flexibleMode); 53 } 54 55 bool VideoCodecH264::operator==(const VideoCodecH264& other) const { 56 return (keyFrameInterval == other.keyFrameInterval && 57 numberOfTemporalLayers == other.numberOfTemporalLayers); 58 } 59 60 VideoCodec::VideoCodec() 61 : codecType(kVideoCodecGeneric), 62 width(0), 63 height(0), 64 startBitrate(0), 65 maxBitrate(0), 66 minBitrate(0), 67 maxFramerate(0), 68 active(true), 69 qpMax(0), 70 numberOfSimulcastStreams(0), 71 simulcastStream(), 72 spatialLayers(), 73 mode(VideoCodecMode::kRealtimeVideo), 74 expect_encode_from_texture(false), 75 timing_frame_thresholds({.delay_ms = 0, .outlier_ratio_percent = 0}), 76 legacy_conference_mode(false), 77 codec_specific_(), 78 complexity_(VideoCodecComplexity::kComplexityNormal) {} 79 80 std::string VideoCodec::ToString() const { 81 char string_buf[2048]; 82 SimpleStringBuilder ss(string_buf); 83 84 ss << "VideoCodec {" << "type: " << CodecTypeToPayloadString(codecType) 85 << ", mode: " 86 << (mode == VideoCodecMode::kRealtimeVideo ? "RealtimeVideo" 87 : "Screensharing"); 88 if (IsSinglecast()) { 89 ss << ", Singlecast: {" << width << "x" << height << " " 90 << ScalabilityModeToString(GetScalabilityMode()) 91 << (active ? ", active" : ", inactive") << "}"; 92 } else { 93 ss << ", Simulcast: {"; 94 for (size_t i = 0; i < numberOfSimulcastStreams; ++i) { 95 const SimulcastStream stream = simulcastStream[i]; 96 ss << "[" << stream.width << "x" << stream.height << " " 97 << ScalabilityModeToString(stream.GetScalabilityMode()) 98 << (stream.active ? ", active" : ", inactive") << "]"; 99 } 100 ss << "}"; 101 } 102 ss << "}"; 103 return ss.str(); 104 } 105 106 VideoCodecVP8* VideoCodec::VP8() { 107 RTC_DCHECK_EQ(codecType, kVideoCodecVP8); 108 return &codec_specific_.VP8; 109 } 110 111 const VideoCodecVP8& VideoCodec::VP8() const { 112 RTC_DCHECK_EQ(codecType, kVideoCodecVP8); 113 return codec_specific_.VP8; 114 } 115 116 VideoCodecVP9* VideoCodec::VP9() { 117 RTC_DCHECK_EQ(codecType, kVideoCodecVP9); 118 return &codec_specific_.VP9; 119 } 120 121 const VideoCodecVP9& VideoCodec::VP9() const { 122 RTC_DCHECK_EQ(codecType, kVideoCodecVP9); 123 return codec_specific_.VP9; 124 } 125 126 VideoCodecH264* VideoCodec::H264() { 127 RTC_DCHECK_EQ(codecType, kVideoCodecH264); 128 return &codec_specific_.H264; 129 } 130 131 const VideoCodecH264& VideoCodec::H264() const { 132 RTC_DCHECK_EQ(codecType, kVideoCodecH264); 133 return codec_specific_.H264; 134 } 135 136 VideoCodecAV1* VideoCodec::AV1() { 137 RTC_DCHECK_EQ(codecType, kVideoCodecAV1); 138 return &codec_specific_.AV1; 139 } 140 141 const VideoCodecAV1& VideoCodec::AV1() const { 142 RTC_DCHECK_EQ(codecType, kVideoCodecAV1); 143 return codec_specific_.AV1; 144 } 145 146 const char* CodecTypeToPayloadString(VideoCodecType type) { 147 switch (type) { 148 case kVideoCodecVP8: 149 return kPayloadNameVp8; 150 case kVideoCodecVP9: 151 return kPayloadNameVp9; 152 case kVideoCodecAV1: 153 return kPayloadNameAv1; 154 case kVideoCodecH264: 155 return kPayloadNameH264; 156 case kVideoCodecGeneric: 157 return kPayloadNameGeneric; 158 case kVideoCodecH265: 159 return kPayloadNameH265; 160 } 161 RTC_CHECK_NOTREACHED(); 162 } 163 164 VideoCodecType PayloadStringToCodecType(const std::string& name) { 165 if (absl::EqualsIgnoreCase(name, kPayloadNameVp8)) 166 return kVideoCodecVP8; 167 if (absl::EqualsIgnoreCase(name, kPayloadNameVp9)) 168 return kVideoCodecVP9; 169 if (absl::EqualsIgnoreCase(name, kPayloadNameAv1) || 170 absl::EqualsIgnoreCase(name, kPayloadNameAv1x)) 171 return kVideoCodecAV1; 172 if (absl::EqualsIgnoreCase(name, kPayloadNameH264)) 173 return kVideoCodecH264; 174 if (absl::EqualsIgnoreCase(name, kPayloadNameH265)) 175 return kVideoCodecH265; 176 return kVideoCodecGeneric; 177 } 178 179 VideoCodecComplexity VideoCodec::GetVideoEncoderComplexity() const { 180 return complexity_; 181 } 182 183 void VideoCodec::SetVideoEncoderComplexity( 184 VideoCodecComplexity complexity_setting) { 185 complexity_ = complexity_setting; 186 } 187 188 bool VideoCodec::GetFrameDropEnabled() const { 189 return frame_drop_enabled_; 190 } 191 192 void VideoCodec::SetFrameDropEnabled(bool enabled) { 193 frame_drop_enabled_ = enabled; 194 } 195 196 bool VideoCodec::IsMixedCodec() const { 197 std::optional<SdpVideoFormat> first_format; 198 for (size_t i = 0; i < numberOfSimulcastStreams; ++i) { 199 if (!simulcastStream[i].active) { 200 continue; 201 } 202 if (!simulcastStream[i].format.has_value()) { 203 return false; // Format is always set for active layers in mixed-codec. 204 } 205 if (!first_format.has_value()) { 206 first_format = simulcastStream[i].format; // First active layer's format. 207 } else if (!first_format->IsSameCodec(*simulcastStream[i].format)) { 208 return true; 209 } 210 } 211 return false; 212 } 213 214 } // namespace webrtc