Home | History | Annotate | Download | only in webrtc
      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