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 <algorithm>
14 #include <memory>
15
16 #include "absl/strings/match.h"
17 #include "media/base/codec.h"
18 #include "media/base/media_constants.h"
19 #include "media/engine/simulcast_encoder_adapter.h"
20 #include "modules/video_coding/include/video_error_codes.h"
21 #include "rtc_base/time_utils.h"
22
23 namespace cricket {
24
25 namespace {
26
27 static const int kEventTimeoutMs = 10000;
28
IsFormatSupported(const std::vector<webrtc::SdpVideoFormat> & supported_formats,const webrtc::SdpVideoFormat & format)29 bool IsFormatSupported(
30 const std::vector<webrtc::SdpVideoFormat>& supported_formats,
31 const webrtc::SdpVideoFormat& format) {
32 for (const webrtc::SdpVideoFormat& supported_format : supported_formats) {
33 if (IsSameCodec(format.name, format.parameters, supported_format.name,
34 supported_format.parameters)) {
35 return true;
36 }
37 }
38 return false;
39 }
40
41 } // namespace
42
43 // Decoder.
FakeWebRtcVideoDecoder(FakeWebRtcVideoDecoderFactory * factory)44 FakeWebRtcVideoDecoder::FakeWebRtcVideoDecoder(
45 FakeWebRtcVideoDecoderFactory* factory)
46 : num_frames_received_(0), factory_(factory) {}
47
~FakeWebRtcVideoDecoder()48 FakeWebRtcVideoDecoder::~FakeWebRtcVideoDecoder() {
49 if (factory_) {
50 factory_->DecoderDestroyed(this);
51 }
52 }
53
InitDecode(const webrtc::VideoCodec *,int32_t)54 int32_t FakeWebRtcVideoDecoder::InitDecode(const webrtc::VideoCodec*, int32_t) {
55 return WEBRTC_VIDEO_CODEC_OK;
56 }
57
Decode(const webrtc::EncodedImage &,bool,int64_t)58 int32_t FakeWebRtcVideoDecoder::Decode(const webrtc::EncodedImage&,
59 bool,
60 int64_t) {
61 num_frames_received_++;
62 return WEBRTC_VIDEO_CODEC_OK;
63 }
64
RegisterDecodeCompleteCallback(webrtc::DecodedImageCallback *)65 int32_t FakeWebRtcVideoDecoder::RegisterDecodeCompleteCallback(
66 webrtc::DecodedImageCallback*) {
67 return WEBRTC_VIDEO_CODEC_OK;
68 }
69
Release()70 int32_t FakeWebRtcVideoDecoder::Release() {
71 return WEBRTC_VIDEO_CODEC_OK;
72 }
73
GetNumFramesReceived() const74 int FakeWebRtcVideoDecoder::GetNumFramesReceived() const {
75 return num_frames_received_;
76 }
77
78 // Decoder factory.
FakeWebRtcVideoDecoderFactory()79 FakeWebRtcVideoDecoderFactory::FakeWebRtcVideoDecoderFactory()
80 : num_created_decoders_(0) {}
81
82 std::vector<webrtc::SdpVideoFormat>
GetSupportedFormats() const83 FakeWebRtcVideoDecoderFactory::GetSupportedFormats() const {
84 std::vector<webrtc::SdpVideoFormat> formats;
85
86 for (const webrtc::SdpVideoFormat& format : supported_codec_formats_) {
87 // Don't add same codec twice.
88 if (!IsFormatSupported(formats, format))
89 formats.push_back(format);
90 }
91
92 return formats;
93 }
94
95 std::unique_ptr<webrtc::VideoDecoder>
CreateVideoDecoder(const webrtc::SdpVideoFormat & format)96 FakeWebRtcVideoDecoderFactory::CreateVideoDecoder(
97 const webrtc::SdpVideoFormat& format) {
98 if (IsFormatSupported(supported_codec_formats_, format)) {
99 num_created_decoders_++;
100 std::unique_ptr<FakeWebRtcVideoDecoder> decoder =
101 std::make_unique<FakeWebRtcVideoDecoder>(this);
102 decoders_.push_back(decoder.get());
103 return decoder;
104 }
105
106 return nullptr;
107 }
108
DecoderDestroyed(FakeWebRtcVideoDecoder * decoder)109 void FakeWebRtcVideoDecoderFactory::DecoderDestroyed(
110 FakeWebRtcVideoDecoder* decoder) {
111 decoders_.erase(std::remove(decoders_.begin(), decoders_.end(), decoder),
112 decoders_.end());
113 }
114
AddSupportedVideoCodecType(const std::string & name)115 void FakeWebRtcVideoDecoderFactory::AddSupportedVideoCodecType(
116 const std::string& name) {
117 // This is to match the default H264 params of cricket::VideoCodec.
118 cricket::VideoCodec video_codec(name);
119 supported_codec_formats_.push_back(
120 webrtc::SdpVideoFormat(video_codec.name, video_codec.params));
121 }
122
GetNumCreatedDecoders()123 int FakeWebRtcVideoDecoderFactory::GetNumCreatedDecoders() {
124 return num_created_decoders_;
125 }
126
127 const std::vector<FakeWebRtcVideoDecoder*>&
decoders()128 FakeWebRtcVideoDecoderFactory::decoders() {
129 return decoders_;
130 }
131
132 // Encoder.
FakeWebRtcVideoEncoder(FakeWebRtcVideoEncoderFactory * factory)133 FakeWebRtcVideoEncoder::FakeWebRtcVideoEncoder(
134 FakeWebRtcVideoEncoderFactory* factory)
135 : num_frames_encoded_(0), factory_(factory) {}
136
~FakeWebRtcVideoEncoder()137 FakeWebRtcVideoEncoder::~FakeWebRtcVideoEncoder() {
138 if (factory_) {
139 factory_->EncoderDestroyed(this);
140 }
141 }
142
SetFecControllerOverride(webrtc::FecControllerOverride * fec_controller_override)143 void FakeWebRtcVideoEncoder::SetFecControllerOverride(
144 webrtc::FecControllerOverride* fec_controller_override) {
145 // Ignored.
146 }
147
InitEncode(const webrtc::VideoCodec * codecSettings,const VideoEncoder::Settings & settings)148 int32_t FakeWebRtcVideoEncoder::InitEncode(
149 const webrtc::VideoCodec* codecSettings,
150 const VideoEncoder::Settings& settings) {
151 webrtc::MutexLock lock(&mutex_);
152 codec_settings_ = *codecSettings;
153 init_encode_event_.Set();
154 return WEBRTC_VIDEO_CODEC_OK;
155 }
156
Encode(const webrtc::VideoFrame & inputImage,const std::vector<webrtc::VideoFrameType> * frame_types)157 int32_t FakeWebRtcVideoEncoder::Encode(
158 const webrtc::VideoFrame& inputImage,
159 const std::vector<webrtc::VideoFrameType>* frame_types) {
160 webrtc::MutexLock lock(&mutex_);
161 ++num_frames_encoded_;
162 init_encode_event_.Set();
163 return WEBRTC_VIDEO_CODEC_OK;
164 }
165
RegisterEncodeCompleteCallback(webrtc::EncodedImageCallback * callback)166 int32_t FakeWebRtcVideoEncoder::RegisterEncodeCompleteCallback(
167 webrtc::EncodedImageCallback* callback) {
168 return WEBRTC_VIDEO_CODEC_OK;
169 }
170
Release()171 int32_t FakeWebRtcVideoEncoder::Release() {
172 return WEBRTC_VIDEO_CODEC_OK;
173 }
174
SetRates(const RateControlParameters & parameters)175 void FakeWebRtcVideoEncoder::SetRates(const RateControlParameters& parameters) {
176 }
177
GetEncoderInfo() const178 webrtc::VideoEncoder::EncoderInfo FakeWebRtcVideoEncoder::GetEncoderInfo()
179 const {
180 EncoderInfo info;
181 info.is_hardware_accelerated = true;
182 info.has_internal_source = false;
183 return info;
184 }
185
WaitForInitEncode()186 bool FakeWebRtcVideoEncoder::WaitForInitEncode() {
187 return init_encode_event_.Wait(kEventTimeoutMs);
188 }
189
GetCodecSettings()190 webrtc::VideoCodec FakeWebRtcVideoEncoder::GetCodecSettings() {
191 webrtc::MutexLock lock(&mutex_);
192 return codec_settings_;
193 }
194
GetNumEncodedFrames()195 int FakeWebRtcVideoEncoder::GetNumEncodedFrames() {
196 webrtc::MutexLock lock(&mutex_);
197 return num_frames_encoded_;
198 }
199
200 // Video encoder factory.
FakeWebRtcVideoEncoderFactory()201 FakeWebRtcVideoEncoderFactory::FakeWebRtcVideoEncoderFactory()
202 : num_created_encoders_(0),
203 encoders_have_internal_sources_(false),
204 vp8_factory_mode_(false) {}
205
206 std::vector<webrtc::SdpVideoFormat>
GetSupportedFormats() const207 FakeWebRtcVideoEncoderFactory::GetSupportedFormats() const {
208 std::vector<webrtc::SdpVideoFormat> formats;
209
210 for (const webrtc::SdpVideoFormat& format : formats_) {
211 // Don't add same codec twice.
212 if (!IsFormatSupported(formats, format))
213 formats.push_back(format);
214 }
215
216 return formats;
217 }
218
219 std::unique_ptr<webrtc::VideoEncoder>
CreateVideoEncoder(const webrtc::SdpVideoFormat & format)220 FakeWebRtcVideoEncoderFactory::CreateVideoEncoder(
221 const webrtc::SdpVideoFormat& format) {
222 webrtc::MutexLock lock(&mutex_);
223 std::unique_ptr<webrtc::VideoEncoder> encoder;
224 if (IsFormatSupported(formats_, format)) {
225 if (absl::EqualsIgnoreCase(format.name, kVp8CodecName) &&
226 !vp8_factory_mode_) {
227 // The simulcast adapter will ask this factory for multiple VP8
228 // encoders. Enter vp8_factory_mode so that we now create these encoders
229 // instead of more adapters.
230 vp8_factory_mode_ = true;
231 encoder = std::make_unique<webrtc::SimulcastEncoderAdapter>(this, format);
232 } else {
233 num_created_encoders_++;
234 created_video_encoder_event_.Set();
235 encoder = std::make_unique<FakeWebRtcVideoEncoder>(this);
236 encoders_.push_back(static_cast<FakeWebRtcVideoEncoder*>(encoder.get()));
237 }
238 }
239 return encoder;
240 }
241
242 webrtc::VideoEncoderFactory::CodecInfo
QueryVideoEncoder(const webrtc::SdpVideoFormat & format) const243 FakeWebRtcVideoEncoderFactory::QueryVideoEncoder(
244 const webrtc::SdpVideoFormat& format) const {
245 webrtc::VideoEncoderFactory::CodecInfo info;
246 info.has_internal_source = encoders_have_internal_sources_;
247 info.is_hardware_accelerated = true;
248 return info;
249 }
250
WaitForCreatedVideoEncoders(int num_encoders)251 bool FakeWebRtcVideoEncoderFactory::WaitForCreatedVideoEncoders(
252 int num_encoders) {
253 int64_t start_offset_ms = rtc::TimeMillis();
254 int64_t wait_time = kEventTimeoutMs;
255 do {
256 if (GetNumCreatedEncoders() >= num_encoders)
257 return true;
258 wait_time = kEventTimeoutMs - (rtc::TimeMillis() - start_offset_ms);
259 } while (wait_time > 0 && created_video_encoder_event_.Wait(wait_time));
260 return false;
261 }
262
EncoderDestroyed(FakeWebRtcVideoEncoder * encoder)263 void FakeWebRtcVideoEncoderFactory::EncoderDestroyed(
264 FakeWebRtcVideoEncoder* encoder) {
265 webrtc::MutexLock lock(&mutex_);
266 encoders_.erase(std::remove(encoders_.begin(), encoders_.end(), encoder),
267 encoders_.end());
268 }
269
set_encoders_have_internal_sources(bool internal_source)270 void FakeWebRtcVideoEncoderFactory::set_encoders_have_internal_sources(
271 bool internal_source) {
272 encoders_have_internal_sources_ = internal_source;
273 }
274
AddSupportedVideoCodec(const webrtc::SdpVideoFormat & format)275 void FakeWebRtcVideoEncoderFactory::AddSupportedVideoCodec(
276 const webrtc::SdpVideoFormat& format) {
277 formats_.push_back(format);
278 }
279
AddSupportedVideoCodecType(const std::string & name)280 void FakeWebRtcVideoEncoderFactory::AddSupportedVideoCodecType(
281 const std::string& name) {
282 // This is to match the default H264 params of cricket::VideoCodec.
283 cricket::VideoCodec video_codec(name);
284 formats_.push_back(
285 webrtc::SdpVideoFormat(video_codec.name, video_codec.params));
286 }
287
GetNumCreatedEncoders()288 int FakeWebRtcVideoEncoderFactory::GetNumCreatedEncoders() {
289 webrtc::MutexLock lock(&mutex_);
290 return num_created_encoders_;
291 }
292
293 const std::vector<FakeWebRtcVideoEncoder*>
encoders()294 FakeWebRtcVideoEncoderFactory::encoders() {
295 webrtc::MutexLock lock(&mutex_);
296 return encoders_;
297 }
298
299 } // namespace cricket
300