1 /* 2 * libjingle 3 * Copyright 2014 Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "talk/media/webrtc/webrtcmediaengine.h" 29 30 #include <algorithm> 31 32 #include "talk/media/webrtc/webrtcvideoengine2.h" 33 #include "talk/media/webrtc/webrtcvoiceengine.h" 34 35 namespace cricket { 36 37 class WebRtcMediaEngine2 38 : public CompositeMediaEngine<WebRtcVoiceEngine, WebRtcVideoEngine2> { 39 public: 40 WebRtcMediaEngine2(webrtc::AudioDeviceModule* adm, 41 WebRtcVideoEncoderFactory* encoder_factory, 42 WebRtcVideoDecoderFactory* decoder_factory) { 43 voice_.SetAudioDeviceModule(adm); 44 video_.SetExternalDecoderFactory(decoder_factory); 45 video_.SetExternalEncoderFactory(encoder_factory); 46 } 47 }; 48 49 } // namespace cricket 50 51 cricket::MediaEngineInterface* CreateWebRtcMediaEngine( 52 webrtc::AudioDeviceModule* adm, 53 cricket::WebRtcVideoEncoderFactory* encoder_factory, 54 cricket::WebRtcVideoDecoderFactory* decoder_factory) { 55 return new cricket::WebRtcMediaEngine2(adm, encoder_factory, 56 decoder_factory); 57 } 58 59 void DestroyWebRtcMediaEngine(cricket::MediaEngineInterface* media_engine) { 60 delete media_engine; 61 } 62 63 namespace cricket { 64 65 // Used by PeerConnectionFactory to create a media engine passed into 66 // ChannelManager. 67 MediaEngineInterface* WebRtcMediaEngineFactory::Create( 68 webrtc::AudioDeviceModule* adm, 69 WebRtcVideoEncoderFactory* encoder_factory, 70 WebRtcVideoDecoderFactory* decoder_factory) { 71 return CreateWebRtcMediaEngine(adm, encoder_factory, decoder_factory); 72 } 73 74 namespace { 75 // Remove mutually exclusive extensions with lower priority. 76 void DiscardRedundantExtensions( 77 std::vector<webrtc::RtpExtension>* extensions, 78 rtc::ArrayView<const char*> extensions_decreasing_prio) { 79 RTC_DCHECK(extensions); 80 bool found = false; 81 for (const char* name : extensions_decreasing_prio) { 82 auto it = std::find_if(extensions->begin(), extensions->end(), 83 [name](const webrtc::RtpExtension& rhs) { 84 return rhs.name == name; 85 }); 86 if (it != extensions->end()) { 87 if (found) { 88 extensions->erase(it); 89 } 90 found = true; 91 } 92 } 93 } 94 } // namespace 95 96 bool ValidateRtpExtensions(const std::vector<RtpHeaderExtension>& extensions) { 97 bool id_used[14] = {false}; 98 for (const auto& extension : extensions) { 99 if (extension.id <= 0 || extension.id >= 15) { 100 LOG(LS_ERROR) << "Bad RTP extension ID: " << extension.ToString(); 101 return false; 102 } 103 if (id_used[extension.id - 1]) { 104 LOG(LS_ERROR) << "Duplicate RTP extension ID: " << extension.ToString(); 105 return false; 106 } 107 id_used[extension.id - 1] = true; 108 } 109 return true; 110 } 111 112 std::vector<webrtc::RtpExtension> FilterRtpExtensions( 113 const std::vector<RtpHeaderExtension>& extensions, 114 bool (*supported)(const std::string&), 115 bool filter_redundant_extensions) { 116 RTC_DCHECK(ValidateRtpExtensions(extensions)); 117 RTC_DCHECK(supported); 118 std::vector<webrtc::RtpExtension> result; 119 120 // Ignore any extensions that we don't recognize. 121 for (const auto& extension : extensions) { 122 if (supported(extension.uri)) { 123 result.push_back({extension.uri, extension.id}); 124 } else { 125 LOG(LS_WARNING) << "Unsupported RTP extension: " << extension.ToString(); 126 } 127 } 128 129 // Sort by name, ascending, so that we don't reset extensions if they were 130 // specified in a different order (also allows us to use std::unique below). 131 std::sort(result.begin(), result.end(), 132 [](const webrtc::RtpExtension& rhs, const webrtc::RtpExtension& lhs) { 133 return rhs.name < lhs.name; 134 }); 135 136 // Remove unnecessary extensions (used on send side). 137 if (filter_redundant_extensions) { 138 auto it = std::unique(result.begin(), result.end(), 139 [](const webrtc::RtpExtension& rhs, const webrtc::RtpExtension& lhs) { 140 return rhs.name == lhs.name; 141 }); 142 result.erase(it, result.end()); 143 144 // Keep just the highest priority extension of any in the following list. 145 static const char* kBweExtensionPriorities[] = { 146 kRtpTransportSequenceNumberHeaderExtension, 147 kRtpAbsoluteSenderTimeHeaderExtension, 148 kRtpTimestampOffsetHeaderExtension 149 }; 150 DiscardRedundantExtensions(&result, kBweExtensionPriorities); 151 } 152 153 return result; 154 } 155 } // namespace cricket 156