tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

webrtc_media_engine.cc (6850B)


      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 <algorithm>
     14 #include <map>
     15 #include <string>
     16 #include <vector>
     17 
     18 #include "absl/algorithm/container.h"
     19 #include "absl/strings/string_view.h"
     20 #include "api/array_view.h"
     21 #include "api/field_trials_view.h"
     22 #include "api/rtp_parameters.h"
     23 #include "api/transport/bitrate_settings.h"
     24 #include "media/base/codec.h"
     25 #include "media/base/media_constants.h"
     26 #include "rtc_base/checks.h"
     27 #include "rtc_base/logging.h"
     28 
     29 namespace webrtc {
     30 namespace {
     31 // Remove mutually exclusive extensions with lower priority.
     32 void DiscardRedundantExtensions(
     33    std::vector<RtpExtension>* extensions,
     34    ArrayView<const char* const> extensions_decreasing_prio) {
     35  RTC_DCHECK(extensions);
     36  bool found = false;
     37  for (const char* uri : extensions_decreasing_prio) {
     38    auto it = absl::c_find_if(
     39        *extensions, [uri](const RtpExtension& rhs) { return rhs.uri == uri; });
     40    if (it != extensions->end()) {
     41      if (found) {
     42        extensions->erase(it);
     43      }
     44      found = true;
     45    }
     46  }
     47 }
     48 }  // namespace
     49 
     50 bool ValidateRtpExtensions(ArrayView<const RtpExtension> extensions,
     51                           ArrayView<const RtpExtension> old_extensions) {
     52  bool id_used[1 + RtpExtension::kMaxId] = {false};
     53  for (const auto& extension : extensions) {
     54    if (extension.id < RtpExtension::kMinId ||
     55        extension.id > RtpExtension::kMaxId) {
     56      RTC_LOG(LS_ERROR) << "Bad RTP extension ID: " << extension.ToString();
     57      return false;
     58    }
     59    if (id_used[extension.id]) {
     60      RTC_LOG(LS_ERROR) << "Duplicate RTP extension ID: "
     61                        << extension.ToString();
     62      return false;
     63    }
     64    id_used[extension.id] = true;
     65  }
     66  // Validate the extension list against the already negotiated extensions.
     67  // Re-registering is OK, re-mapping (either same URL at new ID or same
     68  // ID used with new URL) is an illegal remap.
     69 
     70  // This is required in order to avoid a crash when registering an
     71  // extension. A better structure would use the registered extensions
     72  // in the RTPSender. This requires spinning through:
     73  //
     74  // WebRtcVoiceMediaChannel::::WebRtcAudioSendStream::stream_ (pointer)
     75  // AudioSendStream::rtp_rtcp_module_ (pointer)
     76  // ModuleRtpRtcpImpl2::rtp_sender_ (pointer)
     77  // RtpSenderContext::packet_generator (struct member)
     78  // RTPSender::rtp_header_extension_map_ (class member)
     79  //
     80  // Getting at this seems like a hard slog.
     81  if (!old_extensions.empty()) {
     82    absl::string_view urimap[1 + RtpExtension::kMaxId];
     83    std::map<absl::string_view, int> idmap;
     84    for (const auto& old_extension : old_extensions) {
     85      urimap[old_extension.id] = old_extension.uri;
     86      idmap[old_extension.uri] = old_extension.id;
     87    }
     88    for (const auto& extension : extensions) {
     89      if (!urimap[extension.id].empty() &&
     90          urimap[extension.id] != extension.uri) {
     91        RTC_LOG(LS_ERROR) << "Extension negotiation failure: " << extension.id
     92                          << " was mapped to " << urimap[extension.id]
     93                          << " but is proposed changed to " << extension.uri;
     94        return false;
     95      }
     96      const auto& it = idmap.find(extension.uri);
     97      if (it != idmap.end() && it->second != extension.id) {
     98        RTC_LOG(LS_ERROR) << "Extension negotation failure: " << extension.uri
     99                          << " was identified by " << it->second
    100                          << " but is proposed changed to " << extension.id;
    101        return false;
    102      }
    103    }
    104  }
    105  return true;
    106 }
    107 
    108 std::vector<RtpExtension> FilterRtpExtensions(
    109    const std::vector<RtpExtension>& extensions,
    110    bool (*supported)(absl::string_view),
    111    bool filter_redundant_extensions,
    112    const FieldTrialsView& trials) {
    113  // Don't check against old parameters; this should have been done earlier.
    114  RTC_DCHECK(ValidateRtpExtensions(extensions, {}));
    115  RTC_DCHECK(supported);
    116  std::vector<RtpExtension> result;
    117 
    118  // Ignore any extensions that we don't recognize.
    119  for (const auto& extension : extensions) {
    120    if (supported(extension.uri)) {
    121      result.push_back(extension);
    122    } else {
    123      RTC_LOG(LS_WARNING) << "Unsupported RTP extension: "
    124                          << extension.ToString();
    125    }
    126  }
    127 
    128  // Sort by name, ascending (prioritise encryption), so that we don't reset
    129  // extensions if they were specified in a different order (also allows us
    130  // to use std::unique below).
    131  absl::c_sort(result, [](const RtpExtension& rhs, const RtpExtension& lhs) {
    132    return rhs.encrypt == lhs.encrypt ? rhs.uri < lhs.uri
    133                                      : rhs.encrypt > lhs.encrypt;
    134  });
    135 
    136  // Remove unnecessary extensions (used on send side).
    137  if (filter_redundant_extensions) {
    138    auto it =
    139        std::unique(result.begin(), result.end(),
    140                    [](const RtpExtension& rhs, const RtpExtension& lhs) {
    141                      return rhs.uri == lhs.uri && rhs.encrypt == lhs.encrypt;
    142                    });
    143    result.erase(it, result.end());
    144 
    145    // Keep just the highest priority extension of any in the following lists.
    146    if (trials.IsEnabled("WebRTC-FilterAbsSendTimeExtension")) {
    147      static const char* const kBweExtensionPriorities[] = {
    148          RtpExtension::kTransportSequenceNumberUri,
    149          RtpExtension::kAbsSendTimeUri, RtpExtension::kTimestampOffsetUri};
    150      DiscardRedundantExtensions(&result, kBweExtensionPriorities);
    151    } else {
    152      static const char* const kBweExtensionPriorities[] = {
    153          RtpExtension::kAbsSendTimeUri, RtpExtension::kTimestampOffsetUri};
    154      DiscardRedundantExtensions(&result, kBweExtensionPriorities);
    155    }
    156  }
    157  return result;
    158 }
    159 
    160 BitrateConstraints GetBitrateConfigForCodec(const Codec& codec) {
    161  BitrateConstraints config;
    162  int bitrate_kbps = 0;
    163  if (codec.GetParam(kCodecParamMinBitrate, &bitrate_kbps) &&
    164      bitrate_kbps > 0) {
    165    config.min_bitrate_bps = bitrate_kbps * 1000;
    166  } else {
    167    config.min_bitrate_bps = 0;
    168  }
    169  if (codec.GetParam(kCodecParamStartBitrate, &bitrate_kbps) &&
    170      bitrate_kbps > 0) {
    171    config.start_bitrate_bps = bitrate_kbps * 1000;
    172  } else {
    173    // Do not reconfigure start bitrate unless it's specified and positive.
    174    config.start_bitrate_bps = -1;
    175  }
    176  if (codec.GetParam(kCodecParamMaxBitrate, &bitrate_kbps) &&
    177      bitrate_kbps > 0) {
    178    config.max_bitrate_bps = bitrate_kbps * 1000;
    179  } else {
    180    config.max_bitrate_bps = -1;
    181  }
    182  return config;
    183 }
    184 }  // namespace webrtc