fake_webrtc_video_engine.cc (9693B)
1 /* 2 * Copyright (c) 2018 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 "media/engine/fake_webrtc_video_engine.h" 12 13 #include <cstdint> 14 #include <memory> 15 #include <optional> 16 #include <string> 17 #include <vector> 18 19 #include "absl/strings/match.h" 20 #include "api/environment/environment.h" 21 #include "api/fec_controller_override.h" 22 #include "api/units/time_delta.h" 23 #include "api/video/encoded_image.h" 24 #include "api/video/video_frame.h" 25 #include "api/video/video_frame_type.h" 26 #include "api/video_codecs/scalability_mode.h" 27 #include "api/video_codecs/sdp_video_format.h" 28 #include "api/video_codecs/video_codec.h" 29 #include "api/video_codecs/video_decoder.h" 30 #include "api/video_codecs/video_encoder.h" 31 #include "api/video_codecs/video_encoder_factory.h" 32 #include "media/base/codec.h" 33 #include "media/base/media_constants.h" 34 #include "media/engine/simulcast_encoder_adapter.h" 35 #include "modules/video_coding/include/video_error_codes.h" 36 #include "rtc_base/logging.h" 37 #include "rtc_base/synchronization/mutex.h" 38 #include "rtc_base/time_utils.h" 39 40 namespace webrtc { 41 42 namespace { 43 44 constexpr TimeDelta kEventTimeout = TimeDelta::Seconds(10); 45 46 bool IsScalabilityModeSupported(const std::vector<SdpVideoFormat>& formats, 47 std::optional<std::string> scalability_mode) { 48 if (!scalability_mode.has_value()) { 49 return true; 50 } 51 for (const auto& format : formats) { 52 for (const auto& mode : format.scalability_modes) { 53 if (ScalabilityModeToString(mode) == scalability_mode) 54 return true; 55 } 56 } 57 return false; 58 } 59 60 } // namespace 61 62 // Decoder. 63 FakeWebRtcVideoDecoder::FakeWebRtcVideoDecoder( 64 FakeWebRtcVideoDecoderFactory* factory) 65 : num_frames_received_(0), factory_(factory) {} 66 67 FakeWebRtcVideoDecoder::~FakeWebRtcVideoDecoder() { 68 if (factory_) { 69 factory_->DecoderDestroyed(this); 70 } 71 } 72 73 bool FakeWebRtcVideoDecoder::Configure(const Settings& /* settings */) { 74 return true; 75 } 76 77 int32_t FakeWebRtcVideoDecoder::Decode(const EncodedImage&, int64_t) { 78 num_frames_received_++; 79 return WEBRTC_VIDEO_CODEC_OK; 80 } 81 82 int32_t FakeWebRtcVideoDecoder::RegisterDecodeCompleteCallback( 83 DecodedImageCallback*) { 84 return WEBRTC_VIDEO_CODEC_OK; 85 } 86 87 int32_t FakeWebRtcVideoDecoder::Release() { 88 return WEBRTC_VIDEO_CODEC_OK; 89 } 90 91 int FakeWebRtcVideoDecoder::GetNumFramesReceived() const { 92 return num_frames_received_; 93 } 94 95 // Decoder factory. 96 FakeWebRtcVideoDecoderFactory::FakeWebRtcVideoDecoderFactory() 97 : num_created_decoders_(0) {} 98 99 std::vector<SdpVideoFormat> FakeWebRtcVideoDecoderFactory::GetSupportedFormats() 100 const { 101 std::vector<SdpVideoFormat> formats; 102 103 for (const SdpVideoFormat& format : supported_codec_formats_) { 104 // We need to test erroneous scenarios, so just warn if there's 105 // a duplicate. 106 if (format.IsCodecInList(formats)) { 107 RTC_LOG(LS_WARNING) << "GetSupportedFormats found a duplicate format: " 108 << format << ", check that this is expected."; 109 } 110 formats.push_back(format); 111 } 112 113 return formats; 114 } 115 116 std::unique_ptr<VideoDecoder> FakeWebRtcVideoDecoderFactory::Create( 117 const Environment& /* env */, 118 const SdpVideoFormat& format) { 119 if (format.IsCodecInList(supported_codec_formats_)) { 120 num_created_decoders_++; 121 std::unique_ptr<FakeWebRtcVideoDecoder> decoder = 122 std::make_unique<FakeWebRtcVideoDecoder>(this); 123 decoders_.push_back(decoder.get()); 124 return decoder; 125 } 126 127 return nullptr; 128 } 129 130 void FakeWebRtcVideoDecoderFactory::DecoderDestroyed( 131 FakeWebRtcVideoDecoder* decoder) { 132 std::erase(decoders_, decoder); 133 } 134 135 void FakeWebRtcVideoDecoderFactory::AddSupportedVideoCodec( 136 const SdpVideoFormat& format) { 137 supported_codec_formats_.push_back(format); 138 } 139 140 void FakeWebRtcVideoDecoderFactory::AddSupportedVideoCodecType( 141 const std::string& name) { 142 // This is to match the default H264 params of Codec. 143 Codec video_codec = CreateVideoCodec(name); 144 supported_codec_formats_.push_back( 145 SdpVideoFormat(video_codec.name, video_codec.params)); 146 } 147 148 int FakeWebRtcVideoDecoderFactory::GetNumCreatedDecoders() { 149 return num_created_decoders_; 150 } 151 152 const std::vector<FakeWebRtcVideoDecoder*>& 153 FakeWebRtcVideoDecoderFactory::decoders() { 154 return decoders_; 155 } 156 157 // Encoder. 158 FakeWebRtcVideoEncoder::FakeWebRtcVideoEncoder( 159 FakeWebRtcVideoEncoderFactory* factory) 160 : num_frames_encoded_(0), factory_(factory) {} 161 162 FakeWebRtcVideoEncoder::~FakeWebRtcVideoEncoder() { 163 if (factory_) { 164 factory_->EncoderDestroyed(this); 165 } 166 } 167 168 void FakeWebRtcVideoEncoder::SetFecControllerOverride( 169 FecControllerOverride* /* fec_controller_override */) { 170 // Ignored. 171 } 172 173 int32_t FakeWebRtcVideoEncoder::InitEncode( 174 const VideoCodec* codecSettings, 175 const VideoEncoder::Settings& /* settings */) { 176 MutexLock lock(&mutex_); 177 codec_settings_ = *codecSettings; 178 init_encode_event_.Set(); 179 return WEBRTC_VIDEO_CODEC_OK; 180 } 181 182 int32_t FakeWebRtcVideoEncoder::Encode( 183 const VideoFrame& /* inputImage */, 184 const std::vector<VideoFrameType>* /* frame_types */) { 185 MutexLock lock(&mutex_); 186 ++num_frames_encoded_; 187 init_encode_event_.Set(); 188 return WEBRTC_VIDEO_CODEC_OK; 189 } 190 191 int32_t FakeWebRtcVideoEncoder::RegisterEncodeCompleteCallback( 192 EncodedImageCallback* /* callback */) { 193 return WEBRTC_VIDEO_CODEC_OK; 194 } 195 196 int32_t FakeWebRtcVideoEncoder::Release() { 197 return WEBRTC_VIDEO_CODEC_OK; 198 } 199 200 void FakeWebRtcVideoEncoder::SetRates( 201 const RateControlParameters& /* parameters */) {} 202 203 VideoEncoder::EncoderInfo FakeWebRtcVideoEncoder::GetEncoderInfo() const { 204 EncoderInfo info; 205 info.is_hardware_accelerated = true; 206 return info; 207 } 208 209 bool FakeWebRtcVideoEncoder::WaitForInitEncode() { 210 return init_encode_event_.Wait(kEventTimeout); 211 } 212 213 VideoCodec FakeWebRtcVideoEncoder::GetCodecSettings() { 214 MutexLock lock(&mutex_); 215 return codec_settings_; 216 } 217 218 int FakeWebRtcVideoEncoder::GetNumEncodedFrames() { 219 MutexLock lock(&mutex_); 220 return num_frames_encoded_; 221 } 222 223 // Video encoder factory. 224 FakeWebRtcVideoEncoderFactory::FakeWebRtcVideoEncoderFactory() 225 : num_created_encoders_(0), vp8_factory_mode_(false) {} 226 227 std::vector<SdpVideoFormat> FakeWebRtcVideoEncoderFactory::GetSupportedFormats() 228 const { 229 std::vector<SdpVideoFormat> formats; 230 231 for (const SdpVideoFormat& format : formats_) { 232 // Don't add same codec twice. 233 if (!format.IsCodecInList(formats)) 234 formats.push_back(format); 235 } 236 237 return formats; 238 } 239 240 VideoEncoderFactory::CodecSupport 241 FakeWebRtcVideoEncoderFactory::QueryCodecSupport( 242 const SdpVideoFormat& format, 243 std::optional<std::string> scalability_mode) const { 244 std::vector<SdpVideoFormat> supported_formats; 245 for (const auto& f : formats_) { 246 if (format.IsSameCodec(f)) 247 supported_formats.push_back(f); 248 } 249 if (format.IsCodecInList(formats_)) { 250 return {.is_supported = IsScalabilityModeSupported(supported_formats, 251 scalability_mode)}; 252 } 253 return {.is_supported = false}; 254 } 255 256 std::unique_ptr<VideoEncoder> FakeWebRtcVideoEncoderFactory::Create( 257 const Environment& env, 258 const SdpVideoFormat& format) { 259 MutexLock lock(&mutex_); 260 std::unique_ptr<VideoEncoder> encoder; 261 if (format.IsCodecInList(formats_)) { 262 if (absl::EqualsIgnoreCase(format.name, kVp8CodecName) && 263 !vp8_factory_mode_) { 264 // The simulcast adapter will ask this factory for multiple VP8 265 // encoders. Enter vp8_factory_mode so that we now create these encoders 266 // instead of more adapters. 267 vp8_factory_mode_ = true; 268 encoder = std::make_unique<SimulcastEncoderAdapter>( 269 env, /*primary_factory=*/this, /*fallback_factory=*/nullptr, format); 270 } else { 271 num_created_encoders_++; 272 created_video_encoder_event_.Set(); 273 encoder = std::make_unique<FakeWebRtcVideoEncoder>(this); 274 encoders_.push_back(static_cast<FakeWebRtcVideoEncoder*>(encoder.get())); 275 } 276 } 277 return encoder; 278 } 279 280 bool FakeWebRtcVideoEncoderFactory::WaitForCreatedVideoEncoders( 281 int num_encoders) { 282 int64_t start_offset_ms = TimeMillis(); 283 int64_t wait_time = kEventTimeout.ms(); 284 do { 285 if (GetNumCreatedEncoders() >= num_encoders) 286 return true; 287 wait_time = kEventTimeout.ms() - (TimeMillis() - start_offset_ms); 288 } while (wait_time > 0 && 289 created_video_encoder_event_.Wait(TimeDelta::Millis(wait_time))); 290 return false; 291 } 292 293 void FakeWebRtcVideoEncoderFactory::EncoderDestroyed( 294 FakeWebRtcVideoEncoder* encoder) { 295 MutexLock lock(&mutex_); 296 std::erase(encoders_, encoder); 297 } 298 299 void FakeWebRtcVideoEncoderFactory::AddSupportedVideoCodec( 300 const SdpVideoFormat& format) { 301 formats_.push_back(format); 302 } 303 304 void FakeWebRtcVideoEncoderFactory::AddSupportedVideoCodecType( 305 const std::string& name, 306 const std::vector<ScalabilityMode>& scalability_modes) { 307 // This is to match the default H264 params of Codec. 308 Codec video_codec = CreateVideoCodec(name); 309 formats_.push_back( 310 SdpVideoFormat(video_codec.name, video_codec.params, 311 {scalability_modes.begin(), scalability_modes.end()})); 312 } 313 314 int FakeWebRtcVideoEncoderFactory::GetNumCreatedEncoders() { 315 MutexLock lock(&mutex_); 316 return num_created_encoders_; 317 } 318 319 const std::vector<FakeWebRtcVideoEncoder*> 320 FakeWebRtcVideoEncoderFactory::encoders() { 321 MutexLock lock(&mutex_); 322 return encoders_; 323 } 324 325 } // namespace webrtc