1 /*
2 * libjingle
3 * Copyright 2004 Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #ifndef TALK_MEDIA_BASE_FAKEMEDIAENGINE_H_
29 #define TALK_MEDIA_BASE_FAKEMEDIAENGINE_H_
30
31 #include <list>
32 #include <map>
33 #include <set>
34 #include <string>
35 #include <vector>
36
37 #include "talk/base/buffer.h"
38 #include "talk/base/stringutils.h"
39 #include "talk/media/base/audiorenderer.h"
40 #include "talk/media/base/mediaengine.h"
41 #include "talk/media/base/rtputils.h"
42 #include "talk/media/base/streamparams.h"
43 #include "talk/p2p/base/sessiondescription.h"
44
45 namespace cricket {
46
47 class FakeMediaEngine;
48 class FakeVideoEngine;
49 class FakeVoiceEngine;
50
51 // A common helper class that handles sending and receiving RTP/RTCP packets.
52 template <class Base> class RtpHelper : public Base {
53 public:
RtpHelper()54 RtpHelper()
55 : sending_(false),
56 playout_(false),
57 fail_set_send_codecs_(false),
58 fail_set_recv_codecs_(false),
59 send_ssrc_(0),
60 ready_to_send_(false) {}
recv_extensions()61 const std::vector<RtpHeaderExtension>& recv_extensions() {
62 return recv_extensions_;
63 }
send_extensions()64 const std::vector<RtpHeaderExtension>& send_extensions() {
65 return send_extensions_;
66 }
sending()67 bool sending() const { return sending_; }
playout()68 bool playout() const { return playout_; }
rtp_packets()69 const std::list<std::string>& rtp_packets() const { return rtp_packets_; }
rtcp_packets()70 const std::list<std::string>& rtcp_packets() const { return rtcp_packets_; }
71
SendRtp(const void * data,int len)72 bool SendRtp(const void* data, int len) {
73 if (!sending_) {
74 return false;
75 }
76 talk_base::Buffer packet(data, len, kMaxRtpPacketLen);
77 return Base::SendPacket(&packet);
78 }
SendRtcp(const void * data,int len)79 bool SendRtcp(const void* data, int len) {
80 talk_base::Buffer packet(data, len, kMaxRtpPacketLen);
81 return Base::SendRtcp(&packet);
82 }
83
CheckRtp(const void * data,int len)84 bool CheckRtp(const void* data, int len) {
85 bool success = !rtp_packets_.empty();
86 if (success) {
87 std::string packet = rtp_packets_.front();
88 rtp_packets_.pop_front();
89 success = (packet == std::string(static_cast<const char*>(data), len));
90 }
91 return success;
92 }
CheckRtcp(const void * data,int len)93 bool CheckRtcp(const void* data, int len) {
94 bool success = !rtcp_packets_.empty();
95 if (success) {
96 std::string packet = rtcp_packets_.front();
97 rtcp_packets_.pop_front();
98 success = (packet == std::string(static_cast<const char*>(data), len));
99 }
100 return success;
101 }
CheckNoRtp()102 bool CheckNoRtp() { return rtp_packets_.empty(); }
CheckNoRtcp()103 bool CheckNoRtcp() { return rtcp_packets_.empty(); }
SetRecvRtpHeaderExtensions(const std::vector<RtpHeaderExtension> & extensions)104 virtual bool SetRecvRtpHeaderExtensions(
105 const std::vector<RtpHeaderExtension>& extensions) {
106 recv_extensions_ = extensions;
107 return true;
108 }
SetSendRtpHeaderExtensions(const std::vector<RtpHeaderExtension> & extensions)109 virtual bool SetSendRtpHeaderExtensions(
110 const std::vector<RtpHeaderExtension>& extensions) {
111 send_extensions_ = extensions;
112 return true;
113 }
set_fail_set_send_codecs(bool fail)114 void set_fail_set_send_codecs(bool fail) { fail_set_send_codecs_ = fail; }
set_fail_set_recv_codecs(bool fail)115 void set_fail_set_recv_codecs(bool fail) { fail_set_recv_codecs_ = fail; }
AddSendStream(const StreamParams & sp)116 virtual bool AddSendStream(const StreamParams& sp) {
117 if (std::find(send_streams_.begin(), send_streams_.end(), sp) !=
118 send_streams_.end()) {
119 return false;
120 }
121 send_streams_.push_back(sp);
122 return true;
123 }
RemoveSendStream(uint32 ssrc)124 virtual bool RemoveSendStream(uint32 ssrc) {
125 return RemoveStreamBySsrc(&send_streams_, ssrc);
126 }
AddRecvStream(const StreamParams & sp)127 virtual bool AddRecvStream(const StreamParams& sp) {
128 if (std::find(receive_streams_.begin(), receive_streams_.end(), sp) !=
129 receive_streams_.end()) {
130 return false;
131 }
132 receive_streams_.push_back(sp);
133 return true;
134 }
RemoveRecvStream(uint32 ssrc)135 virtual bool RemoveRecvStream(uint32 ssrc) {
136 return RemoveStreamBySsrc(&receive_streams_, ssrc);
137 }
MuteStream(uint32 ssrc,bool on)138 virtual bool MuteStream(uint32 ssrc, bool on) {
139 if (!HasSendStream(ssrc) && ssrc != 0)
140 return false;
141 if (on)
142 muted_streams_.insert(ssrc);
143 else
144 muted_streams_.erase(ssrc);
145 return true;
146 }
IsStreamMuted(uint32 ssrc)147 bool IsStreamMuted(uint32 ssrc) const {
148 bool ret = muted_streams_.find(ssrc) != muted_streams_.end();
149 // If |ssrc = 0| check if the first send stream is muted.
150 if (!ret && ssrc == 0 && !send_streams_.empty()) {
151 return muted_streams_.find(send_streams_[0].first_ssrc()) !=
152 muted_streams_.end();
153 }
154 return ret;
155 }
send_streams()156 const std::vector<StreamParams>& send_streams() const {
157 return send_streams_;
158 }
recv_streams()159 const std::vector<StreamParams>& recv_streams() const {
160 return receive_streams_;
161 }
HasRecvStream(uint32 ssrc)162 bool HasRecvStream(uint32 ssrc) const {
163 return GetStreamBySsrc(receive_streams_, ssrc, NULL);
164 }
HasSendStream(uint32 ssrc)165 bool HasSendStream(uint32 ssrc) const {
166 return GetStreamBySsrc(send_streams_, ssrc, NULL);
167 }
168 // TODO(perkj): This is to support legacy unit test that only check one
169 // sending stream.
send_ssrc()170 const uint32 send_ssrc() {
171 if (send_streams_.empty())
172 return 0;
173 return send_streams_[0].first_ssrc();
174 }
175
176 // TODO(perkj): This is to support legacy unit test that only check one
177 // sending stream.
rtcp_cname()178 const std::string rtcp_cname() {
179 if (send_streams_.empty())
180 return "";
181 return send_streams_[0].cname;
182 }
183
ready_to_send()184 bool ready_to_send() const {
185 return ready_to_send_;
186 }
187
188 protected:
set_sending(bool send)189 bool set_sending(bool send) {
190 sending_ = send;
191 return true;
192 }
set_playout(bool playout)193 void set_playout(bool playout) { playout_ = playout; }
OnPacketReceived(talk_base::Buffer * packet,const talk_base::PacketTime & packet_time)194 virtual void OnPacketReceived(talk_base::Buffer* packet,
195 const talk_base::PacketTime& packet_time) {
196 rtp_packets_.push_back(std::string(packet->data(), packet->length()));
197 }
OnRtcpReceived(talk_base::Buffer * packet,const talk_base::PacketTime & packet_time)198 virtual void OnRtcpReceived(talk_base::Buffer* packet,
199 const talk_base::PacketTime& packet_time) {
200 rtcp_packets_.push_back(std::string(packet->data(), packet->length()));
201 }
OnReadyToSend(bool ready)202 virtual void OnReadyToSend(bool ready) {
203 ready_to_send_ = ready;
204 }
fail_set_send_codecs()205 bool fail_set_send_codecs() const { return fail_set_send_codecs_; }
fail_set_recv_codecs()206 bool fail_set_recv_codecs() const { return fail_set_recv_codecs_; }
207
208 private:
209 bool sending_;
210 bool playout_;
211 std::vector<RtpHeaderExtension> recv_extensions_;
212 std::vector<RtpHeaderExtension> send_extensions_;
213 std::list<std::string> rtp_packets_;
214 std::list<std::string> rtcp_packets_;
215 std::vector<StreamParams> send_streams_;
216 std::vector<StreamParams> receive_streams_;
217 std::set<uint32> muted_streams_;
218 bool fail_set_send_codecs_;
219 bool fail_set_recv_codecs_;
220 uint32 send_ssrc_;
221 std::string rtcp_cname_;
222 bool ready_to_send_;
223 };
224
225 class FakeVoiceMediaChannel : public RtpHelper<VoiceMediaChannel> {
226 public:
227 struct DtmfInfo {
DtmfInfoDtmfInfo228 DtmfInfo(uint32 ssrc, int event_code, int duration, int flags)
229 : ssrc(ssrc), event_code(event_code), duration(duration), flags(flags) {
230 }
231 uint32 ssrc;
232 int event_code;
233 int duration;
234 int flags;
235 };
FakeVoiceMediaChannel(FakeVoiceEngine * engine)236 explicit FakeVoiceMediaChannel(FakeVoiceEngine* engine)
237 : engine_(engine),
238 fail_set_send_(false),
239 ringback_tone_ssrc_(0),
240 ringback_tone_play_(false),
241 ringback_tone_loop_(false),
242 time_since_last_typing_(-1) {
243 output_scalings_[0] = OutputScaling(); // For default channel.
244 }
245 ~FakeVoiceMediaChannel();
recv_codecs()246 const std::vector<AudioCodec>& recv_codecs() const { return recv_codecs_; }
send_codecs()247 const std::vector<AudioCodec>& send_codecs() const { return send_codecs_; }
codecs()248 const std::vector<AudioCodec>& codecs() const { return send_codecs(); }
dtmf_info_queue()249 const std::vector<DtmfInfo>& dtmf_info_queue() const {
250 return dtmf_info_queue_;
251 }
options()252 const AudioOptions& options() const { return options_; }
253
ringback_tone_ssrc()254 uint32 ringback_tone_ssrc() const { return ringback_tone_ssrc_; }
ringback_tone_play()255 bool ringback_tone_play() const { return ringback_tone_play_; }
ringback_tone_loop()256 bool ringback_tone_loop() const { return ringback_tone_loop_; }
257
SetRecvCodecs(const std::vector<AudioCodec> & codecs)258 virtual bool SetRecvCodecs(const std::vector<AudioCodec>& codecs) {
259 if (fail_set_recv_codecs()) {
260 // Fake the failure in SetRecvCodecs.
261 return false;
262 }
263 recv_codecs_ = codecs;
264 return true;
265 }
SetSendCodecs(const std::vector<AudioCodec> & codecs)266 virtual bool SetSendCodecs(const std::vector<AudioCodec>& codecs) {
267 if (fail_set_send_codecs()) {
268 // Fake the failure in SetSendCodecs.
269 return false;
270 }
271 send_codecs_ = codecs;
272 return true;
273 }
SetPlayout(bool playout)274 virtual bool SetPlayout(bool playout) {
275 set_playout(playout);
276 return true;
277 }
SetSend(SendFlags flag)278 virtual bool SetSend(SendFlags flag) {
279 if (fail_set_send_) {
280 return false;
281 }
282 return set_sending(flag != SEND_NOTHING);
283 }
SetSendBandwidth(bool autobw,int bps)284 virtual bool SetSendBandwidth(bool autobw, int bps) { return true; }
AddRecvStream(const StreamParams & sp)285 virtual bool AddRecvStream(const StreamParams& sp) {
286 if (!RtpHelper<VoiceMediaChannel>::AddRecvStream(sp))
287 return false;
288 output_scalings_[sp.first_ssrc()] = OutputScaling();
289 return true;
290 }
RemoveRecvStream(uint32 ssrc)291 virtual bool RemoveRecvStream(uint32 ssrc) {
292 if (!RtpHelper<VoiceMediaChannel>::RemoveRecvStream(ssrc))
293 return false;
294 output_scalings_.erase(ssrc);
295 return true;
296 }
SetRemoteRenderer(uint32 ssrc,AudioRenderer * renderer)297 virtual bool SetRemoteRenderer(uint32 ssrc, AudioRenderer* renderer) {
298 std::map<uint32, AudioRenderer*>::iterator it =
299 remote_renderers_.find(ssrc);
300 if (renderer) {
301 if (it != remote_renderers_.end()) {
302 ASSERT(it->second == renderer);
303 } else {
304 remote_renderers_.insert(std::make_pair(ssrc, renderer));
305 renderer->AddChannel(0);
306 }
307 } else {
308 if (it != remote_renderers_.end()) {
309 it->second->RemoveChannel(0);
310 remote_renderers_.erase(it);
311 } else {
312 return false;
313 }
314 }
315 return true;
316 }
SetLocalRenderer(uint32 ssrc,AudioRenderer * renderer)317 virtual bool SetLocalRenderer(uint32 ssrc, AudioRenderer* renderer) {
318 std::map<uint32, AudioRenderer*>::iterator it = local_renderers_.find(ssrc);
319 if (renderer) {
320 if (it != local_renderers_.end()) {
321 ASSERT(it->second == renderer);
322 } else {
323 local_renderers_.insert(std::make_pair(ssrc, renderer));
324 renderer->AddChannel(0);
325 }
326 } else {
327 if (it != local_renderers_.end()) {
328 it->second->RemoveChannel(0);
329 local_renderers_.erase(it);
330 } else {
331 return false;
332 }
333 }
334 return true;
335 }
336
GetActiveStreams(AudioInfo::StreamList * streams)337 virtual bool GetActiveStreams(AudioInfo::StreamList* streams) { return true; }
GetOutputLevel()338 virtual int GetOutputLevel() { return 0; }
set_time_since_last_typing(int ms)339 void set_time_since_last_typing(int ms) { time_since_last_typing_ = ms; }
GetTimeSinceLastTyping()340 virtual int GetTimeSinceLastTyping() { return time_since_last_typing_; }
SetTypingDetectionParameters(int time_window,int cost_per_typing,int reporting_threshold,int penalty_decay,int type_event_delay)341 virtual void SetTypingDetectionParameters(
342 int time_window, int cost_per_typing, int reporting_threshold,
343 int penalty_decay, int type_event_delay) {}
344
SetRingbackTone(const char * buf,int len)345 virtual bool SetRingbackTone(const char* buf, int len) { return true; }
PlayRingbackTone(uint32 ssrc,bool play,bool loop)346 virtual bool PlayRingbackTone(uint32 ssrc, bool play, bool loop) {
347 ringback_tone_ssrc_ = ssrc;
348 ringback_tone_play_ = play;
349 ringback_tone_loop_ = loop;
350 return true;
351 }
352
CanInsertDtmf()353 virtual bool CanInsertDtmf() {
354 for (std::vector<AudioCodec>::const_iterator it = send_codecs_.begin();
355 it != send_codecs_.end(); ++it) {
356 // Find the DTMF telephone event "codec".
357 if (_stricmp(it->name.c_str(), "telephone-event") == 0) {
358 return true;
359 }
360 }
361 return false;
362 }
InsertDtmf(uint32 ssrc,int event_code,int duration,int flags)363 virtual bool InsertDtmf(uint32 ssrc, int event_code, int duration,
364 int flags) {
365 dtmf_info_queue_.push_back(DtmfInfo(ssrc, event_code, duration, flags));
366 return true;
367 }
368
SetOutputScaling(uint32 ssrc,double left,double right)369 virtual bool SetOutputScaling(uint32 ssrc, double left, double right) {
370 if (0 == ssrc) {
371 std::map<uint32, OutputScaling>::iterator it;
372 for (it = output_scalings_.begin(); it != output_scalings_.end(); ++it) {
373 it->second.left = left;
374 it->second.right = right;
375 }
376 return true;
377 } else if (output_scalings_.find(ssrc) != output_scalings_.end()) {
378 output_scalings_[ssrc].left = left;
379 output_scalings_[ssrc].right = right;
380 return true;
381 }
382 return false;
383 }
GetOutputScaling(uint32 ssrc,double * left,double * right)384 virtual bool GetOutputScaling(uint32 ssrc, double* left, double* right) {
385 if (output_scalings_.find(ssrc) == output_scalings_.end())
386 return false;
387 *left = output_scalings_[ssrc].left;
388 *right = output_scalings_[ssrc].right;
389 return true;
390 }
391
GetStats(VoiceMediaInfo * info)392 virtual bool GetStats(VoiceMediaInfo* info) { return false; }
GetLastMediaError(uint32 * ssrc,VoiceMediaChannel::Error * error)393 virtual void GetLastMediaError(uint32* ssrc,
394 VoiceMediaChannel::Error* error) {
395 *ssrc = 0;
396 *error = fail_set_send_ ? VoiceMediaChannel::ERROR_REC_DEVICE_OPEN_FAILED
397 : VoiceMediaChannel::ERROR_NONE;
398 }
399
set_fail_set_send(bool fail)400 void set_fail_set_send(bool fail) { fail_set_send_ = fail; }
TriggerError(uint32 ssrc,VoiceMediaChannel::Error error)401 void TriggerError(uint32 ssrc, VoiceMediaChannel::Error error) {
402 VoiceMediaChannel::SignalMediaError(ssrc, error);
403 }
404
SetOptions(const AudioOptions & options)405 virtual bool SetOptions(const AudioOptions& options) {
406 // Does a "merge" of current options and set options.
407 options_.SetAll(options);
408 return true;
409 }
GetOptions(AudioOptions * options)410 virtual bool GetOptions(AudioOptions* options) const {
411 *options = options_;
412 return true;
413 }
414
415 private:
416 struct OutputScaling {
OutputScalingOutputScaling417 OutputScaling() : left(1.0), right(1.0) {}
418 double left, right;
419 };
420
421 FakeVoiceEngine* engine_;
422 std::vector<AudioCodec> recv_codecs_;
423 std::vector<AudioCodec> send_codecs_;
424 std::map<uint32, OutputScaling> output_scalings_;
425 std::vector<DtmfInfo> dtmf_info_queue_;
426 bool fail_set_send_;
427 uint32 ringback_tone_ssrc_;
428 bool ringback_tone_play_;
429 bool ringback_tone_loop_;
430 int time_since_last_typing_;
431 AudioOptions options_;
432 std::map<uint32, AudioRenderer*> local_renderers_;
433 std::map<uint32, AudioRenderer*> remote_renderers_;
434 };
435
436 // A helper function to compare the FakeVoiceMediaChannel::DtmfInfo.
CompareDtmfInfo(const FakeVoiceMediaChannel::DtmfInfo & info,uint32 ssrc,int event_code,int duration,int flags)437 inline bool CompareDtmfInfo(const FakeVoiceMediaChannel::DtmfInfo& info,
438 uint32 ssrc, int event_code, int duration,
439 int flags) {
440 return (info.duration == duration && info.event_code == event_code &&
441 info.flags == flags && info.ssrc == ssrc);
442 }
443
444 class FakeVideoMediaChannel : public RtpHelper<VideoMediaChannel> {
445 public:
FakeVideoMediaChannel(FakeVideoEngine * engine)446 explicit FakeVideoMediaChannel(FakeVideoEngine* engine)
447 : engine_(engine),
448 sent_intra_frame_(false),
449 requested_intra_frame_(false) {}
450 ~FakeVideoMediaChannel();
451
recv_codecs()452 const std::vector<VideoCodec>& recv_codecs() const { return recv_codecs_; }
send_codecs()453 const std::vector<VideoCodec>& send_codecs() const { return send_codecs_; }
codecs()454 const std::vector<VideoCodec>& codecs() const { return send_codecs(); }
rendering()455 bool rendering() const { return playout(); }
options()456 const VideoOptions& options() const { return options_; }
renderers()457 const std::map<uint32, VideoRenderer*>& renderers() const {
458 return renderers_;
459 }
GetSendStreamFormat(uint32 ssrc,VideoFormat * format)460 bool GetSendStreamFormat(uint32 ssrc, VideoFormat* format) {
461 if (send_formats_.find(ssrc) == send_formats_.end()) {
462 return false;
463 }
464 *format = send_formats_[ssrc];
465 return true;
466 }
SetSendStreamFormat(uint32 ssrc,const VideoFormat & format)467 virtual bool SetSendStreamFormat(uint32 ssrc, const VideoFormat& format) {
468 if (send_formats_.find(ssrc) == send_formats_.end()) {
469 return false;
470 }
471 send_formats_[ssrc] = format;
472 return true;
473 }
474
AddSendStream(const StreamParams & sp)475 virtual bool AddSendStream(const StreamParams& sp) {
476 if (!RtpHelper<VideoMediaChannel>::AddSendStream(sp)) {
477 return false;
478 }
479 SetSendStreamDefaultFormat(sp.first_ssrc());
480 return true;
481 }
RemoveSendStream(uint32 ssrc)482 virtual bool RemoveSendStream(uint32 ssrc) {
483 send_formats_.erase(ssrc);
484 return RtpHelper<VideoMediaChannel>::RemoveSendStream(ssrc);
485 }
486
SetRecvCodecs(const std::vector<VideoCodec> & codecs)487 virtual bool SetRecvCodecs(const std::vector<VideoCodec>& codecs) {
488 if (fail_set_recv_codecs()) {
489 // Fake the failure in SetRecvCodecs.
490 return false;
491 }
492 recv_codecs_ = codecs;
493 return true;
494 }
SetSendCodecs(const std::vector<VideoCodec> & codecs)495 virtual bool SetSendCodecs(const std::vector<VideoCodec>& codecs) {
496 if (fail_set_send_codecs()) {
497 // Fake the failure in SetSendCodecs.
498 return false;
499 }
500 send_codecs_ = codecs;
501
502 for (std::vector<StreamParams>::const_iterator it = send_streams().begin();
503 it != send_streams().end(); ++it) {
504 SetSendStreamDefaultFormat(it->first_ssrc());
505 }
506 return true;
507 }
GetSendCodec(VideoCodec * send_codec)508 virtual bool GetSendCodec(VideoCodec* send_codec) {
509 if (send_codecs_.empty()) {
510 return false;
511 }
512 *send_codec = send_codecs_[0];
513 return true;
514 }
SetRender(bool render)515 virtual bool SetRender(bool render) {
516 set_playout(render);
517 return true;
518 }
SetRenderer(uint32 ssrc,VideoRenderer * r)519 virtual bool SetRenderer(uint32 ssrc, VideoRenderer* r) {
520 if (ssrc != 0 && renderers_.find(ssrc) == renderers_.end()) {
521 return false;
522 }
523 if (ssrc != 0) {
524 renderers_[ssrc] = r;
525 }
526 return true;
527 }
528
SetSend(bool send)529 virtual bool SetSend(bool send) { return set_sending(send); }
SetCapturer(uint32 ssrc,VideoCapturer * capturer)530 virtual bool SetCapturer(uint32 ssrc, VideoCapturer* capturer) {
531 capturers_[ssrc] = capturer;
532 return true;
533 }
HasCapturer(uint32 ssrc)534 bool HasCapturer(uint32 ssrc) const {
535 return capturers_.find(ssrc) != capturers_.end();
536 }
SetSendBandwidth(bool autobw,int bps)537 virtual bool SetSendBandwidth(bool autobw, int bps) { return true; }
AddRecvStream(const StreamParams & sp)538 virtual bool AddRecvStream(const StreamParams& sp) {
539 if (!RtpHelper<VideoMediaChannel>::AddRecvStream(sp))
540 return false;
541 renderers_[sp.first_ssrc()] = NULL;
542 return true;
543 }
RemoveRecvStream(uint32 ssrc)544 virtual bool RemoveRecvStream(uint32 ssrc) {
545 if (!RtpHelper<VideoMediaChannel>::RemoveRecvStream(ssrc))
546 return false;
547 renderers_.erase(ssrc);
548 return true;
549 }
550
GetStats(VideoMediaInfo * info)551 virtual bool GetStats(VideoMediaInfo* info) { return false; }
SendIntraFrame()552 virtual bool SendIntraFrame() {
553 sent_intra_frame_ = true;
554 return true;
555 }
RequestIntraFrame()556 virtual bool RequestIntraFrame() {
557 requested_intra_frame_ = true;
558 return true;
559 }
SetOptions(const VideoOptions & options)560 virtual bool SetOptions(const VideoOptions& options) {
561 options_ = options;
562 return true;
563 }
GetOptions(VideoOptions * options)564 virtual bool GetOptions(VideoOptions* options) const {
565 *options = options_;
566 return true;
567 }
UpdateAspectRatio(int ratio_w,int ratio_h)568 virtual void UpdateAspectRatio(int ratio_w, int ratio_h) {}
set_sent_intra_frame(bool v)569 void set_sent_intra_frame(bool v) { sent_intra_frame_ = v; }
sent_intra_frame()570 bool sent_intra_frame() const { return sent_intra_frame_; }
set_requested_intra_frame(bool v)571 void set_requested_intra_frame(bool v) { requested_intra_frame_ = v; }
requested_intra_frame()572 bool requested_intra_frame() const { return requested_intra_frame_; }
573
574 private:
575 // Be default, each send stream uses the first send codec format.
SetSendStreamDefaultFormat(uint32 ssrc)576 void SetSendStreamDefaultFormat(uint32 ssrc) {
577 if (!send_codecs_.empty()) {
578 send_formats_[ssrc] = VideoFormat(
579 send_codecs_[0].width, send_codecs_[0].height,
580 cricket::VideoFormat::FpsToInterval(send_codecs_[0].framerate),
581 cricket::FOURCC_I420);
582 }
583 }
584
585 FakeVideoEngine* engine_;
586 std::vector<VideoCodec> recv_codecs_;
587 std::vector<VideoCodec> send_codecs_;
588 std::map<uint32, VideoRenderer*> renderers_;
589 std::map<uint32, VideoFormat> send_formats_;
590 std::map<uint32, VideoCapturer*> capturers_;
591 bool sent_intra_frame_;
592 bool requested_intra_frame_;
593 VideoOptions options_;
594 };
595
596 class FakeSoundclipMedia : public SoundclipMedia {
597 public:
PlaySound(const char * buf,int len,int flags)598 virtual bool PlaySound(const char* buf, int len, int flags) { return true; }
599 };
600
601 class FakeDataMediaChannel : public RtpHelper<DataMediaChannel> {
602 public:
FakeDataMediaChannel(void * unused)603 explicit FakeDataMediaChannel(void* unused)
604 : auto_bandwidth_(false), send_blocked_(false), max_bps_(-1) {}
~FakeDataMediaChannel()605 ~FakeDataMediaChannel() {}
recv_codecs()606 const std::vector<DataCodec>& recv_codecs() const { return recv_codecs_; }
send_codecs()607 const std::vector<DataCodec>& send_codecs() const { return send_codecs_; }
codecs()608 const std::vector<DataCodec>& codecs() const { return send_codecs(); }
auto_bandwidth()609 bool auto_bandwidth() const { return auto_bandwidth_; }
max_bps()610 int max_bps() const { return max_bps_; }
611
SetRecvCodecs(const std::vector<DataCodec> & codecs)612 virtual bool SetRecvCodecs(const std::vector<DataCodec>& codecs) {
613 if (fail_set_recv_codecs()) {
614 // Fake the failure in SetRecvCodecs.
615 return false;
616 }
617 recv_codecs_ = codecs;
618 return true;
619 }
SetSendCodecs(const std::vector<DataCodec> & codecs)620 virtual bool SetSendCodecs(const std::vector<DataCodec>& codecs) {
621 if (fail_set_send_codecs()) {
622 // Fake the failure in SetSendCodecs.
623 return false;
624 }
625 send_codecs_ = codecs;
626 return true;
627 }
SetSend(bool send)628 virtual bool SetSend(bool send) { return set_sending(send); }
SetReceive(bool receive)629 virtual bool SetReceive(bool receive) {
630 set_playout(receive);
631 return true;
632 }
SetSendBandwidth(bool autobw,int bps)633 virtual bool SetSendBandwidth(bool autobw, int bps) {
634 auto_bandwidth_ = autobw;
635 max_bps_ = bps;
636 return true;
637 }
AddRecvStream(const StreamParams & sp)638 virtual bool AddRecvStream(const StreamParams& sp) {
639 if (!RtpHelper<DataMediaChannel>::AddRecvStream(sp))
640 return false;
641 return true;
642 }
RemoveRecvStream(uint32 ssrc)643 virtual bool RemoveRecvStream(uint32 ssrc) {
644 if (!RtpHelper<DataMediaChannel>::RemoveRecvStream(ssrc))
645 return false;
646 return true;
647 }
648
SendData(const SendDataParams & params,const talk_base::Buffer & payload,SendDataResult * result)649 virtual bool SendData(const SendDataParams& params,
650 const talk_base::Buffer& payload,
651 SendDataResult* result) {
652 if (send_blocked_) {
653 *result = SDR_BLOCK;
654 return false;
655 } else {
656 last_sent_data_params_ = params;
657 last_sent_data_ = std::string(payload.data(), payload.length());
658 return true;
659 }
660 }
661
last_sent_data_params()662 SendDataParams last_sent_data_params() { return last_sent_data_params_; }
last_sent_data()663 std::string last_sent_data() { return last_sent_data_; }
is_send_blocked()664 bool is_send_blocked() { return send_blocked_; }
set_send_blocked(bool blocked)665 void set_send_blocked(bool blocked) { send_blocked_ = blocked; }
666
667 private:
668 std::vector<DataCodec> recv_codecs_;
669 std::vector<DataCodec> send_codecs_;
670 SendDataParams last_sent_data_params_;
671 std::string last_sent_data_;
672 bool auto_bandwidth_;
673 bool send_blocked_;
674 int max_bps_;
675 };
676
677 // A base class for all of the shared parts between FakeVoiceEngine
678 // and FakeVideoEngine.
679 class FakeBaseEngine {
680 public:
FakeBaseEngine()681 FakeBaseEngine()
682 : loglevel_(-1),
683 options_changed_(false),
684 fail_create_channel_(false) {}
Init(talk_base::Thread * worker_thread)685 bool Init(talk_base::Thread* worker_thread) { return true; }
Terminate()686 void Terminate() {}
687
SetLogging(int level,const char * filter)688 void SetLogging(int level, const char* filter) {
689 loglevel_ = level;
690 logfilter_ = filter;
691 }
692
set_fail_create_channel(bool fail)693 void set_fail_create_channel(bool fail) { fail_create_channel_ = fail; }
694
rtp_header_extensions()695 const std::vector<RtpHeaderExtension>& rtp_header_extensions() const {
696 return rtp_header_extensions_;
697 }
698
699 protected:
700 int loglevel_;
701 std::string logfilter_;
702 // Flag used by optionsmessagehandler_unittest for checking whether any
703 // relevant setting has been updated.
704 // TODO(thaloun): Replace with explicit checks of before & after values.
705 bool options_changed_;
706 bool fail_create_channel_;
707 std::vector<RtpHeaderExtension> rtp_header_extensions_;
708 };
709
710 class FakeVoiceEngine : public FakeBaseEngine {
711 public:
FakeVoiceEngine()712 FakeVoiceEngine()
713 : output_volume_(-1),
714 delay_offset_(0),
715 rx_processor_(NULL),
716 tx_processor_(NULL) {
717 // Add a fake audio codec. Note that the name must not be "" as there are
718 // sanity checks against that.
719 codecs_.push_back(AudioCodec(101, "fake_audio_codec", 0, 0, 1, 0));
720 }
GetCapabilities()721 int GetCapabilities() { return AUDIO_SEND | AUDIO_RECV; }
GetAudioOptions()722 AudioOptions GetAudioOptions() const {
723 return options_;
724 }
GetOptions()725 AudioOptions GetOptions() const {
726 return options_;
727 }
SetOptions(const AudioOptions & options)728 bool SetOptions(const AudioOptions& options) {
729 options_ = options;
730 options_changed_ = true;
731 return true;
732 }
733
CreateChannel()734 VoiceMediaChannel* CreateChannel() {
735 if (fail_create_channel_) {
736 return NULL;
737 }
738
739 FakeVoiceMediaChannel* ch = new FakeVoiceMediaChannel(this);
740 channels_.push_back(ch);
741 return ch;
742 }
GetChannel(size_t index)743 FakeVoiceMediaChannel* GetChannel(size_t index) {
744 return (channels_.size() > index) ? channels_[index] : NULL;
745 }
UnregisterChannel(VoiceMediaChannel * channel)746 void UnregisterChannel(VoiceMediaChannel* channel) {
747 channels_.erase(std::find(channels_.begin(), channels_.end(), channel));
748 }
CreateSoundclip()749 SoundclipMedia* CreateSoundclip() { return new FakeSoundclipMedia(); }
750
codecs()751 const std::vector<AudioCodec>& codecs() { return codecs_; }
SetCodecs(const std::vector<AudioCodec> codecs)752 void SetCodecs(const std::vector<AudioCodec> codecs) { codecs_ = codecs; }
753
SetDelayOffset(int offset)754 bool SetDelayOffset(int offset) {
755 delay_offset_ = offset;
756 return true;
757 }
758
SetDevices(const Device * in_device,const Device * out_device)759 bool SetDevices(const Device* in_device, const Device* out_device) {
760 in_device_ = (in_device) ? in_device->name : "";
761 out_device_ = (out_device) ? out_device->name : "";
762 options_changed_ = true;
763 return true;
764 }
765
GetOutputVolume(int * level)766 bool GetOutputVolume(int* level) {
767 *level = output_volume_;
768 return true;
769 }
770
SetOutputVolume(int level)771 bool SetOutputVolume(int level) {
772 output_volume_ = level;
773 options_changed_ = true;
774 return true;
775 }
776
GetInputLevel()777 int GetInputLevel() { return 0; }
778
SetLocalMonitor(bool enable)779 bool SetLocalMonitor(bool enable) { return true; }
780
RegisterProcessor(uint32 ssrc,VoiceProcessor * voice_processor,MediaProcessorDirection direction)781 bool RegisterProcessor(uint32 ssrc, VoiceProcessor* voice_processor,
782 MediaProcessorDirection direction) {
783 if (direction == MPD_RX) {
784 rx_processor_ = voice_processor;
785 return true;
786 } else if (direction == MPD_TX) {
787 tx_processor_ = voice_processor;
788 return true;
789 }
790 return false;
791 }
792
UnregisterProcessor(uint32 ssrc,VoiceProcessor * voice_processor,MediaProcessorDirection direction)793 bool UnregisterProcessor(uint32 ssrc, VoiceProcessor* voice_processor,
794 MediaProcessorDirection direction) {
795 bool unregistered = false;
796 if (direction & MPD_RX) {
797 rx_processor_ = NULL;
798 unregistered = true;
799 }
800 if (direction & MPD_TX) {
801 tx_processor_ = NULL;
802 unregistered = true;
803 }
804 return unregistered;
805 }
806
807 private:
808 std::vector<FakeVoiceMediaChannel*> channels_;
809 std::vector<AudioCodec> codecs_;
810 int output_volume_;
811 int delay_offset_;
812 std::string in_device_;
813 std::string out_device_;
814 VoiceProcessor* rx_processor_;
815 VoiceProcessor* tx_processor_;
816 AudioOptions options_;
817
818 friend class FakeMediaEngine;
819 };
820
821 class FakeVideoEngine : public FakeBaseEngine {
822 public:
FakeVideoEngine()823 FakeVideoEngine() : renderer_(NULL), capture_(false), processor_(NULL) {
824 // Add a fake video codec. Note that the name must not be "" as there are
825 // sanity checks against that.
826 codecs_.push_back(VideoCodec(0, "fake_video_codec", 0, 0, 0, 0));
827 }
GetOptions(VideoOptions * options)828 bool GetOptions(VideoOptions* options) const {
829 *options = options_;
830 return true;
831 }
SetOptions(const VideoOptions & options)832 bool SetOptions(const VideoOptions& options) {
833 options_ = options;
834 options_changed_ = true;
835 return true;
836 }
GetCapabilities()837 int GetCapabilities() { return VIDEO_SEND | VIDEO_RECV; }
SetDefaultEncoderConfig(const VideoEncoderConfig & config)838 bool SetDefaultEncoderConfig(const VideoEncoderConfig& config) {
839 default_encoder_config_ = config;
840 return true;
841 }
GetDefaultEncoderConfig()842 VideoEncoderConfig GetDefaultEncoderConfig() const {
843 return default_encoder_config_;
844 }
default_encoder_config()845 const VideoEncoderConfig& default_encoder_config() const {
846 return default_encoder_config_;
847 }
848
CreateChannel(VoiceMediaChannel * channel)849 VideoMediaChannel* CreateChannel(VoiceMediaChannel* channel) {
850 if (fail_create_channel_) {
851 return NULL;
852 }
853
854 FakeVideoMediaChannel* ch = new FakeVideoMediaChannel(this);
855 channels_.push_back(ch);
856 return ch;
857 }
GetChannel(size_t index)858 FakeVideoMediaChannel* GetChannel(size_t index) {
859 return (channels_.size() > index) ? channels_[index] : NULL;
860 }
UnregisterChannel(VideoMediaChannel * channel)861 void UnregisterChannel(VideoMediaChannel* channel) {
862 channels_.erase(std::find(channels_.begin(), channels_.end(), channel));
863 }
864
codecs()865 const std::vector<VideoCodec>& codecs() const { return codecs_; }
FindCodec(const VideoCodec & in)866 bool FindCodec(const VideoCodec& in) {
867 for (size_t i = 0; i < codecs_.size(); ++i) {
868 if (codecs_[i].Matches(in)) {
869 return true;
870 }
871 }
872 return false;
873 }
SetCodecs(const std::vector<VideoCodec> codecs)874 void SetCodecs(const std::vector<VideoCodec> codecs) { codecs_ = codecs; }
875
SetCaptureDevice(const Device * device)876 bool SetCaptureDevice(const Device* device) {
877 in_device_ = (device) ? device->name : "";
878 options_changed_ = true;
879 return true;
880 }
SetLocalRenderer(VideoRenderer * r)881 bool SetLocalRenderer(VideoRenderer* r) {
882 renderer_ = r;
883 return true;
884 }
SetCapture(bool capture)885 bool SetCapture(bool capture) {
886 capture_ = capture;
887 return true;
888 }
GetStartCaptureFormat()889 VideoFormat GetStartCaptureFormat() const {
890 return VideoFormat(640, 480, cricket::VideoFormat::FpsToInterval(30),
891 FOURCC_I420);
892 }
893
894 sigslot::repeater2<VideoCapturer*, CaptureState> SignalCaptureStateChange;
895
896 private:
897 std::vector<FakeVideoMediaChannel*> channels_;
898 std::vector<VideoCodec> codecs_;
899 VideoEncoderConfig default_encoder_config_;
900 std::string in_device_;
901 VideoRenderer* renderer_;
902 bool capture_;
903 VideoProcessor* processor_;
904 VideoOptions options_;
905
906 friend class FakeMediaEngine;
907 };
908
909 class FakeMediaEngine :
910 public CompositeMediaEngine<FakeVoiceEngine, FakeVideoEngine> {
911 public:
FakeMediaEngine()912 FakeMediaEngine() {
913 voice_ = FakeVoiceEngine();
914 video_ = FakeVideoEngine();
915 }
~FakeMediaEngine()916 virtual ~FakeMediaEngine() {}
917
SetAudioCodecs(const std::vector<AudioCodec> codecs)918 virtual void SetAudioCodecs(const std::vector<AudioCodec> codecs) {
919 voice_.SetCodecs(codecs);
920 }
921
SetVideoCodecs(const std::vector<VideoCodec> codecs)922 virtual void SetVideoCodecs(const std::vector<VideoCodec> codecs) {
923 video_.SetCodecs(codecs);
924 }
925
GetVoiceChannel(size_t index)926 FakeVoiceMediaChannel* GetVoiceChannel(size_t index) {
927 return voice_.GetChannel(index);
928 }
929
GetVideoChannel(size_t index)930 FakeVideoMediaChannel* GetVideoChannel(size_t index) {
931 return video_.GetChannel(index);
932 }
933
audio_options()934 AudioOptions audio_options() const { return voice_.options_; }
audio_delay_offset()935 int audio_delay_offset() const { return voice_.delay_offset_; }
output_volume()936 int output_volume() const { return voice_.output_volume_; }
default_video_encoder_config()937 const VideoEncoderConfig& default_video_encoder_config() const {
938 return video_.default_encoder_config_;
939 }
audio_in_device()940 const std::string& audio_in_device() const { return voice_.in_device_; }
audio_out_device()941 const std::string& audio_out_device() const { return voice_.out_device_; }
local_renderer()942 VideoRenderer* local_renderer() { return video_.renderer_; }
voice_loglevel()943 int voice_loglevel() const { return voice_.loglevel_; }
voice_logfilter()944 const std::string& voice_logfilter() const { return voice_.logfilter_; }
video_loglevel()945 int video_loglevel() const { return video_.loglevel_; }
video_logfilter()946 const std::string& video_logfilter() const { return video_.logfilter_; }
capture()947 bool capture() const { return video_.capture_; }
options_changed()948 bool options_changed() const {
949 return voice_.options_changed_ || video_.options_changed_;
950 }
clear_options_changed()951 void clear_options_changed() {
952 video_.options_changed_ = false;
953 voice_.options_changed_ = false;
954 }
set_fail_create_channel(bool fail)955 void set_fail_create_channel(bool fail) {
956 voice_.set_fail_create_channel(fail);
957 video_.set_fail_create_channel(fail);
958 }
voice_processor_registered(MediaProcessorDirection direction)959 bool voice_processor_registered(MediaProcessorDirection direction) const {
960 if (direction == MPD_RX) {
961 return voice_.rx_processor_ != NULL;
962 } else if (direction == MPD_TX) {
963 return voice_.tx_processor_ != NULL;
964 }
965 return false;
966 }
967 };
968
969 // CompositeMediaEngine with FakeVoiceEngine to expose SetAudioCodecs to
970 // establish a media connectionwith minimum set of audio codes required
971 template <class VIDEO>
972 class CompositeMediaEngineWithFakeVoiceEngine :
973 public CompositeMediaEngine<FakeVoiceEngine, VIDEO> {
974 public:
CompositeMediaEngineWithFakeVoiceEngine()975 CompositeMediaEngineWithFakeVoiceEngine() {}
~CompositeMediaEngineWithFakeVoiceEngine()976 virtual ~CompositeMediaEngineWithFakeVoiceEngine() {}
977
SetAudioCodecs(const std::vector<AudioCodec> & codecs)978 virtual void SetAudioCodecs(const std::vector<AudioCodec>& codecs) {
979 CompositeMediaEngine<FakeVoiceEngine, VIDEO>::voice_.SetCodecs(codecs);
980 }
981 };
982
983 // Have to come afterwards due to declaration order
~FakeVoiceMediaChannel()984 inline FakeVoiceMediaChannel::~FakeVoiceMediaChannel() {
985 if (engine_) {
986 engine_->UnregisterChannel(this);
987 }
988 }
989
~FakeVideoMediaChannel()990 inline FakeVideoMediaChannel::~FakeVideoMediaChannel() {
991 if (engine_) {
992 engine_->UnregisterChannel(this);
993 }
994 }
995
996 class FakeDataEngine : public DataEngineInterface {
997 public:
FakeDataEngine()998 FakeDataEngine() : last_channel_type_(DCT_NONE) {}
999
CreateChannel(DataChannelType data_channel_type)1000 virtual DataMediaChannel* CreateChannel(DataChannelType data_channel_type) {
1001 last_channel_type_ = data_channel_type;
1002 FakeDataMediaChannel* ch = new FakeDataMediaChannel(this);
1003 channels_.push_back(ch);
1004 return ch;
1005 }
1006
GetChannel(size_t index)1007 FakeDataMediaChannel* GetChannel(size_t index) {
1008 return (channels_.size() > index) ? channels_[index] : NULL;
1009 }
1010
UnregisterChannel(DataMediaChannel * channel)1011 void UnregisterChannel(DataMediaChannel* channel) {
1012 channels_.erase(std::find(channels_.begin(), channels_.end(), channel));
1013 }
1014
SetDataCodecs(const std::vector<DataCodec> & data_codecs)1015 virtual void SetDataCodecs(const std::vector<DataCodec>& data_codecs) {
1016 data_codecs_ = data_codecs;
1017 }
1018
data_codecs()1019 virtual const std::vector<DataCodec>& data_codecs() { return data_codecs_; }
1020
last_channel_type()1021 DataChannelType last_channel_type() const { return last_channel_type_; }
1022
1023 private:
1024 std::vector<FakeDataMediaChannel*> channels_;
1025 std::vector<DataCodec> data_codecs_;
1026 DataChannelType last_channel_type_;
1027 };
1028
1029 } // namespace cricket
1030
1031 #endif // TALK_MEDIA_BASE_FAKEMEDIAENGINE_H_
1032