1 /*
2  *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
3  *
4  *  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.
9  */
10 
11 #include "media/engine/webrtc_media_engine.h"
12 
13 #include <memory>
14 #include <utility>
15 
16 #include "absl/algorithm/container.h"
17 #include "media/engine/webrtc_voice_engine.h"
18 #include "system_wrappers/include/field_trial.h"
19 
20 #ifdef HAVE_WEBRTC_VIDEO
21 #include "media/engine/webrtc_video_engine.h"
22 #else
23 #include "media/engine/null_webrtc_video_engine.h"
24 #endif
25 
26 namespace cricket {
27 
CreateMediaEngine(MediaEngineDependencies dependencies)28 std::unique_ptr<MediaEngineInterface> CreateMediaEngine(
29     MediaEngineDependencies dependencies) {
30   auto audio_engine = std::make_unique<WebRtcVoiceEngine>(
31       dependencies.task_queue_factory, std::move(dependencies.adm),
32       std::move(dependencies.audio_encoder_factory),
33       std::move(dependencies.audio_decoder_factory),
34       std::move(dependencies.audio_mixer),
35       std::move(dependencies.audio_processing));
36 #ifdef HAVE_WEBRTC_VIDEO
37   auto video_engine = std::make_unique<WebRtcVideoEngine>(
38       std::move(dependencies.video_encoder_factory),
39       std::move(dependencies.video_decoder_factory));
40 #else
41   auto video_engine = std::make_unique<NullWebRtcVideoEngine>();
42 #endif
43   return std::make_unique<CompositeMediaEngine>(std::move(audio_engine),
44                                                 std::move(video_engine));
45 }
46 
47 namespace {
48 // Remove mutually exclusive extensions with lower priority.
DiscardRedundantExtensions(std::vector<webrtc::RtpExtension> * extensions,rtc::ArrayView<const char * const> extensions_decreasing_prio)49 void DiscardRedundantExtensions(
50     std::vector<webrtc::RtpExtension>* extensions,
51     rtc::ArrayView<const char* const> extensions_decreasing_prio) {
52   RTC_DCHECK(extensions);
53   bool found = false;
54   for (const char* uri : extensions_decreasing_prio) {
55     auto it = absl::c_find_if(
56         *extensions,
57         [uri](const webrtc::RtpExtension& rhs) { return rhs.uri == uri; });
58     if (it != extensions->end()) {
59       if (found) {
60         extensions->erase(it);
61       }
62       found = true;
63     }
64   }
65 }
66 }  // namespace
67 
ValidateRtpExtensions(const std::vector<webrtc::RtpExtension> & extensions)68 bool ValidateRtpExtensions(
69     const std::vector<webrtc::RtpExtension>& extensions) {
70   bool id_used[1 + webrtc::RtpExtension::kMaxId] = {false};
71   for (const auto& extension : extensions) {
72     if (extension.id < webrtc::RtpExtension::kMinId ||
73         extension.id > webrtc::RtpExtension::kMaxId) {
74       RTC_LOG(LS_ERROR) << "Bad RTP extension ID: " << extension.ToString();
75       return false;
76     }
77     if (id_used[extension.id]) {
78       RTC_LOG(LS_ERROR) << "Duplicate RTP extension ID: "
79                         << extension.ToString();
80       return false;
81     }
82     id_used[extension.id] = true;
83   }
84   return true;
85 }
86 
FilterRtpExtensions(const std::vector<webrtc::RtpExtension> & extensions,bool (* supported)(absl::string_view),bool filter_redundant_extensions)87 std::vector<webrtc::RtpExtension> FilterRtpExtensions(
88     const std::vector<webrtc::RtpExtension>& extensions,
89     bool (*supported)(absl::string_view),
90     bool filter_redundant_extensions) {
91   RTC_DCHECK(ValidateRtpExtensions(extensions));
92   RTC_DCHECK(supported);
93   std::vector<webrtc::RtpExtension> result;
94 
95   // Ignore any extensions that we don't recognize.
96   for (const auto& extension : extensions) {
97     if (supported(extension.uri)) {
98       result.push_back(extension);
99     } else {
100       RTC_LOG(LS_WARNING) << "Unsupported RTP extension: "
101                           << extension.ToString();
102     }
103   }
104 
105   // Sort by name, ascending (prioritise encryption), so that we don't reset
106   // extensions if they were specified in a different order (also allows us
107   // to use std::unique below).
108   absl::c_sort(result, [](const webrtc::RtpExtension& rhs,
109                           const webrtc::RtpExtension& lhs) {
110     return rhs.encrypt == lhs.encrypt ? rhs.uri < lhs.uri
111                                       : rhs.encrypt > lhs.encrypt;
112   });
113 
114   // Remove unnecessary extensions (used on send side).
115   if (filter_redundant_extensions) {
116     auto it = std::unique(
117         result.begin(), result.end(),
118         [](const webrtc::RtpExtension& rhs, const webrtc::RtpExtension& lhs) {
119           return rhs.uri == lhs.uri && rhs.encrypt == lhs.encrypt;
120         });
121     result.erase(it, result.end());
122 
123     // Keep just the highest priority extension of any in the following lists.
124     if (webrtc::field_trial::IsEnabled("WebRTC-FilterAbsSendTimeExtension")) {
125       static const char* const kBweExtensionPriorities[] = {
126           webrtc::RtpExtension::kTransportSequenceNumberUri,
127           webrtc::RtpExtension::kAbsSendTimeUri,
128           webrtc::RtpExtension::kTimestampOffsetUri};
129       DiscardRedundantExtensions(&result, kBweExtensionPriorities);
130     } else {
131       static const char* const kBweExtensionPriorities[] = {
132           webrtc::RtpExtension::kAbsSendTimeUri,
133           webrtc::RtpExtension::kTimestampOffsetUri};
134       DiscardRedundantExtensions(&result, kBweExtensionPriorities);
135     }
136   }
137   return result;
138 }
139 
GetBitrateConfigForCodec(const Codec & codec)140 webrtc::BitrateConstraints GetBitrateConfigForCodec(const Codec& codec) {
141   webrtc::BitrateConstraints config;
142   int bitrate_kbps = 0;
143   if (codec.GetParam(kCodecParamMinBitrate, &bitrate_kbps) &&
144       bitrate_kbps > 0) {
145     config.min_bitrate_bps = bitrate_kbps * 1000;
146   } else {
147     config.min_bitrate_bps = 0;
148   }
149   if (codec.GetParam(kCodecParamStartBitrate, &bitrate_kbps) &&
150       bitrate_kbps > 0) {
151     config.start_bitrate_bps = bitrate_kbps * 1000;
152   } else {
153     // Do not reconfigure start bitrate unless it's specified and positive.
154     config.start_bitrate_bps = -1;
155   }
156   if (codec.GetParam(kCodecParamMaxBitrate, &bitrate_kbps) &&
157       bitrate_kbps > 0) {
158     config.max_bitrate_bps = bitrate_kbps * 1000;
159   } else {
160     config.max_bitrate_bps = -1;
161   }
162   return config;
163 }
164 }  // namespace cricket
165