| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173 |
- #include "MediaManager.h"
- #include "Instance.h"
- #include "VideoCaptureInterfaceImpl.h"
- #include "VideoCapturerInterface.h"
- #include "CodecSelectHelper.h"
- #include "AudioDeviceHelper.h"
- #include "Message.h"
- #include "platform/PlatformInterface.h"
- #include "StaticThreads.h"
- #include "api/enable_media.h"
- #include "api/environment/environment_factory.h"
- #include "api/audio_codecs/audio_decoder_factory_template.h"
- #include "api/audio_codecs/audio_encoder_factory_template.h"
- #include "api/audio_codecs/opus/audio_decoder_opus.h"
- #include "api/audio_codecs/opus/audio_encoder_opus.h"
- #include "api/task_queue/default_task_queue_factory.h"
- #include "media/engine/webrtc_media_engine.h"
- #include "system_wrappers/include/field_trial.h"
- #include "api/video/builtin_video_bitrate_allocator_factory.h"
- #include "call/call.h"
- #include "modules/rtp_rtcp/source/rtp_util.h"
- #include "api/call/audio_sink.h"
- #include "modules/audio_processing/audio_buffer.h"
- #include "modules/audio_device/include/audio_device_factory.h"
- #ifdef WEBRTC_IOS
- #include "platform/darwin/iOS/tgcalls_audio_device_module_ios.h"
- #endif
- #include "FieldTrialsConfig.h"
- namespace tgcalls {
- namespace {
- constexpr uint32_t ssrcAudioIncoming = 1;
- constexpr uint32_t ssrcAudioOutgoing = 2;
- constexpr uint32_t ssrcAudioFecIncoming = 5;
- constexpr uint32_t ssrcAudioFecOutgoing = 6;
- constexpr uint32_t ssrcVideoIncoming = 3;
- constexpr uint32_t ssrcVideoOutgoing = 4;
- constexpr uint32_t ssrcVideoFecIncoming = 7;
- constexpr uint32_t ssrcVideoFecOutgoing = 8;
- VideoCaptureInterfaceObject *GetVideoCaptureAssumingSameThread(VideoCaptureInterface *videoCapture) {
- return videoCapture
- ? static_cast<VideoCaptureInterfaceImpl*>(videoCapture)->object()->getSyncAssumingSameThread()
- : nullptr;
- }
- class AudioCaptureAnalyzer : public webrtc::CustomAudioAnalyzer {
- private:
- void Initialize(int sample_rate_hz, int num_channels) override {
- }
- // Analyzes the given capture or render signal.
- void Analyze(const webrtc::AudioBuffer* audio) override {
- _analyze(audio);
- }
- // Returns a string representation of the module state.
- std::string ToString() const override {
- return "analyzing";
- }
- std::function<void(const webrtc::AudioBuffer*)> _analyze;
- public:
- AudioCaptureAnalyzer(std::function<void(const webrtc::AudioBuffer*)> analyze) :
- _analyze(analyze) {
- }
- virtual ~AudioCaptureAnalyzer() = default;
- };
- class AudioCapturePostProcessor : public webrtc::CustomProcessing {
- public:
- AudioCapturePostProcessor(std::function<void(float)> updated, std::vector<float> *externalAudioSamples, webrtc::Mutex *externalAudioSamplesMutex) :
- _updated(updated),
- _externalAudioSamples(externalAudioSamples),
- _externalAudioSamplesMutex(externalAudioSamplesMutex) {
- }
- virtual ~AudioCapturePostProcessor() {
- }
- private:
- virtual void Initialize(int sample_rate_hz, int num_channels) override {
- }
- virtual void Process(webrtc::AudioBuffer *buffer) override {
- if (!buffer) {
- return;
- }
- if (buffer->num_channels() != 1) {
- return;
- }
- float peak = 0;
- int peakCount = 0;
- const float *samples = buffer->channels_const()[0];
- for (int i = 0; i < buffer->num_frames(); i++) {
- float sample = samples[i];
- if (sample < 0) {
- sample = -sample;
- }
- if (peak < sample) {
- peak = sample;
- }
- peakCount += 1;
- }
- _peakCount += peakCount;
- if (_peak < peak) {
- _peak = peak;
- }
- if (_peakCount >= 1200) {
- float level = _peak / 8000.0f;
- _peak = 0;
- _peakCount = 0;
- _updated(level);
- }
- _externalAudioSamplesMutex->Lock();
- if (!_externalAudioSamples->empty()) {
- float *bufferData = buffer->channels()[0];
- int takenSamples = 0;
- for (int i = 0; i < _externalAudioSamples->size() && i < buffer->num_frames(); i++) {
- float sample = (*_externalAudioSamples)[i];
- sample += bufferData[i];
- sample = std::min(sample, 32768.f);
- sample = std::max(sample, -32768.f);
- bufferData[i] = sample;
- takenSamples++;
- }
- if (takenSamples != 0) {
- _externalAudioSamples->erase(_externalAudioSamples->begin(), _externalAudioSamples->begin() + takenSamples);
- }
- }
- _externalAudioSamplesMutex->Unlock();
- }
- virtual std::string ToString() const override {
- return "CustomPostProcessing";
- }
- virtual void SetRuntimeSetting(webrtc::AudioProcessing::RuntimeSetting setting) override {
- }
- private:
- std::function<void(float)> _updated;
- int32_t _peakCount = 0;
- float _peak = 0;
- std::vector<float> *_externalAudioSamples = nullptr;
- webrtc::Mutex *_externalAudioSamplesMutex = nullptr;
- };
- } // namespace
- class VideoSinkInterfaceProxyImpl : public rtc::VideoSinkInterface<webrtc::VideoFrame> {
- public:
- VideoSinkInterfaceProxyImpl(bool rewriteRotation) :
- _rewriteRotation(rewriteRotation) {
- }
- virtual ~VideoSinkInterfaceProxyImpl() {
- }
- virtual void OnFrame(const webrtc::VideoFrame& frame) override {
- if (const auto strong = _impl.lock()) {
- if (_rewriteRotation) {
- webrtc::VideoFrame updatedFrame = frame;
- //updatedFrame.set_rotation(webrtc::VideoRotation::kVideoRotation_90);
- strong->OnFrame(updatedFrame);
- } else {
- strong->OnFrame(frame);
- }
- }
- }
- virtual void OnDiscardedFrame() override {
- if (const auto strong = _impl.lock()) {
- strong->OnDiscardedFrame();
- }
- }
- void setSink(std::weak_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> impl) {
- _impl = impl;
- }
- private:
- bool _rewriteRotation = false;
- std::weak_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> _impl;
- };
- class AudioTrackSinkInterfaceImpl: public webrtc::AudioSinkInterface {
- private:
- std::function<void(float)> _update;
- int _peakCount = 0;
- uint16_t _peak = 0;
- public:
- AudioTrackSinkInterfaceImpl(std::function<void(float)> update) :
- _update(update) {
- }
- virtual ~AudioTrackSinkInterfaceImpl() {
- }
- virtual void OnData(const Data& audio) override {
- if (audio.channels == 1) {
- int16_t *samples = (int16_t *)audio.data;
- int numberOfSamplesInFrame = (int)audio.samples_per_channel;
- for (int i = 0; i < numberOfSamplesInFrame; i++) {
- int16_t sample = samples[i];
- if (sample < 0) {
- sample = -sample;
- }
- if (_peak < sample) {
- _peak = sample;
- }
- _peakCount += 1;
- }
- if (_peakCount >= 1200) {
- float level = ((float)(_peak)) / 4000.0f;
- _peak = 0;
- _peakCount = 0;
- _update(level);
- }
- }
- }
- };
- MediaManager::MediaManager(
- rtc::Thread *thread,
- bool isOutgoing,
- ProtocolVersion protocolVersion,
- const MediaDevicesConfig &devicesConfig,
- std::shared_ptr<VideoCaptureInterface> videoCapture,
- std::function<void(Message &&)> sendSignalingMessage,
- std::function<void(Message &&)> sendTransportMessage,
- std::function<void(int)> signalBarsUpdated,
- std::function<void(float)> audioLevelUpdated,
- std::function<webrtc::scoped_refptr<webrtc::AudioDeviceModule>(webrtc::TaskQueueFactory*)> createAudioDeviceModule,
- bool enableHighBitrateVideo,
- std::vector<std::string> preferredCodecs) :
- _thread(thread),
- _eventLog(std::make_unique<webrtc::RtcEventLogNull>()),
- _sendSignalingMessage(std::move(sendSignalingMessage)),
- _sendTransportMessage(std::move(sendTransportMessage)),
- _signalBarsUpdated(std::move(signalBarsUpdated)),
- _audioLevelUpdated(std::move(audioLevelUpdated)),
- _createAudioDeviceModule(std::move(createAudioDeviceModule)),
- _protocolVersion(protocolVersion),
- _outgoingVideoState(videoCapture ? VideoState::Active : VideoState::Inactive),
- _webrtcEnvironment(webrtc::EnvironmentFactory().Create()),
- _videoCapture(std::move(videoCapture)),
- _enableHighBitrateVideo(enableHighBitrateVideo) {
- bool rewriteFrameRotation = false;
- switch (_protocolVersion) {
- case ProtocolVersion::V0:
- rewriteFrameRotation = true;
- break;
- case ProtocolVersion::V1:
- rewriteFrameRotation = false;
- break;
- default:
- break;
- }
- _incomingVideoSinkProxy.reset(new VideoSinkInterfaceProxyImpl(rewriteFrameRotation));
- _ssrcAudio.incoming = isOutgoing ? ssrcAudioIncoming : ssrcAudioOutgoing;
- _ssrcAudio.outgoing = (!isOutgoing) ? ssrcAudioIncoming : ssrcAudioOutgoing;
- _ssrcAudio.fecIncoming = isOutgoing ? ssrcAudioFecIncoming : ssrcAudioFecOutgoing;
- _ssrcAudio.fecOutgoing = (!isOutgoing) ? ssrcAudioFecIncoming : ssrcAudioFecOutgoing;
- _ssrcVideo.incoming = isOutgoing ? ssrcVideoIncoming : ssrcVideoOutgoing;
- _ssrcVideo.outgoing = (!isOutgoing) ? ssrcVideoIncoming : ssrcVideoOutgoing;
- _ssrcVideo.fecIncoming = isOutgoing ? ssrcVideoFecIncoming : ssrcVideoFecOutgoing;
- _ssrcVideo.fecOutgoing = (!isOutgoing) ? ssrcVideoFecIncoming : ssrcVideoFecOutgoing;
- _audioNetworkInterface = std::unique_ptr<MediaManager::NetworkInterfaceImpl>(new MediaManager::NetworkInterfaceImpl(this, false));
- _videoNetworkInterface = std::unique_ptr<MediaManager::NetworkInterfaceImpl>(new MediaManager::NetworkInterfaceImpl(this, true));
- webrtc::field_trial::InitFieldTrialsFromString(
- "WebRTC-Audio-SendSideBwe/Enabled/"
- "WebRTC-Audio-Allocation/min:32kbps,max:32kbps/"
- "WebRTC-Audio-OpusMinPacketLossRate/Enabled-1/"
- "WebRTC-FlexFEC-03/Enabled/"
- "WebRTC-FlexFEC-03-Advertised/Enabled/"
- "WebRTC-Turn-AllowSystemPorts/Enabled/"
- "WebRTC-Audio-iOS-Holding/Enabled/"
- );
-
- _audioRtpHeaderExtensionMap.RegisterByUri(1, webrtc::RtpExtension::kTransportSequenceNumberUri);
-
- _videoRtpHeaderExtensionMap.RegisterByUri(2, webrtc::RtpExtension::kTransportSequenceNumberUri);
- _videoRtpHeaderExtensionMap.RegisterByUri(3, webrtc::RtpExtension::kVideoRotationUri);
- _videoRtpHeaderExtensionMap.RegisterByUri(4, webrtc::RtpExtension::kTimestampOffsetUri);
- PlatformInterface::SharedInstance()->configurePlatformAudio();
- _videoBitrateAllocatorFactory = webrtc::CreateBuiltinVideoBitrateAllocatorFactory();
- webrtc::PeerConnectionFactoryDependencies peerConnectionFactoryDeps;
-
- peerConnectionFactoryDeps.signaling_thread = StaticThreads::getMediaThread();
- peerConnectionFactoryDeps.worker_thread = StaticThreads::getWorkerThread();
- peerConnectionFactoryDeps.task_queue_factory = webrtc::CreateDefaultTaskQueueFactory();
- peerConnectionFactoryDeps.network_thread = StaticThreads::getNetworkThread();
- peerConnectionFactoryDeps.network_monitor_factory = PlatformInterface::SharedInstance()->createNetworkMonitorFactory();
-
- peerConnectionFactoryDeps.audio_encoder_factory = webrtc::CreateAudioEncoderFactory<webrtc::AudioEncoderOpus>();
- peerConnectionFactoryDeps.audio_decoder_factory = webrtc::CreateAudioDecoderFactory<webrtc::AudioDecoderOpus>();
- peerConnectionFactoryDeps.video_encoder_factory = PlatformInterface::SharedInstance()->makeVideoEncoderFactory();
- peerConnectionFactoryDeps.video_decoder_factory = PlatformInterface::SharedInstance()->makeVideoDecoderFactory();
- _myVideoFormats = ComposeSupportedFormats(
- peerConnectionFactoryDeps.video_encoder_factory->GetSupportedFormats(),
- peerConnectionFactoryDeps.video_decoder_factory->GetSupportedFormats(),
- preferredCodecs);
- webrtc::AudioProcessingBuilder builder;
- std::unique_ptr<AudioCapturePostProcessor> audioProcessor = std::make_unique<AudioCapturePostProcessor>([this](float level) {
- this->_thread->PostTask([this, level](){
- auto strong = this;
- strong->_currentMyAudioLevel = level;
- });
- }, &_externalAudioSamples, &_externalAudioSamplesMutex);
- builder.SetCapturePostProcessing(std::move(audioProcessor));
- peerConnectionFactoryDeps.audio_processing = builder.Create();
- StaticThreads::getWorkerThread()->BlockingCall([&] {
- _audioDeviceModule = this->createAudioDeviceModule();
- peerConnectionFactoryDeps.adm = _audioDeviceModule;
-
- webrtc::EnableMedia(peerConnectionFactoryDeps);
- _mediaEngine = peerConnectionFactoryDeps.media_factory->CreateMediaEngine(_webrtcEnvironment, peerConnectionFactoryDeps);
- _mediaEngine->Init();
- });
- StaticThreads::getWorkerThread()->BlockingCall([&] {
- setAudioInputDevice(devicesConfig.audioInputId);
- setAudioOutputDevice(devicesConfig.audioOutputId);
- setInputVolume(devicesConfig.inputVolume);
- setOutputVolume(devicesConfig.outputVolume);
-
- webrtc::CallConfig callConfig(_webrtcEnvironment);
- callConfig.audio_state = _mediaEngine->voice().GetAudioState();
- _call = peerConnectionFactoryDeps.media_factory->CreateCall(callConfig);
- cricket::AudioOptions audioOptions;
- audioOptions.echo_cancellation = true;
- audioOptions.noise_suppression = true;
- audioOptions.audio_jitter_buffer_fast_accelerate = true;
- std::vector<std::string> streamIds;
- streamIds.push_back("1");
-
- _audioSendChannel = _mediaEngine->voice().CreateSendChannel(_call.get(), cricket::MediaConfig(), audioOptions, webrtc::CryptoOptions::NoGcm(), webrtc::AudioCodecPairId::Create());
- _audioReceiveChannel = _mediaEngine->voice().CreateReceiveChannel(_call.get(), cricket::MediaConfig(), audioOptions, webrtc::CryptoOptions::NoGcm(), webrtc::AudioCodecPairId::Create());
- _videoSendChannel = _mediaEngine->video().CreateSendChannel(_call.get(), cricket::MediaConfig(), cricket::VideoOptions(), webrtc::CryptoOptions::NoGcm(), _videoBitrateAllocatorFactory.get());
- _videoReceiveChannel = _mediaEngine->video().CreateReceiveChannel(_call.get(), cricket::MediaConfig(), cricket::VideoOptions(), webrtc::CryptoOptions::NoGcm());
- const uint32_t opusClockrate = 48000;
- const uint16_t opusSdpPayload = 111;
- const char *opusSdpName = "opus";
- const uint8_t opusSdpChannels = 2;
- const uint8_t opusMinBitrateKbps = 6;
- const uint8_t opusMaxBitrateKbps = 32;
- const uint8_t opusStartBitrateKbps = 8;
- const uint8_t opusPTimeMs = 120;
- cricket::AudioCodec opusCodec = cricket::CreateAudioCodec(opusSdpPayload, opusSdpName, opusClockrate, opusSdpChannels);
- opusCodec.AddFeedbackParam(cricket::FeedbackParam(cricket::kRtcpFbParamTransportCc));
- opusCodec.SetParam(cricket::kCodecParamMinBitrate, opusMinBitrateKbps);
- opusCodec.SetParam(cricket::kCodecParamStartBitrate, opusStartBitrateKbps);
- opusCodec.SetParam(cricket::kCodecParamMaxBitrate, opusMaxBitrateKbps);
- opusCodec.SetParam(cricket::kCodecParamUseInbandFec, 1);
- opusCodec.SetParam(cricket::kCodecParamPTime, opusPTimeMs);
- cricket::AudioSenderParameter audioSendPrameters;
- audioSendPrameters.codecs.push_back(opusCodec);
- audioSendPrameters.extensions.emplace_back(webrtc::RtpExtension::kTransportSequenceNumberUri, 1);
- #if WEBRTC_IOS
- audioSendPrameters.options.echo_cancellation = false;
- audioSendPrameters.options.auto_gain_control = false;
- #else
- audioSendPrameters.options.echo_cancellation = true;
- audioSendPrameters.options.auto_gain_control = true;
- #endif
- audioSendPrameters.options.noise_suppression = true;
- audioSendPrameters.rtcp.reduced_size = true;
- audioSendPrameters.rtcp.remote_estimate = true;
- _audioSendChannel->SetSenderParameters(audioSendPrameters);
- _audioSendChannel->AddSendStream(cricket::StreamParams::CreateLegacy(_ssrcAudio.outgoing));
- _audioSendChannel->SetInterface(_audioNetworkInterface.get());
- cricket::AudioReceiverParameters audioRecvParameters;
- audioRecvParameters.codecs.push_back(opusCodec);
- audioRecvParameters.extensions.emplace_back(webrtc::RtpExtension::kTransportSequenceNumberUri, 1);
- audioRecvParameters.rtcp.reduced_size = true;
- audioRecvParameters.rtcp.remote_estimate = true;
- _audioReceiveChannel->SetReceiverParameters(audioRecvParameters);
- cricket::StreamParams audioRecvStreamParams = cricket::StreamParams::CreateLegacy(_ssrcAudio.incoming);
- audioRecvStreamParams.set_stream_ids(streamIds);
- _audioReceiveChannel->AddRecvStream(audioRecvStreamParams);
- _audioReceiveChannel->SetPlayout(true);
- _videoSendChannel->SetInterface(_videoNetworkInterface.get());
- _videoReceiveChannel->SetInterface(_videoNetworkInterface.get());
-
- adjustBitratePreferences(true);
- });
- }
- webrtc::scoped_refptr<webrtc::AudioDeviceModule> MediaManager::createAudioDeviceModule() {
- const auto create = [&](webrtc::AudioDeviceModule::AudioLayer layer) {
- #ifdef WEBRTC_IOS
- return rtc::make_ref_counted<webrtc::tgcalls_ios_adm::AudioDeviceModuleIOS>(false, false, 1);
- #else
- return webrtc::AudioDeviceModule::Create(
- layer,
- &_webrtcEnvironment.task_queue_factory());
- #endif
- };
- const auto check = [&](const webrtc::scoped_refptr<webrtc::AudioDeviceModule> &result) {
- return (result && result->Init() == 0) ? result : nullptr;
- };
- if (_createAudioDeviceModule) {
- if (const auto result = check(_createAudioDeviceModule(&_webrtcEnvironment.task_queue_factory()))) {
- return result;
- }
- }
- return check(create(webrtc::AudioDeviceModule::kPlatformDefaultAudio));
- }
- void MediaManager::start() {
- const auto weak = std::weak_ptr<MediaManager>(shared_from_this());
- // Here we hope that thread outlives the sink
- rtc::Thread *thread = _thread;
- std::unique_ptr<AudioTrackSinkInterfaceImpl> incomingSink(new AudioTrackSinkInterfaceImpl([weak, thread](float level) {
- thread->PostTask([weak, level] {
- if (const auto strong = weak.lock()) {
- strong->_currentAudioLevel = level;
- }
- });
- }));
- StaticThreads::getWorkerThread()->BlockingCall([&] {
- _audioReceiveChannel->SetRawAudioSink(_ssrcAudio.incoming, std::move(incomingSink));
- });
- _sendSignalingMessage({ _myVideoFormats });
- if (_videoCapture != nullptr) {
- setSendVideo(_videoCapture);
- }
- beginStatsTimer(3000);
- if (_audioLevelUpdated != nullptr) {
- beginLevelsTimer(100);
- }
- }
- MediaManager::~MediaManager() {
- assert(_thread->IsCurrent());
- RTC_LOG(LS_INFO) << "MediaManager::~MediaManager()";
- StaticThreads::getWorkerThread()->BlockingCall([&] {
- _call->SignalChannelNetworkState(webrtc::MediaType::AUDIO, webrtc::kNetworkDown);
- _call->SignalChannelNetworkState(webrtc::MediaType::VIDEO, webrtc::kNetworkDown);
- _audioSendChannel->OnReadyToSend(false);
- _audioSendChannel->SetSend(false);
- _audioSendChannel->SetAudioSend(_ssrcAudio.outgoing, false, nullptr, &_audioSource);
- _audioSendChannel->RemoveSendStream(_ssrcAudio.outgoing);
- _audioReceiveChannel->SetPlayout(false);
- _audioReceiveChannel->RemoveRecvStream(_ssrcAudio.incoming);
- _audioSendChannel->SetInterface(nullptr);
- _audioReceiveChannel->SetInterface(nullptr);
- _audioSendChannel.reset();
- _audioReceiveChannel.reset();
- });
- setSendVideo(nullptr);
- if (computeIsReceivingVideo()) {
- StaticThreads::getWorkerThread()->BlockingCall([&] {
- _videoReceiveChannel->RemoveRecvStream(_ssrcVideo.incoming);
- if (_enableFlexfec) {
- _videoReceiveChannel->RemoveRecvStream(_ssrcVideo.fecIncoming);
- }
- });
- }
- if (_didConfigureVideo) {
- StaticThreads::getWorkerThread()->BlockingCall([&] {
- _videoSendChannel->OnReadyToSend(false);
- _videoSendChannel->SetSend(false);
- if (_enableFlexfec) {
- _videoSendChannel->RemoveSendStream(_ssrcVideo.outgoing);
- _videoSendChannel->RemoveSendStream(_ssrcVideo.fecOutgoing);
- } else {
- _videoSendChannel->RemoveSendStream(_ssrcVideo.outgoing);
- }
- _haveVideoSendChannel = false;
- });
- }
- StaticThreads::getWorkerThread()->BlockingCall([&] {
- _videoSendChannel->SetInterface(nullptr);
- _videoReceiveChannel->SetInterface(nullptr);
- _videoSendChannel.reset();
- _videoReceiveChannel.reset();
- _audioDeviceModule = nullptr;
- _call.reset();
- _mediaEngine.reset();
- });
- }
- void MediaManager::setIsConnected(bool isConnected) {
- if (_isConnected == isConnected) {
- return;
- }
- bool isFirstConnection = false;
- if (!_isConnected && isConnected) {
- _didConnectOnce = true;
- isFirstConnection = true;
- }
- _isConnected = isConnected;
- StaticThreads::getWorkerThread()->BlockingCall([&] {
- if (_isConnected) {
- _call->SignalChannelNetworkState(webrtc::MediaType::AUDIO, webrtc::kNetworkUp);
- _call->SignalChannelNetworkState(webrtc::MediaType::VIDEO, webrtc::kNetworkUp);
- } else {
- _call->SignalChannelNetworkState(webrtc::MediaType::AUDIO, webrtc::kNetworkDown);
- _call->SignalChannelNetworkState(webrtc::MediaType::VIDEO, webrtc::kNetworkDown);
- }
- if (_audioSendChannel) {
- _audioSendChannel->OnReadyToSend(_isConnected);
- _audioSendChannel->SetSend(_isConnected);
- _audioSendChannel->SetAudioSend(_ssrcAudio.outgoing, _isConnected && (_outgoingAudioState == AudioState::Active), nullptr, &_audioSource);
- }
- if (computeIsSendingVideo() && _videoSendChannel) {
- _videoSendChannel->OnReadyToSend(_isConnected);
- _videoSendChannel->SetSend(_isConnected);
- }
- });
- if (isFirstConnection) {
- sendVideoParametersMessage();
- sendOutgoingMediaStateMessage();
- }
- }
- void MediaManager::sendVideoParametersMessage() {
- const auto aspectRatioValue = uint32_t(_localPreferredVideoAspectRatio * 1000.0);
- _sendTransportMessage({ VideoParametersMessage{ aspectRatioValue } });
- }
- void MediaManager::sendOutgoingMediaStateMessage() {
- _sendTransportMessage({ RemoteMediaStateMessage{ _outgoingAudioState, _outgoingVideoState } });
- }
- void MediaManager::beginStatsTimer(int timeoutMs) {
- const auto weak = std::weak_ptr<MediaManager>(shared_from_this());
- _thread->PostDelayedTask([weak]() {
- auto strong = weak.lock();
- if (!strong) {
- return;
- }
- strong->collectStats();
- }, webrtc::TimeDelta::Millis(timeoutMs));
- }
- void MediaManager::beginLevelsTimer(int timeoutMs) {
- const auto weak = std::weak_ptr<MediaManager>(shared_from_this());
- _thread->PostDelayedTask([weak]() {
- auto strong = weak.lock();
- if (!strong) {
- return;
- }
- float effectiveLevel = fmaxf(strong->_currentAudioLevel, strong->_currentMyAudioLevel);
- strong->_audioLevelUpdated(effectiveLevel);
- strong->beginLevelsTimer(100);
- }, webrtc::TimeDelta::Millis(timeoutMs));
- }
- void MediaManager::collectStats() {
- webrtc::Call::Stats stats;
- StaticThreads::getWorkerThread()->BlockingCall([&] {
- stats = _call->GetStats();
- });
- float bitrateNorm = 16.0f;
- switch (_outgoingVideoState) {
- case VideoState::Active:
- bitrateNorm = 600.0f;
- break;
- default:
- break;
- }
- float sendBitrateKbps = ((float)stats.send_bandwidth_bps / 1000.0f);
- RTC_LOG(LS_INFO) << "MediaManager sendBitrateKbps=" << (stats.send_bandwidth_bps / 1000);
- float signalBarsNorm = 4.0f;
- float adjustedQuality = sendBitrateKbps / bitrateNorm;
- adjustedQuality = fmaxf(0.0f, adjustedQuality);
- adjustedQuality = fminf(1.0f, adjustedQuality);
- if (_signalBarsUpdated) {
- _signalBarsUpdated((int)(adjustedQuality * signalBarsNorm));
- }
- _bitrateRecords.push_back(CallStatsBitrateRecord { (int32_t)(rtc::TimeMillis() / 1000), stats.send_bandwidth_bps / 1000 });
- beginStatsTimer(2000);
- }
- void MediaManager::notifyPacketSent(const rtc::SentPacket &sentPacket) {
- _call->OnSentPacket(sentPacket);
- }
- void MediaManager::setPeerVideoFormats(VideoFormatsMessage &&peerFormats) {
- if (!_videoCodecs.empty()) {
- return;
- }
- bool wasReceivingVideo = computeIsReceivingVideo();
- assert(!_videoCodecOut.has_value());
- auto formats = ComputeCommonFormats(
- _myVideoFormats,
- std::move(peerFormats));
- auto codecs = AssignPayloadTypesAndDefaultCodecs(std::move(formats));
- if (codecs.myEncoderIndex >= 0) {
- assert(codecs.myEncoderIndex < codecs.list.size());
- _videoCodecOut = codecs.list[codecs.myEncoderIndex];
- }
- _videoCodecs = std::move(codecs.list);
- if (_videoCodecOut.has_value()) {
- checkIsSendingVideoChanged(false);
- }
- if (_videoCodecs.size() != 0) {
- checkIsReceivingVideoChanged(wasReceivingVideo);
- }
- }
- bool MediaManager::videoCodecsNegotiated() const {
- return !_videoCodecs.empty();
- }
- bool MediaManager::computeIsSendingVideo() const {
- return _videoCapture != nullptr && _videoCodecOut.has_value();
- }
- bool MediaManager::computeIsReceivingVideo() const {
- return _videoCodecs.size() != 0;
- }
- void MediaManager::setSendVideo(std::shared_ptr<VideoCaptureInterface> videoCapture) {
- const auto wasSending = computeIsSendingVideo();
- const auto wasReceiving = computeIsReceivingVideo();
- if (_videoCapture) {
- _videoCaptureGuard = nullptr;
- GetVideoCaptureAssumingSameThread(_videoCapture.get())->setStateUpdated(nullptr);
- }
- _videoCapture = videoCapture;
- if (_videoCapture) {
- _videoCapture->setPreferredAspectRatio(_preferredAspectRatio);
- const auto thread = _thread;
- const auto object = GetVideoCaptureAssumingSameThread(_videoCapture.get());
- _isScreenCapture = object->isScreenCapture();
- _videoCaptureGuard = std::make_shared<bool>(true);
- const auto guard = std::weak_ptr{ _videoCaptureGuard };
- object->setStateUpdated([=](VideoState state) {
- thread->PostTask([=] {
- // Checking this special guard instead of weak_ptr(this)
- // ensures that we won't call setOutgoingVideoState after
- // the _videoCapture was already changed and the old
- // stateUpdated was already null-ed, but the event
- // at that time was already posted.
- if (guard.lock()) {
- setOutgoingVideoState(state);
- }
- });
- });
- setOutgoingVideoState(VideoState::Active);
- } else {
- _isScreenCapture = false;
- setOutgoingVideoState(VideoState::Inactive);
- }
- StaticThreads::getWorkerThread()->BlockingCall([&] {
- if (_enableFlexfec) {
- _videoSendChannel->RemoveSendStream(_ssrcVideo.outgoing);
- _videoSendChannel->RemoveSendStream(_ssrcVideo.fecOutgoing);
- } else {
- _videoSendChannel->RemoveSendStream(_ssrcVideo.outgoing);
- }
- _haveVideoSendChannel = false;
- if (videoCapture) {
- if (_enableFlexfec) {
- cricket::StreamParams videoSendStreamParams;
- cricket::SsrcGroup videoSendSsrcGroup(cricket::kFecFrSsrcGroupSemantics, {_ssrcVideo.outgoing, _ssrcVideo.fecOutgoing});
- videoSendStreamParams.ssrcs = {_ssrcVideo.outgoing, _ssrcVideo.fecOutgoing};
- videoSendStreamParams.ssrc_groups.push_back(videoSendSsrcGroup);
- videoSendStreamParams.cname = "cname";
- _videoSendChannel->AddSendStream(videoSendStreamParams);
- } else {
- _videoSendChannel->AddSendStream(cricket::StreamParams::CreateLegacy(_ssrcVideo.outgoing));
- }
- _haveVideoSendChannel = true;
- }
- });
- checkIsSendingVideoChanged(wasSending);
- checkIsReceivingVideoChanged(wasReceiving);
- }
- void MediaManager::sendVideoDeviceUpdated() {
- if (!computeIsSendingVideo()) {
- return;
- }
- const auto wasScreenCapture = _isScreenCapture;
- const auto object = GetVideoCaptureAssumingSameThread(_videoCapture.get());
- _isScreenCapture = object->isScreenCapture();
- if (_isScreenCapture != wasScreenCapture) {
- StaticThreads::getWorkerThread()->BlockingCall([&] {
- adjustBitratePreferences(true);
- });
- }
- }
- void MediaManager::setRequestedVideoAspect(float aspect) {
- if (_localPreferredVideoAspectRatio != aspect) {
- _localPreferredVideoAspectRatio = aspect;
- if (_didConnectOnce) {
- sendVideoParametersMessage();
- }
- }
- }
- void MediaManager::configureSendingVideoIfNeeded() {
- if (_didConfigureVideo) {
- return;
- }
- if (!_videoCodecOut.has_value()) {
- return;
- }
- _didConfigureVideo = true;
- auto codec = *_videoCodecOut;
- codec.SetParam(cricket::kCodecParamMinBitrate, 64);
- codec.SetParam(cricket::kCodecParamStartBitrate, 400);
- codec.SetParam(cricket::kCodecParamMaxBitrate, _enableHighBitrateVideo ? 2000 : 800);
- cricket::VideoSenderParameters videoSendParameters;
- videoSendParameters.codecs.push_back(codec);
- if (_enableFlexfec) {
- for (auto &c : _videoCodecs) {
- if (c.name == cricket::kFlexfecCodecName) {
- videoSendParameters.codecs.push_back(c);
- break;
- }
- }
- }
- videoSendParameters.extensions.emplace_back(webrtc::RtpExtension::kTransportSequenceNumberUri, 2);
- switch (_protocolVersion) {
- case ProtocolVersion::V1:
- videoSendParameters.extensions.emplace_back(webrtc::RtpExtension::kVideoRotationUri, 3);
- videoSendParameters.extensions.emplace_back(
- webrtc::RtpExtension::kTimestampOffsetUri, 4);
- break;
- default:
- break;
- }
- videoSendParameters.rtcp.remote_estimate = true;
- StaticThreads::getWorkerThread()->BlockingCall([&] {
- _videoSendChannel->SetSenderParameters(videoSendParameters);
- if (_enableFlexfec) {
- cricket::StreamParams videoSendStreamParams;
- cricket::SsrcGroup videoSendSsrcGroup(cricket::kFecFrSsrcGroupSemantics, {_ssrcVideo.outgoing, _ssrcVideo.fecOutgoing});
- videoSendStreamParams.ssrcs = {_ssrcVideo.outgoing, _ssrcVideo.fecOutgoing};
- videoSendStreamParams.ssrc_groups.push_back(videoSendSsrcGroup);
- videoSendStreamParams.cname = "cname";
- _videoSendChannel->AddSendStream(videoSendStreamParams);
- } else {
- _videoSendChannel->AddSendStream(cricket::StreamParams::CreateLegacy(_ssrcVideo.outgoing));
- }
- _haveVideoSendChannel = true;
-
- adjustBitratePreferences(true);
- });
- }
- void MediaManager::checkIsSendingVideoChanged(bool wasSending) {
- const auto sending = computeIsSendingVideo();
- if (sending == wasSending) {
- return;
- } else if (sending) {
- configureSendingVideoIfNeeded();
- webrtc::scoped_refptr<webrtc::VideoTrackSourceInterface> source = GetVideoCaptureAssumingSameThread(_videoCapture.get())->source();
-
- StaticThreads::getWorkerThread()->BlockingCall([&] {
- if (_haveVideoSendChannel) {
- _videoSendChannel->SetVideoSend(_ssrcVideo.outgoing, NULL, source.get());
- }
-
- _videoSendChannel->OnReadyToSend(_isConnected);
- _videoSendChannel->SetSend(_isConnected);
- });
- } else {
- StaticThreads::getWorkerThread()->BlockingCall([&] {
- _videoSendChannel->SetVideoSend(_ssrcVideo.outgoing, NULL, nullptr);
- });
- }
- StaticThreads::getWorkerThread()->BlockingCall([&] {
- adjustBitratePreferences(true);
- });
- }
- int MediaManager::getMaxVideoBitrate() const {
- return (_enableHighBitrateVideo && _isLowCostNetwork) ? 2000000 : 800000;
- }
- int MediaManager::getMaxAudioBitrate() const {
- if (_isDataSavingActive) {
- return 16000;
- } else {
- return 32000;
- }
- }
- void MediaManager::adjustBitratePreferences(bool resetStartBitrate) {
- if (computeIsSendingVideo()) {
- webrtc::BitrateConstraints preferences;
- if (_isScreenCapture) {
- preferences.min_bitrate_bps = 700000;
- if (resetStartBitrate) {
- preferences.start_bitrate_bps = 700000;
- }
- } else {
- preferences.min_bitrate_bps = 64000;
- if (resetStartBitrate) {
- preferences.start_bitrate_bps = 400000;
- }
- }
- preferences.max_bitrate_bps = getMaxVideoBitrate();
- _call->GetTransportControllerSend()->SetSdpBitrateParameters(preferences);
- } else {
- webrtc::BitrateConstraints preferences;
- if (_didConfigureVideo) {
- // After we have configured outgoing video, RTCP stops working for outgoing audio
- // TODO: investigate
- preferences.min_bitrate_bps = 16000;
- if (resetStartBitrate) {
- preferences.start_bitrate_bps = 16000;
- }
- preferences.max_bitrate_bps = 32000;
- } else {
- preferences.min_bitrate_bps = 8000;
- if (resetStartBitrate) {
- preferences.start_bitrate_bps = 16000;
- }
- preferences.max_bitrate_bps = getMaxAudioBitrate();
- }
- _call->GetTransportControllerSend()->SetSdpBitrateParameters(preferences);
- }
- }
- void MediaManager::checkIsReceivingVideoChanged(bool wasReceiving) {
- const auto receiving = computeIsReceivingVideo();
- if (receiving == wasReceiving) {
- return;
- } else {
- cricket::VideoReceiverParameters videoRecvParameters;
- const auto codecs = {
- cricket::kFlexfecCodecName,
- cricket::kH264CodecName,
- #ifndef WEBRTC_DISABLE_H265
- cricket::kH265CodecName,
- #endif
- cricket::kVp8CodecName,
- cricket::kVp9CodecName,
- cricket::kAv1CodecName,
- };
- for (const auto &c : _videoCodecs) {
- for (const auto known : codecs) {
- if (c.name == known) {
- videoRecvParameters.codecs.push_back(c);
- break;
- }
- }
- }
- videoRecvParameters.extensions.emplace_back(webrtc::RtpExtension::kTransportSequenceNumberUri, 2);
- switch (_protocolVersion) {
- case ProtocolVersion::V1:
- videoRecvParameters.extensions.emplace_back(webrtc::RtpExtension::kVideoRotationUri, 3);
- videoRecvParameters.extensions.emplace_back(
- webrtc::RtpExtension::kTimestampOffsetUri, 4);
- break;
- default:
- break;
- }
- videoRecvParameters.rtcp.reduced_size = true;
- videoRecvParameters.rtcp.remote_estimate = true;
- cricket::StreamParams videoRecvStreamParams;
- cricket::SsrcGroup videoRecvSsrcGroup(cricket::kFecFrSsrcGroupSemantics, {_ssrcVideo.incoming, _ssrcVideo.fecIncoming});
- videoRecvStreamParams.ssrcs = {_ssrcVideo.incoming, _ssrcVideo.fecIncoming};
- videoRecvStreamParams.ssrc_groups.push_back(videoRecvSsrcGroup);
- videoRecvStreamParams.cname = "cname";
- std::vector<std::string> streamIds;
- streamIds.push_back("1");
- videoRecvStreamParams.set_stream_ids(streamIds);
- _readyToReceiveVideo = true;
- StaticThreads::getWorkerThread()->BlockingCall([&] {
- _videoReceiveChannel->SetReceiverParameters(videoRecvParameters);
- _videoReceiveChannel->AddRecvStream(videoRecvStreamParams);
- _videoReceiveChannel->SetSink(_ssrcVideo.incoming, _incomingVideoSinkProxy.get());
- _videoReceiveChannel->SetReceive(true);
- });
- }
- }
- void MediaManager::setMuteOutgoingAudio(bool mute) {
- setOutgoingAudioState(mute ? AudioState::Muted : AudioState::Active);
- StaticThreads::getWorkerThread()->BlockingCall([&] {
- _audioSendChannel->SetAudioSend(_ssrcAudio.outgoing, _isConnected && (_outgoingAudioState == AudioState::Active), nullptr, &_audioSource);
- });
- }
- void MediaManager::setOutgoingAudioState(AudioState state) {
- if (_outgoingAudioState == state) {
- return;
- }
- _outgoingAudioState = state;
- sendOutgoingMediaStateMessage();
- }
- void MediaManager::setOutgoingVideoState(VideoState state) {
- if (_outgoingVideoState == state) {
- return;
- }
- _outgoingVideoState = state;
- sendOutgoingMediaStateMessage();
- }
- void MediaManager::setIncomingVideoOutput(std::weak_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink) {
- _incomingVideoSinkProxy->setSink(sink);
- }
- void MediaManager::receiveMessage(DecryptedMessage &&message) {
- const auto data = &message.message.data;
- if (const auto formats = absl::get_if<VideoFormatsMessage>(data)) {
- setPeerVideoFormats(std::move(*formats));
- } else if (const auto audio = absl::get_if<AudioDataMessage>(data)) {
- if (webrtc::IsRtcpPacket(audio->data)) {
- RTC_LOG(LS_VERBOSE) << "Deliver audio RTCP";
- }
- StaticThreads::getWorkerThread()->BlockingCall([&] {
- if (webrtc::IsRtcpPacket(audio->data)) {
- _call->Receiver()->DeliverRtcpPacket(audio->data);
- } else {
- webrtc::RtpPacketReceived parsedPacket(&_audioRtpHeaderExtensionMap, webrtc::Timestamp::Micros(rtc::TimeUTCMicros()));
- if (!parsedPacket.Parse(audio->data)) {
- RTC_LOG(LS_ERROR)
- << "Failed to parse the incoming RTP packet before demuxing. Drop it.";
- return;
- }
-
- _call->Receiver()->DeliverRtpPacket(webrtc::MediaType::AUDIO, parsedPacket, [](const webrtc::RtpPacketReceived &) { return false; });
- }
- });
- } else if (const auto video = absl::get_if<VideoDataMessage>(data)) {
- if (_videoReceiveChannel) {
- if (_readyToReceiveVideo) {
- StaticThreads::getWorkerThread()->BlockingCall([&] {
- if (webrtc::IsRtcpPacket(video->data)) {
- _call->Receiver()->DeliverRtcpPacket(video->data);
- } else {
- webrtc::RtpPacketReceived parsedPacket(&_videoRtpHeaderExtensionMap, webrtc::Timestamp::Micros(rtc::TimeUTCMicros()));
- if (!parsedPacket.Parse(video->data)) {
- RTC_LOG(LS_ERROR)
- << "Failed to parse the incoming RTP video packet before demuxing. Drop it.";
- return;
- }
-
- _call->Receiver()->DeliverRtpPacket(webrtc::MediaType::VIDEO, parsedPacket, [](const webrtc::RtpPacketReceived &) { return false; });
- }
- });
- } else {
- // maybe we need to queue packets for some time?
- }
- }
- } else if (const auto videoParameters = absl::get_if<VideoParametersMessage>(data)) {
- float value = ((float)videoParameters->aspectRatio) / 1000.0;
- _preferredAspectRatio = value;
- if (_videoCapture) {
- _videoCapture->setPreferredAspectRatio(value);
- }
- }
- }
- void MediaManager::remoteVideoStateUpdated(VideoState videoState) {
- switch (videoState) {
- case VideoState::Active:
- case VideoState::Paused:
- configureSendingVideoIfNeeded();
- break;
- default:
- break;
- }
- }
- void MediaManager::setNetworkParameters(bool isLowCost, bool isDataSavingActive) {
- if (_isLowCostNetwork != isLowCost || _isDataSavingActive != isDataSavingActive) {
- _isLowCostNetwork = isLowCost;
- _isDataSavingActive = isDataSavingActive;
- RTC_LOG(LS_INFO) << "MediaManager isLowCostNetwork: " << (isLowCost ? 1 : 0) << ", isDataSavingActive: " << (isDataSavingActive ? 1 : 0);
-
- StaticThreads::getWorkerThread()->BlockingCall([&] {
- adjustBitratePreferences(false);
- });
- }
- }
- void MediaManager::fillCallStats(CallStats &callStats) {
- if (_videoCodecOut.has_value()) {
- callStats.outgoingCodec = _videoCodecOut->name;
- }
- callStats.bitrateRecords = _bitrateRecords;
- }
- void MediaManager::setAudioInputDevice(std::string id) {
- #if defined(WEBRTC_IOS)
- #else
- SetAudioInputDeviceById(_audioDeviceModule.get(), id);
- #endif
- }
- void MediaManager::setAudioOutputDevice(std::string id) {
- #if defined(WEBRTC_IOS)
- #else
- SetAudioOutputDeviceById(_audioDeviceModule.get(), id);
- #endif
- }
- void MediaManager::setInputVolume(float level) {
- // This is not what we want, it changes OS volume on macOS.
- // auto min = uint32_t();
- // auto max = uint32_t();
- // if (const auto result = _audioDeviceModule->MinMicrophoneVolume(&min)) {
- // RTC_LOG(LS_ERROR) << "setInputVolume(" << level << "): MinMicrophoneVolume failed: " << result << ".";
- // return;
- // } else if (const auto result = _audioDeviceModule->MaxMicrophoneVolume(&max)) {
- // RTC_LOG(LS_ERROR) << "setInputVolume(" << level << "): MaxMicrophoneVolume failed: " << result << ".";
- // return;
- // }
- // const auto volume = min + uint32_t(std::round((max - min) * std::min(std::max(level, 0.f), 1.f)));
- // if (const auto result = _audioDeviceModule->SetMicrophoneVolume(volume)) {
- // RTC_LOG(LS_ERROR) << "setInputVolume(" << level << "): SetMicrophoneVolume(" << volume << ") failed: " << result << ".";
- // } else {
- // RTC_LOG(LS_INFO) << "setInputVolume(" << level << ") volume " << volume << " success.";
- // }
- }
- void MediaManager::setOutputVolume(float level) {
- // This is not what we want, it changes OS volume on macOS.
- // auto min = uint32_t();
- // auto max = uint32_t();
- // if (const auto result = _audioDeviceModule->MinSpeakerVolume(&min)) {
- // RTC_LOG(LS_ERROR) << "setOutputVolume(" << level << "): MinSpeakerVolume failed: " << result << ".";
- // return;
- // } else if (const auto result = _audioDeviceModule->MaxSpeakerVolume(&max)) {
- // RTC_LOG(LS_ERROR) << "setOutputVolume(" << level << "): MaxSpeakerVolume failed: " << result << ".";
- // return;
- // }
- // const auto volume = min + uint32_t(std::round((max - min) * std::min(std::max(level, 0.f), 1.f)));
- // if (const auto result = _audioDeviceModule->SetSpeakerVolume(volume)) {
- // RTC_LOG(LS_ERROR) << "setOutputVolume(" << level << "): SetSpeakerVolume(" << volume << ") failed: " << result << ".";
- // } else {
- // RTC_LOG(LS_INFO) << "setOutputVolume(" << level << ") volume " << volume << " success.";
- // }
- }
- void MediaManager::addExternalAudioSamples(std::vector<uint8_t> &&samples) {
- if (samples.size() % 2 != 0) {
- return;
- }
- _externalAudioSamplesMutex.Lock();
- size_t previousSize = _externalAudioSamples.size();
- _externalAudioSamples.resize(_externalAudioSamples.size() + samples.size() / 2);
- webrtc::S16ToFloatS16((const int16_t *)samples.data(), samples.size() / 2, _externalAudioSamples.data() + previousSize);
- if (_externalAudioSamples.size() > 2 * 48000) {
- _externalAudioSamples.erase(_externalAudioSamples.begin(), _externalAudioSamples.begin() + (_externalAudioSamples.size() - 2 * 48000));
- }
- _externalAudioSamplesMutex.Unlock();
- }
- MediaManager::NetworkInterfaceImpl::NetworkInterfaceImpl(MediaManager *mediaManager, bool isVideo) :
- _mediaManager(mediaManager),
- _isVideo(isVideo) {
- }
- bool MediaManager::NetworkInterfaceImpl::SendPacket(rtc::CopyOnWriteBuffer *packet, const rtc::PacketOptions& options) {
- return sendTransportMessage(packet, options);
- }
- bool MediaManager::NetworkInterfaceImpl::SendRtcp(rtc::CopyOnWriteBuffer *packet, const rtc::PacketOptions& options) {
- return sendTransportMessage(packet, options);
- }
- bool MediaManager::NetworkInterfaceImpl::sendTransportMessage(rtc::CopyOnWriteBuffer *packet, const rtc::PacketOptions& options) {
- if (_isVideo) {
- RTC_LOG(LS_VERBOSE) << "Send video packet";
- }
- _mediaManager->_sendTransportMessage(_isVideo
- ? Message{ VideoDataMessage{ *packet } }
- : Message{ AudioDataMessage{ *packet } });
- rtc::SentPacket sentPacket(options.packet_id, rtc::TimeMillis(), options.info_signaled_after_sent);
- _mediaManager->notifyPacketSent(sentPacket);
- return true;
- }
- int MediaManager::NetworkInterfaceImpl::SetOption(cricket::MediaChannelNetworkInterface::SocketType, rtc::Socket::Option, int) {
- return -1;
- }
- } // namespace tgcalls
|