tor-browser

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

media_engine.cc (12957B)


      1 /*
      2 *  Copyright (c) 2004 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/base/media_engine.h"
     12 
     13 #include <cstddef>
     14 #include <cstdint>
     15 #include <memory>
     16 #include <optional>
     17 #include <string>
     18 #include <utility>
     19 #include <vector>
     20 
     21 #include "absl/algorithm/container.h"
     22 #include "api/array_view.h"
     23 #include "api/field_trials_view.h"
     24 #include "api/rtc_error.h"
     25 #include "api/rtp_headers.h"
     26 #include "api/rtp_parameters.h"
     27 #include "api/rtp_transceiver_direction.h"
     28 #include "api/video/video_codec_constants.h"
     29 #include "api/video_codecs/scalability_mode.h"
     30 #include "media/base/codec.h"
     31 #include "media/base/codec_comparators.h"
     32 #include "media/base/rid_description.h"
     33 #include "media/base/stream_params.h"
     34 #include "rtc_base/checks.h"
     35 
     36 namespace webrtc {
     37 namespace {
     38 bool SupportsMode(const Codec& codec,
     39                  std::optional<std::string> scalability_mode) {
     40  if (!scalability_mode.has_value()) {
     41    return true;
     42  }
     43  return absl::c_any_of(codec.scalability_modes, [&](ScalabilityMode mode) {
     44    return ScalabilityModeToString(mode) == *scalability_mode;
     45  });
     46 }
     47 
     48 }  // namespace
     49 
     50 RtpParameters CreateRtpParametersWithOneEncoding() {
     51  RtpParameters parameters;
     52  RtpEncodingParameters encoding;
     53  parameters.encodings.push_back(encoding);
     54  return parameters;
     55 }
     56 
     57 RtpParameters CreateRtpParametersWithEncodings(StreamParams sp) {
     58  std::vector<uint32_t> primary_ssrcs;
     59  sp.GetPrimarySsrcs(&primary_ssrcs);
     60  size_t encoding_count = primary_ssrcs.size();
     61 
     62  std::vector<RtpEncodingParameters> encodings(encoding_count);
     63  for (size_t i = 0; i < encodings.size(); ++i) {
     64    encodings[i].ssrc = primary_ssrcs[i];
     65  }
     66 
     67  const std::vector<RidDescription>& rids = sp.rids();
     68  RTC_DCHECK(rids.empty() || rids.size() == encoding_count);
     69  for (size_t i = 0; i < rids.size(); ++i) {
     70    encodings[i].rid = rids[i].rid;
     71  }
     72 
     73  RtpParameters parameters;
     74  parameters.encodings = encodings;
     75  parameters.rtcp.cname = sp.cname;
     76  return parameters;
     77 }
     78 
     79 std::vector<RtpExtension> GetDefaultEnabledRtpHeaderExtensions(
     80    const RtpHeaderExtensionQueryInterface& query_interface,
     81    const webrtc::FieldTrialsView* field_trials) {
     82  std::vector<RtpExtension> extensions;
     83  for (const auto& entry :
     84       query_interface.GetRtpHeaderExtensions(field_trials)) {
     85    if (entry.direction != RtpTransceiverDirection::kStopped)
     86      extensions.emplace_back(entry.uri, *entry.preferred_id);
     87  }
     88  return extensions;
     89 }
     90 
     91 RTCError CheckScalabilityModeValues(const RtpParameters& rtp_parameters,
     92                                    ArrayView<Codec> send_codecs,
     93                                    std::optional<Codec> send_codec) {
     94  if (send_codecs.empty()) {
     95    // This is an audio sender or an extra check in the stack where the codec
     96    // list is not available and we can't check the scalability_mode values.
     97    return RTCError::OK();
     98  }
     99 
    100  for (size_t i = 0; i < rtp_parameters.encodings.size(); ++i) {
    101    if (rtp_parameters.encodings[i].codec) {
    102      bool codecFound = false;
    103      for (const Codec& codec : send_codecs) {
    104        if (IsSameRtpCodecIgnoringLevel(codec,
    105                                        *rtp_parameters.encodings[i].codec) &&
    106            SupportsMode(codec, rtp_parameters.encodings[i].scalability_mode)) {
    107          codecFound = true;
    108          send_codec = codec;
    109          break;
    110        }
    111      }
    112      if (!codecFound) {
    113        LOG_AND_RETURN_ERROR(
    114            RTCErrorType::INVALID_MODIFICATION,
    115            "Attempted to use an unsupported codec for layer " +
    116                std::to_string(i));
    117      }
    118    }
    119    if (rtp_parameters.encodings[i].scalability_mode) {
    120      if (!send_codec) {
    121        bool scalabilityModeFound = false;
    122        for (const Codec& codec : send_codecs) {
    123          for (const auto& scalability_mode : codec.scalability_modes) {
    124            if (ScalabilityModeToString(scalability_mode) ==
    125                *rtp_parameters.encodings[i].scalability_mode) {
    126              scalabilityModeFound = true;
    127              break;
    128            }
    129          }
    130          if (scalabilityModeFound)
    131            break;
    132        }
    133 
    134        if (!scalabilityModeFound) {
    135          LOG_AND_RETURN_ERROR(
    136              RTCErrorType::INVALID_MODIFICATION,
    137              "Attempted to set RtpParameters scalabilityMode "
    138              "to an unsupported value for the current codecs.");
    139        }
    140      } else {
    141        bool scalabilityModeFound = false;
    142        for (const auto& scalability_mode : send_codec->scalability_modes) {
    143          if (ScalabilityModeToString(scalability_mode) ==
    144              *rtp_parameters.encodings[i].scalability_mode) {
    145            scalabilityModeFound = true;
    146            break;
    147          }
    148        }
    149        if (!scalabilityModeFound) {
    150          LOG_AND_RETURN_ERROR(
    151              RTCErrorType::INVALID_MODIFICATION,
    152              "Attempted to set RtpParameters scalabilityMode "
    153              "to an unsupported value for the current codecs.");
    154        }
    155      }
    156    }
    157  }
    158 
    159  return RTCError::OK();
    160 }
    161 
    162 RTCError CheckRtpParametersValues(const RtpParameters& rtp_parameters,
    163                                  ArrayView<Codec> send_codecs,
    164                                  std::optional<Codec> send_codec,
    165                                  const FieldTrialsView& field_trials) {
    166  bool has_scale_resolution_down_to = false;
    167  for (size_t i = 0; i < rtp_parameters.encodings.size(); ++i) {
    168    if (rtp_parameters.encodings[i].bitrate_priority <= 0) {
    169      LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
    170                           "Attempted to set RtpParameters bitrate_priority to "
    171                           "an invalid number. bitrate_priority must be > 0.");
    172    }
    173    if (rtp_parameters.encodings[i].scale_resolution_down_by &&
    174        *rtp_parameters.encodings[i].scale_resolution_down_by < 1.0) {
    175      LOG_AND_RETURN_ERROR(
    176          RTCErrorType::INVALID_RANGE,
    177          "Attempted to set RtpParameters scale_resolution_down_by to an "
    178          "invalid value. scale_resolution_down_by must be >= 1.0");
    179    }
    180    if (rtp_parameters.encodings[i].max_framerate &&
    181        *rtp_parameters.encodings[i].max_framerate < 0.0) {
    182      LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
    183                           "Attempted to set RtpParameters max_framerate to an "
    184                           "invalid value. max_framerate must be >= 0.0");
    185    }
    186    if (rtp_parameters.encodings[i].min_bitrate_bps &&
    187        rtp_parameters.encodings[i].max_bitrate_bps) {
    188      if (*rtp_parameters.encodings[i].max_bitrate_bps <
    189          *rtp_parameters.encodings[i].min_bitrate_bps) {
    190        LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
    191                             "Attempted to set RtpParameters min bitrate "
    192                             "larger than max bitrate.");
    193      }
    194    }
    195    if (rtp_parameters.encodings[i].num_temporal_layers) {
    196      if (*rtp_parameters.encodings[i].num_temporal_layers < 1 ||
    197          *rtp_parameters.encodings[i].num_temporal_layers >
    198              kMaxTemporalStreams) {
    199        LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
    200                             "Attempted to set RtpParameters "
    201                             "num_temporal_layers to an invalid number.");
    202      }
    203    }
    204 
    205    if (rtp_parameters.encodings[i].scale_resolution_down_to.has_value()) {
    206      has_scale_resolution_down_to = true;
    207      if (rtp_parameters.encodings[i].scale_resolution_down_to->width <= 0 ||
    208          rtp_parameters.encodings[i].scale_resolution_down_to->height <= 0) {
    209        LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
    210                             "The resolution dimensions must be positive.");
    211      }
    212    }
    213 
    214    if (!field_trials.IsEnabled("WebRTC-MixedCodecSimulcast")) {
    215      if (i > 0 && rtp_parameters.encodings[i - 1].codec !=
    216                       rtp_parameters.encodings[i].codec) {
    217        LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
    218                             "Attempted to use different codec values for "
    219                             "different encodings.");
    220      }
    221    }
    222 
    223    if (rtp_parameters.encodings[i].csrcs.has_value() &&
    224        rtp_parameters.encodings[i].csrcs.value().size() > kRtpCsrcSize) {
    225      LOG_AND_RETURN_ERROR(
    226          RTCErrorType::INVALID_RANGE,
    227          "Attempted to set more than the maximum allowed number of CSRCs.")
    228    }
    229 
    230    if (i > 0 && rtp_parameters.encodings[i - 1].csrcs !=
    231                     rtp_parameters.encodings[i].csrcs) {
    232      LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
    233                           "Attempted to set different CSRCs for different "
    234                           "encodings.");
    235    }
    236  }
    237 
    238  if (has_scale_resolution_down_to &&
    239      absl::c_any_of(rtp_parameters.encodings,
    240                     [](const RtpEncodingParameters& encoding) {
    241                       return encoding.active &&
    242                              !encoding.scale_resolution_down_to.has_value();
    243                     })) {
    244    LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
    245                         "If a resolution is specified on any encoding then "
    246                         "it must be specified on all encodings.");
    247  }
    248 
    249  return CheckScalabilityModeValues(rtp_parameters, send_codecs, send_codec);
    250 }
    251 
    252 RTCError CheckRtpParametersInvalidModificationAndValues(
    253    const RtpParameters& old_rtp_parameters,
    254    const RtpParameters& rtp_parameters,
    255    const FieldTrialsView& field_trials) {
    256  return CheckRtpParametersInvalidModificationAndValues(
    257      old_rtp_parameters, rtp_parameters, {}, std::nullopt, field_trials);
    258 }
    259 
    260 RTCError CheckRtpParametersInvalidModificationAndValues(
    261    const RtpParameters& old_rtp_parameters,
    262    const RtpParameters& rtp_parameters,
    263    ArrayView<Codec> send_codecs,
    264    std::optional<Codec> send_codec,
    265    const FieldTrialsView& field_trials) {
    266  if (rtp_parameters.encodings.size() != old_rtp_parameters.encodings.size()) {
    267    LOG_AND_RETURN_ERROR(
    268        RTCErrorType::INVALID_MODIFICATION,
    269        "Attempted to set RtpParameters with different encoding count");
    270  }
    271  if (rtp_parameters.rtcp != old_rtp_parameters.rtcp) {
    272    LOG_AND_RETURN_ERROR(
    273        RTCErrorType::INVALID_MODIFICATION,
    274        "Attempted to set RtpParameters with modified RTCP parameters");
    275  }
    276  if (rtp_parameters.header_extensions !=
    277      old_rtp_parameters.header_extensions) {
    278    LOG_AND_RETURN_ERROR(
    279        RTCErrorType::INVALID_MODIFICATION,
    280        "Attempted to set RtpParameters with modified header extensions");
    281  }
    282  if (!absl::c_equal(old_rtp_parameters.encodings, rtp_parameters.encodings,
    283                     [](const RtpEncodingParameters& encoding1,
    284                        const RtpEncodingParameters& encoding2) {
    285                       return encoding1.rid == encoding2.rid;
    286                     })) {
    287    LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
    288                         "Attempted to change RID values in the encodings.");
    289  }
    290  if (!absl::c_equal(old_rtp_parameters.encodings, rtp_parameters.encodings,
    291                     [](const RtpEncodingParameters& encoding1,
    292                        const RtpEncodingParameters& encoding2) {
    293                       return encoding1.ssrc == encoding2.ssrc;
    294                     })) {
    295    LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
    296                         "Attempted to set RtpParameters with modified SSRC");
    297  }
    298 
    299  return CheckRtpParametersValues(rtp_parameters, send_codecs, send_codec,
    300                                  field_trials);
    301 }
    302 
    303 CompositeMediaEngine::CompositeMediaEngine(
    304    std::unique_ptr<FieldTrialsView> trials,
    305    std::unique_ptr<VoiceEngineInterface> audio_engine,
    306    std::unique_ptr<VideoEngineInterface> video_engine)
    307    : trials_(std::move(trials)),
    308      voice_engine_(std::move(audio_engine)),
    309      video_engine_(std::move(video_engine)) {}
    310 
    311 CompositeMediaEngine::CompositeMediaEngine(
    312    std::unique_ptr<VoiceEngineInterface> audio_engine,
    313    std::unique_ptr<VideoEngineInterface> video_engine)
    314    : CompositeMediaEngine(nullptr,
    315                           std::move(audio_engine),
    316                           std::move(video_engine)) {}
    317 
    318 CompositeMediaEngine::~CompositeMediaEngine() = default;
    319 
    320 bool CompositeMediaEngine::Init() {
    321  voice().Init();
    322  return true;
    323 }
    324 
    325 VoiceEngineInterface& CompositeMediaEngine::voice() {
    326  return *voice_engine_;
    327 }
    328 
    329 VideoEngineInterface& CompositeMediaEngine::video() {
    330  return *video_engine_;
    331 }
    332 
    333 const VoiceEngineInterface& CompositeMediaEngine::voice() const {
    334  return *voice_engine_;
    335 }
    336 
    337 const VideoEngineInterface& CompositeMediaEngine::video() const {
    338  return *video_engine_;
    339 }
    340 
    341 }  // namespace webrtc