Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  PEMFactory.cpp

  Sprache: C
 

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "PEMFactory.h"

#include "PlatformEncoderModule.h"

#ifdef MOZ_APPLEMEDIA
#  include "AppleEncoderModule.h"
#endif

#ifdef MOZ_WIDGET_ANDROID
#  include "AndroidDecoderModule.h"
#  include "AndroidEncoderModule.h"
#endif

#ifdef XP_WIN
#  include "WMFEncoderModule.h"
#endif

#ifdef MOZ_FFMPEG
#  include "FFmpegRuntimeLinker.h"
#endif

#include "FFVPXRuntimeLinker.h"
#include "GMPEncoderModule.h"
#include "mozilla/RemoteEncoderModule.h"
#include "mozilla/StaticMutex.h"
#include "mozilla/StaticPrefs_media.h"
#include "mozilla/gfx/gfxVars.h"

using namespace mozilla::media;

namespace mozilla {

LazyLogModule sPEMLog("PlatformEncoderModule");

#define LOGE(fmt, ...)                                                    \
  MOZ_LOG_FMT(sPEMLog, mozilla::LogLevel::Error, "[PEMFactory] {}: " fmt, \
              __func__, ##__VA_ARGS__)
#define LOG(fmt, ...)                                                     \
  MOZ_LOG_FMT(sPEMLog, mozilla::LogLevel::Debug, "[PEMFactory] {}: " fmt, \
              __func__, ##__VA_ARGS__)

static CodecType MediaCodecToCodecType(MediaCodec aCodec) {
  switch (aCodec) {
    case MediaCodec::H264:
      return CodecType::H264;
    case MediaCodec::VP8:
      return CodecType::VP8;
    case MediaCodec::VP9:
      return CodecType::VP9;
    case MediaCodec::AV1:
      return CodecType::AV1;
    case MediaCodec::HEVC:
      return CodecType::H265;
    case MediaCodec::AAC:
      return CodecType::AAC;
    case MediaCodec::FLAC:
      return CodecType::Flac;
    case MediaCodec::Opus:
      return CodecType::Opus;
    case MediaCodec::Vorbis:
      return CodecType::Vorbis;
    case MediaCodec::MP3:
    case MediaCodec::Wave:
    case MediaCodec::SENTINEL:
      return CodecType::Unknown;
    default:
      MOZ_ASSERT_UNREACHABLE("Unhandled MediaCodec type!");
      return CodecType::Unknown;
  }
}

void PEMFactory::InitGpuPEMs() {
  if (!StaticPrefs::media_use_remote_encoder_video()) {
    return;
  }

#ifdef MOZ_APPLEMEDIA
  if (StaticPrefs::media_gpu_process_encoder()) {
    RefPtr<PlatformEncoderModule> m(new AppleEncoderModule());
    mCurrentPEMs.AppendElement(m);
  }
#endif

#ifdef XP_WIN
  if (StaticPrefs::media_wmf_enabled() &&
      StaticPrefs::media_gpu_process_encoder()) {
    mCurrentPEMs.AppendElement(new WMFEncoderModule());
  }
#endif

#ifndef MOZ_FFVPX_AUDIOONLY
  if (StaticPrefs::media_ffmpeg_encoder_enabled() &&
      StaticPrefs::media_gpu_process_encoder()) {
    if (RefPtr<PlatformEncoderModule> pem =
            FFVPXRuntimeLinker::CreateEncoder()) {
      mCurrentPEMs.AppendElement(pem);
    }
  }
#endif

#ifdef MOZ_FFMPEG
  if (StaticPrefs::media_ffmpeg_encoder_enabled() &&
      StaticPrefs::media_gpu_process_encoder()) {
    if (RefPtr<PlatformEncoderModule> pem =
            FFmpegRuntimeLinker::CreateEncoder()) {
      mCurrentPEMs.AppendElement(pem);
    }
  }
#endif
}

void PEMFactory::InitRddPEMs() {
#ifdef MOZ_APPLEMEDIA
  if (StaticPrefs::media_use_remote_encoder_video() &&
      StaticPrefs::media_rdd_applemedia_enabled()) {
    RefPtr<PlatformEncoderModule> m(new AppleEncoderModule());
    mCurrentPEMs.AppendElement(m);
  }
#endif

#ifdef XP_WIN
  if (StaticPrefs::media_use_remote_encoder_video() &&
      StaticPrefs::media_wmf_enabled() &&
      StaticPrefs::media_rdd_wmf_enabled()) {
    mCurrentPEMs.AppendElement(new WMFEncoderModule());
  }
#endif

#ifdef MOZ_FFVPX_AUDIOONLY
  if (StaticPrefs::media_use_remote_encoder_audio() &&
      StaticPrefs::media_ffmpeg_encoder_enabled() &&
      !StaticPrefs::media_utility_process_enabled() &&
      StaticPrefs::media_rdd_ffvpx_enabled())
#else
  if (((StaticPrefs::media_use_remote_encoder_audio() &&
        !StaticPrefs::media_utility_process_enabled()) ||
       StaticPrefs::media_use_remote_encoder_video()) &&
      StaticPrefs::media_ffmpeg_encoder_enabled() &&
      StaticPrefs::media_rdd_ffvpx_enabled())
#endif
  {
    if (RefPtr<PlatformEncoderModule> pem =
            FFVPXRuntimeLinker::CreateEncoder()) {
      mCurrentPEMs.AppendElement(pem);
    }
  }

#ifdef MOZ_FFMPEG
#  ifdef MOZ_FFVPX_AUDIOONLY
  if (StaticPrefs::media_use_remote_encoder_audio() &&
      StaticPrefs::media_ffmpeg_encoder_enabled() &&
      !StaticPrefs::media_utility_process_enabled() &&
      StaticPrefs::media_rdd_ffmpeg_enabled())
#  else
  if (((StaticPrefs::media_use_remote_encoder_audio() &&
        !StaticPrefs::media_utility_process_enabled()) ||
       StaticPrefs::media_use_remote_encoder_video()) &&
      StaticPrefs::media_ffmpeg_encoder_enabled() &&
      StaticPrefs::media_rdd_ffmpeg_enabled())
#  endif
  {
    if (StaticPrefs::media_ffmpeg_enabled()) {
      if (RefPtr<PlatformEncoderModule> pem =
              FFmpegRuntimeLinker::CreateEncoder()) {
        mCurrentPEMs.AppendElement(pem);
      }
    }
  }
#endif
}

void PEMFactory::InitUtilityPEMs() {
  if (StaticPrefs::media_use_remote_encoder_audio() &&
      StaticPrefs::media_ffmpeg_encoder_enabled()) {
    if (RefPtr<PlatformEncoderModule> pem =
            FFVPXRuntimeLinker::CreateEncoder()) {
      mCurrentPEMs.AppendElement(pem);
    }
  }

#ifdef MOZ_FFMPEG
  if (StaticPrefs::media_use_remote_encoder_audio() &&
      StaticPrefs::media_ffmpeg_enabled()) {
    if (RefPtr<PlatformEncoderModule> pem =
            FFmpegRuntimeLinker::CreateEncoder()) {
      mCurrentPEMs.AppendElement(pem);
    }
  }
#endif

#ifdef MOZ_WIDGET_ANDROID
  if (StaticPrefs::media_utility_android_media_codec_enabled()) {
    mCurrentPEMs.AppendElement(new AndroidEncoderModule());
  }
#endif
}

void PEMFactory::InitContentPEMs() {
  if ((StaticPrefs::media_use_remote_encoder_video() ||
       StaticPrefs::media_use_remote_encoder_audio()) &&
      StaticPrefs::media_rdd_process_enabled()) {
    if (RefPtr<PlatformEncoderModule> pem =
            RemoteEncoderModule::Create(RemoteMediaIn::RddProcess)) {
      mCurrentPEMs.AppendElement(std::move(pem));
    }
  }

  if (StaticPrefs::media_use_remote_encoder_audio() &&
      StaticPrefs::media_utility_process_enabled()) {
#ifdef MOZ_APPLEMEDIA
    if (RefPtr<PlatformEncoderModule> pem = RemoteEncoderModule::Create(
            RemoteMediaIn::UtilityProcess_AppleMedia)) {
      mCurrentPEMs.AppendElement(std::move(pem));
    }
#endif

#ifdef XP_WIN
    if (RefPtr<PlatformEncoderModule> pem =
            RemoteEncoderModule::Create(RemoteMediaIn::UtilityProcess_WMF)) {
      mCurrentPEMs.AppendElement(std::move(pem));
    }
#endif

    if (RefPtr<PlatformEncoderModule> pem = RemoteEncoderModule::Create(
            RemoteMediaIn::UtilityProcess_Generic)) {
      mCurrentPEMs.AppendElement(std::move(pem));
    }
  }

  if (!StaticPrefs::media_use_remote_encoder_video()) {
#ifdef MOZ_APPLEMEDIA
    RefPtr<PlatformEncoderModule> m(new AppleEncoderModule());
    mCurrentPEMs.AppendElement(m);
#endif

#ifdef MOZ_WIDGET_ANDROID
    if (AndroidDecoderModule::IsJavaDecoderModuleAllowed()) {
      mCurrentPEMs.AppendElement(new AndroidEncoderModule());
    }
#endif

#ifdef XP_WIN
    mCurrentPEMs.AppendElement(new WMFEncoderModule());
#endif
  }

#ifdef MOZ_FFVPX_AUDIOONLY
  if (!StaticPrefs::media_use_remote_encoder_audio() &&
      StaticPrefs::media_ffmpeg_encoder_enabled())
#else
  if ((!StaticPrefs::media_use_remote_encoder_audio() ||
       !StaticPrefs::media_use_remote_encoder_video()) &&
      StaticPrefs::media_ffmpeg_encoder_enabled())
#endif
  {
    if (RefPtr<PlatformEncoderModule> pem =
            FFVPXRuntimeLinker::CreateEncoder()) {
      mCurrentPEMs.AppendElement(pem);
    }
  }

#ifdef MOZ_FFMPEG
#  ifdef MOZ_FFVPX_AUDIOONLY
  if (!StaticPrefs::media_use_remote_encoder_audio() &&
      StaticPrefs::media_ffmpeg_enabled() &&
      StaticPrefs::media_ffmpeg_encoder_enabled())
#  else
  if ((!StaticPrefs::media_use_remote_encoder_audio() ||
       !StaticPrefs::media_use_remote_encoder_video()) &&
      StaticPrefs::media_ffmpeg_enabled() &&
      StaticPrefs::media_ffmpeg_encoder_enabled())
#  endif
  {
    if (RefPtr<PlatformEncoderModule> pem =
            FFmpegRuntimeLinker::CreateEncoder()) {
      mCurrentPEMs.AppendElement(pem);
    }
  }
#endif

  if (StaticPrefs::media_gmp_encoder_enabled()) {
    auto pem = MakeRefPtr<GMPEncoderModule>();
    if (StaticPrefs::media_gmp_encoder_preferred()) {
      mCurrentPEMs.InsertElementAt(0, std::move(pem));
    } else {
      mCurrentPEMs.AppendElement(std::move(pem));
    }
  }
}

void PEMFactory::InitDefaultPEMs() {
#ifdef MOZ_APPLEMEDIA
  RefPtr<PlatformEncoderModule> m(new AppleEncoderModule());
  mCurrentPEMs.AppendElement(m);
#endif

#ifdef MOZ_WIDGET_ANDROID
  if (AndroidDecoderModule::IsJavaDecoderModuleAllowed()) {
    mCurrentPEMs.AppendElement(new AndroidEncoderModule());
  }
#endif

#ifdef XP_WIN
  mCurrentPEMs.AppendElement(new WMFEncoderModule());
#endif

  if (StaticPrefs::media_ffmpeg_encoder_enabled()) {
    if (RefPtr<PlatformEncoderModule> pem =
            FFVPXRuntimeLinker::CreateEncoder()) {
      mCurrentPEMs.AppendElement(pem);
    }
  }

#ifdef MOZ_FFMPEG
  if (StaticPrefs::media_ffmpeg_enabled() &&
      StaticPrefs::media_ffmpeg_encoder_enabled()) {
    if (RefPtr<PlatformEncoderModule> pem =
            FFmpegRuntimeLinker::CreateEncoder()) {
      mCurrentPEMs.AppendElement(pem);
    }
  }
#endif

  if (StaticPrefs::media_gmp_encoder_enabled()) {
    auto pem = MakeRefPtr<GMPEncoderModule>();
    if (StaticPrefs::media_gmp_encoder_preferred()) {
      mCurrentPEMs.InsertElementAt(0, std::move(pem));
    } else {
      mCurrentPEMs.AppendElement(std::move(pem));
    }
  }
}

PEMFactory::PEMFactory() {
  gfx::gfxVars::Initialize();

  if (XRE_IsGPUProcess()) {
    InitGpuPEMs();
  } else if (XRE_IsRDDProcess()) {
    InitRddPEMs();
  } else if (XRE_IsUtilityProcess()) {
    InitUtilityPEMs();
  } else if (XRE_IsContentProcess()) {
    InitContentPEMs();
  } else {
    InitDefaultPEMs();
  }
}

already_AddRefed<MediaDataEncoder> PEMFactory::CreateEncoder(
    const EncoderConfig& aConfig, const RefPtr<TaskQueue>& aTaskQueue) {
  RefPtr<PlatformEncoderModule> m = FindPEM(aConfig);
  if (!m) {
    return nullptr;
  }

  return aConfig.IsVideo() ? m->CreateVideoEncoder(aConfig, aTaskQueue)
                           : nullptr;
}

RefPtr<PlatformEncoderModule::CreateEncoderPromise>
PEMFactory::CreateEncoderAsync(const EncoderConfig& aConfig,
                               const RefPtr<TaskQueue>& aTaskQueue) {
  return CheckAndMaybeCreateEncoder(aConfig, 0, aTaskQueue);
}

RefPtr<PlatformEncoderModule::CreateEncoderPromise>
PEMFactory::CheckAndMaybeCreateEncoder(const EncoderConfig& aConfig,
                                       uint32_t aIndex,
                                       const RefPtr<TaskQueue>& aTaskQueue) {
  for (uint32_t i = aIndex; i < mCurrentPEMs.Length(); i++) {
    if (mCurrentPEMs[i]->Supports(aConfig).isEmpty()) {
      continue;
    }
    return CreateEncoderWithPEM(mCurrentPEMs[i], aConfig, aTaskQueue)
        ->Then(
            GetCurrentSerialEventTarget(), __func__,
            [](RefPtr<MediaDataEncoder>&& aEncoder) {
              return PlatformEncoderModule::CreateEncoderPromise::
                  CreateAndResolve(std::move(aEncoder), __func__);
            },
            [self = RefPtr{this}, i, config = aConfig,
             aTaskQueue](const MediaResult& aError) mutable {
              // Try the next PEM.
              return self->CheckAndMaybeCreateEncoder(config, i + 1,
                                                      aTaskQueue);
            });
  }
  return PlatformEncoderModule::CreateEncoderPromise::CreateAndReject(
      MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
                  nsPrintfCString("Error no encoder found for %s",
                                  EnumValueToString(aConfig.mCodec))
                      .get()),
      __func__);
}

RefPtr<PlatformEncoderModule::CreateEncoderPromise>
PEMFactory::CreateEncoderWithPEM(PlatformEncoderModule* aPEM,
                                 const EncoderConfig& aConfig,
                                 const RefPtr<TaskQueue>& aTaskQueue) {
  MOZ_ASSERT(aPEM);
  MediaResult result = NS_OK;

  if (aConfig.IsAudio()) {
    return aPEM->AsyncCreateEncoder(aConfig, aTaskQueue)
        ->Then(
            GetCurrentSerialEventTarget(), __func__,
            [config = aConfig](RefPtr<MediaDataEncoder>&& aEncoder) {
              RefPtr<MediaDataEncoder> decoder = std::move(aEncoder);
              return PlatformEncoderModule::CreateEncoderPromise::
                  CreateAndResolve(decoder, __func__);
            },
            [](const MediaResult& aError) {
              return PlatformEncoderModule::CreateEncoderPromise::
                  CreateAndReject(aError, __func__);
            });
  }

  if (!aConfig.IsVideo()) {
    return PlatformEncoderModule::CreateEncoderPromise::CreateAndReject(
        MediaResult(
            NS_ERROR_DOM_MEDIA_FATAL_ERR,
            RESULT_DETAIL(
                "Encoder configuration error, expected audio or video.")),
        __func__);
  }

  return aPEM->AsyncCreateEncoder(aConfig, aTaskQueue);
}

EncodeSupportSet PEMFactory::Supports(const EncoderConfig& aConfig) const {
  RefPtr<PlatformEncoderModule> found;
  for (const auto& m : mCurrentPEMs) {
    EncodeSupportSet supports = m->Supports(aConfig);
    if (!supports.isEmpty()) {
      // TODO name
      LOG("Checking if {} supports codec {}: yes", m->GetName(),
          EnumValueToString(aConfig.mCodec));
      return supports;
    }
    LOG("Checking if {} supports codec {}: no", m->GetName(),
        EnumValueToString(aConfig.mCodec));
  }
  return EncodeSupportSet{};
}

EncodeSupportSet PEMFactory::SupportsCodec(CodecType aCodec) const {
  EncodeSupportSet supports{};
  for (const auto& m : mCurrentPEMs) {
    EncodeSupportSet pemSupports = m->SupportsCodec(aCodec);
    // TODO name
    LOG("Checking if {} supports codec {}: {}", m->GetName(),
        static_cast<int>(aCodec), pemSupports.isEmpty() ? "no" : "yes");
    supports += pemSupports;
  }
  if (supports.isEmpty()) {
    LOG("No PEM support {}", static_cast<int>(aCodec));
  }
  return supports;
}

already_AddRefed<PlatformEncoderModule> PEMFactory::FindPEM(
    const EncoderConfig& aConfig) const {
  RefPtr<PlatformEncoderModule> found;
  for (const auto& m : mCurrentPEMs) {
    if (!m->Supports(aConfig).isEmpty()) {
      found = m;
      break;
    }
  }
  return found.forget();
}

StaticMutex PEMFactory::sSupportedMutex;

/* static */
MediaCodecsSupported PEMFactory::Supported(bool aForceRefresh) {
  StaticMutexAutoLock lock(sSupportedMutex);

  static auto calculate = []() {
    auto pem = MakeRefPtr<PEMFactory>();
    MediaCodecsSupported supported;
    for (const auto& cd : MCSInfo::GetAllCodecDefinitions()) {
      auto codecType = MediaCodecToCodecType(cd.codec);
      if (codecType == CodecType::Unknown) {
        continue;
      }
      supported += MCSInfo::GetEncodeMediaCodecsSupported(
          cd.codec, pem->SupportsCodec(codecType));
    }
    return supported;
  };

  static MediaCodecsSupported supported = calculate();
  if (aForceRefresh) {
    supported = calculate();
  }

  return supported;
}

/* static */
media::EncodeSupportSet PEMFactory::SupportsCodec(
    CodecType aCodec, const MediaCodecsSupported& aSupported,
    RemoteMediaIn aLocation) {
  const TrackSupportSet supports =
      RemoteMediaManagerChild::GetTrackSupport(aLocation);

  if (supports.contains(TrackSupport::EncodeVideo)) {
    switch (aCodec) {
      case CodecType::H264:
        return media::MCSInfo::GetEncodeSupportSet(MediaCodec::H264,
                                                   aSupported);
      case CodecType::H265:
        return media::MCSInfo::GetEncodeSupportSet(MediaCodec::HEVC,
                                                   aSupported);
      case CodecType::VP8:
        return media::MCSInfo::GetEncodeSupportSet(MediaCodec::VP8, aSupported);
      case CodecType::VP9:
        return media::MCSInfo::GetEncodeSupportSet(MediaCodec::VP9, aSupported);
      case CodecType::AV1:
        return media::MCSInfo::GetEncodeSupportSet(MediaCodec::AV1, aSupported);
      default:
        break;
    }
  }

  if (supports.contains(TrackSupport::EncodeAudio)) {
    switch (aCodec) {
      case CodecType::Opus:
        return media::MCSInfo::GetEncodeSupportSet(MediaCodec::Opus,
                                                   aSupported);
      case CodecType::Vorbis:
        return media::MCSInfo::GetEncodeSupportSet(MediaCodec::Vorbis,
                                                   aSupported);
      case CodecType::Flac:
        return media::MCSInfo::GetEncodeSupportSet(MediaCodec::FLAC,
                                                   aSupported);
      case CodecType::AAC:
        return media::MCSInfo::GetEncodeSupportSet(MediaCodec::AAC, aSupported);
      case CodecType::PCM:
      case CodecType::G722:
      default:
        break;
    }
  }

  return media::EncodeSupportSet{};
}

}  // namespace mozilla

#undef LOGE
#undef LOG

Messung V0.5 in Prozent
C=92 H=97 G=94

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet am  2026-08-25) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=752002