blob: 3c937f21acbc03dc407395934119f41bdbff05c0 [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:
34 WebRtcMediaEngine2(webrtc::AudioDeviceModule* adm,
ossueb1fde42017-05-02 06:46:30 -070035 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>&
36 audio_encoder_factory,
ossu29b1a8d2016-06-13 07:34:51 -070037 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>&
38 audio_decoder_factory,
39 WebRtcVideoEncoderFactory* video_encoder_factory,
gyzhou95aa9642016-12-13 14:06:26 -080040 WebRtcVideoDecoderFactory* video_decoder_factory,
41 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer)
solenbergff976312016-03-30 23:28:51 -070042#ifdef HAVE_WEBRTC_VIDEO
eladalonf1841382017-06-12 01:16:46 -070043 : CompositeMediaEngine<WebRtcVoiceEngine, WebRtcVideoEngine>(
gyzhou95aa9642016-12-13 14:06:26 -080044 adm,
ossueb1fde42017-05-02 06:46:30 -070045 audio_encoder_factory,
gyzhou95aa9642016-12-13 14:06:26 -080046 audio_decoder_factory,
47 audio_mixer){
solenbergff976312016-03-30 23:28:51 -070048#else
ossu29b1a8d2016-06-13 07:34:51 -070049 : CompositeMediaEngine<WebRtcVoiceEngine, NullWebRtcVideoEngine>(
gyzhou95aa9642016-12-13 14:06:26 -080050 adm,
ossueb1fde42017-05-02 06:46:30 -070051 audio_encoder_factory,
gyzhou95aa9642016-12-13 14:06:26 -080052 audio_decoder_factory,
53 audio_mixer) {
solenbergff976312016-03-30 23:28:51 -070054#endif
gyzhou95aa9642016-12-13 14:06:26 -080055 video_.SetExternalDecoderFactory(video_decoder_factory);
ossueb1fde42017-05-02 06:46:30 -070056 video_.SetExternalEncoderFactory(video_encoder_factory);
henrike@webrtc.org0481f152014-08-19 14:56:59 +000057 }
58};
henrike@webrtc.org0481f152014-08-19 14:56:59 +000059
60} // namespace cricket
pbos@webrtc.org9e65a3b2014-06-11 13:42:37 +000061
pbos@webrtc.org9e65a3b2014-06-11 13:42:37 +000062cricket::MediaEngineInterface* CreateWebRtcMediaEngine(
63 webrtc::AudioDeviceModule* adm,
ossueb1fde42017-05-02 06:46:30 -070064 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>&
65 audio_encoder_factory,
ossu29b1a8d2016-06-13 07:34:51 -070066 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>&
67 audio_decoder_factory,
68 cricket::WebRtcVideoEncoderFactory* video_encoder_factory,
gyzhou95aa9642016-12-13 14:06:26 -080069 cricket::WebRtcVideoDecoderFactory* video_decoder_factory,
70 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer) {
ossueb1fde42017-05-02 06:46:30 -070071 return new cricket::WebRtcMediaEngine2(
72 adm, audio_encoder_factory, audio_decoder_factory, video_encoder_factory,
73 video_decoder_factory, audio_mixer);
pbos@webrtc.org9e65a3b2014-06-11 13:42:37 +000074}
75
pbos@webrtc.org9e65a3b2014-06-11 13:42:37 +000076void DestroyWebRtcMediaEngine(cricket::MediaEngineInterface* media_engine) {
henrike@webrtc.org0481f152014-08-19 14:56:59 +000077 delete media_engine;
pbos@webrtc.org9e65a3b2014-06-11 13:42:37 +000078}
henrike@webrtc.org0481f152014-08-19 14:56:59 +000079
80namespace cricket {
81
ossu111744e2016-06-15 02:22:32 -070082// TODO(ossu): Backwards-compatible interface. Will be deprecated once the
83// audio decoder factory is fully plumbed and used throughout WebRTC.
84// See: crbug.com/webrtc/6000
85MediaEngineInterface* WebRtcMediaEngineFactory::Create(
86 webrtc::AudioDeviceModule* adm,
87 WebRtcVideoEncoderFactory* video_encoder_factory,
88 WebRtcVideoDecoderFactory* video_decoder_factory) {
gyzhou95aa9642016-12-13 14:06:26 -080089 return CreateWebRtcMediaEngine(
ossueb1fde42017-05-02 06:46:30 -070090 adm, webrtc::CreateBuiltinAudioEncoderFactory(),
91 webrtc::CreateBuiltinAudioDecoderFactory(), video_encoder_factory,
gyzhou95aa9642016-12-13 14:06:26 -080092 video_decoder_factory, nullptr);
93}
94
95MediaEngineInterface* WebRtcMediaEngineFactory::Create(
96 webrtc::AudioDeviceModule* adm,
97 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>&
98 audio_decoder_factory,
99 WebRtcVideoEncoderFactory* video_encoder_factory,
100 WebRtcVideoDecoderFactory* video_decoder_factory) {
ossueb1fde42017-05-02 06:46:30 -0700101 return CreateWebRtcMediaEngine(
102 adm, webrtc::CreateBuiltinAudioEncoderFactory(), audio_decoder_factory,
103 video_encoder_factory, video_decoder_factory, nullptr);
ossu111744e2016-06-15 02:22:32 -0700104}
105
buildbot@webrtc.org95bbd182014-08-20 07:49:30 +0000106// Used by PeerConnectionFactory to create a media engine passed into
107// ChannelManager.
henrike@webrtc.org0481f152014-08-19 14:56:59 +0000108MediaEngineInterface* WebRtcMediaEngineFactory::Create(
109 webrtc::AudioDeviceModule* adm,
ossu29b1a8d2016-06-13 07:34:51 -0700110 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>&
111 audio_decoder_factory,
112 WebRtcVideoEncoderFactory* video_encoder_factory,
gyzhou95aa9642016-12-13 14:06:26 -0800113 WebRtcVideoDecoderFactory* video_decoder_factory,
114 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer) {
ossueb1fde42017-05-02 06:46:30 -0700115 return CreateWebRtcMediaEngine(
116 adm, webrtc::CreateBuiltinAudioEncoderFactory(), audio_decoder_factory,
117 video_encoder_factory, video_decoder_factory, audio_mixer);
118}
119
120MediaEngineInterface* WebRtcMediaEngineFactory::Create(
121 webrtc::AudioDeviceModule* adm,
122 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>&
123 audio_encoder_factory,
124 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>&
125 audio_decoder_factory,
126 WebRtcVideoEncoderFactory* video_encoder_factory,
127 WebRtcVideoDecoderFactory* video_decoder_factory) {
128 return CreateWebRtcMediaEngine(adm, audio_encoder_factory,
129 audio_decoder_factory, video_encoder_factory,
130 video_decoder_factory, nullptr);
131}
132
133MediaEngineInterface* WebRtcMediaEngineFactory::Create(
134 webrtc::AudioDeviceModule* adm,
135 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>&
136 audio_encoder_factory,
137 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>&
138 audio_decoder_factory,
139 WebRtcVideoEncoderFactory* video_encoder_factory,
140 WebRtcVideoDecoderFactory* video_decoder_factory,
141 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer) {
142 return CreateWebRtcMediaEngine(adm, audio_encoder_factory,
143 audio_decoder_factory, video_encoder_factory,
144 video_decoder_factory, audio_mixer);
henrike@webrtc.org0481f152014-08-19 14:56:59 +0000145}
146
solenberg7e4e01a2015-12-02 08:05:01 -0800147namespace {
148// Remove mutually exclusive extensions with lower priority.
149void DiscardRedundantExtensions(
150 std::vector<webrtc::RtpExtension>* extensions,
151 rtc::ArrayView<const char*> extensions_decreasing_prio) {
152 RTC_DCHECK(extensions);
153 bool found = false;
isheriff6f8d6862016-05-26 11:24:55 -0700154 for (const char* uri : extensions_decreasing_prio) {
155 auto it = std::find_if(
156 extensions->begin(), extensions->end(),
157 [uri](const webrtc::RtpExtension& rhs) { return rhs.uri == uri; });
solenberg7e4e01a2015-12-02 08:05:01 -0800158 if (it != extensions->end()) {
159 if (found) {
160 extensions->erase(it);
161 }
162 found = true;
Stefan Holmerbbaf3632015-10-29 18:53:23 +0100163 }
164 }
solenberg7e4e01a2015-12-02 08:05:01 -0800165}
166} // namespace
167
isheriff6f8d6862016-05-26 11:24:55 -0700168bool ValidateRtpExtensions(
169 const std::vector<webrtc::RtpExtension>& extensions) {
solenberg7e4e01a2015-12-02 08:05:01 -0800170 bool id_used[14] = {false};
171 for (const auto& extension : extensions) {
172 if (extension.id <= 0 || extension.id >= 15) {
173 LOG(LS_ERROR) << "Bad RTP extension ID: " << extension.ToString();
174 return false;
175 }
176 if (id_used[extension.id - 1]) {
177 LOG(LS_ERROR) << "Duplicate RTP extension ID: " << extension.ToString();
178 return false;
179 }
180 id_used[extension.id - 1] = true;
181 }
182 return true;
Stefan Holmerbbaf3632015-10-29 18:53:23 +0100183}
184
solenberg7e4e01a2015-12-02 08:05:01 -0800185std::vector<webrtc::RtpExtension> FilterRtpExtensions(
isheriff6f8d6862016-05-26 11:24:55 -0700186 const std::vector<webrtc::RtpExtension>& extensions,
solenberg7e4e01a2015-12-02 08:05:01 -0800187 bool (*supported)(const std::string&),
188 bool filter_redundant_extensions) {
189 RTC_DCHECK(ValidateRtpExtensions(extensions));
190 RTC_DCHECK(supported);
191 std::vector<webrtc::RtpExtension> result;
192
193 // Ignore any extensions that we don't recognize.
194 for (const auto& extension : extensions) {
195 if (supported(extension.uri)) {
isheriff6f8d6862016-05-26 11:24:55 -0700196 result.push_back(extension);
solenberg7e4e01a2015-12-02 08:05:01 -0800197 } else {
198 LOG(LS_WARNING) << "Unsupported RTP extension: " << extension.ToString();
199 }
200 }
201
202 // Sort by name, ascending, so that we don't reset extensions if they were
203 // specified in a different order (also allows us to use std::unique below).
204 std::sort(result.begin(), result.end(),
isheriff6f8d6862016-05-26 11:24:55 -0700205 [](const webrtc::RtpExtension& rhs,
206 const webrtc::RtpExtension& lhs) { return rhs.uri < lhs.uri; });
solenberg7e4e01a2015-12-02 08:05:01 -0800207
208 // Remove unnecessary extensions (used on send side).
209 if (filter_redundant_extensions) {
isheriff6f8d6862016-05-26 11:24:55 -0700210 auto it = std::unique(
211 result.begin(), result.end(),
solenberg7e4e01a2015-12-02 08:05:01 -0800212 [](const webrtc::RtpExtension& rhs, const webrtc::RtpExtension& lhs) {
isheriff6f8d6862016-05-26 11:24:55 -0700213 return rhs.uri == lhs.uri;
solenberg7e4e01a2015-12-02 08:05:01 -0800214 });
215 result.erase(it, result.end());
216
217 // Keep just the highest priority extension of any in the following list.
218 static const char* kBweExtensionPriorities[] = {
isheriff6f8d6862016-05-26 11:24:55 -0700219 webrtc::RtpExtension::kTransportSequenceNumberUri,
220 webrtc::RtpExtension::kAbsSendTimeUri,
221 webrtc::RtpExtension::kTimestampOffsetUri};
solenberg7e4e01a2015-12-02 08:05:01 -0800222 DiscardRedundantExtensions(&result, kBweExtensionPriorities);
223 }
224
225 return result;
226}
stefan13f1a0a2016-11-30 07:22:58 -0800227
228webrtc::Call::Config::BitrateConfig GetBitrateConfigForCodec(
229 const Codec& codec) {
230 webrtc::Call::Config::BitrateConfig config;
231 int bitrate_kbps = 0;
232 if (codec.GetParam(kCodecParamMinBitrate, &bitrate_kbps) &&
233 bitrate_kbps > 0) {
234 config.min_bitrate_bps = bitrate_kbps * 1000;
235 } else {
236 config.min_bitrate_bps = 0;
237 }
238 if (codec.GetParam(kCodecParamStartBitrate, &bitrate_kbps) &&
239 bitrate_kbps > 0) {
240 config.start_bitrate_bps = bitrate_kbps * 1000;
241 } else {
242 // Do not reconfigure start bitrate unless it's specified and positive.
243 config.start_bitrate_bps = -1;
244 }
245 if (codec.GetParam(kCodecParamMaxBitrate, &bitrate_kbps) &&
246 bitrate_kbps > 0) {
247 config.max_bitrate_bps = bitrate_kbps * 1000;
248 } else {
249 config.max_bitrate_bps = -1;
250 }
251 return config;
252}
henrike@webrtc.org0481f152014-08-19 14:56:59 +0000253} // namespace cricket