tor-browser

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

h264.cc (6318B)


      1 /*
      2 *  Copyright (c) 2015 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 
     12 #include "modules/video_coding/codecs/h264/include/h264.h"
     13 
     14 #include <memory>
     15 #include <optional>
     16 #include <string>
     17 #include <vector>
     18 
     19 #include "absl/base/nullability.h"
     20 #include "absl/container/inlined_vector.h"
     21 #include "api/environment/environment.h"
     22 #include "api/video_codecs/h264_profile_level_id.h"
     23 #include "api/video_codecs/scalability_mode.h"
     24 #include "api/video_codecs/sdp_video_format.h"
     25 #include "api/video_codecs/video_encoder.h"
     26 #include "media/base/media_constants.h"
     27 #include "modules/video_coding/codecs/h264/include/h264_globals.h"
     28 #include "rtc_base/checks.h"
     29 #include "rtc_base/logging.h"
     30 #include "rtc_base/trace_event.h"
     31 
     32 #if defined(WEBRTC_USE_H264)
     33 #include "modules/video_coding/codecs/h264/h264_decoder_impl.h"
     34 #include "modules/video_coding/codecs/h264/h264_encoder_impl.h"
     35 #endif
     36 
     37 namespace webrtc {
     38 
     39 namespace {
     40 
     41 #if defined(WEBRTC_USE_H264)
     42 bool g_rtc_use_h264 = true;
     43 #endif
     44 
     45 // If H.264 OpenH264/FFmpeg codec is supported.
     46 bool IsH264CodecSupported() {
     47 #if defined(WEBRTC_USE_H264)
     48  return g_rtc_use_h264;
     49 #else
     50  return false;
     51 #endif
     52 }
     53 
     54 constexpr ScalabilityMode kSupportedScalabilityModes[] = {
     55    ScalabilityMode::kL1T1, ScalabilityMode::kL1T2, ScalabilityMode::kL1T3};
     56 
     57 }  // namespace
     58 
     59 SdpVideoFormat CreateH264Format(H264Profile profile,
     60                                H264Level level,
     61                                const std::string& packetization_mode,
     62                                bool add_scalability_modes) {
     63  const std::optional<std::string> profile_string =
     64      H264ProfileLevelIdToString(H264ProfileLevelId(profile, level));
     65  RTC_CHECK(profile_string);
     66  absl::InlinedVector<ScalabilityMode, kScalabilityModeCount> scalability_modes;
     67  if (add_scalability_modes) {
     68    for (const auto scalability_mode : kSupportedScalabilityModes) {
     69      scalability_modes.push_back(scalability_mode);
     70    }
     71  }
     72  return SdpVideoFormat(kH264CodecName,
     73                        {{kH264FmtpProfileLevelId, *profile_string},
     74                         {kH264FmtpLevelAsymmetryAllowed, "1"},
     75                         {kH264FmtpPacketizationMode, packetization_mode}},
     76                        scalability_modes);
     77 }
     78 
     79 void DisableRtcUseH264() {
     80 #if defined(WEBRTC_USE_H264)
     81  g_rtc_use_h264 = false;
     82 #endif
     83 }
     84 
     85 std::vector<SdpVideoFormat> SupportedH264Codecs(bool add_scalability_modes) {
     86  TRACE_EVENT0("webrtc", __func__);
     87  if (!IsH264CodecSupported())
     88    return std::vector<SdpVideoFormat>();
     89  // We only support encoding Constrained Baseline Profile (CBP), but the
     90  // decoder supports more profiles. We can list all profiles here that are
     91  // supported by the decoder and that are also supersets of CBP, i.e. the
     92  // decoder for that profile is required to be able to decode CBP. This means
     93  // we can encode and send CBP even though we negotiated a potentially
     94  // higher profile. See the H264 spec for more information.
     95  //
     96  // We support both packetization modes 0 (mandatory) and 1 (optional,
     97  // preferred).
     98  return {CreateH264Format(H264Profile::kProfileBaseline, H264Level::kLevel3_1,
     99                           "1", add_scalability_modes),
    100          CreateH264Format(H264Profile::kProfileBaseline, H264Level::kLevel3_1,
    101                           "0", add_scalability_modes),
    102          CreateH264Format(H264Profile::kProfileConstrainedBaseline,
    103                           H264Level::kLevel3_1, "1", add_scalability_modes),
    104          CreateH264Format(H264Profile::kProfileConstrainedBaseline,
    105                           H264Level::kLevel3_1, "0", add_scalability_modes),
    106          CreateH264Format(H264Profile::kProfileMain, H264Level::kLevel3_1, "1",
    107                           add_scalability_modes),
    108          CreateH264Format(H264Profile::kProfileMain, H264Level::kLevel3_1, "0",
    109                           add_scalability_modes)};
    110 }
    111 
    112 std::vector<SdpVideoFormat> SupportedH264DecoderCodecs() {
    113  TRACE_EVENT0("webrtc", __func__);
    114  if (!IsH264CodecSupported())
    115    return std::vector<SdpVideoFormat>();
    116 
    117  std::vector<SdpVideoFormat> supportedCodecs = SupportedH264Codecs();
    118 
    119  // OpenH264 doesn't yet support High Predictive 4:4:4 encoding but it does
    120  // support decoding.
    121  supportedCodecs.push_back(CreateH264Format(
    122      H264Profile::kProfilePredictiveHigh444, H264Level::kLevel3_1, "1"));
    123  supportedCodecs.push_back(CreateH264Format(
    124      H264Profile::kProfilePredictiveHigh444, H264Level::kLevel3_1, "0"));
    125 
    126  return supportedCodecs;
    127 }
    128 
    129 H264EncoderSettings H264EncoderSettings::Parse(const SdpVideoFormat& format) {
    130  if (auto it = format.parameters.find(kH264FmtpPacketizationMode);
    131      it != format.parameters.end()) {
    132    if (it->second == "0") {
    133      return {.packetization_mode = H264PacketizationMode::SingleNalUnit};
    134    } else if (it->second == "1") {
    135      return {.packetization_mode = H264PacketizationMode::NonInterleaved};
    136    }
    137  }
    138  return {};
    139 }
    140 
    141 absl_nonnull std::unique_ptr<VideoEncoder> CreateH264Encoder(
    142    [[maybe_unused]] const Environment& env,
    143    [[maybe_unused]] H264EncoderSettings settings) {
    144 #if defined(WEBRTC_USE_H264)
    145  RTC_CHECK(g_rtc_use_h264);
    146  RTC_LOG(LS_INFO) << "Creating H264EncoderImpl.";
    147  return std::make_unique<H264EncoderImpl>(env, settings);
    148 #else
    149  RTC_CHECK_NOTREACHED();
    150 #endif
    151 }
    152 
    153 bool H264Encoder::IsSupported() {
    154  return IsH264CodecSupported();
    155 }
    156 
    157 bool H264Encoder::SupportsScalabilityMode(ScalabilityMode scalability_mode) {
    158  for (const auto& entry : kSupportedScalabilityModes) {
    159    if (entry == scalability_mode) {
    160      return true;
    161    }
    162  }
    163  return false;
    164 }
    165 
    166 std::unique_ptr<H264Decoder> H264Decoder::Create() {
    167  RTC_DCHECK(H264Decoder::IsSupported());
    168 #if defined(WEBRTC_USE_H264)
    169  RTC_CHECK(g_rtc_use_h264);
    170  RTC_LOG(LS_INFO) << "Creating H264DecoderImpl.";
    171  return std::make_unique<H264DecoderImpl>();
    172 #else
    173  RTC_DCHECK_NOTREACHED();
    174  return nullptr;
    175 #endif
    176 }
    177 
    178 bool H264Decoder::IsSupported() {
    179  return IsH264CodecSupported();
    180 }
    181 
    182 }  // namespace webrtc