tor-browser

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

PlatformEncoderModule.cpp (6410B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "PlatformEncoderModule.h"
      8 
      9 #include "H264.h"
     10 #include "mozilla/ToString.h"
     11 #include "nsPrintfCString.h"
     12 
     13 namespace mozilla {
     14 
     15 extern LazyLogModule sPEMLog;
     16 #define LOGD(fmt, ...)                       \
     17  MOZ_LOG(sPEMLog, mozilla::LogLevel::Debug, \
     18          ("PEM: %s: " fmt, __func__, ##__VA_ARGS__))
     19 
     20 RefPtr<PlatformEncoderModule::CreateEncoderPromise>
     21 PlatformEncoderModule::AsyncCreateEncoder(const EncoderConfig& aEncoderConfig,
     22                                          const RefPtr<TaskQueue>& aTaskQueue) {
     23  RefPtr<MediaDataEncoder> encoder;
     24  MediaResult result = NS_OK;
     25  if (aEncoderConfig.IsAudio()) {
     26    encoder = CreateAudioEncoder(aEncoderConfig, aTaskQueue);
     27  } else if (aEncoderConfig.IsVideo()) {
     28    encoder = CreateVideoEncoder(aEncoderConfig, aTaskQueue);
     29  }
     30  if (!encoder) {
     31    if (NS_FAILED(result)) {
     32      return CreateEncoderPromise::CreateAndReject(result, __func__);
     33    }
     34    return CreateEncoderPromise::CreateAndReject(
     35        MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
     36                    nsPrintfCString("Error creating encoder for %d",
     37                                    static_cast<int>(aEncoderConfig.mCodec))
     38                        .get()),
     39        __func__);
     40  }
     41  return CreateEncoderPromise::CreateAndResolve(encoder, __func__);
     42 }
     43 
     44 template <typename T>
     45 nsCString MaybeToString(const Maybe<T>& aMaybe) {
     46  return nsPrintfCString(
     47      "%s", aMaybe.isSome() ? ToString(aMaybe.value()).c_str() : "nothing");
     48 }
     49 
     50 struct ConfigurationChangeToString {
     51  nsCString operator()(const DimensionsChange& aDimensionsChange) {
     52    return nsPrintfCString("Dimensions: %dx%d", aDimensionsChange.get().width,
     53                           aDimensionsChange.get().height);
     54  }
     55  nsCString operator()(const DisplayDimensionsChange& aDisplayDimensionChange) {
     56    if (aDisplayDimensionChange.get().isNothing()) {
     57      return nsCString("Display dimensions: nothing");
     58    }
     59    gfx::IntSize displayDimensions = aDisplayDimensionChange.get().value();
     60    return nsPrintfCString("Display dimensions: %dx%d", displayDimensions.width,
     61                           displayDimensions.height);
     62  }
     63  nsCString operator()(const BitrateChange& aBitrateChange) {
     64    if (aBitrateChange.get().isSome()) {
     65      return nsLiteralCString("Bitrate: nothing");
     66    }
     67    return nsPrintfCString("Bitrate: %skbps",
     68                           MaybeToString(aBitrateChange.get()).get());
     69  }
     70  nsCString operator()(const FramerateChange& aFramerateChange) {
     71    if (aFramerateChange.get().isNothing()) {
     72      return nsCString("Framerate: nothing");
     73    }
     74    return nsPrintfCString("Framerate: %lfHz", aFramerateChange.get().value());
     75  }
     76  nsCString operator()(const BitrateModeChange& aBitrateModeChange) {
     77    return nsPrintfCString("Bitrate mode: %s",
     78                           aBitrateModeChange.get() == BitrateMode::Constant
     79                               ? "Constant"
     80                               : "Variable");
     81  }
     82  nsCString operator()(const UsageChange& aUsageChange) {
     83    return nsPrintfCString(
     84        "Usage mode: %s",
     85        aUsageChange.get() == Usage::Realtime ? "Realtime" : "Recoding");
     86  }
     87  nsCString operator()(const ContentHintChange& aContentHintChange) {
     88    return nsPrintfCString("Content hint: %s",
     89                           MaybeToString(aContentHintChange.get()).get());
     90  }
     91  nsCString operator()(const SampleRateChange& aSampleRateChange) {
     92    return nsPrintfCString("Sample rate %" PRIu32 "Hz",
     93                           aSampleRateChange.get());
     94  }
     95  nsCString operator()(const NumberOfChannelsChange& aNumberOfChannelsChange) {
     96    return nsPrintfCString("Channels: %" PRIu32 "Hz",
     97                           aNumberOfChannelsChange.get());
     98  }
     99 };
    100 
    101 nsString EncoderConfigurationChangeList::ToString() const {
    102  nsString rv(
    103      NS_LITERAL_STRING_FROM_CSTRING("EncoderConfigurationChangeList:"_ns));
    104  for (const EncoderConfigurationItem& change : mChanges) {
    105    nsCString str = change.match(ConfigurationChangeToString());
    106    rv.AppendPrintf("- %s\n", str.get());
    107  }
    108  return rv;
    109 }
    110 
    111 bool CanLikelyEncode(const EncoderConfig& aConfig) {
    112  if (aConfig.mCodec == CodecType::H264) {
    113    if (!aConfig.mCodecSpecific.is<H264Specific>()) {
    114      LOGD(
    115          "Error: asking for support codec for h264 without h264 specific "
    116          "config.");
    117      return false;
    118    }
    119    H264Specific specific = aConfig.mCodecSpecific.as<H264Specific>();
    120    int width = aConfig.mSize.width;
    121    int height = aConfig.mSize.height;
    122    if (width % 2 || !width) {
    123      LOGD("Invalid width of %d for h264", width);
    124      return false;
    125    }
    126    if (height % 2 || !height) {
    127      LOGD("Invalid height of %d for h264", height);
    128      return false;
    129    }
    130    if (specific.mProfile != H264_PROFILE_BASE &&
    131        specific.mProfile != H264_PROFILE_MAIN &&
    132        specific.mProfile != H264_PROFILE_HIGH) {
    133      LOGD("Invalid profile of %x for h264", specific.mProfile);
    134      return false;
    135    }
    136    // x264 (Linux software) and some Windows configuration (e.g. some nvidia
    137    // hardware) support level 62 which supports 8k
    138    if ((specific.mLevel >= H264_LEVEL::H264_LEVEL_6) &&
    139        (width > 2 * 4096 || height > 2 * 4096)) {
    140      LOGD("Invalid size of %dx%d for h264", width, height);
    141      return false;
    142    }
    143    // Levels strictly below 6 are limited to 4096x4096px
    144    if (specific.mLevel < H264_LEVEL::H264_LEVEL_6 &&
    145        (width > 4096 || height > 4096)) {
    146      LOGD("Invalid size of %dx%d for h264", width, height);
    147      return false;
    148    }
    149  }
    150  if (aConfig.mCodec == CodecType::VP8) {
    151    int width = aConfig.mSize.width;
    152    int height = aConfig.mSize.height;
    153    if (width > 2 << 13 || height > 2 << 13) {
    154      LOGD("Invalid size of %dx%d for VP8", width, height);
    155      return false;
    156    }
    157  }
    158  if (aConfig.mCodec == CodecType::VP9) {
    159    int width = aConfig.mSize.width;
    160    int height = aConfig.mSize.height;
    161    if (width > 2 << 15 || height > 2 << 15) {
    162      LOGD("Invalid size of %dx%d for VP9", width, height);
    163      return false;
    164    }
    165  }
    166 
    167  return true;
    168 }
    169 
    170 }  // namespace mozilla
    171 
    172 #undef LOGD