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