• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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