blob: 774b6b7f905948697e4d8750896427d127ea5758 [file] [log] [blame]
pbos@webrtc.org289a35c2014-06-03 14:51:34 +00001/*
kjellander1afca732016-02-07 20:46:45 -08002 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
pbos@webrtc.org289a35c2014-06-03 14:51:34 +00003 *
kjellander1afca732016-02-07 20:46:45 -08004 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
pbos@webrtc.org289a35c2014-06-03 14:51:34 +00009 */
10
kjellander@webrtc.org5ad12972016-02-12 06:39:40 +010011#include "webrtc/media/engine/webrtcmediaengine.h"
solenberg7e4e01a2015-12-02 08:05:01 -080012
13#include <algorithm>
14
kwiberg087bd342017-02-10 08:15:44 -080015#include "webrtc/api/audio_codecs/builtin_audio_decoder_factory.h"
ossueb1fde42017-05-02 06:46:30 -070016#include "webrtc/api/audio_codecs/builtin_audio_encoder_factory.h"
kwiberg087bd342017-02-10 08:15:44 -080017#include "webrtc/media/engine/webrtcvoiceengine.h"
18
jbauch4cb3e392016-01-26 13:07:54 -080019#ifdef HAVE_WEBRTC_VIDEO
eladalonf1841382017-06-12 01:16:46 -070020#include "webrtc/media/engine/webrtcvideoengine.h"
jbauch4cb3e392016-01-26 13:07:54 -080021#else
kjellander@webrtc.org5ad12972016-02-12 06:39:40 +010022#include "webrtc/media/engine/nullwebrtcvideoengine.h"
jbauch4cb3e392016-01-26 13:07:54 -080023#endif
henrike@webrtc.org0481f152014-08-19 14:56:59 +000024
25namespace cricket {
26
pbos@webrtc.orge77c9c82015-03-11 10:49:33 +000027class WebRtcMediaEngine2
jbauch4cb3e392016-01-26 13:07:54 -080028#ifdef HAVE_WEBRTC_VIDEO
eladalonf1841382017-06-12 01:16:46 -070029 : public CompositeMediaEngine<WebRtcVoiceEngine, WebRtcVideoEngine> {
jbauch4cb3e392016-01-26 13:07:54 -080030#else
31 : public CompositeMediaEngine<WebRtcVoiceEngine, NullWebRtcVideoEngine> {
32#endif
henrike@webrtc.org0481f152014-08-19 14:56:59 +000033 public:
peaha9cc40b2017-06-29 08:32:09 -070034 WebRtcMediaEngine2(
35 webrtc::AudioDeviceModule* adm,
36 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>&
37 audio_encoder_factory,
38 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>&
39 audio_decoder_factory,
40 WebRtcVideoEncoderFactory* video_encoder_factory,
41 WebRtcVideoDecoderFactory* video_decoder_factory,
42 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer,
43 rtc::scoped_refptr<webrtc::AudioProcessing> audio_processing)
solenbergff976312016-03-30 23:28:51 -070044#ifdef HAVE_WEBRTC_VIDEO
eladalonf1841382017-06-12 01:16:46 -070045 : CompositeMediaEngine<WebRtcVoiceEngine, WebRtcVideoEngine>(
gyzhou95aa9642016-12-13 14:06:26 -080046 adm,
ossueb1fde42017-05-02 06:46:30 -070047 audio_encoder_factory,
gyzhou95aa9642016-12-13 14:06:26 -080048 audio_decoder_factory,
peaha9cc40b2017-06-29 08:32:09 -070049 audio_mixer,
50 audio_processing){
solenbergff976312016-03-30 23:28:51 -070051#else
ossu29b1a8d2016-06-13 07:34:51 -070052 : CompositeMediaEngine<WebRtcVoiceEngine, NullWebRtcVideoEngine>(
gyzhou95aa9642016-12-13 14:06:26 -080053 adm,
ossueb1fde42017-05-02 06:46:30 -070054 audio_encoder_factory,
gyzhou95aa9642016-12-13 14:06:26 -080055 audio_decoder_factory,
peaha9cc40b2017-06-29 08:32:09 -070056 audio_mixer,
57 audio_processing) {
solenbergff976312016-03-30 23:28:51 -070058#endif
gyzhou95aa9642016-12-13 14:06:26 -080059 video_.SetExternalDecoderFactory(video_decoder_factory);
ossueb1fde42017-05-02 06:46:30 -070060 video_.SetExternalEncoderFactory(video_encoder_factory);
henrike@webrtc.org0481f152014-08-19 14:56:59 +000061 }
62};
henrike@webrtc.org0481f152014-08-19 14:56:59 +000063
64} // namespace cricket
pbos@webrtc.org9e65a3b2014-06-11 13:42:37 +000065
pbos@webrtc.org9e65a3b2014-06-11 13:42:37 +000066cricket::MediaEngineInterface* CreateWebRtcMediaEngine(
67 webrtc::AudioDeviceModule* adm,
ossueb1fde42017-05-02 06:46:30 -070068 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>&
69 audio_encoder_factory,
ossu29b1a8d2016-06-13 07:34:51 -070070 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>&
71 audio_decoder_factory,
72 cricket::WebRtcVideoEncoderFactory* video_encoder_factory,
gyzhou95aa9642016-12-13 14:06:26 -080073 cricket::WebRtcVideoDecoderFactory* video_decoder_factory,
peaha9cc40b2017-06-29 08:32:09 -070074 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer,
75 rtc::scoped_refptr<webrtc::AudioProcessing> audio_processing) {
ossueb1fde42017-05-02 06:46:30 -070076 return new cricket::WebRtcMediaEngine2(
77 adm, audio_encoder_factory, audio_decoder_factory, video_encoder_factory,
peaha9cc40b2017-06-29 08:32:09 -070078 video_decoder_factory, audio_mixer, audio_processing);
pbos@webrtc.org9e65a3b2014-06-11 13:42:37 +000079}
80
pbos@webrtc.org9e65a3b2014-06-11 13:42:37 +000081void DestroyWebRtcMediaEngine(cricket::MediaEngineInterface* media_engine) {
henrike@webrtc.org0481f152014-08-19 14:56:59 +000082 delete media_engine;
pbos@webrtc.org9e65a3b2014-06-11 13:42:37 +000083}
henrike@webrtc.org0481f152014-08-19 14:56:59 +000084
85namespace cricket {
86
ossu111744e2016-06-15 02:22:32 -070087// TODO(ossu): Backwards-compatible interface. Will be deprecated once the
88// audio decoder factory is fully plumbed and used throughout WebRTC.
89// See: crbug.com/webrtc/6000
90MediaEngineInterface* WebRtcMediaEngineFactory::Create(
91 webrtc::AudioDeviceModule* adm,
92 WebRtcVideoEncoderFactory* video_encoder_factory,
93 WebRtcVideoDecoderFactory* video_decoder_factory) {
gyzhou95aa9642016-12-13 14:06:26 -080094 return CreateWebRtcMediaEngine(
ossueb1fde42017-05-02 06:46:30 -070095 adm, webrtc::CreateBuiltinAudioEncoderFactory(),
96 webrtc::CreateBuiltinAudioDecoderFactory(), video_encoder_factory,
peaha9cc40b2017-06-29 08:32:09 -070097 video_decoder_factory, nullptr, webrtc::AudioProcessing::Create());
gyzhou95aa9642016-12-13 14:06:26 -080098}
99
100MediaEngineInterface* WebRtcMediaEngineFactory::Create(
101 webrtc::AudioDeviceModule* adm,
102 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>&
103 audio_decoder_factory,
104 WebRtcVideoEncoderFactory* video_encoder_factory,
105 WebRtcVideoDecoderFactory* video_decoder_factory) {
ossueb1fde42017-05-02 06:46:30 -0700106 return CreateWebRtcMediaEngine(
107 adm, webrtc::CreateBuiltinAudioEncoderFactory(), audio_decoder_factory,
peaha9cc40b2017-06-29 08:32:09 -0700108 video_encoder_factory, video_decoder_factory, nullptr,
109 webrtc::AudioProcessing::Create());
ossu111744e2016-06-15 02:22:32 -0700110}
111
buildbot@webrtc.org95bbd182014-08-20 07:49:30 +0000112// Used by PeerConnectionFactory to create a media engine passed into
113// ChannelManager.
henrike@webrtc.org0481f152014-08-19 14:56:59 +0000114MediaEngineInterface* WebRtcMediaEngineFactory::Create(
115 webrtc::AudioDeviceModule* adm,
ossu29b1a8d2016-06-13 07:34:51 -0700116 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>&
117 audio_decoder_factory,
118 WebRtcVideoEncoderFactory* video_encoder_factory,
gyzhou95aa9642016-12-13 14:06:26 -0800119 WebRtcVideoDecoderFactory* video_decoder_factory,
peaha9cc40b2017-06-29 08:32:09 -0700120 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer,
121 rtc::scoped_refptr<webrtc::AudioProcessing> audio_processing) {
ossueb1fde42017-05-02 06:46:30 -0700122 return CreateWebRtcMediaEngine(
123 adm, webrtc::CreateBuiltinAudioEncoderFactory(), audio_decoder_factory,
peaha9cc40b2017-06-29 08:32:09 -0700124 video_encoder_factory, video_decoder_factory, audio_mixer,
125 audio_processing);
ossueb1fde42017-05-02 06:46:30 -0700126}
127
128MediaEngineInterface* WebRtcMediaEngineFactory::Create(
129 webrtc::AudioDeviceModule* adm,
130 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>&
131 audio_encoder_factory,
132 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>&
133 audio_decoder_factory,
134 WebRtcVideoEncoderFactory* video_encoder_factory,
135 WebRtcVideoDecoderFactory* video_decoder_factory) {
peaha9cc40b2017-06-29 08:32:09 -0700136 return CreateWebRtcMediaEngine(
137 adm, audio_encoder_factory, audio_decoder_factory, video_encoder_factory,
138 video_decoder_factory, nullptr, webrtc::AudioProcessing::Create());
ossueb1fde42017-05-02 06:46:30 -0700139}
140
141MediaEngineInterface* WebRtcMediaEngineFactory::Create(
142 webrtc::AudioDeviceModule* adm,
143 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>&
144 audio_encoder_factory,
145 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>&
146 audio_decoder_factory,
147 WebRtcVideoEncoderFactory* video_encoder_factory,
148 WebRtcVideoDecoderFactory* video_decoder_factory,
peaha9cc40b2017-06-29 08:32:09 -0700149 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer,
150 rtc::scoped_refptr<webrtc::AudioProcessing> audio_processing) {
151 return CreateWebRtcMediaEngine(
152 adm, audio_encoder_factory, audio_decoder_factory, video_encoder_factory,
153 video_decoder_factory, audio_mixer, audio_processing);
henrike@webrtc.org0481f152014-08-19 14:56:59 +0000154}
155
solenberg7e4e01a2015-12-02 08:05:01 -0800156namespace {
157// Remove mutually exclusive extensions with lower priority.
158void DiscardRedundantExtensions(
159 std::vector<webrtc::RtpExtension>* extensions,
agrieve26622d32017-08-08 10:48:15 -0700160 rtc::ArrayView<const char* const> extensions_decreasing_prio) {
solenberg7e4e01a2015-12-02 08:05:01 -0800161 RTC_DCHECK(extensions);
162 bool found = false;
isheriff6f8d6862016-05-26 11:24:55 -0700163 for (const char* uri : extensions_decreasing_prio) {
164 auto it = std::find_if(
165 extensions->begin(), extensions->end(),
166 [uri](const webrtc::RtpExtension& rhs) { return rhs.uri == uri; });
solenberg7e4e01a2015-12-02 08:05:01 -0800167 if (it != extensions->end()) {
168 if (found) {
169 extensions->erase(it);
170 }
171 found = true;
Stefan Holmerbbaf3632015-10-29 18:53:23 +0100172 }
173 }
solenberg7e4e01a2015-12-02 08:05:01 -0800174}
175} // namespace
176
isheriff6f8d6862016-05-26 11:24:55 -0700177bool ValidateRtpExtensions(
178 const std::vector<webrtc::RtpExtension>& extensions) {
solenberg7e4e01a2015-12-02 08:05:01 -0800179 bool id_used[14] = {false};
180 for (const auto& extension : extensions) {
181 if (extension.id <= 0 || extension.id >= 15) {
182 LOG(LS_ERROR) << "Bad RTP extension ID: " << extension.ToString();
183 return false;
184 }
185 if (id_used[extension.id - 1]) {
186 LOG(LS_ERROR) << "Duplicate RTP extension ID: " << extension.ToString();
187 return false;
188 }
189 id_used[extension.id - 1] = true;
190 }
191 return true;
Stefan Holmerbbaf3632015-10-29 18:53:23 +0100192}
193
solenberg7e4e01a2015-12-02 08:05:01 -0800194std::vector<webrtc::RtpExtension> FilterRtpExtensions(
isheriff6f8d6862016-05-26 11:24:55 -0700195 const std::vector<webrtc::RtpExtension>& extensions,
solenberg7e4e01a2015-12-02 08:05:01 -0800196 bool (*supported)(const std::string&),
197 bool filter_redundant_extensions) {
198 RTC_DCHECK(ValidateRtpExtensions(extensions));
199 RTC_DCHECK(supported);
200 std::vector<webrtc::RtpExtension> result;
201
202 // Ignore any extensions that we don't recognize.
203 for (const auto& extension : extensions) {
204 if (supported(extension.uri)) {
isheriff6f8d6862016-05-26 11:24:55 -0700205 result.push_back(extension);
solenberg7e4e01a2015-12-02 08:05:01 -0800206 } else {
207 LOG(LS_WARNING) << "Unsupported RTP extension: " << extension.ToString();
208 }
209 }
210
jbauch5869f502017-06-29 12:31:36 -0700211 // Sort by name, ascending (prioritise encryption), so that we don't reset
212 // extensions if they were specified in a different order (also allows us
213 // to use std::unique below).
solenberg7e4e01a2015-12-02 08:05:01 -0800214 std::sort(result.begin(), result.end(),
isheriff6f8d6862016-05-26 11:24:55 -0700215 [](const webrtc::RtpExtension& rhs,
jbauch5869f502017-06-29 12:31:36 -0700216 const webrtc::RtpExtension& lhs) {
217 return rhs.encrypt == lhs.encrypt ? rhs.uri < lhs.uri
218 : rhs.encrypt > lhs.encrypt;
219 });
solenberg7e4e01a2015-12-02 08:05:01 -0800220
221 // Remove unnecessary extensions (used on send side).
222 if (filter_redundant_extensions) {
isheriff6f8d6862016-05-26 11:24:55 -0700223 auto it = std::unique(
224 result.begin(), result.end(),
solenberg7e4e01a2015-12-02 08:05:01 -0800225 [](const webrtc::RtpExtension& rhs, const webrtc::RtpExtension& lhs) {
jbauch5869f502017-06-29 12:31:36 -0700226 return rhs.uri == lhs.uri && rhs.encrypt == lhs.encrypt;
solenberg7e4e01a2015-12-02 08:05:01 -0800227 });
228 result.erase(it, result.end());
229
230 // Keep just the highest priority extension of any in the following list.
agrieve26622d32017-08-08 10:48:15 -0700231 static const char* const kBweExtensionPriorities[] = {
isheriff6f8d6862016-05-26 11:24:55 -0700232 webrtc::RtpExtension::kTransportSequenceNumberUri,
233 webrtc::RtpExtension::kAbsSendTimeUri,
234 webrtc::RtpExtension::kTimestampOffsetUri};
solenberg7e4e01a2015-12-02 08:05:01 -0800235 DiscardRedundantExtensions(&result, kBweExtensionPriorities);
236 }
237
238 return result;
239}
stefan13f1a0a2016-11-30 07:22:58 -0800240
241webrtc::Call::Config::BitrateConfig GetBitrateConfigForCodec(
242 const Codec& codec) {
243 webrtc::Call::Config::BitrateConfig config;
244 int bitrate_kbps = 0;
245 if (codec.GetParam(kCodecParamMinBitrate, &bitrate_kbps) &&
246 bitrate_kbps > 0) {
247 config.min_bitrate_bps = bitrate_kbps * 1000;
248 } else {
249 config.min_bitrate_bps = 0;
250 }
251 if (codec.GetParam(kCodecParamStartBitrate, &bitrate_kbps) &&
252 bitrate_kbps > 0) {
253 config.start_bitrate_bps = bitrate_kbps * 1000;
254 } else {
255 // Do not reconfigure start bitrate unless it's specified and positive.
256 config.start_bitrate_bps = -1;
257 }
258 if (codec.GetParam(kCodecParamMaxBitrate, &bitrate_kbps) &&
259 bitrate_kbps > 0) {
260 config.max_bitrate_bps = bitrate_kbps * 1000;
261 } else {
262 config.max_bitrate_bps = -1;
263 }
264 return config;
265}
henrike@webrtc.org0481f152014-08-19 14:56:59 +0000266} // namespace cricket