blob: 59157eb1429e6469f1b1325e9247634dce44d903 [file] [log] [blame]
Anders Carlsson67537952018-05-03 11:28:29 +02001/*
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/fakewebrtcvideoengine.h"
12
13#include "media/base/codec.h"
14#include "media/engine/simulcast_encoder_adapter.h"
15#include "media/engine/vp8_encoder_simulcast_proxy.h"
16#include "media/engine/webrtcvideodecoderfactory.h"
17#include "media/engine/webrtcvideoencoderfactory.h"
18#include "modules/video_coding/include/video_error_codes.h"
19#include "rtc_base/basictypes.h"
20#include "rtc_base/gunit.h"
21#include "rtc_base/stringutils.h"
22
23namespace cricket {
24
25namespace {
26
27static const int kEventTimeoutMs = 10000;
28
29bool 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.
44FakeWebRtcVideoDecoder::FakeWebRtcVideoDecoder(
45 FakeWebRtcVideoDecoderFactory* factory)
46 : num_frames_received_(0), factory_(factory) {}
47
48FakeWebRtcVideoDecoder::~FakeWebRtcVideoDecoder() {
49 if (factory_) {
50 factory_->DecoderDestroyed(this);
51 }
52}
53
54int32_t FakeWebRtcVideoDecoder::InitDecode(const webrtc::VideoCodec*, int32_t) {
55 return WEBRTC_VIDEO_CODEC_OK;
56}
57
58int32_t FakeWebRtcVideoDecoder::Decode(const webrtc::EncodedImage&,
59 bool,
60 const webrtc::RTPFragmentationHeader*,
61 const webrtc::CodecSpecificInfo*,
62 int64_t) {
63 num_frames_received_++;
64 return WEBRTC_VIDEO_CODEC_OK;
65}
66
67int32_t FakeWebRtcVideoDecoder::RegisterDecodeCompleteCallback(
68 webrtc::DecodedImageCallback*) {
69 return WEBRTC_VIDEO_CODEC_OK;
70}
71
72int32_t FakeWebRtcVideoDecoder::Release() {
73 return WEBRTC_VIDEO_CODEC_OK;
74}
75
76int FakeWebRtcVideoDecoder::GetNumFramesReceived() const {
77 return num_frames_received_;
78}
79
80// Decoder factory.
81FakeWebRtcVideoDecoderFactory::FakeWebRtcVideoDecoderFactory()
82 : num_created_decoders_(0),
83 internal_decoder_factory_(new webrtc::InternalDecoderFactory()) {}
84
85FakeWebRtcVideoDecoderFactory::~FakeWebRtcVideoDecoderFactory() {
86 delete internal_decoder_factory_;
87}
88
89std::vector<webrtc::SdpVideoFormat>
90FakeWebRtcVideoDecoderFactory::GetSupportedFormats() const {
91 std::vector<webrtc::SdpVideoFormat> formats =
92 internal_decoder_factory_->GetSupportedFormats();
93
94 // Add external codecs.
95 for (const webrtc::SdpVideoFormat& format : supported_codec_formats_) {
96 // Don't add same codec twice.
97 if (!IsFormatSupported(formats, format))
98 formats.push_back(format);
99 }
100
101 return formats;
102}
103
104std::unique_ptr<webrtc::VideoDecoder>
105FakeWebRtcVideoDecoderFactory::CreateVideoDecoder(
106 const webrtc::SdpVideoFormat& format) {
107 if (IsFormatSupported(supported_codec_formats_, format)) {
108 num_created_decoders_++;
109 std::unique_ptr<FakeWebRtcVideoDecoder> decoder =
110 rtc::MakeUnique<FakeWebRtcVideoDecoder>(this);
111 decoders_.push_back(decoder.get());
112 return decoder;
113 } else {
114 return internal_decoder_factory_->CreateVideoDecoder(format);
115 }
116}
117
118void FakeWebRtcVideoDecoderFactory::DecoderDestroyed(
119 FakeWebRtcVideoDecoder* decoder) {
120 decoders_.erase(std::remove(decoders_.begin(), decoders_.end(), decoder),
121 decoders_.end());
122}
123
124void FakeWebRtcVideoDecoderFactory::AddSupportedVideoCodecType(
125 const webrtc::SdpVideoFormat& format) {
126 supported_codec_formats_.push_back(format);
127}
128
129int FakeWebRtcVideoDecoderFactory::GetNumCreatedDecoders() {
130 return num_created_decoders_;
131}
132
133const std::vector<FakeWebRtcVideoDecoder*>&
134FakeWebRtcVideoDecoderFactory::decoders() {
135 return decoders_;
136}
137
138// Encoder.
139FakeWebRtcVideoEncoder::FakeWebRtcVideoEncoder(
140 FakeWebRtcVideoEncoderFactory* factory)
141 : init_encode_event_(false, false),
142 num_frames_encoded_(0),
143 factory_(factory) {}
144
145FakeWebRtcVideoEncoder::~FakeWebRtcVideoEncoder() {
146 if (factory_) {
147 factory_->EncoderDestroyed(this);
148 }
149}
150
151int32_t FakeWebRtcVideoEncoder::InitEncode(
152 const webrtc::VideoCodec* codecSettings,
153 int32_t numberOfCores,
154 size_t maxPayloadSize) {
155 rtc::CritScope lock(&crit_);
156 codec_settings_ = *codecSettings;
157 init_encode_event_.Set();
158 return WEBRTC_VIDEO_CODEC_OK;
159}
160
161int32_t FakeWebRtcVideoEncoder::Encode(
162 const webrtc::VideoFrame& inputImage,
163 const webrtc::CodecSpecificInfo* codecSpecificInfo,
164 const std::vector<webrtc::FrameType>* frame_types) {
165 rtc::CritScope lock(&crit_);
166 ++num_frames_encoded_;
167 init_encode_event_.Set();
168 return WEBRTC_VIDEO_CODEC_OK;
169}
170
171int32_t FakeWebRtcVideoEncoder::RegisterEncodeCompleteCallback(
172 webrtc::EncodedImageCallback* callback) {
173 return WEBRTC_VIDEO_CODEC_OK;
174}
175
176int32_t FakeWebRtcVideoEncoder::Release() {
177 return WEBRTC_VIDEO_CODEC_OK;
178}
179
180int32_t FakeWebRtcVideoEncoder::SetChannelParameters(uint32_t packetLoss,
181 int64_t rtt) {
182 return WEBRTC_VIDEO_CODEC_OK;
183}
184
185int32_t FakeWebRtcVideoEncoder::SetRateAllocation(
186 const webrtc::VideoBitrateAllocation& allocation,
187 uint32_t framerate) {
188 return WEBRTC_VIDEO_CODEC_OK;
189}
190
191bool FakeWebRtcVideoEncoder::WaitForInitEncode() {
192 return init_encode_event_.Wait(kEventTimeoutMs);
193}
194
195webrtc::VideoCodec FakeWebRtcVideoEncoder::GetCodecSettings() {
196 rtc::CritScope lock(&crit_);
197 return codec_settings_;
198}
199
200int FakeWebRtcVideoEncoder::GetNumEncodedFrames() {
201 rtc::CritScope lock(&crit_);
202 return num_frames_encoded_;
203}
204
205// Video encoder factory.
206FakeWebRtcVideoEncoderFactory::FakeWebRtcVideoEncoderFactory()
207 : created_video_encoder_event_(false, false),
208 num_created_encoders_(0),
209 encoders_have_internal_sources_(false),
210 internal_encoder_factory_(new webrtc::InternalEncoderFactory()),
211 vp8_factory_mode_(false) {}
212
213FakeWebRtcVideoEncoderFactory::~FakeWebRtcVideoEncoderFactory() {
214 delete internal_encoder_factory_;
215}
216
217std::vector<webrtc::SdpVideoFormat>
218FakeWebRtcVideoEncoderFactory::GetSupportedFormats() const {
219 std::vector<webrtc::SdpVideoFormat> formats =
220 internal_encoder_factory_->GetSupportedFormats();
221
222 // Add external codecs.
223 for (const webrtc::SdpVideoFormat& format : formats_) {
224 // Don't add same codec twice.
225 if (!IsFormatSupported(formats, format))
226 formats.push_back(format);
227 }
228
229 return formats;
230}
231
232std::unique_ptr<webrtc::VideoEncoder>
233FakeWebRtcVideoEncoderFactory::CreateVideoEncoder(
234 const webrtc::SdpVideoFormat& format) {
235 rtc::CritScope lock(&crit_);
236 std::unique_ptr<webrtc::VideoEncoder> encoder;
237 if (IsFormatSupported(formats_, format)) {
238 if (CodecNamesEq(format.name.c_str(), kVp8CodecName) &&
239 !vp8_factory_mode_) {
240 // The simulcast adapter will ask this factory for multiple VP8
241 // encoders. Enter vp8_factory_mode so that we now create these encoders
242 // instead of more adapters.
243 vp8_factory_mode_ = true;
244 encoder = rtc::MakeUnique<webrtc::SimulcastEncoderAdapter>(this);
245 } else {
246 num_created_encoders_++;
247 created_video_encoder_event_.Set();
248 encoder = rtc::MakeUnique<FakeWebRtcVideoEncoder>(this);
249 encoders_.push_back(static_cast<FakeWebRtcVideoEncoder*>(encoder.get()));
250 }
251 } else {
252 RTC_LOG(LS_INFO) << "FakeWebRtcVideoEncoderFactory: no match for "
253 << format.name;
254 for (auto elem : format.parameters) {
255 RTC_LOG(LS_INFO) << elem.first << " " << elem.second;
256 }
257 encoder = CodecNamesEq(format.name.c_str(), kVp8CodecName)
258 ? rtc::MakeUnique<webrtc::VP8EncoderSimulcastProxy>(
259 internal_encoder_factory_)
260 : internal_encoder_factory_->CreateVideoEncoder(format);
261 }
262 return encoder;
263}
264
265webrtc::VideoEncoderFactory::CodecInfo
266FakeWebRtcVideoEncoderFactory::QueryVideoEncoder(
267 const webrtc::SdpVideoFormat& format) const {
268 if (IsFormatSupported(formats_, format)) {
269 webrtc::VideoEncoderFactory::CodecInfo info;
270 info.has_internal_source = encoders_have_internal_sources_;
271 info.is_hardware_accelerated = true;
272 return info;
273 } else {
274 return internal_encoder_factory_->QueryVideoEncoder(format);
275 }
276}
277
278bool FakeWebRtcVideoEncoderFactory::WaitForCreatedVideoEncoders(
279 int num_encoders) {
280 int64_t start_offset_ms = rtc::TimeMillis();
281 int64_t wait_time = kEventTimeoutMs;
282 do {
283 if (GetNumCreatedEncoders() >= num_encoders)
284 return true;
285 wait_time = kEventTimeoutMs - (rtc::TimeMillis() - start_offset_ms);
286 } while (wait_time > 0 && created_video_encoder_event_.Wait(wait_time));
287 return false;
288}
289
290void FakeWebRtcVideoEncoderFactory::EncoderDestroyed(
291 FakeWebRtcVideoEncoder* encoder) {
292 rtc::CritScope lock(&crit_);
293 encoders_.erase(std::remove(encoders_.begin(), encoders_.end(), encoder),
294 encoders_.end());
295}
296
297void FakeWebRtcVideoEncoderFactory::set_encoders_have_internal_sources(
298 bool internal_source) {
299 encoders_have_internal_sources_ = internal_source;
300}
301
302void FakeWebRtcVideoEncoderFactory::AddSupportedVideoCodec(
303 const webrtc::SdpVideoFormat& format) {
304 formats_.push_back(format);
305}
306
307void FakeWebRtcVideoEncoderFactory::AddSupportedVideoCodecType(
308 const std::string& name) {
309 // This is to match the default H264 params of cricket::VideoCodec.
310 cricket::VideoCodec video_codec(name);
311 formats_.push_back(
312 webrtc::SdpVideoFormat(video_codec.name, video_codec.params));
313}
314
315int FakeWebRtcVideoEncoderFactory::GetNumCreatedEncoders() {
316 rtc::CritScope lock(&crit_);
317 return num_created_encoders_;
318}
319
320const std::vector<FakeWebRtcVideoEncoder*>
321FakeWebRtcVideoEncoderFactory::encoders() {
322 rtc::CritScope lock(&crit_);
323 return encoders_;
324}
325
326} // namespace cricket