/* * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef MEDIA_BASE_FAKE_MEDIA_ENGINE_H_ #define MEDIA_BASE_FAKE_MEDIA_ENGINE_H_ #include #include #include #include #include #include #include #include #include #include #include #include #include "absl/algorithm/container.h" #include "absl/base/nullability.h" #include "absl/functional/any_invocable.h" #include "absl/strings/string_view.h" #include "api/audio/audio_device.h" #include "api/audio_codecs/audio_codec_pair_id.h" #include "api/audio_codecs/audio_decoder.h" #include "api/audio_codecs/audio_decoder_factory.h" #include "api/audio_codecs/audio_encoder.h" #include "api/audio_codecs/audio_encoder_factory.h" #include "api/audio_codecs/audio_format.h" #include "api/audio_options.h" #include "api/call/audio_sink.h" #include "api/crypto/crypto_options.h" #include "api/crypto/frame_decryptor_interface.h" #include "api/crypto/frame_encryptor_interface.h" #include "api/environment/environment.h" #include "api/field_trials_view.h" #include "api/frame_transformer_interface.h" #include "api/media_types.h" #include "api/rtc_error.h" #include "api/rtp_headers.h" #include "api/rtp_parameters.h" #include "api/rtp_sender_interface.h" #include "api/scoped_refptr.h" #include "api/task_queue/task_queue_base.h" #include "api/transport/rtp/rtp_source.h" #include "api/video/recordable_encoded_frame.h" #include "api/video/video_bitrate_allocator_factory.h" #include "api/video/video_sink_interface.h" #include "api/video/video_source_interface.h" #include "call/audio_state.h" #include "media/base/audio_source.h" #include "media/base/codec.h" #include "media/base/media_channel.h" #include "media/base/media_channel_impl.h" #include "media/base/media_config.h" #include "media/base/media_engine.h" #include "media/base/rtp_utils.h" #include "media/base/stream_params.h" #include "modules/rtp_rtcp/source/rtp_packet_received.h" #include "rtc_base/async_packet_socket.h" #include "rtc_base/checks.h" #include "rtc_base/copy_on_write_buffer.h" #include "rtc_base/network/sent_packet.h" #include "rtc_base/network_route.h" #include "rtc_base/system/file_wrapper.h" #include "test/create_test_field_trials.h" namespace webrtc { class FakeMediaEngine; class FakeVideoEngine; class FakeVoiceEngine; // A common helper class that handles sending and receiving RTP/RTCP packets. template class RtpReceiveChannelHelper : public Base, public MediaChannelUtil { public: explicit RtpReceiveChannelHelper(TaskQueueBase* network_thread) : MediaChannelUtil(network_thread), playout_(false), fail_set_recv_codecs_(false), transport_overhead_per_packet_(0), num_network_route_changes_(0) {} ~RtpReceiveChannelHelper() override = default; const std::vector& recv_extensions() { return recv_extensions_; } bool playout() const { return playout_; } const std::list& rtp_packets() const { return rtp_packets_; } const std::list& rtcp_packets() const { return rtcp_packets_; } bool SendRtcp(const void* data, size_t len) { CopyOnWriteBuffer packet(reinterpret_cast(data), len, kMaxRtpPacketLen); return Base::SendRtcp(&packet, AsyncSocketPacketOptions()); } bool CheckRtp(const void* data, size_t len) { bool success = !rtp_packets_.empty(); if (success) { std::string packet = rtp_packets_.front(); rtp_packets_.pop_front(); success = (packet == std::string(static_cast(data), len)); } return success; } bool CheckRtcp(const void* data, size_t len) { bool success = !rtcp_packets_.empty(); if (success) { std::string packet = rtcp_packets_.front(); rtcp_packets_.pop_front(); success = (packet == std::string(static_cast(data), len)); } return success; } bool CheckNoRtp() { return rtp_packets_.empty(); } bool CheckNoRtcp() { return rtcp_packets_.empty(); } void set_fail_set_recv_codecs(bool fail) { fail_set_recv_codecs_ = fail; } void ResetUnsignaledRecvStream() override {} std::optional GetUnsignaledSsrc() const override { return std::nullopt; } void ChooseReceiverReportSsrc( const std::set& /* choices */) override {} virtual bool SetLocalSsrc(const StreamParams& /* sp */) { return true; } void OnDemuxerCriteriaUpdatePending() override {} void OnDemuxerCriteriaUpdateComplete() override {} bool AddRecvStream(const StreamParams& sp) override { if (absl::c_linear_search(receive_streams_, sp)) { return false; } receive_streams_.push_back(sp); rtp_receive_parameters_[sp.first_ssrc()] = CreateRtpParametersWithEncodings(sp); return true; } bool RemoveRecvStream(uint32_t ssrc) override { auto parameters_iterator = rtp_receive_parameters_.find(ssrc); if (parameters_iterator != rtp_receive_parameters_.end()) { rtp_receive_parameters_.erase(parameters_iterator); } return RemoveStreamBySsrc(&receive_streams_, ssrc); } RtpParameters GetRtpReceiverParameters(uint32_t ssrc) const override { auto parameters_iterator = rtp_receive_parameters_.find(ssrc); if (parameters_iterator != rtp_receive_parameters_.end()) { return parameters_iterator->second; } return RtpParameters(); } RtpParameters GetDefaultRtpReceiveParameters() const override { return RtpParameters(); } const std::vector& recv_streams() const { return receive_streams_; } bool HasRecvStream(uint32_t ssrc) const { return GetStreamBySsrc(receive_streams_, ssrc) != nullptr; } const MediaChannelParameters::RtcpParameters& recv_rtcp_parameters() { return recv_rtcp_parameters_; } int transport_overhead_per_packet() const { return transport_overhead_per_packet_; } NetworkRoute last_network_route() const { return last_network_route_; } int num_network_route_changes() const { return num_network_route_changes_; } void set_num_network_route_changes(int changes) { num_network_route_changes_ = changes; } void OnRtcpPacketReceived(CopyOnWriteBuffer* packet, int64_t /* packet_time_us */) { rtcp_packets_.push_back(std::string(packet->cdata(), packet->size())); } void SetFrameDecryptor(uint32_t /* ssrc */, scoped_refptr /* frame_decryptor */) override {} void SetDepacketizerToDecoderFrameTransformer( uint32_t /* ssrc */, scoped_refptr /* frame_transformer */) override {} void SetInterface(MediaChannelNetworkInterface* iface) override { network_interface_ = iface; MediaChannelUtil::SetInterface(iface); } protected: void set_playout(bool playout) { playout_ = playout; } bool SetRecvRtpHeaderExtensions(const std::vector& extensions) { recv_extensions_ = extensions; return true; } void set_recv_rtcp_parameters( const MediaChannelParameters::RtcpParameters& params) { recv_rtcp_parameters_ = params; } void OnPacketReceived(const RtpPacketReceived& packet) override { rtp_packets_.push_back( std::string(packet.Buffer().cdata(), packet.size())); } bool fail_set_recv_codecs() const { return fail_set_recv_codecs_; } private: bool playout_; std::vector recv_extensions_; std::list rtp_packets_; std::list rtcp_packets_; std::vector receive_streams_; MediaChannelParameters::RtcpParameters recv_rtcp_parameters_; std::map rtp_receive_parameters_; bool fail_set_recv_codecs_; std::string rtcp_cname_; int transport_overhead_per_packet_; NetworkRoute last_network_route_; int num_network_route_changes_; MediaChannelNetworkInterface* network_interface_ = nullptr; }; // A common helper class that handles sending and receiving RTP/RTCP packets. template class RtpSendChannelHelper : public Base, public MediaChannelUtil { public: explicit RtpSendChannelHelper(TaskQueueBase* network_thread) : MediaChannelUtil(network_thread), sending_(false), fail_set_send_codecs_(false), send_ssrc_(0), ready_to_send_(false), transport_overhead_per_packet_(0), num_network_route_changes_(0) {} ~RtpSendChannelHelper() override = default; const std::vector& send_extensions() { return send_extensions_; } bool sending() const { return sending_; } const std::list& rtp_packets() const { return rtp_packets_; } const std::list& rtcp_packets() const { return rtcp_packets_; } bool SendPacket(const void* data, size_t len, const AsyncSocketPacketOptions& options) { if (!sending_) { return false; } CopyOnWriteBuffer packet(reinterpret_cast(data), len, kMaxRtpPacketLen); return MediaChannelUtil::SendPacket(&packet, options); } bool SendRtcp(const void* data, size_t len) { CopyOnWriteBuffer packet(reinterpret_cast(data), len, kMaxRtpPacketLen); return MediaChannelUtil::SendRtcp(&packet, AsyncSocketPacketOptions()); } bool CheckRtp(const void* data, size_t len) { bool success = !rtp_packets_.empty(); if (success) { std::string packet = rtp_packets_.front(); rtp_packets_.pop_front(); success = (packet == std::string(static_cast(data), len)); } return success; } bool CheckRtcp(const void* data, size_t len) { bool success = !rtcp_packets_.empty(); if (success) { std::string packet = rtcp_packets_.front(); rtcp_packets_.pop_front(); success = (packet == std::string(static_cast(data), len)); } return success; } bool CheckNoRtp() { return rtp_packets_.empty(); } bool CheckNoRtcp() { return rtcp_packets_.empty(); } void set_fail_set_send_codecs(bool fail) { fail_set_send_codecs_ = fail; } bool AddSendStream(const StreamParams& sp) override { if (absl::c_linear_search(send_streams_, sp)) { return false; } send_streams_.push_back(sp); rtp_send_parameters_[sp.first_ssrc()] = CreateRtpParametersWithEncodings(sp); if (ssrc_list_changed_callback_) { std::set ssrcs_in_use; for (const auto& send_stream : send_streams_) { ssrcs_in_use.insert(send_stream.first_ssrc()); } ssrc_list_changed_callback_(ssrcs_in_use); } return true; } bool RemoveSendStream(uint32_t ssrc) override { auto parameters_iterator = rtp_send_parameters_.find(ssrc); if (parameters_iterator != rtp_send_parameters_.end()) { rtp_send_parameters_.erase(parameters_iterator); } return RemoveStreamBySsrc(&send_streams_, ssrc); } void SetSsrcListChangedCallback( absl::AnyInvocable&)> callback) override { ssrc_list_changed_callback_ = std::move(callback); } void SetExtmapAllowMixed(bool extmap_allow_mixed) override { return MediaChannelUtil::SetExtmapAllowMixed(extmap_allow_mixed); } bool ExtmapAllowMixed() const override { return MediaChannelUtil::ExtmapAllowMixed(); } RtpParameters GetRtpSendParameters(uint32_t ssrc) const override { auto parameters_iterator = rtp_send_parameters_.find(ssrc); if (parameters_iterator != rtp_send_parameters_.end()) { // Take header extensions from channel global, not iterated. auto parameters = parameters_iterator->second; parameters.header_extensions = send_extensions_; return parameters; } return RtpParameters(); } RTCError SetRtpSendParameters(uint32_t ssrc, const RtpParameters& parameters, SetParametersCallback callback) override { auto parameters_iterator = rtp_send_parameters_.find(ssrc); if (parameters_iterator != rtp_send_parameters_.end()) { auto result = CheckRtpParametersInvalidModificationAndValues( parameters_iterator->second, parameters, CreateTestFieldTrials()); if (!result.ok()) { return InvokeSetParametersCallback(callback, result); } bool changed = (parameters_iterator->second != parameters); parameters_iterator->second = parameters; // Invoke the callback if set. if (changed && on_rtp_send_parameters_changed_callback_) { on_rtp_send_parameters_changed_callback_(ssrc, parameters); } InvokeSetParametersCallback(callback, RTCError::OK()); return RTCError::OK(); } // Replicate the behavior of the real media channel: return false // when setting parameters for unknown SSRCs. return InvokeSetParametersCallback(callback, RTCError(RTCErrorType::INTERNAL_ERROR)); } bool IsStreamMuted(uint32_t ssrc) const { bool ret = muted_streams_.find(ssrc) != muted_streams_.end(); // If |ssrc = 0| check if the first send stream is muted. if (!ret && ssrc == 0 && !send_streams_.empty()) { return muted_streams_.find(send_streams_[0].first_ssrc()) != muted_streams_.end(); } return ret; } const std::vector& send_streams() const { return send_streams_; } bool HasSendStream(uint32_t ssrc) const { return GetStreamBySsrc(send_streams_, ssrc) != nullptr; } // TODO(perkj): This is to support legacy unit test that only check one // sending stream. uint32_t send_ssrc() const { if (send_streams_.empty()) return 0; return send_streams_[0].first_ssrc(); } const MediaChannelParameters::RtcpParameters& send_rtcp_parameters() { return send_rtcp_parameters_; } bool ready_to_send() const { return ready_to_send_; } int transport_overhead_per_packet() const { return transport_overhead_per_packet_; } NetworkRoute last_network_route() const { return last_network_route_; } int num_network_route_changes() const { return num_network_route_changes_; } void set_num_network_route_changes(int changes) { num_network_route_changes_ = changes; } void OnRtcpPacketReceived(CopyOnWriteBuffer* packet, int64_t /* packet_time_us */) { rtcp_packets_.push_back(std::string(packet->cdata(), packet->size())); } // Stuff that deals with encryptors, transformers and the like void SetOnRtpSendParametersChanged( absl::AnyInvocable, const RtpParameters&)> callback) override { RTC_DCHECK(!on_rtp_send_parameters_changed_callback_); on_rtp_send_parameters_changed_callback_ = std::move(callback); } void SetFrameEncryptor(uint32_t /* ssrc */, scoped_refptr /* frame_encryptor */) override {} void SetEncoderToPacketizerFrameTransformer( uint32_t /* ssrc */, scoped_refptr /* frame_transformer */) override {} void SetInterface(MediaChannelNetworkInterface* iface) override { network_interface_ = iface; MediaChannelUtil::SetInterface(iface); } bool HasNetworkInterface() const override { return network_interface_ != nullptr; } protected: bool MuteStream(uint32_t ssrc, bool mute) { if (!HasSendStream(ssrc) && ssrc != 0) { return false; } if (mute) { muted_streams_.insert(ssrc); } else { muted_streams_.erase(ssrc); } return true; } bool set_sending(bool send) { sending_ = send; return true; } bool SetSendRtpHeaderExtensions(const std::vector& extensions) { send_extensions_ = extensions; return true; } void set_send_rtcp_parameters( const MediaChannelParameters::RtcpParameters& params) { send_rtcp_parameters_ = params; } void OnPacketSent(const SentPacketInfo& /* sent_packet */) override {} void OnReadyToSend(bool ready) override { ready_to_send_ = ready; } void OnNetworkRouteChanged(absl::string_view /* transport_name */, const NetworkRoute& network_route) override { last_network_route_ = network_route; ++num_network_route_changes_; transport_overhead_per_packet_ = network_route.packet_overhead; } bool fail_set_send_codecs() const { return fail_set_send_codecs_; } private: // TODO(bugs.webrtc.org/12783): This flag is used from more than one thread. // As a workaround for tsan, it's currently std::atomic but that might not // be the appropriate fix. std::atomic sending_; std::vector send_extensions_; std::list rtp_packets_; std::list rtcp_packets_; std::vector send_streams_; MediaChannelParameters::RtcpParameters send_rtcp_parameters_; std::set muted_streams_; std::map rtp_send_parameters_; bool fail_set_send_codecs_; uint32_t send_ssrc_; std::string rtcp_cname_; bool ready_to_send_; int transport_overhead_per_packet_; NetworkRoute last_network_route_; int num_network_route_changes_; MediaChannelNetworkInterface* network_interface_ = nullptr; absl::AnyInvocable&)> ssrc_list_changed_callback_ = nullptr; absl::AnyInvocable, const RtpParameters&)> on_rtp_send_parameters_changed_callback_; }; class FakeVoiceMediaReceiveChannel : public RtpReceiveChannelHelper { public: struct DtmfInfo { DtmfInfo(uint32_t ssrc, int event_code, int duration); uint32_t ssrc; int event_code; int duration; }; FakeVoiceMediaReceiveChannel(const AudioOptions& options, TaskQueueBase* network_thread); ~FakeVoiceMediaReceiveChannel() override; // Test methods const std::vector& recv_codecs() const; const std::vector& dtmf_info_queue() const; const AudioOptions& options() const; int max_bps() const; bool HasSource(uint32_t ssrc) const; // Overrides VideoMediaReceiveChannelInterface* AsVideoReceiveChannel() override { return nullptr; } VoiceMediaReceiveChannelInterface* AsVoiceReceiveChannel() override { return this; } MediaType media_type() const override { return MediaType::AUDIO; } bool SetReceiverParameters(const AudioReceiverParameters& params) override; void SetPlayout(bool playout) override; bool AddRecvStream(const StreamParams& sp) override; bool RemoveRecvStream(uint32_t ssrc) override; bool SetOutputVolume(uint32_t ssrc, double volume) override; bool SetDefaultOutputVolume(double volume) override; bool GetOutputVolume(uint32_t ssrc, double* volume); bool SetBaseMinimumPlayoutDelayMs(uint32_t ssrc, int delay_ms) override; std::optional GetBaseMinimumPlayoutDelayMs(uint32_t ssrc) const override; bool GetStats(VoiceMediaReceiveInfo* info, bool get_and_clear_legacy_stats) override; void SetRawAudioSink(uint32_t ssrc, std::unique_ptr sink) override; void SetDefaultRawAudioSink( std::unique_ptr sink) override; ::webrtc::RtcpMode RtcpMode() const override { return recv_rtcp_mode_; } void SetRtcpMode(::webrtc::RtcpMode mode) override { recv_rtcp_mode_ = mode; } std::vector GetSources(uint32_t ssrc) const override; void SetReceiveNackEnabled(bool /* enabled */) override {} void SetReceiveNonSenderRttEnabled(bool /* enabled */) override {} private: class VoiceChannelAudioSink : public AudioSource::Sink { public: explicit VoiceChannelAudioSink(AudioSource* source); ~VoiceChannelAudioSink() override; void OnData(const void* audio_data, int bits_per_sample, int sample_rate, size_t number_of_channels, size_t number_of_frames, std::optional absolute_capture_timestamp_ms) override; void OnClose() override; int NumPreferredChannels() const override { return -1; } AudioSource* source() const; private: AudioSource* source_; }; bool SetRecvCodecs(const std::vector& codecs); bool SetMaxSendBandwidth(int bps); bool SetOptions(const AudioOptions& options) override; std::vector recv_codecs_; std::map output_scalings_; std::map output_delays_; std::vector dtmf_info_queue_; AudioOptions options_; std::map> local_sinks_; std::unique_ptr sink_; int max_bps_; ::webrtc::RtcpMode recv_rtcp_mode_ = RtcpMode::kCompound; }; class FakeVoiceMediaSendChannel : public RtpSendChannelHelper { public: struct DtmfInfo { DtmfInfo(uint32_t ssrc, int event_code, int duration); uint32_t ssrc; int event_code; int duration; }; FakeVoiceMediaSendChannel(const AudioOptions& options, TaskQueueBase* network_thread); ~FakeVoiceMediaSendChannel() override; const std::vector& send_codecs() const; const std::vector& dtmf_info_queue() const; const AudioOptions& options() const; int max_bps() const; bool HasSource(uint32_t ssrc) const; bool GetOutputVolume(uint32_t ssrc, double* volume); // Overrides VideoMediaSendChannelInterface* AsVideoSendChannel() override { return nullptr; } VoiceMediaSendChannelInterface* AsVoiceSendChannel() override { return this; } MediaType media_type() const override { return MediaType::AUDIO; } bool SetSenderParameters(const AudioSenderParameter& params) override; void SetSend(bool send) override; bool SetAudioSend(uint32_t ssrc, bool enable, const AudioOptions* options, AudioSource* source) override; bool CanInsertDtmf() override; bool InsertDtmf(uint32_t ssrc, int event_code, int duration) override; bool SetOptions(const AudioOptions& options) override; bool SenderNackEnabled() const override { return false; } bool SenderNonSenderRttEnabled() const override { return false; } void SetReceiveNackEnabled(bool /* enabled */) {} void SetReceiveNonSenderRttEnabled(bool /* enabled */) {} bool SendCodecHasNack() const override { return false; } std::optional GetSendCodec() const override; bool GetStats(VoiceMediaSendInfo* stats) override; private: class VoiceChannelAudioSink : public AudioSource::Sink { public: explicit VoiceChannelAudioSink(AudioSource* source); ~VoiceChannelAudioSink() override; void OnData(const void* audio_data, int bits_per_sample, int sample_rate, size_t number_of_channels, size_t number_of_frames, std::optional absolute_capture_timestamp_ms) override; void OnClose() override; int NumPreferredChannels() const override { return -1; } AudioSource* source() const; private: AudioSource* source_; }; bool SetSendCodecs(const std::vector& codecs); bool SetMaxSendBandwidth(int bps); bool SetLocalSource(uint32_t ssrc, AudioSource* source); std::vector send_codecs_; std::map output_scalings_; std::map output_delays_; std::vector dtmf_info_queue_; AudioOptions options_; std::map> local_sinks_; int max_bps_; }; // A helper function to compare the FakeVoiceMediaChannel::DtmfInfo. bool CompareDtmfInfo(const FakeVoiceMediaSendChannel::DtmfInfo& info, uint32_t ssrc, int event_code, int duration); class FakeVideoMediaReceiveChannel : public RtpReceiveChannelHelper { public: FakeVideoMediaReceiveChannel(const VideoOptions& options, TaskQueueBase* network_thread); ~FakeVideoMediaReceiveChannel() override; VideoMediaReceiveChannelInterface* AsVideoReceiveChannel() override { return this; } VoiceMediaReceiveChannelInterface* AsVoiceReceiveChannel() override { return nullptr; } MediaType media_type() const override { return MediaType::VIDEO; } const std::vector& recv_codecs() const; const std::vector& send_codecs() const; bool rendering() const; const VideoOptions& options() const; const std::map*>& sinks() const; int max_bps() const; bool SetReceiverParameters(const VideoReceiverParameters& params) override; bool SetSink(uint32_t ssrc, VideoSinkInterface* sink) override; void SetDefaultSink(VideoSinkInterface* sink) override; bool HasSink(uint32_t ssrc) const; void SetReceive(bool /* receive */) override {} bool HasSource(uint32_t ssrc) const; bool AddRecvStream(const StreamParams& sp) override; bool RemoveRecvStream(uint32_t ssrc) override; std::vector GetSources(uint32_t ssrc) const override; bool SetBaseMinimumPlayoutDelayMs(uint32_t ssrc, int delay_ms) override; std::optional GetBaseMinimumPlayoutDelayMs(uint32_t ssrc) const override; void SetRecordableEncodedFrameCallback( uint32_t ssrc, std::function callback) override; void ClearRecordableEncodedFrameCallback(uint32_t ssrc) override; void RequestRecvKeyFrame(uint32_t ssrc) override; bool GetStats(VideoMediaReceiveInfo* info) override; bool AddDefaultRecvStreamForTesting(const StreamParams& /* sp */) override { RTC_CHECK_NOTREACHED(); return false; } private: bool SetRecvCodecs(const std::vector& codecs); bool SetSendCodecs(const std::vector& codecs); bool SetOptions(const VideoOptions& options); bool SetMaxSendBandwidth(int bps); std::vector recv_codecs_; std::map*> sinks_; std::map*> sources_; std::map output_delays_; VideoOptions options_; int max_bps_; }; class FakeVideoMediaSendChannel : public RtpSendChannelHelper { public: FakeVideoMediaSendChannel(const VideoOptions& options, TaskQueueBase* network_thread); ~FakeVideoMediaSendChannel() override; VideoMediaSendChannelInterface* AsVideoSendChannel() override { return this; } VoiceMediaSendChannelInterface* AsVoiceSendChannel() override { return nullptr; } MediaType media_type() const override { return MediaType::VIDEO; } const std::vector& send_codecs() const; const std::vector& codecs() const; const VideoOptions& options() const; const std::map*>& sinks() const; int max_bps() const; bool SetSenderParameters(const VideoSenderParameters& params) override; std::optional GetSendCodec() const override; bool SetSend(bool send) override; bool SetVideoSend(uint32_t ssrc, const VideoOptions* options, VideoSourceInterface* source) override; bool HasSource(uint32_t ssrc) const; void FillBitrateInfo(BandwidthEstimationInfo* bwe_info) override; void GenerateSendKeyFrame(uint32_t ssrc, const std::vector& rids) override; RtcpMode SendCodecRtcpMode() const override { return RtcpMode::kCompound; } void SetSsrcListChangedCallback( absl::AnyInvocable&)> /* callback */) override {} bool SendCodecHasLntf() const override { return false; } bool SendCodecHasNack() const override { return false; } std::optional SendCodecRtxTime() const override { return std::nullopt; } bool GetStats(VideoMediaSendInfo* info) override; bool SetOptions(const VideoOptions& options) override; private: bool SetSendCodecs(const std::vector& codecs); bool SetMaxSendBandwidth(int bps); std::vector send_codecs_; std::map*> sources_; VideoOptions options_; int max_bps_; }; class FakeVoiceEngine : public VoiceEngineInterface { public: FakeVoiceEngine(); void Init() override; void Terminate() override; scoped_refptr GetAudioState() const override; std::unique_ptr CreateSendChannel( const Environment& env, Call* call, const MediaConfig& config, const AudioOptions& options, const CryptoOptions& crypto_options) override; std::unique_ptr CreateReceiveChannel( const Environment& env, Call* call, const MediaConfig& config, const AudioOptions& options, const CryptoOptions& crypto_options) override; // TODO(ossu): For proper testing, These should either individually settable // or the voice engine should reference mockable factories. // TODO: https://issues.webrtc.org/360058654 - stop faking codecs here. const std::vector& LegacySendCodecs() const override; const std::vector& LegacyRecvCodecs() const override; AudioEncoderFactory* encoder_factory() const override { return encoder_factory_.get(); } AudioDecoderFactory* decoder_factory() const override { return decoder_factory_.get(); } void SetCodecs(const std::vector& codecs); void SetRecvCodecs(const std::vector& codecs); void SetSendCodecs(const std::vector& codecs); int GetInputLevel(); bool StartAecDump(FileWrapper file, int64_t max_size_bytes) override; void StopAecDump() override; std::optional GetAudioDeviceStats() override; std::vector GetRtpHeaderExtensions( const FieldTrialsView* field_trials) const override; void SetRtpHeaderExtensions( std::vector header_extensions); private: class FakeVoiceEncoderFactory : public AudioEncoderFactory { public: explicit FakeVoiceEncoderFactory(FakeVoiceEngine* owner) : owner_(owner) {} std::vector GetSupportedEncoders() override { // The reason for this convoluted mapping is because there are // too many tests that expect to push codecs into the fake voice // engine's "send_codecs/recv_codecs" and have them show up later. std::vector specs; for (const auto& codec : owner_->send_codecs_) { specs.push_back(AudioCodecSpec{ .format = {codec.name, codec.clockrate, codec.channels}, .info = {codec.clockrate, codec.channels, codec.bitrate}}); } return specs; } std::optional QueryAudioEncoder( const SdpAudioFormat& format) override { return std::nullopt; } absl_nullable std::unique_ptr Create( const Environment& env, const SdpAudioFormat& format, Options options) override { return nullptr; } FakeVoiceEngine* owner_; }; class FakeVoiceDecoderFactory : public AudioDecoderFactory { public: explicit FakeVoiceDecoderFactory(FakeVoiceEngine* owner) : owner_(owner) {} std::vector GetSupportedDecoders() override { // The reason for this convoluted mapping is because there are // too many tests that expect to push codecs into the fake voice // engine's "send_codecs/recv_codecs" and have them show up later. std::vector specs; for (const auto& codec : owner_->recv_codecs_) { specs.push_back(AudioCodecSpec{ .format = {codec.name, codec.clockrate, codec.channels}, .info = {codec.clockrate, codec.channels, codec.bitrate}}); } return specs; } bool IsSupportedDecoder(const SdpAudioFormat& format) override { return false; } absl_nullable std::unique_ptr Create( const Environment& env, const SdpAudioFormat& format, std::optional codec_pair_id) override { return nullptr; } private: FakeVoiceEngine* owner_; }; std::vector recv_codecs_; std::vector send_codecs_; scoped_refptr encoder_factory_; scoped_refptr decoder_factory_; std::vector header_extensions_; friend class FakeMediaEngine; }; class FakeVideoEngine : public VideoEngineInterface { public: FakeVideoEngine(); bool SetOptions(const VideoOptions& options); std::unique_ptr CreateSendChannel( const Environment& env, Call* call, const MediaConfig& config, const VideoOptions& options, const CryptoOptions& crypto_options, VideoBitrateAllocatorFactory* video_bitrate_allocator_factory) override; std::unique_ptr CreateReceiveChannel( const Environment& env, Call* call, const MediaConfig& config, const VideoOptions& options, const CryptoOptions& crypto_options) override; FakeVideoMediaSendChannel* GetSendChannel(size_t index); FakeVideoMediaReceiveChannel* GetReceiveChannel(size_t index); std::vector LegacySendCodecs() const override { return LegacySendCodecs(true); } std::vector LegacyRecvCodecs() const override { return LegacyRecvCodecs(true); } std::vector LegacySendCodecs(bool include_rtx) const override; std::vector LegacyRecvCodecs(bool include_rtx) const override; void SetSendCodecs(const std::vector& codecs); void SetRecvCodecs(const std::vector& codecs); bool SetCapture(bool capture); std::vector GetRtpHeaderExtensions( const FieldTrialsView* field_trials) const override; void SetRtpHeaderExtensions( std::vector header_extensions); private: std::vector send_codecs_; std::vector recv_codecs_; bool capture_; VideoOptions options_; std::vector header_extensions_; friend class FakeMediaEngine; }; class FakeMediaEngine : public CompositeMediaEngine { public: FakeMediaEngine(); ~FakeMediaEngine() override; void SetAudioCodecs(const std::vector& codecs); void SetAudioRecvCodecs(const std::vector& codecs); void SetAudioSendCodecs(const std::vector& codecs); void SetVideoCodecs(const std::vector& codecs); void SetVideoRecvCodecs(const std::vector& codecs); void SetVideoSendCodecs(const std::vector& codecs); FakeVoiceEngine* fake_voice_engine() { return voice_; } FakeVideoEngine* fake_video_engine() { return video_; } private: FakeVoiceEngine* const voice_; FakeVideoEngine* const video_; }; } // namespace webrtc #endif // MEDIA_BASE_FAKE_MEDIA_ENGINE_H_